| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/extensions_service.h" | 5 #include "chrome/browser/extensions/extensions_service.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
| 9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 10 #include "base/values.h" | 10 #include "base/values.h" |
| 11 #include "chrome/browser/extensions/crx_installer.h" | 11 #include "chrome/browser/extensions/crx_installer.h" |
| 12 #include "chrome/browser/extensions/extension_browser_event_router.h" | 12 #include "chrome/browser/extensions/extension_browser_event_router.h" |
| 13 #include "chrome/browser/extensions/extension_file_util.h" | 13 #include "chrome/browser/extensions/extension_file_util.h" |
| 14 #include "chrome/browser/extensions/extension_updater.h" | 14 #include "chrome/browser/extensions/extension_updater.h" |
| 15 #include "chrome/browser/extensions/external_extension_provider.h" | 15 #include "chrome/browser/extensions/external_extension_provider.h" |
| 16 #include "chrome/browser/extensions/external_pref_extension_provider.h" | 16 #include "chrome/browser/extensions/external_pref_extension_provider.h" |
| 17 #include "chrome/browser/extensions/theme_preview_infobar_delegate.h" | |
| 18 #include "chrome/browser/profile.h" | 17 #include "chrome/browser/profile.h" |
| 19 #include "chrome/browser/tab_contents/tab_contents.h" | |
| 20 #include "chrome/common/chrome_switches.h" | 18 #include "chrome/common/chrome_switches.h" |
| 21 #include "chrome/common/extensions/extension.h" | 19 #include "chrome/common/extensions/extension.h" |
| 22 #include "chrome/common/extensions/extension_error_reporter.h" | 20 #include "chrome/common/extensions/extension_error_reporter.h" |
| 23 #include "chrome/common/notification_service.h" | 21 #include "chrome/common/notification_service.h" |
| 24 #include "chrome/common/pref_names.h" | 22 #include "chrome/common/pref_names.h" |
| 25 #include "chrome/common/pref_service.h" | 23 #include "chrome/common/pref_service.h" |
| 26 #include "chrome/common/url_constants.h" | 24 #include "chrome/common/url_constants.h" |
| 27 | 25 |
| 28 #if defined(OS_WIN) | 26 #if defined(OS_WIN) |
| 29 #include "chrome/browser/extensions/external_registry_extension_provider_win.h" | 27 #include "chrome/browser/extensions/external_registry_extension_provider_win.h" |
| 30 #endif | 28 #endif |
| 31 | 29 |
| 32 // ExtensionsService. | 30 // ExtensionsService. |
| 33 | 31 |
| 34 const char* ExtensionsService::kInstallDirectoryName = "Extensions"; | 32 const char* ExtensionsService::kInstallDirectoryName = "Extensions"; |
| 35 const char* ExtensionsService::kCurrentVersionFileName = "Current Version"; | 33 const char* ExtensionsService::kCurrentVersionFileName = "Current Version"; |
| 36 | 34 |
| 35 /* |
| 37 const char* ExtensionsService::kGalleryDownloadURLPrefix = | 36 const char* ExtensionsService::kGalleryDownloadURLPrefix = |
| 38 "https://dl-ssl.google.com/chrome/"; | 37 "https://dl-ssl.google.com/chrome/"; |
| 39 const char* ExtensionsService::kGalleryURLPrefix = | 38 const char* ExtensionsService::kGalleryURLPrefix = |
| 40 "https://tools.google.com/chrome/"; | 39 "https://tools.google.com/chrome/"; |
| 40 */ |
| 41 const char* ExtensionsService::kGalleryDownloadURLPrefix = |
| 42 "http://www.corp.google.com/~glen/chrome/"; |
| 43 const char* ExtensionsService::kGalleryURLPrefix = |
| 44 "http://www.corp.google.com/~glen/chrome/"; |
| 41 | 45 |
| 42 // static | 46 // static |
| 43 bool ExtensionsService::IsDownloadFromGallery(const GURL& download_url, | 47 bool ExtensionsService::IsDownloadFromGallery(const GURL& download_url, |
| 44 const GURL& referrer_url) { | 48 const GURL& referrer_url) { |
| 45 if (StartsWithASCII(download_url.spec(), kGalleryDownloadURLPrefix, false) && | 49 if (StartsWithASCII(download_url.spec(), kGalleryDownloadURLPrefix, false) && |
| 46 StartsWithASCII(referrer_url.spec(), kGalleryURLPrefix, false)) { | 50 StartsWithASCII(referrer_url.spec(), kGalleryURLPrefix, false)) { |
| 47 return true; | 51 return true; |
| 48 } else { | 52 } else { |
| 49 return false; | 53 return false; |
| 50 } | 54 } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 | 105 |
| 102 // TODO(erikkay) this should probably be deferred to a future point | 106 // TODO(erikkay) this should probably be deferred to a future point |
| 103 // rather than running immediately at startup. | 107 // rather than running immediately at startup. |
| 104 CheckForExternalUpdates(); | 108 CheckForExternalUpdates(); |
| 105 | 109 |
| 106 // TODO(erikkay) this should probably be deferred as well. | 110 // TODO(erikkay) this should probably be deferred as well. |
| 107 GarbageCollectExtensions(); | 111 GarbageCollectExtensions(); |
| 108 } | 112 } |
| 109 | 113 |
| 110 void ExtensionsService::InstallExtension(const FilePath& extension_path) { | 114 void ExtensionsService::InstallExtension(const FilePath& extension_path) { |
| 111 InstallExtension(extension_path, GURL(), GURL()); | 115 CrxInstaller::Start(extension_path, install_directory_, Extension::INTERNAL, |
| 112 } | 116 "", // no expected id |
| 113 | 117 false, // don't delete crx when complete |
| 114 void ExtensionsService::InstallExtension(const FilePath& extension_path, | 118 backend_loop_, |
| 115 const GURL& download_url, | 119 this, |
| 116 const GURL& referrer_url) { | 120 NULL); // no client (silent install) |
| 117 new CrxInstaller(extension_path, install_directory_, Extension::INTERNAL, | |
| 118 "", // no expected id | |
| 119 extensions_enabled_, | |
| 120 IsDownloadFromGallery(download_url, referrer_url), | |
| 121 show_extensions_prompts(), | |
| 122 false, // don't delete crx when complete | |
| 123 backend_loop_, | |
| 124 this); | |
| 125 } | 121 } |
| 126 | 122 |
| 127 void ExtensionsService::UpdateExtension(const std::string& id, | 123 void ExtensionsService::UpdateExtension(const std::string& id, |
| 128 const FilePath& extension_path) { | 124 const FilePath& extension_path) { |
| 129 | 125 |
| 130 if (!GetExtensionById(id)) { | 126 if (!GetExtensionById(id)) { |
| 131 LOG(WARNING) << "Will not update extension " << id << " because it is not " | 127 LOG(WARNING) << "Will not update extension " << id << " because it is not " |
| 132 << "installed"; | 128 << "installed"; |
| 133 return; | 129 return; |
| 134 } | 130 } |
| 135 | 131 |
| 136 new CrxInstaller(extension_path, install_directory_, Extension::INTERNAL, | 132 CrxInstaller::Start(extension_path, install_directory_, Extension::INTERNAL, |
| 137 id, extensions_enabled_, | 133 id, |
| 138 false, // not from gallery | 134 true, // delete crx when complete |
| 139 show_extensions_prompts(), | 135 backend_loop_, |
| 140 true, // delete crx when complete | 136 this, |
| 141 backend_loop_, | 137 NULL); // no client (silent install) |
| 142 this); | |
| 143 } | 138 } |
| 144 | 139 |
| 145 void ExtensionsService::UninstallExtension(const std::string& extension_id, | 140 void ExtensionsService::UninstallExtension(const std::string& extension_id, |
| 146 bool external_uninstall) { | 141 bool external_uninstall) { |
| 147 Extension* extension = GetExtensionById(extension_id); | 142 Extension* extension = GetExtensionById(extension_id); |
| 148 | 143 |
| 149 // Callers should not send us nonexistant extensions. | 144 // Callers should not send us nonexistant extensions. |
| 150 DCHECK(extension); | 145 DCHECK(extension); |
| 151 | 146 |
| 152 extension_prefs_->OnExtensionUninstalled(extension, external_uninstall); | 147 extension_prefs_->OnExtensionUninstalled(extension, external_uninstall); |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 297 } | 292 } |
| 298 } | 293 } |
| 299 } | 294 } |
| 300 | 295 |
| 301 void ExtensionsService::OnExtensionInstalled(Extension* extension) { | 296 void ExtensionsService::OnExtensionInstalled(Extension* extension) { |
| 302 extension_prefs_->OnExtensionInstalled(extension); | 297 extension_prefs_->OnExtensionInstalled(extension); |
| 303 | 298 |
| 304 // If the extension is a theme, tell the profile (and therefore ThemeProvider) | 299 // If the extension is a theme, tell the profile (and therefore ThemeProvider) |
| 305 // to apply it. | 300 // to apply it. |
| 306 if (extension->IsTheme()) { | 301 if (extension->IsTheme()) { |
| 307 ShowThemePreviewInfobar(extension); | |
| 308 NotificationService::current()->Notify( | 302 NotificationService::current()->Notify( |
| 309 NotificationType::THEME_INSTALLED, | 303 NotificationType::THEME_INSTALLED, |
| 310 Source<ExtensionsService>(this), | 304 Source<ExtensionsService>(this), |
| 311 Details<Extension>(extension)); | 305 Details<Extension>(extension)); |
| 312 } else { | 306 } else { |
| 313 NotificationService::current()->Notify( | 307 NotificationService::current()->Notify( |
| 314 NotificationType::EXTENSION_INSTALLED, | 308 NotificationType::EXTENSION_INSTALLED, |
| 315 Source<ExtensionsService>(this), | 309 Source<ExtensionsService>(this), |
| 316 Details<Extension>(extension)); | 310 Details<Extension>(extension)); |
| 317 } | 311 } |
| 318 | 312 |
| 319 // Also load the extension. | 313 // Also load the extension. |
| 320 ExtensionList* list = new ExtensionList; | 314 ExtensionList* list = new ExtensionList; |
| 321 list->push_back(extension); | 315 list->push_back(extension); |
| 322 OnExtensionsLoaded(list); | 316 OnExtensionsLoaded(list); |
| 323 } | 317 } |
| 324 | 318 |
| 325 | 319 |
| 326 void ExtensionsService::OnExtensionOverinstallAttempted(const std::string& id) { | 320 void ExtensionsService::OnExtensionOverinstallAttempted(const std::string& id) { |
| 327 Extension* extension = GetExtensionById(id); | 321 Extension* extension = GetExtensionById(id); |
| 328 if (extension && extension->IsTheme()) { | 322 if (extension && extension->IsTheme()) { |
| 329 ShowThemePreviewInfobar(extension); | |
| 330 NotificationService::current()->Notify( | 323 NotificationService::current()->Notify( |
| 331 NotificationType::THEME_INSTALLED, | 324 NotificationType::THEME_INSTALLED, |
| 332 Source<ExtensionsService>(this), | 325 Source<ExtensionsService>(this), |
| 333 Details<Extension>(extension)); | 326 Details<Extension>(extension)); |
| 334 } | 327 } |
| 335 } | 328 } |
| 336 | 329 |
| 337 Extension* ExtensionsService::GetExtensionById(const std::string& id) { | 330 Extension* ExtensionsService::GetExtensionById(const std::string& id) { |
| 338 std::string lowercase_id = StringToLowerASCII(id); | 331 std::string lowercase_id = StringToLowerASCII(id); |
| 339 for (ExtensionList::const_iterator iter = extensions_.begin(); | 332 for (ExtensionList::const_iterator iter = extensions_.begin(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 354 &ExtensionsServiceBackend::ClearProvidersForTesting)); | 347 &ExtensionsServiceBackend::ClearProvidersForTesting)); |
| 355 } | 348 } |
| 356 | 349 |
| 357 void ExtensionsService::SetProviderForTesting( | 350 void ExtensionsService::SetProviderForTesting( |
| 358 Extension::Location location, ExternalExtensionProvider* test_provider) { | 351 Extension::Location location, ExternalExtensionProvider* test_provider) { |
| 359 backend_loop_->PostTask(FROM_HERE, NewRunnableMethod(backend_.get(), | 352 backend_loop_->PostTask(FROM_HERE, NewRunnableMethod(backend_.get(), |
| 360 &ExtensionsServiceBackend::SetProviderForTesting, | 353 &ExtensionsServiceBackend::SetProviderForTesting, |
| 361 location, test_provider)); | 354 location, test_provider)); |
| 362 } | 355 } |
| 363 | 356 |
| 364 bool ExtensionsService::ShowThemePreviewInfobar(Extension* extension) { | |
| 365 if (!profile_) | |
| 366 return false; | |
| 367 | |
| 368 Browser* browser = BrowserList::GetLastActiveWithProfile(profile_); | |
| 369 if (!browser) | |
| 370 return false; | |
| 371 | |
| 372 TabContents* tab_contents = browser->GetSelectedTabContents(); | |
| 373 if (!tab_contents) | |
| 374 return false; | |
| 375 | |
| 376 tab_contents->AddInfoBar(new ThemePreviewInfobarDelegate(tab_contents, | |
| 377 extension->name())); | |
| 378 return true; | |
| 379 } | |
| 380 | |
| 381 void ExtensionsService::OnExternalExtensionFound(const std::string& id, | 357 void ExtensionsService::OnExternalExtensionFound(const std::string& id, |
| 382 const std::string& version, | 358 const std::string& version, |
| 383 const FilePath& path, | 359 const FilePath& path, |
| 384 Extension::Location location) { | 360 Extension::Location location) { |
| 385 // Before even bothering to unpack, check and see if we already have this | 361 // Before even bothering to unpack, check and see if we already have this |
| 386 // version. This is important because these extensions are going to get | 362 // version. This is important because these extensions are going to get |
| 387 // installed on every startup. | 363 // installed on every startup. |
| 388 Extension* existing = GetExtensionById(id); | 364 Extension* existing = GetExtensionById(id); |
| 389 if (existing) { | 365 if (existing) { |
| 390 switch (existing->version()->CompareTo( | 366 switch (existing->version()->CompareTo( |
| 391 *Version::GetVersionFromString(version))) { | 367 *Version::GetVersionFromString(version))) { |
| 392 case -1: // existing version is older, we should upgrade | 368 case -1: // existing version is older, we should upgrade |
| 393 break; | 369 break; |
| 394 case 0: // existing version is same, do nothing | 370 case 0: // existing version is same, do nothing |
| 395 return; | 371 return; |
| 396 case 1: // existing version is newer, uh-oh | 372 case 1: // existing version is newer, uh-oh |
| 397 LOG(WARNING) << "Found external version of extension " << id | 373 LOG(WARNING) << "Found external version of extension " << id |
| 398 << "that is older than current version. Current version " | 374 << "that is older than current version. Current version " |
| 399 << "is: " << existing->VersionString() << ". New version " | 375 << "is: " << existing->VersionString() << ". New version " |
| 400 << "is: " << version << ". Keeping current version."; | 376 << "is: " << version << ". Keeping current version."; |
| 401 return; | 377 return; |
| 402 } | 378 } |
| 403 } | 379 } |
| 404 | 380 |
| 405 new CrxInstaller(path, install_directory_, location, id, extensions_enabled_, | 381 CrxInstaller::Start(path, install_directory_, location, id, |
| 406 false, // not from gallery | 382 false, // don't delete crx when complete |
| 407 show_extensions_prompts(), | 383 backend_loop_, |
| 408 false, // don't delete crx when complete | 384 this, |
| 409 backend_loop_, | 385 NULL); // no client (silent install) |
| 410 this); | |
| 411 } | 386 } |
| 412 | 387 |
| 413 | 388 |
| 414 // ExtensionsServicesBackend | 389 // ExtensionsServicesBackend |
| 415 | 390 |
| 416 ExtensionsServiceBackend::ExtensionsServiceBackend( | 391 ExtensionsServiceBackend::ExtensionsServiceBackend( |
| 417 const FilePath& install_directory, MessageLoop* frontend_loop) | 392 const FilePath& install_directory, MessageLoop* frontend_loop) |
| 418 : frontend_(NULL), | 393 : frontend_(NULL), |
| 419 install_directory_(install_directory), | 394 install_directory_(install_directory), |
| 420 alert_on_error_(false), | 395 alert_on_error_(false), |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 599 linked_ptr<ExternalExtensionProvider>(test_provider); | 574 linked_ptr<ExternalExtensionProvider>(test_provider); |
| 600 } | 575 } |
| 601 | 576 |
| 602 void ExtensionsServiceBackend::OnExternalExtensionFound( | 577 void ExtensionsServiceBackend::OnExternalExtensionFound( |
| 603 const std::string& id, const Version* version, const FilePath& path, | 578 const std::string& id, const Version* version, const FilePath& path, |
| 604 Extension::Location location) { | 579 Extension::Location location) { |
| 605 frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod(frontend_, | 580 frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod(frontend_, |
| 606 &ExtensionsService::OnExternalExtensionFound, id, version->GetString(), | 581 &ExtensionsService::OnExternalExtensionFound, id, version->GetString(), |
| 607 path, location)); | 582 path, location)); |
| 608 } | 583 } |
| OLD | NEW |