Prevent chrome://net-internals/#export from flickering
[chromium-blink-merge.git] / chrome / browser / extensions / component_loader.cc
blobed34824ebc0bab24cf57f61556c3a28ce6163519
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/time/time.h"
16 #include "base/trace_event/trace_event.h"
17 #include "chrome/browser/extensions/extension_service.h"
18 #include "chrome/browser/pdf/pdf_extension_util.h"
19 #include "chrome/browser/search/hotword_service.h"
20 #include "chrome/browser/search/hotword_service_factory.h"
21 #include "chrome/common/chrome_paths.h"
22 #include "chrome/common/chrome_switches.h"
23 #include "chrome/common/chrome_version_info.h"
24 #include "chrome/common/extensions/extension_constants.h"
25 #include "chrome/grit/generated_resources.h"
26 #include "components/crx_file/id_util.h"
27 #include "content/public/browser/browser_context.h"
28 #include "content/public/browser/browser_thread.h"
29 #include "content/public/browser/plugin_service.h"
30 #include "extensions/common/extension.h"
31 #include "extensions/common/extension_l10n_util.h"
32 #include "extensions/common/file_util.h"
33 #include "extensions/common/manifest_constants.h"
34 #include "grit/browser_resources.h"
35 #include "ui/base/l10n/l10n_util.h"
36 #include "ui/base/resource/resource_bundle.h"
38 #if defined(OS_CHROMEOS)
39 #include "components/user_manager/user_manager.h"
40 #include "grit/keyboard_resources.h"
41 #include "ui/file_manager/grit/file_manager_resources.h"
42 #include "ui/keyboard/keyboard_util.h"
43 #endif
45 #if defined(GOOGLE_CHROME_BUILD)
46 #include "chrome/browser/defaults.h"
47 #endif
49 #if defined(OS_CHROMEOS)
50 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
51 #include "chromeos/chromeos_switches.h"
52 #include "content/public/browser/site_instance.h"
53 #include "content/public/browser/storage_partition.h"
54 #include "extensions/browser/extensions_browser_client.h"
55 #include "storage/browser/fileapi/file_system_context.h"
56 #endif
58 #if defined(ENABLE_APP_LIST)
59 #include "chrome/grit/chromium_strings.h"
60 #endif
62 #if defined(ENABLE_APP_LIST) && defined(OS_CHROMEOS)
63 #include "chrome/browser/ui/app_list/google_now_extension.h"
64 #endif
66 using content::BrowserThread;
68 namespace extensions {
70 namespace {
72 static bool enable_background_extensions_during_testing = false;
74 std::string GenerateId(const base::DictionaryValue* manifest,
75 const base::FilePath& path) {
76 std::string raw_key;
77 std::string id_input;
78 CHECK(manifest->GetString(manifest_keys::kPublicKey, &raw_key));
79 CHECK(Extension::ParsePEMKeyBytes(raw_key, &id_input));
80 std::string id = crx_file::id_util::GenerateId(id_input);
81 return id;
84 #if defined(OS_CHROMEOS)
85 scoped_ptr<base::DictionaryValue>
86 LoadManifestOnFileThread(
87 const base::FilePath& chromevox_path, const char* manifest_filename) {
88 DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
89 std::string error;
90 scoped_ptr<base::DictionaryValue> manifest(
91 file_util::LoadManifest(chromevox_path, manifest_filename, &error));
92 CHECK(manifest) << error;
93 bool localized = extension_l10n_util::LocalizeExtension(
94 chromevox_path, manifest.get(), &error);
95 CHECK(localized) << error;
96 return manifest.Pass();
99 bool IsNormalSession() {
100 return !base::CommandLine::ForCurrentProcess()->HasSwitch(
101 chromeos::switches::kGuestSession) &&
102 user_manager::UserManager::IsInitialized() &&
103 user_manager::UserManager::Get()->IsUserLoggedIn();
105 #endif // defined(OS_CHROMEOS)
107 } // namespace
109 ComponentLoader::ComponentExtensionInfo::ComponentExtensionInfo(
110 const base::DictionaryValue* manifest, const base::FilePath& directory)
111 : manifest(manifest),
112 root_directory(directory) {
113 if (!root_directory.IsAbsolute()) {
114 CHECK(PathService::Get(chrome::DIR_RESOURCES, &root_directory));
115 root_directory = root_directory.Append(directory);
117 extension_id = GenerateId(manifest, root_directory);
120 ComponentLoader::ComponentLoader(ExtensionServiceInterface* extension_service,
121 PrefService* profile_prefs,
122 PrefService* local_state,
123 content::BrowserContext* browser_context)
124 : profile_prefs_(profile_prefs),
125 local_state_(local_state),
126 browser_context_(browser_context),
127 extension_service_(extension_service),
128 weak_factory_(this) {}
130 ComponentLoader::~ComponentLoader() {
131 ClearAllRegistered();
134 void ComponentLoader::LoadAll() {
135 TRACE_EVENT0("browser,startup", "ComponentLoader::LoadAll");
136 SCOPED_UMA_HISTOGRAM_TIMER("Extensions.LoadAllComponentTime");
138 for (RegisteredComponentExtensions::iterator it =
139 component_extensions_.begin();
140 it != component_extensions_.end(); ++it) {
141 Load(*it);
145 base::DictionaryValue* ComponentLoader::ParseManifest(
146 const std::string& manifest_contents) const {
147 JSONStringValueDeserializer deserializer(manifest_contents);
148 scoped_ptr<base::Value> manifest(deserializer.Deserialize(NULL, NULL));
150 if (!manifest.get() || !manifest->IsType(base::Value::TYPE_DICTIONARY)) {
151 LOG(ERROR) << "Failed to parse extension manifest.";
152 return NULL;
154 // Transfer ownership to the caller.
155 return static_cast<base::DictionaryValue*>(manifest.release());
158 void ComponentLoader::ClearAllRegistered() {
159 for (RegisteredComponentExtensions::iterator it =
160 component_extensions_.begin();
161 it != component_extensions_.end(); ++it) {
162 delete it->manifest;
165 component_extensions_.clear();
168 std::string ComponentLoader::GetExtensionID(
169 int manifest_resource_id,
170 const base::FilePath& root_directory) {
171 std::string manifest_contents = ResourceBundle::GetSharedInstance().
172 GetRawDataResource(manifest_resource_id).as_string();
173 base::DictionaryValue* manifest = ParseManifest(manifest_contents);
174 if (!manifest)
175 return std::string();
177 ComponentExtensionInfo info(manifest, root_directory);
178 return info.extension_id;
181 std::string ComponentLoader::Add(int manifest_resource_id,
182 const base::FilePath& root_directory) {
183 std::string manifest_contents =
184 ResourceBundle::GetSharedInstance().GetRawDataResource(
185 manifest_resource_id).as_string();
186 return Add(manifest_contents, root_directory);
189 std::string ComponentLoader::Add(const std::string& manifest_contents,
190 const base::FilePath& root_directory) {
191 // The Value is kept for the lifetime of the ComponentLoader. This is
192 // required in case LoadAll() is called again.
193 base::DictionaryValue* manifest = ParseManifest(manifest_contents);
194 if (manifest)
195 return Add(manifest, root_directory);
196 return std::string();
199 std::string ComponentLoader::Add(const base::DictionaryValue* parsed_manifest,
200 const base::FilePath& root_directory) {
201 ComponentExtensionInfo info(parsed_manifest, root_directory);
202 component_extensions_.push_back(info);
203 if (extension_service_->is_ready())
204 Load(info);
205 return info.extension_id;
208 std::string ComponentLoader::AddOrReplace(const base::FilePath& path) {
209 base::FilePath absolute_path = base::MakeAbsoluteFilePath(path);
210 std::string error;
211 scoped_ptr<base::DictionaryValue> manifest(
212 file_util::LoadManifest(absolute_path, &error));
213 if (!manifest) {
214 LOG(ERROR) << "Could not load extension from '" <<
215 absolute_path.value() << "'. " << error;
216 return std::string();
218 Remove(GenerateId(manifest.get(), absolute_path));
220 return Add(manifest.release(), absolute_path);
223 void ComponentLoader::Reload(const std::string& extension_id) {
224 for (RegisteredComponentExtensions::iterator it =
225 component_extensions_.begin(); it != component_extensions_.end();
226 ++it) {
227 if (it->extension_id == extension_id) {
228 Load(*it);
229 break;
234 void ComponentLoader::Load(const ComponentExtensionInfo& info) {
235 // TODO(abarth): We should REQUIRE_MODERN_MANIFEST_VERSION once we've updated
236 // our component extensions to the new manifest version.
237 int flags = Extension::REQUIRE_KEY;
239 std::string error;
241 scoped_refptr<const Extension> extension(Extension::Create(
242 info.root_directory,
243 Manifest::COMPONENT,
244 *info.manifest,
245 flags,
246 &error));
247 if (!extension.get()) {
248 LOG(ERROR) << error;
249 return;
252 CHECK_EQ(info.extension_id, extension->id()) << extension->name();
253 extension_service_->AddComponentExtension(extension.get());
256 void ComponentLoader::Remove(const base::FilePath& root_directory) {
257 // Find the ComponentExtensionInfo for the extension.
258 RegisteredComponentExtensions::iterator it = component_extensions_.begin();
259 for (; it != component_extensions_.end(); ++it) {
260 if (it->root_directory == root_directory) {
261 Remove(GenerateId(it->manifest, root_directory));
262 break;
267 void ComponentLoader::Remove(const std::string& id) {
268 RegisteredComponentExtensions::iterator it = component_extensions_.begin();
269 for (; it != component_extensions_.end(); ++it) {
270 if (it->extension_id == id) {
271 UnloadComponent(&(*it));
272 it = component_extensions_.erase(it);
273 break;
278 bool ComponentLoader::Exists(const std::string& id) const {
279 RegisteredComponentExtensions::const_iterator it =
280 component_extensions_.begin();
281 for (; it != component_extensions_.end(); ++it)
282 if (it->extension_id == id)
283 return true;
284 return false;
287 void ComponentLoader::AddFileManagerExtension() {
288 #if defined(OS_CHROMEOS)
289 #ifndef NDEBUG
290 const base::CommandLine* command_line =
291 base::CommandLine::ForCurrentProcess();
292 if (command_line->HasSwitch(switches::kFileManagerExtensionPath)) {
293 base::FilePath filemgr_extension_path(
294 command_line->GetSwitchValuePath(switches::kFileManagerExtensionPath));
295 AddWithNameAndDescription(IDR_FILEMANAGER_MANIFEST,
296 filemgr_extension_path,
297 IDS_FILEMANAGER_APP_NAME,
298 IDS_FILEMANAGER_APP_DESCRIPTION);
299 return;
301 #endif // NDEBUG
302 AddWithNameAndDescription(IDR_FILEMANAGER_MANIFEST,
303 base::FilePath(FILE_PATH_LITERAL("file_manager")),
304 IDS_FILEMANAGER_APP_NAME,
305 IDS_FILEMANAGER_APP_DESCRIPTION);
306 #endif // defined(OS_CHROMEOS)
309 void ComponentLoader::AddVideoPlayerExtension() {
310 #if defined(OS_CHROMEOS)
311 Add(IDR_VIDEO_PLAYER_MANIFEST,
312 base::FilePath(FILE_PATH_LITERAL("video_player")));
313 #endif // defined(OS_CHROMEOS)
316 void ComponentLoader::AddAudioPlayerExtension() {
317 #if defined(OS_CHROMEOS)
318 Add(IDR_AUDIO_PLAYER_MANIFEST,
319 base::FilePath(FILE_PATH_LITERAL("audio_player")));
320 #endif // defined(OS_CHROMEOS)
323 void ComponentLoader::AddGalleryExtension() {
324 #if defined(OS_CHROMEOS)
325 Add(IDR_GALLERY_MANIFEST, base::FilePath(FILE_PATH_LITERAL("gallery")));
326 #endif
329 void ComponentLoader::AddHangoutServicesExtension() {
330 #if defined(GOOGLE_CHROME_BUILD) || defined(ENABLE_HANGOUT_SERVICES_EXTENSION)
331 Add(IDR_HANGOUT_SERVICES_MANIFEST,
332 base::FilePath(FILE_PATH_LITERAL("hangout_services")));
333 #endif
336 void ComponentLoader::AddHotwordAudioVerificationApp() {
337 if (HotwordService::IsExperimentalHotwordingEnabled() &&
338 HotwordServiceFactory::IsHotwordHardwareAvailable()) {
339 Add(IDR_HOTWORD_AUDIO_VERIFICATION_MANIFEST,
340 base::FilePath(FILE_PATH_LITERAL("hotword_audio_verification")));
344 void ComponentLoader::AddHotwordHelperExtension() {
345 if (HotwordServiceFactory::IsHotwordAllowed(browser_context_)) {
346 if (HotwordService::IsExperimentalHotwordingEnabled()) {
347 Add(IDR_HOTWORD_MANIFEST,
348 base::FilePath(FILE_PATH_LITERAL("hotword")));
349 } else {
350 Add(IDR_HOTWORD_HELPER_MANIFEST,
351 base::FilePath(FILE_PATH_LITERAL("hotword_helper")));
356 void ComponentLoader::AddImageLoaderExtension() {
357 #if defined(IMAGE_LOADER_EXTENSION)
358 Add(IDR_IMAGE_LOADER_MANIFEST,
359 base::FilePath(FILE_PATH_LITERAL("image_loader")));
360 #endif // defined(IMAGE_LOADER_EXTENSION)
363 void ComponentLoader::AddNetworkSpeechSynthesisExtension() {
364 Add(IDR_NETWORK_SPEECH_SYNTHESIS_MANIFEST,
365 base::FilePath(FILE_PATH_LITERAL("network_speech_synthesis")));
368 #if defined(OS_CHROMEOS)
369 void ComponentLoader::AddChromeVoxExtension(
370 const base::Closure& done_cb) {
371 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
372 base::FilePath resources_path;
373 PathService::Get(chrome::DIR_RESOURCES, &resources_path);
375 base::FilePath chromevox_path =
376 resources_path.Append(extension_misc::kChromeVoxExtensionPath);
378 const char* manifest_filename =
379 IsNormalSession() ? extension_misc::kChromeVoxManifestFilename
380 : extension_misc::kChromeVoxGuestManifestFilename;
382 BrowserThread::PostTaskAndReplyWithResult(
383 BrowserThread::FILE,
384 FROM_HERE,
385 base::Bind(&LoadManifestOnFileThread, chromevox_path, manifest_filename),
386 base::Bind(&ComponentLoader::AddChromeVoxExtensionWithManifest,
387 weak_factory_.GetWeakPtr(),
388 chromevox_path,
389 done_cb));
392 void ComponentLoader::AddChromeVoxExtensionWithManifest(
393 const base::FilePath& chromevox_path,
394 const base::Closure& done_cb,
395 scoped_ptr<base::DictionaryValue> manifest) {
396 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
397 std::string extension_id = Add(manifest.release(), chromevox_path);
398 CHECK_EQ(extension_misc::kChromeVoxExtensionId, extension_id);
399 if (!done_cb.is_null())
400 done_cb.Run();
403 std::string ComponentLoader::AddChromeOsSpeechSynthesisExtension() {
404 int idr = IsNormalSession() ? IDR_SPEECH_SYNTHESIS_MANIFEST
405 : IDR_SPEECH_SYNTHESIS_GUEST_MANIFEST;
406 std::string id = Add(idr,
407 base::FilePath(extension_misc::kSpeechSynthesisExtensionPath));
408 EnableFileSystemInGuestMode(id);
409 return id;
411 #endif
413 void ComponentLoader::AddWithNameAndDescription(
414 int manifest_resource_id,
415 const base::FilePath& root_directory,
416 int name_string_id,
417 int description_string_id) {
418 std::string manifest_contents =
419 ResourceBundle::GetSharedInstance().GetRawDataResource(
420 manifest_resource_id).as_string();
422 // The Value is kept for the lifetime of the ComponentLoader. This is
423 // required in case LoadAll() is called again.
424 base::DictionaryValue* manifest = ParseManifest(manifest_contents);
426 if (manifest) {
427 manifest->SetString(manifest_keys::kName,
428 l10n_util::GetStringUTF8(name_string_id));
429 manifest->SetString(manifest_keys::kDescription,
430 l10n_util::GetStringUTF8(description_string_id));
431 Add(manifest, root_directory);
435 void ComponentLoader::AddChromeApp() {
436 #if defined(ENABLE_APP_LIST)
437 AddWithNameAndDescription(IDR_CHROME_APP_MANIFEST,
438 base::FilePath(FILE_PATH_LITERAL("chrome_app")),
439 IDS_SHORT_PRODUCT_NAME,
440 IDS_CHROME_SHORTCUT_DESCRIPTION);
441 #endif
444 void ComponentLoader::AddKeyboardApp() {
445 #if defined(OS_CHROMEOS)
446 Add(IDR_KEYBOARD_MANIFEST, base::FilePath(FILE_PATH_LITERAL("keyboard")));
447 #endif
450 void ComponentLoader::AddWebStoreApp() {
451 AddWithNameAndDescription(IDR_WEBSTORE_MANIFEST,
452 base::FilePath(FILE_PATH_LITERAL("web_store")),
453 IDS_WEBSTORE_NAME_STORE,
454 IDS_WEBSTORE_APP_DESCRIPTION);
457 // static
458 void ComponentLoader::EnableBackgroundExtensionsForTesting() {
459 enable_background_extensions_during_testing = true;
462 void ComponentLoader::AddDefaultComponentExtensions(
463 bool skip_session_components) {
464 // Do not add component extensions that have background pages here -- add them
465 // to AddDefaultComponentExtensionsWithBackgroundPages.
466 #if defined(OS_CHROMEOS)
467 Add(IDR_MOBILE_MANIFEST,
468 base::FilePath(FILE_PATH_LITERAL("/usr/share/chromeos-assets/mobile")));
470 #if defined(GOOGLE_CHROME_BUILD)
471 if (browser_defaults::enable_help_app) {
472 Add(IDR_HELP_MANIFEST, base::FilePath(FILE_PATH_LITERAL(
473 "/usr/share/chromeos-assets/helpapp")));
475 #endif
477 // Skip all other extensions that require user session presence.
478 if (!skip_session_components) {
479 const base::CommandLine* command_line =
480 base::CommandLine::ForCurrentProcess();
481 if (!command_line->HasSwitch(chromeos::switches::kGuestSession))
482 Add(IDR_BOOKMARKS_MANIFEST,
483 base::FilePath(FILE_PATH_LITERAL("bookmark_manager")));
485 Add(IDR_CROSH_BUILTIN_MANIFEST, base::FilePath(FILE_PATH_LITERAL(
486 "/usr/share/chromeos-assets/crosh_builtin")));
488 #else // !defined(OS_CHROMEOS)
489 DCHECK(!skip_session_components);
490 Add(IDR_BOOKMARKS_MANIFEST,
491 base::FilePath(FILE_PATH_LITERAL("bookmark_manager")));
492 // Cloud Print component app. Not required on Chrome OS.
493 Add(IDR_CLOUDPRINT_MANIFEST,
494 base::FilePath(FILE_PATH_LITERAL("cloud_print")));
495 #endif
497 if (!skip_session_components) {
498 AddWebStoreApp();
499 AddChromeApp();
502 AddKeyboardApp();
504 AddDefaultComponentExtensionsWithBackgroundPages(skip_session_components);
507 void ComponentLoader::AddDefaultComponentExtensionsForKioskMode(
508 bool skip_session_components) {
509 // No component extension for kiosk app launch splash screen.
510 if (skip_session_components)
511 return;
513 // Component extensions needed for kiosk apps.
514 AddFileManagerExtension();
516 // Add virtual keyboard.
517 AddKeyboardApp();
520 void ComponentLoader::AddDefaultComponentExtensionsWithBackgroundPages(
521 bool skip_session_components) {
522 const base::CommandLine* command_line =
523 base::CommandLine::ForCurrentProcess();
525 // Component extensions with background pages are not enabled during tests
526 // because they generate a lot of background behavior that can interfere.
527 if (!enable_background_extensions_during_testing &&
528 (command_line->HasSwitch(switches::kTestType) ||
529 command_line->HasSwitch(
530 switches::kDisableComponentExtensionsWithBackgroundPages))) {
531 return;
534 #if defined(OS_CHROMEOS) && defined(GOOGLE_CHROME_BUILD)
535 // Since this is a v2 app it has a background page.
536 AddWithNameAndDescription(IDR_GENIUS_APP_MANIFEST,
537 base::FilePath(FILE_PATH_LITERAL(
538 "/usr/share/chromeos-assets/genius_app")),
539 IDS_GENIUS_APP_NAME,
540 IDS_GENIUS_APP_DESCRIPTION);
541 #endif
543 if (!skip_session_components) {
544 AddVideoPlayerExtension();
545 AddAudioPlayerExtension();
546 AddFileManagerExtension();
547 AddGalleryExtension();
549 AddHangoutServicesExtension();
550 AddHotwordAudioVerificationApp();
551 AddHotwordHelperExtension();
552 AddImageLoaderExtension();
554 bool install_feedback = enable_background_extensions_during_testing;
555 #if defined(GOOGLE_CHROME_BUILD)
556 install_feedback = true;
557 #endif // defined(GOOGLE_CHROME_BUILD)
558 if (install_feedback)
559 Add(IDR_FEEDBACK_MANIFEST, base::FilePath(FILE_PATH_LITERAL("feedback")));
561 #if defined(ENABLE_SETTINGS_APP)
562 Add(IDR_SETTINGS_APP_MANIFEST,
563 base::FilePath(FILE_PATH_LITERAL("settings_app")));
564 #endif
567 #if defined(OS_CHROMEOS)
568 if (!skip_session_components) {
569 #if defined(GOOGLE_CHROME_BUILD)
570 if (!command_line->HasSwitch(
571 chromeos::switches::kDisableOfficeEditingComponentApp)) {
572 std::string id = Add(IDR_QUICKOFFICE_MANIFEST, base::FilePath(
573 FILE_PATH_LITERAL("/usr/share/chromeos-assets/quickoffice")));
574 EnableFileSystemInGuestMode(id);
576 #endif // defined(GOOGLE_CHROME_BUILD)
578 Add(IDR_ECHO_MANIFEST,
579 base::FilePath(FILE_PATH_LITERAL("/usr/share/chromeos-assets/echo")));
581 if (!command_line->HasSwitch(chromeos::switches::kGuestSession)) {
582 Add(IDR_WALLPAPERMANAGER_MANIFEST,
583 base::FilePath(FILE_PATH_LITERAL("chromeos/wallpaper_manager")));
586 Add(IDR_FIRST_RUN_DIALOG_MANIFEST,
587 base::FilePath(FILE_PATH_LITERAL("chromeos/first_run/app")));
589 Add(IDR_NETWORK_CONFIGURATION_MANIFEST,
590 base::FilePath(FILE_PATH_LITERAL("chromeos/network_configuration")));
592 Add(IDR_CONNECTIVITY_DIAGNOSTICS_MANIFEST,
593 base::FilePath(extension_misc::kConnectivityDiagnosticsPath));
594 Add(IDR_CONNECTIVITY_DIAGNOSTICS_LAUNCHER_MANIFEST,
595 base::FilePath(extension_misc::kConnectivityDiagnosticsLauncherPath));
598 // Load ChromeVox extension now if spoken feedback is enabled.
599 if (chromeos::AccessibilityManager::Get() &&
600 chromeos::AccessibilityManager::Get()->IsSpokenFeedbackEnabled()) {
601 AddChromeVoxExtension(base::Closure());
603 #endif // defined(OS_CHROMEOS)
605 #if defined(ENABLE_GOOGLE_NOW)
606 const char kEnablePrefix[] = "Enable";
607 const char kFieldTrialName[] = "GoogleNow";
608 std::string enable_prefix(kEnablePrefix);
609 std::string field_trial_result =
610 base::FieldTrialList::FindFullName(kFieldTrialName);
612 bool enabled_via_field_trial =
613 field_trial_result.compare(0, enable_prefix.length(), enable_prefix) == 0;
615 // Enable the feature on trybots and trunk builds.
616 bool enabled_via_trunk_build =
617 chrome::VersionInfo::GetChannel() == chrome::VersionInfo::CHANNEL_UNKNOWN;
619 bool enabled = enabled_via_field_trial || enabled_via_trunk_build;
621 #if defined(ENABLE_APP_LIST) && defined(OS_CHROMEOS)
622 // Don't load if newer trial is running (== new extension id is available).
623 std::string ignored_extension_id;
624 if (GetGoogleNowExtensionId(&ignored_extension_id)) {
625 enabled = false;
627 #endif
629 if (!skip_session_components && enabled) {
630 Add(IDR_GOOGLE_NOW_MANIFEST,
631 base::FilePath(FILE_PATH_LITERAL("google_now")));
633 #endif
635 #if defined(GOOGLE_CHROME_BUILD)
636 #if !defined(OS_CHROMEOS) // http://crbug.com/314799
637 AddNetworkSpeechSynthesisExtension();
638 #endif
640 #endif // defined(GOOGLE_CHROME_BUILD)
642 #if defined(ENABLE_PLUGINS)
643 if (switches::OutOfProcessPdfEnabled()) {
644 Add(pdf_extension_util::GetManifest(),
645 base::FilePath(FILE_PATH_LITERAL("pdf")));
647 #endif
649 Add(IDR_CRYPTOTOKEN_MANIFEST,
650 base::FilePath(FILE_PATH_LITERAL("cryptotoken")));
653 void ComponentLoader::UnloadComponent(ComponentExtensionInfo* component) {
654 delete component->manifest;
655 if (extension_service_->is_ready()) {
656 extension_service_->
657 RemoveComponentExtension(component->extension_id);
661 void ComponentLoader::EnableFileSystemInGuestMode(const std::string& id) {
662 #if defined(OS_CHROMEOS)
663 if (!IsNormalSession()) {
664 // TODO(dpolukhin): Hack to enable HTML5 temporary file system for
665 // the extension. Some component extensions don't work without temporary
666 // file system access. Make sure temporary file system is enabled in the off
667 // the record browser context (as that is the one used in guest session).
668 content::BrowserContext* off_the_record_context =
669 ExtensionsBrowserClient::Get()->GetOffTheRecordContext(
670 browser_context_);
671 GURL site = content::SiteInstance::GetSiteForURL(
672 off_the_record_context, Extension::GetBaseURLFromExtensionId(id));
673 storage::FileSystemContext* file_system_context =
674 content::BrowserContext::GetStoragePartitionForSite(
675 off_the_record_context, site)->GetFileSystemContext();
676 file_system_context->EnableTemporaryFileSystemInIncognito();
678 #endif
681 } // namespace extensions