7929617591bd4771800e6e54c24ea7bb8e045b62
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / component_loader.cc
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.
4
5 #include "chrome/browser/extensions/component_loader.h"
6
7 #include <map>
8 #include <string>
9
10 #include "base/command_line.h"
11 #include "base/file_util.h"
12 #include "base/json/json_string_value_serializer.h"
13 #include "base/metrics/field_trial.h"
14 #include "base/path_service.h"
15 #include "base/prefs/pref_change_registrar.h"
16 #include "chrome/browser/chrome_notification_types.h"
17 #include "chrome/browser/extensions/extension_service.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/search/hotword_service_factory.h"
20 #include "chrome/common/chrome_paths.h"
21 #include "chrome/common/chrome_switches.h"
22 #include "chrome/common/chrome_version_info.h"
23 #include "chrome/common/extensions/extension_file_util.h"
24 #include "chrome/common/pref_names.h"
25 #include "content/public/browser/notification_details.h"
26 #include "content/public/browser/notification_source.h"
27 #include "content/public/browser/plugin_service.h"
28 #include "extensions/common/extension.h"
29 #include "extensions/common/id_util.h"
30 #include "extensions/common/manifest_constants.h"
31 #include "grit/browser_resources.h"
32 #include "grit/generated_resources.h"
33 #include "ui/base/l10n/l10n_util.h"
34 #include "ui/base/resource/resource_bundle.h"
35
36 #if defined(OS_CHROMEOS)
37 #include "grit/keyboard_resources.h"
38 #include "ui/keyboard/keyboard_util.h"
39 #endif
40
41 #if defined(GOOGLE_CHROME_BUILD)
42 #include "chrome/browser/defaults.h"
43 #endif
44
45 #if defined(OS_CHROMEOS)
46 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
47 #include "chrome/browser/chromeos/login/user_manager.h"
48 #include "chromeos/chromeos_switches.h"
49 #include "content/public/browser/site_instance.h"
50 #include "content/public/browser/storage_partition.h"
51 #include "extensions/browser/extensions_browser_client.h"
52 #include "webkit/browser/fileapi/file_system_context.h"
53 #endif
54
55 #if defined(ENABLE_APP_LIST)
56 #include "grit/chromium_strings.h"
57 #endif
58
59 namespace extensions {
60
61 namespace {
62
63 static bool enable_background_extensions_during_testing = false;
64
65 std::string LookupWebstoreName() {
66   const char kWebStoreNameFieldTrialName[] = "WebStoreName";
67   const char kStoreControl[] = "StoreControl";
68   const char kWebStore[] = "WebStore";
69   const char kGetApps[] = "GetApps";
70   const char kAddApps[] = "AddApps";
71   const char kMoreApps[] = "MoreApps";
72
73   typedef std::map<std::string, int> NameMap;
74   CR_DEFINE_STATIC_LOCAL(NameMap, names, ());
75   if (names.empty()) {
76     names.insert(std::make_pair(kStoreControl, IDS_WEBSTORE_NAME_STORE));
77     names.insert(std::make_pair(kWebStore, IDS_WEBSTORE_NAME_WEBSTORE));
78     names.insert(std::make_pair(kGetApps, IDS_WEBSTORE_NAME_GET_APPS));
79     names.insert(std::make_pair(kAddApps, IDS_WEBSTORE_NAME_ADD_APPS));
80     names.insert(std::make_pair(kMoreApps, IDS_WEBSTORE_NAME_MORE_APPS));
81   }
82   std::string field_trial_name =
83       base::FieldTrialList::FindFullName(kWebStoreNameFieldTrialName);
84   NameMap::iterator it = names.find(field_trial_name);
85   int string_id = it == names.end() ? names[kStoreControl] : it->second;
86   return l10n_util::GetStringUTF8(string_id);
87 }
88
89 std::string GenerateId(const base::DictionaryValue* manifest,
90                        const base::FilePath& path) {
91   std::string raw_key;
92   std::string id_input;
93   CHECK(manifest->GetString(manifest_keys::kPublicKey, &raw_key));
94   CHECK(Extension::ParsePEMKeyBytes(raw_key, &id_input));
95   std::string id = id_util::GenerateId(id_input);
96   return id;
97 }
98
99 }  // namespace
100
101 ComponentLoader::ComponentExtensionInfo::ComponentExtensionInfo(
102     const base::DictionaryValue* manifest, const base::FilePath& directory)
103     : manifest(manifest),
104       root_directory(directory) {
105   if (!root_directory.IsAbsolute()) {
106     CHECK(PathService::Get(chrome::DIR_RESOURCES, &root_directory));
107     root_directory = root_directory.Append(directory);
108   }
109   extension_id = GenerateId(manifest, root_directory);
110 }
111
112 ComponentLoader::ComponentLoader(ExtensionServiceInterface* extension_service,
113                                  PrefService* profile_prefs,
114                                  PrefService* local_state,
115                                  content::BrowserContext* browser_context)
116     : profile_prefs_(profile_prefs),
117       local_state_(local_state),
118       browser_context_(browser_context),
119       extension_service_(extension_service) {}
120
121 ComponentLoader::~ComponentLoader() {
122   ClearAllRegistered();
123 }
124
125 void ComponentLoader::LoadAll() {
126   for (RegisteredComponentExtensions::iterator it =
127           component_extensions_.begin();
128       it != component_extensions_.end(); ++it) {
129     Load(*it);
130   }
131 }
132
133 base::DictionaryValue* ComponentLoader::ParseManifest(
134     const std::string& manifest_contents) const {
135   JSONStringValueSerializer serializer(manifest_contents);
136   scoped_ptr<base::Value> manifest(serializer.Deserialize(NULL, NULL));
137
138   if (!manifest.get() || !manifest->IsType(base::Value::TYPE_DICTIONARY)) {
139     LOG(ERROR) << "Failed to parse extension manifest.";
140     return NULL;
141   }
142   // Transfer ownership to the caller.
143   return static_cast<base::DictionaryValue*>(manifest.release());
144 }
145
146 void ComponentLoader::ClearAllRegistered() {
147   for (RegisteredComponentExtensions::iterator it =
148           component_extensions_.begin();
149       it != component_extensions_.end(); ++it) {
150       delete it->manifest;
151   }
152
153   component_extensions_.clear();
154 }
155
156 std::string ComponentLoader::GetExtensionID(
157     int manifest_resource_id,
158     const base::FilePath& root_directory) {
159   std::string manifest_contents = ResourceBundle::GetSharedInstance().
160       GetRawDataResource(manifest_resource_id).as_string();
161   base::DictionaryValue* manifest = ParseManifest(manifest_contents);
162   if (!manifest)
163     return std::string();
164
165   ComponentExtensionInfo info(manifest, root_directory);
166   return info.extension_id;
167 }
168
169 std::string ComponentLoader::Add(int manifest_resource_id,
170                                  const base::FilePath& root_directory) {
171   std::string manifest_contents =
172       ResourceBundle::GetSharedInstance().GetRawDataResource(
173           manifest_resource_id).as_string();
174   return Add(manifest_contents, root_directory);
175 }
176
177 std::string ComponentLoader::Add(const std::string& manifest_contents,
178                                  const base::FilePath& root_directory) {
179   // The Value is kept for the lifetime of the ComponentLoader. This is
180   // required in case LoadAll() is called again.
181   base::DictionaryValue* manifest = ParseManifest(manifest_contents);
182   if (manifest)
183     return Add(manifest, root_directory);
184   return std::string();
185 }
186
187 std::string ComponentLoader::Add(const base::DictionaryValue* parsed_manifest,
188                                  const base::FilePath& root_directory) {
189   ComponentExtensionInfo info(parsed_manifest, root_directory);
190   component_extensions_.push_back(info);
191   if (extension_service_->is_ready())
192     Load(info);
193   return info.extension_id;
194 }
195
196 std::string ComponentLoader::AddOrReplace(const base::FilePath& path) {
197   base::FilePath absolute_path = base::MakeAbsoluteFilePath(path);
198   std::string error;
199   scoped_ptr<base::DictionaryValue> manifest(
200       extension_file_util::LoadManifest(absolute_path, &error));
201   if (!manifest) {
202     LOG(ERROR) << "Could not load extension from '" <<
203                   absolute_path.value() << "'. " << error;
204     return std::string();
205   }
206   Remove(GenerateId(manifest.get(), absolute_path));
207
208   return Add(manifest.release(), absolute_path);
209 }
210
211 void ComponentLoader::Reload(const std::string& extension_id) {
212   for (RegisteredComponentExtensions::iterator it =
213          component_extensions_.begin(); it != component_extensions_.end();
214          ++it) {
215     if (it->extension_id == extension_id) {
216       Load(*it);
217       break;
218     }
219   }
220 }
221
222 void ComponentLoader::Load(const ComponentExtensionInfo& info) {
223   // TODO(abarth): We should REQUIRE_MODERN_MANIFEST_VERSION once we've updated
224   //               our component extensions to the new manifest version.
225   int flags = Extension::REQUIRE_KEY;
226
227   std::string error;
228
229   scoped_refptr<const Extension> extension(Extension::Create(
230       info.root_directory,
231       Manifest::COMPONENT,
232       *info.manifest,
233       flags,
234       &error));
235   if (!extension.get()) {
236     LOG(ERROR) << error;
237     return;
238   }
239
240   CHECK_EQ(info.extension_id, extension->id()) << extension->name();
241   extension_service_->AddComponentExtension(extension.get());
242 }
243
244 void ComponentLoader::Remove(const base::FilePath& root_directory) {
245   // Find the ComponentExtensionInfo for the extension.
246   RegisteredComponentExtensions::iterator it = component_extensions_.begin();
247   for (; it != component_extensions_.end(); ++it) {
248     if (it->root_directory == root_directory) {
249       Remove(GenerateId(it->manifest, root_directory));
250       break;
251     }
252   }
253 }
254
255 void ComponentLoader::Remove(const std::string& id) {
256   RegisteredComponentExtensions::iterator it = component_extensions_.begin();
257   for (; it != component_extensions_.end(); ++it) {
258     if (it->extension_id == id) {
259       UnloadComponent(&(*it));
260       it = component_extensions_.erase(it);
261       break;
262     }
263   }
264 }
265
266 bool ComponentLoader::Exists(const std::string& id) const {
267   RegisteredComponentExtensions::const_iterator it =
268       component_extensions_.begin();
269   for (; it != component_extensions_.end(); ++it)
270     if (it->extension_id == id)
271       return true;
272   return false;
273 }
274
275 void ComponentLoader::AddFileManagerExtension() {
276 #if defined(OS_CHROMEOS)
277 #ifndef NDEBUG
278   const CommandLine* command_line = CommandLine::ForCurrentProcess();
279   if (command_line->HasSwitch(switches::kFileManagerExtensionPath)) {
280     base::FilePath filemgr_extension_path(
281         command_line->GetSwitchValuePath(switches::kFileManagerExtensionPath));
282     Add(IDR_FILEMANAGER_MANIFEST, filemgr_extension_path);
283     return;
284   }
285 #endif  // NDEBUG
286   Add(IDR_FILEMANAGER_MANIFEST,
287       base::FilePath(FILE_PATH_LITERAL("file_manager")));
288 #endif  // defined(OS_CHROMEOS)
289 }
290
291 void ComponentLoader::AddHangoutServicesExtension() {
292 #if defined(GOOGLE_CHROME_BUILD) || defined(ENABLE_HANGOUT_SERVICES_EXTENSION)
293   Add(IDR_HANGOUT_SERVICES_MANIFEST,
294       base::FilePath(FILE_PATH_LITERAL("hangout_services")));
295 #endif
296 }
297
298 void ComponentLoader::AddHotwordHelperExtension() {
299   Profile* profile = static_cast<Profile*>(browser_context_);
300   if (HotwordServiceFactory::IsHotwordAllowed(profile)) {
301     Add(IDR_HOTWORD_HELPER_MANIFEST,
302         base::FilePath(FILE_PATH_LITERAL("hotword_helper")));
303   }
304 }
305
306 void ComponentLoader::AddImageLoaderExtension() {
307 #if defined(IMAGE_LOADER_EXTENSION)
308 #ifndef NDEBUG
309   const CommandLine* command_line = CommandLine::ForCurrentProcess();
310   if (command_line->HasSwitch(switches::kImageLoaderExtensionPath)) {
311     base::FilePath image_loader_extension_path(
312         command_line->GetSwitchValuePath(switches::kImageLoaderExtensionPath));
313     Add(IDR_IMAGE_LOADER_MANIFEST, image_loader_extension_path);
314     return;
315   }
316 #endif  // NDEBUG
317   Add(IDR_IMAGE_LOADER_MANIFEST,
318       base::FilePath(FILE_PATH_LITERAL("image_loader")));
319 #endif  // defined(IMAGE_LOADER_EXTENSION)
320 }
321
322 void ComponentLoader::AddBookmarksExtensions() {
323   Add(IDR_BOOKMARKS_MANIFEST,
324       base::FilePath(FILE_PATH_LITERAL("bookmark_manager")));
325 #if defined(ENABLE_ENHANCED_BOOKMARKS)
326   Add(IDR_ENHANCED_BOOKMARKS_MANIFEST,
327       base::FilePath(FILE_PATH_LITERAL("enhanced_bookmark_manager")));
328 #endif
329 }
330
331 void ComponentLoader::AddNetworkSpeechSynthesisExtension() {
332   Add(IDR_NETWORK_SPEECH_SYNTHESIS_MANIFEST,
333       base::FilePath(FILE_PATH_LITERAL("network_speech_synthesis")));
334 }
335
336 #if defined(OS_CHROMEOS)
337 std::string ComponentLoader::AddChromeVoxExtension() {
338   const CommandLine* command_line = CommandLine::ForCurrentProcess();
339   int idr = command_line->HasSwitch(chromeos::switches::kGuestSession) ?
340       IDR_CHROMEVOX_GUEST_MANIFEST : IDR_CHROMEVOX_MANIFEST;
341   return Add(idr, base::FilePath(extension_misc::kChromeVoxExtensionPath));
342 }
343
344 std::string ComponentLoader::AddChromeOsSpeechSynthesisExtension() {
345   const CommandLine* command_line = CommandLine::ForCurrentProcess();
346   int idr = command_line->HasSwitch(chromeos::switches::kGuestSession) ?
347       IDR_SPEECH_SYNTHESIS_GUEST_MANIFEST : IDR_SPEECH_SYNTHESIS_MANIFEST;
348   std::string id = Add(idr,
349       base::FilePath(extension_misc::kSpeechSynthesisExtensionPath));
350   EnableFileSystemInGuestMode(id);
351   return id;
352 }
353 #endif
354
355 void ComponentLoader::AddWithName(int manifest_resource_id,
356                                   const base::FilePath& root_directory,
357                                   const std::string& name) {
358   std::string manifest_contents =
359       ResourceBundle::GetSharedInstance().GetRawDataResource(
360           manifest_resource_id).as_string();
361
362   // The Value is kept for the lifetime of the ComponentLoader. This is
363   // required in case LoadAll() is called again.
364   base::DictionaryValue* manifest = ParseManifest(manifest_contents);
365
366   if (manifest) {
367     // Update manifest to use a proper name.
368     manifest->SetString(manifest_keys::kName, name);
369     Add(manifest, root_directory);
370   }
371 }
372
373 void ComponentLoader::AddChromeApp() {
374 #if defined(ENABLE_APP_LIST)
375   AddWithName(IDR_CHROME_APP_MANIFEST,
376               base::FilePath(FILE_PATH_LITERAL("chrome_app")),
377               l10n_util::GetStringUTF8(IDS_SHORT_PRODUCT_NAME));
378 #endif
379 }
380
381 void ComponentLoader::AddKeyboardApp() {
382 #if defined(OS_CHROMEOS)
383   Add(IDR_KEYBOARD_MANIFEST, base::FilePath(FILE_PATH_LITERAL("keyboard")));
384 #endif
385 }
386
387 void ComponentLoader::AddWebStoreApp() {
388   AddWithName(IDR_WEBSTORE_MANIFEST,
389               base::FilePath(FILE_PATH_LITERAL("web_store")),
390               LookupWebstoreName());
391 }
392
393 // static
394 void ComponentLoader::EnableBackgroundExtensionsForTesting() {
395   enable_background_extensions_during_testing = true;
396 }
397
398 void ComponentLoader::AddDefaultComponentExtensions(
399     bool skip_session_components) {
400   // Do not add component extensions that have background pages here -- add them
401   // to AddDefaultComponentExtensionsWithBackgroundPages.
402 #if defined(OS_CHROMEOS)
403   Add(IDR_MOBILE_MANIFEST,
404       base::FilePath(FILE_PATH_LITERAL("/usr/share/chromeos-assets/mobile")));
405
406 #if defined(GOOGLE_CHROME_BUILD)
407   if (browser_defaults::enable_help_app) {
408     Add(IDR_HELP_MANIFEST, base::FilePath(FILE_PATH_LITERAL(
409                                "/usr/share/chromeos-assets/helpapp")));
410   }
411 #endif
412
413   // Skip all other extensions that require user session presence.
414   if (!skip_session_components) {
415     const CommandLine* command_line = CommandLine::ForCurrentProcess();
416     if (!command_line->HasSwitch(chromeos::switches::kGuestSession))
417       AddBookmarksExtensions();
418
419     Add(IDR_CROSH_BUILTIN_MANIFEST, base::FilePath(FILE_PATH_LITERAL(
420         "/usr/share/chromeos-assets/crosh_builtin")));
421   }
422 #else  // !defined(OS_CHROMEOS)
423   DCHECK(!skip_session_components);
424   AddBookmarksExtensions();
425   // Cloud Print component app. Not required on Chrome OS.
426   Add(IDR_CLOUDPRINT_MANIFEST,
427       base::FilePath(FILE_PATH_LITERAL("cloud_print")));
428 #endif
429
430   if (!skip_session_components) {
431     AddWebStoreApp();
432     AddChromeApp();
433   }
434
435   AddKeyboardApp();
436
437   AddDefaultComponentExtensionsWithBackgroundPages(skip_session_components);
438 }
439
440 void ComponentLoader::AddDefaultComponentExtensionsForKioskMode(
441     bool skip_session_components) {
442   // No component extension for kiosk app launch splash screen.
443   if (skip_session_components)
444     return;
445
446   // Component extensions needed for kiosk apps.
447   AddFileManagerExtension();
448
449   // Add virtual keyboard.
450   AddKeyboardApp();
451 }
452
453 void ComponentLoader::AddDefaultComponentExtensionsWithBackgroundPages(
454     bool skip_session_components) {
455   const CommandLine* command_line = CommandLine::ForCurrentProcess();
456
457   // Component extensions with background pages are not enabled during tests
458   // because they generate a lot of background behavior that can interfere.
459   if (!enable_background_extensions_during_testing &&
460       (command_line->HasSwitch(switches::kTestType) ||
461           command_line->HasSwitch(
462               switches::kDisableComponentExtensionsWithBackgroundPages))) {
463     return;
464   }
465
466 #if defined(OS_CHROMEOS) && defined(GOOGLE_CHROME_BUILD)
467   // Since this is a v2 app it has a background page.
468   if (!command_line->HasSwitch(chromeos::switches::kDisableGeniusApp)) {
469     AddWithName(IDR_GENIUS_APP_MANIFEST,
470                 base::FilePath(FILE_PATH_LITERAL(
471                     "/usr/share/chromeos-assets/genius_app")),
472                 l10n_util::GetStringUTF8(IDS_GENIUS_APP_NAME));
473   }
474 #endif
475
476   if (!skip_session_components) {
477     AddFileManagerExtension();
478     AddHangoutServicesExtension();
479     AddHotwordHelperExtension();
480     AddImageLoaderExtension();
481
482 #if defined(ENABLE_SETTINGS_APP)
483     Add(IDR_SETTINGS_APP_MANIFEST,
484         base::FilePath(FILE_PATH_LITERAL("settings_app")));
485 #endif
486   }
487
488   // If (!enable_background_extensions_during_testing || this isn't a test)
489   //   install_feedback = false;
490   bool install_feedback = enable_background_extensions_during_testing;
491 #if defined(GOOGLE_CHROME_BUILD)
492   install_feedback = true;
493 #endif  // defined(GOOGLE_CHROME_BUILD)
494   if (install_feedback)
495     Add(IDR_FEEDBACK_MANIFEST, base::FilePath(FILE_PATH_LITERAL("feedback")));
496
497 #if defined(OS_CHROMEOS)
498   if (!skip_session_components) {
499 #if defined(GOOGLE_CHROME_BUILD)
500     if (!command_line->HasSwitch(
501             chromeos::switches::kDisableQuickofficeComponentApp)) {
502       std::string id = Add(IDR_QUICKOFFICE_MANIFEST, base::FilePath(
503           FILE_PATH_LITERAL("/usr/share/chromeos-assets/quick_office")));
504       EnableFileSystemInGuestMode(id);
505     }
506 #endif  // defined(GOOGLE_CHROME_BUILD)
507
508     base::FilePath echo_extension_path(FILE_PATH_LITERAL(
509         "/usr/share/chromeos-assets/echo"));
510     if (command_line->HasSwitch(chromeos::switches::kEchoExtensionPath)) {
511       echo_extension_path = command_line->GetSwitchValuePath(
512           chromeos::switches::kEchoExtensionPath);
513     }
514     Add(IDR_ECHO_MANIFEST, echo_extension_path);
515
516     if (!command_line->HasSwitch(chromeos::switches::kGuestSession)) {
517       Add(IDR_WALLPAPERMANAGER_MANIFEST,
518           base::FilePath(FILE_PATH_LITERAL("chromeos/wallpaper_manager")));
519     }
520
521     if (!command_line->HasSwitch(chromeos::switches::kDisableFirstRunUI)) {
522       Add(IDR_FIRST_RUN_DIALOG_MANIFEST,
523           base::FilePath(FILE_PATH_LITERAL("chromeos/first_run/app")));
524     }
525
526     Add(IDR_NETWORK_CONFIGURATION_MANIFEST,
527         base::FilePath(FILE_PATH_LITERAL("chromeos/network_configuration")));
528
529     Add(IDR_CONNECTIVITY_DIAGNOSTICS_MANIFEST,
530         base::FilePath(extension_misc::kConnectivityDiagnosticsPath));
531     Add(IDR_CONNECTIVITY_DIAGNOSTICS_LAUNCHER_MANIFEST,
532         base::FilePath(extension_misc::kConnectivityDiagnosticsLauncherPath));
533   }
534
535   // Load ChromeVox extension now if spoken feedback is enabled.
536   if (chromeos::AccessibilityManager::Get() &&
537       chromeos::AccessibilityManager::Get()->IsSpokenFeedbackEnabled()) {
538     AddChromeVoxExtension();
539   }
540 #endif  // defined(OS_CHROMEOS)
541
542 #if defined(ENABLE_GOOGLE_NOW)
543   const char kEnablePrefix[] = "Enable";
544   const char kFieldTrialName[] = "GoogleNow";
545   std::string enable_prefix(kEnablePrefix);
546   std::string field_trial_result =
547       base::FieldTrialList::FindFullName(kFieldTrialName);
548
549   bool enabled_via_field_trial = field_trial_result.compare(
550       0,
551       enable_prefix.length(),
552       enable_prefix) == 0;
553
554   // Enable the feature on trybots.
555   bool enabled_via_trunk_build = chrome::VersionInfo::GetChannel() ==
556       chrome::VersionInfo::CHANNEL_UNKNOWN;
557
558   bool enabled_via_flag =
559       chrome::VersionInfo::GetChannel() !=
560           chrome::VersionInfo::CHANNEL_STABLE &&
561       CommandLine::ForCurrentProcess()->HasSwitch(
562           switches::kEnableGoogleNowIntegration);
563
564   bool enabled =
565       enabled_via_field_trial || enabled_via_trunk_build || enabled_via_flag;
566
567   bool disabled_via_flag =
568       CommandLine::ForCurrentProcess()->HasSwitch(
569           switches::kDisableGoogleNowIntegration);
570
571   if (!skip_session_components && enabled && !disabled_via_flag) {
572     Add(IDR_GOOGLE_NOW_MANIFEST,
573         base::FilePath(FILE_PATH_LITERAL("google_now")));
574   }
575 #endif
576
577 #if defined(GOOGLE_CHROME_BUILD)
578 #if !defined(OS_CHROMEOS)  // http://crbug.com/314799
579   AddNetworkSpeechSynthesisExtension();
580 #endif
581 #endif  // defined(GOOGLE_CHROME_BUILD)
582
583 #if defined(ENABLE_PLUGINS)
584   base::FilePath pdf_path;
585   content::PluginService* plugin_service =
586       content::PluginService::GetInstance();
587   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kOutOfProcessPdf) &&
588       PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf_path) &&
589       plugin_service->GetRegisteredPpapiPluginInfo(pdf_path)) {
590     Add(IDR_PDF_MANIFEST, base::FilePath(FILE_PATH_LITERAL("pdf")));
591   }
592 #endif
593 }
594
595 void ComponentLoader::UnloadComponent(ComponentExtensionInfo* component) {
596   delete component->manifest;
597   if (extension_service_->is_ready()) {
598     extension_service_->
599         RemoveComponentExtension(component->extension_id);
600   }
601 }
602
603 void ComponentLoader::EnableFileSystemInGuestMode(const std::string& id) {
604 #if defined(OS_CHROMEOS)
605   const CommandLine* command_line = CommandLine::ForCurrentProcess();
606   if (command_line->HasSwitch(chromeos::switches::kGuestSession)) {
607     // TODO(dpolukhin): Hack to enable HTML5 temporary file system for
608     // the extension. Some component extensions don't work without temporary
609     // file system access. Make sure temporary file system is enabled in the off
610     // the record browser context (as that is the one used in guest session).
611     content::BrowserContext* off_the_record_context =
612         ExtensionsBrowserClient::Get()->GetOffTheRecordContext(
613             browser_context_);
614     GURL site = content::SiteInstance::GetSiteForURL(
615         off_the_record_context, Extension::GetBaseURLFromExtensionId(id));
616     fileapi::FileSystemContext* file_system_context =
617         content::BrowserContext::GetStoragePartitionForSite(
618             off_the_record_context, site)->GetFileSystemContext();
619     file_system_context->EnableTemporaryFileSystemInIncognito();
620   }
621 #endif
622 }
623
624 }  // namespace extensions