blob: c8696b69ebbd60b661ab5e1cc5bc64c211cb17fa [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"
Ben Franz1d4cef82022-05-16 12:38:2638#include "chrome/browser/profiles/profiles_state.h"
Song Fangzhencda4af62021-09-09 05:24:0239#include "chrome/browser/web_applications/preinstalled_app_install_features.h"
[email protected]f0841cd2011-01-19 15:07:2440#include "chrome/common/chrome_paths.h"
[email protected]83b59325a2011-10-14 15:58:0741#include "chrome/common/chrome_switches.h"
xiyuan65b68ab12015-06-26 19:00:1842#include "chrome/common/extensions/extension_constants.h"
dpolukhin2c6ef2932015-05-12 16:06:1343#include "chrome/common/pref_names.h"
[email protected]fdd28372014-08-21 02:27:2644#include "components/crx_file/id_util.h"
brettwb1fc1b82016-02-02 00:19:0845#include "components/prefs/pref_service.h"
[email protected]c38831a12011-10-28 12:44:4946#include "content/public/browser/browser_thread.h"
David Bertoni58c113a2019-08-02 19:53:2647#include "extensions/browser/extension_registry.h"
lazyboye8634172016-01-28 00:10:4848#include "extensions/browser/external_install_info.h"
[email protected]301116c62013-11-26 10:37:4549#include "extensions/browser/external_provider_interface.h"
Dominique Fauteux-Chapleauff3bb352019-10-16 14:32:3450#include "extensions/browser/pref_names.h"
Phillis Tang28427c462021-10-19 20:50:3851#include "extensions/common/constants.h"
[email protected]e4452d32013-11-15 23:07:4152#include "extensions/common/extension.h"
[email protected]d42c11152013-08-22 19:36:3253#include "extensions/common/manifest.h"
[email protected]9d32ded072011-10-11 16:31:0554#include "ui/base/l10n/l10n_util.h"
[email protected]8e4560b62011-01-14 10:09:1455
Ben Franz1d4cef82022-05-16 12:38:2656#if BUILDFLAG(IS_CHROMEOS)
57#include "chrome/browser/chromeos/app_mode/kiosk_app_external_loader.h"
58#endif // BUIDLFLAG(IS_CHROMEOS)
59
Yuta Hijikata1290fee22020-11-25 09:46:2860#if BUILDFLAG(IS_CHROMEOS_ASH)
Yao Lic9cd767d2021-11-16 02:17:4761#include "ash/components/arc/arc_util.h"
Henrique Ferreiro37770262021-02-06 01:20:5362#include "ash/constants/ash_paths.h"
Wenzhao Zang463f1142018-09-05 22:50:5063#include "base/path_service.h"
Yeunjoo Choi91907642021-04-16 13:18:1964#include "chrome/browser/ash/customization/customization_document.h"
Henrique Ferreiro606669a2021-02-24 13:36:5565#include "chrome/browser/ash/login/demo_mode/demo_extensions_external_loader.h"
66#include "chrome/browser/ash/login/demo_mode/demo_session.h"
Yeunjoo Choi7227dba2021-08-04 06:35:4767#include "chrome/browser/ash/policy/core/browser_policy_connector_ash.h"
Yeunjoo Choi8623e4a2021-07-02 01:57:0668#include "chrome/browser/ash/policy/core/device_local_account.h"
69#include "chrome/browser/ash/policy/core/device_local_account_policy_service.h"
Yeunjoo Choi15ab1ac2021-02-04 17:15:0770#include "chrome/browser/ash/profiles/profile_helper.h"
[email protected]af984882013-10-21 21:08:5171#include "chrome/browser/chromeos/extensions/device_local_account_external_policy_loader.h"
Maksim Ivanov8738d332020-01-07 22:19:0172#include "chrome/browser/chromeos/extensions/signin_screen_extensions_external_loader.h"
Swapnil5eca0412021-02-12 08:32:5473#include "extensions/common/constants.h"
[email protected]b39d25712013-03-14 09:53:4074#else
Daniel Murphy3657906d2021-04-13 20:33:1275#include "chrome/browser/extensions/preinstalled_apps.h"
[email protected]86c6b9e32011-10-25 17:09:1076#endif
77
Xiaohan Wangbe233b62022-01-14 19:15:5378#if BUILDFLAG(IS_WIN)
[email protected]5df038b2012-07-16 19:03:2779#include "chrome/browser/extensions/external_registry_loader_win.h"
[email protected]8e4560b62011-01-14 10:09:1480#endif
81
[email protected]631bb742011-11-02 11:29:3982using content::BrowserThread;
Gyuyoung Kim2e954c42021-03-19 14:06:2983using extensions::mojom::ManifestLocation;
[email protected]5df038b2012-07-16 19:03:2784
85namespace extensions {
[email protected]631bb742011-11-02 11:29:3986
Ahmed Fakhry9ef29e042017-09-01 16:32:0087namespace {
88
Yuta Hijikata1290fee22020-11-25 09:46:2889#if BUILDFLAG(IS_CHROMEOS_ASH)
Ahmed Fakhry9ef29e042017-09-01 16:32:0090
Wei Lee799de532021-11-10 03:33:3691const char kCameraAppId[] = "hfhhnacclhffhdffklopdkcgdhifgngh";
92
Daniel Murphy3657906d2021-04-13 20:33:1293// Certain pre-installed extensions are no longer needed on ARC devices as they
94// were replaced by their ARC counterparts.
Ahmed Fakhry9ef29e042017-09-01 16:32:0095bool ShouldUninstallExtensionReplacedByArcApp(const std::string& extension_id) {
Alex Newcomerf8c542f2018-08-13 23:48:5096 if (!arc::IsArcAvailable())
Ahmed Fakhry9ef29e042017-09-01 16:32:0097 return false;
98
99 if (extension_id == extension_misc::kGooglePlayBooksAppId ||
100 extension_id == extension_misc::kGooglePlayMoviesAppId ||
101 extension_id == extension_misc::kGooglePlayMusicAppId) {
102 return true;
103 }
104
105 return false;
106}
107
Yuta Hijikata1290fee22020-11-25 09:46:28108#endif // BUILDFLAG(IS_CHROMEOS_ASH)
Ahmed Fakhry9ef29e042017-09-01 16:32:00109
110} // namespace
111
[email protected]8e4560b62011-01-14 10:09:14112// Constants for keeping track of extension preferences in a dictionary.
[email protected]d8fd0fd2014-03-24 13:16:06113const char ExternalProviderImpl::kInstallParam[] = "install_parameter";
[email protected]5df038b2012-07-16 19:03:27114const char ExternalProviderImpl::kExternalCrx[] = "external_crx";
[email protected]7425d7df2012-11-28 14:35:42115const char ExternalProviderImpl::kExternalVersion[] = "external_version";
116const char ExternalProviderImpl::kExternalUpdateUrl[] = "external_update_url";
[email protected]7425d7df2012-11-28 14:35:42117const char ExternalProviderImpl::kIsBookmarkApp[] = "is_bookmark_app";
118const char ExternalProviderImpl::kIsFromWebstore[] = "is_from_webstore";
[email protected]19eac6d2013-05-30 06:51:03119const char ExternalProviderImpl::kKeepIfPresent[] = "keep_if_present";
[email protected]bf9fd5ae2014-04-09 22:50:06120const char ExternalProviderImpl::kWasInstalledByOem[] = "was_installed_by_oem";
Alan Cutterb81d0e02020-08-05 09:10:34121const char ExternalProviderImpl::kWebAppMigrationFlag[] =
122 "web_app_migration_flag";
[email protected]bf9fd5ae2014-04-09 22:50:06123const char ExternalProviderImpl::kSupportedLocales[] = "supported_locales";
[email protected]2b6a5802014-08-16 07:58:08124const char ExternalProviderImpl::kMayBeUntrusted[] = "may_be_untrusted";
dpolukhin2c6ef2932015-05-12 16:06:13125const char ExternalProviderImpl::kMinProfileCreatedByVersion[] =
126 "min_profile_created_by_version";
dpolukhin1687ef32015-06-22 11:12:37127const char ExternalProviderImpl::kDoNotInstallForEnterprise[] =
128 "do_not_install_for_enterprise";
[email protected]8e4560b62011-01-14 10:09:14129
[email protected]af984882013-10-21 21:08:51130ExternalProviderImpl::ExternalProviderImpl(
131 VisitorInterface* service,
132 const scoped_refptr<ExternalLoader>& loader,
133 Profile* profile,
Gyuyoung Kim2e954c42021-03-19 14:06:29134 ManifestLocation crx_location,
135 ManifestLocation download_location,
[email protected]af984882013-10-21 21:08:51136 int creation_flags)
[email protected]4b4c0132013-06-12 17:58:55137 : crx_location_(crx_location),
138 download_location_(download_location),
139 service_(service),
[email protected]4b4c0132013-06-12 17:58:55140 loader_(loader),
141 profile_(profile),
Toni Barzic87026682018-01-08 23:21:04142 creation_flags_(creation_flags) {
Oleg Davydov66246bd92019-09-26 16:31:51143 DCHECK(profile_);
[email protected]8e4560b62011-01-14 10:09:14144 loader_->Init(this);
145}
146
[email protected]5df038b2012-07-16 19:03:27147ExternalProviderImpl::~ExternalProviderImpl() {
Istiaque Ahmedf6e72622017-09-08 23:14:17148 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]8e4560b62011-01-14 10:09:14149 loader_->OwnerShutdown();
150}
151
[email protected]5df038b2012-07-16 19:03:27152void ExternalProviderImpl::VisitRegisteredExtension() {
[email protected]8e4560b62011-01-14 10:09:14153 // The loader will call back to SetPrefs.
154 loader_->StartLoading();
155}
156
Anina Koehler100794e22021-09-08 13:09:52157void ExternalProviderImpl::SetPrefs(
158 std::unique_ptr<base::DictionaryValue> prefs) {
Istiaque Ahmedf6e72622017-09-08 23:14:17159 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]8e4560b62011-01-14 10:09:14160
[email protected]47fc70c2011-12-06 07:29:51161 // Check if the service is still alive. It is possible that it went
[email protected]8e4560b62011-01-14 10:09:14162 // away while |loader_| was working on the FILE thread.
Matt Menkedc421a9c2022-06-07 19:53:02163 if (!service_)
164 return;
[email protected]8e4560b62011-01-14 10:09:14165
Oleg Davydovdec175a2020-05-25 16:44:29166 InstallStageTracker* install_stage_tracker =
167 InstallStageTracker::Get(profile_);
Peter Kasting7c683fe2021-06-24 15:12:10168 for (auto it : prefs->DictItems()) {
Swapnil5e0e0dc2020-09-21 14:59:47169 install_stage_tracker->ReportInstallCreationStage(
170 it.first,
171 InstallStageTracker::InstallCreationStage::SEEN_BY_EXTERNAL_PROVIDER);
Oleg Davydov52db8742019-08-20 09:14:40172 }
173
Matt Menkedc421a9c2022-06-07 19:53:02174 prefs_ = std::make_unique<base::Value::Dict>(std::move(prefs->GetDict()));
[email protected]8a839a02013-03-07 05:23:33175 ready_ = true; // Queries for extensions are allowed from this point.
[email protected]8e4560b62011-01-14 10:09:14176
Maria Petrisorbb5226b2022-06-02 09:10:51177 NotifyServiceOnExternalExtensionsFound();
Maria Petrisordba7ac42021-10-06 09:01:30178}
179
180void ExternalProviderImpl::TriggerOnExternalExtensionFound() {
181 DCHECK_CURRENTLY_ON(BrowserThread::UI);
182
183 // Check if the service is still alive. It is possible that it went
184 // away while |loader_| was working on the FILE thread. The prefs can be
185 // missing if SetPrefs() was not called yet.
186 if (!service_ || !prefs_)
187 return;
188
Maria Petrisorbb5226b2022-06-02 09:10:51189 NotifyServiceOnExternalExtensionsFound();
Maria Petrisordba7ac42021-10-06 09:01:30190}
191
Maria Petrisorbb5226b2022-06-02 09:10:51192void ExternalProviderImpl::NotifyServiceOnExternalExtensionsFound() {
Devlin Cronin19f70b6a2017-10-01 04:14:05193 std::vector<ExternalInstallInfoUpdateUrl> external_update_url_extensions;
194 std::vector<ExternalInstallInfoFile> external_file_extensions;
lazyboye8634172016-01-28 00:10:48195
196 RetrieveExtensionsFromPrefs(&external_update_url_extensions,
197 &external_file_extensions);
lazyboy4aeef202016-09-07 21:28:59198 for (const auto& extension : external_update_url_extensions)
Maria Petrisorbb5226b2022-06-02 09:10:51199 service_->OnExternalExtensionUpdateUrlFound(extension,
200 /*force_update=*/true);
lazyboye8634172016-01-28 00:10:48201
lazyboy4aeef202016-09-07 21:28:59202 for (const auto& extension : external_file_extensions)
Devlin Cronin19f70b6a2017-10-01 04:14:05203 service_->OnExternalExtensionFileFound(extension);
Maria Petrisorbb5226b2022-06-02 09:10:51204
205 service_->OnExternalProviderReady(this);
lazyboye8634172016-01-28 00:10:48206}
207
Anina Koehler100794e22021-09-08 13:09:52208void ExternalProviderImpl::UpdatePrefs(
209 std::unique_ptr<base::DictionaryValue> prefs) {
Istiaque Ahmedf6e72622017-09-08 23:14:17210 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Toni Barzic87026682018-01-08 23:21:04211 CHECK(allow_updates_);
lazyboye8634172016-01-28 00:10:48212
213 // Check if the service is still alive. It is possible that it went
214 // away while |loader_| was working on the FILE thread.
215 if (!service_)
216 return;
217
218 std::set<std::string> removed_extensions;
219 // Find extensions that were removed by this ExternalProvider.
Matt Menkedc421a9c2022-06-07 19:53:02220 for (auto pref : *prefs_) {
minchd4e260e2022-01-21 19:17:53221 const std::string& extension_id = pref.first;
lazyboye8634172016-01-28 00:10:48222 // Don't bother about invalid ids.
223 if (!crx_file::id_util::IdIsValid(extension_id))
224 continue;
Maks Orlovich96e5a342022-01-05 20:24:36225 if (!prefs->FindKey(extension_id))
lazyboye8634172016-01-28 00:10:48226 removed_extensions.insert(extension_id);
227 }
228
Matt Menkedc421a9c2022-06-07 19:53:02229 prefs_ = std::make_unique<base::Value::Dict>(std::move(prefs->GetDict()));
lazyboye8634172016-01-28 00:10:48230
Devlin Cronin19f70b6a2017-10-01 04:14:05231 std::vector<ExternalInstallInfoUpdateUrl> external_update_url_extensions;
232 std::vector<ExternalInstallInfoFile> external_file_extensions;
lazyboye8634172016-01-28 00:10:48233 RetrieveExtensionsFromPrefs(&external_update_url_extensions,
234 &external_file_extensions);
235
236 // Notify ExtensionService about completion of finding incremental updates
237 // from this provider.
238 // Provide the list of added and removed extensions.
239 service_->OnExternalProviderUpdateComplete(
240 this, external_update_url_extensions, external_file_extensions,
241 removed_extensions);
242}
243
244void ExternalProviderImpl::RetrieveExtensionsFromPrefs(
Devlin Cronin19f70b6a2017-10-01 04:14:05245 std::vector<ExternalInstallInfoUpdateUrl>* external_update_url_extensions,
246 std::vector<ExternalInstallInfoFile>* external_file_extensions) {
[email protected]9d32ded072011-10-11 16:31:05247 // Set of unsupported extensions that need to be deleted from prefs_.
248 std::set<std::string> unsupported_extensions;
Oleg Davydovdec175a2020-05-25 16:44:29249 InstallStageTracker* install_stage_tracker =
250 InstallStageTracker::Get(profile_);
[email protected]9d32ded072011-10-11 16:31:05251
lazyboye8634172016-01-28 00:10:48252 // Discover all the extensions this provider has.
Matt Menkedc421a9c2022-06-07 19:53:02253 for (auto pref : *prefs_) {
minchd4e260e2022-01-21 19:17:53254 const std::string& extension_id = pref.first;
Peter Kasting42e82e92021-09-15 16:39:17255 const base::DictionaryValue* extension_dict = nullptr;
[email protected]ab22ba42011-01-14 16:36:38256
Yuta Hijikata1290fee22020-11-25 09:46:28257#if BUILDFLAG(IS_CHROMEOS_ASH)
Wei Lee799de532021-11-10 03:33:36258 if (extension_id == kCameraAppId) {
Swapnil5eca0412021-02-12 08:32:54259 unsupported_extensions.insert(extension_id);
260 install_stage_tracker->ReportFailure(
261 extension_id,
262 InstallStageTracker::FailureReason::REPLACED_BY_SYSTEM_APP);
263 continue;
264 }
265
Ahmed Fakhry9ef29e042017-09-01 16:32:00266 if (ShouldUninstallExtensionReplacedByArcApp(extension_id)) {
267 VLOG(1) << "Extension with key: " << extension_id << " was replaced "
268 << "by a default ARC app, and will be uninstalled.";
269 unsupported_extensions.emplace(extension_id);
Oleg Davydovdec175a2020-05-25 16:44:29270 install_stage_tracker->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51271 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29272 InstallStageTracker::FailureReason::REPLACED_BY_ARC_APP);
Ahmed Fakhry9ef29e042017-09-01 16:32:00273 continue;
274 }
Yuta Hijikata1290fee22020-11-25 09:46:28275#endif // BUILDFLAG(IS_CHROMEOS_ASH)
Ahmed Fakhry9ef29e042017-09-01 16:32:00276
[email protected]fdd28372014-08-21 02:27:26277 if (!crx_file::id_util::IdIsValid(extension_id)) {
[email protected]ab22ba42011-01-14 16:36:38278 LOG(WARNING) << "Malformed extension dictionary: key "
279 << extension_id.c_str() << " is not a valid id.";
Oleg Davydovdec175a2020-05-25 16:44:29280 install_stage_tracker->ReportFailure(
281 extension_id, InstallStageTracker::FailureReason::INVALID_ID);
[email protected]8e4560b62011-01-14 10:09:14282 continue;
[email protected]ab22ba42011-01-14 16:36:38283 }
284
minchd4e260e2022-01-21 19:17:53285 if (!pref.second.GetAsDictionary(&extension_dict)) {
[email protected]ab22ba42011-01-14 16:36:38286 LOG(WARNING) << "Malformed extension dictionary: key "
287 << extension_id.c_str()
288 << " has a value that is not a dictionary.";
Oleg Davydovdec175a2020-05-25 16:44:29289 install_stage_tracker->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51290 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29291 InstallStageTracker::FailureReason::MALFORMED_EXTENSION_DICT);
[email protected]ab22ba42011-01-14 16:36:38292 continue;
293 }
[email protected]8e4560b62011-01-14 10:09:14294
Anina Koehler100794e22021-09-08 13:09:52295 std::string external_crx;
296 const base::Value* external_version_value = nullptr;
[email protected]8e4560b62011-01-14 10:09:14297 std::string external_version;
Anina Koehler100794e22021-09-08 13:09:52298 std::string external_update_url;
299
Peter Kasting42e82e92021-09-15 16:39:17300 bool has_external_crx =
301 extension_dict->GetString(kExternalCrx, &external_crx);
Anina Koehler100794e22021-09-08 13:09:52302
[email protected]0d461c52012-07-03 19:29:41303 bool has_external_version = false;
Peter Kasting42e82e92021-09-15 16:39:17304 if (extension_dict->Get(kExternalVersion, &external_version_value)) {
jdoerrie1f536b22017-10-23 17:15:11305 if (external_version_value->is_string()) {
Alex Rudenkoa4d75ab52021-07-09 15:39:44306 external_version = external_version_value->GetString();
[email protected]0d461c52012-07-03 19:29:41307 has_external_version = true;
308 } else {
Oleg Davydovdec175a2020-05-25 16:44:29309 install_stage_tracker->ReportFailure(
310 extension_id, InstallStageTracker::FailureReason::
Oleg Davydov66246bd92019-09-26 16:31:51311 MALFORMED_EXTENSION_DICT_VERSION);
[email protected]0d461c52012-07-03 19:29:41312 LOG(WARNING) << "Malformed extension dictionary for extension: "
313 << extension_id.c_str() << ". " << kExternalVersion
314 << " value must be a string.";
315 continue;
316 }
317 }
318
Peter Kasting42e82e92021-09-15 16:39:17319 bool has_external_update_url =
320 extension_dict->GetString(kExternalUpdateUrl, &external_update_url);
[email protected]8e4560b62011-01-14 10:09:14321 if (has_external_crx != has_external_version) {
Oleg Davydovdec175a2020-05-25 16:44:29322 install_stage_tracker->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51323 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29324 InstallStageTracker::FailureReason::MALFORMED_EXTENSION_DICT);
[email protected]8e4560b62011-01-14 10:09:14325 LOG(WARNING) << "Malformed extension dictionary for extension: "
326 << extension_id.c_str() << ". " << kExternalCrx
327 << " and " << kExternalVersion << " must be used together.";
328 continue;
329 }
330
331 if (has_external_crx == has_external_update_url) {
Oleg Davydovdec175a2020-05-25 16:44:29332 install_stage_tracker->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51333 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29334 InstallStageTracker::FailureReason::MALFORMED_EXTENSION_DICT);
[email protected]8e4560b62011-01-14 10:09:14335 LOG(WARNING) << "Malformed extension dictionary for extension: "
336 << extension_id.c_str() << ". Exactly one of the "
Anina Koehler100794e22021-09-08 13:09:52337 << "followng keys should be used: " << kExternalCrx
338 << ", " << kExternalUpdateUrl << ".";
[email protected]8e4560b62011-01-14 10:09:14339 continue;
340 }
341
[email protected]9d32ded072011-10-11 16:31:05342 // Check that extension supports current browser locale.
Anina Koehler100794e22021-09-08 13:09:52343 const base::ListValue* supported_locales = nullptr;
Peter Kasting42e82e92021-09-15 16:39:17344 if (extension_dict->GetList(kSupportedLocales, &supported_locales)) {
[email protected]9d32ded072011-10-11 16:31:05345 std::vector<std::string> browser_locales;
346 l10n_util::GetParentLocales(g_browser_process->GetApplicationLocale(),
347 &browser_locales);
348
[email protected]9d32ded072011-10-11 16:31:05349 bool locale_supported = false;
Daniel Cheng354945d2022-02-02 23:39:17350 for (const base::Value& locale : supported_locales->GetListDeprecated()) {
Maks Orlovichab5bbab2021-11-26 16:30:35351 const std::string* current_locale = locale.GetIfString();
352 if (current_locale && l10n_util::IsValidLocaleSyntax(*current_locale)) {
353 std::string normalized_locale =
354 l10n_util::NormalizeLocale(*current_locale);
355 if (base::Contains(browser_locales, normalized_locale)) {
[email protected]9d32ded072011-10-11 16:31:05356 locale_supported = true;
357 break;
358 }
359 } else {
Maks Orlovichab5bbab2021-11-26 16:30:35360 LOG(WARNING) << "Unrecognized locale '"
361 << (current_locale ? *current_locale : "(Not a string)")
[email protected]9d32ded072011-10-11 16:31:05362 << "' found as supported locale for extension: "
363 << extension_id;
364 }
365 }
366
367 if (!locale_supported) {
368 unsupported_extensions.insert(extension_id);
Oleg Davydovdec175a2020-05-25 16:44:29369 install_stage_tracker->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51370 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29371 InstallStageTracker::FailureReason::LOCALE_NOT_SUPPORTED);
[email protected]19eac6d2013-05-30 06:51:03372 VLOG(1) << "Skip installing (or uninstall) external extension: "
373 << extension_id << " because the extension doesn't support "
374 << "the browser locale.";
[email protected]9d32ded072011-10-11 16:31:05375 continue;
376 }
377 }
378
[email protected]f121003b2012-05-04 21:57:47379 int creation_flags = creation_flags_;
Nan Linc3aff1b92021-11-08 21:46:38380 absl::optional<bool> is_bookmark_app =
381 extension_dict->FindBoolKey(kIsBookmarkApp);
382 if (is_bookmark_app.value_or(false)) {
[email protected]f121003b2012-05-04 21:57:47383 creation_flags |= Extension::FROM_BOOKMARK;
384 }
Nan Linc3aff1b92021-11-08 21:46:38385 absl::optional<bool> is_from_webstore =
386 extension_dict->FindBoolKey(kIsFromWebstore);
387 if (is_from_webstore.value_or(false)) {
[email protected]7425d7df2012-11-28 14:35:42388 creation_flags |= Extension::FROM_WEBSTORE;
389 }
Alan Cutterb81d0e02020-08-05 09:10:34390
391 // If the extension is in a web app migration treat it as "keep_if_present"
392 // so it can get uninstalled by WebAppUiManager::UninstallAndReplace() once
393 // the replacement web app has installed and migrated over user preferences.
394 // TODO(crbug.com/1099150): Remove this field after migration is complete.
395 const std::string* web_app_migration_flag =
Peter Kasting42e82e92021-09-15 16:39:17396 extension_dict->FindStringPath(kWebAppMigrationFlag);
Alan Cutterb81d0e02020-08-05 09:10:34397 bool is_migrating_to_web_app =
398 web_app_migration_flag &&
Alan Cutter52914e72021-05-05 09:35:48399 web_app::IsPreinstalledAppInstallFeatureEnabled(*web_app_migration_flag,
400 *profile_);
Alan Cutterb81d0e02020-08-05 09:10:34401 bool keep_if_present =
Peter Kasting42e82e92021-09-15 16:39:17402 extension_dict->FindBoolPath(kKeepIfPresent).value_or(false);
Alan Cutterb81d0e02020-08-05 09:10:34403 if (keep_if_present || is_migrating_to_web_app) {
David Bertoni58c113a2019-08-02 19:53:26404 ExtensionRegistry* extension_registry = ExtensionRegistry::Get(profile_);
405 const Extension* extension =
David Bertonia0b34722019-09-30 20:51:26406 extension_registry ? extension_registry->GetExtensionById(
407 extension_id, ExtensionRegistry::EVERYTHING)
408 : nullptr;
[email protected]19eac6d2013-05-30 06:51:03409 if (!extension) {
dpolukhin2c6ef2932015-05-12 16:06:13410 unsupported_extensions.insert(extension_id);
Oleg Davydovdec175a2020-05-25 16:44:29411 install_stage_tracker->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51412 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29413 InstallStageTracker::FailureReason::NOT_PERFORMING_NEW_INSTALL);
[email protected]19eac6d2013-05-30 06:51:03414 VLOG(1) << "Skip installing (or uninstall) external extension: "
415 << extension_id << " because the extension should be kept "
416 << "only if it is already installed.";
417 continue;
418 }
419 }
Alan Cutterb81d0e02020-08-05 09:10:34420
Nan Linc3aff1b92021-11-08 21:46:38421 absl::optional<bool> was_installed_by_oem =
422 extension_dict->FindBoolKey(kWasInstalledByOem);
423 if (was_installed_by_oem.value_or(false)) {
dpolukhind0be494a2015-05-28 09:43:17424 creation_flags |= Extension::WAS_INSTALLED_BY_OEM;
425 }
Nan Linc3aff1b92021-11-08 21:46:38426 absl::optional<bool> may_be_untrusted =
427 extension_dict->FindBoolKey(kMayBeUntrusted);
428 if (may_be_untrusted.value_or(false)) {
[email protected]2b6a5802014-08-16 07:58:08429 creation_flags |= Extension::MAY_BE_UNTRUSTED;
430 }
[email protected]f121003b2012-05-04 21:57:47431
Peter Kasting42e82e92021-09-15 16:39:17432 if (!HandleMinProfileVersion(extension_dict, extension_id,
dpolukhin1687ef32015-06-22 11:12:37433 &unsupported_extensions)) {
dpolukhin2c6ef2932015-05-12 16:06:13434 continue;
dpolukhin1687ef32015-06-22 11:12:37435 }
436
Peter Kasting42e82e92021-09-15 16:39:17437 if (!HandleDoNotInstallForEnterprise(extension_dict, extension_id,
dpolukhin1687ef32015-06-22 11:12:37438 &unsupported_extensions)) {
439 continue;
440 }
dpolukhin2c6ef2932015-05-12 16:06:13441
Anina Koehler100794e22021-09-08 13:09:52442 std::string install_parameter;
Peter Kasting42e82e92021-09-15 16:39:17443 extension_dict->GetString(kInstallParam, &install_parameter);
[email protected]d8fd0fd2014-03-24 13:16:06444
[email protected]8e4560b62011-01-14 10:09:14445 if (has_external_crx) {
Gyuyoung Kim2e954c42021-03-19 14:06:29446 if (crx_location_ == ManifestLocation::kInvalidLocation) {
Oleg Davydovdec175a2020-05-25 16:44:29447 install_stage_tracker->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51448 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29449 InstallStageTracker::FailureReason::NOT_SUPPORTED_EXTENSION_DICT);
[email protected]8e4560b62011-01-14 10:09:14450 LOG(WARNING) << "This provider does not support installing external "
451 << "extensions from crx files.";
452 continue;
453 }
Peter Kasting141279b2021-02-09 22:34:20454
Anina Koehler100794e22021-09-08 13:09:52455 base::FilePath path = base::FilePath::FromUTF8Unsafe(external_crx);
Peter Kasting141279b2021-02-09 22:34:20456 if (path.value().find(base::FilePath::kParentDirectory) !=
[email protected]8e4560b62011-01-14 10:09:14457 base::StringPiece::npos) {
Oleg Davydovdec175a2020-05-25 16:44:29458 install_stage_tracker->ReportFailure(
459 extension_id, InstallStageTracker::FailureReason::
Oleg Davydov66246bd92019-09-26 16:31:51460 MALFORMED_EXTENSION_DICT_FILE_PATH);
[email protected]8e4560b62011-01-14 10:09:14461 LOG(WARNING) << "Path traversal not allowed in path: "
Anina Koehler100794e22021-09-08 13:09:52462 << external_crx.c_str();
[email protected]8e4560b62011-01-14 10:09:14463 continue;
464 }
465
[email protected]f0841cd2011-01-19 15:07:24466 // If the path is relative, and the provider has a base path,
467 // build the absolute path to the crx file.
Peter Kasting141279b2021-02-09 22:34:20468
[email protected]8e4560b62011-01-14 10:09:14469 if (!path.IsAbsolute()) {
[email protected]650b2d52013-02-10 03:41:45470 base::FilePath base_path = loader_->GetBaseCrxFilePath();
[email protected]f0841cd2011-01-19 15:07:24471 if (base_path.empty()) {
Oleg Davydovdec175a2020-05-25 16:44:29472 install_stage_tracker->ReportFailure(
473 extension_id, InstallStageTracker::FailureReason::
Oleg Davydov66246bd92019-09-26 16:31:51474 MALFORMED_EXTENSION_DICT_FILE_PATH);
Anina Koehler100794e22021-09-08 13:09:52475 LOG(WARNING) << "File path " << external_crx.c_str()
[email protected]f0841cd2011-01-19 15:07:24476 << " is relative. An absolute path is required.";
477 continue;
478 }
Peter Kasting141279b2021-02-09 22:34:20479 path = base_path.Append(path);
[email protected]8e4560b62011-01-14 10:09:14480 }
481
Devlin Cronind4c2a8f32017-09-29 17:08:30482 base::Version version(external_version);
483 if (!version.IsValid()) {
Oleg Davydovdec175a2020-05-25 16:44:29484 install_stage_tracker->ReportFailure(
485 extension_id, InstallStageTracker::FailureReason::
Oleg Davydov66246bd92019-09-26 16:31:51486 MALFORMED_EXTENSION_DICT_VERSION);
[email protected]8e4560b62011-01-14 10:09:14487 LOG(WARNING) << "Malformed extension dictionary for extension: "
488 << extension_id.c_str() << ". Invalid version string \""
489 << external_version << "\".";
490 continue;
491 }
Devlin Cronin19f70b6a2017-10-01 04:14:05492 external_file_extensions->emplace_back(
493 extension_id, version, path, crx_location_, creation_flags,
494 auto_acknowledge_, install_immediately_);
[email protected]8a839a02013-03-07 05:23:33495 } else { // if (has_external_update_url)
[email protected]8e4560b62011-01-14 10:09:14496 CHECK(has_external_update_url); // Checking of keys above ensures this.
Gyuyoung Kim2e954c42021-03-19 14:06:29497 if (download_location_ == ManifestLocation::kInvalidLocation) {
Oleg Davydovdec175a2020-05-25 16:44:29498 install_stage_tracker->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51499 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29500 InstallStageTracker::FailureReason::NOT_SUPPORTED_EXTENSION_DICT);
[email protected]8e4560b62011-01-14 10:09:14501 LOG(WARNING) << "This provider does not support installing external "
502 << "extensions from update URLs.";
503 continue;
504 }
Anina Koehler100794e22021-09-08 13:09:52505 GURL update_url(external_update_url);
Devlin Cronind4c2a8f32017-09-29 17:08:30506 if (!update_url.is_valid()) {
Oleg Davydovdec175a2020-05-25 16:44:29507 install_stage_tracker->ReportFailure(
508 extension_id, InstallStageTracker::FailureReason::
Oleg Davydov66246bd92019-09-26 16:31:51509 MALFORMED_EXTENSION_DICT_UPDATE_URL);
[email protected]8e4560b62011-01-14 10:09:14510 LOG(WARNING) << "Malformed extension dictionary for extension: "
[email protected]ab22ba42011-01-14 16:36:38511 << extension_id.c_str() << ". Key " << kExternalUpdateUrl
512 << " has value \"" << external_update_url
513 << "\", which is not a valid URL.";
[email protected]8e4560b62011-01-14 10:09:14514 continue;
515 }
Devlin Cronin19f70b6a2017-10-01 04:14:05516 external_update_url_extensions->emplace_back(
Anina Koehler100794e22021-09-08 13:09:52517 extension_id, install_parameter, std::move(update_url),
Devlin Cronin19f70b6a2017-10-01 04:14:05518 download_location_, creation_flags, auto_acknowledge_);
[email protected]8e4560b62011-01-14 10:09:14519 }
520 }
521
jdoerrie13cd648c82018-10-02 21:21:02522 for (auto it = unsupported_extensions.begin();
[email protected]9d32ded072011-10-11 16:31:05523 it != unsupported_extensions.end(); ++it) {
524 // Remove extension for the list of know external extensions. The extension
525 // will be uninstalled later because provider doesn't provide it anymore.
Matt Menkedc421a9c2022-06-07 19:53:02526 prefs_->Remove(*it);
[email protected]9d32ded072011-10-11 16:31:05527 }
[email protected]8e4560b62011-01-14 10:09:14528}
529
[email protected]5df038b2012-07-16 19:03:27530void ExternalProviderImpl::ServiceShutdown() {
Bartek Nowierski3253b672020-06-01 20:37:12531 service_ = nullptr;
[email protected]8e4560b62011-01-14 10:09:14532}
533
[email protected]5df038b2012-07-16 19:03:27534bool ExternalProviderImpl::IsReady() const {
[email protected]8e4560b62011-01-14 10:09:14535 return ready_;
536}
537
[email protected]5df038b2012-07-16 19:03:27538bool ExternalProviderImpl::HasExtension(
[email protected]8e4560b62011-01-14 10:09:14539 const std::string& id) const {
Istiaque Ahmedf6e72622017-09-08 23:14:17540 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]8e4560b62011-01-14 10:09:14541 CHECK(prefs_.get());
542 CHECK(ready_);
Matt Menkedc421a9c2022-06-07 19:53:02543 return prefs_->contains(id);
[email protected]8e4560b62011-01-14 10:09:14544}
545
[email protected]5df038b2012-07-16 19:03:27546bool ExternalProviderImpl::GetExtensionDetails(
dchengc963c7142016-04-08 03:55:22547 const std::string& id,
Gyuyoung Kim2e954c42021-03-19 14:06:29548 ManifestLocation* location,
pwnallcbd73192016-08-22 18:59:17549 std::unique_ptr<base::Version>* version) const {
Istiaque Ahmedf6e72622017-09-08 23:14:17550 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]8e4560b62011-01-14 10:09:14551 CHECK(prefs_.get());
552 CHECK(ready_);
Matt Menkedc421a9c2022-06-07 19:53:02553 base::Value::Dict* dict = prefs_->FindDict(id);
554 if (!dict)
[email protected]8e4560b62011-01-14 10:09:14555 return false;
556
Gyuyoung Kim2e954c42021-03-19 14:06:29557 ManifestLocation loc = ManifestLocation::kInvalidLocation;
Matt Menkedc421a9c2022-06-07 19:53:02558 if (dict->contains(kExternalUpdateUrl)) {
[email protected]8e4560b62011-01-14 10:09:14559 loc = download_location_;
560
Matt Menkedc421a9c2022-06-07 19:53:02561 } else if (dict->contains(kExternalCrx)) {
[email protected]8e4560b62011-01-14 10:09:14562 loc = crx_location_;
563
Matt Menkedc421a9c2022-06-07 19:53:02564 const std::string* external_version = dict->FindString(kExternalVersion);
Maks Orlovich96e5a342022-01-05 20:24:36565 if (!external_version)
[email protected]8e4560b62011-01-14 10:09:14566 return false;
567
568 if (version)
Maks Orlovich96e5a342022-01-05 20:24:36569 *version = std::make_unique<base::Version>(*external_version);
[email protected]8e4560b62011-01-14 10:09:14570
571 } else {
572 NOTREACHED(); // Chrome should not allow prefs to get into this state.
573 return false;
574 }
575
576 if (location)
577 *location = loc;
578
579 return true;
580}
581
dpolukhin2c6ef2932015-05-12 16:06:13582bool ExternalProviderImpl::HandleMinProfileVersion(
Anina Koehler100794e22021-09-08 13:09:52583 const base::DictionaryValue* extension,
dpolukhin2c6ef2932015-05-12 16:06:13584 const std::string& extension_id,
585 std::set<std::string>* unsupported_extensions) {
Anina Koehler100794e22021-09-08 13:09:52586 std::string min_profile_created_by_version;
587 if (extension->GetString(kMinProfileCreatedByVersion,
588 &min_profile_created_by_version)) {
pwnallcbd73192016-08-22 18:59:17589 base::Version profile_version(
dpolukhin2c6ef2932015-05-12 16:06:13590 profile_->GetPrefs()->GetString(prefs::kProfileCreatedByVersion));
Anina Koehler100794e22021-09-08 13:09:52591 base::Version min_version(min_profile_created_by_version);
dpolukhin2c6ef2932015-05-12 16:06:13592 if (min_version.IsValid() && profile_version.CompareTo(min_version) < 0) {
593 unsupported_extensions->insert(extension_id);
Oleg Davydovdec175a2020-05-25 16:44:29594 InstallStageTracker::Get(profile_)->ReportFailure(
595 extension_id, InstallStageTracker::FailureReason::TOO_OLD_PROFILE);
dpolukhin2c6ef2932015-05-12 16:06:13596 VLOG(1) << "Skip installing (or uninstall) external extension: "
597 << extension_id
598 << " profile.created_by_version: " << profile_version.GetString()
599 << " min_profile_created_by_version: "
600 << min_profile_created_by_version;
601 return false;
602 }
603 }
604 return true;
605}
606
dpolukhin1687ef32015-06-22 11:12:37607bool ExternalProviderImpl::HandleDoNotInstallForEnterprise(
Anina Koehler100794e22021-09-08 13:09:52608 const base::DictionaryValue* extension,
dpolukhin1687ef32015-06-22 11:12:37609 const std::string& extension_id,
610 std::set<std::string>* unsupported_extensions) {
Nan Linc3aff1b92021-11-08 21:46:38611 absl::optional<bool> do_not_install_for_enterprise =
612 extension->FindBoolKey(kDoNotInstallForEnterprise);
613 if (do_not_install_for_enterprise.value_or(false)) {
dpolukhin1687ef32015-06-22 11:12:37614 const policy::ProfilePolicyConnector* const connector =
Xi Hanfe39afc62019-04-29 14:50:14615 profile_->GetProfilePolicyConnector();
dpolukhin1687ef32015-06-22 11:12:37616 if (connector->IsManaged()) {
617 unsupported_extensions->insert(extension_id);
Oleg Davydovdec175a2020-05-25 16:44:29618 InstallStageTracker::Get(profile_)->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51619 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29620 InstallStageTracker::FailureReason::DO_NOT_INSTALL_FOR_ENTERPRISE);
dpolukhin1687ef32015-06-22 11:12:37621 VLOG(1) << "Skip installing (or uninstall) external extension "
622 << extension_id << " restricted for managed user";
623 return false;
624 }
625 }
626 return true;
627}
628
[email protected]8e4560b62011-01-14 10:09:14629// static
[email protected]5df038b2012-07-16 19:03:27630void ExternalProviderImpl::CreateExternalProviders(
[email protected]8e4560b62011-01-14 10:09:14631 VisitorInterface* service,
632 Profile* profile,
633 ProviderCollection* provider_list) {
rkaplowdd66a1342015-03-05 00:31:49634 TRACE_EVENT0("browser,startup",
635 "ExternalProviderImpl::CreateExternalProviders");
[email protected]af984882013-10-21 21:08:51636 scoped_refptr<ExternalLoader> external_loader;
binjincccacef2014-10-13 19:00:20637 scoped_refptr<ExternalLoader> external_recommended_loader;
Gyuyoung Kim2e954c42021-03-19 14:06:29638 ManifestLocation crx_location = ManifestLocation::kInvalidLocation;
achuithd3da4f02017-03-23 20:05:29639
Yuta Hijikata1290fee22020-11-25 09:46:28640#if BUILDFLAG(IS_CHROMEOS_ASH)
Yeunjoo Choi36f21d542022-01-13 03:12:33641 if (ash::ProfileHelper::IsSigninProfile(profile)) {
Maksim Ivanov12801d0d2020-02-18 10:23:41642 // Download extensions/apps installed by policy in the login profile.
643 // Extensions (not apps) installed through this path will have type
644 // |TYPE_LOGIN_SCREEN_EXTENSION| with limited API capabilities.
Gyuyoung Kim2e954c42021-03-19 14:06:29645 crx_location = ManifestLocation::kExternalPolicyDownload;
Maksim Ivanov8738d332020-01-07 22:19:01646 external_loader =
647 base::MakeRefCounted<chromeos::SigninScreenExtensionsExternalLoader>(
Oleg Davydovba7dd392021-03-18 09:47:44648 profile);
Jinho Bangb5216cec2018-01-17 19:43:11649 auto signin_profile_provider = std::make_unique<ExternalProviderImpl>(
achuithd3da4f02017-03-23 20:05:29650 service, external_loader, profile, crx_location,
Gyuyoung Kim2e954c42021-03-19 14:06:29651 ManifestLocation::kExternalPolicyDownload, Extension::FOR_LOGIN_SCREEN);
Maksim Ivanov8738d332020-01-07 22:19:01652 signin_profile_provider->set_auto_acknowledge(true);
Toni Barzic87026682018-01-08 23:21:04653 signin_profile_provider->set_allow_updates(true);
654 provider_list->push_back(std::move(signin_profile_provider));
achuithd3da4f02017-03-23 20:05:29655 return;
656 }
657
Yeunjoo Choi7227dba2021-08-04 06:35:47658 policy::BrowserPolicyConnectorAsh* connector =
659 g_browser_process->platform_part()->browser_policy_connector_ash();
[email protected]2d4cfed2014-01-14 13:59:57660 bool is_chrome_os_public_session = false;
[email protected]2fda9972014-07-23 14:51:59661 const user_manager::User* user =
Yeunjoo Choi36f21d542022-01-13 03:12:33662 ash::ProfileHelper::Get()->GetUserByProfile(profile);
[email protected]2d4cfed2014-01-14 13:59:57663 policy::DeviceLocalAccount::Type account_type;
Roland Bock4ce23a922021-06-11 13:23:11664 if (user && connector->IsDeviceEnterpriseManaged() &&
alemate909aa58a2016-11-03 22:49:07665 policy::IsDeviceLocalAccountUser(user->GetAccountId().GetUserEmail(),
666 &account_type)) {
[email protected]2d4cfed2014-01-14 13:59:57667 if (account_type == policy::DeviceLocalAccount::TYPE_PUBLIC_SESSION)
668 is_chrome_os_public_session = true;
[email protected]af984882013-10-21 21:08:51669 policy::DeviceLocalAccountPolicyBroker* broker =
[email protected]97275822014-01-21 19:30:36670 connector->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
alemate909aa58a2016-11-03 22:49:07671 user->GetAccountId().GetUserEmail());
[email protected]af984882013-10-21 21:08:51672 if (broker) {
673 external_loader = broker->extension_loader();
Gyuyoung Kim2e954c42021-03-19 14:06:29674 crx_location = ManifestLocation::kExternalPolicy;
[email protected]af984882013-10-21 21:08:51675 } else {
676 NOTREACHED();
677 }
678 } else {
Matthew Dentonef83a622019-08-30 02:07:00679 external_loader = base::MakeRefCounted<ExternalPolicyLoader>(
Oleg Davydov52db8742019-08-20 09:14:40680 profile, ExtensionManagementFactory::GetForBrowserContext(profile),
binjincccacef2014-10-13 19:00:20681 ExternalPolicyLoader::FORCED);
Matthew Dentonef83a622019-08-30 02:07:00682 external_recommended_loader = base::MakeRefCounted<ExternalPolicyLoader>(
Oleg Davydov52db8742019-08-20 09:14:40683 profile, ExtensionManagementFactory::GetForBrowserContext(profile),
binjincccacef2014-10-13 19:00:20684 ExternalPolicyLoader::RECOMMENDED);
[email protected]af984882013-10-21 21:08:51685 }
686#else
Matthew Dentonef83a622019-08-30 02:07:00687 external_loader = base::MakeRefCounted<ExternalPolicyLoader>(
Oleg Davydov52db8742019-08-20 09:14:40688 profile, ExtensionManagementFactory::GetForBrowserContext(profile),
binjincccacef2014-10-13 19:00:20689 ExternalPolicyLoader::FORCED);
Matthew Dentonef83a622019-08-30 02:07:00690 external_recommended_loader = base::MakeRefCounted<ExternalPolicyLoader>(
Oleg Davydov52db8742019-08-20 09:14:40691 profile, ExtensionManagementFactory::GetForBrowserContext(profile),
binjincccacef2014-10-13 19:00:20692 ExternalPolicyLoader::RECOMMENDED);
[email protected]af984882013-10-21 21:08:51693#endif
694
[email protected]b9f4fe52012-11-09 21:40:59695 // Policies are mandatory so they can't be skipped with command line flag.
dchengc7047942014-08-26 05:05:31696 if (external_loader.get()) {
Jinho Bangb5216cec2018-01-17 19:43:11697 auto policy_provider = std::make_unique<ExternalProviderImpl>(
lazyboyf33109d2016-08-31 00:37:08698 service, external_loader, profile, crx_location,
Gyuyoung Kim2e954c42021-03-19 14:06:29699 ManifestLocation::kExternalPolicyDownload, Extension::NO_FLAGS);
Toni Barzic87026682018-01-08 23:21:04700 policy_provider->set_allow_updates(true);
701 provider_list->push_back(std::move(policy_provider));
[email protected]af984882013-10-21 21:08:51702 }
[email protected]b9f4fe52012-11-09 21:40:59703
Anqing Zhaof0e96fb42020-12-11 23:21:21704 // Load the KioskAppExternalProvider when running in the Chrome App kiosk
705 // mode.
[email protected]ee3da0552014-07-16 05:27:31706 if (chrome::IsRunningInForcedAppMode()) {
Ben Franz1d4cef82022-05-16 12:38:26707#if BUILDFLAG(IS_CHROMEOS)
708 if (profiles::IsChromeAppKioskSession()) {
709 ManifestLocation location = ManifestLocation::kExternalPolicy;
710
Yuta Hijikata1290fee22020-11-25 09:46:28711#if BUILDFLAG(IS_CHROMEOS_ASH)
Yeunjoo Choi7227dba2021-08-04 06:35:47712 policy::BrowserPolicyConnectorAsh* const connector =
713 g_browser_process->platform_part()->browser_policy_connector_ash();
Ben Franz1d4cef82022-05-16 12:38:26714 if (!connector || !connector->IsDeviceEnterpriseManaged())
715 location = ManifestLocation::kExternalPref;
716#endif
pbond43ddd4f2015-09-08 16:39:19717
Anqing Zhaof0e96fb42020-12-11 23:21:21718 auto kiosk_app_provider = std::make_unique<ExternalProviderImpl>(
719 service,
Henrique Ferreiro26ed25a2021-02-01 21:59:29720 base::MakeRefCounted<ash::KioskAppExternalLoader>(
721 ash::KioskAppExternalLoader::AppClass::kPrimary),
Gyuyoung Kim2e954c42021-03-19 14:06:29722 profile, location, ManifestLocation::kInvalidLocation,
723 Extension::NO_FLAGS);
Anqing Zhaof0e96fb42020-12-11 23:21:21724 kiosk_app_provider->set_auto_acknowledge(true);
725 kiosk_app_provider->set_install_immediately(true);
726 kiosk_app_provider->set_allow_updates(true);
727 provider_list->push_back(std::move(kiosk_app_provider));
jennyz26b7f432015-09-03 20:59:27728
Anqing Zhaof0e96fb42020-12-11 23:21:21729 // Kiosk secondary app external provider.
730 auto secondary_kiosk_app_provider =
731 std::make_unique<ExternalProviderImpl>(
732 service,
Henrique Ferreiro26ed25a2021-02-01 21:59:29733 base::MakeRefCounted<ash::KioskAppExternalLoader>(
734 ash::KioskAppExternalLoader::AppClass::kSecondary),
Gyuyoung Kim2e954c42021-03-19 14:06:29735 profile, ManifestLocation::kExternalPref,
736 ManifestLocation::kExternalPrefDownload, Extension::NO_FLAGS);
Anqing Zhaof0e96fb42020-12-11 23:21:21737 secondary_kiosk_app_provider->set_auto_acknowledge(true);
738 secondary_kiosk_app_provider->set_install_immediately(true);
739 secondary_kiosk_app_provider->set_allow_updates(true);
740 provider_list->push_back(std::move(secondary_kiosk_app_provider));
741 }
[email protected]ee3da0552014-07-16 05:27:31742#endif
743 return;
744 }
745
binjincccacef2014-10-13 19:00:20746 // Extensions provided by recommended policies.
747 if (external_recommended_loader.get()) {
Nicolas Ouellet-Payeur93b74ca1d2020-12-09 23:33:12748 auto recommended_provider = std::make_unique<ExternalProviderImpl>(
lazyboyf33109d2016-08-31 00:37:08749 service, external_recommended_loader, profile, crx_location,
Gyuyoung Kim2e954c42021-03-19 14:06:29750 ManifestLocation::kExternalPrefDownload, Extension::NO_FLAGS);
Nicolas Ouellet-Payeur93b74ca1d2020-12-09 23:33:12751 recommended_provider->set_auto_acknowledge(true);
752 provider_list->push_back(std::move(recommended_provider));
binjincccacef2014-10-13 19:00:20753 }
754
Daniel Murphy3657906d2021-04-13 20:33:12755 // In tests don't install pre-installed apps.
[email protected]b9f4fe52012-11-09 21:40:59756 // It would only slowdown tests and make them flaky.
avi3ef9ec9e2014-12-22 22:50:17757 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
Alan Cutterd4c29eee2022-03-28 05:50:03758 ::switches::kDisableDefaultApps)) {
[email protected]b9f4fe52012-11-09 21:40:59759 return;
[email protected]98820ac72019-01-24 19:47:16760 }
[email protected]73e4c362011-09-22 14:47:18761
Xiaohan Wangbe233b62022-01-14 19:15:53762#if !BUILDFLAG(IS_WIN)
[email protected]73e4c362011-09-22 14:47:18763 // On Mac OS, items in /Library/... should be written by the superuser.
764 // Check that all components of the path are writable by root only.
[email protected]5df038b2012-07-16 19:03:27765 ExternalPrefLoader::Options check_admin_permissions_on_mac;
Xiaohan Wangbe233b62022-01-14 19:15:53766#if BUILDFLAG(IS_MAC)
[email protected]0edc55412011-11-07 16:47:33767 check_admin_permissions_on_mac =
Peter Kasting9c68b0f2021-07-27 09:47:40768 ExternalPrefLoader::ENSURE_PATH_CONTROLLED_BY_ADMIN;
[email protected]73e4c362011-09-22 14:47:18769#else
[email protected]5df038b2012-07-16 19:03:27770 check_admin_permissions_on_mac = ExternalPrefLoader::NONE;
[email protected]73e4c362011-09-22 14:47:18771#endif
[email protected]d6f7b102012-05-04 13:59:05772 int bundled_extension_creation_flags = Extension::NO_FLAGS;
Peter Kastingbe940e92014-11-20 23:14:08773#endif
Yuta Hijikata1290fee22020-11-25 09:46:28774#if BUILDFLAG(IS_CHROMEOS_ASH)
[email protected]5861bcd2012-10-16 21:40:19775 bundled_extension_creation_flags = Extension::FROM_WEBSTORE |
776 Extension::WAS_INSTALLED_BY_DEFAULT;
[email protected]a4567732013-07-25 21:01:20777
rkcb526cd6b2014-12-18 16:54:37778 if (!is_chrome_os_public_session) {
[email protected]98820ac72019-01-24 19:47:16779 int pref_load_flags =
ginkagef66fae522015-03-03 16:38:16780 profile->IsNewProfile()
781 ? ExternalPrefLoader::DELAY_LOAD_UNTIL_PRIORITY_SYNC
782 : ExternalPrefLoader::NONE;
[email protected]98820ac72019-01-24 19:47:16783 pref_load_flags |= ExternalPrefLoader::USE_USER_TYPE_PROFILE_FILTER;
784 provider_list->push_back(std::make_unique<ExternalProviderImpl>(
785 service,
Matthew Dentonef83a622019-08-30 02:07:00786 base::MakeRefCounted<ExternalPrefLoader>(
787 chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS, pref_load_flags,
788 profile),
Gyuyoung Kim2e954c42021-03-19 14:06:29789 profile, ManifestLocation::kExternalPref,
790 ManifestLocation::kExternalPrefDownload,
[email protected]98820ac72019-01-24 19:47:16791 bundled_extension_creation_flags));
[email protected]d0b28892014-03-05 18:56:31792
Daniel Murphy3657906d2021-04-13 20:33:12793 // OEM pre-installed apps.
[email protected]acc3c7c22014-03-19 06:23:39794 int oem_extension_creation_flags =
795 bundled_extension_creation_flags | Extension::WAS_INSTALLED_BY_OEM;
Yeunjoo Choicf61fba2021-04-23 02:43:09796 ash::ServicesCustomizationDocument* customization =
797 ash::ServicesCustomizationDocument::GetInstance();
Jinho Bangb5216cec2018-01-17 19:43:11798 provider_list->push_back(std::make_unique<ExternalProviderImpl>(
lazyboyf33109d2016-08-31 00:37:08799 service, customization->CreateExternalLoader(profile), profile,
Gyuyoung Kim2e954c42021-03-19 14:06:29800 ManifestLocation::kExternalPref,
801 ManifestLocation::kExternalPrefDownload, oem_extension_creation_flags));
[email protected]ebb489f2013-09-19 22:08:52802 }
Toni Barzicdff51562018-07-24 19:55:46803
804 // For Chrome OS demo sessions, add pre-installed demo extensions and apps.
Henrique Ferreirod71de902021-05-10 18:57:11805 if (ash::DemoExtensionsExternalLoader::SupportedForProfile(profile)) {
Wenzhao Zang463f1142018-09-05 22:50:50806 base::FilePath cache_dir;
Henrique Ferreirod08abdf2022-01-18 11:35:09807 CHECK(base::PathService::Get(ash::DIR_DEVICE_EXTENSION_LOCAL_CACHE,
Wenzhao Zang463f1142018-09-05 22:50:50808 &cache_dir));
Henrique Ferreirod71de902021-05-10 18:57:11809 auto loader =
810 base::MakeRefCounted<ash::DemoExtensionsExternalLoader>(cache_dir);
Toni Barzicdff51562018-07-24 19:55:46811 std::unique_ptr<ExternalProviderImpl> demo_apps_provider =
812 std::make_unique<ExternalProviderImpl>(
Gyuyoung Kim2e954c42021-03-19 14:06:29813 service, loader, profile, ManifestLocation::kExternalPolicy,
814 ManifestLocation::kExternalPolicyDownload, Extension::NO_FLAGS);
Toni Barzicdff51562018-07-24 19:55:46815 demo_apps_provider->set_auto_acknowledge(true);
816 demo_apps_provider->set_install_immediately(true);
Henrique Ferreirod71de902021-05-10 18:57:11817 ash::DemoSession::Get()->SetExtensionsExternalLoader(loader);
Toni Barzicdff51562018-07-24 19:55:46818 provider_list->push_back(std::move(demo_apps_provider));
819 }
[email protected]5bed2ec32013-08-29 22:55:46820#endif
Dominique Fauteux-Chapleauff3bb352019-10-16 14:32:34821 if (!profile->GetPrefs()->GetBoolean(pref_names::kBlockExternalExtensions)) {
Yuta Hijikata1290fee22020-11-25 09:46:28822// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
823// of lacros-chrome is complete.
Xiaohan Wangbe233b62022-01-14 19:15:53824#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
Taiju Tsuikib1879b72018-09-21 06:22:47825 provider_list->push_back(std::make_unique<ExternalProviderImpl>(
826 service,
Matthew Dentonef83a622019-08-30 02:07:00827 base::MakeRefCounted<ExternalPrefLoader>(
Dominique Fauteux-Chapleauff3bb352019-10-16 14:32:34828 chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS,
829 ExternalPrefLoader::USE_USER_TYPE_PROFILE_FILTER, profile),
Gyuyoung Kim2e954c42021-03-19 14:06:29830 profile, ManifestLocation::kExternalPref,
831 ManifestLocation::kExternalPrefDownload,
Taiju Tsuikib1879b72018-09-21 06:22:47832 bundled_extension_creation_flags));
Dominique Fauteux-Chapleauff3bb352019-10-16 14:32:34833#endif
Xiaohan Wangbe233b62022-01-14 19:15:53834#if BUILDFLAG(IS_WIN)
Toby Huangf93f7002021-01-24 01:08:13835 auto registry_provider = std::make_unique<ExternalProviderImpl>(
836 service, new ExternalRegistryLoader, profile,
Gyuyoung Kim2e954c42021-03-19 14:06:29837 ManifestLocation::kExternalRegistry,
838 ManifestLocation::kExternalPrefDownload, Extension::NO_FLAGS);
Toby Huangf93f7002021-01-24 01:08:13839 registry_provider->set_allow_updates(true);
840 provider_list->push_back(std::move(registry_provider));
Dominique Fauteux-Chapleauff3bb352019-10-16 14:32:34841#else
Toby Huangf93f7002021-01-24 01:08:13842 provider_list->push_back(std::make_unique<ExternalProviderImpl>(
843 service,
844 base::MakeRefCounted<ExternalPrefLoader>(
845 chrome::DIR_EXTERNAL_EXTENSIONS, check_admin_permissions_on_mac,
846 nullptr),
Gyuyoung Kim2e954c42021-03-19 14:06:29847 profile, ManifestLocation::kExternalPref,
848 ManifestLocation::kExternalPrefDownload,
Toby Huangf93f7002021-01-24 01:08:13849 bundled_extension_creation_flags));
[email protected]5bed2ec32013-08-29 22:55:46850
Toby Huangf93f7002021-01-24 01:08:13851 // Define a per-user source of external extensions.
Xiaohan Wangbe233b62022-01-14 19:15:53852#if BUILDFLAG(IS_MAC) || ((BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && \
853 BUILDFLAG(CHROMIUM_BRANDING))
Toby Huangf93f7002021-01-24 01:08:13854 provider_list->push_back(std::make_unique<ExternalProviderImpl>(
855 service,
Matthew Dentonef83a622019-08-30 02:07:00856 base::MakeRefCounted<ExternalPrefLoader>(
Toby Huangf93f7002021-01-24 01:08:13857 chrome::DIR_USER_EXTERNAL_EXTENSIONS, ExternalPrefLoader::NONE,
858 nullptr),
Gyuyoung Kim2e954c42021-03-19 14:06:29859 profile, ManifestLocation::kExternalPref,
860 ManifestLocation::kExternalPrefDownload, Extension::NO_FLAGS));
Toby Huangf93f7002021-01-24 01:08:13861#endif
862#endif
863 }
864
865#if !BUILDFLAG(IS_CHROMEOS_ASH)
Daniel Murphy3657906d2021-04-13 20:33:12866 // The pre-installed apps are installed as INTERNAL but use the external
Toby Huangf93f7002021-01-24 01:08:13867 // extension installer codeflow.
Daniel Murphy3657906d2021-04-13 20:33:12868 provider_list->push_back(std::make_unique<preinstalled_apps::Provider>(
Toby Huangf93f7002021-01-24 01:08:13869 profile, service,
870 base::MakeRefCounted<ExternalPrefLoader>(
871 chrome::DIR_DEFAULT_APPS, ExternalPrefLoader::NONE, nullptr),
Gyuyoung Kim2e954c42021-03-19 14:06:29872 ManifestLocation::kInternal, ManifestLocation::kInternal,
Toby Huangf93f7002021-01-24 01:08:13873 Extension::FROM_WEBSTORE | Extension::WAS_INSTALLED_BY_DEFAULT));
[email protected]98b4aca62011-09-28 01:27:23874#endif
xiyuan65b68ab12015-06-26 19:00:18875
Toby Huangf93f7002021-01-24 01:08:13876 std::unique_ptr<ExternalProviderImpl> drive_migration_provider(
877 new ExternalProviderImpl(
878 service,
879 base::MakeRefCounted<ExtensionMigrator>(
Phillis Tang28427c462021-10-19 20:50:38880 profile, extension_misc::kGoogleDriveAppId,
Toby Huangf93f7002021-01-24 01:08:13881 extension_misc::kDocsOfflineExtensionId),
Gyuyoung Kim2e954c42021-03-19 14:06:29882 profile, ManifestLocation::kExternalPref,
883 ManifestLocation::kExternalPrefDownload,
Toby Huangf93f7002021-01-24 01:08:13884 Extension::FROM_WEBSTORE | Extension::WAS_INSTALLED_BY_DEFAULT));
885 drive_migration_provider->set_auto_acknowledge(true);
886 provider_list->push_back(std::move(drive_migration_provider));
treibcc82ab82015-03-02 09:41:49887
Jinho Bangb5216cec2018-01-17 19:43:11888 provider_list->push_back(std::make_unique<ExternalProviderImpl>(
Matthew Dentonef83a622019-08-30 02:07:00889 service, base::MakeRefCounted<ExternalComponentLoader>(profile), profile,
Gyuyoung Kim2e954c42021-03-19 14:06:29890 ManifestLocation::kInvalidLocation, ManifestLocation::kExternalComponent,
lazyboyf33109d2016-08-31 00:37:08891 Extension::FROM_WEBSTORE | Extension::WAS_INSTALLED_BY_DEFAULT));
[email protected]8e4560b62011-01-14 10:09:14892}
[email protected]5df038b2012-07-16 19:03:27893
894} // namespace extensions