| Index: chrome/browser/plugins/plugin_finder.cc
|
| diff --git a/chrome/browser/plugins/plugin_finder.cc b/chrome/browser/plugins/plugin_finder.cc
|
| index 626b0a3980ed24ca0a873ec4874a70598d53fbda..6e8b5b3198f6e7fb6b800b2e5468673db464df42 100644
|
| --- a/chrome/browser/plugins/plugin_finder.cc
|
| +++ b/chrome/browser/plugins/plugin_finder.cc
|
| @@ -7,6 +7,7 @@
|
| #include "base/bind.h"
|
| #include "base/json/json_reader.h"
|
| #include "base/message_loop/message_loop.h"
|
| +#include "base/metrics/histogram_macros.h"
|
| #include "base/prefs/pref_registry_simple.h"
|
| #include "base/prefs/pref_service.h"
|
| #include "base/stl_util.h"
|
| @@ -33,6 +34,22 @@ namespace {
|
|
|
| typedef std::map<std::string, PluginMetadata*> PluginMap;
|
|
|
| +// Do not change these values, as they are used in UMA.
|
| +enum class PluginListError {
|
| + // NO_ERROR is defined by Windows headers.
|
| + PLUGIN_LIST_NO_ERROR = 0,
|
| + JSON_INVALID_ESCAPE = 1,
|
| + JSON_SYNTAX_ERROR = 2,
|
| + JSON_UNEXPECTED_TOKEN = 3,
|
| + JSON_TRAILING_COMMA = 4,
|
| + JSON_TOO_MUCH_NESTING = 5,
|
| + JSON_UNEXPECTED_DATA_AFTER_ROOT = 5,
|
| + JSON_UNSUPPORTED_ENCODING = 6,
|
| + JSON_UNQUOTED_DICTIONARY_KEY = 7,
|
| + SCHEMA_ERROR = 8,
|
| + NUM_VALUES
|
| +};
|
| +
|
| // Gets the full path of the plugin file as the identifier.
|
| std::string GetLongIdentifier(const content::WebPluginInfo& plugin) {
|
| return plugin.path.AsUTF8Unsafe();
|
| @@ -128,6 +145,12 @@ PluginMetadata* CreatePluginMetadata(
|
| return plugin;
|
| }
|
|
|
| +void RecordBuiltInPluginListError(PluginListError error_code) {
|
| + UMA_HISTOGRAM_ENUMERATION("PluginFinder.BuiltInPluginList.ErrorCode",
|
| + static_cast<int>(error_code),
|
| + static_cast<int>(PluginListError::NUM_VALUES));
|
| +}
|
| +
|
| } // namespace
|
|
|
| // static
|
| @@ -151,7 +174,13 @@ void PluginFinder::Init() {
|
| // Load the built-in plugin list first. If we have a newer version stored
|
| // locally or download one, we will replace this one with it.
|
| scoped_ptr<base::DictionaryValue> plugin_list(LoadBuiltInPluginList());
|
| - DCHECK(plugin_list);
|
| +
|
| + // Gracefully handle the case where we couldn't parse the built-in plugin list
|
| + // for some reason (https://crbug.com/388560). TODO(bauerb): Change back to a
|
| + // DCHECK once we have gathered more data about the underlying problem.
|
| + if (!plugin_list)
|
| + return;
|
| +
|
| ReinitializePlugins(plugin_list.get());
|
| }
|
|
|
| @@ -161,17 +190,56 @@ base::DictionaryValue* PluginFinder::LoadBuiltInPluginList() {
|
| ResourceBundle::GetSharedInstance().GetRawDataResource(
|
| IDR_PLUGIN_DB_JSON));
|
| std::string error_str;
|
| + int error_code = base::JSONReader::JSON_NO_ERROR;
|
| scoped_ptr<base::Value> value(base::JSONReader::ReadAndReturnError(
|
| - json_resource,
|
| - base::JSON_PARSE_RFC,
|
| - NULL,
|
| - &error_str));
|
| - if (!value.get()) {
|
| + json_resource, base::JSON_PARSE_RFC, &error_code, &error_str));
|
| + if (!value) {
|
| DLOG(ERROR) << error_str;
|
| - return NULL;
|
| + switch (error_code) {
|
| + case base::JSONReader::JSON_INVALID_ESCAPE:
|
| + RecordBuiltInPluginListError(PluginListError::JSON_INVALID_ESCAPE);
|
| + break;
|
| + case base::JSONReader::JSON_SYNTAX_ERROR:
|
| + RecordBuiltInPluginListError(PluginListError::JSON_SYNTAX_ERROR);
|
| + break;
|
| + case base::JSONReader::JSON_UNEXPECTED_TOKEN:
|
| + RecordBuiltInPluginListError(PluginListError::JSON_UNEXPECTED_TOKEN);
|
| + break;
|
| + case base::JSONReader::JSON_TRAILING_COMMA:
|
| + RecordBuiltInPluginListError(PluginListError::JSON_TRAILING_COMMA);
|
| + break;
|
| + case base::JSONReader::JSON_TOO_MUCH_NESTING:
|
| + RecordBuiltInPluginListError(PluginListError::JSON_TOO_MUCH_NESTING);
|
| + break;
|
| + case base::JSONReader::JSON_UNEXPECTED_DATA_AFTER_ROOT:
|
| + RecordBuiltInPluginListError(
|
| + PluginListError::JSON_UNEXPECTED_DATA_AFTER_ROOT);
|
| + break;
|
| + case base::JSONReader::JSON_UNSUPPORTED_ENCODING:
|
| + RecordBuiltInPluginListError(
|
| + PluginListError::JSON_UNSUPPORTED_ENCODING);
|
| + break;
|
| + case base::JSONReader::JSON_UNQUOTED_DICTIONARY_KEY:
|
| + RecordBuiltInPluginListError(
|
| + PluginListError::JSON_UNQUOTED_DICTIONARY_KEY);
|
| + break;
|
| + case base::JSONReader::JSON_NO_ERROR:
|
| + case base::JSONReader::JSON_PARSE_ERROR_COUNT:
|
| + NOTREACHED();
|
| + break;
|
| + }
|
| + return nullptr;
|
| }
|
| - if (value->GetType() != base::Value::TYPE_DICTIONARY)
|
| - return NULL;
|
| +
|
| + if (value->GetType() != base::Value::TYPE_DICTIONARY) {
|
| + // JSONReader::JSON_PARSE_ERROR_COUNT is used for the case where the JSON
|
| + // value has the wrong type.
|
| + RecordBuiltInPluginListError(PluginListError::SCHEMA_ERROR);
|
| + return nullptr;
|
| + }
|
| +
|
| + DCHECK_EQ(base::JSONReader::JSON_NO_ERROR, error_code);
|
| + RecordBuiltInPluginListError(PluginListError::PLUGIN_LIST_NO_ERROR);
|
| return static_cast<base::DictionaryValue*>(value.release());
|
| }
|
|
|
|
|