1 // 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
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "base/callback_helpers.h"
11 #include "base/logging.h"
12 #include "base/metrics/histogram_functions.h"
13 #include "base/stl_util.h"
14 #include "base/strings/string16.h"
15 #include "base/strings/string_split.h"
16 #include "base/strings/string_util.h"
17 #include "base/syslog_logging.h"
18 #include "base/trace_event/trace_event.h"
19 #include "base/version.h"
20 #include "chrome/browser/extensions/extension_management_constants.h"
21 #include "chrome/browser/extensions/extension_management_internal.h"
22 #include "chrome/browser/extensions/external_policy_loader.h"
23 #include "chrome/browser/extensions/external_provider_impl.h"
24 #include "chrome/browser/extensions/forced_extensions/install_stage_tracker_factory.h"
25 #include "chrome/browser/extensions/permissions_based_management_policy_provider.h"
26 #include "chrome/browser/extensions/standard_management_policy_provider.h"
27 #include "chrome/browser/profiles/incognito_helpers.h"
28 #include "chrome/browser/profiles/profile.h"
29 #include "chrome/common/extensions/extension_constants.h"
30 #include "chrome/common/pref_names.h"
31 #include "components/crx_file/id_util.h"
32 #include "components/keyed_service/content/browser_context_dependency_manager.h"
33 #include "components/pref_registry/pref_registry_syncable.h"
34 #include "components/prefs/pref_service.h"
35 #include "extensions/browser/pref_names.h"
36 #include "extensions/common/extension.h"
37 #include "extensions/common/extension_urls.h"
38 #include "extensions/common/manifest_constants.h"
39 #include "extensions/common/permissions/api_permission_set.h"
40 #include "extensions/common/permissions/permission_set.h"
41 #include "extensions/common/url_pattern.h"
42 #include "url/gurl.h"
43
44 #if defined(OS_CHROMEOS)
45 #include "chrome/browser/chromeos/profiles/profile_helper.h"
46 #else
47 #include "components/enterprise/browser/reporting/common_pref_names.h"
48 #endif
49
50 namespace extensions {
51
ExtensionManagement(Profile * profile)52 ExtensionManagement::ExtensionManagement(Profile* profile)
53 : profile_(profile),
54 pref_service_(profile_->GetPrefs()),
55 is_child_(profile_->IsChild()) {
56 TRACE_EVENT0("browser,startup",
57 "ExtensionManagement::ExtensionManagement::ctor");
58 #if defined(OS_CHROMEOS)
59 is_signin_profile_ = chromeos::ProfileHelper::IsSigninProfile(profile);
60 #endif
61 pref_change_registrar_.Init(pref_service_);
62 base::Closure pref_change_callback = base::BindRepeating(
63 &ExtensionManagement::OnExtensionPrefChanged, base::Unretained(this));
64 pref_change_registrar_.Add(pref_names::kInstallAllowList,
65 pref_change_callback);
66 pref_change_registrar_.Add(pref_names::kInstallDenyList,
67 pref_change_callback);
68 pref_change_registrar_.Add(pref_names::kInstallForceList,
69 pref_change_callback);
70 pref_change_registrar_.Add(pref_names::kLoginScreenExtensions,
71 pref_change_callback);
72 pref_change_registrar_.Add(pref_names::kAllowedInstallSites,
73 pref_change_callback);
74 pref_change_registrar_.Add(pref_names::kAllowedTypes, pref_change_callback);
75 pref_change_registrar_.Add(pref_names::kExtensionManagement,
76 pref_change_callback);
77 pref_change_registrar_.Add(prefs::kCloudExtensionRequestEnabled,
78 pref_change_callback);
79 #if !defined(OS_CHROMEOS)
80 pref_change_registrar_.Add(enterprise_reporting::kCloudReportingEnabled,
81 pref_change_callback);
82 #endif
83 // Note that both |global_settings_| and |default_settings_| will be null
84 // before first call to Refresh(), so in order to resolve this, Refresh() must
85 // be called in the initialization of ExtensionManagement.
86 Refresh();
87 ReportExtensionManagementInstallCreationStage(
88 InstallStageTracker::InstallCreationStage::
89 NOTIFIED_FROM_MANAGEMENT_INITIAL_CREATION_FORCED,
90 InstallStageTracker::InstallCreationStage::
91 NOTIFIED_FROM_MANAGEMENT_INITIAL_CREATION_NOT_FORCED);
92 providers_.push_back(
93 std::make_unique<StandardManagementPolicyProvider>(this));
94 providers_.push_back(
95 std::make_unique<PermissionsBasedManagementPolicyProvider>(this));
96 }
97
~ExtensionManagement()98 ExtensionManagement::~ExtensionManagement() {
99 }
100
Shutdown()101 void ExtensionManagement::Shutdown() {
102 pref_change_registrar_.RemoveAll();
103 pref_service_ = nullptr;
104 }
105
AddObserver(Observer * observer)106 void ExtensionManagement::AddObserver(Observer* observer) {
107 observer_list_.AddObserver(observer);
108 }
109
RemoveObserver(Observer * observer)110 void ExtensionManagement::RemoveObserver(Observer* observer) {
111 observer_list_.RemoveObserver(observer);
112 }
113
114 const std::vector<std::unique_ptr<ManagementPolicy::Provider>>&
GetProviders() const115 ExtensionManagement::GetProviders() const {
116 return providers_;
117 }
118
BlocklistedByDefault() const119 bool ExtensionManagement::BlocklistedByDefault() const {
120 return (default_settings_->installation_mode == INSTALLATION_BLOCKED ||
121 default_settings_->installation_mode == INSTALLATION_REMOVED);
122 }
123
GetInstallationMode(const Extension * extension) const124 ExtensionManagement::InstallationMode ExtensionManagement::GetInstallationMode(
125 const Extension* extension) const {
126 std::string update_url;
127 if (extension->manifest()->GetString(manifest_keys::kUpdateURL, &update_url))
128 return GetInstallationMode(extension->id(), update_url);
129 return GetInstallationMode(extension->id(), std::string());
130 }
131
GetInstallationMode(const ExtensionId & extension_id,const std::string & update_url) const132 ExtensionManagement::InstallationMode ExtensionManagement::GetInstallationMode(
133 const ExtensionId& extension_id,
134 const std::string& update_url) const {
135 // Check per-extension installation mode setting first.
136 auto iter_id = settings_by_id_.find(extension_id);
137 if (iter_id != settings_by_id_.end())
138 return iter_id->second->installation_mode;
139 // Check per-update-url installation mode setting.
140 if (!update_url.empty()) {
141 auto iter_update_url = settings_by_update_url_.find(update_url);
142 if (iter_update_url != settings_by_update_url_.end())
143 return iter_update_url->second->installation_mode;
144 }
145 // Fall back to default installation mode setting.
146 return default_settings_->installation_mode;
147 }
148
149 std::unique_ptr<base::DictionaryValue>
GetForceInstallList() const150 ExtensionManagement::GetForceInstallList() const {
151 return GetInstallListByMode(INSTALLATION_FORCED);
152 }
153
154 std::unique_ptr<base::DictionaryValue>
GetRecommendedInstallList() const155 ExtensionManagement::GetRecommendedInstallList() const {
156 return GetInstallListByMode(INSTALLATION_RECOMMENDED);
157 }
158
HasAllowlistedExtension() const159 bool ExtensionManagement::HasAllowlistedExtension() const {
160 if (default_settings_->installation_mode != INSTALLATION_BLOCKED &&
161 default_settings_->installation_mode != INSTALLATION_REMOVED) {
162 return true;
163 }
164
165 for (const auto& it : settings_by_id_) {
166 if (it.second->installation_mode == INSTALLATION_ALLOWED)
167 return true;
168 }
169 return false;
170 }
171
IsInstallationExplicitlyAllowed(const ExtensionId & id) const172 bool ExtensionManagement::IsInstallationExplicitlyAllowed(
173 const ExtensionId& id) const {
174 auto it = settings_by_id_.find(id);
175 // No settings explicitly specified for |id|.
176 if (it == settings_by_id_.end())
177 return false;
178 // Checks if the extension is on the automatically installed list or
179 // install allow-list.
180 InstallationMode mode = it->second->installation_mode;
181 return mode == INSTALLATION_FORCED || mode == INSTALLATION_RECOMMENDED ||
182 mode == INSTALLATION_ALLOWED;
183 }
184
IsInstallationExplicitlyBlocked(const ExtensionId & id) const185 bool ExtensionManagement::IsInstallationExplicitlyBlocked(
186 const ExtensionId& id) const {
187 auto it = settings_by_id_.find(id);
188 // No settings explicitly specified for |id|.
189 if (it == settings_by_id_.end())
190 return false;
191 // Checks if the extension is on the black list or removed list.
192 InstallationMode mode = it->second->installation_mode;
193 return mode == INSTALLATION_BLOCKED || mode == INSTALLATION_REMOVED;
194 }
195
IsOffstoreInstallAllowed(const GURL & url,const GURL & referrer_url) const196 bool ExtensionManagement::IsOffstoreInstallAllowed(
197 const GURL& url,
198 const GURL& referrer_url) const {
199 // No allowed install sites specified, disallow by default.
200 if (!global_settings_->has_restricted_install_sources)
201 return false;
202
203 const URLPatternSet& url_patterns = global_settings_->install_sources;
204
205 if (!url_patterns.MatchesURL(url))
206 return false;
207
208 // The referrer URL must also be allowlisted, unless the URL has the file
209 // scheme (there's no referrer for those URLs).
210 return url.SchemeIsFile() || url_patterns.MatchesURL(referrer_url);
211 }
212
IsAllowedManifestType(Manifest::Type manifest_type,const std::string & extension_id) const213 bool ExtensionManagement::IsAllowedManifestType(
214 Manifest::Type manifest_type,
215 const std::string& extension_id) const {
216 if (!global_settings_->has_restricted_allowed_types)
217 return true;
218 const std::vector<Manifest::Type>& allowed_types =
219 global_settings_->allowed_types;
220 return base::Contains(allowed_types, manifest_type);
221 }
222
GetBlockedAPIPermissions(const Extension * extension) const223 APIPermissionSet ExtensionManagement::GetBlockedAPIPermissions(
224 const Extension* extension) const {
225 std::string update_url;
226 if (extension->manifest()->GetString(manifest_keys::kUpdateURL, &update_url))
227 return GetBlockedAPIPermissions(extension->id(), update_url);
228 return GetBlockedAPIPermissions(extension->id(), std::string());
229 }
230
GetBlockedAPIPermissions(const ExtensionId & extension_id,const std::string & update_url) const231 APIPermissionSet ExtensionManagement::GetBlockedAPIPermissions(
232 const ExtensionId& extension_id,
233 const std::string& update_url) const {
234 // Fetch per-extension blocked permissions setting.
235 auto iter_id = settings_by_id_.find(extension_id);
236
237 // Fetch per-update-url blocked permissions setting.
238 auto iter_update_url = settings_by_update_url_.end();
239 if (!update_url.empty())
240 iter_update_url = settings_by_update_url_.find(update_url);
241
242 if (iter_id != settings_by_id_.end() &&
243 iter_update_url != settings_by_update_url_.end()) {
244 // Blocked permissions setting are specified in both per-extension and
245 // per-update-url settings, try to merge them.
246 APIPermissionSet merged;
247 APIPermissionSet::Union(iter_id->second->blocked_permissions,
248 iter_update_url->second->blocked_permissions,
249 &merged);
250 return merged;
251 }
252 // Check whether if in one of them, setting is specified.
253 if (iter_id != settings_by_id_.end())
254 return iter_id->second->blocked_permissions.Clone();
255 if (iter_update_url != settings_by_update_url_.end())
256 return iter_update_url->second->blocked_permissions.Clone();
257 // Fall back to the default blocked permissions setting.
258 return default_settings_->blocked_permissions.Clone();
259 }
260
GetDefaultPolicyBlockedHosts() const261 const URLPatternSet& ExtensionManagement::GetDefaultPolicyBlockedHosts() const {
262 return default_settings_->policy_blocked_hosts;
263 }
264
GetDefaultPolicyAllowedHosts() const265 const URLPatternSet& ExtensionManagement::GetDefaultPolicyAllowedHosts() const {
266 return default_settings_->policy_allowed_hosts;
267 }
268
GetPolicyBlockedHosts(const Extension * extension) const269 const URLPatternSet& ExtensionManagement::GetPolicyBlockedHosts(
270 const Extension* extension) const {
271 auto iter_id = settings_by_id_.find(extension->id());
272 if (iter_id != settings_by_id_.end())
273 return iter_id->second->policy_blocked_hosts;
274 return default_settings_->policy_blocked_hosts;
275 }
276
GetPolicyAllowedHosts(const Extension * extension) const277 const URLPatternSet& ExtensionManagement::GetPolicyAllowedHosts(
278 const Extension* extension) const {
279 auto iter_id = settings_by_id_.find(extension->id());
280 if (iter_id != settings_by_id_.end())
281 return iter_id->second->policy_allowed_hosts;
282 return default_settings_->policy_allowed_hosts;
283 }
284
UsesDefaultPolicyHostRestrictions(const Extension * extension) const285 bool ExtensionManagement::UsesDefaultPolicyHostRestrictions(
286 const Extension* extension) const {
287 return settings_by_id_.find(extension->id()) == settings_by_id_.end();
288 }
289
IsPolicyBlockedHost(const Extension * extension,const GURL & url) const290 bool ExtensionManagement::IsPolicyBlockedHost(const Extension* extension,
291 const GURL& url) const {
292 auto iter_id = settings_by_id_.find(extension->id());
293 if (iter_id != settings_by_id_.end())
294 return iter_id->second->policy_blocked_hosts.MatchesURL(url);
295 return default_settings_->policy_blocked_hosts.MatchesURL(url);
296 }
297
GetBlockedPermissions(const Extension * extension) const298 std::unique_ptr<const PermissionSet> ExtensionManagement::GetBlockedPermissions(
299 const Extension* extension) const {
300 // Only api permissions are supported currently.
301 return std::unique_ptr<const PermissionSet>(new PermissionSet(
302 GetBlockedAPIPermissions(extension), ManifestPermissionSet(),
303 URLPatternSet(), URLPatternSet()));
304 }
305
IsPermissionSetAllowed(const Extension * extension,const PermissionSet & perms) const306 bool ExtensionManagement::IsPermissionSetAllowed(
307 const Extension* extension,
308 const PermissionSet& perms) const {
309 std::string update_url;
310 if (extension->manifest()->GetString(manifest_keys::kUpdateURL, &update_url))
311 return IsPermissionSetAllowed(extension->id(), update_url, perms);
312 return IsPermissionSetAllowed(extension->id(), std::string(), perms);
313 }
314
IsPermissionSetAllowed(const ExtensionId & extension_id,const std::string & update_url,const PermissionSet & perms) const315 bool ExtensionManagement::IsPermissionSetAllowed(
316 const ExtensionId& extension_id,
317 const std::string& update_url,
318 const PermissionSet& perms) const {
319 for (const extensions::APIPermission* blocked_api :
320 GetBlockedAPIPermissions(extension_id, update_url)) {
321 if (perms.HasAPIPermission(blocked_api->id()))
322 return false;
323 }
324 return true;
325 }
326
BlockedInstallMessage(const ExtensionId & id) const327 const std::string ExtensionManagement::BlockedInstallMessage(
328 const ExtensionId& id) const {
329 auto iter_id = settings_by_id_.find(id);
330 if (iter_id != settings_by_id_.end())
331 return iter_id->second->blocked_install_message;
332 return default_settings_->blocked_install_message;
333 }
334
GetForcePinnedList() const335 ExtensionIdSet ExtensionManagement::GetForcePinnedList() const {
336 ExtensionIdSet force_pinned_list;
337 for (const auto& entry : settings_by_id_) {
338 if (entry.second->toolbar_pin == ToolbarPinMode::kForcePinned)
339 force_pinned_list.insert(entry.first);
340 }
341 return force_pinned_list;
342 }
343
CheckMinimumVersion(const Extension * extension,std::string * required_version) const344 bool ExtensionManagement::CheckMinimumVersion(
345 const Extension* extension,
346 std::string* required_version) const {
347 auto iter = settings_by_id_.find(extension->id());
348 // If there are no minimum version required for |extension|, return true.
349 if (iter == settings_by_id_.end() || !iter->second->minimum_version_required)
350 return true;
351 bool meets_requirement = extension->version().CompareTo(
352 *iter->second->minimum_version_required) >= 0;
353 // Output a human readable version string for prompting if necessary.
354 if (!meets_requirement && required_version)
355 *required_version = iter->second->minimum_version_required->GetString();
356 return meets_requirement;
357 }
358
Refresh()359 void ExtensionManagement::Refresh() {
360 TRACE_EVENT0("browser,startup", "ExtensionManagement::Refresh");
361 // Load all extension management settings preferences.
362 const base::ListValue* allowed_list_pref =
363 static_cast<const base::ListValue*>(LoadPreference(
364 pref_names::kInstallAllowList, true, base::Value::Type::LIST));
365 // Allow user to use preference to block certain extensions. Note that policy
366 // managed forcelist or allowlist will always override this.
367 const base::ListValue* denied_list_pref =
368 static_cast<const base::ListValue*>(LoadPreference(
369 pref_names::kInstallDenyList, false, base::Value::Type::LIST));
370 const base::DictionaryValue* forced_list_pref =
371 static_cast<const base::DictionaryValue*>(LoadPreference(
372 pref_names::kInstallForceList, true, base::Value::Type::DICTIONARY));
373 const base::DictionaryValue* login_screen_extensions_pref = nullptr;
374 if (is_signin_profile_) {
375 login_screen_extensions_pref = static_cast<const base::DictionaryValue*>(
376 LoadPreference(pref_names::kLoginScreenExtensions, true,
377 base::Value::Type::DICTIONARY));
378 }
379 const base::ListValue* install_sources_pref =
380 static_cast<const base::ListValue*>(LoadPreference(
381 pref_names::kAllowedInstallSites, true, base::Value::Type::LIST));
382 const base::ListValue* allowed_types_pref =
383 static_cast<const base::ListValue*>(LoadPreference(
384 pref_names::kAllowedTypes, true, base::Value::Type::LIST));
385 const base::DictionaryValue* dict_pref =
386 static_cast<const base::DictionaryValue*>(
387 LoadPreference(pref_names::kExtensionManagement,
388 true,
389 base::Value::Type::DICTIONARY));
390 const base::Value* extension_request_pref = LoadPreference(
391 prefs::kCloudExtensionRequestEnabled, false, base::Value::Type::BOOLEAN);
392
393 // Reset all settings.
394 global_settings_.reset(new internal::GlobalSettings());
395 settings_by_id_.clear();
396 default_settings_.reset(new internal::IndividualSettings());
397
398 // Parse default settings.
399 const base::Value wildcard("*");
400 if ((denied_list_pref &&
401 denied_list_pref->Find(wildcard) != denied_list_pref->end()) ||
402 (extension_request_pref && extension_request_pref->GetBool())) {
403 default_settings_->installation_mode = INSTALLATION_BLOCKED;
404 }
405
406 const base::DictionaryValue* subdict = NULL;
407 if (dict_pref &&
408 dict_pref->GetDictionary(schema_constants::kWildcard, &subdict)) {
409 if (!default_settings_->Parse(
410 subdict, internal::IndividualSettings::SCOPE_DEFAULT)) {
411 LOG(WARNING) << "Default extension management settings parsing error.";
412 default_settings_->Reset();
413 }
414
415 // Settings from new preference have higher priority over legacy ones.
416 const base::ListValue* list_value = NULL;
417 if (subdict->GetList(schema_constants::kInstallSources, &list_value))
418 install_sources_pref = list_value;
419 if (subdict->GetList(schema_constants::kAllowedTypes, &list_value))
420 allowed_types_pref = list_value;
421 }
422
423 // Parse legacy preferences.
424 ExtensionId id;
425
426 if (allowed_list_pref) {
427 for (auto it = allowed_list_pref->begin(); it != allowed_list_pref->end();
428 ++it) {
429 if (it->GetAsString(&id) && crx_file::id_util::IdIsValid(id))
430 AccessById(id)->installation_mode = INSTALLATION_ALLOWED;
431 }
432 }
433
434 if (denied_list_pref) {
435 for (auto it = denied_list_pref->begin(); it != denied_list_pref->end();
436 ++it) {
437 if (it->GetAsString(&id) && crx_file::id_util::IdIsValid(id))
438 AccessById(id)->installation_mode = INSTALLATION_BLOCKED;
439 }
440 }
441
442 UpdateForcedExtensions(forced_list_pref);
443 UpdateForcedExtensions(login_screen_extensions_pref);
444
445 if (install_sources_pref) {
446 global_settings_->has_restricted_install_sources = true;
447 for (auto it = install_sources_pref->begin();
448 it != install_sources_pref->end(); ++it) {
449 std::string url_pattern;
450 if (it->GetAsString(&url_pattern)) {
451 URLPattern entry(URLPattern::SCHEME_ALL);
452 if (entry.Parse(url_pattern) == URLPattern::ParseResult::kSuccess) {
453 global_settings_->install_sources.AddPattern(entry);
454 } else {
455 LOG(WARNING) << "Invalid URL pattern in for preference "
456 << pref_names::kAllowedInstallSites << ": "
457 << url_pattern << ".";
458 }
459 }
460 }
461 }
462
463 if (allowed_types_pref) {
464 global_settings_->has_restricted_allowed_types = true;
465 for (auto it = allowed_types_pref->begin(); it != allowed_types_pref->end();
466 ++it) {
467 int int_value;
468 std::string string_value;
469 if (it->GetAsInteger(&int_value) && int_value >= 0 &&
470 int_value < Manifest::Type::NUM_LOAD_TYPES) {
471 global_settings_->allowed_types.push_back(
472 static_cast<Manifest::Type>(int_value));
473 } else if (it->GetAsString(&string_value)) {
474 Manifest::Type manifest_type =
475 schema_constants::GetManifestType(string_value);
476 if (manifest_type != Manifest::TYPE_UNKNOWN)
477 global_settings_->allowed_types.push_back(manifest_type);
478 }
479 }
480 }
481
482 if (dict_pref) {
483 // Parse new extension management preference.
484 for (base::DictionaryValue::Iterator iter(*dict_pref); !iter.IsAtEnd();
485 iter.Advance()) {
486 if (iter.key() == schema_constants::kWildcard)
487 continue;
488 if (!iter.value().GetAsDictionary(&subdict))
489 continue;
490 if (base::StartsWith(iter.key(), schema_constants::kUpdateUrlPrefix,
491 base::CompareCase::SENSITIVE)) {
492 const std::string& update_url =
493 iter.key().substr(strlen(schema_constants::kUpdateUrlPrefix));
494 if (!GURL(update_url).is_valid()) {
495 LOG(WARNING) << "Invalid update URL: " << update_url << ".";
496 continue;
497 }
498 internal::IndividualSettings* by_update_url =
499 AccessByUpdateUrl(update_url);
500 if (!by_update_url->Parse(
501 subdict, internal::IndividualSettings::SCOPE_UPDATE_URL)) {
502 settings_by_update_url_.erase(update_url);
503 LOG(WARNING) << "Malformed Extension Management settings for "
504 "extensions with update url: " << update_url << ".";
505 }
506 } else {
507 std::vector<std::string> extension_ids = base::SplitString(
508 iter.key(), ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
509 InstallStageTracker* install_stage_tracker =
510 InstallStageTracker::Get(profile_);
511 for (const auto& extension_id : extension_ids) {
512 if (!crx_file::id_util::IdIsValid(extension_id)) {
513 SYSLOG(WARNING) << "Invalid extension ID : " << extension_id << ".";
514 continue;
515 }
516 internal::IndividualSettings* by_id = AccessById(extension_id);
517 const bool included_in_forcelist =
518 by_id->installation_mode == InstallationMode::INSTALLATION_FORCED;
519 if (!by_id->Parse(subdict,
520 internal::IndividualSettings::SCOPE_INDIVIDUAL)) {
521 settings_by_id_.erase(extension_id);
522 install_stage_tracker->ReportFailure(
523 extension_id, InstallStageTracker::FailureReason::
524 MALFORMED_EXTENSION_SETTINGS);
525 SYSLOG(WARNING) << "Malformed Extension Management settings for "
526 << extension_id << ".";
527 }
528 // If applying the ExtensionSettings policy changes installation mode
529 // from force-installed to anything else, the extension might not get
530 // installed and will get stuck in CREATED stage.
531 if (included_in_forcelist &&
532 by_id->installation_mode !=
533 InstallationMode::INSTALLATION_FORCED) {
534 install_stage_tracker->ReportFailure(
535 extension_id,
536 InstallStageTracker::FailureReason::OVERRIDDEN_BY_SETTINGS);
537 }
538 }
539 }
540 }
541 size_t force_pinned_count = GetForcePinnedList().size();
542 if (force_pinned_count > 0) {
543 base::UmaHistogramCounts100("Extensions.ForceToolbarPinnedCount",
544 force_pinned_count);
545 }
546 }
547 }
548
LoadPreference(const char * pref_name,bool force_managed,base::Value::Type expected_type) const549 const base::Value* ExtensionManagement::LoadPreference(
550 const char* pref_name,
551 bool force_managed,
552 base::Value::Type expected_type) const {
553 if (!pref_service_)
554 return nullptr;
555 const PrefService::Preference* pref =
556 pref_service_->FindPreference(pref_name);
557 if (pref && !pref->IsDefaultValue() &&
558 (!force_managed || pref->IsManaged())) {
559 const base::Value* value = pref->GetValue();
560 if (value && value->type() == expected_type)
561 return value;
562 }
563 return nullptr;
564 }
565
OnExtensionPrefChanged()566 void ExtensionManagement::OnExtensionPrefChanged() {
567 Refresh();
568 NotifyExtensionManagementPrefChanged();
569 }
570
NotifyExtensionManagementPrefChanged()571 void ExtensionManagement::NotifyExtensionManagementPrefChanged() {
572 ReportExtensionManagementInstallCreationStage(
573 InstallStageTracker::InstallCreationStage::NOTIFIED_FROM_MANAGEMENT,
574 InstallStageTracker::InstallCreationStage::
575 NOTIFIED_FROM_MANAGEMENT_NOT_FORCED);
576 for (auto& observer : observer_list_)
577 observer.OnExtensionManagementSettingsChanged();
578 }
579
ReportExtensionManagementInstallCreationStage(InstallStageTracker::InstallCreationStage forced_stage,InstallStageTracker::InstallCreationStage other_stage)580 void ExtensionManagement::ReportExtensionManagementInstallCreationStage(
581 InstallStageTracker::InstallCreationStage forced_stage,
582 InstallStageTracker::InstallCreationStage other_stage) {
583 InstallStageTracker* install_stage_tracker =
584 InstallStageTracker::Get(profile_);
585 for (const auto& entry : settings_by_id_) {
586 if (entry.second->installation_mode == INSTALLATION_FORCED) {
587 install_stage_tracker->ReportInstallCreationStage(entry.first,
588 forced_stage);
589 } else {
590 install_stage_tracker->ReportInstallCreationStage(entry.first,
591 other_stage);
592 }
593 }
594 }
595
596 std::unique_ptr<base::DictionaryValue>
GetInstallListByMode(InstallationMode installation_mode) const597 ExtensionManagement::GetInstallListByMode(
598 InstallationMode installation_mode) const {
599 auto extension_dict = std::make_unique<base::DictionaryValue>();
600 for (const auto& entry : settings_by_id_) {
601 if (entry.second->installation_mode == installation_mode) {
602 ExternalPolicyLoader::AddExtension(extension_dict.get(), entry.first,
603 entry.second->update_url);
604 }
605 }
606 return extension_dict;
607 }
608
UpdateForcedExtensions(const base::DictionaryValue * extension_dict)609 void ExtensionManagement::UpdateForcedExtensions(
610 const base::DictionaryValue* extension_dict) {
611 if (!extension_dict)
612 return;
613
614 std::string update_url;
615 InstallStageTracker* install_stage_tracker =
616 InstallStageTracker::Get(profile_);
617 for (base::DictionaryValue::Iterator it(*extension_dict); !it.IsAtEnd();
618 it.Advance()) {
619 if (!crx_file::id_util::IdIsValid(it.key())) {
620 install_stage_tracker->ReportFailure(
621 it.key(), InstallStageTracker::FailureReason::INVALID_ID);
622 continue;
623 }
624 const base::DictionaryValue* dict_value = nullptr;
625 if (it.value().GetAsDictionary(&dict_value) &&
626 dict_value->GetStringWithoutPathExpansion(
627 ExternalProviderImpl::kExternalUpdateUrl, &update_url)) {
628 internal::IndividualSettings* by_id = AccessById(it.key());
629 by_id->installation_mode = INSTALLATION_FORCED;
630 by_id->update_url = update_url;
631 install_stage_tracker->ReportInstallationStage(
632 it.key(), InstallStageTracker::Stage::CREATED);
633 install_stage_tracker->ReportInstallCreationStage(
634 it.key(),
635 InstallStageTracker::InstallCreationStage::CREATION_INITIATED);
636 } else {
637 install_stage_tracker->ReportFailure(
638 it.key(), InstallStageTracker::FailureReason::NO_UPDATE_URL);
639 }
640 }
641 }
642
AccessById(const ExtensionId & id)643 internal::IndividualSettings* ExtensionManagement::AccessById(
644 const ExtensionId& id) {
645 DCHECK(crx_file::id_util::IdIsValid(id)) << "Invalid ID: " << id;
646 std::unique_ptr<internal::IndividualSettings>& settings = settings_by_id_[id];
647 if (!settings) {
648 settings =
649 std::make_unique<internal::IndividualSettings>(default_settings_.get());
650 }
651 return settings.get();
652 }
653
AccessByUpdateUrl(const std::string & update_url)654 internal::IndividualSettings* ExtensionManagement::AccessByUpdateUrl(
655 const std::string& update_url) {
656 DCHECK(GURL(update_url).is_valid()) << "Invalid update URL: " << update_url;
657 std::unique_ptr<internal::IndividualSettings>& settings =
658 settings_by_update_url_[update_url];
659 if (!settings) {
660 settings =
661 std::make_unique<internal::IndividualSettings>(default_settings_.get());
662 }
663 return settings.get();
664 }
665
666 // static
GetForBrowserContext(content::BrowserContext * context)667 ExtensionManagement* ExtensionManagementFactory::GetForBrowserContext(
668 content::BrowserContext* context) {
669 return static_cast<ExtensionManagement*>(
670 GetInstance()->GetServiceForBrowserContext(context, true));
671 }
672
673 // static
GetInstance()674 ExtensionManagementFactory* ExtensionManagementFactory::GetInstance() {
675 return base::Singleton<ExtensionManagementFactory>::get();
676 }
677
ExtensionManagementFactory()678 ExtensionManagementFactory::ExtensionManagementFactory()
679 : BrowserContextKeyedServiceFactory(
680 "ExtensionManagement",
681 BrowserContextDependencyManager::GetInstance()) {
682 DependsOn(InstallStageTrackerFactory::GetInstance());
683 }
684
~ExtensionManagementFactory()685 ExtensionManagementFactory::~ExtensionManagementFactory() {
686 }
687
BuildServiceInstanceFor(content::BrowserContext * context) const688 KeyedService* ExtensionManagementFactory::BuildServiceInstanceFor(
689 content::BrowserContext* context) const {
690 TRACE_EVENT0("browser,startup",
691 "ExtensionManagementFactory::BuildServiceInstanceFor");
692 return new ExtensionManagement(Profile::FromBrowserContext(context));
693 }
694
GetBrowserContextToUse(content::BrowserContext * context) const695 content::BrowserContext* ExtensionManagementFactory::GetBrowserContextToUse(
696 content::BrowserContext* context) const {
697 return chrome::GetBrowserContextRedirectedInIncognito(context);
698 }
699
RegisterProfilePrefs(user_prefs::PrefRegistrySyncable * user_prefs)700 void ExtensionManagementFactory::RegisterProfilePrefs(
701 user_prefs::PrefRegistrySyncable* user_prefs) {
702 user_prefs->RegisterDictionaryPref(pref_names::kExtensionManagement);
703 }
704
705 } // namespace extensions
706