Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / extensions / external_provider_impl.cc
blobb3af2f3db421537378de2b7b0371d419c43257ca
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/external_provider_impl.h"
7 #include <set>
8 #include <vector>
10 #include "base/command_line.h"
11 #include "base/files/file_path.h"
12 #include "base/logging.h"
13 #include "base/memory/linked_ptr.h"
14 #include "base/metrics/field_trial.h"
15 #include "base/prefs/pref_service.h"
16 #include "base/strings/string_util.h"
17 #include "base/trace_event/trace_event.h"
18 #include "base/values.h"
19 #include "base/version.h"
20 #include "chrome/browser/app_mode/app_mode_utils.h"
21 #include "chrome/browser/browser_process.h"
22 #include "chrome/browser/browser_process_platform_part.h"
23 #include "chrome/browser/extensions/extension_management.h"
24 #include "chrome/browser/extensions/extension_migrator.h"
25 #include "chrome/browser/extensions/extension_service.h"
26 #include "chrome/browser/extensions/external_component_loader.h"
27 #include "chrome/browser/extensions/external_policy_loader.h"
28 #include "chrome/browser/extensions/external_pref_loader.h"
29 #include "chrome/browser/policy/profile_policy_connector.h"
30 #include "chrome/browser/policy/profile_policy_connector_factory.h"
31 #include "chrome/browser/profiles/profile.h"
32 #include "chrome/common/chrome_paths.h"
33 #include "chrome/common/chrome_switches.h"
34 #include "chrome/common/extensions/extension_constants.h"
35 #include "chrome/common/pref_names.h"
36 #include "components/crx_file/id_util.h"
37 #include "content/public/browser/browser_thread.h"
38 #include "extensions/browser/extension_system.h"
39 #include "extensions/browser/external_provider_interface.h"
40 #include "extensions/common/extension.h"
41 #include "extensions/common/manifest.h"
42 #include "ui/base/l10n/l10n_util.h"
44 #if defined(OS_CHROMEOS)
45 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
46 #include "chrome/browser/chromeos/customization/customization_document.h"
47 #include "chrome/browser/chromeos/extensions/device_local_account_external_policy_loader.h"
48 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
49 #include "chrome/browser/chromeos/policy/device_local_account.h"
50 #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
51 #include "chrome/browser/chromeos/profiles/profile_helper.h"
52 #include "components/user_manager/user.h"
53 #else
54 #include "chrome/browser/extensions/default_apps.h"
55 #endif
57 #if defined(OS_WIN)
58 #include "chrome/browser/extensions/external_registry_loader_win.h"
59 #endif
61 using content::BrowserThread;
63 namespace extensions {
65 // Constants for keeping track of extension preferences in a dictionary.
66 const char ExternalProviderImpl::kInstallParam[] = "install_parameter";
67 const char ExternalProviderImpl::kExternalCrx[] = "external_crx";
68 const char ExternalProviderImpl::kExternalVersion[] = "external_version";
69 const char ExternalProviderImpl::kExternalUpdateUrl[] = "external_update_url";
70 const char ExternalProviderImpl::kIsBookmarkApp[] = "is_bookmark_app";
71 const char ExternalProviderImpl::kIsFromWebstore[] = "is_from_webstore";
72 const char ExternalProviderImpl::kKeepIfPresent[] = "keep_if_present";
73 const char ExternalProviderImpl::kWasInstalledByOem[] = "was_installed_by_oem";
74 const char ExternalProviderImpl::kSupportedLocales[] = "supported_locales";
75 const char ExternalProviderImpl::kMayBeUntrusted[] = "may_be_untrusted";
76 const char ExternalProviderImpl::kMinProfileCreatedByVersion[] =
77 "min_profile_created_by_version";
78 const char ExternalProviderImpl::kDoNotInstallForEnterprise[] =
79 "do_not_install_for_enterprise";
81 ExternalProviderImpl::ExternalProviderImpl(
82 VisitorInterface* service,
83 const scoped_refptr<ExternalLoader>& loader,
84 Profile* profile,
85 Manifest::Location crx_location,
86 Manifest::Location download_location,
87 int creation_flags)
88 : crx_location_(crx_location),
89 download_location_(download_location),
90 service_(service),
91 ready_(false),
92 loader_(loader),
93 profile_(profile),
94 creation_flags_(creation_flags),
95 auto_acknowledge_(false),
96 install_immediately_(false) {
97 loader_->Init(this);
100 ExternalProviderImpl::~ExternalProviderImpl() {
101 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
102 loader_->OwnerShutdown();
105 void ExternalProviderImpl::VisitRegisteredExtension() {
106 // The loader will call back to SetPrefs.
107 loader_->StartLoading();
110 void ExternalProviderImpl::SetPrefs(base::DictionaryValue* prefs) {
111 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
113 // Check if the service is still alive. It is possible that it went
114 // away while |loader_| was working on the FILE thread.
115 if (!service_) return;
117 prefs_.reset(prefs);
118 ready_ = true; // Queries for extensions are allowed from this point.
120 // Set of unsupported extensions that need to be deleted from prefs_.
121 std::set<std::string> unsupported_extensions;
123 // Notify ExtensionService about all the extensions this provider has.
124 for (base::DictionaryValue::Iterator i(*prefs_); !i.IsAtEnd(); i.Advance()) {
125 const std::string& extension_id = i.key();
126 const base::DictionaryValue* extension = NULL;
128 if (!crx_file::id_util::IdIsValid(extension_id)) {
129 LOG(WARNING) << "Malformed extension dictionary: key "
130 << extension_id.c_str() << " is not a valid id.";
131 continue;
134 if (!i.value().GetAsDictionary(&extension)) {
135 LOG(WARNING) << "Malformed extension dictionary: key "
136 << extension_id.c_str()
137 << " has a value that is not a dictionary.";
138 continue;
141 base::FilePath::StringType external_crx;
142 const base::Value* external_version_value = NULL;
143 std::string external_version;
144 std::string external_update_url;
146 bool has_external_crx = extension->GetString(kExternalCrx, &external_crx);
148 bool has_external_version = false;
149 if (extension->Get(kExternalVersion, &external_version_value)) {
150 if (external_version_value->IsType(base::Value::TYPE_STRING)) {
151 external_version_value->GetAsString(&external_version);
152 has_external_version = true;
153 } else {
154 LOG(WARNING) << "Malformed extension dictionary for extension: "
155 << extension_id.c_str() << ". " << kExternalVersion
156 << " value must be a string.";
157 continue;
161 bool has_external_update_url = extension->GetString(kExternalUpdateUrl,
162 &external_update_url);
163 if (has_external_crx != has_external_version) {
164 LOG(WARNING) << "Malformed extension dictionary for extension: "
165 << extension_id.c_str() << ". " << kExternalCrx
166 << " and " << kExternalVersion << " must be used together.";
167 continue;
170 if (has_external_crx == has_external_update_url) {
171 LOG(WARNING) << "Malformed extension dictionary for extension: "
172 << extension_id.c_str() << ". Exactly one of the "
173 << "followng keys should be used: " << kExternalCrx
174 << ", " << kExternalUpdateUrl << ".";
175 continue;
178 // Check that extension supports current browser locale.
179 const base::ListValue* supported_locales = NULL;
180 if (extension->GetList(kSupportedLocales, &supported_locales)) {
181 std::vector<std::string> browser_locales;
182 l10n_util::GetParentLocales(g_browser_process->GetApplicationLocale(),
183 &browser_locales);
185 size_t num_locales = supported_locales->GetSize();
186 bool locale_supported = false;
187 for (size_t j = 0; j < num_locales; j++) {
188 std::string current_locale;
189 if (supported_locales->GetString(j, &current_locale) &&
190 l10n_util::IsValidLocaleSyntax(current_locale)) {
191 current_locale = l10n_util::NormalizeLocale(current_locale);
192 if (std::find(browser_locales.begin(), browser_locales.end(),
193 current_locale) != browser_locales.end()) {
194 locale_supported = true;
195 break;
197 } else {
198 LOG(WARNING) << "Unrecognized locale '" << current_locale
199 << "' found as supported locale for extension: "
200 << extension_id;
204 if (!locale_supported) {
205 unsupported_extensions.insert(extension_id);
206 VLOG(1) << "Skip installing (or uninstall) external extension: "
207 << extension_id << " because the extension doesn't support "
208 << "the browser locale.";
209 continue;
213 int creation_flags = creation_flags_;
214 bool is_bookmark_app;
215 if (extension->GetBoolean(kIsBookmarkApp, &is_bookmark_app) &&
216 is_bookmark_app) {
217 creation_flags |= Extension::FROM_BOOKMARK;
219 bool is_from_webstore = false;
220 if (extension->GetBoolean(kIsFromWebstore, &is_from_webstore) &&
221 is_from_webstore) {
222 creation_flags |= Extension::FROM_WEBSTORE;
224 bool keep_if_present = false;
225 if (extension->GetBoolean(kKeepIfPresent, &keep_if_present) &&
226 keep_if_present && profile_) {
227 ExtensionServiceInterface* extension_service =
228 ExtensionSystem::Get(profile_)->extension_service();
229 const Extension* extension = extension_service ?
230 extension_service->GetExtensionById(extension_id, true) : NULL;
231 if (!extension) {
232 unsupported_extensions.insert(extension_id);
233 VLOG(1) << "Skip installing (or uninstall) external extension: "
234 << extension_id << " because the extension should be kept "
235 << "only if it is already installed.";
236 continue;
239 bool was_installed_by_oem = false;
240 if (extension->GetBoolean(kWasInstalledByOem, &was_installed_by_oem) &&
241 was_installed_by_oem) {
242 creation_flags |= Extension::WAS_INSTALLED_BY_OEM;
244 bool may_be_untrusted = false;
245 if (extension->GetBoolean(kMayBeUntrusted, &may_be_untrusted) &&
246 may_be_untrusted) {
247 creation_flags |= Extension::MAY_BE_UNTRUSTED;
250 if (!HandleMinProfileVersion(extension, extension_id,
251 &unsupported_extensions)) {
252 continue;
255 if (!HandleDoNotInstallForEnterprise(extension, extension_id,
256 &unsupported_extensions)) {
257 continue;
260 std::string install_parameter;
261 extension->GetString(kInstallParam, &install_parameter);
263 if (has_external_crx) {
264 if (crx_location_ == Manifest::INVALID_LOCATION) {
265 LOG(WARNING) << "This provider does not support installing external "
266 << "extensions from crx files.";
267 continue;
269 if (external_crx.find(base::FilePath::kParentDirectory) !=
270 base::StringPiece::npos) {
271 LOG(WARNING) << "Path traversal not allowed in path: "
272 << external_crx.c_str();
273 continue;
276 // If the path is relative, and the provider has a base path,
277 // build the absolute path to the crx file.
278 base::FilePath path(external_crx);
279 if (!path.IsAbsolute()) {
280 base::FilePath base_path = loader_->GetBaseCrxFilePath();
281 if (base_path.empty()) {
282 LOG(WARNING) << "File path " << external_crx.c_str()
283 << " is relative. An absolute path is required.";
284 continue;
286 path = base_path.Append(external_crx);
289 Version version(external_version);
290 if (!version.IsValid()) {
291 LOG(WARNING) << "Malformed extension dictionary for extension: "
292 << extension_id.c_str() << ". Invalid version string \""
293 << external_version << "\".";
294 continue;
296 service_->OnExternalExtensionFileFound(extension_id, &version, path,
297 crx_location_, creation_flags,
298 auto_acknowledge_,
299 install_immediately_);
300 } else { // if (has_external_update_url)
301 CHECK(has_external_update_url); // Checking of keys above ensures this.
302 if (download_location_ == Manifest::INVALID_LOCATION) {
303 LOG(WARNING) << "This provider does not support installing external "
304 << "extensions from update URLs.";
305 continue;
307 GURL update_url(external_update_url);
308 if (!update_url.is_valid()) {
309 LOG(WARNING) << "Malformed extension dictionary for extension: "
310 << extension_id.c_str() << ". Key " << kExternalUpdateUrl
311 << " has value \"" << external_update_url
312 << "\", which is not a valid URL.";
313 continue;
315 service_->OnExternalExtensionUpdateUrlFound(extension_id,
316 install_parameter,
317 update_url,
318 download_location_,
319 creation_flags,
320 auto_acknowledge_);
324 for (std::set<std::string>::iterator it = unsupported_extensions.begin();
325 it != unsupported_extensions.end(); ++it) {
326 // Remove extension for the list of know external extensions. The extension
327 // will be uninstalled later because provider doesn't provide it anymore.
328 prefs_->Remove(*it, NULL);
331 service_->OnExternalProviderReady(this);
334 void ExternalProviderImpl::ServiceShutdown() {
335 service_ = NULL;
338 bool ExternalProviderImpl::IsReady() const {
339 return ready_;
342 bool ExternalProviderImpl::HasExtension(
343 const std::string& id) const {
344 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
345 CHECK(prefs_.get());
346 CHECK(ready_);
347 return prefs_->HasKey(id);
350 bool ExternalProviderImpl::GetExtensionDetails(
351 const std::string& id, Manifest::Location* location,
352 scoped_ptr<Version>* version) const {
353 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
354 CHECK(prefs_.get());
355 CHECK(ready_);
356 base::DictionaryValue* extension = NULL;
357 if (!prefs_->GetDictionary(id, &extension))
358 return false;
360 Manifest::Location loc = Manifest::INVALID_LOCATION;
361 if (extension->HasKey(kExternalUpdateUrl)) {
362 loc = download_location_;
364 } else if (extension->HasKey(kExternalCrx)) {
365 loc = crx_location_;
367 std::string external_version;
368 if (!extension->GetString(kExternalVersion, &external_version))
369 return false;
371 if (version)
372 version->reset(new Version(external_version));
374 } else {
375 NOTREACHED(); // Chrome should not allow prefs to get into this state.
376 return false;
379 if (location)
380 *location = loc;
382 return true;
385 bool ExternalProviderImpl::HandleMinProfileVersion(
386 const base::DictionaryValue* extension,
387 const std::string& extension_id,
388 std::set<std::string>* unsupported_extensions) {
389 std::string min_profile_created_by_version;
390 if (profile_ &&
391 extension->GetString(kMinProfileCreatedByVersion,
392 &min_profile_created_by_version)) {
393 Version profile_version(
394 profile_->GetPrefs()->GetString(prefs::kProfileCreatedByVersion));
395 Version min_version(min_profile_created_by_version);
396 if (min_version.IsValid() && profile_version.CompareTo(min_version) < 0) {
397 unsupported_extensions->insert(extension_id);
398 VLOG(1) << "Skip installing (or uninstall) external extension: "
399 << extension_id
400 << " profile.created_by_version: " << profile_version.GetString()
401 << " min_profile_created_by_version: "
402 << min_profile_created_by_version;
403 return false;
406 return true;
409 bool ExternalProviderImpl::HandleDoNotInstallForEnterprise(
410 const base::DictionaryValue* extension,
411 const std::string& extension_id,
412 std::set<std::string>* unsupported_extensions) {
413 bool do_not_install_for_enterprise = false;
414 if (extension->GetBoolean(kDoNotInstallForEnterprise,
415 &do_not_install_for_enterprise) &&
416 do_not_install_for_enterprise) {
417 const policy::ProfilePolicyConnector* const connector =
418 policy::ProfilePolicyConnectorFactory::GetForBrowserContext(profile_);
419 if (connector->IsManaged()) {
420 unsupported_extensions->insert(extension_id);
421 VLOG(1) << "Skip installing (or uninstall) external extension "
422 << extension_id << " restricted for managed user";
423 return false;
426 return true;
429 // static
430 void ExternalProviderImpl::CreateExternalProviders(
431 VisitorInterface* service,
432 Profile* profile,
433 ProviderCollection* provider_list) {
434 TRACE_EVENT0("browser,startup",
435 "ExternalProviderImpl::CreateExternalProviders");
436 scoped_refptr<ExternalLoader> external_loader;
437 scoped_refptr<ExternalLoader> external_recommended_loader;
438 extensions::Manifest::Location crx_location = Manifest::INVALID_LOCATION;
439 #if defined(OS_CHROMEOS)
440 policy::BrowserPolicyConnectorChromeOS* connector =
441 g_browser_process->platform_part()->browser_policy_connector_chromeos();
442 bool is_chrome_os_public_session = false;
443 const user_manager::User* user =
444 chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
445 policy::DeviceLocalAccount::Type account_type;
446 if (user &&
447 connector->IsEnterpriseManaged() &&
448 policy::IsDeviceLocalAccountUser(user->email(), &account_type)) {
449 if (account_type == policy::DeviceLocalAccount::TYPE_PUBLIC_SESSION)
450 is_chrome_os_public_session = true;
451 policy::DeviceLocalAccountPolicyBroker* broker =
452 connector->GetDeviceLocalAccountPolicyService()->GetBrokerForUser(
453 user->email());
454 if (broker) {
455 external_loader = broker->extension_loader();
456 crx_location = Manifest::EXTERNAL_POLICY;
457 } else {
458 NOTREACHED();
460 } else {
461 external_loader = new ExternalPolicyLoader(
462 ExtensionManagementFactory::GetForBrowserContext(profile),
463 ExternalPolicyLoader::FORCED);
464 external_recommended_loader = new ExternalPolicyLoader(
465 ExtensionManagementFactory::GetForBrowserContext(profile),
466 ExternalPolicyLoader::RECOMMENDED);
468 #else
469 external_loader = new ExternalPolicyLoader(
470 ExtensionManagementFactory::GetForBrowserContext(profile),
471 ExternalPolicyLoader::FORCED);
472 external_recommended_loader = new ExternalPolicyLoader(
473 ExtensionManagementFactory::GetForBrowserContext(profile),
474 ExternalPolicyLoader::RECOMMENDED);
475 #endif
477 // Policies are mandatory so they can't be skipped with command line flag.
478 if (external_loader.get()) {
479 provider_list->push_back(
480 linked_ptr<ExternalProviderInterface>(
481 new ExternalProviderImpl(
482 service,
483 external_loader,
484 profile,
485 crx_location,
486 Manifest::EXTERNAL_POLICY_DOWNLOAD,
487 Extension::NO_FLAGS)));
490 // Load the KioskAppExternalProvider when running in kiosk mode.
491 if (chrome::IsRunningInForcedAppMode()) {
492 #if defined(OS_CHROMEOS)
493 chromeos::KioskAppManager* kiosk_app_manager =
494 chromeos::KioskAppManager::Get();
495 CHECK(kiosk_app_manager);
497 // Kiosk primary app external provider.
498 if (!kiosk_app_manager->external_loader_created()) {
499 // For enterprise managed kiosk apps, change the location to
500 // "force-installed by policy".
501 policy::BrowserPolicyConnectorChromeOS* const connector =
502 g_browser_process->platform_part()
503 ->browser_policy_connector_chromeos();
504 Manifest::Location location = Manifest::EXTERNAL_PREF;
505 if (connector && connector->IsEnterpriseManaged())
506 location = Manifest::EXTERNAL_POLICY;
508 scoped_ptr<ExternalProviderImpl> kiosk_app_provider(
509 new ExternalProviderImpl(
510 service, kiosk_app_manager->CreateExternalLoader(), profile,
511 location, Manifest::INVALID_LOCATION, Extension::NO_FLAGS));
512 kiosk_app_provider->set_auto_acknowledge(true);
513 kiosk_app_provider->set_install_immediately(true);
514 provider_list->push_back(
515 linked_ptr<ExternalProviderInterface>(kiosk_app_provider.release()));
518 // Kiosk secondary app external provider.
519 if (!kiosk_app_manager->secondary_app_external_loader_created()) {
520 scoped_ptr<ExternalProviderImpl> secondary_kiosk_app_provider(
521 new ExternalProviderImpl(
522 service, kiosk_app_manager->CreateSecondaryAppExternalLoader(),
523 profile, Manifest::EXTERNAL_PREF,
524 Manifest::EXTERNAL_PREF_DOWNLOAD, Extension::NO_FLAGS));
525 secondary_kiosk_app_provider->set_auto_acknowledge(true);
526 secondary_kiosk_app_provider->set_install_immediately(true);
527 provider_list->push_back(linked_ptr<ExternalProviderInterface>(
528 secondary_kiosk_app_provider.release()));
530 #endif
531 return;
534 // Extensions provided by recommended policies.
535 if (external_recommended_loader.get()) {
536 provider_list->push_back(linked_ptr<ExternalProviderInterface>(
537 new ExternalProviderImpl(service,
538 external_recommended_loader,
539 profile,
540 crx_location,
541 Manifest::EXTERNAL_PREF_DOWNLOAD,
542 Extension::NO_FLAGS)));
545 // In tests don't install extensions from default external sources.
546 // It would only slowdown tests and make them flaky.
547 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
548 switches::kDisableDefaultApps))
549 return;
551 // On Mac OS, items in /Library/... should be written by the superuser.
552 // Check that all components of the path are writable by root only.
553 ExternalPrefLoader::Options check_admin_permissions_on_mac;
554 #if defined(OS_MACOSX)
555 check_admin_permissions_on_mac =
556 ExternalPrefLoader::ENSURE_PATH_CONTROLLED_BY_ADMIN;
557 #else
558 check_admin_permissions_on_mac = ExternalPrefLoader::NONE;
559 #endif
561 #if !defined(OS_WIN)
562 int bundled_extension_creation_flags = Extension::NO_FLAGS;
563 #endif
564 #if defined(OS_CHROMEOS)
565 bundled_extension_creation_flags = Extension::FROM_WEBSTORE |
566 Extension::WAS_INSTALLED_BY_DEFAULT;
568 if (!is_chrome_os_public_session) {
569 int external_apps_path_id = profile->IsSupervised() ?
570 chrome::DIR_SUPERVISED_USERS_DEFAULT_APPS :
571 chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS;
572 ExternalPrefLoader::Options pref_load_flags =
573 profile->IsNewProfile()
574 ? ExternalPrefLoader::DELAY_LOAD_UNTIL_PRIORITY_SYNC
575 : ExternalPrefLoader::NONE;
576 provider_list->push_back(
577 linked_ptr<ExternalProviderInterface>(new ExternalProviderImpl(
578 service, new ExternalPrefLoader(external_apps_path_id,
579 pref_load_flags, profile),
580 profile, Manifest::EXTERNAL_PREF, Manifest::EXTERNAL_PREF_DOWNLOAD,
581 bundled_extension_creation_flags)));
583 // OEM default apps.
584 int oem_extension_creation_flags =
585 bundled_extension_creation_flags | Extension::WAS_INSTALLED_BY_OEM;
586 chromeos::ServicesCustomizationDocument* customization =
587 chromeos::ServicesCustomizationDocument::GetInstance();
588 provider_list->push_back(linked_ptr<ExternalProviderInterface>(
589 new ExternalProviderImpl(service,
590 customization->CreateExternalLoader(profile),
591 profile,
592 Manifest::EXTERNAL_PREF,
593 Manifest::EXTERNAL_PREF_DOWNLOAD,
594 oem_extension_creation_flags)));
596 #elif defined(OS_LINUX)
597 if (!profile->IsLegacySupervised()) {
598 provider_list->push_back(
599 linked_ptr<ExternalProviderInterface>(
600 new ExternalProviderImpl(
601 service,
602 new ExternalPrefLoader(
603 chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS,
604 ExternalPrefLoader::NONE,
605 NULL),
606 profile,
607 Manifest::EXTERNAL_PREF,
608 Manifest::EXTERNAL_PREF_DOWNLOAD,
609 bundled_extension_creation_flags)));
611 #endif
613 if (!profile->IsLegacySupervised()) {
614 #if defined(OS_WIN)
615 provider_list->push_back(
616 linked_ptr<ExternalProviderInterface>(
617 new ExternalProviderImpl(
618 service,
619 new ExternalRegistryLoader,
620 profile,
621 Manifest::EXTERNAL_REGISTRY,
622 Manifest::EXTERNAL_PREF_DOWNLOAD,
623 Extension::NO_FLAGS)));
624 #else
625 provider_list->push_back(
626 linked_ptr<ExternalProviderInterface>(
627 new ExternalProviderImpl(
628 service,
629 new ExternalPrefLoader(chrome::DIR_EXTERNAL_EXTENSIONS,
630 check_admin_permissions_on_mac,
631 NULL),
632 profile,
633 Manifest::EXTERNAL_PREF,
634 Manifest::EXTERNAL_PREF_DOWNLOAD,
635 bundled_extension_creation_flags)));
637 // Define a per-user source of external extensions.
638 #if defined(OS_MACOSX) || (defined(OS_LINUX) && defined(CHROMIUM_BUILD))
639 provider_list->push_back(
640 linked_ptr<ExternalProviderInterface>(
641 new ExternalProviderImpl(
642 service,
643 new ExternalPrefLoader(chrome::DIR_USER_EXTERNAL_EXTENSIONS,
644 ExternalPrefLoader::NONE,
645 NULL),
646 profile,
647 Manifest::EXTERNAL_PREF,
648 Manifest::EXTERNAL_PREF_DOWNLOAD,
649 Extension::NO_FLAGS)));
650 #endif
651 #endif
653 #if !defined(OS_CHROMEOS)
654 // The default apps are installed as INTERNAL but use the external
655 // extension installer codeflow.
656 provider_list->push_back(
657 linked_ptr<ExternalProviderInterface>(
658 new default_apps::Provider(
659 profile,
660 service,
661 new ExternalPrefLoader(chrome::DIR_DEFAULT_APPS,
662 ExternalPrefLoader::NONE,
663 NULL),
664 Manifest::INTERNAL,
665 Manifest::INTERNAL,
666 Extension::FROM_WEBSTORE |
667 Extension::WAS_INSTALLED_BY_DEFAULT)));
668 #endif
670 scoped_ptr<ExternalProviderImpl> drive_migration_provider(
671 new ExternalProviderImpl(
672 service,
673 new ExtensionMigrator(profile,
674 extension_misc::kDriveHostedAppId,
675 extension_misc::kDriveExtensionId),
676 profile,
677 Manifest::EXTERNAL_PREF,
678 Manifest::EXTERNAL_PREF_DOWNLOAD,
679 Extension::FROM_WEBSTORE |
680 Extension::WAS_INSTALLED_BY_DEFAULT));
681 drive_migration_provider->set_auto_acknowledge(true);
682 provider_list->push_back(linked_ptr<ExternalProviderInterface>(
683 drive_migration_provider.release()));
686 provider_list->push_back(
687 linked_ptr<ExternalProviderInterface>(
688 new ExternalProviderImpl(
689 service,
690 new ExternalComponentLoader(profile),
691 profile,
692 Manifest::INVALID_LOCATION,
693 Manifest::EXTERNAL_COMPONENT,
694 Extension::FROM_WEBSTORE | Extension::WAS_INSTALLED_BY_DEFAULT)));
697 } // namespace extensions