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