blob: 74f300e03564df3e8baf1662cf79d61f7eef94d9 [file] [log] [blame]
[email protected]a12ce8b22012-01-17 18:40:531// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]8e4560b62011-01-14 10:09:142// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]5df038b2012-07-16 19:03:275#include "chrome/browser/extensions/external_provider_impl.h"
[email protected]8e4560b62011-01-14 10:09:146
avia2f4804a2015-12-24 23:11:137#include <stddef.h>
8
Toni Barzic87026682018-01-08 23:21:049#include <memory>
[email protected]8a839a02013-03-07 05:23:3310#include <set>
Toni Barzic87026682018-01-08 23:21:0411#include <utility>
[email protected]8a839a02013-03-07 05:23:3312#include <vector>
13
[email protected]83b59325a2011-10-14 15:58:0714#include "base/command_line.h"
Jan Wilken Dörrieb5a41c32020-12-09 18:55:4715#include "base/containers/contains.h"
[email protected]57999812013-02-24 05:40:5216#include "base/files/file_path.h"
[email protected]8e4560b62011-01-14 10:09:1417#include "base/logging.h"
Matthew Dentonef83a622019-08-30 02:07:0018#include "base/memory/scoped_refptr.h"
[email protected]51a7a9d2011-09-27 17:21:4119#include "base/metrics/field_trial.h"
[email protected]46acbf12013-06-10 18:43:4220#include "base/strings/string_util.h"
rkaplowdd66a1342015-03-05 00:31:4921#include "base/trace_event/trace_event.h"
[email protected]8e4560b62011-01-14 10:09:1422#include "base/values.h"
23#include "base/version.h"
Nico Weber897593f2019-07-25 23:17:5524#include "build/branding_buildflags.h"
avia2f4804a2015-12-24 23:11:1325#include "build/build_config.h"
Yuta Hijikata1290fee22020-11-25 09:46:2826#include "build/chromeos_buildflags.h"
[email protected]8a839a02013-03-07 05:23:3327#include "chrome/browser/app_mode/app_mode_utils.h"
[email protected]e601e822011-10-05 19:25:3728#include "chrome/browser/browser_process.h"
pbond43ddd4f2015-09-08 16:39:1929#include "chrome/browser/browser_process_platform_part.h"
binjin30301062014-09-08 20:27:3430#include "chrome/browser/extensions/extension_management.h"
xiyuan65b68ab12015-06-26 19:00:1831#include "chrome/browser/extensions/extension_migrator.h"
[email protected]8aa50c7752013-05-23 12:57:5032#include "chrome/browser/extensions/external_component_loader.h"
[email protected]5df038b2012-07-16 19:03:2733#include "chrome/browser/extensions/external_policy_loader.h"
34#include "chrome/browser/extensions/external_pref_loader.h"
Oleg Davydovdec175a2020-05-25 16:44:2935#include "chrome/browser/extensions/forced_extensions/install_stage_tracker.h"
dpolukhin1687ef32015-06-22 11:12:3736#include "chrome/browser/policy/profile_policy_connector.h"
[email protected]8e4560b62011-01-14 10:09:1437#include "chrome/browser/profiles/profile.h"
Song Fangzhencda4af62021-09-09 05:24:0238#include "chrome/browser/web_applications/preinstalled_app_install_features.h"
[email protected]f0841cd2011-01-19 15:07:2439#include "chrome/common/chrome_paths.h"
[email protected]83b59325a2011-10-14 15:58:0740#include "chrome/common/chrome_switches.h"
xiyuan65b68ab12015-06-26 19:00:1841#include "chrome/common/extensions/extension_constants.h"
dpolukhin2c6ef2932015-05-12 16:06:1342#include "chrome/common/pref_names.h"
[email protected]fdd28372014-08-21 02:27:2643#include "components/crx_file/id_util.h"
brettwb1fc1b82016-02-02 00:19:0844#include "components/prefs/pref_service.h"
[email protected]c38831a12011-10-28 12:44:4945#include "content/public/browser/browser_thread.h"
David Bertoni58c113a2019-08-02 19:53:2646#include "extensions/browser/extension_registry.h"
lazyboye8634172016-01-28 00:10:4847#include "extensions/browser/external_install_info.h"
[email protected]301116c62013-11-26 10:37:4548#include "extensions/browser/external_provider_interface.h"
Dominique Fauteux-Chapleauff3bb352019-10-16 14:32:3449#include "extensions/browser/pref_names.h"
Phillis Tang28427c462021-10-19 20:50:3850#include "extensions/common/constants.h"
[email protected]e4452d32013-11-15 23:07:4151#include "extensions/common/extension.h"
[email protected]d42c11152013-08-22 19:36:3252#include "extensions/common/manifest.h"
[email protected]9d32ded072011-10-11 16:31:0553#include "ui/base/l10n/l10n_util.h"
[email protected]8e4560b62011-01-14 10:09:1454
Yuta Hijikata1290fee22020-11-25 09:46:2855#if BUILDFLAG(IS_CHROMEOS_ASH)
Yao Lic9cd767d2021-11-16 02:17:4756#include "ash/components/arc/arc_util.h"
Henrique Ferreiro37770262021-02-06 01:20:5357#include "ash/constants/ash_paths.h"
Wenzhao Zang463f1142018-09-05 22:50:5058#include "base/path_service.h"
Henrique Ferreiro53d4dc42021-01-27 01:02:3859#include "chrome/browser/ash/app_mode/kiosk_app_external_loader.h"
Yeunjoo Choi91907642021-04-16 13:18:1960#include "chrome/browser/ash/customization/customization_document.h"
Henrique Ferreiro606669a2021-02-24 13:36:5561#include "chrome/browser/ash/login/demo_mode/demo_extensions_external_loader.h"
62#include "chrome/browser/ash/login/demo_mode/demo_session.h"
Yeunjoo Choi7227dba2021-08-04 06:35:4763#include "chrome/browser/ash/policy/core/browser_policy_connector_ash.h"
Yeunjoo Choi8623e4a2021-07-02 01:57:0664#include "chrome/browser/ash/policy/core/device_local_account.h"
65#include "chrome/browser/ash/policy/core/device_local_account_policy_service.h"
Yeunjoo Choi15ab1ac2021-02-04 17:15:0766#include "chrome/browser/ash/profiles/profile_helper.h"
[email protected]af984882013-10-21 21:08:5167#include "chrome/browser/chromeos/extensions/device_local_account_external_policy_loader.h"
Maksim Ivanov8738d332020-01-07 22:19:0168#include "chrome/browser/chromeos/extensions/signin_screen_extensions_external_loader.h"
Swapnil5eca0412021-02-12 08:32:5469#include "extensions/common/constants.h"
[email protected]b39d25712013-03-14 09:53:4070#else
Daniel Murphy3657906d2021-04-13 20:33:1271#include "chrome/browser/extensions/preinstalled_apps.h"
[email protected]86c6b9e32011-10-25 17:09:1072#endif
73
[email protected]8e4560b62011-01-14 10:09:1474#if defined(OS_WIN)
[email protected]5df038b2012-07-16 19:03:2775#include "chrome/browser/extensions/external_registry_loader_win.h"
[email protected]8e4560b62011-01-14 10:09:1476#endif
77
[email protected]631bb742011-11-02 11:29:3978using content::BrowserThread;
Gyuyoung Kim2e954c42021-03-19 14:06:2979using extensions::mojom::ManifestLocation;
[email protected]5df038b2012-07-16 19:03:2780
81namespace extensions {
[email protected]631bb742011-11-02 11:29:3982
Ahmed Fakhry9ef29e042017-09-01 16:32:0083namespace {
84
Yuta Hijikata1290fee22020-11-25 09:46:2885#if BUILDFLAG(IS_CHROMEOS_ASH)
Ahmed Fakhry9ef29e042017-09-01 16:32:0086
Wei Lee799de532021-11-10 03:33:3687const char kCameraAppId[] = "hfhhnacclhffhdffklopdkcgdhifgngh";
88
Daniel Murphy3657906d2021-04-13 20:33:1289// Certain pre-installed extensions are no longer needed on ARC devices as they
90// were replaced by their ARC counterparts.
Ahmed Fakhry9ef29e042017-09-01 16:32:0091bool ShouldUninstallExtensionReplacedByArcApp(const std::string& extension_id) {
Alex Newcomerf8c542f2018-08-13 23:48:5092 if (!arc::IsArcAvailable())
Ahmed Fakhry9ef29e042017-09-01 16:32:0093 return false;
94
95 if (extension_id == extension_misc::kGooglePlayBooksAppId ||
96 extension_id == extension_misc::kGooglePlayMoviesAppId ||
97 extension_id == extension_misc::kGooglePlayMusicAppId) {
98 return true;
99 }
100
101 return false;
102}
103
Yuta Hijikata1290fee22020-11-25 09:46:28104#endif // BUILDFLAG(IS_CHROMEOS_ASH)
Ahmed Fakhry9ef29e042017-09-01 16:32:00105
106} // namespace
107
[email protected]8e4560b62011-01-14 10:09:14108// Constants for keeping track of extension preferences in a dictionary.
[email protected]d8fd0fd2014-03-24 13:16:06109const char ExternalProviderImpl::kInstallParam[] = "install_parameter";
[email protected]5df038b2012-07-16 19:03:27110const char ExternalProviderImpl::kExternalCrx[] = "external_crx";
[email protected]7425d7df2012-11-28 14:35:42111const char ExternalProviderImpl::kExternalVersion[] = "external_version";
112const char ExternalProviderImpl::kExternalUpdateUrl[] = "external_update_url";
[email protected]7425d7df2012-11-28 14:35:42113const char ExternalProviderImpl::kIsBookmarkApp[] = "is_bookmark_app";
114const char ExternalProviderImpl::kIsFromWebstore[] = "is_from_webstore";
[email protected]19eac6d2013-05-30 06:51:03115const char ExternalProviderImpl::kKeepIfPresent[] = "keep_if_present";
[email protected]bf9fd5ae2014-04-09 22:50:06116const char ExternalProviderImpl::kWasInstalledByOem[] = "was_installed_by_oem";
Alan Cutterb81d0e02020-08-05 09:10:34117const char ExternalProviderImpl::kWebAppMigrationFlag[] =
118 "web_app_migration_flag";
[email protected]bf9fd5ae2014-04-09 22:50:06119const char ExternalProviderImpl::kSupportedLocales[] = "supported_locales";
[email protected]2b6a5802014-08-16 07:58:08120const char ExternalProviderImpl::kMayBeUntrusted[] = "may_be_untrusted";
dpolukhin2c6ef2932015-05-12 16:06:13121const char ExternalProviderImpl::kMinProfileCreatedByVersion[] =
122 "min_profile_created_by_version";
dpolukhin1687ef32015-06-22 11:12:37123const char ExternalProviderImpl::kDoNotInstallForEnterprise[] =
124 "do_not_install_for_enterprise";
[email protected]8e4560b62011-01-14 10:09:14125
[email protected]af984882013-10-21 21:08:51126ExternalProviderImpl::ExternalProviderImpl(
127 VisitorInterface* service,
128 const scoped_refptr<ExternalLoader>& loader,
129 Profile* profile,
Gyuyoung Kim2e954c42021-03-19 14:06:29130 ManifestLocation crx_location,
131 ManifestLocation download_location,
[email protected]af984882013-10-21 21:08:51132 int creation_flags)
[email protected]4b4c0132013-06-12 17:58:55133 : crx_location_(crx_location),
134 download_location_(download_location),
135 service_(service),
[email protected]4b4c0132013-06-12 17:58:55136 loader_(loader),
137 profile_(profile),
Toni Barzic87026682018-01-08 23:21:04138 creation_flags_(creation_flags) {
Oleg Davydov66246bd92019-09-26 16:31:51139 DCHECK(profile_);
[email protected]8e4560b62011-01-14 10:09:14140 loader_->Init(this);
141}
142
[email protected]5df038b2012-07-16 19:03:27143ExternalProviderImpl::~ExternalProviderImpl() {
Istiaque Ahmedf6e72622017-09-08 23:14:17144 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]8e4560b62011-01-14 10:09:14145 loader_->OwnerShutdown();
146}
147
[email protected]5df038b2012-07-16 19:03:27148void ExternalProviderImpl::VisitRegisteredExtension() {
[email protected]8e4560b62011-01-14 10:09:14149 // The loader will call back to SetPrefs.
150 loader_->StartLoading();
151}
152
Anina Koehler100794e22021-09-08 13:09:52153void ExternalProviderImpl::SetPrefs(
154 std::unique_ptr<base::DictionaryValue> prefs) {
Istiaque Ahmedf6e72622017-09-08 23:14:17155 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]8e4560b62011-01-14 10:09:14156
[email protected]47fc70c2011-12-06 07:29:51157 // Check if the service is still alive. It is possible that it went
[email protected]8e4560b62011-01-14 10:09:14158 // away while |loader_| was working on the FILE thread.
159 if (!service_) return;
160
Oleg Davydovdec175a2020-05-25 16:44:29161 InstallStageTracker* install_stage_tracker =
162 InstallStageTracker::Get(profile_);
Peter Kasting7c683fe2021-06-24 15:12:10163 for (auto it : prefs->DictItems()) {
Swapnil5e0e0dc2020-09-21 14:59:47164 install_stage_tracker->ReportInstallCreationStage(
165 it.first,
166 InstallStageTracker::InstallCreationStage::SEEN_BY_EXTERNAL_PROVIDER);
Oleg Davydov52db8742019-08-20 09:14:40167 }
168
Istiaque Ahmeda7431b32017-08-20 18:33:37169 prefs_ = std::move(prefs);
[email protected]8a839a02013-03-07 05:23:33170 ready_ = true; // Queries for extensions are allowed from this point.
[email protected]8e4560b62011-01-14 10:09:14171
Maria Petrisordba7ac42021-10-06 09:01:30172 NotifyServiceOnExternalExtensionsFound(/*is_initial_load=*/true);
173 service_->OnExternalProviderReady(this);
174}
175
176void ExternalProviderImpl::TriggerOnExternalExtensionFound() {
177 DCHECK_CURRENTLY_ON(BrowserThread::UI);
178
179 // Check if the service is still alive. It is possible that it went
180 // away while |loader_| was working on the FILE thread. The prefs can be
181 // missing if SetPrefs() was not called yet.
182 if (!service_ || !prefs_)
183 return;
184
185 NotifyServiceOnExternalExtensionsFound(/*is_initial_load=*/false);
186}
187
188void ExternalProviderImpl::NotifyServiceOnExternalExtensionsFound(
189 bool is_initial_load) {
Devlin Cronin19f70b6a2017-10-01 04:14:05190 std::vector<ExternalInstallInfoUpdateUrl> external_update_url_extensions;
191 std::vector<ExternalInstallInfoFile> external_file_extensions;
lazyboye8634172016-01-28 00:10:48192
193 RetrieveExtensionsFromPrefs(&external_update_url_extensions,
194 &external_file_extensions);
lazyboy4aeef202016-09-07 21:28:59195 for (const auto& extension : external_update_url_extensions)
Maria Petrisordba7ac42021-10-06 09:01:30196 service_->OnExternalExtensionUpdateUrlFound(extension, is_initial_load);
lazyboye8634172016-01-28 00:10:48197
lazyboy4aeef202016-09-07 21:28:59198 for (const auto& extension : external_file_extensions)
Devlin Cronin19f70b6a2017-10-01 04:14:05199 service_->OnExternalExtensionFileFound(extension);
lazyboye8634172016-01-28 00:10:48200}
201
Anina Koehler100794e22021-09-08 13:09:52202void ExternalProviderImpl::UpdatePrefs(
203 std::unique_ptr<base::DictionaryValue> prefs) {
Istiaque Ahmedf6e72622017-09-08 23:14:17204 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Toni Barzic87026682018-01-08 23:21:04205 CHECK(allow_updates_);
lazyboye8634172016-01-28 00:10:48206
207 // Check if the service is still alive. It is possible that it went
208 // away while |loader_| was working on the FILE thread.
209 if (!service_)
210 return;
211
212 std::set<std::string> removed_extensions;
213 // Find extensions that were removed by this ExternalProvider.
Anina Koehler100794e22021-09-08 13:09:52214 for (base::DictionaryValue::Iterator i(*prefs_); !i.IsAtEnd(); i.Advance()) {
215 const std::string& extension_id = i.key();
lazyboye8634172016-01-28 00:10:48216 // Don't bother about invalid ids.
217 if (!crx_file::id_util::IdIsValid(extension_id))
218 continue;
Anina Koehler100794e22021-09-08 13:09:52219 if (!prefs->HasKey(extension_id))
lazyboye8634172016-01-28 00:10:48220 removed_extensions.insert(extension_id);
221 }
222
Istiaque Ahmeda7431b32017-08-20 18:33:37223 prefs_ = std::move(prefs);
lazyboye8634172016-01-28 00:10:48224
Devlin Cronin19f70b6a2017-10-01 04:14:05225 std::vector<ExternalInstallInfoUpdateUrl> external_update_url_extensions;
226 std::vector<ExternalInstallInfoFile> external_file_extensions;
lazyboye8634172016-01-28 00:10:48227 RetrieveExtensionsFromPrefs(&external_update_url_extensions,
228 &external_file_extensions);
229
230 // Notify ExtensionService about completion of finding incremental updates
231 // from this provider.
232 // Provide the list of added and removed extensions.
233 service_->OnExternalProviderUpdateComplete(
234 this, external_update_url_extensions, external_file_extensions,
235 removed_extensions);
236}
237
238void ExternalProviderImpl::RetrieveExtensionsFromPrefs(
Devlin Cronin19f70b6a2017-10-01 04:14:05239 std::vector<ExternalInstallInfoUpdateUrl>* external_update_url_extensions,
240 std::vector<ExternalInstallInfoFile>* external_file_extensions) {
[email protected]9d32ded072011-10-11 16:31:05241 // Set of unsupported extensions that need to be deleted from prefs_.
242 std::set<std::string> unsupported_extensions;
Oleg Davydovdec175a2020-05-25 16:44:29243 InstallStageTracker* install_stage_tracker =
244 InstallStageTracker::Get(profile_);
[email protected]9d32ded072011-10-11 16:31:05245
lazyboye8634172016-01-28 00:10:48246 // Discover all the extensions this provider has.
Anina Koehler100794e22021-09-08 13:09:52247 for (base::DictionaryValue::Iterator i(*prefs_); !i.IsAtEnd(); i.Advance()) {
248 const std::string& extension_id = i.key();
Peter Kasting42e82e92021-09-15 16:39:17249 const base::DictionaryValue* extension_dict = nullptr;
[email protected]ab22ba42011-01-14 16:36:38250
Yuta Hijikata1290fee22020-11-25 09:46:28251#if BUILDFLAG(IS_CHROMEOS_ASH)
Wei Lee799de532021-11-10 03:33:36252 if (extension_id == kCameraAppId) {
Swapnil5eca0412021-02-12 08:32:54253 unsupported_extensions.insert(extension_id);
254 install_stage_tracker->ReportFailure(
255 extension_id,
256 InstallStageTracker::FailureReason::REPLACED_BY_SYSTEM_APP);
257 continue;
258 }
259
Ahmed Fakhry9ef29e042017-09-01 16:32:00260 if (ShouldUninstallExtensionReplacedByArcApp(extension_id)) {
261 VLOG(1) << "Extension with key: " << extension_id << " was replaced "
262 << "by a default ARC app, and will be uninstalled.";
263 unsupported_extensions.emplace(extension_id);
Oleg Davydovdec175a2020-05-25 16:44:29264 install_stage_tracker->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51265 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29266 InstallStageTracker::FailureReason::REPLACED_BY_ARC_APP);
Ahmed Fakhry9ef29e042017-09-01 16:32:00267 continue;
268 }
Yuta Hijikata1290fee22020-11-25 09:46:28269#endif // BUILDFLAG(IS_CHROMEOS_ASH)
Ahmed Fakhry9ef29e042017-09-01 16:32:00270
[email protected]fdd28372014-08-21 02:27:26271 if (!crx_file::id_util::IdIsValid(extension_id)) {
[email protected]ab22ba42011-01-14 16:36:38272 LOG(WARNING) << "Malformed extension dictionary: key "
273 << extension_id.c_str() << " is not a valid id.";
Oleg Davydovdec175a2020-05-25 16:44:29274 install_stage_tracker->ReportFailure(
275 extension_id, InstallStageTracker::FailureReason::INVALID_ID);
[email protected]8e4560b62011-01-14 10:09:14276 continue;
[email protected]ab22ba42011-01-14 16:36:38277 }
278
Peter Kasting42e82e92021-09-15 16:39:17279 if (!i.value().GetAsDictionary(&extension_dict)) {
[email protected]ab22ba42011-01-14 16:36:38280 LOG(WARNING) << "Malformed extension dictionary: key "
281 << extension_id.c_str()
282 << " has a value that is not a dictionary.";
Oleg Davydovdec175a2020-05-25 16:44:29283 install_stage_tracker->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51284 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29285 InstallStageTracker::FailureReason::MALFORMED_EXTENSION_DICT);
[email protected]ab22ba42011-01-14 16:36:38286 continue;
287 }
[email protected]8e4560b62011-01-14 10:09:14288
Anina Koehler100794e22021-09-08 13:09:52289 std::string external_crx;
290 const base::Value* external_version_value = nullptr;
[email protected]8e4560b62011-01-14 10:09:14291 std::string external_version;
Anina Koehler100794e22021-09-08 13:09:52292 std::string external_update_url;
293
Peter Kasting42e82e92021-09-15 16:39:17294 bool has_external_crx =
295 extension_dict->GetString(kExternalCrx, &external_crx);
Anina Koehler100794e22021-09-08 13:09:52296
[email protected]0d461c52012-07-03 19:29:41297 bool has_external_version = false;
Peter Kasting42e82e92021-09-15 16:39:17298 if (extension_dict->Get(kExternalVersion, &external_version_value)) {
jdoerrie1f536b22017-10-23 17:15:11299 if (external_version_value->is_string()) {
Alex Rudenkoa4d75ab52021-07-09 15:39:44300 external_version = external_version_value->GetString();
[email protected]0d461c52012-07-03 19:29:41301 has_external_version = true;
302 } else {
Oleg Davydovdec175a2020-05-25 16:44:29303 install_stage_tracker->ReportFailure(
304 extension_id, InstallStageTracker::FailureReason::
Oleg Davydov66246bd92019-09-26 16:31:51305 MALFORMED_EXTENSION_DICT_VERSION);
[email protected]0d461c52012-07-03 19:29:41306 LOG(WARNING) << "Malformed extension dictionary for extension: "
307 << extension_id.c_str() << ". " << kExternalVersion
308 << " value must be a string.";
309 continue;
310 }
311 }
312
Peter Kasting42e82e92021-09-15 16:39:17313 bool has_external_update_url =
314 extension_dict->GetString(kExternalUpdateUrl, &external_update_url);
[email protected]8e4560b62011-01-14 10:09:14315 if (has_external_crx != has_external_version) {
Oleg Davydovdec175a2020-05-25 16:44:29316 install_stage_tracker->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51317 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29318 InstallStageTracker::FailureReason::MALFORMED_EXTENSION_DICT);
[email protected]8e4560b62011-01-14 10:09:14319 LOG(WARNING) << "Malformed extension dictionary for extension: "
320 << extension_id.c_str() << ". " << kExternalCrx
321 << " and " << kExternalVersion << " must be used together.";
322 continue;
323 }
324
325 if (has_external_crx == has_external_update_url) {
Oleg Davydovdec175a2020-05-25 16:44:29326 install_stage_tracker->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51327 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29328 InstallStageTracker::FailureReason::MALFORMED_EXTENSION_DICT);
[email protected]8e4560b62011-01-14 10:09:14329 LOG(WARNING) << "Malformed extension dictionary for extension: "
330 << extension_id.c_str() << ". Exactly one of the "
Anina Koehler100794e22021-09-08 13:09:52331 << "followng keys should be used: " << kExternalCrx
332 << ", " << kExternalUpdateUrl << ".";
[email protected]8e4560b62011-01-14 10:09:14333 continue;
334 }
335
[email protected]9d32ded072011-10-11 16:31:05336 // Check that extension supports current browser locale.
Anina Koehler100794e22021-09-08 13:09:52337 const base::ListValue* supported_locales = nullptr;
Peter Kasting42e82e92021-09-15 16:39:17338 if (extension_dict->GetList(kSupportedLocales, &supported_locales)) {
[email protected]9d32ded072011-10-11 16:31:05339 std::vector<std::string> browser_locales;
340 l10n_util::GetParentLocales(g_browser_process->GetApplicationLocale(),
341 &browser_locales);
342
[email protected]9d32ded072011-10-11 16:31:05343 bool locale_supported = false;
Maks Orlovichab5bbab2021-11-26 16:30:35344 for (const base::Value& locale : supported_locales->GetList()) {
345 const std::string* current_locale = locale.GetIfString();
346 if (current_locale && l10n_util::IsValidLocaleSyntax(*current_locale)) {
347 std::string normalized_locale =
348 l10n_util::NormalizeLocale(*current_locale);
349 if (base::Contains(browser_locales, normalized_locale)) {
[email protected]9d32ded072011-10-11 16:31:05350 locale_supported = true;
351 break;
352 }
353 } else {
Maks Orlovichab5bbab2021-11-26 16:30:35354 LOG(WARNING) << "Unrecognized locale '"
355 << (current_locale ? *current_locale : "(Not a string)")
[email protected]9d32ded072011-10-11 16:31:05356 << "' found as supported locale for extension: "
357 << extension_id;
358 }
359 }
360
361 if (!locale_supported) {
362 unsupported_extensions.insert(extension_id);
Oleg Davydovdec175a2020-05-25 16:44:29363 install_stage_tracker->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51364 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29365 InstallStageTracker::FailureReason::LOCALE_NOT_SUPPORTED);
[email protected]19eac6d2013-05-30 06:51:03366 VLOG(1) << "Skip installing (or uninstall) external extension: "
367 << extension_id << " because the extension doesn't support "
368 << "the browser locale.";
[email protected]9d32ded072011-10-11 16:31:05369 continue;
370 }
371 }
372
[email protected]f121003b2012-05-04 21:57:47373 int creation_flags = creation_flags_;
Nan Linc3aff1b92021-11-08 21:46:38374 absl::optional<bool> is_bookmark_app =
375 extension_dict->FindBoolKey(kIsBookmarkApp);
376 if (is_bookmark_app.value_or(false)) {
[email protected]f121003b2012-05-04 21:57:47377 creation_flags |= Extension::FROM_BOOKMARK;
378 }
Nan Linc3aff1b92021-11-08 21:46:38379 absl::optional<bool> is_from_webstore =
380 extension_dict->FindBoolKey(kIsFromWebstore);
381 if (is_from_webstore.value_or(false)) {
[email protected]7425d7df2012-11-28 14:35:42382 creation_flags |= Extension::FROM_WEBSTORE;
383 }
Alan Cutterb81d0e02020-08-05 09:10:34384
385 // If the extension is in a web app migration treat it as "keep_if_present"
386 // so it can get uninstalled by WebAppUiManager::UninstallAndReplace() once
387 // the replacement web app has installed and migrated over user preferences.
388 // TODO(crbug.com/1099150): Remove this field after migration is complete.
389 const std::string* web_app_migration_flag =
Peter Kasting42e82e92021-09-15 16:39:17390 extension_dict->FindStringPath(kWebAppMigrationFlag);
Alan Cutterb81d0e02020-08-05 09:10:34391 bool is_migrating_to_web_app =
392 web_app_migration_flag &&
Alan Cutter52914e72021-05-05 09:35:48393 web_app::IsPreinstalledAppInstallFeatureEnabled(*web_app_migration_flag,
394 *profile_);
Alan Cutterb81d0e02020-08-05 09:10:34395 bool keep_if_present =
Peter Kasting42e82e92021-09-15 16:39:17396 extension_dict->FindBoolPath(kKeepIfPresent).value_or(false);
Alan Cutterb81d0e02020-08-05 09:10:34397 if (keep_if_present || is_migrating_to_web_app) {
David Bertoni58c113a2019-08-02 19:53:26398 ExtensionRegistry* extension_registry = ExtensionRegistry::Get(profile_);
399 const Extension* extension =
David Bertonia0b34722019-09-30 20:51:26400 extension_registry ? extension_registry->GetExtensionById(
401 extension_id, ExtensionRegistry::EVERYTHING)
402 : nullptr;
[email protected]19eac6d2013-05-30 06:51:03403 if (!extension) {
dpolukhin2c6ef2932015-05-12 16:06:13404 unsupported_extensions.insert(extension_id);
Oleg Davydovdec175a2020-05-25 16:44:29405 install_stage_tracker->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51406 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29407 InstallStageTracker::FailureReason::NOT_PERFORMING_NEW_INSTALL);
[email protected]19eac6d2013-05-30 06:51:03408 VLOG(1) << "Skip installing (or uninstall) external extension: "
409 << extension_id << " because the extension should be kept "
410 << "only if it is already installed.";
411 continue;
412 }
413 }
Alan Cutterb81d0e02020-08-05 09:10:34414
Nan Linc3aff1b92021-11-08 21:46:38415 absl::optional<bool> was_installed_by_oem =
416 extension_dict->FindBoolKey(kWasInstalledByOem);
417 if (was_installed_by_oem.value_or(false)) {
dpolukhind0be494a2015-05-28 09:43:17418 creation_flags |= Extension::WAS_INSTALLED_BY_OEM;
419 }
Nan Linc3aff1b92021-11-08 21:46:38420 absl::optional<bool> may_be_untrusted =
421 extension_dict->FindBoolKey(kMayBeUntrusted);
422 if (may_be_untrusted.value_or(false)) {
[email protected]2b6a5802014-08-16 07:58:08423 creation_flags |= Extension::MAY_BE_UNTRUSTED;
424 }
[email protected]f121003b2012-05-04 21:57:47425
Peter Kasting42e82e92021-09-15 16:39:17426 if (!HandleMinProfileVersion(extension_dict, extension_id,
dpolukhin1687ef32015-06-22 11:12:37427 &unsupported_extensions)) {
dpolukhin2c6ef2932015-05-12 16:06:13428 continue;
dpolukhin1687ef32015-06-22 11:12:37429 }
430
Peter Kasting42e82e92021-09-15 16:39:17431 if (!HandleDoNotInstallForEnterprise(extension_dict, extension_id,
dpolukhin1687ef32015-06-22 11:12:37432 &unsupported_extensions)) {
433 continue;
434 }
dpolukhin2c6ef2932015-05-12 16:06:13435
Anina Koehler100794e22021-09-08 13:09:52436 std::string install_parameter;
Peter Kasting42e82e92021-09-15 16:39:17437 extension_dict->GetString(kInstallParam, &install_parameter);
[email protected]d8fd0fd2014-03-24 13:16:06438
[email protected]8e4560b62011-01-14 10:09:14439 if (has_external_crx) {
Gyuyoung Kim2e954c42021-03-19 14:06:29440 if (crx_location_ == ManifestLocation::kInvalidLocation) {
Oleg Davydovdec175a2020-05-25 16:44:29441 install_stage_tracker->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51442 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29443 InstallStageTracker::FailureReason::NOT_SUPPORTED_EXTENSION_DICT);
[email protected]8e4560b62011-01-14 10:09:14444 LOG(WARNING) << "This provider does not support installing external "
445 << "extensions from crx files.";
446 continue;
447 }
Peter Kasting141279b2021-02-09 22:34:20448
Anina Koehler100794e22021-09-08 13:09:52449 base::FilePath path = base::FilePath::FromUTF8Unsafe(external_crx);
Peter Kasting141279b2021-02-09 22:34:20450 if (path.value().find(base::FilePath::kParentDirectory) !=
[email protected]8e4560b62011-01-14 10:09:14451 base::StringPiece::npos) {
Oleg Davydovdec175a2020-05-25 16:44:29452 install_stage_tracker->ReportFailure(
453 extension_id, InstallStageTracker::FailureReason::
Oleg Davydov66246bd92019-09-26 16:31:51454 MALFORMED_EXTENSION_DICT_FILE_PATH);
[email protected]8e4560b62011-01-14 10:09:14455 LOG(WARNING) << "Path traversal not allowed in path: "
Anina Koehler100794e22021-09-08 13:09:52456 << external_crx.c_str();
[email protected]8e4560b62011-01-14 10:09:14457 continue;
458 }
459
[email protected]f0841cd2011-01-19 15:07:24460 // If the path is relative, and the provider has a base path,
461 // build the absolute path to the crx file.
Peter Kasting141279b2021-02-09 22:34:20462
[email protected]8e4560b62011-01-14 10:09:14463 if (!path.IsAbsolute()) {
[email protected]650b2d52013-02-10 03:41:45464 base::FilePath base_path = loader_->GetBaseCrxFilePath();
[email protected]f0841cd2011-01-19 15:07:24465 if (base_path.empty()) {
Oleg Davydovdec175a2020-05-25 16:44:29466 install_stage_tracker->ReportFailure(
467 extension_id, InstallStageTracker::FailureReason::
Oleg Davydov66246bd92019-09-26 16:31:51468 MALFORMED_EXTENSION_DICT_FILE_PATH);
Anina Koehler100794e22021-09-08 13:09:52469 LOG(WARNING) << "File path " << external_crx.c_str()
[email protected]f0841cd2011-01-19 15:07:24470 << " is relative. An absolute path is required.";
471 continue;
472 }
Peter Kasting141279b2021-02-09 22:34:20473 path = base_path.Append(path);
[email protected]8e4560b62011-01-14 10:09:14474 }
475
Devlin Cronind4c2a8f32017-09-29 17:08:30476 base::Version version(external_version);
477 if (!version.IsValid()) {
Oleg Davydovdec175a2020-05-25 16:44:29478 install_stage_tracker->ReportFailure(
479 extension_id, InstallStageTracker::FailureReason::
Oleg Davydov66246bd92019-09-26 16:31:51480 MALFORMED_EXTENSION_DICT_VERSION);
[email protected]8e4560b62011-01-14 10:09:14481 LOG(WARNING) << "Malformed extension dictionary for extension: "
482 << extension_id.c_str() << ". Invalid version string \""
483 << external_version << "\".";
484 continue;
485 }
Devlin Cronin19f70b6a2017-10-01 04:14:05486 external_file_extensions->emplace_back(
487 extension_id, version, path, crx_location_, creation_flags,
488 auto_acknowledge_, install_immediately_);
[email protected]8a839a02013-03-07 05:23:33489 } else { // if (has_external_update_url)
[email protected]8e4560b62011-01-14 10:09:14490 CHECK(has_external_update_url); // Checking of keys above ensures this.
Gyuyoung Kim2e954c42021-03-19 14:06:29491 if (download_location_ == ManifestLocation::kInvalidLocation) {
Oleg Davydovdec175a2020-05-25 16:44:29492 install_stage_tracker->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51493 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29494 InstallStageTracker::FailureReason::NOT_SUPPORTED_EXTENSION_DICT);
[email protected]8e4560b62011-01-14 10:09:14495 LOG(WARNING) << "This provider does not support installing external "
496 << "extensions from update URLs.";
497 continue;
498 }
Anina Koehler100794e22021-09-08 13:09:52499 GURL update_url(external_update_url);
Devlin Cronind4c2a8f32017-09-29 17:08:30500 if (!update_url.is_valid()) {
Oleg Davydovdec175a2020-05-25 16:44:29501 install_stage_tracker->ReportFailure(
502 extension_id, InstallStageTracker::FailureReason::
Oleg Davydov66246bd92019-09-26 16:31:51503 MALFORMED_EXTENSION_DICT_UPDATE_URL);
[email protected]8e4560b62011-01-14 10:09:14504 LOG(WARNING) << "Malformed extension dictionary for extension: "
[email protected]ab22ba42011-01-14 16:36:38505 << extension_id.c_str() << ". Key " << kExternalUpdateUrl
506 << " has value \"" << external_update_url
507 << "\", which is not a valid URL.";
[email protected]8e4560b62011-01-14 10:09:14508 continue;
509 }
Devlin Cronin19f70b6a2017-10-01 04:14:05510 external_update_url_extensions->emplace_back(
Anina Koehler100794e22021-09-08 13:09:52511 extension_id, install_parameter, std::move(update_url),
Devlin Cronin19f70b6a2017-10-01 04:14:05512 download_location_, creation_flags, auto_acknowledge_);
[email protected]8e4560b62011-01-14 10:09:14513 }
514 }
515
jdoerrie13cd648c82018-10-02 21:21:02516 for (auto it = unsupported_extensions.begin();
[email protected]9d32ded072011-10-11 16:31:05517 it != unsupported_extensions.end(); ++it) {
518 // Remove extension for the list of know external extensions. The extension
519 // will be uninstalled later because provider doesn't provide it anymore.
Song Fangzhencdbb7062021-07-07 11:13:53520 prefs_->RemoveKey(*it);
[email protected]9d32ded072011-10-11 16:31:05521 }
[email protected]8e4560b62011-01-14 10:09:14522}
523
[email protected]5df038b2012-07-16 19:03:27524void ExternalProviderImpl::ServiceShutdown() {
Bartek Nowierski3253b672020-06-01 20:37:12525 service_ = nullptr;
[email protected]8e4560b62011-01-14 10:09:14526}
527
[email protected]5df038b2012-07-16 19:03:27528bool ExternalProviderImpl::IsReady() const {
[email protected]8e4560b62011-01-14 10:09:14529 return ready_;
530}
531
[email protected]5df038b2012-07-16 19:03:27532bool ExternalProviderImpl::HasExtension(
[email protected]8e4560b62011-01-14 10:09:14533 const std::string& id) const {
Istiaque Ahmedf6e72622017-09-08 23:14:17534 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]8e4560b62011-01-14 10:09:14535 CHECK(prefs_.get());
536 CHECK(ready_);
Anina Koehler100794e22021-09-08 13:09:52537 return prefs_->HasKey(id);
[email protected]8e4560b62011-01-14 10:09:14538}
539
[email protected]5df038b2012-07-16 19:03:27540bool ExternalProviderImpl::GetExtensionDetails(
dchengc963c7142016-04-08 03:55:22541 const std::string& id,
Gyuyoung Kim2e954c42021-03-19 14:06:29542 ManifestLocation* location,
pwnallcbd73192016-08-22 18:59:17543 std::unique_ptr<base::Version>* version) const {
Istiaque Ahmedf6e72622017-09-08 23:14:17544 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]8e4560b62011-01-14 10:09:14545 CHECK(prefs_.get());
546 CHECK(ready_);
Anina Koehler100794e22021-09-08 13:09:52547 base::DictionaryValue* extension = nullptr;
548 if (!prefs_->GetDictionary(id, &extension))
[email protected]8e4560b62011-01-14 10:09:14549 return false;
550
Gyuyoung Kim2e954c42021-03-19 14:06:29551 ManifestLocation loc = ManifestLocation::kInvalidLocation;
Anina Koehler100794e22021-09-08 13:09:52552 if (extension->HasKey(kExternalUpdateUrl)) {
[email protected]8e4560b62011-01-14 10:09:14553 loc = download_location_;
554
Anina Koehler100794e22021-09-08 13:09:52555 } else if (extension->HasKey(kExternalCrx)) {
[email protected]8e4560b62011-01-14 10:09:14556 loc = crx_location_;
557
Anina Koehler100794e22021-09-08 13:09:52558 std::string external_version;
559 if (!extension->GetString(kExternalVersion, &external_version))
[email protected]8e4560b62011-01-14 10:09:14560 return false;
561
562 if (version)
Anina Koehler100794e22021-09-08 13:09:52563 *version = std::make_unique<base::Version>(external_version);
[email protected]8e4560b62011-01-14 10:09:14564
565 } else {
566 NOTREACHED(); // Chrome should not allow prefs to get into this state.
567 return false;
568 }
569
570 if (location)
571 *location = loc;
572
573 return true;
574}
575
dpolukhin2c6ef2932015-05-12 16:06:13576bool ExternalProviderImpl::HandleMinProfileVersion(
Anina Koehler100794e22021-09-08 13:09:52577 const base::DictionaryValue* extension,
dpolukhin2c6ef2932015-05-12 16:06:13578 const std::string& extension_id,
579 std::set<std::string>* unsupported_extensions) {
Anina Koehler100794e22021-09-08 13:09:52580 std::string min_profile_created_by_version;
581 if (extension->GetString(kMinProfileCreatedByVersion,
582 &min_profile_created_by_version)) {
pwnallcbd73192016-08-22 18:59:17583 base::Version profile_version(
dpolukhin2c6ef2932015-05-12 16:06:13584 profile_->GetPrefs()->GetString(prefs::kProfileCreatedByVersion));
Anina Koehler100794e22021-09-08 13:09:52585 base::Version min_version(min_profile_created_by_version);
dpolukhin2c6ef2932015-05-12 16:06:13586 if (min_version.IsValid() && profile_version.CompareTo(min_version) < 0) {
587 unsupported_extensions->insert(extension_id);
Oleg Davydovdec175a2020-05-25 16:44:29588 InstallStageTracker::Get(profile_)->ReportFailure(
589 extension_id, InstallStageTracker::FailureReason::TOO_OLD_PROFILE);
dpolukhin2c6ef2932015-05-12 16:06:13590 VLOG(1) << "Skip installing (or uninstall) external extension: "
591 << extension_id
592 << " profile.created_by_version: " << profile_version.GetString()
593 << " min_profile_created_by_version: "
594 << min_profile_created_by_version;
595 return false;
596 }
597 }
598 return true;
599}
600
dpolukhin1687ef32015-06-22 11:12:37601bool ExternalProviderImpl::HandleDoNotInstallForEnterprise(
Anina Koehler100794e22021-09-08 13:09:52602 const base::DictionaryValue* extension,
dpolukhin1687ef32015-06-22 11:12:37603 const std::string& extension_id,
604 std::set<std::string>* unsupported_extensions) {
Nan Linc3aff1b92021-11-08 21:46:38605 absl::optional<bool> do_not_install_for_enterprise =
606 extension->FindBoolKey(kDoNotInstallForEnterprise);
607 if (do_not_install_for_enterprise.value_or(false)) {
dpolukhin1687ef32015-06-22 11:12:37608 const policy::ProfilePolicyConnector* const connector =
Xi Hanfe39afc62019-04-29 14:50:14609 profile_->GetProfilePolicyConnector();
dpolukhin1687ef32015-06-22 11:12:37610 if (connector->IsManaged()) {
611 unsupported_extensions->insert(extension_id);
Oleg Davydovdec175a2020-05-25 16:44:29612 InstallStageTracker::Get(profile_)->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51613 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29614 InstallStageTracker::FailureReason::DO_NOT_INSTALL_FOR_ENTERPRISE);
dpolukhin1687ef32015-06-22 11:12:37615 VLOG(1) << "Skip installing (or uninstall) external extension "
616 << extension_id << " restricted for managed user";
617 return false;
618 }
619 }
620 return true;
621}
622
[email protected]8e4560b62011-01-14 10:09:14623// static
[email protected]5df038b2012-07-16 19:03:27624void ExternalProviderImpl::CreateExternalProviders(
[email protected]8e4560b62011-01-14 10:09:14625 VisitorInterface* service,
626 Profile* profile,
627 ProviderCollection* provider_list) {
rkaplowdd66a1342015-03-05 00:31:49628 TRACE_EVENT0("browser,startup",
629 "ExternalProviderImpl::CreateExternalProviders");
[email protected]af984882013-10-21 21:08:51630 scoped_refptr<ExternalLoader> external_loader;
binjincccacef2014-10-13 19:00:20631 scoped_refptr<ExternalLoader> external_recommended_loader;
Gyuyoung Kim2e954c42021-03-19 14:06:29632 ManifestLocation crx_location = ManifestLocation::kInvalidLocation;
achuithd3da4f02017-03-23 20:05:29633
Yuta Hijikata1290fee22020-11-25 09:46:28634#if BUILDFLAG(IS_CHROMEOS_ASH)
achuithd3da4f02017-03-23 20:05:29635 if (chromeos::ProfileHelper::IsSigninProfile(profile)) {
Maksim Ivanov12801d0d2020-02-18 10:23:41636 // Download extensions/apps installed by policy in the login profile.
637 // Extensions (not apps) installed through this path will have type
638 // |TYPE_LOGIN_SCREEN_EXTENSION| with limited API capabilities.
Gyuyoung Kim2e954c42021-03-19 14:06:29639 crx_location = ManifestLocation::kExternalPolicyDownload;
Maksim Ivanov8738d332020-01-07 22:19:01640 external_loader =
641 base::MakeRefCounted<chromeos::SigninScreenExtensionsExternalLoader>(
Oleg Davydovba7dd392021-03-18 09:47:44642 profile);
Jinho Bangb5216cec2018-01-17 19:43:11643 auto signin_profile_provider = std::make_unique<ExternalProviderImpl>(
achuithd3da4f02017-03-23 20:05:29644 service, external_loader, profile, crx_location,
Gyuyoung Kim2e954c42021-03-19 14:06:29645 ManifestLocation::kExternalPolicyDownload, Extension::FOR_LOGIN_SCREEN);
Maksim Ivanov8738d332020-01-07 22:19:01646 signin_profile_provider->set_auto_acknowledge(true);
Toni Barzic87026682018-01-08 23:21:04647 signin_profile_provider->set_allow_updates(true);
648 provider_list->push_back(std::move(signin_profile_provider));
achuithd3da4f02017-03-23 20:05:29649 return;
650 }
651
Yeunjoo Choi7227dba2021-08-04 06:35:47652 policy::BrowserPolicyConnectorAsh* connector =
653 g_browser_process->platform_part()->browser_policy_connector_ash();
[email protected]2d4cfed2014-01-14 13:59:57654 bool is_chrome_os_public_session = false;
[email protected]2fda9972014-07-23 14:51:59655 const user_manager::User* user =
[email protected]052e3ac2014-06-30 14:22:47656 chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
[email protected]2d4cfed2014-01-14 13:59:57657 policy::DeviceLocalAccount::Type account_type;
Roland Bock4ce23a922021-06-11 13:23:11658 if (user && connector->IsDeviceEnterpriseManaged() &&
alemate909aa58a2016-11-03 22:49:07659 policy::IsDeviceLocalAccountUser(user->GetAccountId().GetUserEmail(),
660 &account_type)) {
[email protected]2d4cfed2014-01-14 13:59:57661 if (account_type == policy::DeviceLocalAccount::TYPE_PUBLIC_SESSION)
662 is_chrome_os_public_session = true;
[email protected]af984882013-10-21 21:08:51663 policy::DeviceLocalAccountPolicyBroker* broker =
[email protected]97275822014-01-21 19:30:36664 connector->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
alemate909aa58a2016-11-03 22:49:07665 user->GetAccountId().GetUserEmail());
[email protected]af984882013-10-21 21:08:51666 if (broker) {
667 external_loader = broker->extension_loader();
Gyuyoung Kim2e954c42021-03-19 14:06:29668 crx_location = ManifestLocation::kExternalPolicy;
[email protected]af984882013-10-21 21:08:51669 } else {
670 NOTREACHED();
671 }
672 } else {
Matthew Dentonef83a622019-08-30 02:07:00673 external_loader = base::MakeRefCounted<ExternalPolicyLoader>(
Oleg Davydov52db8742019-08-20 09:14:40674 profile, ExtensionManagementFactory::GetForBrowserContext(profile),
binjincccacef2014-10-13 19:00:20675 ExternalPolicyLoader::FORCED);
Matthew Dentonef83a622019-08-30 02:07:00676 external_recommended_loader = base::MakeRefCounted<ExternalPolicyLoader>(
Oleg Davydov52db8742019-08-20 09:14:40677 profile, ExtensionManagementFactory::GetForBrowserContext(profile),
binjincccacef2014-10-13 19:00:20678 ExternalPolicyLoader::RECOMMENDED);
[email protected]af984882013-10-21 21:08:51679 }
680#else
Matthew Dentonef83a622019-08-30 02:07:00681 external_loader = base::MakeRefCounted<ExternalPolicyLoader>(
Oleg Davydov52db8742019-08-20 09:14:40682 profile, ExtensionManagementFactory::GetForBrowserContext(profile),
binjincccacef2014-10-13 19:00:20683 ExternalPolicyLoader::FORCED);
Matthew Dentonef83a622019-08-30 02:07:00684 external_recommended_loader = base::MakeRefCounted<ExternalPolicyLoader>(
Oleg Davydov52db8742019-08-20 09:14:40685 profile, ExtensionManagementFactory::GetForBrowserContext(profile),
binjincccacef2014-10-13 19:00:20686 ExternalPolicyLoader::RECOMMENDED);
[email protected]af984882013-10-21 21:08:51687#endif
688
[email protected]b9f4fe52012-11-09 21:40:59689 // Policies are mandatory so they can't be skipped with command line flag.
dchengc7047942014-08-26 05:05:31690 if (external_loader.get()) {
Jinho Bangb5216cec2018-01-17 19:43:11691 auto policy_provider = std::make_unique<ExternalProviderImpl>(
lazyboyf33109d2016-08-31 00:37:08692 service, external_loader, profile, crx_location,
Gyuyoung Kim2e954c42021-03-19 14:06:29693 ManifestLocation::kExternalPolicyDownload, Extension::NO_FLAGS);
Toni Barzic87026682018-01-08 23:21:04694 policy_provider->set_allow_updates(true);
695 provider_list->push_back(std::move(policy_provider));
[email protected]af984882013-10-21 21:08:51696 }
[email protected]b9f4fe52012-11-09 21:40:59697
Anqing Zhaof0e96fb42020-12-11 23:21:21698 // Load the KioskAppExternalProvider when running in the Chrome App kiosk
699 // mode.
[email protected]ee3da0552014-07-16 05:27:31700 if (chrome::IsRunningInForcedAppMode()) {
Yuta Hijikata1290fee22020-11-25 09:46:28701#if BUILDFLAG(IS_CHROMEOS_ASH)
Anqing Zhaof0e96fb42020-12-11 23:21:21702 if (user && user->GetType() == user_manager::USER_TYPE_KIOSK_APP) {
703 // Kiosk primary app external provider.
704 // For enterprise managed kiosk apps, change the location to
705 // "force-installed by policy".
Yeunjoo Choi7227dba2021-08-04 06:35:47706 policy::BrowserPolicyConnectorAsh* const connector =
707 g_browser_process->platform_part()->browser_policy_connector_ash();
Gyuyoung Kim2e954c42021-03-19 14:06:29708 ManifestLocation location = ManifestLocation::kExternalPref;
Roland Bock4ce23a922021-06-11 13:23:11709 if (connector && connector->IsDeviceEnterpriseManaged())
Gyuyoung Kim2e954c42021-03-19 14:06:29710 location = ManifestLocation::kExternalPolicy;
pbond43ddd4f2015-09-08 16:39:19711
Anqing Zhaof0e96fb42020-12-11 23:21:21712 auto kiosk_app_provider = std::make_unique<ExternalProviderImpl>(
713 service,
Henrique Ferreiro26ed25a2021-02-01 21:59:29714 base::MakeRefCounted<ash::KioskAppExternalLoader>(
715 ash::KioskAppExternalLoader::AppClass::kPrimary),
Gyuyoung Kim2e954c42021-03-19 14:06:29716 profile, location, ManifestLocation::kInvalidLocation,
717 Extension::NO_FLAGS);
Anqing Zhaof0e96fb42020-12-11 23:21:21718 kiosk_app_provider->set_auto_acknowledge(true);
719 kiosk_app_provider->set_install_immediately(true);
720 kiosk_app_provider->set_allow_updates(true);
721 provider_list->push_back(std::move(kiosk_app_provider));
jennyz26b7f432015-09-03 20:59:27722
Anqing Zhaof0e96fb42020-12-11 23:21:21723 // Kiosk secondary app external provider.
724 auto secondary_kiosk_app_provider =
725 std::make_unique<ExternalProviderImpl>(
726 service,
Henrique Ferreiro26ed25a2021-02-01 21:59:29727 base::MakeRefCounted<ash::KioskAppExternalLoader>(
728 ash::KioskAppExternalLoader::AppClass::kSecondary),
Gyuyoung Kim2e954c42021-03-19 14:06:29729 profile, ManifestLocation::kExternalPref,
730 ManifestLocation::kExternalPrefDownload, Extension::NO_FLAGS);
Anqing Zhaof0e96fb42020-12-11 23:21:21731 secondary_kiosk_app_provider->set_auto_acknowledge(true);
732 secondary_kiosk_app_provider->set_install_immediately(true);
733 secondary_kiosk_app_provider->set_allow_updates(true);
734 provider_list->push_back(std::move(secondary_kiosk_app_provider));
735 }
[email protected]ee3da0552014-07-16 05:27:31736#endif
737 return;
738 }
739
binjincccacef2014-10-13 19:00:20740 // Extensions provided by recommended policies.
741 if (external_recommended_loader.get()) {
Nicolas Ouellet-Payeur93b74ca1d2020-12-09 23:33:12742 auto recommended_provider = std::make_unique<ExternalProviderImpl>(
lazyboyf33109d2016-08-31 00:37:08743 service, external_recommended_loader, profile, crx_location,
Gyuyoung Kim2e954c42021-03-19 14:06:29744 ManifestLocation::kExternalPrefDownload, Extension::NO_FLAGS);
Nicolas Ouellet-Payeur93b74ca1d2020-12-09 23:33:12745 recommended_provider->set_auto_acknowledge(true);
746 provider_list->push_back(std::move(recommended_provider));
binjincccacef2014-10-13 19:00:20747 }
748
Daniel Murphy3657906d2021-04-13 20:33:12749 // In tests don't install pre-installed apps.
[email protected]b9f4fe52012-11-09 21:40:59750 // It would only slowdown tests and make them flaky.
avi3ef9ec9e2014-12-22 22:50:17751 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
Daniel Murphy3657906d2021-04-13 20:33:12752 ::switches::kDisablePreinstalledApps)) {
[email protected]b9f4fe52012-11-09 21:40:59753 return;
[email protected]98820ac72019-01-24 19:47:16754 }
[email protected]73e4c362011-09-22 14:47:18755
Peter Kasting9c68b0f2021-07-27 09:47:40756#if !defined(OS_WIN)
[email protected]73e4c362011-09-22 14:47:18757 // On Mac OS, items in /Library/... should be written by the superuser.
758 // Check that all components of the path are writable by root only.
[email protected]5df038b2012-07-16 19:03:27759 ExternalPrefLoader::Options check_admin_permissions_on_mac;
Avi Drissman2e458df2020-07-29 16:24:31760#if defined(OS_MAC)
[email protected]0edc55412011-11-07 16:47:33761 check_admin_permissions_on_mac =
Peter Kasting9c68b0f2021-07-27 09:47:40762 ExternalPrefLoader::ENSURE_PATH_CONTROLLED_BY_ADMIN;
[email protected]73e4c362011-09-22 14:47:18763#else
[email protected]5df038b2012-07-16 19:03:27764 check_admin_permissions_on_mac = ExternalPrefLoader::NONE;
[email protected]73e4c362011-09-22 14:47:18765#endif
[email protected]d6f7b102012-05-04 13:59:05766 int bundled_extension_creation_flags = Extension::NO_FLAGS;
Peter Kastingbe940e92014-11-20 23:14:08767#endif
Yuta Hijikata1290fee22020-11-25 09:46:28768#if BUILDFLAG(IS_CHROMEOS_ASH)
[email protected]5861bcd2012-10-16 21:40:19769 bundled_extension_creation_flags = Extension::FROM_WEBSTORE |
770 Extension::WAS_INSTALLED_BY_DEFAULT;
[email protected]a4567732013-07-25 21:01:20771
rkcb526cd6b2014-12-18 16:54:37772 if (!is_chrome_os_public_session) {
[email protected]98820ac72019-01-24 19:47:16773 int pref_load_flags =
ginkagef66fae522015-03-03 16:38:16774 profile->IsNewProfile()
775 ? ExternalPrefLoader::DELAY_LOAD_UNTIL_PRIORITY_SYNC
776 : ExternalPrefLoader::NONE;
[email protected]98820ac72019-01-24 19:47:16777 pref_load_flags |= ExternalPrefLoader::USE_USER_TYPE_PROFILE_FILTER;
778 provider_list->push_back(std::make_unique<ExternalProviderImpl>(
779 service,
Matthew Dentonef83a622019-08-30 02:07:00780 base::MakeRefCounted<ExternalPrefLoader>(
781 chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS, pref_load_flags,
782 profile),
Gyuyoung Kim2e954c42021-03-19 14:06:29783 profile, ManifestLocation::kExternalPref,
784 ManifestLocation::kExternalPrefDownload,
[email protected]98820ac72019-01-24 19:47:16785 bundled_extension_creation_flags));
[email protected]d0b28892014-03-05 18:56:31786
Daniel Murphy3657906d2021-04-13 20:33:12787 // OEM pre-installed apps.
[email protected]acc3c7c22014-03-19 06:23:39788 int oem_extension_creation_flags =
789 bundled_extension_creation_flags | Extension::WAS_INSTALLED_BY_OEM;
Yeunjoo Choicf61fba2021-04-23 02:43:09790 ash::ServicesCustomizationDocument* customization =
791 ash::ServicesCustomizationDocument::GetInstance();
Jinho Bangb5216cec2018-01-17 19:43:11792 provider_list->push_back(std::make_unique<ExternalProviderImpl>(
lazyboyf33109d2016-08-31 00:37:08793 service, customization->CreateExternalLoader(profile), profile,
Gyuyoung Kim2e954c42021-03-19 14:06:29794 ManifestLocation::kExternalPref,
795 ManifestLocation::kExternalPrefDownload, oem_extension_creation_flags));
[email protected]ebb489f2013-09-19 22:08:52796 }
Toni Barzicdff51562018-07-24 19:55:46797
798 // For Chrome OS demo sessions, add pre-installed demo extensions and apps.
Henrique Ferreirod71de902021-05-10 18:57:11799 if (ash::DemoExtensionsExternalLoader::SupportedForProfile(profile)) {
Wenzhao Zang463f1142018-09-05 22:50:50800 base::FilePath cache_dir;
801 CHECK(base::PathService::Get(chromeos::DIR_DEVICE_EXTENSION_LOCAL_CACHE,
802 &cache_dir));
Henrique Ferreirod71de902021-05-10 18:57:11803 auto loader =
804 base::MakeRefCounted<ash::DemoExtensionsExternalLoader>(cache_dir);
Toni Barzicdff51562018-07-24 19:55:46805 std::unique_ptr<ExternalProviderImpl> demo_apps_provider =
806 std::make_unique<ExternalProviderImpl>(
Gyuyoung Kim2e954c42021-03-19 14:06:29807 service, loader, profile, ManifestLocation::kExternalPolicy,
808 ManifestLocation::kExternalPolicyDownload, Extension::NO_FLAGS);
Toni Barzicdff51562018-07-24 19:55:46809 demo_apps_provider->set_auto_acknowledge(true);
810 demo_apps_provider->set_install_immediately(true);
Henrique Ferreirod71de902021-05-10 18:57:11811 ash::DemoSession::Get()->SetExtensionsExternalLoader(loader);
Toni Barzicdff51562018-07-24 19:55:46812 provider_list->push_back(std::move(demo_apps_provider));
813 }
[email protected]5bed2ec32013-08-29 22:55:46814#endif
Dominique Fauteux-Chapleauff3bb352019-10-16 14:32:34815 if (!profile->GetPrefs()->GetBoolean(pref_names::kBlockExternalExtensions)) {
Yuta Hijikata1290fee22020-11-25 09:46:28816// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
817// of lacros-chrome is complete.
818#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
Taiju Tsuikib1879b72018-09-21 06:22:47819 provider_list->push_back(std::make_unique<ExternalProviderImpl>(
820 service,
Matthew Dentonef83a622019-08-30 02:07:00821 base::MakeRefCounted<ExternalPrefLoader>(
Dominique Fauteux-Chapleauff3bb352019-10-16 14:32:34822 chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS,
823 ExternalPrefLoader::USE_USER_TYPE_PROFILE_FILTER, profile),
Gyuyoung Kim2e954c42021-03-19 14:06:29824 profile, ManifestLocation::kExternalPref,
825 ManifestLocation::kExternalPrefDownload,
Taiju Tsuikib1879b72018-09-21 06:22:47826 bundled_extension_creation_flags));
Dominique Fauteux-Chapleauff3bb352019-10-16 14:32:34827#endif
Dominique Fauteux-Chapleauff3bb352019-10-16 14:32:34828#if defined(OS_WIN)
Toby Huangf93f7002021-01-24 01:08:13829 auto registry_provider = std::make_unique<ExternalProviderImpl>(
830 service, new ExternalRegistryLoader, profile,
Gyuyoung Kim2e954c42021-03-19 14:06:29831 ManifestLocation::kExternalRegistry,
832 ManifestLocation::kExternalPrefDownload, Extension::NO_FLAGS);
Toby Huangf93f7002021-01-24 01:08:13833 registry_provider->set_allow_updates(true);
834 provider_list->push_back(std::move(registry_provider));
Dominique Fauteux-Chapleauff3bb352019-10-16 14:32:34835#else
Toby Huangf93f7002021-01-24 01:08:13836 provider_list->push_back(std::make_unique<ExternalProviderImpl>(
837 service,
838 base::MakeRefCounted<ExternalPrefLoader>(
839 chrome::DIR_EXTERNAL_EXTENSIONS, check_admin_permissions_on_mac,
840 nullptr),
Gyuyoung Kim2e954c42021-03-19 14:06:29841 profile, ManifestLocation::kExternalPref,
842 ManifestLocation::kExternalPrefDownload,
Toby Huangf93f7002021-01-24 01:08:13843 bundled_extension_creation_flags));
[email protected]5bed2ec32013-08-29 22:55:46844
Toby Huangf93f7002021-01-24 01:08:13845 // Define a per-user source of external extensions.
Sean McAllister4a991b972020-08-19 17:38:51846#if defined(OS_MAC) || ((defined(OS_LINUX) || defined(OS_CHROMEOS)) && \
847 BUILDFLAG(CHROMIUM_BRANDING))
Toby Huangf93f7002021-01-24 01:08:13848 provider_list->push_back(std::make_unique<ExternalProviderImpl>(
849 service,
Matthew Dentonef83a622019-08-30 02:07:00850 base::MakeRefCounted<ExternalPrefLoader>(
Toby Huangf93f7002021-01-24 01:08:13851 chrome::DIR_USER_EXTERNAL_EXTENSIONS, ExternalPrefLoader::NONE,
852 nullptr),
Gyuyoung Kim2e954c42021-03-19 14:06:29853 profile, ManifestLocation::kExternalPref,
854 ManifestLocation::kExternalPrefDownload, Extension::NO_FLAGS));
Toby Huangf93f7002021-01-24 01:08:13855#endif
856#endif
857 }
858
859#if !BUILDFLAG(IS_CHROMEOS_ASH)
Daniel Murphy3657906d2021-04-13 20:33:12860 // The pre-installed apps are installed as INTERNAL but use the external
Toby Huangf93f7002021-01-24 01:08:13861 // extension installer codeflow.
Daniel Murphy3657906d2021-04-13 20:33:12862 provider_list->push_back(std::make_unique<preinstalled_apps::Provider>(
Toby Huangf93f7002021-01-24 01:08:13863 profile, service,
864 base::MakeRefCounted<ExternalPrefLoader>(
865 chrome::DIR_DEFAULT_APPS, ExternalPrefLoader::NONE, nullptr),
Gyuyoung Kim2e954c42021-03-19 14:06:29866 ManifestLocation::kInternal, ManifestLocation::kInternal,
Toby Huangf93f7002021-01-24 01:08:13867 Extension::FROM_WEBSTORE | Extension::WAS_INSTALLED_BY_DEFAULT));
[email protected]98b4aca62011-09-28 01:27:23868#endif
xiyuan65b68ab12015-06-26 19:00:18869
Toby Huangf93f7002021-01-24 01:08:13870 std::unique_ptr<ExternalProviderImpl> drive_migration_provider(
871 new ExternalProviderImpl(
872 service,
873 base::MakeRefCounted<ExtensionMigrator>(
Phillis Tang28427c462021-10-19 20:50:38874 profile, extension_misc::kGoogleDriveAppId,
Toby Huangf93f7002021-01-24 01:08:13875 extension_misc::kDocsOfflineExtensionId),
Gyuyoung Kim2e954c42021-03-19 14:06:29876 profile, ManifestLocation::kExternalPref,
877 ManifestLocation::kExternalPrefDownload,
Toby Huangf93f7002021-01-24 01:08:13878 Extension::FROM_WEBSTORE | Extension::WAS_INSTALLED_BY_DEFAULT));
879 drive_migration_provider->set_auto_acknowledge(true);
880 provider_list->push_back(std::move(drive_migration_provider));
treibcc82ab82015-03-02 09:41:49881
Jinho Bangb5216cec2018-01-17 19:43:11882 provider_list->push_back(std::make_unique<ExternalProviderImpl>(
Matthew Dentonef83a622019-08-30 02:07:00883 service, base::MakeRefCounted<ExternalComponentLoader>(profile), profile,
Gyuyoung Kim2e954c42021-03-19 14:06:29884 ManifestLocation::kInvalidLocation, ManifestLocation::kExternalComponent,
lazyboyf33109d2016-08-31 00:37:08885 Extension::FROM_WEBSTORE | Extension::WAS_INSTALLED_BY_DEFAULT));
[email protected]8e4560b62011-01-14 10:09:14886}
[email protected]5df038b2012-07-16 19:03:27887
888} // namespace extensions