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