blob: 6b926d7b03e41d625379e5902b1556778cce24e0 [file] [log] [blame]
binjin5f405ef2014-09-03 21:23:161// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/extensions/extension_management.h"
6
binjin81d7c552014-10-02 11:47:127#include <algorithm>
dcheng1fc00f12015-12-26 22:18:038#include <utility>
binjin81d7c552014-10-02 11:47:129
binjin1569c9b2014-09-05 13:33:1810#include "base/bind.h"
11#include "base/bind_helpers.h"
binjin5f405ef2014-09-03 21:23:1612#include "base/logging.h"
rkaplowdd66a1342015-03-05 00:31:4913#include "base/metrics/histogram_macros.h"
binjine6b58b52014-10-31 01:55:5714#include "base/strings/string16.h"
binjinb2454382014-09-22 15:17:4315#include "base/strings/string_util.h"
rkaplowdd66a1342015-03-05 00:31:4916#include "base/trace_event/trace_event.h"
binjin8e3d0182014-12-04 16:44:2817#include "base/version.h"
binjinb2454382014-09-22 15:17:4318#include "chrome/browser/extensions/extension_management_constants.h"
binjin81d7c552014-10-02 11:47:1219#include "chrome/browser/extensions/extension_management_internal.h"
binjin30301062014-09-08 20:27:3420#include "chrome/browser/extensions/external_policy_loader.h"
binjin5f405ef2014-09-03 21:23:1621#include "chrome/browser/extensions/external_provider_impl.h"
binjine6b58b52014-10-31 01:55:5722#include "chrome/browser/extensions/permissions_based_management_policy_provider.h"
binjin1569c9b2014-09-05 13:33:1823#include "chrome/browser/extensions/standard_management_policy_provider.h"
binjin9733df12014-09-08 15:21:2124#include "chrome/browser/profiles/incognito_helpers.h"
binjin1569c9b2014-09-05 13:33:1825#include "chrome/browser/profiles/profile.h"
binjin5f405ef2014-09-03 21:23:1626#include "components/crx_file/id_util.h"
binjin1569c9b2014-09-05 13:33:1827#include "components/keyed_service/content/browser_context_dependency_manager.h"
binjinb2454382014-09-22 15:17:4328#include "components/pref_registry/pref_registry_syncable.h"
brettwb1fc1b82016-02-02 00:19:0829#include "components/prefs/pref_service.h"
binjin5f405ef2014-09-03 21:23:1630#include "extensions/browser/pref_names.h"
rdevlin.cronin0670b562016-07-02 02:05:4331#include "extensions/common/extension.h"
binjin685ade82014-11-06 09:53:5632#include "extensions/common/manifest_constants.h"
binjine6b58b52014-10-31 01:55:5733#include "extensions/common/permissions/api_permission_set.h"
34#include "extensions/common/permissions/permission_set.h"
binjin5f405ef2014-09-03 21:23:1635#include "extensions/common/url_pattern.h"
binjin311ecdf2014-09-12 22:56:5236#include "url/gurl.h"
binjin5f405ef2014-09-03 21:23:1637
38namespace extensions {
39
binjin5f405ef2014-09-03 21:23:1640ExtensionManagement::ExtensionManagement(PrefService* pref_service)
41 : pref_service_(pref_service) {
rkaplowdd66a1342015-03-05 00:31:4942 TRACE_EVENT0("browser,startup",
43 "ExtensionManagement::ExtensionManagement::ctor");
binjin1569c9b2014-09-05 13:33:1844 pref_change_registrar_.Init(pref_service_);
45 base::Closure pref_change_callback = base::Bind(
46 &ExtensionManagement::OnExtensionPrefChanged, base::Unretained(this));
47 pref_change_registrar_.Add(pref_names::kInstallAllowList,
48 pref_change_callback);
49 pref_change_registrar_.Add(pref_names::kInstallDenyList,
50 pref_change_callback);
51 pref_change_registrar_.Add(pref_names::kInstallForceList,
52 pref_change_callback);
53 pref_change_registrar_.Add(pref_names::kAllowedInstallSites,
54 pref_change_callback);
55 pref_change_registrar_.Add(pref_names::kAllowedTypes, pref_change_callback);
binjinb2454382014-09-22 15:17:4356 pref_change_registrar_.Add(pref_names::kExtensionManagement,
57 pref_change_callback);
binjin81d7c552014-10-02 11:47:1258 // Note that both |global_settings_| and |default_settings_| will be null
59 // before first call to Refresh(), so in order to resolve this, Refresh() must
60 // be called in the initialization of ExtensionManagement.
binjin1569c9b2014-09-05 13:33:1861 Refresh();
binjine6b58b52014-10-31 01:55:5762 providers_.push_back(new StandardManagementPolicyProvider(this));
63 providers_.push_back(new PermissionsBasedManagementPolicyProvider(this));
binjin5f405ef2014-09-03 21:23:1664}
65
66ExtensionManagement::~ExtensionManagement() {
67}
68
binjine6b58b52014-10-31 01:55:5769void ExtensionManagement::Shutdown() {
70 pref_change_registrar_.RemoveAll();
71 pref_service_ = nullptr;
72}
73
binjin1569c9b2014-09-05 13:33:1874void ExtensionManagement::AddObserver(Observer* observer) {
75 observer_list_.AddObserver(observer);
76}
77
78void ExtensionManagement::RemoveObserver(Observer* observer) {
79 observer_list_.RemoveObserver(observer);
80}
81
binjine6b58b52014-10-31 01:55:5782std::vector<ManagementPolicy::Provider*> ExtensionManagement::GetProviders()
83 const {
84 return providers_.get();
binjin1569c9b2014-09-05 13:33:1885}
86
binjin81d7c552014-10-02 11:47:1287bool ExtensionManagement::BlacklistedByDefault() const {
88 return default_settings_->installation_mode == INSTALLATION_BLOCKED;
89}
90
91ExtensionManagement::InstallationMode ExtensionManagement::GetInstallationMode(
binjin685ade82014-11-06 09:53:5692 const Extension* extension) const {
93 // Check per-extension installation mode setting first.
94 auto iter_id = settings_by_id_.find(extension->id());
95 if (iter_id != settings_by_id_.end())
96 return iter_id->second->installation_mode;
97 std::string update_url;
98 // Check per-update-url installation mode setting.
99 if (extension->manifest()->GetString(manifest_keys::kUpdateURL,
100 &update_url)) {
101 auto iter_update_url = settings_by_update_url_.find(update_url);
102 if (iter_update_url != settings_by_update_url_.end())
103 return iter_update_url->second->installation_mode;
104 }
105 // Fall back to default installation mode setting.
106 return default_settings_->installation_mode;
binjin1569c9b2014-09-05 13:33:18107}
108
dchengc963c7142016-04-08 03:55:22109std::unique_ptr<base::DictionaryValue>
110ExtensionManagement::GetForceInstallList() const {
111 std::unique_ptr<base::DictionaryValue> install_list(
112 new base::DictionaryValue());
binjin30301062014-09-08 20:27:34113 for (SettingsIdMap::const_iterator it = settings_by_id_.begin();
114 it != settings_by_id_.end();
115 ++it) {
binjin81d7c552014-10-02 11:47:12116 if (it->second->installation_mode == INSTALLATION_FORCED) {
binjin30301062014-09-08 20:27:34117 ExternalPolicyLoader::AddExtension(
binjincccacef2014-10-13 19:00:20118 install_list.get(), it->first, it->second->update_url);
binjin30301062014-09-08 20:27:34119 }
120 }
dcheng1fc00f12015-12-26 22:18:03121 return install_list;
binjincccacef2014-10-13 19:00:20122}
123
dchengc963c7142016-04-08 03:55:22124std::unique_ptr<base::DictionaryValue>
binjincccacef2014-10-13 19:00:20125ExtensionManagement::GetRecommendedInstallList() const {
dchengc963c7142016-04-08 03:55:22126 std::unique_ptr<base::DictionaryValue> install_list(
127 new base::DictionaryValue());
binjincccacef2014-10-13 19:00:20128 for (SettingsIdMap::const_iterator it = settings_by_id_.begin();
129 it != settings_by_id_.end();
130 ++it) {
131 if (it->second->installation_mode == INSTALLATION_RECOMMENDED) {
132 ExternalPolicyLoader::AddExtension(
133 install_list.get(), it->first, it->second->update_url);
134 }
135 }
dcheng1fc00f12015-12-26 22:18:03136 return install_list;
binjin30301062014-09-08 20:27:34137}
138
binjinc641add2014-10-15 16:20:45139bool ExtensionManagement::IsInstallationExplicitlyAllowed(
140 const ExtensionId& id) const {
141 SettingsIdMap::const_iterator it = settings_by_id_.find(id);
142 // No settings explicitly specified for |id|.
143 if (it == settings_by_id_.end())
144 return false;
145 // Checks if the extension is on the automatically installed list or
146 // install white-list.
147 InstallationMode mode = it->second->installation_mode;
148 return mode == INSTALLATION_FORCED || mode == INSTALLATION_RECOMMENDED ||
149 mode == INSTALLATION_ALLOWED;
binjin30301062014-09-08 20:27:34150}
151
binjin81d7c552014-10-02 11:47:12152bool ExtensionManagement::IsOffstoreInstallAllowed(
153 const GURL& url,
154 const GURL& referrer_url) const {
binjin311ecdf2014-09-12 22:56:52155 // No allowed install sites specified, disallow by default.
binjin81d7c552014-10-02 11:47:12156 if (!global_settings_->has_restricted_install_sources)
binjin311ecdf2014-09-12 22:56:52157 return false;
158
binjin81d7c552014-10-02 11:47:12159 const URLPatternSet& url_patterns = global_settings_->install_sources;
binjin311ecdf2014-09-12 22:56:52160
161 if (!url_patterns.MatchesURL(url))
162 return false;
163
164 // The referrer URL must also be whitelisted, unless the URL has the file
165 // scheme (there's no referrer for those URLs).
166 return url.SchemeIsFile() || url_patterns.MatchesURL(referrer_url);
167}
168
binjin81d7c552014-10-02 11:47:12169bool ExtensionManagement::IsAllowedManifestType(
170 Manifest::Type manifest_type) const {
171 if (!global_settings_->has_restricted_allowed_types)
172 return true;
173 const std::vector<Manifest::Type>& allowed_types =
174 global_settings_->allowed_types;
175 return std::find(allowed_types.begin(), allowed_types.end(), manifest_type) !=
176 allowed_types.end();
binjin1569c9b2014-09-05 13:33:18177}
178
binjin685ade82014-11-06 09:53:56179APIPermissionSet ExtensionManagement::GetBlockedAPIPermissions(
180 const Extension* extension) const {
181 // Fetch per-extension blocked permissions setting.
182 auto iter_id = settings_by_id_.find(extension->id());
183
184 // Fetch per-update-url blocked permissions setting.
185 std::string update_url;
186 auto iter_update_url = settings_by_update_url_.end();
187 if (extension->manifest()->GetString(manifest_keys::kUpdateURL,
188 &update_url)) {
189 iter_update_url = settings_by_update_url_.find(update_url);
190 }
191
192 if (iter_id != settings_by_id_.end() &&
193 iter_update_url != settings_by_update_url_.end()) {
194 // Blocked permissions setting are specified in both per-extension and
195 // per-update-url settings, try to merge them.
196 APIPermissionSet merged;
197 APIPermissionSet::Union(iter_id->second->blocked_permissions,
198 iter_update_url->second->blocked_permissions,
199 &merged);
200 return merged;
201 }
202 // Check whether if in one of them, setting is specified.
203 if (iter_id != settings_by_id_.end())
204 return iter_id->second->blocked_permissions;
205 if (iter_update_url != settings_by_update_url_.end())
206 return iter_update_url->second->blocked_permissions;
207 // Fall back to the default blocked permissions setting.
208 return default_settings_->blocked_permissions;
binjine6b58b52014-10-31 01:55:57209}
210
dchengc963c7142016-04-08 03:55:22211std::unique_ptr<const PermissionSet> ExtensionManagement::GetBlockedPermissions(
binjin685ade82014-11-06 09:53:56212 const Extension* extension) const {
binjine6b58b52014-10-31 01:55:57213 // Only api permissions are supported currently.
dchengc963c7142016-04-08 03:55:22214 return std::unique_ptr<const PermissionSet>(new PermissionSet(
binjin685ade82014-11-06 09:53:56215 GetBlockedAPIPermissions(extension), ManifestPermissionSet(),
216 URLPatternSet(), URLPatternSet()));
binjine6b58b52014-10-31 01:55:57217}
218
219bool ExtensionManagement::IsPermissionSetAllowed(
binjin685ade82014-11-06 09:53:56220 const Extension* extension,
rdevlin.cronine2d0fd02015-09-24 22:35:49221 const PermissionSet& perms) const {
vmpstrae72b082016-07-25 21:55:47222 for (auto* blocked_api : GetBlockedAPIPermissions(extension)) {
rdevlin.cronine2d0fd02015-09-24 22:35:49223 if (perms.HasAPIPermission(blocked_api->id()))
binjine6b58b52014-10-31 01:55:57224 return false;
225 }
226 return true;
227}
228
binjin8e3d0182014-12-04 16:44:28229bool ExtensionManagement::CheckMinimumVersion(
230 const Extension* extension,
231 std::string* required_version) const {
232 auto iter = settings_by_id_.find(extension->id());
233 // If there are no minimum version required for |extension|, return true.
234 if (iter == settings_by_id_.end() || !iter->second->minimum_version_required)
235 return true;
236 bool meets_requirement = extension->version()->CompareTo(
237 *iter->second->minimum_version_required) >= 0;
238 // Output a human readable version string for prompting if necessary.
239 if (!meets_requirement && required_version)
240 *required_version = iter->second->minimum_version_required->GetString();
241 return meets_requirement;
242}
243
binjin5f405ef2014-09-03 21:23:16244void ExtensionManagement::Refresh() {
rkaplowdd66a1342015-03-05 00:31:49245 TRACE_EVENT0("browser,startup", "ExtensionManagement::Refresh");
246 SCOPED_UMA_HISTOGRAM_TIMER("Extensions.ExtensionManagement_RefreshTime");
binjin5f405ef2014-09-03 21:23:16247 // Load all extension management settings preferences.
248 const base::ListValue* allowed_list_pref =
249 static_cast<const base::ListValue*>(LoadPreference(
250 pref_names::kInstallAllowList, true, base::Value::TYPE_LIST));
251 // Allow user to use preference to block certain extensions. Note that policy
252 // managed forcelist or whitelist will always override this.
253 const base::ListValue* denied_list_pref =
254 static_cast<const base::ListValue*>(LoadPreference(
255 pref_names::kInstallDenyList, false, base::Value::TYPE_LIST));
256 const base::DictionaryValue* forced_list_pref =
257 static_cast<const base::DictionaryValue*>(LoadPreference(
258 pref_names::kInstallForceList, true, base::Value::TYPE_DICTIONARY));
259 const base::ListValue* install_sources_pref =
260 static_cast<const base::ListValue*>(LoadPreference(
261 pref_names::kAllowedInstallSites, true, base::Value::TYPE_LIST));
262 const base::ListValue* allowed_types_pref =
263 static_cast<const base::ListValue*>(LoadPreference(
264 pref_names::kAllowedTypes, true, base::Value::TYPE_LIST));
binjinb2454382014-09-22 15:17:43265 const base::DictionaryValue* dict_pref =
266 static_cast<const base::DictionaryValue*>(
267 LoadPreference(pref_names::kExtensionManagement,
268 true,
269 base::Value::TYPE_DICTIONARY));
binjin5f405ef2014-09-03 21:23:16270
271 // Reset all settings.
binjin81d7c552014-10-02 11:47:12272 global_settings_.reset(new internal::GlobalSettings());
binjin5f405ef2014-09-03 21:23:16273 settings_by_id_.clear();
binjin81d7c552014-10-02 11:47:12274 default_settings_.reset(new internal::IndividualSettings());
binjin5f405ef2014-09-03 21:23:16275
276 // Parse default settings.
277 const base::StringValue wildcard("*");
278 if (denied_list_pref &&
279 denied_list_pref->Find(wildcard) != denied_list_pref->end()) {
binjin81d7c552014-10-02 11:47:12280 default_settings_->installation_mode = INSTALLATION_BLOCKED;
binjin5f405ef2014-09-03 21:23:16281 }
282
binjinb2454382014-09-22 15:17:43283 const base::DictionaryValue* subdict = NULL;
284 if (dict_pref &&
285 dict_pref->GetDictionary(schema_constants::kWildcard, &subdict)) {
binjin81d7c552014-10-02 11:47:12286 if (!default_settings_->Parse(
287 subdict, internal::IndividualSettings::SCOPE_DEFAULT)) {
binjinb2454382014-09-22 15:17:43288 LOG(WARNING) << "Default extension management settings parsing error.";
binjin81d7c552014-10-02 11:47:12289 default_settings_->Reset();
binjinb2454382014-09-22 15:17:43290 }
291
292 // Settings from new preference have higher priority over legacy ones.
293 const base::ListValue* list_value = NULL;
294 if (subdict->GetList(schema_constants::kInstallSources, &list_value))
295 install_sources_pref = list_value;
296 if (subdict->GetList(schema_constants::kAllowedTypes, &list_value))
297 allowed_types_pref = list_value;
298 }
299
binjin5f405ef2014-09-03 21:23:16300 // Parse legacy preferences.
301 ExtensionId id;
302
303 if (allowed_list_pref) {
304 for (base::ListValue::const_iterator it = allowed_list_pref->begin();
305 it != allowed_list_pref->end(); ++it) {
306 if ((*it)->GetAsString(&id) && crx_file::id_util::IdIsValid(id))
307 AccessById(id)->installation_mode = INSTALLATION_ALLOWED;
308 }
309 }
310
311 if (denied_list_pref) {
312 for (base::ListValue::const_iterator it = denied_list_pref->begin();
313 it != denied_list_pref->end(); ++it) {
314 if ((*it)->GetAsString(&id) && crx_file::id_util::IdIsValid(id))
315 AccessById(id)->installation_mode = INSTALLATION_BLOCKED;
316 }
317 }
318
319 if (forced_list_pref) {
320 std::string update_url;
321 for (base::DictionaryValue::Iterator it(*forced_list_pref); !it.IsAtEnd();
322 it.Advance()) {
323 if (!crx_file::id_util::IdIsValid(it.key()))
324 continue;
325 const base::DictionaryValue* dict_value = NULL;
326 if (it.value().GetAsDictionary(&dict_value) &&
327 dict_value->GetStringWithoutPathExpansion(
328 ExternalProviderImpl::kExternalUpdateUrl, &update_url)) {
binjin81d7c552014-10-02 11:47:12329 internal::IndividualSettings* by_id = AccessById(it.key());
binjin5f405ef2014-09-03 21:23:16330 by_id->installation_mode = INSTALLATION_FORCED;
331 by_id->update_url = update_url;
332 }
333 }
334 }
335
336 if (install_sources_pref) {
binjin81d7c552014-10-02 11:47:12337 global_settings_->has_restricted_install_sources = true;
binjin5f405ef2014-09-03 21:23:16338 for (base::ListValue::const_iterator it = install_sources_pref->begin();
339 it != install_sources_pref->end(); ++it) {
binjinb2454382014-09-22 15:17:43340 std::string url_pattern;
binjin5f405ef2014-09-03 21:23:16341 if ((*it)->GetAsString(&url_pattern)) {
binjinb2454382014-09-22 15:17:43342 URLPattern entry(URLPattern::SCHEME_ALL);
binjin5f405ef2014-09-03 21:23:16343 if (entry.Parse(url_pattern) == URLPattern::PARSE_SUCCESS) {
binjin81d7c552014-10-02 11:47:12344 global_settings_->install_sources.AddPattern(entry);
binjin5f405ef2014-09-03 21:23:16345 } else {
346 LOG(WARNING) << "Invalid URL pattern in for preference "
347 << pref_names::kAllowedInstallSites << ": "
348 << url_pattern << ".";
349 }
350 }
351 }
352 }
353
354 if (allowed_types_pref) {
binjin81d7c552014-10-02 11:47:12355 global_settings_->has_restricted_allowed_types = true;
binjin5f405ef2014-09-03 21:23:16356 for (base::ListValue::const_iterator it = allowed_types_pref->begin();
357 it != allowed_types_pref->end(); ++it) {
358 int int_value;
binjinb2454382014-09-22 15:17:43359 std::string string_value;
binjin5f405ef2014-09-03 21:23:16360 if ((*it)->GetAsInteger(&int_value) && int_value >= 0 &&
361 int_value < Manifest::Type::NUM_LOAD_TYPES) {
binjin81d7c552014-10-02 11:47:12362 global_settings_->allowed_types.push_back(
binjin5f405ef2014-09-03 21:23:16363 static_cast<Manifest::Type>(int_value));
binjinb2454382014-09-22 15:17:43364 } else if ((*it)->GetAsString(&string_value)) {
365 Manifest::Type manifest_type =
366 schema_constants::GetManifestType(string_value);
367 if (manifest_type != Manifest::TYPE_UNKNOWN)
binjin81d7c552014-10-02 11:47:12368 global_settings_->allowed_types.push_back(manifest_type);
binjin5f405ef2014-09-03 21:23:16369 }
370 }
371 }
372
binjinb2454382014-09-22 15:17:43373 if (dict_pref) {
374 // Parse new extension management preference.
375 for (base::DictionaryValue::Iterator iter(*dict_pref); !iter.IsAtEnd();
376 iter.Advance()) {
377 if (iter.key() == schema_constants::kWildcard)
378 continue;
binjin81d7c552014-10-02 11:47:12379 if (!iter.value().GetAsDictionary(&subdict))
binjinb2454382014-09-22 15:17:43380 continue;
brettw66d1b81b2015-07-06 19:29:40381 if (base::StartsWith(iter.key(), schema_constants::kUpdateUrlPrefix,
382 base::CompareCase::SENSITIVE)) {
binjin685ade82014-11-06 09:53:56383 const std::string& update_url =
384 iter.key().substr(strlen(schema_constants::kUpdateUrlPrefix));
385 if (!GURL(update_url).is_valid()) {
386 LOG(WARNING) << "Invalid update URL: " << update_url << ".";
387 continue;
388 }
389 internal::IndividualSettings* by_update_url =
390 AccessByUpdateUrl(update_url);
391 if (!by_update_url->Parse(
392 subdict, internal::IndividualSettings::SCOPE_UPDATE_URL)) {
393 settings_by_update_url_.erase(update_url);
394 LOG(WARNING) << "Malformed Extension Management settings for "
395 "extensions with update url: " << update_url << ".";
396 }
397 } else {
398 const std::string& extension_id = iter.key();
399 if (!crx_file::id_util::IdIsValid(extension_id)) {
400 LOG(WARNING) << "Invalid extension ID : " << extension_id << ".";
401 continue;
402 }
403 internal::IndividualSettings* by_id = AccessById(extension_id);
404 if (!by_id->Parse(subdict,
405 internal::IndividualSettings::SCOPE_INDIVIDUAL)) {
406 settings_by_id_.erase(extension_id);
407 LOG(WARNING) << "Malformed Extension Management settings for "
408 << extension_id << ".";
409 }
binjinb2454382014-09-22 15:17:43410 }
411 }
412 }
binjin5f405ef2014-09-03 21:23:16413}
414
binjin5f405ef2014-09-03 21:23:16415const base::Value* ExtensionManagement::LoadPreference(
416 const char* pref_name,
417 bool force_managed,
418 base::Value::Type expected_type) {
binjine6b58b52014-10-31 01:55:57419 if (!pref_service_)
420 return nullptr;
binjin5f405ef2014-09-03 21:23:16421 const PrefService::Preference* pref =
422 pref_service_->FindPreference(pref_name);
423 if (pref && !pref->IsDefaultValue() &&
424 (!force_managed || pref->IsManaged())) {
425 const base::Value* value = pref->GetValue();
426 if (value && value->IsType(expected_type))
427 return value;
428 }
binjine6b58b52014-10-31 01:55:57429 return nullptr;
binjin5f405ef2014-09-03 21:23:16430}
431
binjin1569c9b2014-09-05 13:33:18432void ExtensionManagement::OnExtensionPrefChanged() {
433 Refresh();
434 NotifyExtensionManagementPrefChanged();
435}
436
437void ExtensionManagement::NotifyExtensionManagementPrefChanged() {
438 FOR_EACH_OBSERVER(
439 Observer, observer_list_, OnExtensionManagementSettingsChanged());
440}
441
binjin81d7c552014-10-02 11:47:12442internal::IndividualSettings* ExtensionManagement::AccessById(
binjin5f405ef2014-09-03 21:23:16443 const ExtensionId& id) {
444 DCHECK(crx_file::id_util::IdIsValid(id)) << "Invalid ID: " << id;
445 SettingsIdMap::iterator it = settings_by_id_.find(id);
binjin81d7c552014-10-02 11:47:12446 if (it == settings_by_id_.end()) {
dchengc963c7142016-04-08 03:55:22447 std::unique_ptr<internal::IndividualSettings> settings(
binjin8e3d0182014-12-04 16:44:28448 new internal::IndividualSettings(default_settings_.get()));
dcheng1fc00f12015-12-26 22:18:03449 it = settings_by_id_.add(id, std::move(settings)).first;
binjin81d7c552014-10-02 11:47:12450 }
451 return it->second;
binjin5f405ef2014-09-03 21:23:16452}
453
binjin685ade82014-11-06 09:53:56454internal::IndividualSettings* ExtensionManagement::AccessByUpdateUrl(
455 const std::string& update_url) {
456 DCHECK(GURL(update_url).is_valid()) << "Invalid update URL: " << update_url;
457 SettingsUpdateUrlMap::iterator it = settings_by_update_url_.find(update_url);
458 if (it == settings_by_update_url_.end()) {
dchengc963c7142016-04-08 03:55:22459 std::unique_ptr<internal::IndividualSettings> settings(
binjin8e3d0182014-12-04 16:44:28460 new internal::IndividualSettings(default_settings_.get()));
dcheng1fc00f12015-12-26 22:18:03461 it = settings_by_update_url_.add(update_url, std::move(settings)).first;
binjin685ade82014-11-06 09:53:56462 }
463 return it->second;
464}
465
binjin1569c9b2014-09-05 13:33:18466ExtensionManagement* ExtensionManagementFactory::GetForBrowserContext(
467 content::BrowserContext* context) {
468 return static_cast<ExtensionManagement*>(
469 GetInstance()->GetServiceForBrowserContext(context, true));
470}
471
472ExtensionManagementFactory* ExtensionManagementFactory::GetInstance() {
olli.raula36aa8be2015-09-10 11:14:22473 return base::Singleton<ExtensionManagementFactory>::get();
binjin1569c9b2014-09-05 13:33:18474}
475
476ExtensionManagementFactory::ExtensionManagementFactory()
477 : BrowserContextKeyedServiceFactory(
478 "ExtensionManagement",
479 BrowserContextDependencyManager::GetInstance()) {
480}
481
482ExtensionManagementFactory::~ExtensionManagementFactory() {
483}
484
485KeyedService* ExtensionManagementFactory::BuildServiceInstanceFor(
486 content::BrowserContext* context) const {
rkaplowdd66a1342015-03-05 00:31:49487 TRACE_EVENT0("browser,startup",
488 "ExtensionManagementFactory::BuildServiceInstanceFor");
binjin1569c9b2014-09-05 13:33:18489 return new ExtensionManagement(
490 Profile::FromBrowserContext(context)->GetPrefs());
491}
492
binjin9733df12014-09-08 15:21:21493content::BrowserContext* ExtensionManagementFactory::GetBrowserContextToUse(
494 content::BrowserContext* context) const {
495 return chrome::GetBrowserContextRedirectedInIncognito(context);
496}
497
binjinb2454382014-09-22 15:17:43498void ExtensionManagementFactory::RegisterProfilePrefs(
499 user_prefs::PrefRegistrySyncable* user_prefs) {
raymesaa608722015-04-27 03:00:25500 user_prefs->RegisterDictionaryPref(pref_names::kExtensionManagement);
binjinb2454382014-09-22 15:17:43501}
502
binjin5f405ef2014-09-03 21:23:16503} // namespace extensions