| 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" |
| (...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 326 NewRunnableMethod( | 326 NewRunnableMethod( |
| 327 context_getter, | 327 context_getter, |
| 328 &ChromeURLRequestContextGetter::OnNewExtensions, | 328 &ChromeURLRequestContextGetter::OnNewExtensions, |
| 329 extension->id(), | 329 extension->id(), |
| 330 extension->path())); | 330 extension->path())); |
| 331 } | 331 } |
| 332 } | 332 } |
| 333 | 333 |
| 334 NotificationService::current()->Notify( | 334 NotificationService::current()->Notify( |
| 335 NotificationType::EXTENSION_LOADED, | 335 NotificationType::EXTENSION_LOADED, |
| 336 Source<ExtensionsService>(this), | 336 Source<Profile>(profile_), |
| 337 Details<Extension>(extension)); | 337 Details<Extension>(extension)); |
| 338 } | 338 } |
| 339 | 339 |
| 340 void ExtensionsService::NotifyExtensionUnloaded(Extension* extension) { | 340 void ExtensionsService::NotifyExtensionUnloaded(Extension* extension) { |
| 341 LOG(INFO) << "Sending EXTENSION_UNLOADED"; | 341 LOG(INFO) << "Sending EXTENSION_UNLOADED"; |
| 342 | 342 |
| 343 NotificationService::current()->Notify( | 343 NotificationService::current()->Notify( |
| 344 NotificationType::EXTENSION_UNLOADED, | 344 NotificationType::EXTENSION_UNLOADED, |
| 345 Source<ExtensionsService>(this), | 345 Source<Profile>(profile_), |
| 346 Details<Extension>(extension)); | 346 Details<Extension>(extension)); |
| 347 | 347 |
| 348 if (profile_ && !profile_->IsOffTheRecord()) { | 348 if (profile_ && !profile_->IsOffTheRecord()) { |
| 349 ChromeURLRequestContextGetter* context_getter = | 349 ChromeURLRequestContextGetter* context_getter = |
| 350 static_cast<ChromeURLRequestContextGetter*>( | 350 static_cast<ChromeURLRequestContextGetter*>( |
| 351 profile_->GetRequestContext()); | 351 profile_->GetRequestContext()); |
| 352 if (context_getter) { | 352 if (context_getter) { |
| 353 ChromeThread::PostTask( | 353 ChromeThread::PostTask( |
| 354 ChromeThread::IO, FROM_HERE, | 354 ChromeThread::IO, FROM_HERE, |
| 355 NewRunnableMethod( | 355 NewRunnableMethod( |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 410 ExtensionDOMUI::UnregisterChromeURLOverrides(profile_, | 410 ExtensionDOMUI::UnregisterChromeURLOverrides(profile_, |
| 411 extension->GetChromeURLOverrides()); | 411 extension->GetChromeURLOverrides()); |
| 412 | 412 |
| 413 ExtensionList::iterator iter = std::find(disabled_extensions_.begin(), | 413 ExtensionList::iterator iter = std::find(disabled_extensions_.begin(), |
| 414 disabled_extensions_.end(), | 414 disabled_extensions_.end(), |
| 415 extension.get()); | 415 extension.get()); |
| 416 if (iter != disabled_extensions_.end()) { | 416 if (iter != disabled_extensions_.end()) { |
| 417 disabled_extensions_.erase(iter); | 417 disabled_extensions_.erase(iter); |
| 418 NotificationService::current()->Notify( | 418 NotificationService::current()->Notify( |
| 419 NotificationType::EXTENSION_UNLOADED_DISABLED, | 419 NotificationType::EXTENSION_UNLOADED_DISABLED, |
| 420 Source<ExtensionsService>(this), | 420 Source<Profile>(profile_), |
| 421 Details<Extension>(extension.get())); | 421 Details<Extension>(extension.get())); |
| 422 return; | 422 return; |
| 423 } | 423 } |
| 424 | 424 |
| 425 iter = std::find(extensions_.begin(), extensions_.end(), extension.get()); | 425 iter = std::find(extensions_.begin(), extensions_.end(), extension.get()); |
| 426 | 426 |
| 427 // Remove the extension from our list. | 427 // Remove the extension from our list. |
| 428 extensions_.erase(iter); | 428 extensions_.erase(iter); |
| 429 | 429 |
| 430 NotifyExtensionUnloaded(extension.get()); | 430 NotifyExtensionUnloaded(extension.get()); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 456 installed.extensions())); | 456 installed.extensions())); |
| 457 } | 457 } |
| 458 | 458 |
| 459 void ExtensionsService::OnLoadedInstalledExtensions() { | 459 void ExtensionsService::OnLoadedInstalledExtensions() { |
| 460 ready_ = true; | 460 ready_ = true; |
| 461 if (updater_.get()) { | 461 if (updater_.get()) { |
| 462 updater_->Start(); | 462 updater_->Start(); |
| 463 } | 463 } |
| 464 NotificationService::current()->Notify( | 464 NotificationService::current()->Notify( |
| 465 NotificationType::EXTENSIONS_READY, | 465 NotificationType::EXTENSIONS_READY, |
| 466 Source<ExtensionsService>(this), | 466 Source<Profile>(profile_), |
| 467 NotificationService::NoDetails()); | 467 NotificationService::NoDetails()); |
| 468 } | 468 } |
| 469 | 469 |
| 470 void ExtensionsService::OnExtensionLoaded(Extension* extension, | 470 void ExtensionsService::OnExtensionLoaded(Extension* extension, |
| 471 bool allow_privilege_increase) { | 471 bool allow_privilege_increase) { |
| 472 // Ensure extension is deleted unless we transfer ownership. | 472 // Ensure extension is deleted unless we transfer ownership. |
| 473 scoped_ptr<Extension> scoped_extension(extension); | 473 scoped_ptr<Extension> scoped_extension(extension); |
| 474 | 474 |
| 475 if (extensions_enabled() || | 475 if (extensions_enabled() || |
| 476 extension->IsTheme() || | 476 extension->IsTheme() || |
| (...skipping 10 matching lines...) Expand all Loading... |
| 487 // then load the new one. | 487 // then load the new one. |
| 488 UnloadExtension(old->id()); | 488 UnloadExtension(old->id()); |
| 489 old = NULL; | 489 old = NULL; |
| 490 | 490 |
| 491 if (!allow_silent_upgrade) { | 491 if (!allow_silent_upgrade) { |
| 492 // Extension has changed permissions significantly. Disable it and | 492 // Extension has changed permissions significantly. Disable it and |
| 493 // notify the user. | 493 // notify the user. |
| 494 extension_prefs_->SetExtensionState(extension, Extension::DISABLED); | 494 extension_prefs_->SetExtensionState(extension, Extension::DISABLED); |
| 495 NotificationService::current()->Notify( | 495 NotificationService::current()->Notify( |
| 496 NotificationType::EXTENSION_UPDATE_DISABLED, | 496 NotificationType::EXTENSION_UPDATE_DISABLED, |
| 497 Source<ExtensionsService>(this), | 497 Source<Profile>(profile_), |
| 498 Details<Extension>(extension)); | 498 Details<Extension>(extension)); |
| 499 } | 499 } |
| 500 } else { | 500 } else { |
| 501 // We already have the extension of the same or older version. | 501 // We already have the extension of the same or older version. |
| 502 std::string error_message("Duplicate extension load attempt: "); | 502 std::string error_message("Duplicate extension load attempt: "); |
| 503 error_message += extension->id(); | 503 error_message += extension->id(); |
| 504 LOG(WARNING) << error_message; | 504 LOG(WARNING) << error_message; |
| 505 ReportExtensionLoadError(extension->path(), | 505 ReportExtensionLoadError(extension->path(), |
| 506 error_message, | 506 error_message, |
| 507 NotificationType::EXTENSION_OVERINSTALL_ERROR, | 507 NotificationType::EXTENSION_OVERINSTALL_ERROR, |
| (...skipping 13 matching lines...) Expand all Loading... |
| 521 } | 521 } |
| 522 | 522 |
| 523 if (extension->location() != Extension::LOAD) | 523 if (extension->location() != Extension::LOAD) |
| 524 extension_prefs_->MigrateToPrefs(extension); | 524 extension_prefs_->MigrateToPrefs(extension); |
| 525 | 525 |
| 526 NotifyExtensionLoaded(extension); | 526 NotifyExtensionLoaded(extension); |
| 527 | 527 |
| 528 if (extension->IsTheme() && extension->location() == Extension::LOAD) { | 528 if (extension->IsTheme() && extension->location() == Extension::LOAD) { |
| 529 NotificationService::current()->Notify( | 529 NotificationService::current()->Notify( |
| 530 NotificationType::THEME_INSTALLED, | 530 NotificationType::THEME_INSTALLED, |
| 531 Source<ExtensionsService>(this), | 531 Source<Profile>(profile_), |
| 532 Details<Extension>(extension)); | 532 Details<Extension>(extension)); |
| 533 } else { | 533 } else { |
| 534 ExtensionDOMUI::RegisterChromeURLOverrides(profile_, | 534 ExtensionDOMUI::RegisterChromeURLOverrides(profile_, |
| 535 extension->GetChromeURLOverrides()); | 535 extension->GetChromeURLOverrides()); |
| 536 } | 536 } |
| 537 break; | 537 break; |
| 538 case Extension::DISABLED: | 538 case Extension::DISABLED: |
| 539 NotificationService::current()->Notify( | 539 NotificationService::current()->Notify( |
| 540 NotificationType::EXTENSION_UPDATE_DISABLED, | 540 NotificationType::EXTENSION_UPDATE_DISABLED, |
| 541 Source<ExtensionsService>(this), | 541 Source<Profile>(profile_), |
| 542 Details<Extension>(extension)); | 542 Details<Extension>(extension)); |
| 543 disabled_extensions_.push_back(scoped_extension.release()); | 543 disabled_extensions_.push_back(scoped_extension.release()); |
| 544 break; | 544 break; |
| 545 default: | 545 default: |
| 546 NOTREACHED(); | 546 NOTREACHED(); |
| 547 break; | 547 break; |
| 548 } | 548 } |
| 549 } | 549 } |
| 550 } | 550 } |
| 551 | 551 |
| 552 void ExtensionsService::OnExtensionInstalled(Extension* extension, | 552 void ExtensionsService::OnExtensionInstalled(Extension* extension, |
| 553 bool allow_privilege_increase) { | 553 bool allow_privilege_increase) { |
| 554 extension_prefs_->OnExtensionInstalled(extension); | 554 extension_prefs_->OnExtensionInstalled(extension); |
| 555 | 555 |
| 556 // If the extension is a theme, tell the profile (and therefore ThemeProvider) | 556 // If the extension is a theme, tell the profile (and therefore ThemeProvider) |
| 557 // to apply it. | 557 // to apply it. |
| 558 if (extension->IsTheme()) { | 558 if (extension->IsTheme()) { |
| 559 NotificationService::current()->Notify( | 559 NotificationService::current()->Notify( |
| 560 NotificationType::THEME_INSTALLED, | 560 NotificationType::THEME_INSTALLED, |
| 561 Source<ExtensionsService>(this), | 561 Source<Profile>(profile_), |
| 562 Details<Extension>(extension)); | 562 Details<Extension>(extension)); |
| 563 } else { | 563 } else { |
| 564 NotificationService::current()->Notify( | 564 NotificationService::current()->Notify( |
| 565 NotificationType::EXTENSION_INSTALLED, | 565 NotificationType::EXTENSION_INSTALLED, |
| 566 Source<ExtensionsService>(this), | 566 Source<Profile>(profile_), |
| 567 Details<Extension>(extension)); | 567 Details<Extension>(extension)); |
| 568 } | 568 } |
| 569 | 569 |
| 570 // Also load the extension. | 570 // Also load the extension. |
| 571 OnExtensionLoaded(extension, allow_privilege_increase); | 571 OnExtensionLoaded(extension, allow_privilege_increase); |
| 572 } | 572 } |
| 573 | 573 |
| 574 void ExtensionsService::OnExtensionOverinstallAttempted(const std::string& id) { | 574 void ExtensionsService::OnExtensionOverinstallAttempted(const std::string& id) { |
| 575 Extension* extension = GetExtensionById(id); | 575 Extension* extension = GetExtensionById(id); |
| 576 if (extension && extension->IsTheme()) { | 576 if (extension && extension->IsTheme()) { |
| 577 NotificationService::current()->Notify( | 577 NotificationService::current()->Notify( |
| 578 NotificationType::THEME_INSTALLED, | 578 NotificationType::THEME_INSTALLED, |
| 579 Source<ExtensionsService>(this), | 579 Source<Profile>(profile_), |
| 580 Details<Extension>(extension)); | 580 Details<Extension>(extension)); |
| 581 } else { | 581 } else { |
| 582 NotificationService::current()->Notify( | 582 NotificationService::current()->Notify( |
| 583 NotificationType::NO_THEME_DETECTED, | 583 NotificationType::NO_THEME_DETECTED, |
| 584 Source<ExtensionsService>(this), | 584 Source<Profile>(profile_), |
| 585 NotificationService::NoDetails()); | 585 NotificationService::NoDetails()); |
| 586 } | 586 } |
| 587 } | 587 } |
| 588 | 588 |
| 589 Extension* ExtensionsService::GetExtensionByIdInternal(const std::string& id, | 589 Extension* ExtensionsService::GetExtensionByIdInternal(const std::string& id, |
| 590 bool include_enabled, | 590 bool include_enabled, |
| 591 bool include_disabled) { | 591 bool include_disabled) { |
| 592 std::string lowercase_id = StringToLowerASCII(id); | 592 std::string lowercase_id = StringToLowerASCII(id); |
| 593 if (include_enabled) { | 593 if (include_enabled) { |
| 594 for (ExtensionList::const_iterator iter = extensions_.begin(); | 594 for (ExtensionList::const_iterator iter = extensions_.begin(); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 659 NULL); // no client (silent install) | 659 NULL); // no client (silent install) |
| 660 } | 660 } |
| 661 | 661 |
| 662 void ExtensionsService::ReportExtensionLoadError( | 662 void ExtensionsService::ReportExtensionLoadError( |
| 663 const FilePath& extension_path, | 663 const FilePath& extension_path, |
| 664 const std::string &error, | 664 const std::string &error, |
| 665 NotificationType type, | 665 NotificationType type, |
| 666 bool be_noisy) { | 666 bool be_noisy) { |
| 667 NotificationService* service = NotificationService::current(); | 667 NotificationService* service = NotificationService::current(); |
| 668 service->Notify(type, | 668 service->Notify(type, |
| 669 Source<ExtensionsService>(this), | 669 Source<Profile>(profile_), |
| 670 Details<const std::string>(&error)); | 670 Details<const std::string>(&error)); |
| 671 | 671 |
| 672 // TODO(port): note that this isn't guaranteed to work properly on Linux. | 672 // TODO(port): note that this isn't guaranteed to work properly on Linux. |
| 673 std::string path_str = WideToASCII(extension_path.ToWStringHack()); | 673 std::string path_str = WideToASCII(extension_path.ToWStringHack()); |
| 674 std::string message = StringPrintf("Could not load extension from '%s'. %s", | 674 std::string message = StringPrintf("Could not load extension from '%s'. %s", |
| 675 path_str.c_str(), error.c_str()); | 675 path_str.c_str(), error.c_str()); |
| 676 ExtensionErrorReporter::GetInstance()->ReportError(message, be_noisy); | 676 ExtensionErrorReporter::GetInstance()->ReportError(message, be_noisy); |
| 677 } | 677 } |
| 678 | 678 |
| 679 std::vector<FilePath> ExtensionsService::GetPersistentBlacklistPaths() { |
| 680 std::vector<FilePath> result; |
| 681 for (ExtensionList::const_iterator extension_iter = extensions()->begin(); |
| 682 extension_iter != extensions()->end(); ++extension_iter) { |
| 683 if ((*extension_iter)->location() == Extension::LOAD) |
| 684 continue; |
| 685 |
| 686 std::vector<Extension::PrivacyBlacklistInfo> blacklists( |
| 687 (*extension_iter)->privacy_blacklists()); |
| 688 std::vector<Extension::PrivacyBlacklistInfo>::const_iterator blacklist_iter; |
| 689 for (blacklist_iter = blacklists.begin(); |
| 690 blacklist_iter != blacklists.end(); ++blacklist_iter) { |
| 691 result.push_back(blacklist_iter->path); |
| 692 } |
| 693 } |
| 694 return result; |
| 695 } |
| 696 |
| 697 std::vector<FilePath> ExtensionsService::GetTransientBlacklistPaths() { |
| 698 std::vector<FilePath> result; |
| 699 for (ExtensionList::const_iterator extension_iter = extensions()->begin(); |
| 700 extension_iter != extensions()->end(); ++extension_iter) { |
| 701 if ((*extension_iter)->location() != Extension::LOAD) |
| 702 continue; |
| 703 |
| 704 std::vector<Extension::PrivacyBlacklistInfo> blacklists( |
| 705 (*extension_iter)->privacy_blacklists()); |
| 706 std::vector<Extension::PrivacyBlacklistInfo>::const_iterator blacklist_iter; |
| 707 for (blacklist_iter = blacklists.begin(); |
| 708 blacklist_iter != blacklists.end(); ++blacklist_iter) { |
| 709 result.push_back(blacklist_iter->path); |
| 710 } |
| 711 } |
| 712 return result; |
| 713 } |
| 714 |
| 679 // ExtensionsServicesBackend | 715 // ExtensionsServicesBackend |
| 680 | 716 |
| 681 ExtensionsServiceBackend::ExtensionsServiceBackend( | 717 ExtensionsServiceBackend::ExtensionsServiceBackend( |
| 682 const FilePath& install_directory) | 718 const FilePath& install_directory) |
| 683 : frontend_(NULL), | 719 : frontend_(NULL), |
| 684 install_directory_(install_directory), | 720 install_directory_(install_directory), |
| 685 alert_on_error_(false) { | 721 alert_on_error_(false) { |
| 686 // TODO(aa): This ends up doing blocking IO on the UI thread because it reads | 722 // TODO(aa): This ends up doing blocking IO on the UI thread because it reads |
| 687 // pref data in the ctor and that is called on the UI thread. Would be better | 723 // pref data in the ctor and that is called on the UI thread. Would be better |
| 688 // to re-read data each time we list external extensions, anyway. | 724 // to re-read data each time we list external extensions, anyway. |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 823 | 859 |
| 824 void ExtensionsServiceBackend::OnExternalExtensionFound( | 860 void ExtensionsServiceBackend::OnExternalExtensionFound( |
| 825 const std::string& id, const Version* version, const FilePath& path, | 861 const std::string& id, const Version* version, const FilePath& path, |
| 826 Extension::Location location) { | 862 Extension::Location location) { |
| 827 ChromeThread::PostTask( | 863 ChromeThread::PostTask( |
| 828 ChromeThread::UI, FROM_HERE, | 864 ChromeThread::UI, FROM_HERE, |
| 829 NewRunnableMethod( | 865 NewRunnableMethod( |
| 830 frontend_, &ExtensionsService::OnExternalExtensionFound, id, | 866 frontend_, &ExtensionsService::OnExternalExtensionFound, id, |
| 831 version->GetString(), path, location)); | 867 version->GetString(), path, location)); |
| 832 } | 868 } |
| OLD | NEW |