Upstream version 11.39.250.0
[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 <string>
8
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"
31
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"
36 #endif
37
38 #if defined(GOOGLE_CHROME_BUILD)
39 #include "chrome/browser/defaults.h"
40 #endif
41
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"
49 #endif
50
51 #if defined(ENABLE_APP_LIST)
52 #include "chrome/grit/chromium_strings.h"
53 #endif
54
55 using content::BrowserThread;
56
57 namespace extensions {
58
59 namespace {
60
61 static bool enable_background_extensions_during_testing = false;
62
63 std::string GenerateId(const base::DictionaryValue* manifest,
64                        const base::FilePath& path) {
65   std::string raw_key;
66   std::string id_input;
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);
70   return id;
71 }
72
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);
78   std::string error;
79   scoped_ptr<base::DictionaryValue> manifest(
80       file_util::LoadManifest(chromevox_path, manifest_filename, &error));
81   CHECK(manifest) << error;
82   return manifest.Pass();
83 }
84 #endif  // defined(OS_CHROMEOS)
85
86 }  // namespace
87
88 ComponentLoader::ComponentExtensionInfo::ComponentExtensionInfo(
89     const base::DictionaryValue* manifest, const base::FilePath& directory)
90     : manifest(manifest),
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);
95   }
96   extension_id = GenerateId(manifest, root_directory);
97 }
98
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) {}
108
109 ComponentLoader::~ComponentLoader() {
110   ClearAllRegistered();
111 }
112
113 void ComponentLoader::LoadAll() {
114   for (RegisteredComponentExtensions::iterator it =
115           component_extensions_.begin();
116       it != component_extensions_.end(); ++it) {
117     Load(*it);
118   }
119 }
120
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));
125
126   if (!manifest.get() || !manifest->IsType(base::Value::TYPE_DICTIONARY)) {
127     LOG(ERROR) << "Failed to parse extension manifest.";
128     return NULL;
129   }
130   // Transfer ownership to the caller.
131   return static_cast<base::DictionaryValue*>(manifest.release());
132 }
133
134 void ComponentLoader::ClearAllRegistered() {
135   for (RegisteredComponentExtensions::iterator it =
136           component_extensions_.begin();
137       it != component_extensions_.end(); ++it) {
138       delete it->manifest;
139   }
140
141   component_extensions_.clear();
142 }
143
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);
150   if (!manifest)
151     return std::string();
152
153   ComponentExtensionInfo info(manifest, root_directory);
154   return info.extension_id;
155 }
156
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);
163 }
164
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);
170   if (manifest)
171     return Add(manifest, root_directory);
172   return std::string();
173 }
174
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())
180     Load(info);
181   return info.extension_id;
182 }
183
184 std::string ComponentLoader::AddOrReplace(const base::FilePath& path) {
185   base::FilePath absolute_path = base::MakeAbsoluteFilePath(path);
186   std::string error;
187   scoped_ptr<base::DictionaryValue> manifest(
188       file_util::LoadManifest(absolute_path, &error));
189   if (!manifest) {
190     LOG(ERROR) << "Could not load extension from '" <<
191                   absolute_path.value() << "'. " << error;
192     return std::string();
193   }
194   Remove(GenerateId(manifest.get(), absolute_path));
195
196   return Add(manifest.release(), absolute_path);
197 }
198
199 void ComponentLoader::Reload(const std::string& extension_id) {
200   for (RegisteredComponentExtensions::iterator it =
201          component_extensions_.begin(); it != component_extensions_.end();
202          ++it) {
203     if (it->extension_id == extension_id) {
204       Load(*it);
205       break;
206     }
207   }
208 }
209
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;
214
215   std::string error;
216
217   scoped_refptr<const Extension> extension(Extension::Create(
218       info.root_directory,
219       Manifest::COMPONENT,
220       *info.manifest,
221       flags,
222       &error));
223   if (!extension.get()) {
224     LOG(ERROR) << error;
225     return;
226   }
227
228   CHECK_EQ(info.extension_id, extension->id()) << extension->name();
229   extension_service_->AddComponentExtension(extension.get());
230 }
231
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));
238       break;
239     }
240   }
241 }
242
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);
249       break;
250     }
251   }
252 }
253
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)
259       return true;
260   return false;
261 }
262
263 void ComponentLoader::AddFileManagerExtension() {
264 #if defined(OS_CHROMEOS)
265 #ifndef NDEBUG
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);
274     return;
275   }
276 #endif  // NDEBUG
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)
282 }
283
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)
289 }
290
291 void ComponentLoader::AddGalleryExtension() {
292 #if defined(OS_CHROMEOS)
293   Add(IDR_GALLERY_MANIFEST, base::FilePath(FILE_PATH_LITERAL("gallery")));
294 #endif
295 }
296
297 void ComponentLoader::AddHangoutServicesExtension() {
298 #if defined(GOOGLE_CHROME_BUILD) || defined(ENABLE_HANGOUT_SERVICES_EXTENSION)
299   Add(IDR_HANGOUT_SERVICES_MANIFEST,
300       base::FilePath(FILE_PATH_LITERAL("hangout_services")));
301 #endif
302 }
303
304 void ComponentLoader::AddHotwordAudioVerificationApp() {
305   CommandLine* command_line = CommandLine::ForCurrentProcess();
306   if (command_line->HasSwitch(switches::kEnableExperimentalHotwording)) {
307     Add(IDR_HOTWORD_AUDIO_VERIFICATION_MANIFEST,
308         base::FilePath(FILE_PATH_LITERAL("hotword_audio_verification")));
309   }
310 }
311
312 void ComponentLoader::AddHotwordHelperExtension() {
313   if (HotwordServiceFactory::IsHotwordAllowed(browser_context_)) {
314     CommandLine* command_line = CommandLine::ForCurrentProcess();
315     if (command_line->HasSwitch(switches::kEnableExperimentalHotwording)) {
316       Add(IDR_HOTWORD_MANIFEST,
317           base::FilePath(FILE_PATH_LITERAL("hotword")));
318     } else {
319       Add(IDR_HOTWORD_HELPER_MANIFEST,
320           base::FilePath(FILE_PATH_LITERAL("hotword_helper")));
321     }
322   }
323 }
324
325 void ComponentLoader::AddImageLoaderExtension() {
326 #if defined(IMAGE_LOADER_EXTENSION)
327   Add(IDR_IMAGE_LOADER_MANIFEST,
328       base::FilePath(FILE_PATH_LITERAL("image_loader")));
329 #endif  // defined(IMAGE_LOADER_EXTENSION)
330 }
331
332 void ComponentLoader::AddNetworkSpeechSynthesisExtension() {
333   Add(IDR_NETWORK_SPEECH_SYNTHESIS_MANIFEST,
334       base::FilePath(FILE_PATH_LITERAL("network_speech_synthesis")));
335 }
336
337 #if defined(OS_CHROMEOS)
338 void ComponentLoader::AddChromeVoxExtension(
339     const base::Closure& done_cb) {
340   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
341   base::FilePath resources_path;
342   PathService::Get(chrome::DIR_RESOURCES, &resources_path);
343
344   base::FilePath chromevox_path =
345       resources_path.Append(extension_misc::kChromeVoxExtensionPath);
346
347   const CommandLine* command_line = CommandLine::ForCurrentProcess();
348   bool is_chromevox_next =
349       command_line->HasSwitch(chromeos::switches::kEnableChromeVoxNext);
350   bool is_guest = command_line->HasSwitch(chromeos::switches::kGuestSession);
351   const char* manifest_filename;
352   if (is_chromevox_next) {
353     manifest_filename =
354         is_guest ? extension_misc::kChromeVoxNextGuestManifestFilename
355                  : extension_misc::kChromeVoxNextManifestFilename;
356   } else {
357     manifest_filename =
358         is_guest ? extension_misc::kChromeVoxGuestManifestFilename
359                  : extension_misc::kChromeVoxManifestFilename;
360   }
361   BrowserThread::PostTaskAndReplyWithResult(
362       BrowserThread::FILE,
363       FROM_HERE,
364       base::Bind(&LoadManifestOnFileThread, chromevox_path, manifest_filename),
365       base::Bind(&ComponentLoader::AddChromeVoxExtensionWithManifest,
366                  weak_factory_.GetWeakPtr(),
367                  chromevox_path,
368                  done_cb));
369 }
370
371 void ComponentLoader::AddChromeVoxExtensionWithManifest(
372     const base::FilePath& chromevox_path,
373     const base::Closure& done_cb,
374     scoped_ptr<base::DictionaryValue> manifest) {
375   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
376   std::string extension_id = Add(manifest.release(), chromevox_path);
377   CHECK_EQ(extension_misc::kChromeVoxExtensionId, extension_id);
378   if (!done_cb.is_null())
379     done_cb.Run();
380 }
381
382 std::string ComponentLoader::AddChromeOsSpeechSynthesisExtension() {
383   const CommandLine* command_line = CommandLine::ForCurrentProcess();
384   int idr = command_line->HasSwitch(chromeos::switches::kGuestSession) ?
385       IDR_SPEECH_SYNTHESIS_GUEST_MANIFEST : IDR_SPEECH_SYNTHESIS_MANIFEST;
386   std::string id = Add(idr,
387       base::FilePath(extension_misc::kSpeechSynthesisExtensionPath));
388   EnableFileSystemInGuestMode(id);
389   return id;
390 }
391 #endif
392
393 void ComponentLoader::AddWithNameAndDescription(
394     int manifest_resource_id,
395     const base::FilePath& root_directory,
396     int name_string_id,
397     int description_string_id) {
398   std::string manifest_contents =
399       ResourceBundle::GetSharedInstance().GetRawDataResource(
400           manifest_resource_id).as_string();
401
402   // The Value is kept for the lifetime of the ComponentLoader. This is
403   // required in case LoadAll() is called again.
404   base::DictionaryValue* manifest = ParseManifest(manifest_contents);
405
406   if (manifest) {
407     manifest->SetString(manifest_keys::kName,
408                         l10n_util::GetStringUTF8(name_string_id));
409     manifest->SetString(manifest_keys::kDescription,
410                         l10n_util::GetStringUTF8(description_string_id));
411     Add(manifest, root_directory);
412   }
413 }
414
415 void ComponentLoader::AddChromeApp() {
416 #if defined(ENABLE_APP_LIST)
417   AddWithNameAndDescription(IDR_CHROME_APP_MANIFEST,
418                             base::FilePath(FILE_PATH_LITERAL("chrome_app")),
419                             IDS_SHORT_PRODUCT_NAME,
420                             IDS_CHROME_SHORTCUT_DESCRIPTION);
421 #endif
422 }
423
424 void ComponentLoader::AddKeyboardApp() {
425 #if defined(OS_CHROMEOS)
426   Add(IDR_KEYBOARD_MANIFEST, base::FilePath(FILE_PATH_LITERAL("keyboard")));
427 #endif
428 }
429
430 void ComponentLoader::AddWebStoreApp() {
431   AddWithNameAndDescription(IDR_WEBSTORE_MANIFEST,
432                             base::FilePath(FILE_PATH_LITERAL("web_store")),
433                             IDS_WEBSTORE_NAME_STORE,
434                             IDS_WEBSTORE_APP_DESCRIPTION);
435 }
436
437 // static
438 void ComponentLoader::EnableBackgroundExtensionsForTesting() {
439   enable_background_extensions_during_testing = true;
440 }
441
442 void ComponentLoader::AddDefaultComponentExtensions(
443     bool skip_session_components) {
444   // Do not add component extensions that have background pages here -- add them
445   // to AddDefaultComponentExtensionsWithBackgroundPages.
446 #if defined(OS_CHROMEOS)
447   Add(IDR_MOBILE_MANIFEST,
448       base::FilePath(FILE_PATH_LITERAL("/usr/share/chromeos-assets/mobile")));
449
450 #if defined(GOOGLE_CHROME_BUILD)
451   if (browser_defaults::enable_help_app) {
452     Add(IDR_HELP_MANIFEST, base::FilePath(FILE_PATH_LITERAL(
453                                "/usr/share/chromeos-assets/helpapp")));
454   }
455 #endif
456
457   // Skip all other extensions that require user session presence.
458   if (!skip_session_components) {
459     const CommandLine* command_line = CommandLine::ForCurrentProcess();
460     if (!command_line->HasSwitch(chromeos::switches::kGuestSession))
461       Add(IDR_BOOKMARKS_MANIFEST,
462           base::FilePath(FILE_PATH_LITERAL("bookmark_manager")));
463
464     Add(IDR_CROSH_BUILTIN_MANIFEST, base::FilePath(FILE_PATH_LITERAL(
465         "/usr/share/chromeos-assets/crosh_builtin")));
466   }
467 #else  // !defined(OS_CHROMEOS)
468   DCHECK(!skip_session_components);
469   Add(IDR_BOOKMARKS_MANIFEST,
470       base::FilePath(FILE_PATH_LITERAL("bookmark_manager")));
471   // Cloud Print component app. Not required on Chrome OS.
472   Add(IDR_CLOUDPRINT_MANIFEST,
473       base::FilePath(FILE_PATH_LITERAL("cloud_print")));
474 #endif
475
476   if (!skip_session_components) {
477     AddWebStoreApp();
478     AddChromeApp();
479   }
480
481   AddKeyboardApp();
482
483   AddDefaultComponentExtensionsWithBackgroundPages(skip_session_components);
484 }
485
486 void ComponentLoader::AddDefaultComponentExtensionsForKioskMode(
487     bool skip_session_components) {
488   // No component extension for kiosk app launch splash screen.
489   if (skip_session_components)
490     return;
491
492   // Component extensions needed for kiosk apps.
493   AddFileManagerExtension();
494
495   // Add virtual keyboard.
496   AddKeyboardApp();
497 }
498
499 void ComponentLoader::AddDefaultComponentExtensionsWithBackgroundPages(
500     bool skip_session_components) {
501   const CommandLine* command_line = CommandLine::ForCurrentProcess();
502
503   // Component extensions with background pages are not enabled during tests
504   // because they generate a lot of background behavior that can interfere.
505   if (!enable_background_extensions_during_testing &&
506       (command_line->HasSwitch(switches::kTestType) ||
507           command_line->HasSwitch(
508               switches::kDisableComponentExtensionsWithBackgroundPages))) {
509     return;
510   }
511
512 #if defined(OS_CHROMEOS) && defined(GOOGLE_CHROME_BUILD)
513   // Since this is a v2 app it has a background page.
514   AddWithNameAndDescription(IDR_GENIUS_APP_MANIFEST,
515                             base::FilePath(FILE_PATH_LITERAL(
516                                 "/usr/share/chromeos-assets/genius_app")),
517                             IDS_GENIUS_APP_NAME,
518                             IDS_GENIUS_APP_DESCRIPTION);
519 #endif
520
521   if (!skip_session_components) {
522     AddVideoPlayerExtension();
523     AddFileManagerExtension();
524     AddGalleryExtension();
525
526     AddHangoutServicesExtension();
527     AddHotwordAudioVerificationApp();
528     AddHotwordHelperExtension();
529     AddImageLoaderExtension();
530
531 #if defined(ENABLE_SETTINGS_APP)
532     Add(IDR_SETTINGS_APP_MANIFEST,
533         base::FilePath(FILE_PATH_LITERAL("settings_app")));
534 #endif
535   }
536
537   // If (!enable_background_extensions_during_testing || this isn't a test)
538   //   install_feedback = false;
539   bool install_feedback = enable_background_extensions_during_testing;
540 #if defined(GOOGLE_CHROME_BUILD)
541   install_feedback = true;
542 #endif  // defined(GOOGLE_CHROME_BUILD)
543   if (install_feedback)
544     Add(IDR_FEEDBACK_MANIFEST, base::FilePath(FILE_PATH_LITERAL("feedback")));
545
546 #if defined(OS_CHROMEOS)
547   if (!skip_session_components) {
548 #if defined(GOOGLE_CHROME_BUILD)
549     if (!command_line->HasSwitch(
550             chromeos::switches::kDisableOfficeEditingComponentApp)) {
551       std::string id = Add(IDR_QUICKOFFICE_MANIFEST, base::FilePath(
552           FILE_PATH_LITERAL("/usr/share/chromeos-assets/quickoffice")));
553       EnableFileSystemInGuestMode(id);
554     }
555 #endif  // defined(GOOGLE_CHROME_BUILD)
556
557     Add(IDR_ECHO_MANIFEST,
558         base::FilePath(FILE_PATH_LITERAL("/usr/share/chromeos-assets/echo")));
559
560     if (!command_line->HasSwitch(chromeos::switches::kGuestSession)) {
561       Add(IDR_WALLPAPERMANAGER_MANIFEST,
562           base::FilePath(FILE_PATH_LITERAL("chromeos/wallpaper_manager")));
563     }
564
565     Add(IDR_FIRST_RUN_DIALOG_MANIFEST,
566         base::FilePath(FILE_PATH_LITERAL("chromeos/first_run/app")));
567
568     Add(IDR_NETWORK_CONFIGURATION_MANIFEST,
569         base::FilePath(FILE_PATH_LITERAL("chromeos/network_configuration")));
570
571     Add(IDR_CONNECTIVITY_DIAGNOSTICS_MANIFEST,
572         base::FilePath(extension_misc::kConnectivityDiagnosticsPath));
573     Add(IDR_CONNECTIVITY_DIAGNOSTICS_LAUNCHER_MANIFEST,
574         base::FilePath(extension_misc::kConnectivityDiagnosticsLauncherPath));
575   }
576
577   // Load ChromeVox extension now if spoken feedback is enabled.
578   if (chromeos::AccessibilityManager::Get() &&
579       chromeos::AccessibilityManager::Get()->IsSpokenFeedbackEnabled()) {
580     AddChromeVoxExtension(base::Closure());
581   }
582 #endif  // defined(OS_CHROMEOS)
583
584 #if defined(ENABLE_GOOGLE_NOW)
585   const char kEnablePrefix[] = "Enable";
586   const char kFieldTrialName[] = "GoogleNow";
587   std::string enable_prefix(kEnablePrefix);
588   std::string field_trial_result =
589       base::FieldTrialList::FindFullName(kFieldTrialName);
590
591   bool enabled_via_field_trial =
592       field_trial_result.compare(0, enable_prefix.length(), enable_prefix) == 0;
593
594   // Enable the feature on trybots and trunk builds.
595   bool enabled_via_trunk_build =
596       chrome::VersionInfo::GetChannel() == chrome::VersionInfo::CHANNEL_UNKNOWN;
597
598   bool enabled = enabled_via_field_trial || enabled_via_trunk_build;
599
600   if (!skip_session_components && enabled) {
601     Add(IDR_GOOGLE_NOW_MANIFEST,
602         base::FilePath(FILE_PATH_LITERAL("google_now")));
603   }
604 #endif
605
606 #if defined(GOOGLE_CHROME_BUILD)
607 #if !defined(OS_CHROMEOS)  // http://crbug.com/314799
608   AddNetworkSpeechSynthesisExtension();
609 #endif
610
611 #endif  // defined(GOOGLE_CHROME_BUILD)
612
613 #if defined(ENABLE_PLUGINS)
614   base::FilePath pdf_path;
615   content::PluginService* plugin_service =
616       content::PluginService::GetInstance();
617   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kOutOfProcessPdf) &&
618       PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf_path) &&
619       plugin_service->GetRegisteredPpapiPluginInfo(pdf_path)) {
620     Add(IDR_PDF_MANIFEST, base::FilePath(FILE_PATH_LITERAL("pdf")));
621   }
622 #endif
623
624   Add(IDR_CRYPTOTOKEN_MANIFEST,
625       base::FilePath(FILE_PATH_LITERAL("cryptotoken")));
626 }
627
628 void ComponentLoader::UnloadComponent(ComponentExtensionInfo* component) {
629   delete component->manifest;
630   if (extension_service_->is_ready()) {
631     extension_service_->
632         RemoveComponentExtension(component->extension_id);
633   }
634 }
635
636 void ComponentLoader::EnableFileSystemInGuestMode(const std::string& id) {
637 #if defined(OS_CHROMEOS)
638   const CommandLine* command_line = CommandLine::ForCurrentProcess();
639   if (command_line->HasSwitch(chromeos::switches::kGuestSession)) {
640     // TODO(dpolukhin): Hack to enable HTML5 temporary file system for
641     // the extension. Some component extensions don't work without temporary
642     // file system access. Make sure temporary file system is enabled in the off
643     // the record browser context (as that is the one used in guest session).
644     content::BrowserContext* off_the_record_context =
645         ExtensionsBrowserClient::Get()->GetOffTheRecordContext(
646             browser_context_);
647     GURL site = content::SiteInstance::GetSiteForURL(
648         off_the_record_context, Extension::GetBaseURLFromExtensionId(id));
649     storage::FileSystemContext* file_system_context =
650         content::BrowserContext::GetStoragePartitionForSite(
651             off_the_record_context, site)->GetFileSystemContext();
652     file_system_context->EnableTemporaryFileSystemInIncognito();
653   }
654 #endif
655 }
656
657 }  // namespace extensions