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"
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/path_service.h"
14 #include "chrome/browser/extensions/extension_service.h"
15 #include "chrome/browser/search/hotword_service_factory.h"
16 #include "chrome/common/chrome_paths.h"
17 #include "chrome/common/chrome_switches.h"
18 #include "chrome/common/chrome_version_info.h"
19 #include "chrome/common/extensions/extension_constants.h"
20 #include "chrome/grit/generated_resources.h"
21 #include "components/crx_file/id_util.h"
22 #include "content/public/browser/browser_context.h"
23 #include "content/public/browser/browser_thread.h"
24 #include "content/public/browser/plugin_service.h"
25 #include "extensions/common/extension.h"
26 #include "extensions/common/file_util.h"
27 #include "extensions/common/manifest_constants.h"
28 #include "grit/browser_resources.h"
29 #include "ui/base/l10n/l10n_util.h"
30 #include "ui/base/resource/resource_bundle.h"
32 #if defined(OS_CHROMEOS)
33 #include "grit/keyboard_resources.h"
34 #include "ui/file_manager/grit/file_manager_resources.h"
35 #include "ui/keyboard/keyboard_util.h"
38 #if defined(GOOGLE_CHROME_BUILD)
39 #include "chrome/browser/defaults.h"
42 #if defined(OS_CHROMEOS)
43 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
44 #include "chromeos/chromeos_switches.h"
45 #include "content/public/browser/site_instance.h"
46 #include "content/public/browser/storage_partition.h"
47 #include "extensions/browser/extensions_browser_client.h"
48 #include "storage/browser/fileapi/file_system_context.h"
51 #if defined(ENABLE_APP_LIST)
52 #include "chrome/grit/chromium_strings.h"
55 using content::BrowserThread
;
57 namespace extensions
{
61 static bool enable_background_extensions_during_testing
= false;
63 std::string
GenerateId(const base::DictionaryValue
* manifest
,
64 const base::FilePath
& path
) {
67 CHECK(manifest
->GetString(manifest_keys::kPublicKey
, &raw_key
));
68 CHECK(Extension::ParsePEMKeyBytes(raw_key
, &id_input
));
69 std::string id
= crx_file::id_util::GenerateId(id_input
);
73 #if defined(OS_CHROMEOS)
74 scoped_ptr
<base::DictionaryValue
>
75 LoadManifestOnFileThread(
76 const base::FilePath
& chromevox_path
, const char* manifest_filename
) {
77 DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
79 scoped_ptr
<base::DictionaryValue
> manifest(
80 file_util::LoadManifest(chromevox_path
, manifest_filename
, &error
));
81 CHECK(manifest
) << error
;
82 return manifest
.Pass();
84 #endif // defined(OS_CHROMEOS)
88 ComponentLoader::ComponentExtensionInfo::ComponentExtensionInfo(
89 const base::DictionaryValue
* manifest
, const base::FilePath
& directory
)
91 root_directory(directory
) {
92 if (!root_directory
.IsAbsolute()) {
93 CHECK(PathService::Get(chrome::DIR_RESOURCES
, &root_directory
));
94 root_directory
= root_directory
.Append(directory
);
96 extension_id
= GenerateId(manifest
, root_directory
);
99 ComponentLoader::ComponentLoader(ExtensionServiceInterface
* extension_service
,
100 PrefService
* profile_prefs
,
101 PrefService
* local_state
,
102 content::BrowserContext
* browser_context
)
103 : profile_prefs_(profile_prefs
),
104 local_state_(local_state
),
105 browser_context_(browser_context
),
106 extension_service_(extension_service
),
107 weak_factory_(this) {}
109 ComponentLoader::~ComponentLoader() {
110 ClearAllRegistered();
113 void ComponentLoader::LoadAll() {
114 for (RegisteredComponentExtensions::iterator it
=
115 component_extensions_
.begin();
116 it
!= component_extensions_
.end(); ++it
) {
121 base::DictionaryValue
* ComponentLoader::ParseManifest(
122 const std::string
& manifest_contents
) const {
123 JSONStringValueSerializer
serializer(manifest_contents
);
124 scoped_ptr
<base::Value
> manifest(serializer
.Deserialize(NULL
, NULL
));
126 if (!manifest
.get() || !manifest
->IsType(base::Value::TYPE_DICTIONARY
)) {
127 LOG(ERROR
) << "Failed to parse extension manifest.";
130 // Transfer ownership to the caller.
131 return static_cast<base::DictionaryValue
*>(manifest
.release());
134 void ComponentLoader::ClearAllRegistered() {
135 for (RegisteredComponentExtensions::iterator it
=
136 component_extensions_
.begin();
137 it
!= component_extensions_
.end(); ++it
) {
141 component_extensions_
.clear();
144 std::string
ComponentLoader::GetExtensionID(
145 int manifest_resource_id
,
146 const base::FilePath
& root_directory
) {
147 std::string manifest_contents
= ResourceBundle::GetSharedInstance().
148 GetRawDataResource(manifest_resource_id
).as_string();
149 base::DictionaryValue
* manifest
= ParseManifest(manifest_contents
);
151 return std::string();
153 ComponentExtensionInfo
info(manifest
, root_directory
);
154 return info
.extension_id
;
157 std::string
ComponentLoader::Add(int manifest_resource_id
,
158 const base::FilePath
& root_directory
) {
159 std::string manifest_contents
=
160 ResourceBundle::GetSharedInstance().GetRawDataResource(
161 manifest_resource_id
).as_string();
162 return Add(manifest_contents
, root_directory
);
165 std::string
ComponentLoader::Add(const std::string
& manifest_contents
,
166 const base::FilePath
& root_directory
) {
167 // The Value is kept for the lifetime of the ComponentLoader. This is
168 // required in case LoadAll() is called again.
169 base::DictionaryValue
* manifest
= ParseManifest(manifest_contents
);
171 return Add(manifest
, root_directory
);
172 return std::string();
175 std::string
ComponentLoader::Add(const base::DictionaryValue
* parsed_manifest
,
176 const base::FilePath
& root_directory
) {
177 ComponentExtensionInfo
info(parsed_manifest
, root_directory
);
178 component_extensions_
.push_back(info
);
179 if (extension_service_
->is_ready())
181 return info
.extension_id
;
184 std::string
ComponentLoader::AddOrReplace(const base::FilePath
& path
) {
185 base::FilePath absolute_path
= base::MakeAbsoluteFilePath(path
);
187 scoped_ptr
<base::DictionaryValue
> manifest(
188 file_util::LoadManifest(absolute_path
, &error
));
190 LOG(ERROR
) << "Could not load extension from '" <<
191 absolute_path
.value() << "'. " << error
;
192 return std::string();
194 Remove(GenerateId(manifest
.get(), absolute_path
));
196 return Add(manifest
.release(), absolute_path
);
199 void ComponentLoader::Reload(const std::string
& extension_id
) {
200 for (RegisteredComponentExtensions::iterator it
=
201 component_extensions_
.begin(); it
!= component_extensions_
.end();
203 if (it
->extension_id
== extension_id
) {
210 void ComponentLoader::Load(const ComponentExtensionInfo
& info
) {
211 // TODO(abarth): We should REQUIRE_MODERN_MANIFEST_VERSION once we've updated
212 // our component extensions to the new manifest version.
213 int flags
= Extension::REQUIRE_KEY
;
217 scoped_refptr
<const Extension
> extension(Extension::Create(
223 if (!extension
.get()) {
228 CHECK_EQ(info
.extension_id
, extension
->id()) << extension
->name();
229 extension_service_
->AddComponentExtension(extension
.get());
232 void ComponentLoader::Remove(const base::FilePath
& root_directory
) {
233 // Find the ComponentExtensionInfo for the extension.
234 RegisteredComponentExtensions::iterator it
= component_extensions_
.begin();
235 for (; it
!= component_extensions_
.end(); ++it
) {
236 if (it
->root_directory
== root_directory
) {
237 Remove(GenerateId(it
->manifest
, root_directory
));
243 void ComponentLoader::Remove(const std::string
& id
) {
244 RegisteredComponentExtensions::iterator it
= component_extensions_
.begin();
245 for (; it
!= component_extensions_
.end(); ++it
) {
246 if (it
->extension_id
== id
) {
247 UnloadComponent(&(*it
));
248 it
= component_extensions_
.erase(it
);
254 bool ComponentLoader::Exists(const std::string
& id
) const {
255 RegisteredComponentExtensions::const_iterator it
=
256 component_extensions_
.begin();
257 for (; it
!= component_extensions_
.end(); ++it
)
258 if (it
->extension_id
== id
)
263 void ComponentLoader::AddFileManagerExtension() {
264 #if defined(OS_CHROMEOS)
266 const CommandLine
* command_line
= CommandLine::ForCurrentProcess();
267 if (command_line
->HasSwitch(switches::kFileManagerExtensionPath
)) {
268 base::FilePath
filemgr_extension_path(
269 command_line
->GetSwitchValuePath(switches::kFileManagerExtensionPath
));
270 AddWithNameAndDescription(IDR_FILEMANAGER_MANIFEST
,
271 filemgr_extension_path
,
272 IDS_FILEMANAGER_APP_NAME
,
273 IDS_FILEMANAGER_APP_DESCRIPTION
);
277 AddWithNameAndDescription(IDR_FILEMANAGER_MANIFEST
,
278 base::FilePath(FILE_PATH_LITERAL("file_manager")),
279 IDS_FILEMANAGER_APP_NAME
,
280 IDS_FILEMANAGER_APP_DESCRIPTION
);
281 #endif // defined(OS_CHROMEOS)
284 void ComponentLoader::AddVideoPlayerExtension() {
285 #if defined(OS_CHROMEOS)
286 Add(IDR_VIDEO_PLAYER_MANIFEST
,
287 base::FilePath(FILE_PATH_LITERAL("video_player")));
288 #endif // defined(OS_CHROMEOS)
291 void ComponentLoader::AddAudioPlayerExtension() {
292 #if defined(OS_CHROMEOS)
293 Add(IDR_AUDIO_PLAYER_MANIFEST
,
294 base::FilePath(FILE_PATH_LITERAL("audio_player")));
295 #endif // defined(OS_CHROMEOS)
298 void ComponentLoader::AddGalleryExtension() {
299 #if defined(OS_CHROMEOS)
300 Add(IDR_GALLERY_MANIFEST
, base::FilePath(FILE_PATH_LITERAL("gallery")));
304 void ComponentLoader::AddHangoutServicesExtension() {
305 #if defined(GOOGLE_CHROME_BUILD) || defined(ENABLE_HANGOUT_SERVICES_EXTENSION)
306 Add(IDR_HANGOUT_SERVICES_MANIFEST
,
307 base::FilePath(FILE_PATH_LITERAL("hangout_services")));
311 void ComponentLoader::AddHotwordAudioVerificationApp() {
312 CommandLine
* command_line
= CommandLine::ForCurrentProcess();
313 if (command_line
->HasSwitch(switches::kEnableExperimentalHotwording
)) {
314 Add(IDR_HOTWORD_AUDIO_VERIFICATION_MANIFEST
,
315 base::FilePath(FILE_PATH_LITERAL("hotword_audio_verification")));
319 void ComponentLoader::AddHotwordHelperExtension() {
320 if (HotwordServiceFactory::IsHotwordAllowed(browser_context_
)) {
321 CommandLine
* command_line
= CommandLine::ForCurrentProcess();
322 if (command_line
->HasSwitch(switches::kEnableExperimentalHotwording
)) {
323 Add(IDR_HOTWORD_MANIFEST
,
324 base::FilePath(FILE_PATH_LITERAL("hotword")));
326 Add(IDR_HOTWORD_HELPER_MANIFEST
,
327 base::FilePath(FILE_PATH_LITERAL("hotword_helper")));
332 void ComponentLoader::AddImageLoaderExtension() {
333 #if defined(IMAGE_LOADER_EXTENSION)
334 Add(IDR_IMAGE_LOADER_MANIFEST
,
335 base::FilePath(FILE_PATH_LITERAL("image_loader")));
336 #endif // defined(IMAGE_LOADER_EXTENSION)
339 void ComponentLoader::AddNetworkSpeechSynthesisExtension() {
340 Add(IDR_NETWORK_SPEECH_SYNTHESIS_MANIFEST
,
341 base::FilePath(FILE_PATH_LITERAL("network_speech_synthesis")));
344 #if defined(OS_CHROMEOS)
345 void ComponentLoader::AddChromeVoxExtension(
346 const base::Closure
& done_cb
) {
347 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
348 base::FilePath resources_path
;
349 PathService::Get(chrome::DIR_RESOURCES
, &resources_path
);
351 base::FilePath chromevox_path
=
352 resources_path
.Append(extension_misc::kChromeVoxExtensionPath
);
354 const CommandLine
* command_line
= CommandLine::ForCurrentProcess();
355 bool is_chromevox_next
=
356 command_line
->HasSwitch(chromeos::switches::kEnableChromeVoxNext
);
357 bool is_guest
= command_line
->HasSwitch(chromeos::switches::kGuestSession
);
358 const char* manifest_filename
;
359 if (is_chromevox_next
) {
361 is_guest
? extension_misc::kChromeVoxNextGuestManifestFilename
362 : extension_misc::kChromeVoxNextManifestFilename
;
365 is_guest
? extension_misc::kChromeVoxGuestManifestFilename
366 : extension_misc::kChromeVoxManifestFilename
;
368 BrowserThread::PostTaskAndReplyWithResult(
371 base::Bind(&LoadManifestOnFileThread
, chromevox_path
, manifest_filename
),
372 base::Bind(&ComponentLoader::AddChromeVoxExtensionWithManifest
,
373 weak_factory_
.GetWeakPtr(),
378 void ComponentLoader::AddChromeVoxExtensionWithManifest(
379 const base::FilePath
& chromevox_path
,
380 const base::Closure
& done_cb
,
381 scoped_ptr
<base::DictionaryValue
> manifest
) {
382 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
383 std::string extension_id
= Add(manifest
.release(), chromevox_path
);
384 CHECK_EQ(extension_misc::kChromeVoxExtensionId
, extension_id
);
385 if (!done_cb
.is_null())
389 std::string
ComponentLoader::AddChromeOsSpeechSynthesisExtension() {
390 const CommandLine
* command_line
= CommandLine::ForCurrentProcess();
391 int idr
= command_line
->HasSwitch(chromeos::switches::kGuestSession
) ?
392 IDR_SPEECH_SYNTHESIS_GUEST_MANIFEST
: IDR_SPEECH_SYNTHESIS_MANIFEST
;
393 std::string id
= Add(idr
,
394 base::FilePath(extension_misc::kSpeechSynthesisExtensionPath
));
395 EnableFileSystemInGuestMode(id
);
400 void ComponentLoader::AddWithNameAndDescription(
401 int manifest_resource_id
,
402 const base::FilePath
& root_directory
,
404 int description_string_id
) {
405 std::string manifest_contents
=
406 ResourceBundle::GetSharedInstance().GetRawDataResource(
407 manifest_resource_id
).as_string();
409 // The Value is kept for the lifetime of the ComponentLoader. This is
410 // required in case LoadAll() is called again.
411 base::DictionaryValue
* manifest
= ParseManifest(manifest_contents
);
414 manifest
->SetString(manifest_keys::kName
,
415 l10n_util::GetStringUTF8(name_string_id
));
416 manifest
->SetString(manifest_keys::kDescription
,
417 l10n_util::GetStringUTF8(description_string_id
));
418 Add(manifest
, root_directory
);
422 void ComponentLoader::AddChromeApp() {
423 #if defined(ENABLE_APP_LIST)
424 AddWithNameAndDescription(IDR_CHROME_APP_MANIFEST
,
425 base::FilePath(FILE_PATH_LITERAL("chrome_app")),
426 IDS_SHORT_PRODUCT_NAME
,
427 IDS_CHROME_SHORTCUT_DESCRIPTION
);
431 void ComponentLoader::AddKeyboardApp() {
432 #if defined(OS_CHROMEOS)
433 Add(IDR_KEYBOARD_MANIFEST
, base::FilePath(FILE_PATH_LITERAL("keyboard")));
437 void ComponentLoader::AddWebStoreApp() {
438 AddWithNameAndDescription(IDR_WEBSTORE_MANIFEST
,
439 base::FilePath(FILE_PATH_LITERAL("web_store")),
440 IDS_WEBSTORE_NAME_STORE
,
441 IDS_WEBSTORE_APP_DESCRIPTION
);
445 void ComponentLoader::EnableBackgroundExtensionsForTesting() {
446 enable_background_extensions_during_testing
= true;
449 void ComponentLoader::AddDefaultComponentExtensions(
450 bool skip_session_components
) {
451 // Do not add component extensions that have background pages here -- add them
452 // to AddDefaultComponentExtensionsWithBackgroundPages.
453 #if defined(OS_CHROMEOS)
454 Add(IDR_MOBILE_MANIFEST
,
455 base::FilePath(FILE_PATH_LITERAL("/usr/share/chromeos-assets/mobile")));
457 #if defined(GOOGLE_CHROME_BUILD)
458 if (browser_defaults::enable_help_app
) {
459 Add(IDR_HELP_MANIFEST
, base::FilePath(FILE_PATH_LITERAL(
460 "/usr/share/chromeos-assets/helpapp")));
464 // Skip all other extensions that require user session presence.
465 if (!skip_session_components
) {
466 const CommandLine
* command_line
= CommandLine::ForCurrentProcess();
467 if (!command_line
->HasSwitch(chromeos::switches::kGuestSession
))
468 Add(IDR_BOOKMARKS_MANIFEST
,
469 base::FilePath(FILE_PATH_LITERAL("bookmark_manager")));
471 Add(IDR_CROSH_BUILTIN_MANIFEST
, base::FilePath(FILE_PATH_LITERAL(
472 "/usr/share/chromeos-assets/crosh_builtin")));
474 #else // !defined(OS_CHROMEOS)
475 DCHECK(!skip_session_components
);
476 Add(IDR_BOOKMARKS_MANIFEST
,
477 base::FilePath(FILE_PATH_LITERAL("bookmark_manager")));
478 // Cloud Print component app. Not required on Chrome OS.
479 Add(IDR_CLOUDPRINT_MANIFEST
,
480 base::FilePath(FILE_PATH_LITERAL("cloud_print")));
483 if (!skip_session_components
) {
490 AddDefaultComponentExtensionsWithBackgroundPages(skip_session_components
);
493 void ComponentLoader::AddDefaultComponentExtensionsForKioskMode(
494 bool skip_session_components
) {
495 // No component extension for kiosk app launch splash screen.
496 if (skip_session_components
)
499 // Component extensions needed for kiosk apps.
500 AddVideoPlayerExtension();
501 AddAudioPlayerExtension();
502 AddFileManagerExtension();
503 AddGalleryExtension();
505 // Add virtual keyboard.
509 void ComponentLoader::AddDefaultComponentExtensionsWithBackgroundPages(
510 bool skip_session_components
) {
511 const CommandLine
* command_line
= CommandLine::ForCurrentProcess();
513 // Component extensions with background pages are not enabled during tests
514 // because they generate a lot of background behavior that can interfere.
515 if (!enable_background_extensions_during_testing
&&
516 (command_line
->HasSwitch(switches::kTestType
) ||
517 command_line
->HasSwitch(
518 switches::kDisableComponentExtensionsWithBackgroundPages
))) {
522 #if defined(OS_CHROMEOS) && defined(GOOGLE_CHROME_BUILD)
523 // Since this is a v2 app it has a background page.
524 AddWithNameAndDescription(IDR_GENIUS_APP_MANIFEST
,
525 base::FilePath(FILE_PATH_LITERAL(
526 "/usr/share/chromeos-assets/genius_app")),
528 IDS_GENIUS_APP_DESCRIPTION
);
531 if (!skip_session_components
) {
532 AddVideoPlayerExtension();
533 AddAudioPlayerExtension();
534 AddFileManagerExtension();
535 AddGalleryExtension();
537 AddHangoutServicesExtension();
538 AddHotwordAudioVerificationApp();
539 AddHotwordHelperExtension();
540 AddImageLoaderExtension();
542 #if defined(ENABLE_SETTINGS_APP)
543 Add(IDR_SETTINGS_APP_MANIFEST
,
544 base::FilePath(FILE_PATH_LITERAL("settings_app")));
548 // If (!enable_background_extensions_during_testing || this isn't a test)
549 // install_feedback = false;
550 bool install_feedback
= enable_background_extensions_during_testing
;
551 #if defined(GOOGLE_CHROME_BUILD)
552 install_feedback
= true;
553 #endif // defined(GOOGLE_CHROME_BUILD)
554 if (install_feedback
)
555 Add(IDR_FEEDBACK_MANIFEST
, base::FilePath(FILE_PATH_LITERAL("feedback")));
557 #if defined(OS_CHROMEOS)
558 if (!skip_session_components
) {
559 #if defined(GOOGLE_CHROME_BUILD)
560 if (!command_line
->HasSwitch(
561 chromeos::switches::kDisableOfficeEditingComponentApp
)) {
562 std::string id
= Add(IDR_QUICKOFFICE_MANIFEST
, base::FilePath(
563 FILE_PATH_LITERAL("/usr/share/chromeos-assets/quickoffice")));
564 EnableFileSystemInGuestMode(id
);
566 #endif // defined(GOOGLE_CHROME_BUILD)
568 Add(IDR_ECHO_MANIFEST
,
569 base::FilePath(FILE_PATH_LITERAL("/usr/share/chromeos-assets/echo")));
571 if (!command_line
->HasSwitch(chromeos::switches::kGuestSession
)) {
572 Add(IDR_WALLPAPERMANAGER_MANIFEST
,
573 base::FilePath(FILE_PATH_LITERAL("chromeos/wallpaper_manager")));
576 Add(IDR_FIRST_RUN_DIALOG_MANIFEST
,
577 base::FilePath(FILE_PATH_LITERAL("chromeos/first_run/app")));
579 Add(IDR_NETWORK_CONFIGURATION_MANIFEST
,
580 base::FilePath(FILE_PATH_LITERAL("chromeos/network_configuration")));
582 Add(IDR_CONNECTIVITY_DIAGNOSTICS_MANIFEST
,
583 base::FilePath(extension_misc::kConnectivityDiagnosticsPath
));
584 Add(IDR_CONNECTIVITY_DIAGNOSTICS_LAUNCHER_MANIFEST
,
585 base::FilePath(extension_misc::kConnectivityDiagnosticsLauncherPath
));
588 // Load ChromeVox extension now if spoken feedback is enabled.
589 if (chromeos::AccessibilityManager::Get() &&
590 chromeos::AccessibilityManager::Get()->IsSpokenFeedbackEnabled()) {
591 AddChromeVoxExtension(base::Closure());
593 #endif // defined(OS_CHROMEOS)
595 #if defined(ENABLE_GOOGLE_NOW)
596 const char kEnablePrefix
[] = "Enable";
597 const char kFieldTrialName
[] = "GoogleNow";
598 std::string
enable_prefix(kEnablePrefix
);
599 std::string field_trial_result
=
600 base::FieldTrialList::FindFullName(kFieldTrialName
);
602 bool enabled_via_field_trial
=
603 field_trial_result
.compare(0, enable_prefix
.length(), enable_prefix
) == 0;
605 // Enable the feature on trybots and trunk builds.
606 bool enabled_via_trunk_build
=
607 chrome::VersionInfo::GetChannel() == chrome::VersionInfo::CHANNEL_UNKNOWN
;
609 bool enabled
= enabled_via_field_trial
|| enabled_via_trunk_build
;
611 if (!skip_session_components
&& enabled
) {
612 Add(IDR_GOOGLE_NOW_MANIFEST
,
613 base::FilePath(FILE_PATH_LITERAL("google_now")));
617 #if defined(GOOGLE_CHROME_BUILD)
618 #if !defined(OS_CHROMEOS) // http://crbug.com/314799
619 AddNetworkSpeechSynthesisExtension();
622 #endif // defined(GOOGLE_CHROME_BUILD)
624 #if defined(ENABLE_PLUGINS)
625 base::FilePath pdf_path
;
626 content::PluginService
* plugin_service
=
627 content::PluginService::GetInstance();
628 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kOutOfProcessPdf
) &&
629 PathService::Get(chrome::FILE_PDF_PLUGIN
, &pdf_path
) &&
630 plugin_service
->GetRegisteredPpapiPluginInfo(pdf_path
)) {
631 Add(IDR_PDF_MANIFEST
, base::FilePath(FILE_PATH_LITERAL("pdf")));
635 Add(IDR_CRYPTOTOKEN_MANIFEST
,
636 base::FilePath(FILE_PATH_LITERAL("cryptotoken")));
639 void ComponentLoader::UnloadComponent(ComponentExtensionInfo
* component
) {
640 delete component
->manifest
;
641 if (extension_service_
->is_ready()) {
643 RemoveComponentExtension(component
->extension_id
);
647 void ComponentLoader::EnableFileSystemInGuestMode(const std::string
& id
) {
648 #if defined(OS_CHROMEOS)
649 const CommandLine
* command_line
= CommandLine::ForCurrentProcess();
650 if (command_line
->HasSwitch(chromeos::switches::kGuestSession
)) {
651 // TODO(dpolukhin): Hack to enable HTML5 temporary file system for
652 // the extension. Some component extensions don't work without temporary
653 // file system access. Make sure temporary file system is enabled in the off
654 // the record browser context (as that is the one used in guest session).
655 content::BrowserContext
* off_the_record_context
=
656 ExtensionsBrowserClient::Get()->GetOffTheRecordContext(
658 GURL site
= content::SiteInstance::GetSiteForURL(
659 off_the_record_context
, Extension::GetBaseURLFromExtensionId(id
));
660 storage::FileSystemContext
* file_system_context
=
661 content::BrowserContext::GetStoragePartitionForSite(
662 off_the_record_context
, site
)->GetFileSystemContext();
663 file_system_context
->EnableTemporaryFileSystemInIncognito();
668 } // namespace extensions