in libcef/common/crash_reporter_client.cc [354:530]
bool CefCrashReporterClient::ReadCrashConfigFile() {
if (has_crash_config_file_)
return true;
PathString config_path = GetCrashConfigPath();
if (config_path.empty())
return false;
#if defined(OS_WIN)
FILE* fp = _wfopen(config_path.c_str(), L"r");
#else
FILE* fp = fopen(config_path.c_str(), "r");
#endif
if (!fp)
return false;
char line[1000];
size_t small_index = 0;
size_t medium_index = 0;
size_t large_index = 0;
std::string map_keys;
enum section {
kNoSection,
kConfigSection,
kCrashKeysSection,
} current_section = kNoSection;
while (fgets(line, sizeof(line) - 1, fp) != nullptr) {
std::string str = line;
base::TrimString(str, base::kWhitespaceASCII, &str);
if (str.empty() || str[0] == '#')
continue;
if (str == "[Config]") {
current_section = kConfigSection;
continue;
} else if (str == "[CrashKeys]") {
current_section = kCrashKeysSection;
continue;
} else if (str[0] == '[') {
current_section = kNoSection;
continue;
}
if (current_section == kNoSection)
continue;
size_t div = str.find('=');
if (div == std::string::npos)
continue;
std::string name_str = str.substr(0, div);
base::TrimString(name_str, base::kWhitespaceASCII, &name_str);
std::string val_str = str.substr(div + 1);
base::TrimString(val_str, base::kWhitespaceASCII, &val_str);
if (name_str.empty())
continue;
if (current_section == kConfigSection) {
if (name_str == "ServerURL") {
ParseURL(val_str, &server_url_);
} else if (name_str == "ProductName") {
product_name_ = val_str;
} else if (name_str == "ProductVersion") {
product_version_ = val_str;
} else if (name_str == "RateLimitEnabled") {
rate_limit_ = ParseBool(val_str);
} else if (name_str == "MaxUploadsPerDay") {
max_uploads_ = ParseZeroBasedInt(val_str);
} else if (name_str == "MaxDatabaseSizeInMb") {
max_db_size_ = ParseZeroBasedInt(val_str);
} else if (name_str == "MaxDatabaseAgeInDays") {
max_db_age_ = ParseZeroBasedInt(val_str);
}
#if defined(OS_WIN)
else if (name_str == "ExternalHandler") {
if (!val_str.empty())
external_handler_ = sanitizePath(val_str);
} else if (name_str == "AppName") {
if (!val_str.empty()) {
val_str = sanitizePathComponent(val_str);
if (!val_str.empty())
app_name_ = val_str;
}
}
#elif defined(OS_MAC)
else if (name_str == "BrowserCrashForwardingEnabled") {
enable_browser_crash_forwarding_ = ParseBool(val_str);
}
#endif
} else if (current_section == kCrashKeysSection) {
// Skip duplicate definitions.
if (!crash_keys_.empty() &&
crash_keys_.find(name_str) != crash_keys_.end()) {
continue;
}
KeySize size;
size_t index;
char group;
if (val_str == "small") {
size = SMALL_SIZE;
index = small_index++;
group = 'S';
} else if (val_str == "medium") {
size = MEDIUM_SIZE;
index = medium_index++;
group = 'M';
} else if (val_str == "large") {
size = LARGE_SIZE;
index = large_index++;
group = 'L';
} else {
continue;
}
name_str = NormalizeCrashKey(name_str);
crash_keys_.insert(std::make_pair(name_str, std::make_pair(size, index)));
const std::string& key =
std::string(1, group) + "-" + std::string(1, 'A' + index);
if (!map_keys.empty()) {
map_keys.append(std::string(1, kKeyMapDelim));
}
map_keys.append(key + "=" + name_str);
}
}
fclose(fp);
if (!map_keys.empty()) {
// Split |map_keys| across multiple Annotations if necessary.
// Must match the logic in crash_report_utils::FilterParameters.
using IDKey =
crash_reporter::CrashKeyString<crashpad::Annotation::kValueMaxSize>;
static IDKey ids[] = {
{"K-A", IDKey::Tag::kArray},
{"K-B", IDKey::Tag::kArray},
{"K-C", IDKey::Tag::kArray},
};
// Make sure we can fit all possible name/value pairs.
static_assert(base::size(ids) * crashpad::Annotation::kValueMaxSize >=
3 * 26 /* sizes (small, medium, large) * slots (A to Z) */
* (3 + 2 /* key size ("S-A") + delim size ("=,") */
+ crashpad::Annotation::kNameMaxLength),
"Not enough storage for key map");
size_t offset = 0;
for (size_t i = 0; i < base::size(ids); ++i) {
size_t length = std::min(map_keys.size() - offset,
crashpad::Annotation::kValueMaxSize);
ids[i].Set(base::StringPiece(map_keys.data() + offset, length));
offset += length;
if (offset >= map_keys.size())
break;
}
}
// Allow override of some values via environment variables.
{
std::unique_ptr<base::Environment> env(base::Environment::Create());
std::string val_str;
if (env->GetVar("CEF_CRASH_REPORTER_SERVER_URL", &val_str)) {
ParseURL(val_str, &server_url_);
}
if (env->GetVar("CEF_CRASH_REPORTER_RATE_LIMIT_ENABLED", &val_str)) {
rate_limit_ = ParseBool(val_str);
}
}
has_crash_config_file_ = true;
return true;
}