summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/extensions/extension_management.cc207
-rw-r--r--chrome/browser/extensions/extension_management.h93
-rw-r--r--chrome/browser/extensions/extension_management_internal.cc94
-rw-r--r--chrome/browser/extensions/extension_management_internal.h87
-rw-r--r--chrome/browser/extensions/extension_management_unittest.cc151
-rw-r--r--chrome/browser/extensions/standard_management_policy_provider.cc19
-rw-r--r--chrome/chrome_browser_extensions.gypi2
7 files changed, 358 insertions, 295 deletions
diff --git a/chrome/browser/extensions/extension_management.cc b/chrome/browser/extensions/extension_management.cc
index 1ecca8d..33b066b 100644
--- a/chrome/browser/extensions/extension_management.cc
+++ b/chrome/browser/extensions/extension_management.cc
@@ -4,12 +4,17 @@
#include "chrome/browser/extensions/extension_management.h"
+#include <algorithm>
+#include <string>
+#include <vector>
+
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/prefs/pref_service.h"
#include "base/strings/string_util.h"
#include "chrome/browser/extensions/extension_management_constants.h"
+#include "chrome/browser/extensions/extension_management_internal.h"
#include "chrome/browser/extensions/external_policy_loader.h"
#include "chrome/browser/extensions/external_provider_impl.h"
#include "chrome/browser/extensions/standard_management_policy_provider.h"
@@ -24,97 +29,6 @@
namespace extensions {
-namespace {
-
-const char kMalformedPreferenceWarning[] =
- "Malformed extension management preference.";
-
-enum Scope {
- // Parses the default settings.
- SCOPE_DEFAULT = 0,
- // Parses the settings for an extension with specified extension ID.
- SCOPE_INDIVIDUAL,
-};
-
-// Parse the individual settings for |settings|. |dict| is the a
-// sub-dictionary in extension management preference and |scope| represents
-// the applicable range of the settings, a single extension, a group of
-// extensions or default settings.
-// Note that in case of parsing errors, |settings| will NOT be left untouched.
-bool ParseIndividualSettings(
- const base::DictionaryValue* dict,
- Scope scope,
- ExtensionManagement::IndividualSettings* settings) {
- std::string installation_mode;
- if (dict->GetStringWithoutPathExpansion(schema_constants::kInstallationMode,
- &installation_mode)) {
- if (installation_mode == schema_constants::kAllowed) {
- settings->installation_mode = ExtensionManagement::INSTALLATION_ALLOWED;
- } else if (installation_mode == schema_constants::kBlocked) {
- settings->installation_mode = ExtensionManagement::INSTALLATION_BLOCKED;
- } else if (installation_mode == schema_constants::kForceInstalled) {
- settings->installation_mode = ExtensionManagement::INSTALLATION_FORCED;
- } else if (installation_mode == schema_constants::kNormalInstalled) {
- settings->installation_mode =
- ExtensionManagement::INSTALLATION_RECOMMENDED;
- } else {
- // Invalid value for 'installation_mode'.
- LOG(WARNING) << kMalformedPreferenceWarning;
- return false;
- }
- }
-
- if (settings->installation_mode == ExtensionManagement::INSTALLATION_FORCED ||
- settings->installation_mode ==
- ExtensionManagement::INSTALLATION_RECOMMENDED) {
- if (scope != SCOPE_INDIVIDUAL) {
- // Only individual extensions are allowed to be automatically installed.
- LOG(WARNING) << kMalformedPreferenceWarning;
- return false;
- }
- std::string update_url;
- if (dict->GetStringWithoutPathExpansion(schema_constants::kUpdateUrl,
- &update_url) &&
- GURL(update_url).is_valid()) {
- settings->update_url = update_url;
- } else {
- // No valid update URL for extension.
- LOG(WARNING) << kMalformedPreferenceWarning;
- return false;
- }
- }
-
- return true;
-}
-
-} // namespace
-
-ExtensionManagement::IndividualSettings::IndividualSettings() {
- Reset();
-}
-
-ExtensionManagement::IndividualSettings::~IndividualSettings() {
-}
-
-void ExtensionManagement::IndividualSettings::Reset() {
- installation_mode = ExtensionManagement::INSTALLATION_ALLOWED;
- update_url.clear();
-}
-
-ExtensionManagement::GlobalSettings::GlobalSettings() {
- Reset();
-}
-
-ExtensionManagement::GlobalSettings::~GlobalSettings() {
-}
-
-void ExtensionManagement::GlobalSettings::Reset() {
- has_restricted_install_sources = false;
- install_sources.ClearPatterns();
- has_restricted_allowed_types = false;
- allowed_types.clear();
-}
-
ExtensionManagement::ExtensionManagement(PrefService* pref_service)
: pref_service_(pref_service) {
pref_change_registrar_.Init(pref_service_);
@@ -131,6 +45,9 @@ ExtensionManagement::ExtensionManagement(PrefService* pref_service)
pref_change_registrar_.Add(pref_names::kAllowedTypes, pref_change_callback);
pref_change_registrar_.Add(pref_names::kExtensionManagement,
pref_change_callback);
+ // Note that both |global_settings_| and |default_settings_| will be null
+ // before first call to Refresh(), so in order to resolve this, Refresh() must
+ // be called in the initialization of ExtensionManagement.
Refresh();
provider_.reset(new StandardManagementPolicyProvider(this));
}
@@ -146,12 +63,17 @@ void ExtensionManagement::RemoveObserver(Observer* observer) {
observer_list_.RemoveObserver(observer);
}
-ManagementPolicy::Provider* ExtensionManagement::GetProvider() {
+ManagementPolicy::Provider* ExtensionManagement::GetProvider() const {
return provider_.get();
}
-bool ExtensionManagement::BlacklistedByDefault() {
- return default_settings_.installation_mode == INSTALLATION_BLOCKED;
+bool ExtensionManagement::BlacklistedByDefault() const {
+ return default_settings_->installation_mode == INSTALLATION_BLOCKED;
+}
+
+ExtensionManagement::InstallationMode ExtensionManagement::GetInstallationMode(
+ const ExtensionId& id) const {
+ return ReadById(id)->installation_mode;
}
scoped_ptr<base::DictionaryValue> ExtensionManagement::GetForceInstallList()
@@ -160,26 +82,26 @@ scoped_ptr<base::DictionaryValue> ExtensionManagement::GetForceInstallList()
for (SettingsIdMap::const_iterator it = settings_by_id_.begin();
it != settings_by_id_.end();
++it) {
- if (it->second.installation_mode == INSTALLATION_FORCED) {
+ if (it->second->installation_mode == INSTALLATION_FORCED) {
ExternalPolicyLoader::AddExtension(
- forcelist.get(), it->first, it->second.update_url);
+ forcelist.get(), it->first, it->second->update_url);
}
}
return forcelist.Pass();
}
bool ExtensionManagement::IsInstallationAllowed(const ExtensionId& id) const {
- return ReadById(id).installation_mode != INSTALLATION_BLOCKED;
+ return ReadById(id)->installation_mode != INSTALLATION_BLOCKED;
}
-bool ExtensionManagement::IsOffstoreInstallAllowed(const GURL& url,
- const GURL& referrer_url) {
+bool ExtensionManagement::IsOffstoreInstallAllowed(
+ const GURL& url,
+ const GURL& referrer_url) const {
// No allowed install sites specified, disallow by default.
- if (!global_settings_.has_restricted_install_sources)
+ if (!global_settings_->has_restricted_install_sources)
return false;
- const extensions::URLPatternSet& url_patterns =
- global_settings_.install_sources;
+ const URLPatternSet& url_patterns = global_settings_->install_sources;
if (!url_patterns.MatchesURL(url))
return false;
@@ -189,18 +111,14 @@ bool ExtensionManagement::IsOffstoreInstallAllowed(const GURL& url,
return url.SchemeIsFile() || url_patterns.MatchesURL(referrer_url);
}
-const ExtensionManagement::IndividualSettings& ExtensionManagement::ReadById(
- const ExtensionId& id) const {
- DCHECK(crx_file::id_util::IdIsValid(id)) << "Invalid ID: " << id;
- SettingsIdMap::const_iterator it = settings_by_id_.find(id);
- if (it != settings_by_id_.end())
- return it->second;
- return default_settings_;
-}
-
-const ExtensionManagement::GlobalSettings&
-ExtensionManagement::ReadGlobalSettings() const {
- return global_settings_;
+bool ExtensionManagement::IsAllowedManifestType(
+ Manifest::Type manifest_type) const {
+ if (!global_settings_->has_restricted_allowed_types)
+ return true;
+ const std::vector<Manifest::Type>& allowed_types =
+ global_settings_->allowed_types;
+ return std::find(allowed_types.begin(), allowed_types.end(), manifest_type) !=
+ allowed_types.end();
}
void ExtensionManagement::Refresh() {
@@ -229,23 +147,24 @@ void ExtensionManagement::Refresh() {
base::Value::TYPE_DICTIONARY));
// Reset all settings.
- global_settings_.Reset();
+ global_settings_.reset(new internal::GlobalSettings());
settings_by_id_.clear();
- default_settings_.Reset();
+ default_settings_.reset(new internal::IndividualSettings());
// Parse default settings.
const base::StringValue wildcard("*");
if (denied_list_pref &&
denied_list_pref->Find(wildcard) != denied_list_pref->end()) {
- default_settings_.installation_mode = INSTALLATION_BLOCKED;
+ default_settings_->installation_mode = INSTALLATION_BLOCKED;
}
const base::DictionaryValue* subdict = NULL;
if (dict_pref &&
dict_pref->GetDictionary(schema_constants::kWildcard, &subdict)) {
- if (!ParseIndividualSettings(subdict, SCOPE_DEFAULT, &default_settings_)) {
+ if (!default_settings_->Parse(
+ subdict, internal::IndividualSettings::SCOPE_DEFAULT)) {
LOG(WARNING) << "Default extension management settings parsing error.";
- default_settings_.Reset();
+ default_settings_->Reset();
}
// Settings from new preference have higher priority over legacy ones.
@@ -285,7 +204,7 @@ void ExtensionManagement::Refresh() {
if (it.value().GetAsDictionary(&dict_value) &&
dict_value->GetStringWithoutPathExpansion(
ExternalProviderImpl::kExternalUpdateUrl, &update_url)) {
- IndividualSettings* by_id = AccessById(it.key());
+ internal::IndividualSettings* by_id = AccessById(it.key());
by_id->installation_mode = INSTALLATION_FORCED;
by_id->update_url = update_url;
}
@@ -293,14 +212,14 @@ void ExtensionManagement::Refresh() {
}
if (install_sources_pref) {
- global_settings_.has_restricted_install_sources = true;
+ global_settings_->has_restricted_install_sources = true;
for (base::ListValue::const_iterator it = install_sources_pref->begin();
it != install_sources_pref->end(); ++it) {
std::string url_pattern;
if ((*it)->GetAsString(&url_pattern)) {
URLPattern entry(URLPattern::SCHEME_ALL);
if (entry.Parse(url_pattern) == URLPattern::PARSE_SUCCESS) {
- global_settings_.install_sources.AddPattern(entry);
+ global_settings_->install_sources.AddPattern(entry);
} else {
LOG(WARNING) << "Invalid URL pattern in for preference "
<< pref_names::kAllowedInstallSites << ": "
@@ -311,20 +230,20 @@ void ExtensionManagement::Refresh() {
}
if (allowed_types_pref) {
- global_settings_.has_restricted_allowed_types = true;
+ global_settings_->has_restricted_allowed_types = true;
for (base::ListValue::const_iterator it = allowed_types_pref->begin();
it != allowed_types_pref->end(); ++it) {
int int_value;
std::string string_value;
if ((*it)->GetAsInteger(&int_value) && int_value >= 0 &&
int_value < Manifest::Type::NUM_LOAD_TYPES) {
- global_settings_.allowed_types.push_back(
+ global_settings_->allowed_types.push_back(
static_cast<Manifest::Type>(int_value));
} else if ((*it)->GetAsString(&string_value)) {
Manifest::Type manifest_type =
schema_constants::GetManifestType(string_value);
if (manifest_type != Manifest::TYPE_UNKNOWN)
- global_settings_.allowed_types.push_back(manifest_type);
+ global_settings_->allowed_types.push_back(manifest_type);
}
}
}
@@ -335,20 +254,19 @@ void ExtensionManagement::Refresh() {
iter.Advance()) {
if (iter.key() == schema_constants::kWildcard)
continue;
- if (!iter.value().GetAsDictionary(&subdict)) {
- LOG(WARNING) << kMalformedPreferenceWarning;
+ if (!iter.value().GetAsDictionary(&subdict))
continue;
- }
if (StartsWithASCII(iter.key(), schema_constants::kUpdateUrlPrefix, true))
continue;
const std::string& extension_id = iter.key();
if (!crx_file::id_util::IdIsValid(extension_id)) {
- LOG(WARNING) << kMalformedPreferenceWarning;
+ LOG(WARNING) << "Invalid extension ID : " << extension_id << ".";
continue;
}
- IndividualSettings* by_id = AccessById(extension_id);
- if (!ParseIndividualSettings(subdict, SCOPE_INDIVIDUAL, by_id)) {
- settings_by_id_.erase(settings_by_id_.find(extension_id));
+ internal::IndividualSettings* by_id = AccessById(extension_id);
+ if (!by_id->Parse(subdict,
+ internal::IndividualSettings::SCOPE_INDIVIDUAL)) {
+ settings_by_id_.erase(extension_id);
LOG(WARNING) << "Malformed Extension Management settings for "
<< extension_id << ".";
}
@@ -381,13 +299,30 @@ void ExtensionManagement::NotifyExtensionManagementPrefChanged() {
Observer, observer_list_, OnExtensionManagementSettingsChanged());
}
-ExtensionManagement::IndividualSettings* ExtensionManagement::AccessById(
+const internal::IndividualSettings* ExtensionManagement::ReadById(
+ const ExtensionId& id) const {
+ DCHECK(crx_file::id_util::IdIsValid(id)) << "Invalid ID: " << id;
+ SettingsIdMap::const_iterator it = settings_by_id_.find(id);
+ if (it != settings_by_id_.end())
+ return it->second;
+ return default_settings_.get();
+}
+
+const internal::GlobalSettings* ExtensionManagement::ReadGlobalSettings()
+ const {
+ return global_settings_.get();
+}
+
+internal::IndividualSettings* ExtensionManagement::AccessById(
const ExtensionId& id) {
DCHECK(crx_file::id_util::IdIsValid(id)) << "Invalid ID: " << id;
SettingsIdMap::iterator it = settings_by_id_.find(id);
- if (it == settings_by_id_.end())
- it = settings_by_id_.insert(std::make_pair(id, default_settings_)).first;
- return &it->second;
+ if (it == settings_by_id_.end()) {
+ scoped_ptr<internal::IndividualSettings> settings(
+ new internal::IndividualSettings(*default_settings_));
+ it = settings_by_id_.add(id, settings.Pass()).first;
+ }
+ return it->second;
}
ExtensionManagement* ExtensionManagementFactory::GetForBrowserContext(
diff --git a/chrome/browser/extensions/extension_management.h b/chrome/browser/extensions/extension_management.h
index d7d1466..5cea880 100644
--- a/chrome/browser/extensions/extension_management.h
+++ b/chrome/browser/extensions/extension_management.h
@@ -5,10 +5,7 @@
#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_MANAGEMENT_H_
#define CHROME_BROWSER_EXTENSIONS_EXTENSION_MANAGEMENT_H_
-#include <map>
-#include <string>
-#include <vector>
-
+#include "base/containers/scoped_ptr_hash_map.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
@@ -20,7 +17,6 @@
#include "extensions/browser/management_policy.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest.h"
-#include "extensions/common/url_pattern_set.h"
class GURL;
class PrefService;
@@ -31,6 +27,13 @@ class BrowserContext;
namespace extensions {
+namespace internal {
+
+struct IndividualSettings;
+struct GlobalSettings;
+
+} // namespace internal
+
// Tracks the management policies that affect extensions and provides interfaces
// for observing and obtaining the global settings for all extensions, as well
// as per-extension settings.
@@ -41,7 +44,7 @@ class ExtensionManagement : public KeyedService {
public:
virtual ~Observer() {}
- // Will be called when an extension management preference changes.
+ // Called when the extension management settings change.
virtual void OnExtensionManagementSettingsChanged() = 0;
};
@@ -59,48 +62,6 @@ class ExtensionManagement : public KeyedService {
INSTALLATION_RECOMMENDED,
};
- // Class to hold extension management settings for one or a group of
- // extensions. Settings can be applied to an individual extension identified
- // by an ID, a group of extensions with specific |update_url| or all
- // extensions at once.
- struct IndividualSettings {
- IndividualSettings();
- ~IndividualSettings();
-
- void Reset();
-
- // Extension installation mode. Setting this to INSTALLATION_FORCED or
- // INSTALLATION_RECOMMENDED will enable extension auto-loading (only
- // applicable to single extension), and in this case the |update_url| must
- // be specified, containing the update URL for this extension.
- // Note that |update_url| will be ignored for INSTALLATION_ALLOWED and
- // INSTALLATION_BLOCKED installation mode.
- // These settings will override the default settings, and unspecified
- // settings will take value from default settings.
- InstallationMode installation_mode;
- std::string update_url;
- };
-
- // Global extension management settings, applicable to all extensions.
- struct GlobalSettings {
- GlobalSettings();
- ~GlobalSettings();
-
- void Reset();
-
- // Settings specifying which URLs are allowed to install extensions, will be
- // enforced only if |has_restricted_install_sources| is set to true.
- URLPatternSet install_sources;
- bool has_restricted_install_sources;
-
- // Settings specifying all allowed app/extension types, will be enforced
- // only of |has_restricted_allowed_types| is set to true.
- std::vector<Manifest::Type> allowed_types;
- bool has_restricted_allowed_types;
- };
-
- typedef std::map<ExtensionId, IndividualSettings> SettingsIdMap;
-
explicit ExtensionManagement(PrefService* pref_service);
virtual ~ExtensionManagement();
@@ -109,12 +70,15 @@ class ExtensionManagement : public KeyedService {
// Get the ManagementPolicy::Provider controlled by extension management
// policy settings.
- ManagementPolicy::Provider* GetProvider();
+ ManagementPolicy::Provider* GetProvider() const;
// Checks if extensions are blacklisted by default, by policy. When true,
// this means that even extensions without an ID should be blacklisted (e.g.
// from the command line, or when loaded as an unpacked extension).
- bool BlacklistedByDefault();
+ bool BlacklistedByDefault() const;
+
+ // Returns installation mode for an extension.
+ InstallationMode GetInstallationMode(const ExtensionId& id) const;
// Returns the force install list, in format specified by
// ExternalPolicyLoader::AddExtension().
@@ -124,16 +88,18 @@ class ExtensionManagement : public KeyedService {
bool IsInstallationAllowed(const ExtensionId& id) const;
// Returns true if an extension download should be allowed to proceed.
- bool IsOffstoreInstallAllowed(const GURL& url, const GURL& referrer_url);
-
- // Helper function to read |settings_by_id_| with |id| as key. Returns a
- // constant reference to default settings if |id| does not exist.
- const IndividualSettings& ReadById(const ExtensionId& id) const;
+ bool IsOffstoreInstallAllowed(const GURL& url,
+ const GURL& referrer_url) const;
- // Returns a constant reference to |global_settings_|.
- const GlobalSettings& ReadGlobalSettings() const;
+ // Returns true if an extension with manifest type |manifest_type| is
+ // allowed to be installed.
+ bool IsAllowedManifestType(Manifest::Type manifest_type) const;
private:
+ typedef base::ScopedPtrHashMap<ExtensionId, internal::IndividualSettings>
+ SettingsIdMap;
+ friend class ExtensionManagementServiceTest;
+
// Load all extension management preferences from |pref_service|, and
// refresh the settings.
void Refresh();
@@ -149,10 +115,17 @@ class ExtensionManagement : public KeyedService {
void OnExtensionPrefChanged();
void NotifyExtensionManagementPrefChanged();
+ // Helper function to read |settings_by_id_| with |id| as key. Returns a
+ // constant reference to default settings if |id| does not exist.
+ const internal::IndividualSettings* ReadById(const ExtensionId& id) const;
+
+ // Returns a constant reference to |global_settings_|.
+ const internal::GlobalSettings* ReadGlobalSettings() const;
+
// Helper function to access |settings_by_id_| with |id| as key.
// Adds a new IndividualSettings entry to |settings_by_id_| if none exists for
// |id| yet.
- IndividualSettings* AccessById(const ExtensionId& id);
+ internal::IndividualSettings* AccessById(const ExtensionId& id);
// A map containing all IndividualSettings applied to an individual extension
// identified by extension ID. The extension ID is used as index key of the
@@ -167,10 +140,10 @@ class ExtensionManagement : public KeyedService {
// URL), all unspecified part will take value from |default_settings_|.
// For all other extensions, all settings from |default_settings_| will be
// enforced.
- IndividualSettings default_settings_;
+ scoped_ptr<internal::IndividualSettings> default_settings_;
// Extension settings applicable to all extensions.
- GlobalSettings global_settings_;
+ scoped_ptr<internal::GlobalSettings> global_settings_;
PrefService* pref_service_;
diff --git a/chrome/browser/extensions/extension_management_internal.cc b/chrome/browser/extensions/extension_management_internal.cc
new file mode 100644
index 0000000..73bd132
--- /dev/null
+++ b/chrome/browser/extensions/extension_management_internal.cc
@@ -0,0 +1,94 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/extension_management_internal.h"
+
+#include "base/logging.h"
+#include "base/values.h"
+#include "chrome/browser/extensions/extension_management_constants.h"
+#include "extensions/common/url_pattern_set.h"
+#include "url/gurl.h"
+
+namespace extensions {
+
+namespace internal {
+
+namespace {
+const char kMalformedPreferenceWarning[] =
+ "Malformed extension management preference.";
+} // namespace
+
+IndividualSettings::IndividualSettings() {
+ Reset();
+}
+
+IndividualSettings::~IndividualSettings() {
+}
+
+bool IndividualSettings::Parse(const base::DictionaryValue* dict,
+ ParsingScope scope) {
+ std::string installation_mode_str;
+ if (dict->GetStringWithoutPathExpansion(schema_constants::kInstallationMode,
+ &installation_mode_str)) {
+ if (installation_mode_str == schema_constants::kAllowed) {
+ installation_mode = ExtensionManagement::INSTALLATION_ALLOWED;
+ } else if (installation_mode_str == schema_constants::kBlocked) {
+ installation_mode = ExtensionManagement::INSTALLATION_BLOCKED;
+ } else if (installation_mode_str == schema_constants::kForceInstalled) {
+ installation_mode = ExtensionManagement::INSTALLATION_FORCED;
+ } else if (installation_mode_str == schema_constants::kNormalInstalled) {
+ installation_mode = ExtensionManagement::INSTALLATION_RECOMMENDED;
+ } else {
+ // Invalid value for 'installation_mode'.
+ LOG(WARNING) << kMalformedPreferenceWarning;
+ return false;
+ }
+
+ // Only proceed to fetch update url if force or recommended install mode
+ // is set.
+ if (installation_mode == ExtensionManagement::INSTALLATION_FORCED ||
+ installation_mode == ExtensionManagement::INSTALLATION_RECOMMENDED) {
+ if (scope != SCOPE_INDIVIDUAL) {
+ // Only individual extensions are allowed to be automatically installed.
+ LOG(WARNING) << kMalformedPreferenceWarning;
+ return false;
+ }
+ std::string update_url_str;
+ if (dict->GetStringWithoutPathExpansion(schema_constants::kUpdateUrl,
+ &update_url_str) &&
+ GURL(update_url_str).is_valid()) {
+ update_url = update_url_str;
+ } else {
+ // No valid update URL for extension.
+ LOG(WARNING) << kMalformedPreferenceWarning;
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+void IndividualSettings::Reset() {
+ installation_mode = ExtensionManagement::INSTALLATION_ALLOWED;
+ update_url.clear();
+}
+
+GlobalSettings::GlobalSettings() {
+ Reset();
+}
+
+GlobalSettings::~GlobalSettings() {
+}
+
+void GlobalSettings::Reset() {
+ has_restricted_install_sources = false;
+ install_sources.ClearPatterns();
+ has_restricted_allowed_types = false;
+ allowed_types.clear();
+}
+
+} // namespace internal
+
+} // namespace extensions
diff --git a/chrome/browser/extensions/extension_management_internal.h b/chrome/browser/extensions/extension_management_internal.h
new file mode 100644
index 0000000..d01bb33
--- /dev/null
+++ b/chrome/browser/extensions/extension_management_internal.h
@@ -0,0 +1,87 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_MANAGEMENT_INTERNAL_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTENSION_MANAGEMENT_INTERNAL_H_
+
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "chrome/browser/extensions/extension_management.h"
+#include "extensions/common/manifest.h"
+
+namespace base {
+class DictionaryValue;
+} // namespace base
+
+namespace extensions {
+
+class URLPatternSet;
+
+namespace internal {
+
+// Class to hold extension management settings for one or a group of
+// extensions. Settings can be applied to an individual extension identified
+// by an ID, a group of extensions with specific |update_url| or all
+// extensions at once.
+struct IndividualSettings {
+ enum ParsingScope {
+ // Parses the default settings.
+ SCOPE_DEFAULT = 0,
+ // Parses the settings for an extension with specified extension ID.
+ SCOPE_INDIVIDUAL,
+ };
+
+ IndividualSettings();
+ ~IndividualSettings();
+
+ void Reset();
+
+ // Parses the individual settings. |dict| is the a sub-dictionary in extension
+ // management preference and |scope| represents the applicable range of the
+ // settings, a single extension, a group of extensions or default settings.
+ // Note that in case of parsing errors, |this| will NOT be left untouched.
+ bool Parse(const base::DictionaryValue* dict, ParsingScope scope);
+
+ // Extension installation mode. Setting this to INSTALLATION_FORCED or
+ // INSTALLATION_RECOMMENDED will enable extension auto-loading (only
+ // applicable to single extension), and in this case the |update_url| must
+ // be specified, containing the update URL for this extension.
+ // Note that |update_url| will be ignored for INSTALLATION_ALLOWED and
+ // INSTALLATION_BLOCKED installation mode.
+ // These settings will override the default settings, and unspecified
+ // settings will take value from default settings.
+ ExtensionManagement::InstallationMode installation_mode;
+ std::string update_url;
+
+ private:
+ DISALLOW_ASSIGN(IndividualSettings);
+};
+
+// Global extension management settings, applicable to all extensions.
+struct GlobalSettings {
+ GlobalSettings();
+ ~GlobalSettings();
+
+ void Reset();
+
+ // Settings specifying which URLs are allowed to install extensions, will be
+ // enforced only if |has_restricted_install_sources| is set to true.
+ URLPatternSet install_sources;
+ bool has_restricted_install_sources;
+
+ // Settings specifying all allowed app/extension types, will be enforced
+ // only of |has_restricted_allowed_types| is set to true.
+ std::vector<Manifest::Type> allowed_types;
+ bool has_restricted_allowed_types;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GlobalSettings);
+};
+
+} // namespace internal
+
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_MANAGEMENT_INTERNAL_H_
diff --git a/chrome/browser/extensions/extension_management_unittest.cc b/chrome/browser/extensions/extension_management_unittest.cc
index 9d91895..35f12f5 100644
--- a/chrome/browser/extensions/extension_management_unittest.cc
+++ b/chrome/browser/extensions/extension_management_unittest.cc
@@ -11,6 +11,7 @@
#include "base/prefs/testing_pref_service.h"
#include "base/values.h"
#include "chrome/browser/extensions/extension_management.h"
+#include "chrome/browser/extensions/extension_management_internal.h"
#include "chrome/browser/extensions/extension_management_test_util.h"
#include "chrome/browser/extensions/external_policy_loader.h"
#include "extensions/browser/pref_names.h"
@@ -93,6 +94,14 @@ class ExtensionManagementServiceTest : public testing::Test {
pref_service_->RemoveUserPref(path);
}
+ const internal::IndividualSettings* ReadById(const ExtensionId& id) {
+ return extension_management_->ReadById(id);
+ }
+
+ const internal::GlobalSettings* ReadGlobalSettings() {
+ return extension_management_->ReadGlobalSettings();
+ }
+
void SetExampleDictPref() {
std::string error_msg;
scoped_ptr<base::Value> parsed(base::JSONReader::ReadAndReturnError(
@@ -202,10 +211,8 @@ TEST_F(ExtensionManagementServiceTest, LegacyInstallSources) {
allowed_sites_pref.AppendString("https://corp.mycompany.com/*");
SetPref(
true, pref_names::kAllowedInstallSites, allowed_sites_pref.DeepCopy());
- const URLPatternSet& allowed_sites =
- extension_management_->ReadGlobalSettings().install_sources;
- ASSERT_TRUE(extension_management_->ReadGlobalSettings()
- .has_restricted_install_sources);
+ const URLPatternSet& allowed_sites = ReadGlobalSettings()->install_sources;
+ ASSERT_TRUE(ReadGlobalSettings()->has_restricted_install_sources);
EXPECT_FALSE(allowed_sites.is_empty());
EXPECT_TRUE(allowed_sites.MatchesURL(GURL("https://www.example.com/foo")));
EXPECT_FALSE(allowed_sites.MatchesURL(GURL("https://www.example.com/bar")));
@@ -224,9 +231,8 @@ TEST_F(ExtensionManagementServiceTest, LegacyAllowedTypes) {
SetPref(true, pref_names::kAllowedTypes, allowed_types_pref.DeepCopy());
const std::vector<Manifest::Type>& allowed_types =
- extension_management_->ReadGlobalSettings().allowed_types;
- ASSERT_TRUE(
- extension_management_->ReadGlobalSettings().has_restricted_allowed_types);
+ ReadGlobalSettings()->allowed_types;
+ ASSERT_TRUE(ReadGlobalSettings()->has_restricted_allowed_types);
EXPECT_TRUE(allowed_types.size() == 2);
EXPECT_FALSE(std::find(allowed_types.begin(),
allowed_types.end(),
@@ -246,9 +252,9 @@ TEST_F(ExtensionManagementServiceTest, LegacyInstallBlacklist) {
denied_list_pref.AppendString(kTargetExtension);
SetPref(true, pref_names::kInstallDenyList, denied_list_pref.DeepCopy());
- EXPECT_EQ(extension_management_->ReadById(kTargetExtension).installation_mode,
+ EXPECT_EQ(ReadById(kTargetExtension)->installation_mode,
ExtensionManagement::INSTALLATION_BLOCKED);
- EXPECT_EQ(extension_management_->ReadById(kOtherExtension).installation_mode,
+ EXPECT_EQ(ReadById(kOtherExtension)->installation_mode,
ExtensionManagement::INSTALLATION_ALLOWED);
}
@@ -262,15 +268,15 @@ TEST_F(ExtensionManagementServiceTest, LegacyInstallWhitelist) {
SetPref(true, pref_names::kInstallDenyList, denied_list_pref.DeepCopy());
SetPref(true, pref_names::kInstallAllowList, allowed_list_pref.DeepCopy());
- EXPECT_EQ(extension_management_->ReadById(kTargetExtension).installation_mode,
+ EXPECT_EQ(ReadById(kTargetExtension)->installation_mode,
ExtensionManagement::INSTALLATION_ALLOWED);
- EXPECT_EQ(extension_management_->ReadById(kOtherExtension).installation_mode,
+ EXPECT_EQ(ReadById(kOtherExtension)->installation_mode,
ExtensionManagement::INSTALLATION_BLOCKED);
// Verify that install whitelist preference set by user is ignored.
RemovePref(true, pref_names::kInstallAllowList);
SetPref(false, pref_names::kInstallAllowList, allowed_list_pref.DeepCopy());
- EXPECT_EQ(extension_management_->ReadById(kTargetExtension).installation_mode,
+ EXPECT_EQ(ReadById(kTargetExtension)->installation_mode,
ExtensionManagement::INSTALLATION_BLOCKED);
}
@@ -282,17 +288,16 @@ TEST_F(ExtensionManagementServiceTest, LegacyInstallForcelist) {
&forced_list_pref, kTargetExtension, kExampleUpdateUrl);
SetPref(true, pref_names::kInstallForceList, forced_list_pref.DeepCopy());
- EXPECT_EQ(extension_management_->ReadById(kTargetExtension).installation_mode,
+ EXPECT_EQ(ReadById(kTargetExtension)->installation_mode,
ExtensionManagement::INSTALLATION_FORCED);
- EXPECT_EQ(extension_management_->ReadById(kTargetExtension).update_url,
- kExampleUpdateUrl);
- EXPECT_EQ(extension_management_->ReadById(kOtherExtension).installation_mode,
+ EXPECT_EQ(ReadById(kTargetExtension)->update_url, kExampleUpdateUrl);
+ EXPECT_EQ(ReadById(kOtherExtension)->installation_mode,
ExtensionManagement::INSTALLATION_ALLOWED);
// Verify that install forcelist preference set by user is ignored.
RemovePref(true, pref_names::kInstallForceList);
SetPref(false, pref_names::kInstallForceList, forced_list_pref.DeepCopy());
- EXPECT_EQ(extension_management_->ReadById(kTargetExtension).installation_mode,
+ EXPECT_EQ(ReadById(kTargetExtension)->installation_mode,
ExtensionManagement::INSTALLATION_ALLOWED);
}
@@ -302,34 +307,27 @@ TEST_F(ExtensionManagementServiceTest, PreferenceParsing) {
// Verifies the installation mode settings.
EXPECT_TRUE(extension_management_->BlacklistedByDefault());
- EXPECT_EQ(extension_management_->ReadById(kTargetExtension).installation_mode,
+ EXPECT_EQ(ReadById(kTargetExtension)->installation_mode,
ExtensionManagement::INSTALLATION_ALLOWED);
- EXPECT_EQ(
- extension_management_->ReadById(kTargetExtension2).installation_mode,
- ExtensionManagement::INSTALLATION_FORCED);
- EXPECT_EQ(extension_management_->ReadById(kTargetExtension2).update_url,
- kExampleUpdateUrl);
- EXPECT_EQ(
- extension_management_->ReadById(kTargetExtension3).installation_mode,
- ExtensionManagement::INSTALLATION_RECOMMENDED);
- EXPECT_EQ(extension_management_->ReadById(kTargetExtension3).update_url,
- kExampleUpdateUrl);
- EXPECT_EQ(extension_management_->ReadById(kOtherExtension).installation_mode,
+ EXPECT_EQ(ReadById(kTargetExtension2)->installation_mode,
+ ExtensionManagement::INSTALLATION_FORCED);
+ EXPECT_EQ(ReadById(kTargetExtension2)->update_url, kExampleUpdateUrl);
+ EXPECT_EQ(ReadById(kTargetExtension3)->installation_mode,
+ ExtensionManagement::INSTALLATION_RECOMMENDED);
+ EXPECT_EQ(ReadById(kTargetExtension3)->update_url, kExampleUpdateUrl);
+ EXPECT_EQ(ReadById(kOtherExtension)->installation_mode,
ExtensionManagement::INSTALLATION_BLOCKED);
// Verifies global settings.
- EXPECT_TRUE(extension_management_->ReadGlobalSettings()
- .has_restricted_install_sources);
- const URLPatternSet& allowed_sites =
- extension_management_->ReadGlobalSettings().install_sources;
+ EXPECT_TRUE(ReadGlobalSettings()->has_restricted_install_sources);
+ const URLPatternSet& allowed_sites = ReadGlobalSettings()->install_sources;
EXPECT_EQ(allowed_sites.size(), 1u);
EXPECT_TRUE(allowed_sites.MatchesURL(GURL("http://foo.com/entry")));
EXPECT_FALSE(allowed_sites.MatchesURL(GURL("http://bar.com/entry")));
- EXPECT_TRUE(
- extension_management_->ReadGlobalSettings().has_restricted_allowed_types);
+ EXPECT_TRUE(ReadGlobalSettings()->has_restricted_allowed_types);
const std::vector<Manifest::Type>& allowed_types =
- extension_management_->ReadGlobalSettings().allowed_types;
+ ReadGlobalSettings()->allowed_types;
EXPECT_EQ(allowed_types.size(), 2u);
EXPECT_TRUE(std::find(allowed_types.begin(),
allowed_types.end(),
@@ -347,11 +345,9 @@ TEST_F(ExtensionManagementServiceTest, NewInstallSources) {
allowed_sites_pref.AppendString("https://www.example.com/foo");
SetPref(
true, pref_names::kAllowedInstallSites, allowed_sites_pref.DeepCopy());
- EXPECT_TRUE(extension_management_->ReadGlobalSettings()
- .has_restricted_install_sources);
- EXPECT_TRUE(
- extension_management_->ReadGlobalSettings()
- .install_sources.MatchesURL(GURL("https://www.example.com/foo")));
+ EXPECT_TRUE(ReadGlobalSettings()->has_restricted_install_sources);
+ EXPECT_TRUE(ReadGlobalSettings()->install_sources.MatchesURL(
+ GURL("https://www.example.com/foo")));
// Set the new dictionary preference.
{
@@ -359,22 +355,18 @@ TEST_F(ExtensionManagementServiceTest, NewInstallSources) {
updater.ClearInstallSources();
}
// Verifies that the new one overrides the legacy ones.
- EXPECT_TRUE(extension_management_->ReadGlobalSettings()
- .has_restricted_install_sources);
- EXPECT_FALSE(
- extension_management_->ReadGlobalSettings()
- .install_sources.MatchesURL(GURL("https://www.example.com/foo")));
+ EXPECT_TRUE(ReadGlobalSettings()->has_restricted_install_sources);
+ EXPECT_FALSE(ReadGlobalSettings()->install_sources.MatchesURL(
+ GURL("https://www.example.com/foo")));
// Updates the new dictionary preference.
{
PrefUpdater updater(pref_service_.get());
updater.AddInstallSource("https://corp.mycompany.com/*");
}
- EXPECT_TRUE(extension_management_->ReadGlobalSettings()
- .has_restricted_install_sources);
- EXPECT_TRUE(extension_management_->ReadGlobalSettings()
- .install_sources.MatchesURL(
- GURL("https://corp.mycompany.com/entry")));
+ EXPECT_TRUE(ReadGlobalSettings()->has_restricted_install_sources);
+ EXPECT_TRUE(ReadGlobalSettings()->install_sources.MatchesURL(
+ GURL("https://corp.mycompany.com/entry")));
}
// Tests functionality of new preference as to deprecate legacy
@@ -384,12 +376,9 @@ TEST_F(ExtensionManagementServiceTest, NewAllowedTypes) {
base::ListValue allowed_types_pref;
allowed_types_pref.AppendInteger(Manifest::TYPE_USER_SCRIPT);
SetPref(true, pref_names::kAllowedTypes, allowed_types_pref.DeepCopy());
- EXPECT_TRUE(
- extension_management_->ReadGlobalSettings().has_restricted_allowed_types);
- EXPECT_EQ(extension_management_->ReadGlobalSettings().allowed_types.size(),
- 1u);
- EXPECT_EQ(extension_management_->ReadGlobalSettings().allowed_types[0],
- Manifest::TYPE_USER_SCRIPT);
+ EXPECT_TRUE(ReadGlobalSettings()->has_restricted_allowed_types);
+ EXPECT_EQ(ReadGlobalSettings()->allowed_types.size(), 1u);
+ EXPECT_EQ(ReadGlobalSettings()->allowed_types[0], Manifest::TYPE_USER_SCRIPT);
// Set the new dictionary preference.
{
@@ -397,22 +386,17 @@ TEST_F(ExtensionManagementServiceTest, NewAllowedTypes) {
updater.ClearAllowedTypes();
}
// Verifies that the new one overrides the legacy ones.
- EXPECT_TRUE(
- extension_management_->ReadGlobalSettings().has_restricted_allowed_types);
- EXPECT_EQ(extension_management_->ReadGlobalSettings().allowed_types.size(),
- 0u);
+ EXPECT_TRUE(ReadGlobalSettings()->has_restricted_allowed_types);
+ EXPECT_EQ(ReadGlobalSettings()->allowed_types.size(), 0u);
// Updates the new dictionary preference.
{
PrefUpdater updater(pref_service_.get());
updater.AddAllowedType("theme");
}
- EXPECT_TRUE(
- extension_management_->ReadGlobalSettings().has_restricted_allowed_types);
- EXPECT_EQ(extension_management_->ReadGlobalSettings().allowed_types.size(),
- 1u);
- EXPECT_EQ(extension_management_->ReadGlobalSettings().allowed_types[0],
- Manifest::TYPE_THEME);
+ EXPECT_TRUE(ReadGlobalSettings()->has_restricted_allowed_types);
+ EXPECT_EQ(ReadGlobalSettings()->allowed_types.size(), 1u);
+ EXPECT_EQ(ReadGlobalSettings()->allowed_types[0], Manifest::TYPE_THEME);
}
// Tests functionality of new preference as to deprecate legacy
@@ -427,9 +411,9 @@ TEST_F(ExtensionManagementServiceTest, NewInstallBlacklist) {
updater.ClearPerExtensionSettings(kOtherExtension);
}
EXPECT_FALSE(extension_management_->BlacklistedByDefault());
- EXPECT_EQ(extension_management_->ReadById(kTargetExtension).installation_mode,
+ EXPECT_EQ(ReadById(kTargetExtension)->installation_mode,
ExtensionManagement::INSTALLATION_BLOCKED);
- EXPECT_EQ(extension_management_->ReadById(kOtherExtension).installation_mode,
+ EXPECT_EQ(ReadById(kOtherExtension)->installation_mode,
ExtensionManagement::INSTALLATION_ALLOWED);
// Set legacy preference.
@@ -444,12 +428,11 @@ TEST_F(ExtensionManagementServiceTest, NewInstallBlacklist) {
// Verifies that the new one have higher priority over the legacy ones.
EXPECT_FALSE(extension_management_->BlacklistedByDefault());
- EXPECT_EQ(extension_management_->ReadById(kTargetExtension).installation_mode,
+ EXPECT_EQ(ReadById(kTargetExtension)->installation_mode,
+ ExtensionManagement::INSTALLATION_BLOCKED);
+ EXPECT_EQ(ReadById(kTargetExtension2)->installation_mode,
ExtensionManagement::INSTALLATION_BLOCKED);
- EXPECT_EQ(
- extension_management_->ReadById(kTargetExtension2).installation_mode,
- ExtensionManagement::INSTALLATION_BLOCKED);
- EXPECT_EQ(extension_management_->ReadById(kOtherExtension).installation_mode,
+ EXPECT_EQ(ReadById(kOtherExtension)->installation_mode,
ExtensionManagement::INSTALLATION_ALLOWED);
}
@@ -465,9 +448,9 @@ TEST_F(ExtensionManagementServiceTest, NewInstallWhitelist) {
updater.ClearPerExtensionSettings(kOtherExtension);
}
EXPECT_TRUE(extension_management_->BlacklistedByDefault());
- EXPECT_EQ(extension_management_->ReadById(kTargetExtension).installation_mode,
+ EXPECT_EQ(ReadById(kTargetExtension)->installation_mode,
ExtensionManagement::INSTALLATION_ALLOWED);
- EXPECT_EQ(extension_management_->ReadById(kOtherExtension).installation_mode,
+ EXPECT_EQ(ReadById(kOtherExtension)->installation_mode,
ExtensionManagement::INSTALLATION_BLOCKED);
// Set legacy preference.
@@ -481,12 +464,11 @@ TEST_F(ExtensionManagementServiceTest, NewInstallWhitelist) {
// Verifies that the new one have higher priority over the legacy ones.
EXPECT_TRUE(extension_management_->BlacklistedByDefault());
- EXPECT_EQ(extension_management_->ReadById(kTargetExtension).installation_mode,
+ EXPECT_EQ(ReadById(kTargetExtension)->installation_mode,
+ ExtensionManagement::INSTALLATION_ALLOWED);
+ EXPECT_EQ(ReadById(kTargetExtension2)->installation_mode,
ExtensionManagement::INSTALLATION_ALLOWED);
- EXPECT_EQ(
- extension_management_->ReadById(kTargetExtension2).installation_mode,
- ExtensionManagement::INSTALLATION_ALLOWED);
- EXPECT_EQ(extension_management_->ReadById(kOtherExtension).installation_mode,
+ EXPECT_EQ(ReadById(kOtherExtension)->installation_mode,
ExtensionManagement::INSTALLATION_BLOCKED);
}
@@ -506,11 +488,10 @@ TEST_F(ExtensionManagementServiceTest, NewInstallForcelist) {
kTargetExtension, kExampleUpdateUrl, true);
updater.ClearPerExtensionSettings(kOtherExtension);
}
- EXPECT_EQ(extension_management_->ReadById(kTargetExtension).installation_mode,
+ EXPECT_EQ(ReadById(kTargetExtension)->installation_mode,
ExtensionManagement::INSTALLATION_FORCED);
- EXPECT_EQ(extension_management_->ReadById(kTargetExtension).update_url,
- kExampleUpdateUrl);
- EXPECT_EQ(extension_management_->ReadById(kOtherExtension).installation_mode,
+ EXPECT_EQ(ReadById(kTargetExtension)->update_url, kExampleUpdateUrl);
+ EXPECT_EQ(ReadById(kOtherExtension)->installation_mode,
ExtensionManagement::INSTALLATION_ALLOWED);
}
diff --git a/chrome/browser/extensions/standard_management_policy_provider.cc b/chrome/browser/extensions/standard_management_policy_provider.cc
index f282406..0212257 100644
--- a/chrome/browser/extensions/standard_management_policy_provider.cc
+++ b/chrome/browser/extensions/standard_management_policy_provider.cc
@@ -4,7 +4,6 @@
#include "chrome/browser/extensions/standard_management_policy_provider.h"
-#include <algorithm>
#include <string>
#include "base/logging.h"
@@ -77,16 +76,12 @@ bool StandardManagementPolicyProvider::UserMayLoad(
if (Manifest::IsComponentLocation(extension->location()))
return true;
- // Fields in |by_id| will automatically fall back to default settings if
- // they are not specified by policy.
- const ExtensionManagement::IndividualSettings& by_id =
- settings_->ReadById(extension->id());
- const ExtensionManagement::GlobalSettings& global =
- settings_->ReadGlobalSettings();
+ ExtensionManagement::InstallationMode installation_mode =
+ settings_->GetInstallationMode(extension->id());
// Force-installed extensions cannot be overwritten manually.
if (!Manifest::IsPolicyLocation(extension->location()) &&
- by_id.installation_mode == ExtensionManagement::INSTALLATION_FORCED) {
+ installation_mode == ExtensionManagement::INSTALLATION_FORCED) {
return ReturnLoadError(extension, error);
}
@@ -107,19 +102,15 @@ bool StandardManagementPolicyProvider::UserMayLoad(
case Manifest::TYPE_LEGACY_PACKAGED_APP:
case Manifest::TYPE_PLATFORM_APP:
case Manifest::TYPE_SHARED_MODULE: {
- if (global.has_restricted_allowed_types &&
- std::find(global.allowed_types.begin(),
- global.allowed_types.end(),
- extension->GetType()) == global.allowed_types.end()) {
+ if (!settings_->IsAllowedManifestType(extension->GetType()))
return ReturnLoadError(extension, error);
- }
break;
}
case Manifest::NUM_LOAD_TYPES:
NOTREACHED();
}
- if (by_id.installation_mode == ExtensionManagement::INSTALLATION_BLOCKED)
+ if (installation_mode == ExtensionManagement::INSTALLATION_BLOCKED)
return ReturnLoadError(extension, error);
return true;
diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi
index a40a726..25b5a99 100644
--- a/chrome/chrome_browser_extensions.gypi
+++ b/chrome/chrome_browser_extensions.gypi
@@ -622,6 +622,8 @@
'browser/extensions/extension_management.h',
'browser/extensions/extension_management_constants.cc',
'browser/extensions/extension_management_constants.h',
+ 'browser/extensions/extension_management_internal.cc',
+ 'browser/extensions/extension_management_internal.h',
'browser/extensions/extension_message_bubble_controller.cc',
'browser/extensions/extension_message_bubble_controller.h',
'browser/extensions/extension_renderer_state.cc',