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