Switch global error menu icon to vectorized MD asset
[chromium-blink-merge.git] / chrome / browser / extensions / component_loader.cc
blobe92e237850729fe74853f65b7c571b7264c144a8
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/component_loader.h"
7 #include <string>
9 #include "base/command_line.h"
10 #include "base/files/file_util.h"
11 #include "base/json/json_string_value_serializer.h"
12 #include "base/metrics/field_trial.h"
13 #include "base/metrics/histogram_macros.h"
14 #include "base/path_service.h"
15 #include "base/profiler/scoped_profile.h"
16 #include "base/time/time.h"
17 #include "base/trace_event/trace_event.h"
18 #include "chrome/browser/extensions/component_extensions_whitelist/whitelist.h"
19 #include "chrome/browser/extensions/data_deleter.h"
20 #include "chrome/browser/extensions/extension_service.h"
21 #include "chrome/browser/pdf/pdf_extension_util.h"
22 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/browser/search/hotword_service.h"
24 #include "chrome/browser/search/hotword_service_factory.h"
25 #include "chrome/browser/signin/signin_manager_factory.h"
26 #include "chrome/common/channel_info.h"
27 #include "chrome/common/chrome_paths.h"
28 #include "chrome/common/chrome_switches.h"
29 #include "chrome/common/extensions/extension_constants.h"
30 #include "chrome/grit/generated_resources.h"
31 #include "components/crx_file/id_util.h"
32 #include "components/signin/core/browser/signin_manager.h"
33 #include "components/signin/core/browser/signin_manager_base.h"
34 #include "components/version_info/version_info.h"
35 #include "content/public/browser/browser_thread.h"
36 #include "content/public/browser/plugin_service.h"
37 #include "extensions/common/constants.h"
38 #include "extensions/common/extension.h"
39 #include "extensions/common/extension_l10n_util.h"
40 #include "extensions/common/file_util.h"
41 #include "extensions/common/manifest_constants.h"
42 #include "grit/browser_resources.h"
43 #include "ui/base/l10n/l10n_util.h"
44 #include "ui/base/resource/resource_bundle.h"
46 #if defined(OS_CHROMEOS)
47 #include "ash/system/chromeos/devicetype_utils.h"
48 #include "components/chrome_apps/grit/chrome_apps_resources.h"
49 #include "components/user_manager/user_manager.h"
50 #include "grit/keyboard_resources.h"
51 #include "ui/file_manager/grit/file_manager_resources.h"
52 #include "ui/keyboard/keyboard_util.h"
53 #endif
55 #if defined(GOOGLE_CHROME_BUILD)
56 #include "chrome/browser/defaults.h"
57 #endif
59 #if defined(OS_CHROMEOS)
60 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
61 #include "chromeos/chromeos_switches.h"
62 #include "content/public/browser/site_instance.h"
63 #include "content/public/browser/storage_partition.h"
64 #include "extensions/browser/extensions_browser_client.h"
65 #include "storage/browser/fileapi/file_system_context.h"
66 #endif
68 #if defined(ENABLE_APP_LIST)
69 #include "chrome/grit/chromium_strings.h"
70 #endif
72 #if defined(ENABLE_APP_LIST) && defined(OS_CHROMEOS)
73 #include "chrome/browser/ui/app_list/google_now_extension.h"
74 #endif
76 using content::BrowserThread;
78 namespace extensions {
80 namespace {
82 static bool enable_background_extensions_during_testing = false;
84 std::string GenerateId(const base::DictionaryValue* manifest,
85 const base::FilePath& path) {
86 std::string raw_key;
87 std::string id_input;
88 CHECK(manifest->GetString(manifest_keys::kPublicKey, &raw_key));
89 CHECK(Extension::ParsePEMKeyBytes(raw_key, &id_input));
90 std::string id = crx_file::id_util::GenerateId(id_input);
91 return id;
94 #if defined(OS_CHROMEOS)
95 scoped_ptr<base::DictionaryValue>
96 LoadManifestOnFileThread(
97 const base::FilePath& root_directory,
98 const base::FilePath::CharType* manifest_filename) {
99 DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
100 std::string error;
101 scoped_ptr<base::DictionaryValue> manifest(
102 file_util::LoadManifest(root_directory, manifest_filename, &error));
103 if (!manifest) {
104 LOG(ERROR) << "Can't load "
105 << root_directory.Append(manifest_filename).AsUTF8Unsafe()
106 << ": " << error;
107 return nullptr;
109 bool localized = extension_l10n_util::LocalizeExtension(
110 root_directory, manifest.get(), &error);
111 CHECK(localized) << error;
112 return manifest.Pass();
115 bool IsNormalSession() {
116 return !base::CommandLine::ForCurrentProcess()->HasSwitch(
117 chromeos::switches::kGuestSession) &&
118 user_manager::UserManager::IsInitialized() &&
119 user_manager::UserManager::Get()->IsUserLoggedIn();
121 #endif // defined(OS_CHROMEOS)
123 } // namespace
125 ComponentLoader::ComponentExtensionInfo::ComponentExtensionInfo(
126 const base::DictionaryValue* manifest, const base::FilePath& directory)
127 : manifest(manifest),
128 root_directory(directory) {
129 if (!root_directory.IsAbsolute()) {
130 CHECK(PathService::Get(chrome::DIR_RESOURCES, &root_directory));
131 root_directory = root_directory.Append(directory);
133 extension_id = GenerateId(manifest, root_directory);
136 ComponentLoader::ComponentLoader(ExtensionServiceInterface* extension_service,
137 PrefService* profile_prefs,
138 PrefService* local_state,
139 Profile* profile)
140 : profile_prefs_(profile_prefs),
141 local_state_(local_state),
142 profile_(profile),
143 extension_service_(extension_service),
144 ignore_whitelist_for_testing_(false),
145 weak_factory_(this) {}
147 ComponentLoader::~ComponentLoader() {
148 ClearAllRegistered();
151 void ComponentLoader::LoadAll() {
152 TRACE_EVENT0("browser,startup", "ComponentLoader::LoadAll");
153 TRACK_SCOPED_REGION("Startup", "ComponentLoader::LoadAll");
154 SCOPED_UMA_HISTOGRAM_TIMER("Extensions.LoadAllComponentTime");
156 for (RegisteredComponentExtensions::iterator it =
157 component_extensions_.begin();
158 it != component_extensions_.end(); ++it) {
159 Load(*it);
163 base::DictionaryValue* ComponentLoader::ParseManifest(
164 const std::string& manifest_contents) const {
165 JSONStringValueDeserializer deserializer(manifest_contents);
166 scoped_ptr<base::Value> manifest(deserializer.Deserialize(NULL, NULL));
168 if (!manifest.get() || !manifest->IsType(base::Value::TYPE_DICTIONARY)) {
169 LOG(ERROR) << "Failed to parse extension manifest.";
170 return NULL;
172 // Transfer ownership to the caller.
173 return static_cast<base::DictionaryValue*>(manifest.release());
176 void ComponentLoader::ClearAllRegistered() {
177 for (RegisteredComponentExtensions::iterator it =
178 component_extensions_.begin();
179 it != component_extensions_.end(); ++it) {
180 delete it->manifest;
183 component_extensions_.clear();
186 std::string ComponentLoader::GetExtensionID(
187 int manifest_resource_id,
188 const base::FilePath& root_directory) {
189 std::string manifest_contents = ResourceBundle::GetSharedInstance().
190 GetRawDataResource(manifest_resource_id).as_string();
191 base::DictionaryValue* manifest = ParseManifest(manifest_contents);
192 if (!manifest)
193 return std::string();
195 ComponentExtensionInfo info(manifest, root_directory);
196 return info.extension_id;
199 std::string ComponentLoader::Add(int manifest_resource_id,
200 const base::FilePath& root_directory) {
201 if (!ignore_whitelist_for_testing_ &&
202 !IsComponentExtensionWhitelisted(manifest_resource_id))
203 return std::string();
205 std::string manifest_contents =
206 ResourceBundle::GetSharedInstance().GetRawDataResource(
207 manifest_resource_id).as_string();
208 return Add(manifest_contents, root_directory, true);
211 std::string ComponentLoader::Add(const std::string& manifest_contents,
212 const base::FilePath& root_directory) {
213 return Add(manifest_contents, root_directory, false);
216 std::string ComponentLoader::Add(const std::string& manifest_contents,
217 const base::FilePath& root_directory,
218 bool skip_whitelist) {
219 // The Value is kept for the lifetime of the ComponentLoader. This is
220 // required in case LoadAll() is called again.
221 base::DictionaryValue* manifest = ParseManifest(manifest_contents);
222 if (manifest)
223 return Add(manifest, root_directory, skip_whitelist);
224 return std::string();
227 std::string ComponentLoader::Add(const base::DictionaryValue* parsed_manifest,
228 const base::FilePath& root_directory,
229 bool skip_whitelist) {
230 ComponentExtensionInfo info(parsed_manifest, root_directory);
231 if (!ignore_whitelist_for_testing_ &&
232 !skip_whitelist &&
233 !IsComponentExtensionWhitelisted(info.extension_id))
234 return std::string();
236 component_extensions_.push_back(info);
237 if (extension_service_->is_ready())
238 Load(info);
239 return info.extension_id;
242 std::string ComponentLoader::AddOrReplace(const base::FilePath& path) {
243 base::FilePath absolute_path = base::MakeAbsoluteFilePath(path);
244 std::string error;
245 scoped_ptr<base::DictionaryValue> manifest(
246 file_util::LoadManifest(absolute_path, &error));
247 if (!manifest) {
248 LOG(ERROR) << "Could not load extension from '" <<
249 absolute_path.value() << "'. " << error;
250 return std::string();
252 Remove(GenerateId(manifest.get(), absolute_path));
254 // We don't check component extensions loaded by path because this is only
255 // used by developers for testing.
256 return Add(manifest.release(), absolute_path, true);
259 void ComponentLoader::Reload(const std::string& extension_id) {
260 for (RegisteredComponentExtensions::iterator it =
261 component_extensions_.begin(); it != component_extensions_.end();
262 ++it) {
263 if (it->extension_id == extension_id) {
264 Load(*it);
265 break;
270 void ComponentLoader::Load(const ComponentExtensionInfo& info) {
271 std::string error;
272 scoped_refptr<const Extension> extension(CreateExtension(info, &error));
273 if (!extension.get()) {
274 LOG(ERROR) << error;
275 return;
278 CHECK_EQ(info.extension_id, extension->id()) << extension->name();
279 extension_service_->AddComponentExtension(extension.get());
282 void ComponentLoader::Remove(const base::FilePath& root_directory) {
283 // Find the ComponentExtensionInfo for the extension.
284 RegisteredComponentExtensions::iterator it = component_extensions_.begin();
285 for (; it != component_extensions_.end(); ++it) {
286 if (it->root_directory == root_directory) {
287 Remove(GenerateId(it->manifest, root_directory));
288 break;
293 void ComponentLoader::Remove(const std::string& id) {
294 RegisteredComponentExtensions::iterator it = component_extensions_.begin();
295 for (; it != component_extensions_.end(); ++it) {
296 if (it->extension_id == id) {
297 UnloadComponent(&(*it));
298 it = component_extensions_.erase(it);
299 break;
304 bool ComponentLoader::Exists(const std::string& id) const {
305 RegisteredComponentExtensions::const_iterator it =
306 component_extensions_.begin();
307 for (; it != component_extensions_.end(); ++it)
308 if (it->extension_id == id)
309 return true;
310 return false;
313 void ComponentLoader::AddFileManagerExtension() {
314 #if defined(OS_CHROMEOS)
315 AddWithNameAndDescription(
316 IDR_FILEMANAGER_MANIFEST,
317 base::FilePath(FILE_PATH_LITERAL("file_manager")),
318 l10n_util::GetStringUTF8(IDS_FILEMANAGER_APP_NAME),
319 l10n_util::GetStringUTF8(IDS_FILEMANAGER_APP_DESCRIPTION));
320 #endif // defined(OS_CHROMEOS)
323 void ComponentLoader::AddVideoPlayerExtension() {
324 #if defined(OS_CHROMEOS)
325 Add(IDR_VIDEO_PLAYER_MANIFEST,
326 base::FilePath(FILE_PATH_LITERAL("video_player")));
327 #endif // defined(OS_CHROMEOS)
330 void ComponentLoader::AddAudioPlayerExtension() {
331 #if defined(OS_CHROMEOS)
332 Add(IDR_AUDIO_PLAYER_MANIFEST,
333 base::FilePath(FILE_PATH_LITERAL("audio_player")));
334 #endif // defined(OS_CHROMEOS)
337 void ComponentLoader::AddGalleryExtension() {
338 #if defined(OS_CHROMEOS)
339 Add(IDR_GALLERY_MANIFEST, base::FilePath(FILE_PATH_LITERAL("gallery")));
340 #endif
343 void ComponentLoader::AddWebstoreWidgetExtension() {
344 #if defined(OS_CHROMEOS)
345 AddWithNameAndDescription(
346 IDR_CHROME_APPS_WEBSTORE_WIDGET_MANIFEST,
347 base::FilePath(FILE_PATH_LITERAL("webstore_widget")),
348 l10n_util::GetStringUTF8(IDS_WEBSTORE_WIDGET_APP_NAME),
349 l10n_util::GetStringUTF8(IDS_WEBSTORE_WIDGET_APP_DESC));
350 #endif
353 void ComponentLoader::AddHangoutServicesExtension() {
354 #if defined(GOOGLE_CHROME_BUILD) || defined(ENABLE_HANGOUT_SERVICES_EXTENSION)
355 Add(IDR_HANGOUT_SERVICES_MANIFEST,
356 base::FilePath(FILE_PATH_LITERAL("hangout_services")));
357 #endif
360 void ComponentLoader::AddHotwordAudioVerificationApp() {
361 if (HotwordServiceFactory::IsAlwaysOnAvailable()) {
362 Add(IDR_HOTWORD_AUDIO_VERIFICATION_MANIFEST,
363 base::FilePath(FILE_PATH_LITERAL("hotword_audio_verification")));
367 void ComponentLoader::AddHotwordHelperExtension() {
368 if (HotwordServiceFactory::IsHotwordAllowed(profile_)) {
369 Add(IDR_HOTWORD_MANIFEST,
370 base::FilePath(FILE_PATH_LITERAL("hotword")));
374 void ComponentLoader::AddImageLoaderExtension() {
375 #if defined(IMAGE_LOADER_EXTENSION)
376 Add(IDR_IMAGE_LOADER_MANIFEST,
377 base::FilePath(FILE_PATH_LITERAL("image_loader")));
378 #endif // defined(IMAGE_LOADER_EXTENSION)
381 void ComponentLoader::AddNetworkSpeechSynthesisExtension() {
382 Add(IDR_NETWORK_SPEECH_SYNTHESIS_MANIFEST,
383 base::FilePath(FILE_PATH_LITERAL("network_speech_synthesis")));
386 void ComponentLoader::AddGoogleNowExtension() {
387 #if defined(ENABLE_GOOGLE_NOW)
388 const char kEnablePrefix[] = "Enable";
389 const char kFieldTrialName[] = "GoogleNow";
390 std::string enable_prefix(kEnablePrefix);
391 std::string field_trial_result =
392 base::FieldTrialList::FindFullName(kFieldTrialName);
394 bool enabled_via_field_trial =
395 field_trial_result.compare(0, enable_prefix.length(), enable_prefix) == 0;
397 // Enable the feature on trybots and trunk builds.
398 bool enabled_via_trunk_build =
399 chrome::GetChannel() == version_info::Channel::UNKNOWN;
401 bool is_authenticated =
402 SigninManagerFactory::GetForProfile(profile_)->IsAuthenticated();
404 bool enabled =
405 (enabled_via_field_trial && is_authenticated) || enabled_via_trunk_build;
407 #if defined(ENABLE_APP_LIST) && defined(OS_CHROMEOS)
408 // Don't load if newer trial is running (== new extension id is available).
409 std::string ignored_extension_id;
410 if (GetGoogleNowExtensionId(&ignored_extension_id)) {
411 enabled = false;
413 #endif // defined(ENABLE_APP_LIST) && defined(OS_CHROMEOS)
415 const int google_now_manifest_id = IDR_GOOGLE_NOW_MANIFEST;
416 const base::FilePath root_directory =
417 base::FilePath(FILE_PATH_LITERAL("google_now"));
418 if (enabled) {
419 Add(google_now_manifest_id, root_directory);
420 } else {
421 DeleteData(google_now_manifest_id, root_directory);
423 #endif // defined(ENABLE_GOOGLE_NOW)
426 #if defined(OS_CHROMEOS)
427 void ComponentLoader::AddChromeVoxExtension(
428 const base::Closure& done_cb) {
429 base::FilePath resources_path;
430 CHECK(PathService::Get(chrome::DIR_RESOURCES, &resources_path));
432 base::FilePath chromevox_path =
433 resources_path.Append(extension_misc::kChromeVoxExtensionPath);
435 const base::FilePath::CharType* manifest_filename =
436 IsNormalSession() ? extensions::kManifestFilename
437 : extension_misc::kGuestManifestFilename;
438 AddWithManifestFile(
439 manifest_filename,
440 chromevox_path,
441 extension_misc::kChromeVoxExtensionId,
442 done_cb);
445 void ComponentLoader::AddChromeOsSpeechSynthesisExtension() {
446 const base::FilePath::CharType* manifest_filename =
447 IsNormalSession() ? extensions::kManifestFilename
448 : extension_misc::kGuestManifestFilename;
449 AddWithManifestFile(
450 manifest_filename,
451 base::FilePath(extension_misc::kSpeechSynthesisExtensionPath),
452 extension_misc::kSpeechSynthesisExtensionId,
453 base::Bind(&ComponentLoader::EnableFileSystemInGuestMode,
454 weak_factory_.GetWeakPtr(),
455 extension_misc::kChromeVoxExtensionId));
457 #endif
459 void ComponentLoader::AddWithNameAndDescription(
460 int manifest_resource_id,
461 const base::FilePath& root_directory,
462 const std::string& name_string,
463 const std::string& description_string) {
464 if (!ignore_whitelist_for_testing_ &&
465 !IsComponentExtensionWhitelisted(manifest_resource_id))
466 return;
468 std::string manifest_contents =
469 ResourceBundle::GetSharedInstance().GetRawDataResource(
470 manifest_resource_id).as_string();
472 // The Value is kept for the lifetime of the ComponentLoader. This is
473 // required in case LoadAll() is called again.
474 base::DictionaryValue* manifest = ParseManifest(manifest_contents);
476 if (manifest) {
477 manifest->SetString(manifest_keys::kName, name_string);
478 manifest->SetString(manifest_keys::kDescription, description_string);
479 Add(manifest, root_directory, true);
483 void ComponentLoader::AddChromeApp() {
484 #if defined(ENABLE_APP_LIST)
485 AddWithNameAndDescription(
486 IDR_CHROME_APP_MANIFEST, base::FilePath(FILE_PATH_LITERAL("chrome_app")),
487 l10n_util::GetStringUTF8(IDS_SHORT_PRODUCT_NAME),
488 l10n_util::GetStringUTF8(IDS_CHROME_SHORTCUT_DESCRIPTION));
489 #endif
492 void ComponentLoader::AddKeyboardApp() {
493 #if defined(OS_CHROMEOS)
494 Add(IDR_KEYBOARD_MANIFEST, base::FilePath(FILE_PATH_LITERAL("keyboard")));
495 #endif
498 void ComponentLoader::AddWebStoreApp() {
499 #if defined(OS_CHROMEOS)
500 if (!IsNormalSession())
501 return;
502 #endif
504 AddWithNameAndDescription(
505 IDR_WEBSTORE_MANIFEST, base::FilePath(FILE_PATH_LITERAL("web_store")),
506 l10n_util::GetStringUTF8(IDS_WEBSTORE_NAME_STORE),
507 l10n_util::GetStringUTF8(IDS_WEBSTORE_APP_DESCRIPTION));
510 scoped_refptr<const Extension> ComponentLoader::CreateExtension(
511 const ComponentExtensionInfo& info, std::string* utf8_error) {
512 // TODO(abarth): We should REQUIRE_MODERN_MANIFEST_VERSION once we've updated
513 // our component extensions to the new manifest version.
514 int flags = Extension::REQUIRE_KEY;
515 return Extension::Create(
516 info.root_directory,
517 Manifest::COMPONENT,
518 *info.manifest,
519 flags,
520 utf8_error);
523 // static
524 void ComponentLoader::EnableBackgroundExtensionsForTesting() {
525 enable_background_extensions_during_testing = true;
528 void ComponentLoader::AddDefaultComponentExtensions(
529 bool skip_session_components) {
530 // Do not add component extensions that have background pages here -- add them
531 // to AddDefaultComponentExtensionsWithBackgroundPages.
532 #if defined(OS_CHROMEOS)
533 Add(IDR_MOBILE_MANIFEST,
534 base::FilePath(FILE_PATH_LITERAL("/usr/share/chromeos-assets/mobile")));
536 #if defined(GOOGLE_CHROME_BUILD)
537 if (browser_defaults::enable_help_app) {
538 Add(IDR_HELP_MANIFEST, base::FilePath(FILE_PATH_LITERAL(
539 "/usr/share/chromeos-assets/helpapp")));
541 #endif
543 // Skip all other extensions that require user session presence.
544 if (!skip_session_components) {
545 const base::CommandLine* command_line =
546 base::CommandLine::ForCurrentProcess();
547 if (!command_line->HasSwitch(chromeos::switches::kGuestSession))
548 Add(IDR_BOOKMARKS_MANIFEST,
549 base::FilePath(FILE_PATH_LITERAL("bookmark_manager")));
551 Add(IDR_CROSH_BUILTIN_MANIFEST, base::FilePath(FILE_PATH_LITERAL(
552 "/usr/share/chromeos-assets/crosh_builtin")));
554 #else // !defined(OS_CHROMEOS)
555 DCHECK(!skip_session_components);
556 Add(IDR_BOOKMARKS_MANIFEST,
557 base::FilePath(FILE_PATH_LITERAL("bookmark_manager")));
558 // Cloud Print component app. Not required on Chrome OS.
559 Add(IDR_CLOUDPRINT_MANIFEST,
560 base::FilePath(FILE_PATH_LITERAL("cloud_print")));
561 #endif
563 if (!skip_session_components) {
564 AddWebStoreApp();
565 AddChromeApp();
568 AddKeyboardApp();
570 AddDefaultComponentExtensionsWithBackgroundPages(skip_session_components);
572 #if defined(ENABLE_PLUGINS)
573 Add(pdf_extension_util::GetManifest(),
574 base::FilePath(FILE_PATH_LITERAL("pdf")));
575 #endif
578 void ComponentLoader::AddDefaultComponentExtensionsForKioskMode(
579 bool skip_session_components) {
580 // No component extension for kiosk app launch splash screen.
581 if (skip_session_components)
582 return;
584 // Component extensions needed for kiosk apps.
585 AddFileManagerExtension();
587 // Add virtual keyboard.
588 AddKeyboardApp();
590 #if defined(ENABLE_PLUGINS)
591 Add(pdf_extension_util::GetManifest(),
592 base::FilePath(FILE_PATH_LITERAL("pdf")));
593 #endif
596 void ComponentLoader::AddDefaultComponentExtensionsWithBackgroundPages(
597 bool skip_session_components) {
598 const base::CommandLine* command_line =
599 base::CommandLine::ForCurrentProcess();
601 // Component extensions with background pages are not enabled during tests
602 // because they generate a lot of background behavior that can interfere.
603 if (!enable_background_extensions_during_testing &&
604 (command_line->HasSwitch(switches::kTestType) ||
605 command_line->HasSwitch(
606 switches::kDisableComponentExtensionsWithBackgroundPages))) {
607 return;
610 #if defined(OS_CHROMEOS) && defined(GOOGLE_CHROME_BUILD)
611 // Since this is a v2 app it has a background page.
612 AddWithNameAndDescription(
613 IDR_GENIUS_APP_MANIFEST, base::FilePath(FILE_PATH_LITERAL(
614 "/usr/share/chromeos-assets/genius_app")),
615 l10n_util::GetStringUTF8(IDS_GENIUS_APP_NAME),
616 l10n_util::GetStringFUTF8(IDS_GENIUS_APP_DESCRIPTION,
617 ash::GetChromeOSDeviceName()));
618 #endif
620 if (!skip_session_components) {
621 AddVideoPlayerExtension();
622 AddAudioPlayerExtension();
623 AddFileManagerExtension();
624 AddGalleryExtension();
625 AddWebstoreWidgetExtension();
627 AddHangoutServicesExtension();
628 AddHotwordAudioVerificationApp();
629 AddHotwordHelperExtension();
630 AddImageLoaderExtension();
631 AddGoogleNowExtension();
633 bool install_feedback = enable_background_extensions_during_testing;
634 #if defined(GOOGLE_CHROME_BUILD)
635 install_feedback = true;
636 #endif // defined(GOOGLE_CHROME_BUILD)
637 if (install_feedback)
638 Add(IDR_FEEDBACK_MANIFEST, base::FilePath(FILE_PATH_LITERAL("feedback")));
640 #if defined(ENABLE_SETTINGS_APP)
641 Add(IDR_SETTINGS_APP_MANIFEST,
642 base::FilePath(FILE_PATH_LITERAL("settings_app")));
643 #endif
646 #if defined(OS_CHROMEOS)
647 if (!skip_session_components) {
648 #if defined(GOOGLE_CHROME_BUILD)
649 if (!command_line->HasSwitch(
650 chromeos::switches::kDisableOfficeEditingComponentApp)) {
651 std::string id = Add(IDR_QUICKOFFICE_MANIFEST, base::FilePath(
652 FILE_PATH_LITERAL("/usr/share/chromeos-assets/quickoffice")));
653 EnableFileSystemInGuestMode(id);
655 #endif // defined(GOOGLE_CHROME_BUILD)
657 Add(IDR_ECHO_MANIFEST,
658 base::FilePath(FILE_PATH_LITERAL("/usr/share/chromeos-assets/echo")));
660 if (!command_line->HasSwitch(chromeos::switches::kGuestSession)) {
661 Add(IDR_WALLPAPERMANAGER_MANIFEST,
662 base::FilePath(FILE_PATH_LITERAL("chromeos/wallpaper_manager")));
665 Add(IDR_FIRST_RUN_DIALOG_MANIFEST,
666 base::FilePath(FILE_PATH_LITERAL("chromeos/first_run/app")));
668 Add(IDR_CONNECTIVITY_DIAGNOSTICS_MANIFEST,
669 base::FilePath(extension_misc::kConnectivityDiagnosticsPath));
670 Add(IDR_CONNECTIVITY_DIAGNOSTICS_LAUNCHER_MANIFEST,
671 base::FilePath(extension_misc::kConnectivityDiagnosticsLauncherPath));
674 // Load ChromeVox extension now if spoken feedback is enabled.
675 if (chromeos::AccessibilityManager::Get() &&
676 chromeos::AccessibilityManager::Get()->IsSpokenFeedbackEnabled()) {
677 AddChromeVoxExtension(base::Closure());
679 #endif // defined(OS_CHROMEOS)
681 #if defined(GOOGLE_CHROME_BUILD)
682 #if !defined(OS_CHROMEOS) // http://crbug.com/314799
683 AddNetworkSpeechSynthesisExtension();
684 #endif
686 #endif // defined(GOOGLE_CHROME_BUILD)
688 Add(IDR_CRYPTOTOKEN_MANIFEST,
689 base::FilePath(FILE_PATH_LITERAL("cryptotoken")));
692 void ComponentLoader::DeleteData(int manifest_resource_id,
693 const base::FilePath& root_directory) {
694 std::string manifest_contents =
695 ResourceBundle::GetSharedInstance().GetRawDataResource(
696 manifest_resource_id).as_string();
697 base::DictionaryValue* manifest = ParseManifest(manifest_contents);
698 if (!manifest)
699 return;
701 ComponentExtensionInfo info(manifest, root_directory);
702 std::string error;
703 scoped_refptr<const Extension> extension(CreateExtension(info, &error));
704 if (!extension.get()) {
705 LOG(ERROR) << error;
706 return;
709 DataDeleter::StartDeleting(
710 profile_, extension.get(), base::Bind(base::DoNothing));
713 void ComponentLoader::UnloadComponent(ComponentExtensionInfo* component) {
714 delete component->manifest;
715 if (extension_service_->is_ready()) {
716 extension_service_->
717 RemoveComponentExtension(component->extension_id);
721 void ComponentLoader::EnableFileSystemInGuestMode(const std::string& id) {
722 #if defined(OS_CHROMEOS)
723 if (!IsNormalSession()) {
724 // TODO(dpolukhin): Hack to enable HTML5 temporary file system for
725 // the extension. Some component extensions don't work without temporary
726 // file system access. Make sure temporary file system is enabled in the off
727 // the record browser context (as that is the one used in guest session).
728 content::BrowserContext* off_the_record_context =
729 ExtensionsBrowserClient::Get()->GetOffTheRecordContext(profile_);
730 GURL site = content::SiteInstance::GetSiteForURL(
731 off_the_record_context, Extension::GetBaseURLFromExtensionId(id));
732 storage::FileSystemContext* file_system_context =
733 content::BrowserContext::GetStoragePartitionForSite(
734 off_the_record_context, site)->GetFileSystemContext();
735 file_system_context->EnableTemporaryFileSystemInIncognito();
737 #endif
740 #if defined(OS_CHROMEOS)
741 void ComponentLoader::AddWithManifestFile(
742 const base::FilePath::CharType* manifest_filename,
743 const base::FilePath& root_directory,
744 const char* extension_id,
745 const base::Closure& done_cb) {
746 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
747 BrowserThread::PostTaskAndReplyWithResult(
748 BrowserThread::FILE,
749 FROM_HERE,
750 base::Bind(&LoadManifestOnFileThread, root_directory, manifest_filename),
751 base::Bind(&ComponentLoader::FinishAddWithManifestFile,
752 weak_factory_.GetWeakPtr(),
753 root_directory,
754 extension_id,
755 done_cb));
758 void ComponentLoader::FinishAddWithManifestFile(
759 const base::FilePath& root_directory,
760 const char* extension_id,
761 const base::Closure& done_cb,
762 scoped_ptr<base::DictionaryValue> manifest) {
763 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
764 if (!manifest)
765 return; // Error already logged.
766 std::string actual_extension_id = Add(
767 manifest.release(),
768 root_directory,
769 false);
770 CHECK_EQ(extension_id, actual_extension_id);
771 if (!done_cb.is_null())
772 done_cb.Run();
774 #endif
776 } // namespace extensions