blob: 065734538e3b2d3afa034e124c8b6ab42663b447 [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)
Henrique Ferreiro37770262021-02-06 01:20:5356#include "ash/constants/ash_paths.h"
Wenzhao Zang463f1142018-09-05 22:50:5057#include "base/path_service.h"
Henrique Ferreiro53d4dc42021-01-27 01:02:3858#include "chrome/browser/ash/app_mode/kiosk_app_external_loader.h"
Yeunjoo Choi91907642021-04-16 13:18:1959#include "chrome/browser/ash/customization/customization_document.h"
Henrique Ferreiro606669a2021-02-24 13:36:5560#include "chrome/browser/ash/login/demo_mode/demo_extensions_external_loader.h"
61#include "chrome/browser/ash/login/demo_mode/demo_session.h"
Yeunjoo Choi7227dba2021-08-04 06:35:4762#include "chrome/browser/ash/policy/core/browser_policy_connector_ash.h"
Yeunjoo Choi8623e4a2021-07-02 01:57:0663#include "chrome/browser/ash/policy/core/device_local_account.h"
64#include "chrome/browser/ash/policy/core/device_local_account_policy_service.h"
Yeunjoo Choi15ab1ac2021-02-04 17:15:0765#include "chrome/browser/ash/profiles/profile_helper.h"
[email protected]af984882013-10-21 21:08:5166#include "chrome/browser/chromeos/extensions/device_local_account_external_policy_loader.h"
Maksim Ivanov8738d332020-01-07 22:19:0167#include "chrome/browser/chromeos/extensions/signin_screen_extensions_external_loader.h"
Ahmed Fakhry9ef29e042017-09-01 16:32:0068#include "components/arc/arc_util.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
Daniel Murphy3657906d2021-04-13 20:33:1287// Certain pre-installed extensions are no longer needed on ARC devices as they
88// were replaced by their ARC counterparts.
Ahmed Fakhry9ef29e042017-09-01 16:32:0089bool ShouldUninstallExtensionReplacedByArcApp(const std::string& extension_id) {
Alex Newcomerf8c542f2018-08-13 23:48:5090 if (!arc::IsArcAvailable())
Ahmed Fakhry9ef29e042017-09-01 16:32:0091 return false;
92
93 if (extension_id == extension_misc::kGooglePlayBooksAppId ||
94 extension_id == extension_misc::kGooglePlayMoviesAppId ||
95 extension_id == extension_misc::kGooglePlayMusicAppId) {
96 return true;
97 }
98
99 return false;
100}
101
Yuta Hijikata1290fee22020-11-25 09:46:28102#endif // BUILDFLAG(IS_CHROMEOS_ASH)
Ahmed Fakhry9ef29e042017-09-01 16:32:00103
104} // namespace
105
[email protected]8e4560b62011-01-14 10:09:14106// Constants for keeping track of extension preferences in a dictionary.
[email protected]d8fd0fd2014-03-24 13:16:06107const char ExternalProviderImpl::kInstallParam[] = "install_parameter";
[email protected]5df038b2012-07-16 19:03:27108const char ExternalProviderImpl::kExternalCrx[] = "external_crx";
[email protected]7425d7df2012-11-28 14:35:42109const char ExternalProviderImpl::kExternalVersion[] = "external_version";
110const char ExternalProviderImpl::kExternalUpdateUrl[] = "external_update_url";
[email protected]7425d7df2012-11-28 14:35:42111const char ExternalProviderImpl::kIsBookmarkApp[] = "is_bookmark_app";
112const char ExternalProviderImpl::kIsFromWebstore[] = "is_from_webstore";
[email protected]19eac6d2013-05-30 06:51:03113const char ExternalProviderImpl::kKeepIfPresent[] = "keep_if_present";
[email protected]bf9fd5ae2014-04-09 22:50:06114const char ExternalProviderImpl::kWasInstalledByOem[] = "was_installed_by_oem";
Alan Cutterb81d0e02020-08-05 09:10:34115const char ExternalProviderImpl::kWebAppMigrationFlag[] =
116 "web_app_migration_flag";
[email protected]bf9fd5ae2014-04-09 22:50:06117const char ExternalProviderImpl::kSupportedLocales[] = "supported_locales";
[email protected]2b6a5802014-08-16 07:58:08118const char ExternalProviderImpl::kMayBeUntrusted[] = "may_be_untrusted";
dpolukhin2c6ef2932015-05-12 16:06:13119const char ExternalProviderImpl::kMinProfileCreatedByVersion[] =
120 "min_profile_created_by_version";
dpolukhin1687ef32015-06-22 11:12:37121const char ExternalProviderImpl::kDoNotInstallForEnterprise[] =
122 "do_not_install_for_enterprise";
[email protected]8e4560b62011-01-14 10:09:14123
[email protected]af984882013-10-21 21:08:51124ExternalProviderImpl::ExternalProviderImpl(
125 VisitorInterface* service,
126 const scoped_refptr<ExternalLoader>& loader,
127 Profile* profile,
Gyuyoung Kim2e954c42021-03-19 14:06:29128 ManifestLocation crx_location,
129 ManifestLocation download_location,
[email protected]af984882013-10-21 21:08:51130 int creation_flags)
[email protected]4b4c0132013-06-12 17:58:55131 : crx_location_(crx_location),
132 download_location_(download_location),
133 service_(service),
[email protected]4b4c0132013-06-12 17:58:55134 loader_(loader),
135 profile_(profile),
Toni Barzic87026682018-01-08 23:21:04136 creation_flags_(creation_flags) {
Oleg Davydov66246bd92019-09-26 16:31:51137 DCHECK(profile_);
[email protected]8e4560b62011-01-14 10:09:14138 loader_->Init(this);
139}
140
[email protected]5df038b2012-07-16 19:03:27141ExternalProviderImpl::~ExternalProviderImpl() {
Istiaque Ahmedf6e72622017-09-08 23:14:17142 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]8e4560b62011-01-14 10:09:14143 loader_->OwnerShutdown();
144}
145
[email protected]5df038b2012-07-16 19:03:27146void ExternalProviderImpl::VisitRegisteredExtension() {
[email protected]8e4560b62011-01-14 10:09:14147 // The loader will call back to SetPrefs.
148 loader_->StartLoading();
149}
150
Anina Koehler100794e22021-09-08 13:09:52151void ExternalProviderImpl::SetPrefs(
152 std::unique_ptr<base::DictionaryValue> prefs) {
Istiaque Ahmedf6e72622017-09-08 23:14:17153 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]8e4560b62011-01-14 10:09:14154
[email protected]47fc70c2011-12-06 07:29:51155 // Check if the service is still alive. It is possible that it went
[email protected]8e4560b62011-01-14 10:09:14156 // away while |loader_| was working on the FILE thread.
157 if (!service_) return;
158
Oleg Davydovdec175a2020-05-25 16:44:29159 InstallStageTracker* install_stage_tracker =
160 InstallStageTracker::Get(profile_);
Peter Kasting7c683fe2021-06-24 15:12:10161 for (auto it : prefs->DictItems()) {
Swapnil5e0e0dc2020-09-21 14:59:47162 install_stage_tracker->ReportInstallCreationStage(
163 it.first,
164 InstallStageTracker::InstallCreationStage::SEEN_BY_EXTERNAL_PROVIDER);
Oleg Davydov52db8742019-08-20 09:14:40165 }
166
Istiaque Ahmeda7431b32017-08-20 18:33:37167 prefs_ = std::move(prefs);
[email protected]8a839a02013-03-07 05:23:33168 ready_ = true; // Queries for extensions are allowed from this point.
[email protected]8e4560b62011-01-14 10:09:14169
Maria Petrisordba7ac42021-10-06 09:01:30170 NotifyServiceOnExternalExtensionsFound(/*is_initial_load=*/true);
171 service_->OnExternalProviderReady(this);
172}
173
174void ExternalProviderImpl::TriggerOnExternalExtensionFound() {
175 DCHECK_CURRENTLY_ON(BrowserThread::UI);
176
177 // Check if the service is still alive. It is possible that it went
178 // away while |loader_| was working on the FILE thread. The prefs can be
179 // missing if SetPrefs() was not called yet.
180 if (!service_ || !prefs_)
181 return;
182
183 NotifyServiceOnExternalExtensionsFound(/*is_initial_load=*/false);
184}
185
186void ExternalProviderImpl::NotifyServiceOnExternalExtensionsFound(
187 bool is_initial_load) {
Devlin Cronin19f70b6a2017-10-01 04:14:05188 std::vector<ExternalInstallInfoUpdateUrl> external_update_url_extensions;
189 std::vector<ExternalInstallInfoFile> external_file_extensions;
lazyboye8634172016-01-28 00:10:48190
191 RetrieveExtensionsFromPrefs(&external_update_url_extensions,
192 &external_file_extensions);
lazyboy4aeef202016-09-07 21:28:59193 for (const auto& extension : external_update_url_extensions)
Maria Petrisordba7ac42021-10-06 09:01:30194 service_->OnExternalExtensionUpdateUrlFound(extension, is_initial_load);
lazyboye8634172016-01-28 00:10:48195
lazyboy4aeef202016-09-07 21:28:59196 for (const auto& extension : external_file_extensions)
Devlin Cronin19f70b6a2017-10-01 04:14:05197 service_->OnExternalExtensionFileFound(extension);
lazyboye8634172016-01-28 00:10:48198}
199
Anina Koehler100794e22021-09-08 13:09:52200void ExternalProviderImpl::UpdatePrefs(
201 std::unique_ptr<base::DictionaryValue> prefs) {
Istiaque Ahmedf6e72622017-09-08 23:14:17202 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Toni Barzic87026682018-01-08 23:21:04203 CHECK(allow_updates_);
lazyboye8634172016-01-28 00:10:48204
205 // Check if the service is still alive. It is possible that it went
206 // away while |loader_| was working on the FILE thread.
207 if (!service_)
208 return;
209
210 std::set<std::string> removed_extensions;
211 // Find extensions that were removed by this ExternalProvider.
Anina Koehler100794e22021-09-08 13:09:52212 for (base::DictionaryValue::Iterator i(*prefs_); !i.IsAtEnd(); i.Advance()) {
213 const std::string& extension_id = i.key();
lazyboye8634172016-01-28 00:10:48214 // Don't bother about invalid ids.
215 if (!crx_file::id_util::IdIsValid(extension_id))
216 continue;
Anina Koehler100794e22021-09-08 13:09:52217 if (!prefs->HasKey(extension_id))
lazyboye8634172016-01-28 00:10:48218 removed_extensions.insert(extension_id);
219 }
220
Istiaque Ahmeda7431b32017-08-20 18:33:37221 prefs_ = std::move(prefs);
lazyboye8634172016-01-28 00:10:48222
Devlin Cronin19f70b6a2017-10-01 04:14:05223 std::vector<ExternalInstallInfoUpdateUrl> external_update_url_extensions;
224 std::vector<ExternalInstallInfoFile> external_file_extensions;
lazyboye8634172016-01-28 00:10:48225 RetrieveExtensionsFromPrefs(&external_update_url_extensions,
226 &external_file_extensions);
227
228 // Notify ExtensionService about completion of finding incremental updates
229 // from this provider.
230 // Provide the list of added and removed extensions.
231 service_->OnExternalProviderUpdateComplete(
232 this, external_update_url_extensions, external_file_extensions,
233 removed_extensions);
234}
235
236void ExternalProviderImpl::RetrieveExtensionsFromPrefs(
Devlin Cronin19f70b6a2017-10-01 04:14:05237 std::vector<ExternalInstallInfoUpdateUrl>* external_update_url_extensions,
238 std::vector<ExternalInstallInfoFile>* external_file_extensions) {
[email protected]9d32ded072011-10-11 16:31:05239 // Set of unsupported extensions that need to be deleted from prefs_.
240 std::set<std::string> unsupported_extensions;
Oleg Davydovdec175a2020-05-25 16:44:29241 InstallStageTracker* install_stage_tracker =
242 InstallStageTracker::Get(profile_);
[email protected]9d32ded072011-10-11 16:31:05243
lazyboye8634172016-01-28 00:10:48244 // Discover all the extensions this provider has.
Anina Koehler100794e22021-09-08 13:09:52245 for (base::DictionaryValue::Iterator i(*prefs_); !i.IsAtEnd(); i.Advance()) {
246 const std::string& extension_id = i.key();
Peter Kasting42e82e92021-09-15 16:39:17247 const base::DictionaryValue* extension_dict = nullptr;
[email protected]ab22ba42011-01-14 16:36:38248
Yuta Hijikata1290fee22020-11-25 09:46:28249#if BUILDFLAG(IS_CHROMEOS_ASH)
Swapnil5eca0412021-02-12 08:32:54250 if (extension_id == extension_misc::kCameraAppId) {
251 unsupported_extensions.insert(extension_id);
252 install_stage_tracker->ReportFailure(
253 extension_id,
254 InstallStageTracker::FailureReason::REPLACED_BY_SYSTEM_APP);
255 continue;
256 }
257
Ahmed Fakhry9ef29e042017-09-01 16:32:00258 if (ShouldUninstallExtensionReplacedByArcApp(extension_id)) {
259 VLOG(1) << "Extension with key: " << extension_id << " was replaced "
260 << "by a default ARC app, and will be uninstalled.";
261 unsupported_extensions.emplace(extension_id);
Oleg Davydovdec175a2020-05-25 16:44:29262 install_stage_tracker->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51263 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29264 InstallStageTracker::FailureReason::REPLACED_BY_ARC_APP);
Ahmed Fakhry9ef29e042017-09-01 16:32:00265 continue;
266 }
Yuta Hijikata1290fee22020-11-25 09:46:28267#endif // BUILDFLAG(IS_CHROMEOS_ASH)
Ahmed Fakhry9ef29e042017-09-01 16:32:00268
[email protected]fdd28372014-08-21 02:27:26269 if (!crx_file::id_util::IdIsValid(extension_id)) {
[email protected]ab22ba42011-01-14 16:36:38270 LOG(WARNING) << "Malformed extension dictionary: key "
271 << extension_id.c_str() << " is not a valid id.";
Oleg Davydovdec175a2020-05-25 16:44:29272 install_stage_tracker->ReportFailure(
273 extension_id, InstallStageTracker::FailureReason::INVALID_ID);
[email protected]8e4560b62011-01-14 10:09:14274 continue;
[email protected]ab22ba42011-01-14 16:36:38275 }
276
Peter Kasting42e82e92021-09-15 16:39:17277 if (!i.value().GetAsDictionary(&extension_dict)) {
[email protected]ab22ba42011-01-14 16:36:38278 LOG(WARNING) << "Malformed extension dictionary: key "
279 << extension_id.c_str()
280 << " has a value that is not a dictionary.";
Oleg Davydovdec175a2020-05-25 16:44:29281 install_stage_tracker->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51282 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29283 InstallStageTracker::FailureReason::MALFORMED_EXTENSION_DICT);
[email protected]ab22ba42011-01-14 16:36:38284 continue;
285 }
[email protected]8e4560b62011-01-14 10:09:14286
Anina Koehler100794e22021-09-08 13:09:52287 std::string external_crx;
288 const base::Value* external_version_value = nullptr;
[email protected]8e4560b62011-01-14 10:09:14289 std::string external_version;
Anina Koehler100794e22021-09-08 13:09:52290 std::string external_update_url;
291
Peter Kasting42e82e92021-09-15 16:39:17292 bool has_external_crx =
293 extension_dict->GetString(kExternalCrx, &external_crx);
Anina Koehler100794e22021-09-08 13:09:52294
[email protected]0d461c52012-07-03 19:29:41295 bool has_external_version = false;
Peter Kasting42e82e92021-09-15 16:39:17296 if (extension_dict->Get(kExternalVersion, &external_version_value)) {
jdoerrie1f536b22017-10-23 17:15:11297 if (external_version_value->is_string()) {
Alex Rudenkoa4d75ab52021-07-09 15:39:44298 external_version = external_version_value->GetString();
[email protected]0d461c52012-07-03 19:29:41299 has_external_version = true;
300 } else {
Oleg Davydovdec175a2020-05-25 16:44:29301 install_stage_tracker->ReportFailure(
302 extension_id, InstallStageTracker::FailureReason::
Oleg Davydov66246bd92019-09-26 16:31:51303 MALFORMED_EXTENSION_DICT_VERSION);
[email protected]0d461c52012-07-03 19:29:41304 LOG(WARNING) << "Malformed extension dictionary for extension: "
305 << extension_id.c_str() << ". " << kExternalVersion
306 << " value must be a string.";
307 continue;
308 }
309 }
310
Peter Kasting42e82e92021-09-15 16:39:17311 bool has_external_update_url =
312 extension_dict->GetString(kExternalUpdateUrl, &external_update_url);
[email protected]8e4560b62011-01-14 10:09:14313 if (has_external_crx != has_external_version) {
Oleg Davydovdec175a2020-05-25 16:44:29314 install_stage_tracker->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51315 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29316 InstallStageTracker::FailureReason::MALFORMED_EXTENSION_DICT);
[email protected]8e4560b62011-01-14 10:09:14317 LOG(WARNING) << "Malformed extension dictionary for extension: "
318 << extension_id.c_str() << ". " << kExternalCrx
319 << " and " << kExternalVersion << " must be used together.";
320 continue;
321 }
322
323 if (has_external_crx == has_external_update_url) {
Oleg Davydovdec175a2020-05-25 16:44:29324 install_stage_tracker->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51325 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29326 InstallStageTracker::FailureReason::MALFORMED_EXTENSION_DICT);
[email protected]8e4560b62011-01-14 10:09:14327 LOG(WARNING) << "Malformed extension dictionary for extension: "
328 << extension_id.c_str() << ". Exactly one of the "
Anina Koehler100794e22021-09-08 13:09:52329 << "followng keys should be used: " << kExternalCrx
330 << ", " << kExternalUpdateUrl << ".";
[email protected]8e4560b62011-01-14 10:09:14331 continue;
332 }
333
[email protected]9d32ded072011-10-11 16:31:05334 // Check that extension supports current browser locale.
Anina Koehler100794e22021-09-08 13:09:52335 const base::ListValue* supported_locales = nullptr;
Peter Kasting42e82e92021-09-15 16:39:17336 if (extension_dict->GetList(kSupportedLocales, &supported_locales)) {
[email protected]9d32ded072011-10-11 16:31:05337 std::vector<std::string> browser_locales;
338 l10n_util::GetParentLocales(g_browser_process->GetApplicationLocale(),
339 &browser_locales);
340
Clark DuVallf01846a2021-09-02 02:21:47341 size_t num_locales = supported_locales->GetList().size();
[email protected]9d32ded072011-10-11 16:31:05342 bool locale_supported = false;
343 for (size_t j = 0; j < num_locales; j++) {
Anina Koehler100794e22021-09-08 13:09:52344 std::string current_locale;
345 if (supported_locales->GetString(j, &current_locale) &&
[email protected]9d32ded072011-10-11 16:31:05346 l10n_util::IsValidLocaleSyntax(current_locale)) {
347 current_locale = l10n_util::NormalizeLocale(current_locale);
Jan Wilken Dörrieade79222019-06-06 19:01:12348 if (base::Contains(browser_locales, current_locale)) {
[email protected]9d32ded072011-10-11 16:31:05349 locale_supported = true;
350 break;
351 }
352 } else {
353 LOG(WARNING) << "Unrecognized locale '" << current_locale
354 << "' found as supported locale for extension: "
355 << extension_id;
356 }
357 }
358
359 if (!locale_supported) {
360 unsupported_extensions.insert(extension_id);
Oleg Davydovdec175a2020-05-25 16:44:29361 install_stage_tracker->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51362 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29363 InstallStageTracker::FailureReason::LOCALE_NOT_SUPPORTED);
[email protected]19eac6d2013-05-30 06:51:03364 VLOG(1) << "Skip installing (or uninstall) external extension: "
365 << extension_id << " because the extension doesn't support "
366 << "the browser locale.";
[email protected]9d32ded072011-10-11 16:31:05367 continue;
368 }
369 }
370
[email protected]f121003b2012-05-04 21:57:47371 int creation_flags = creation_flags_;
Anina Koehler100794e22021-09-08 13:09:52372 bool is_bookmark_app;
Peter Kasting42e82e92021-09-15 16:39:17373 if (extension_dict->GetBoolean(kIsBookmarkApp, &is_bookmark_app) &&
Anina Koehler100794e22021-09-08 13:09:52374 is_bookmark_app) {
[email protected]f121003b2012-05-04 21:57:47375 creation_flags |= Extension::FROM_BOOKMARK;
376 }
Anina Koehler100794e22021-09-08 13:09:52377 bool is_from_webstore = false;
Peter Kasting42e82e92021-09-15 16:39:17378 if (extension_dict->GetBoolean(kIsFromWebstore, &is_from_webstore) &&
Anina Koehler100794e22021-09-08 13:09:52379 is_from_webstore) {
[email protected]7425d7df2012-11-28 14:35:42380 creation_flags |= Extension::FROM_WEBSTORE;
381 }
Alan Cutterb81d0e02020-08-05 09:10:34382
383 // If the extension is in a web app migration treat it as "keep_if_present"
384 // so it can get uninstalled by WebAppUiManager::UninstallAndReplace() once
385 // the replacement web app has installed and migrated over user preferences.
386 // TODO(crbug.com/1099150): Remove this field after migration is complete.
387 const std::string* web_app_migration_flag =
Peter Kasting42e82e92021-09-15 16:39:17388 extension_dict->FindStringPath(kWebAppMigrationFlag);
Alan Cutterb81d0e02020-08-05 09:10:34389 bool is_migrating_to_web_app =
390 web_app_migration_flag &&
Alan Cutter52914e72021-05-05 09:35:48391 web_app::IsPreinstalledAppInstallFeatureEnabled(*web_app_migration_flag,
392 *profile_);
Alan Cutterb81d0e02020-08-05 09:10:34393 bool keep_if_present =
Peter Kasting42e82e92021-09-15 16:39:17394 extension_dict->FindBoolPath(kKeepIfPresent).value_or(false);
Alan Cutterb81d0e02020-08-05 09:10:34395 if (keep_if_present || is_migrating_to_web_app) {
David Bertoni58c113a2019-08-02 19:53:26396 ExtensionRegistry* extension_registry = ExtensionRegistry::Get(profile_);
397 const Extension* extension =
David Bertonia0b34722019-09-30 20:51:26398 extension_registry ? extension_registry->GetExtensionById(
399 extension_id, ExtensionRegistry::EVERYTHING)
400 : nullptr;
[email protected]19eac6d2013-05-30 06:51:03401 if (!extension) {
dpolukhin2c6ef2932015-05-12 16:06:13402 unsupported_extensions.insert(extension_id);
Oleg Davydovdec175a2020-05-25 16:44:29403 install_stage_tracker->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51404 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29405 InstallStageTracker::FailureReason::NOT_PERFORMING_NEW_INSTALL);
[email protected]19eac6d2013-05-30 06:51:03406 VLOG(1) << "Skip installing (or uninstall) external extension: "
407 << extension_id << " because the extension should be kept "
408 << "only if it is already installed.";
409 continue;
410 }
411 }
Alan Cutterb81d0e02020-08-05 09:10:34412
Anina Koehler100794e22021-09-08 13:09:52413 bool was_installed_by_oem = false;
Peter Kasting42e82e92021-09-15 16:39:17414 if (extension_dict->GetBoolean(kWasInstalledByOem, &was_installed_by_oem) &&
Anina Koehler100794e22021-09-08 13:09:52415 was_installed_by_oem) {
dpolukhind0be494a2015-05-28 09:43:17416 creation_flags |= Extension::WAS_INSTALLED_BY_OEM;
417 }
Anina Koehler100794e22021-09-08 13:09:52418 bool may_be_untrusted = false;
Peter Kasting42e82e92021-09-15 16:39:17419 if (extension_dict->GetBoolean(kMayBeUntrusted, &may_be_untrusted) &&
Anina Koehler100794e22021-09-08 13:09:52420 may_be_untrusted) {
[email protected]2b6a5802014-08-16 07:58:08421 creation_flags |= Extension::MAY_BE_UNTRUSTED;
422 }
[email protected]f121003b2012-05-04 21:57:47423
Peter Kasting42e82e92021-09-15 16:39:17424 if (!HandleMinProfileVersion(extension_dict, extension_id,
dpolukhin1687ef32015-06-22 11:12:37425 &unsupported_extensions)) {
dpolukhin2c6ef2932015-05-12 16:06:13426 continue;
dpolukhin1687ef32015-06-22 11:12:37427 }
428
Peter Kasting42e82e92021-09-15 16:39:17429 if (!HandleDoNotInstallForEnterprise(extension_dict, extension_id,
dpolukhin1687ef32015-06-22 11:12:37430 &unsupported_extensions)) {
431 continue;
432 }
dpolukhin2c6ef2932015-05-12 16:06:13433
Anina Koehler100794e22021-09-08 13:09:52434 std::string install_parameter;
Peter Kasting42e82e92021-09-15 16:39:17435 extension_dict->GetString(kInstallParam, &install_parameter);
[email protected]d8fd0fd2014-03-24 13:16:06436
[email protected]8e4560b62011-01-14 10:09:14437 if (has_external_crx) {
Gyuyoung Kim2e954c42021-03-19 14:06:29438 if (crx_location_ == ManifestLocation::kInvalidLocation) {
Oleg Davydovdec175a2020-05-25 16:44:29439 install_stage_tracker->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51440 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29441 InstallStageTracker::FailureReason::NOT_SUPPORTED_EXTENSION_DICT);
[email protected]8e4560b62011-01-14 10:09:14442 LOG(WARNING) << "This provider does not support installing external "
443 << "extensions from crx files.";
444 continue;
445 }
Peter Kasting141279b2021-02-09 22:34:20446
Anina Koehler100794e22021-09-08 13:09:52447 base::FilePath path = base::FilePath::FromUTF8Unsafe(external_crx);
Peter Kasting141279b2021-02-09 22:34:20448 if (path.value().find(base::FilePath::kParentDirectory) !=
[email protected]8e4560b62011-01-14 10:09:14449 base::StringPiece::npos) {
Oleg Davydovdec175a2020-05-25 16:44:29450 install_stage_tracker->ReportFailure(
451 extension_id, InstallStageTracker::FailureReason::
Oleg Davydov66246bd92019-09-26 16:31:51452 MALFORMED_EXTENSION_DICT_FILE_PATH);
[email protected]8e4560b62011-01-14 10:09:14453 LOG(WARNING) << "Path traversal not allowed in path: "
Anina Koehler100794e22021-09-08 13:09:52454 << external_crx.c_str();
[email protected]8e4560b62011-01-14 10:09:14455 continue;
456 }
457
[email protected]f0841cd2011-01-19 15:07:24458 // If the path is relative, and the provider has a base path,
459 // build the absolute path to the crx file.
Peter Kasting141279b2021-02-09 22:34:20460
[email protected]8e4560b62011-01-14 10:09:14461 if (!path.IsAbsolute()) {
[email protected]650b2d52013-02-10 03:41:45462 base::FilePath base_path = loader_->GetBaseCrxFilePath();
[email protected]f0841cd2011-01-19 15:07:24463 if (base_path.empty()) {
Oleg Davydovdec175a2020-05-25 16:44:29464 install_stage_tracker->ReportFailure(
465 extension_id, InstallStageTracker::FailureReason::
Oleg Davydov66246bd92019-09-26 16:31:51466 MALFORMED_EXTENSION_DICT_FILE_PATH);
Anina Koehler100794e22021-09-08 13:09:52467 LOG(WARNING) << "File path " << external_crx.c_str()
[email protected]f0841cd2011-01-19 15:07:24468 << " is relative. An absolute path is required.";
469 continue;
470 }
Peter Kasting141279b2021-02-09 22:34:20471 path = base_path.Append(path);
[email protected]8e4560b62011-01-14 10:09:14472 }
473
Devlin Cronind4c2a8f32017-09-29 17:08:30474 base::Version version(external_version);
475 if (!version.IsValid()) {
Oleg Davydovdec175a2020-05-25 16:44:29476 install_stage_tracker->ReportFailure(
477 extension_id, InstallStageTracker::FailureReason::
Oleg Davydov66246bd92019-09-26 16:31:51478 MALFORMED_EXTENSION_DICT_VERSION);
[email protected]8e4560b62011-01-14 10:09:14479 LOG(WARNING) << "Malformed extension dictionary for extension: "
480 << extension_id.c_str() << ". Invalid version string \""
481 << external_version << "\".";
482 continue;
483 }
Devlin Cronin19f70b6a2017-10-01 04:14:05484 external_file_extensions->emplace_back(
485 extension_id, version, path, crx_location_, creation_flags,
486 auto_acknowledge_, install_immediately_);
[email protected]8a839a02013-03-07 05:23:33487 } else { // if (has_external_update_url)
[email protected]8e4560b62011-01-14 10:09:14488 CHECK(has_external_update_url); // Checking of keys above ensures this.
Gyuyoung Kim2e954c42021-03-19 14:06:29489 if (download_location_ == ManifestLocation::kInvalidLocation) {
Oleg Davydovdec175a2020-05-25 16:44:29490 install_stage_tracker->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51491 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29492 InstallStageTracker::FailureReason::NOT_SUPPORTED_EXTENSION_DICT);
[email protected]8e4560b62011-01-14 10:09:14493 LOG(WARNING) << "This provider does not support installing external "
494 << "extensions from update URLs.";
495 continue;
496 }
Anina Koehler100794e22021-09-08 13:09:52497 GURL update_url(external_update_url);
Devlin Cronind4c2a8f32017-09-29 17:08:30498 if (!update_url.is_valid()) {
Oleg Davydovdec175a2020-05-25 16:44:29499 install_stage_tracker->ReportFailure(
500 extension_id, InstallStageTracker::FailureReason::
Oleg Davydov66246bd92019-09-26 16:31:51501 MALFORMED_EXTENSION_DICT_UPDATE_URL);
[email protected]8e4560b62011-01-14 10:09:14502 LOG(WARNING) << "Malformed extension dictionary for extension: "
[email protected]ab22ba42011-01-14 16:36:38503 << extension_id.c_str() << ". Key " << kExternalUpdateUrl
504 << " has value \"" << external_update_url
505 << "\", which is not a valid URL.";
[email protected]8e4560b62011-01-14 10:09:14506 continue;
507 }
Devlin Cronin19f70b6a2017-10-01 04:14:05508 external_update_url_extensions->emplace_back(
Anina Koehler100794e22021-09-08 13:09:52509 extension_id, install_parameter, std::move(update_url),
Devlin Cronin19f70b6a2017-10-01 04:14:05510 download_location_, creation_flags, auto_acknowledge_);
[email protected]8e4560b62011-01-14 10:09:14511 }
512 }
513
jdoerrie13cd648c82018-10-02 21:21:02514 for (auto it = unsupported_extensions.begin();
[email protected]9d32ded072011-10-11 16:31:05515 it != unsupported_extensions.end(); ++it) {
516 // Remove extension for the list of know external extensions. The extension
517 // will be uninstalled later because provider doesn't provide it anymore.
Song Fangzhencdbb7062021-07-07 11:13:53518 prefs_->RemoveKey(*it);
[email protected]9d32ded072011-10-11 16:31:05519 }
[email protected]8e4560b62011-01-14 10:09:14520}
521
[email protected]5df038b2012-07-16 19:03:27522void ExternalProviderImpl::ServiceShutdown() {
Bartek Nowierski3253b672020-06-01 20:37:12523 service_ = nullptr;
[email protected]8e4560b62011-01-14 10:09:14524}
525
[email protected]5df038b2012-07-16 19:03:27526bool ExternalProviderImpl::IsReady() const {
[email protected]8e4560b62011-01-14 10:09:14527 return ready_;
528}
529
[email protected]5df038b2012-07-16 19:03:27530bool ExternalProviderImpl::HasExtension(
[email protected]8e4560b62011-01-14 10:09:14531 const std::string& id) const {
Istiaque Ahmedf6e72622017-09-08 23:14:17532 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]8e4560b62011-01-14 10:09:14533 CHECK(prefs_.get());
534 CHECK(ready_);
Anina Koehler100794e22021-09-08 13:09:52535 return prefs_->HasKey(id);
[email protected]8e4560b62011-01-14 10:09:14536}
537
[email protected]5df038b2012-07-16 19:03:27538bool ExternalProviderImpl::GetExtensionDetails(
dchengc963c7142016-04-08 03:55:22539 const std::string& id,
Gyuyoung Kim2e954c42021-03-19 14:06:29540 ManifestLocation* location,
pwnallcbd73192016-08-22 18:59:17541 std::unique_ptr<base::Version>* version) const {
Istiaque Ahmedf6e72622017-09-08 23:14:17542 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]8e4560b62011-01-14 10:09:14543 CHECK(prefs_.get());
544 CHECK(ready_);
Anina Koehler100794e22021-09-08 13:09:52545 base::DictionaryValue* extension = nullptr;
546 if (!prefs_->GetDictionary(id, &extension))
[email protected]8e4560b62011-01-14 10:09:14547 return false;
548
Gyuyoung Kim2e954c42021-03-19 14:06:29549 ManifestLocation loc = ManifestLocation::kInvalidLocation;
Anina Koehler100794e22021-09-08 13:09:52550 if (extension->HasKey(kExternalUpdateUrl)) {
[email protected]8e4560b62011-01-14 10:09:14551 loc = download_location_;
552
Anina Koehler100794e22021-09-08 13:09:52553 } else if (extension->HasKey(kExternalCrx)) {
[email protected]8e4560b62011-01-14 10:09:14554 loc = crx_location_;
555
Anina Koehler100794e22021-09-08 13:09:52556 std::string external_version;
557 if (!extension->GetString(kExternalVersion, &external_version))
[email protected]8e4560b62011-01-14 10:09:14558 return false;
559
560 if (version)
Anina Koehler100794e22021-09-08 13:09:52561 *version = std::make_unique<base::Version>(external_version);
[email protected]8e4560b62011-01-14 10:09:14562
563 } else {
564 NOTREACHED(); // Chrome should not allow prefs to get into this state.
565 return false;
566 }
567
568 if (location)
569 *location = loc;
570
571 return true;
572}
573
dpolukhin2c6ef2932015-05-12 16:06:13574bool ExternalProviderImpl::HandleMinProfileVersion(
Anina Koehler100794e22021-09-08 13:09:52575 const base::DictionaryValue* extension,
dpolukhin2c6ef2932015-05-12 16:06:13576 const std::string& extension_id,
577 std::set<std::string>* unsupported_extensions) {
Anina Koehler100794e22021-09-08 13:09:52578 std::string min_profile_created_by_version;
579 if (extension->GetString(kMinProfileCreatedByVersion,
580 &min_profile_created_by_version)) {
pwnallcbd73192016-08-22 18:59:17581 base::Version profile_version(
dpolukhin2c6ef2932015-05-12 16:06:13582 profile_->GetPrefs()->GetString(prefs::kProfileCreatedByVersion));
Anina Koehler100794e22021-09-08 13:09:52583 base::Version min_version(min_profile_created_by_version);
dpolukhin2c6ef2932015-05-12 16:06:13584 if (min_version.IsValid() && profile_version.CompareTo(min_version) < 0) {
585 unsupported_extensions->insert(extension_id);
Oleg Davydovdec175a2020-05-25 16:44:29586 InstallStageTracker::Get(profile_)->ReportFailure(
587 extension_id, InstallStageTracker::FailureReason::TOO_OLD_PROFILE);
dpolukhin2c6ef2932015-05-12 16:06:13588 VLOG(1) << "Skip installing (or uninstall) external extension: "
589 << extension_id
590 << " profile.created_by_version: " << profile_version.GetString()
591 << " min_profile_created_by_version: "
592 << min_profile_created_by_version;
593 return false;
594 }
595 }
596 return true;
597}
598
dpolukhin1687ef32015-06-22 11:12:37599bool ExternalProviderImpl::HandleDoNotInstallForEnterprise(
Anina Koehler100794e22021-09-08 13:09:52600 const base::DictionaryValue* extension,
dpolukhin1687ef32015-06-22 11:12:37601 const std::string& extension_id,
602 std::set<std::string>* unsupported_extensions) {
Anina Koehler100794e22021-09-08 13:09:52603 bool do_not_install_for_enterprise = false;
604 if (extension->GetBoolean(kDoNotInstallForEnterprise,
605 &do_not_install_for_enterprise) &&
606 do_not_install_for_enterprise) {
dpolukhin1687ef32015-06-22 11:12:37607 const policy::ProfilePolicyConnector* const connector =
Xi Hanfe39afc62019-04-29 14:50:14608 profile_->GetProfilePolicyConnector();
dpolukhin1687ef32015-06-22 11:12:37609 if (connector->IsManaged()) {
610 unsupported_extensions->insert(extension_id);
Oleg Davydovdec175a2020-05-25 16:44:29611 InstallStageTracker::Get(profile_)->ReportFailure(
Oleg Davydov66246bd92019-09-26 16:31:51612 extension_id,
Oleg Davydovdec175a2020-05-25 16:44:29613 InstallStageTracker::FailureReason::DO_NOT_INSTALL_FOR_ENTERPRISE);
dpolukhin1687ef32015-06-22 11:12:37614 VLOG(1) << "Skip installing (or uninstall) external extension "
615 << extension_id << " restricted for managed user";
616 return false;
617 }
618 }
619 return true;
620}
621
[email protected]8e4560b62011-01-14 10:09:14622// static
[email protected]5df038b2012-07-16 19:03:27623void ExternalProviderImpl::CreateExternalProviders(
[email protected]8e4560b62011-01-14 10:09:14624 VisitorInterface* service,
625 Profile* profile,
626 ProviderCollection* provider_list) {
rkaplowdd66a1342015-03-05 00:31:49627 TRACE_EVENT0("browser,startup",
628 "ExternalProviderImpl::CreateExternalProviders");
[email protected]af984882013-10-21 21:08:51629 scoped_refptr<ExternalLoader> external_loader;
binjincccacef2014-10-13 19:00:20630 scoped_refptr<ExternalLoader> external_recommended_loader;
Gyuyoung Kim2e954c42021-03-19 14:06:29631 ManifestLocation crx_location = ManifestLocation::kInvalidLocation;
achuithd3da4f02017-03-23 20:05:29632
Yuta Hijikata1290fee22020-11-25 09:46:28633#if BUILDFLAG(IS_CHROMEOS_ASH)
achuithd3da4f02017-03-23 20:05:29634 if (chromeos::ProfileHelper::IsSigninProfile(profile)) {
Maksim Ivanov12801d0d2020-02-18 10:23:41635 // Download extensions/apps installed by policy in the login profile.
636 // Extensions (not apps) installed through this path will have type
637 // |TYPE_LOGIN_SCREEN_EXTENSION| with limited API capabilities.
Gyuyoung Kim2e954c42021-03-19 14:06:29638 crx_location = ManifestLocation::kExternalPolicyDownload;
Maksim Ivanov8738d332020-01-07 22:19:01639 external_loader =
640 base::MakeRefCounted<chromeos::SigninScreenExtensionsExternalLoader>(
Oleg Davydovba7dd392021-03-18 09:47:44641 profile);
Jinho Bangb5216cec2018-01-17 19:43:11642 auto signin_profile_provider = std::make_unique<ExternalProviderImpl>(
achuithd3da4f02017-03-23 20:05:29643 service, external_loader, profile, crx_location,
Gyuyoung Kim2e954c42021-03-19 14:06:29644 ManifestLocation::kExternalPolicyDownload, Extension::FOR_LOGIN_SCREEN);
Maksim Ivanov8738d332020-01-07 22:19:01645 signin_profile_provider->set_auto_acknowledge(true);
Toni Barzic87026682018-01-08 23:21:04646 signin_profile_provider->set_allow_updates(true);
647 provider_list->push_back(std::move(signin_profile_provider));
achuithd3da4f02017-03-23 20:05:29648 return;
649 }
650
Yeunjoo Choi7227dba2021-08-04 06:35:47651 policy::BrowserPolicyConnectorAsh* connector =
652 g_browser_process->platform_part()->browser_policy_connector_ash();
[email protected]2d4cfed2014-01-14 13:59:57653 bool is_chrome_os_public_session = false;
[email protected]2fda9972014-07-23 14:51:59654 const user_manager::User* user =
[email protected]052e3ac2014-06-30 14:22:47655 chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
[email protected]2d4cfed2014-01-14 13:59:57656 policy::DeviceLocalAccount::Type account_type;
Roland Bock4ce23a922021-06-11 13:23:11657 if (user && connector->IsDeviceEnterpriseManaged() &&
alemate909aa58a2016-11-03 22:49:07658 policy::IsDeviceLocalAccountUser(user->GetAccountId().GetUserEmail(),
659 &account_type)) {
[email protected]2d4cfed2014-01-14 13:59:57660 if (account_type == policy::DeviceLocalAccount::TYPE_PUBLIC_SESSION)
661 is_chrome_os_public_session = true;
[email protected]af984882013-10-21 21:08:51662 policy::DeviceLocalAccountPolicyBroker* broker =
[email protected]97275822014-01-21 19:30:36663 connector->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
alemate909aa58a2016-11-03 22:49:07664 user->GetAccountId().GetUserEmail());
[email protected]af984882013-10-21 21:08:51665 if (broker) {
666 external_loader = broker->extension_loader();
Gyuyoung Kim2e954c42021-03-19 14:06:29667 crx_location = ManifestLocation::kExternalPolicy;
[email protected]af984882013-10-21 21:08:51668 } else {
669 NOTREACHED();
670 }
671 } else {
Matthew Dentonef83a622019-08-30 02:07:00672 external_loader = base::MakeRefCounted<ExternalPolicyLoader>(
Oleg Davydov52db8742019-08-20 09:14:40673 profile, ExtensionManagementFactory::GetForBrowserContext(profile),
binjincccacef2014-10-13 19:00:20674 ExternalPolicyLoader::FORCED);
Matthew Dentonef83a622019-08-30 02:07:00675 external_recommended_loader = base::MakeRefCounted<ExternalPolicyLoader>(
Oleg Davydov52db8742019-08-20 09:14:40676 profile, ExtensionManagementFactory::GetForBrowserContext(profile),
binjincccacef2014-10-13 19:00:20677 ExternalPolicyLoader::RECOMMENDED);
[email protected]af984882013-10-21 21:08:51678 }
679#else
Matthew Dentonef83a622019-08-30 02:07:00680 external_loader = base::MakeRefCounted<ExternalPolicyLoader>(
Oleg Davydov52db8742019-08-20 09:14:40681 profile, ExtensionManagementFactory::GetForBrowserContext(profile),
binjincccacef2014-10-13 19:00:20682 ExternalPolicyLoader::FORCED);
Matthew Dentonef83a622019-08-30 02:07:00683 external_recommended_loader = base::MakeRefCounted<ExternalPolicyLoader>(
Oleg Davydov52db8742019-08-20 09:14:40684 profile, ExtensionManagementFactory::GetForBrowserContext(profile),
binjincccacef2014-10-13 19:00:20685 ExternalPolicyLoader::RECOMMENDED);
[email protected]af984882013-10-21 21:08:51686#endif
687
[email protected]b9f4fe52012-11-09 21:40:59688 // Policies are mandatory so they can't be skipped with command line flag.
dchengc7047942014-08-26 05:05:31689 if (external_loader.get()) {
Jinho Bangb5216cec2018-01-17 19:43:11690 auto policy_provider = std::make_unique<ExternalProviderImpl>(
lazyboyf33109d2016-08-31 00:37:08691 service, external_loader, profile, crx_location,
Gyuyoung Kim2e954c42021-03-19 14:06:29692 ManifestLocation::kExternalPolicyDownload, Extension::NO_FLAGS);
Toni Barzic87026682018-01-08 23:21:04693 policy_provider->set_allow_updates(true);
694 provider_list->push_back(std::move(policy_provider));
[email protected]af984882013-10-21 21:08:51695 }
[email protected]b9f4fe52012-11-09 21:40:59696
Anqing Zhaof0e96fb42020-12-11 23:21:21697 // Load the KioskAppExternalProvider when running in the Chrome App kiosk
698 // mode.
[email protected]ee3da0552014-07-16 05:27:31699 if (chrome::IsRunningInForcedAppMode()) {
Yuta Hijikata1290fee22020-11-25 09:46:28700#if BUILDFLAG(IS_CHROMEOS_ASH)
Anqing Zhaof0e96fb42020-12-11 23:21:21701 if (user && user->GetType() == user_manager::USER_TYPE_KIOSK_APP) {
702 // Kiosk primary app external provider.
703 // For enterprise managed kiosk apps, change the location to
704 // "force-installed by policy".
Yeunjoo Choi7227dba2021-08-04 06:35:47705 policy::BrowserPolicyConnectorAsh* const connector =
706 g_browser_process->platform_part()->browser_policy_connector_ash();
Gyuyoung Kim2e954c42021-03-19 14:06:29707 ManifestLocation location = ManifestLocation::kExternalPref;
Roland Bock4ce23a922021-06-11 13:23:11708 if (connector && connector->IsDeviceEnterpriseManaged())
Gyuyoung Kim2e954c42021-03-19 14:06:29709 location = ManifestLocation::kExternalPolicy;
pbond43ddd4f2015-09-08 16:39:19710
Anqing Zhaof0e96fb42020-12-11 23:21:21711 auto kiosk_app_provider = std::make_unique<ExternalProviderImpl>(
712 service,
Henrique Ferreiro26ed25a2021-02-01 21:59:29713 base::MakeRefCounted<ash::KioskAppExternalLoader>(
714 ash::KioskAppExternalLoader::AppClass::kPrimary),
Gyuyoung Kim2e954c42021-03-19 14:06:29715 profile, location, ManifestLocation::kInvalidLocation,
716 Extension::NO_FLAGS);
Anqing Zhaof0e96fb42020-12-11 23:21:21717 kiosk_app_provider->set_auto_acknowledge(true);
718 kiosk_app_provider->set_install_immediately(true);
719 kiosk_app_provider->set_allow_updates(true);
720 provider_list->push_back(std::move(kiosk_app_provider));
jennyz26b7f432015-09-03 20:59:27721
Anqing Zhaof0e96fb42020-12-11 23:21:21722 // Kiosk secondary app external provider.
723 auto secondary_kiosk_app_provider =
724 std::make_unique<ExternalProviderImpl>(
725 service,
Henrique Ferreiro26ed25a2021-02-01 21:59:29726 base::MakeRefCounted<ash::KioskAppExternalLoader>(
727 ash::KioskAppExternalLoader::AppClass::kSecondary),
Gyuyoung Kim2e954c42021-03-19 14:06:29728 profile, ManifestLocation::kExternalPref,
729 ManifestLocation::kExternalPrefDownload, Extension::NO_FLAGS);
Anqing Zhaof0e96fb42020-12-11 23:21:21730 secondary_kiosk_app_provider->set_auto_acknowledge(true);
731 secondary_kiosk_app_provider->set_install_immediately(true);
732 secondary_kiosk_app_provider->set_allow_updates(true);
733 provider_list->push_back(std::move(secondary_kiosk_app_provider));
734 }
[email protected]ee3da0552014-07-16 05:27:31735#endif
736 return;
737 }
738
binjincccacef2014-10-13 19:00:20739 // Extensions provided by recommended policies.
740 if (external_recommended_loader.get()) {
Nicolas Ouellet-Payeur93b74ca1d2020-12-09 23:33:12741 auto recommended_provider = std::make_unique<ExternalProviderImpl>(
lazyboyf33109d2016-08-31 00:37:08742 service, external_recommended_loader, profile, crx_location,
Gyuyoung Kim2e954c42021-03-19 14:06:29743 ManifestLocation::kExternalPrefDownload, Extension::NO_FLAGS);
Nicolas Ouellet-Payeur93b74ca1d2020-12-09 23:33:12744 recommended_provider->set_auto_acknowledge(true);
745 provider_list->push_back(std::move(recommended_provider));
binjincccacef2014-10-13 19:00:20746 }
747
Daniel Murphy3657906d2021-04-13 20:33:12748 // In tests don't install pre-installed apps.
[email protected]b9f4fe52012-11-09 21:40:59749 // It would only slowdown tests and make them flaky.
avi3ef9ec9e2014-12-22 22:50:17750 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
Daniel Murphy3657906d2021-04-13 20:33:12751 ::switches::kDisablePreinstalledApps)) {
[email protected]b9f4fe52012-11-09 21:40:59752 return;
[email protected]98820ac72019-01-24 19:47:16753 }
[email protected]73e4c362011-09-22 14:47:18754
Peter Kasting9c68b0f2021-07-27 09:47:40755#if !defined(OS_WIN)
[email protected]73e4c362011-09-22 14:47:18756 // On Mac OS, items in /Library/... should be written by the superuser.
757 // Check that all components of the path are writable by root only.
[email protected]5df038b2012-07-16 19:03:27758 ExternalPrefLoader::Options check_admin_permissions_on_mac;
Avi Drissman2e458df2020-07-29 16:24:31759#if defined(OS_MAC)
[email protected]0edc55412011-11-07 16:47:33760 check_admin_permissions_on_mac =
Peter Kasting9c68b0f2021-07-27 09:47:40761 ExternalPrefLoader::ENSURE_PATH_CONTROLLED_BY_ADMIN;
[email protected]73e4c362011-09-22 14:47:18762#else
[email protected]5df038b2012-07-16 19:03:27763 check_admin_permissions_on_mac = ExternalPrefLoader::NONE;
[email protected]73e4c362011-09-22 14:47:18764#endif
[email protected]d6f7b102012-05-04 13:59:05765 int bundled_extension_creation_flags = Extension::NO_FLAGS;
Peter Kastingbe940e92014-11-20 23:14:08766#endif
Yuta Hijikata1290fee22020-11-25 09:46:28767#if BUILDFLAG(IS_CHROMEOS_ASH)
[email protected]5861bcd2012-10-16 21:40:19768 bundled_extension_creation_flags = Extension::FROM_WEBSTORE |
769 Extension::WAS_INSTALLED_BY_DEFAULT;
[email protected]a4567732013-07-25 21:01:20770
rkcb526cd6b2014-12-18 16:54:37771 if (!is_chrome_os_public_session) {
[email protected]98820ac72019-01-24 19:47:16772 int pref_load_flags =
ginkagef66fae522015-03-03 16:38:16773 profile->IsNewProfile()
774 ? ExternalPrefLoader::DELAY_LOAD_UNTIL_PRIORITY_SYNC
775 : ExternalPrefLoader::NONE;
[email protected]98820ac72019-01-24 19:47:16776 pref_load_flags |= ExternalPrefLoader::USE_USER_TYPE_PROFILE_FILTER;
777 provider_list->push_back(std::make_unique<ExternalProviderImpl>(
778 service,
Matthew Dentonef83a622019-08-30 02:07:00779 base::MakeRefCounted<ExternalPrefLoader>(
780 chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS, pref_load_flags,
781 profile),
Gyuyoung Kim2e954c42021-03-19 14:06:29782 profile, ManifestLocation::kExternalPref,
783 ManifestLocation::kExternalPrefDownload,
[email protected]98820ac72019-01-24 19:47:16784 bundled_extension_creation_flags));
[email protected]d0b28892014-03-05 18:56:31785
Daniel Murphy3657906d2021-04-13 20:33:12786 // OEM pre-installed apps.
[email protected]acc3c7c22014-03-19 06:23:39787 int oem_extension_creation_flags =
788 bundled_extension_creation_flags | Extension::WAS_INSTALLED_BY_OEM;
Yeunjoo Choicf61fba2021-04-23 02:43:09789 ash::ServicesCustomizationDocument* customization =
790 ash::ServicesCustomizationDocument::GetInstance();
Jinho Bangb5216cec2018-01-17 19:43:11791 provider_list->push_back(std::make_unique<ExternalProviderImpl>(
lazyboyf33109d2016-08-31 00:37:08792 service, customization->CreateExternalLoader(profile), profile,
Gyuyoung Kim2e954c42021-03-19 14:06:29793 ManifestLocation::kExternalPref,
794 ManifestLocation::kExternalPrefDownload, oem_extension_creation_flags));
[email protected]ebb489f2013-09-19 22:08:52795 }
Toni Barzicdff51562018-07-24 19:55:46796
797 // For Chrome OS demo sessions, add pre-installed demo extensions and apps.
Henrique Ferreirod71de902021-05-10 18:57:11798 if (ash::DemoExtensionsExternalLoader::SupportedForProfile(profile)) {
Wenzhao Zang463f1142018-09-05 22:50:50799 base::FilePath cache_dir;
800 CHECK(base::PathService::Get(chromeos::DIR_DEVICE_EXTENSION_LOCAL_CACHE,
801 &cache_dir));
Henrique Ferreirod71de902021-05-10 18:57:11802 auto loader =
803 base::MakeRefCounted<ash::DemoExtensionsExternalLoader>(cache_dir);
Toni Barzicdff51562018-07-24 19:55:46804 std::unique_ptr<ExternalProviderImpl> demo_apps_provider =
805 std::make_unique<ExternalProviderImpl>(
Gyuyoung Kim2e954c42021-03-19 14:06:29806 service, loader, profile, ManifestLocation::kExternalPolicy,
807 ManifestLocation::kExternalPolicyDownload, Extension::NO_FLAGS);
Toni Barzicdff51562018-07-24 19:55:46808 demo_apps_provider->set_auto_acknowledge(true);
809 demo_apps_provider->set_install_immediately(true);
Henrique Ferreirod71de902021-05-10 18:57:11810 ash::DemoSession::Get()->SetExtensionsExternalLoader(loader);
Toni Barzicdff51562018-07-24 19:55:46811 provider_list->push_back(std::move(demo_apps_provider));
812 }
[email protected]5bed2ec32013-08-29 22:55:46813#endif
Dominique Fauteux-Chapleauff3bb352019-10-16 14:32:34814 if (!profile->GetPrefs()->GetBoolean(pref_names::kBlockExternalExtensions)) {
Yuta Hijikata1290fee22020-11-25 09:46:28815// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
816// of lacros-chrome is complete.
817#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
Taiju Tsuikib1879b72018-09-21 06:22:47818 provider_list->push_back(std::make_unique<ExternalProviderImpl>(
819 service,
Matthew Dentonef83a622019-08-30 02:07:00820 base::MakeRefCounted<ExternalPrefLoader>(
Dominique Fauteux-Chapleauff3bb352019-10-16 14:32:34821 chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS,
822 ExternalPrefLoader::USE_USER_TYPE_PROFILE_FILTER, profile),
Gyuyoung Kim2e954c42021-03-19 14:06:29823 profile, ManifestLocation::kExternalPref,
824 ManifestLocation::kExternalPrefDownload,
Taiju Tsuikib1879b72018-09-21 06:22:47825 bundled_extension_creation_flags));
Dominique Fauteux-Chapleauff3bb352019-10-16 14:32:34826#endif
Dominique Fauteux-Chapleauff3bb352019-10-16 14:32:34827#if defined(OS_WIN)
Toby Huangf93f7002021-01-24 01:08:13828 auto registry_provider = std::make_unique<ExternalProviderImpl>(
829 service, new ExternalRegistryLoader, profile,
Gyuyoung Kim2e954c42021-03-19 14:06:29830 ManifestLocation::kExternalRegistry,
831 ManifestLocation::kExternalPrefDownload, Extension::NO_FLAGS);
Toby Huangf93f7002021-01-24 01:08:13832 registry_provider->set_allow_updates(true);
833 provider_list->push_back(std::move(registry_provider));
Dominique Fauteux-Chapleauff3bb352019-10-16 14:32:34834#else
Toby Huangf93f7002021-01-24 01:08:13835 provider_list->push_back(std::make_unique<ExternalProviderImpl>(
836 service,
837 base::MakeRefCounted<ExternalPrefLoader>(
838 chrome::DIR_EXTERNAL_EXTENSIONS, check_admin_permissions_on_mac,
839 nullptr),
Gyuyoung Kim2e954c42021-03-19 14:06:29840 profile, ManifestLocation::kExternalPref,
841 ManifestLocation::kExternalPrefDownload,
Toby Huangf93f7002021-01-24 01:08:13842 bundled_extension_creation_flags));
[email protected]5bed2ec32013-08-29 22:55:46843
Toby Huangf93f7002021-01-24 01:08:13844 // Define a per-user source of external extensions.
Sean McAllister4a991b972020-08-19 17:38:51845#if defined(OS_MAC) || ((defined(OS_LINUX) || defined(OS_CHROMEOS)) && \
846 BUILDFLAG(CHROMIUM_BRANDING))
Toby Huangf93f7002021-01-24 01:08:13847 provider_list->push_back(std::make_unique<ExternalProviderImpl>(
848 service,
Matthew Dentonef83a622019-08-30 02:07:00849 base::MakeRefCounted<ExternalPrefLoader>(
Toby Huangf93f7002021-01-24 01:08:13850 chrome::DIR_USER_EXTERNAL_EXTENSIONS, ExternalPrefLoader::NONE,
851 nullptr),
Gyuyoung Kim2e954c42021-03-19 14:06:29852 profile, ManifestLocation::kExternalPref,
853 ManifestLocation::kExternalPrefDownload, Extension::NO_FLAGS));
Toby Huangf93f7002021-01-24 01:08:13854#endif
855#endif
856 }
857
858#if !BUILDFLAG(IS_CHROMEOS_ASH)
Daniel Murphy3657906d2021-04-13 20:33:12859 // The pre-installed apps are installed as INTERNAL but use the external
Toby Huangf93f7002021-01-24 01:08:13860 // extension installer codeflow.
Daniel Murphy3657906d2021-04-13 20:33:12861 provider_list->push_back(std::make_unique<preinstalled_apps::Provider>(
Toby Huangf93f7002021-01-24 01:08:13862 profile, service,
863 base::MakeRefCounted<ExternalPrefLoader>(
864 chrome::DIR_DEFAULT_APPS, ExternalPrefLoader::NONE, nullptr),
Gyuyoung Kim2e954c42021-03-19 14:06:29865 ManifestLocation::kInternal, ManifestLocation::kInternal,
Toby Huangf93f7002021-01-24 01:08:13866 Extension::FROM_WEBSTORE | Extension::WAS_INSTALLED_BY_DEFAULT));
[email protected]98b4aca62011-09-28 01:27:23867#endif
xiyuan65b68ab12015-06-26 19:00:18868
Toby Huangf93f7002021-01-24 01:08:13869 std::unique_ptr<ExternalProviderImpl> drive_migration_provider(
870 new ExternalProviderImpl(
871 service,
872 base::MakeRefCounted<ExtensionMigrator>(
Phillis Tang28427c462021-10-19 20:50:38873 profile, extension_misc::kGoogleDriveAppId,
Toby Huangf93f7002021-01-24 01:08:13874 extension_misc::kDocsOfflineExtensionId),
Gyuyoung Kim2e954c42021-03-19 14:06:29875 profile, ManifestLocation::kExternalPref,
876 ManifestLocation::kExternalPrefDownload,
Toby Huangf93f7002021-01-24 01:08:13877 Extension::FROM_WEBSTORE | Extension::WAS_INSTALLED_BY_DEFAULT));
878 drive_migration_provider->set_auto_acknowledge(true);
879 provider_list->push_back(std::move(drive_migration_provider));
treibcc82ab82015-03-02 09:41:49880
Jinho Bangb5216cec2018-01-17 19:43:11881 provider_list->push_back(std::make_unique<ExternalProviderImpl>(
Matthew Dentonef83a622019-08-30 02:07:00882 service, base::MakeRefCounted<ExternalComponentLoader>(profile), profile,
Gyuyoung Kim2e954c42021-03-19 14:06:29883 ManifestLocation::kInvalidLocation, ManifestLocation::kExternalComponent,
lazyboyf33109d2016-08-31 00:37:08884 Extension::FROM_WEBSTORE | Extension::WAS_INSTALLED_BY_DEFAULT));
[email protected]8e4560b62011-01-14 10:09:14885}
[email protected]5df038b2012-07-16 19:03:27886
887} // namespace extensions