diff options
author | kalman@chromium.org <kalman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-31 19:52:07 +0000 |
---|---|---|
committer | kalman@chromium.org <kalman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-31 19:52:07 +0000 |
commit | 9f3c853d2c154744e7240988b86f1b4b86a39244 (patch) | |
tree | dbd050915d3a06d0b4f0fcc9cd1273ba557414e6 /chrome/browser/extensions | |
parent | 68476cbd621d10d779d2a316854841666f16de8f (diff) | |
download | chromium_src-9f3c853d2c154744e7240988b86f1b4b86a39244.zip chromium_src-9f3c853d2c154744e7240988b86f1b4b86a39244.tar.gz chromium_src-9f3c853d2c154744e7240988b86f1b4b86a39244.tar.bz2 |
Silently install blacklisted extensions from auto-install locations (sync,
policy, etc) into a blacklisted state, rather than not-silently not-installing
them. This new behaviour is correct from a sync perspective, and the old
behaviour is quite annoying.
BUG=257677
R=yoz@chromium.org,isherman@chromium.org
TBR=akalin@chromium.org,dimich@chromium.org,estade@chromium.org
Review URL: https://chromiumcodereview.appspot.com/20217002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@214806 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/extensions')
20 files changed, 447 insertions, 236 deletions
diff --git a/chrome/browser/extensions/api/preference/preference_api_prefs_unittest.cc b/chrome/browser/extensions/api/preference/preference_api_prefs_unittest.cc index 41e797c..8a69ab3 100644 --- a/chrome/browser/extensions/api/preference/preference_api_prefs_unittest.cc +++ b/chrome/browser/extensions/api/preference/preference_api_prefs_unittest.cc @@ -152,7 +152,9 @@ void ExtensionControlledPrefsTest::EnsureExtensionInstalled( extension4() }; for (size_t i = 0; i < kNumInstalledExtensions; ++i) { if (extension == extensions[i] && !installed_[i]) { - prefs()->OnExtensionInstalled(extension, Extension::ENABLED, + prefs()->OnExtensionInstalled(extension, + Extension::ENABLED, + Blacklist::NOT_BLACKLISTED, syncer::StringOrdinal()); installed_[i] = true; break; diff --git a/chrome/browser/extensions/app_process_apitest.cc b/chrome/browser/extensions/app_process_apitest.cc index 85f6ef8..b1a2b08 100644 --- a/chrome/browser/extensions/app_process_apitest.cc +++ b/chrome/browser/extensions/app_process_apitest.cc @@ -308,6 +308,7 @@ IN_PROC_BROWSER_TEST_F(AppApiTest, MAYBE_BookmarkAppGetsNormalProcess) { service->OnExtensionInstalled(extension.get(), syncer::StringOrdinal::CreateInitialOrdinal(), false /* no requirement errors */, + extensions::Blacklist::NOT_BLACKLISTED, false /* don't wait for idle */); ASSERT_TRUE(extension.get()); ASSERT_TRUE(extension->from_bookmark()); diff --git a/chrome/browser/extensions/blacklist.cc b/chrome/browser/extensions/blacklist.cc index 87c7e28..e0f6dbb5 100644 --- a/chrome/browser/extensions/blacklist.cc +++ b/chrome/browser/extensions/blacklist.cc @@ -13,7 +13,6 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/extensions/extension_prefs.h" -#include "chrome/browser/safe_browsing/database_manager.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/browser/safe_browsing/safe_browsing_util.h" #include "chrome/common/pref_names.h" @@ -116,7 +115,8 @@ class SafeBrowsingClientImpl void IsNotEmpty(const Blacklist::IsBlacklistedCallback& callback, const std::set<std::string>& set) { - callback.Run(!set.empty()); + callback.Run(set.empty() ? Blacklist::NOT_BLACKLISTED + : Blacklist::BLACKLISTED); } } // namespace diff --git a/chrome/browser/extensions/blacklist.h b/chrome/browser/extensions/blacklist.h index 3d6dd8b..ed7acf4 100644 --- a/chrome/browser/extensions/blacklist.h +++ b/chrome/browser/extensions/blacklist.h @@ -52,10 +52,15 @@ class Blacklist : public content::NotificationObserver, DISALLOW_COPY_AND_ASSIGN(ScopedDatabaseManagerForTest); }; + enum BlacklistState { + NOT_BLACKLISTED, + BLACKLISTED, + }; + typedef base::Callback<void(const std::set<std::string>&)> GetBlacklistedIDsCallback; - typedef base::Callback<void(bool)> IsBlacklistedCallback; + typedef base::Callback<void(BlacklistState)> IsBlacklistedCallback; // |prefs_| must outlive this. explicit Blacklist(ExtensionPrefs* prefs); diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc index 588e2f1..a80d1e0 100644 --- a/chrome/browser/extensions/crx_installer.cc +++ b/chrome/browser/extensions/crx_installer.cc @@ -100,13 +100,13 @@ CrxInstaller::CrxInstaller( client_(client), apps_require_extension_mime_type_(false), allow_silent_install_(false), - bypass_blacklist_for_test_(false), install_cause_(extension_misc::INSTALL_CAUSE_UNSET), creation_flags_(Extension::NO_FLAGS), off_store_install_allow_reason_(OffStoreInstallDisallowed), did_handle_successfully_(true), error_on_unsupported_requirements_(false), has_requirement_errors_(false), + blacklist_state_(extensions::Blacklist::NOT_BLACKLISTED), install_wait_for_idle_(true), update_from_settings_page_(false), installer_(service_weak->profile()) { @@ -429,6 +429,9 @@ void CrxInstaller::CheckImportsAndRequirements() { void CrxInstaller::OnRequirementsChecked( std::vector<std::string> requirement_errors) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (!service_weak_) + return; + if (!requirement_errors.empty()) { if (error_on_unsupported_requirements_) { ReportFailureFromUIThread(CrxInstallerError( @@ -437,6 +440,36 @@ void CrxInstaller::OnRequirementsChecked( } has_requirement_errors_ = true; } + + ExtensionSystem::Get(profile())->blacklist()->IsBlacklisted( + extension()->id(), + base::Bind(&CrxInstaller::OnBlacklistChecked, this)); +} + +void CrxInstaller::OnBlacklistChecked( + extensions::Blacklist::BlacklistState blacklist_state) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (!service_weak_) + return; + + blacklist_state_ = blacklist_state; + + if (blacklist_state_ == extensions::Blacklist::BLACKLISTED && + !allow_silent_install_) { + // User tried to install a blacklisted extension. Show an error and + // refuse to install it. + ReportFailureFromUIThread(extensions::CrxInstallerError( + l10n_util::GetStringFUTF16(IDS_EXTENSION_IS_BLACKLISTED, + UTF8ToUTF16(extension()->name())))); + UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.BlockCRX", + extension()->location(), + Manifest::NUM_LOCATIONS); + return; + } + + // NOTE: extension may still be blacklisted, but we're forced to silently + // install it. In this case, ExtensionService::OnExtensionInstalled needs to + // deal with it. ConfirmInstall(); } @@ -673,43 +706,12 @@ void CrxInstaller::ReportSuccessFromUIThread() { } } - // Install the extension if it's not blacklisted, but notify either way. - base::Closure on_success = - base::Bind(&ExtensionService::OnExtensionInstalled, - service_weak_, - extension(), - page_ordinal_, - has_requirement_errors_, - install_wait_for_idle_); - if (bypass_blacklist_for_test_) { - HandleIsBlacklistedResponse(on_success, false); - } else { - ExtensionSystem::Get(profile())->blacklist()->IsBlacklisted( - extension()->id(), - base::Bind(&CrxInstaller::HandleIsBlacklistedResponse, - this, - on_success)); - } -} - -void CrxInstaller::HandleIsBlacklistedResponse( - const base::Closure& on_success, - bool is_blacklisted) { - if (is_blacklisted) { - string16 error = l10n_util::GetStringFUTF16( - IDS_EXTENSION_IS_BLACKLISTED, - UTF8ToUTF16(extension()->name())); - make_scoped_ptr(ExtensionInstallUI::Create(profile()))->OnInstallFailure( - extensions::CrxInstallerError(error)); - // Show error via reporter to make tests happy. - ExtensionErrorReporter::GetInstance()->ReportError(error, false); // quiet - UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.BlockCRX", - extension()->location(), - Manifest::NUM_LOCATIONS); - } else { - on_success.Run(); - } - NotifyCrxInstallComplete(!is_blacklisted); + service_weak_->OnExtensionInstalled(extension(), + page_ordinal_, + has_requirement_errors_, + blacklist_state_, + install_wait_for_idle_); + NotifyCrxInstallComplete(true); } void CrxInstaller::NotifyCrxInstallComplete(bool success) { @@ -726,7 +728,6 @@ void CrxInstaller::NotifyCrxInstallComplete(bool success) { if (success) ConfirmReEnable(); - } void CrxInstaller::CleanupTempFiles() { diff --git a/chrome/browser/extensions/crx_installer.h b/chrome/browser/extensions/crx_installer.h index dd2e9216..6f71868 100644 --- a/chrome/browser/extensions/crx_installer.h +++ b/chrome/browser/extensions/crx_installer.h @@ -12,6 +12,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/version.h" +#include "chrome/browser/extensions/blacklist.h" #include "chrome/browser/extensions/extension_install_prompt.h" #include "chrome/browser/extensions/extension_installer.h" #include "chrome/browser/extensions/sandboxed_unpacker.h" @@ -131,10 +132,6 @@ class CrxInstaller bool allow_silent_install() const { return allow_silent_install_; } void set_allow_silent_install(bool val) { allow_silent_install_ = val; } - void set_bypass_blacklist_for_test(bool val) { - bypass_blacklist_for_test_ = val; - } - bool is_gallery_install() const { return (creation_flags_ & Extension::FROM_WEBSTORE) > 0; } @@ -231,6 +228,10 @@ class CrxInstaller // Runs on the UI thread. Callback from RequirementsChecker. void OnRequirementsChecked(std::vector<std::string> requirement_errors); + // Runs on the UI thread. Callback from Blacklist. + void OnBlacklistChecked( + extensions::Blacklist::BlacklistState blacklist_state); + // Runs on the UI thread. Confirms the installation to the ExtensionService. void ConfirmInstall(); @@ -243,8 +244,6 @@ class CrxInstaller void ReportFailureFromUIThread(const CrxInstallerError& error); void ReportSuccessFromFileThread(); void ReportSuccessFromUIThread(); - void HandleIsBlacklistedResponse(const base::Closure& on_success, - bool success); void NotifyCrxInstallComplete(bool success); // Deletes temporary directory and crx file if needed. @@ -349,9 +348,6 @@ class CrxInstaller // dialog. bool allow_silent_install_; - // Allows for bypassing the blacklist check. Only use for tests. - bool bypass_blacklist_for_test_; - // The value of the content type header sent with the CRX. // Ignorred unless |require_extension_mime_type_| is true. std::string original_mime_type_; @@ -381,6 +377,8 @@ class CrxInstaller bool has_requirement_errors_; + extensions::Blacklist::BlacklistState blacklist_state_; + bool install_wait_for_idle_; // Sequenced task runner where file I/O operations will be performed. diff --git a/chrome/browser/extensions/crx_installer_browsertest.cc b/chrome/browser/extensions/crx_installer_browsertest.cc index 9a764d9..9cdfcaf 100644 --- a/chrome/browser/extensions/crx_installer_browsertest.cc +++ b/chrome/browser/extensions/crx_installer_browsertest.cc @@ -107,7 +107,6 @@ class ExtensionCrxInstallerTest : public ExtensionBrowserTest { approval.get() /* keep ownership */)); installer->set_allow_silent_install(true); installer->set_is_gallery_install(true); - installer->set_bypass_blacklist_for_test(true); installer->InstallCrx(PackExtension(ext_path)); content::RunMessageLoop(); @@ -379,4 +378,18 @@ IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, ASSERT_EQ("3.0", extension->version()->GetString()); } +IN_PROC_BROWSER_TEST_F(ExtensionCrxInstallerTest, Blacklist) { + extensions::Blacklist* blacklist = + ExtensionSystem::Get(profile())->blacklist(); + + // Fake the blacklisting of the extension we're about to install by + // pretending that we get a blacklist update which includes it. + const std::string kId = "gllekhaobjnhgeagipipnkpmmmpchacm"; + blacklist->SetFromUpdater(std::vector<std::string>(1, kId), "some-version"); + + base::FilePath crx_path = test_data_dir_.AppendASCII("theme_hidpi_crx") + .AppendASCII("theme_hidpi.crx"); + EXPECT_FALSE(InstallExtension(crx_path, 0)); +} + } // namespace extensions diff --git a/chrome/browser/extensions/extension_blacklist_browsertest.cc b/chrome/browser/extensions/extension_blacklist_browsertest.cc index a75706c..3f57cb6 100644 --- a/chrome/browser/extensions/extension_blacklist_browsertest.cc +++ b/chrome/browser/extensions/extension_blacklist_browsertest.cc @@ -3,151 +3,19 @@ // found in the LICENSE file. #include "base/run_loop.h" -#include "base/strings/stringprintf.h" -#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/extensions/blacklist.h" #include "chrome/browser/extensions/extension_browsertest.h" +#include "chrome/browser/extensions/extension_notification_observer.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_system.h" #include "chrome/browser/ui/browser.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_constants.h" -#include "content/public/browser/notification_details.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" -#include "content/public/browser/notification_service.h" -#include "content/public/browser/notification_source.h" namespace extensions { namespace { -// Records notifications, but only for extensions with specific IDs. -class FilteringNotificationObserver : public content::NotificationObserver { - public: - FilteringNotificationObserver( - content::NotificationSource source, - const std::set<std::string>& extension_ids) - : extension_ids_(extension_ids) { - registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, source); - registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED, source); - registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, source); - } - - // Checks then clears notifications for our extensions. - testing::AssertionResult CheckNotifications(chrome::NotificationType type) { - return CheckNotifications(std::vector<chrome::NotificationType>(1, type)); - } - - // Checks then clears notifications for our extensions. - testing::AssertionResult CheckNotifications(chrome::NotificationType t1, - chrome::NotificationType t2) { - std::vector<chrome::NotificationType> types; - types.push_back(t1); - types.push_back(t2); - return CheckNotifications(types); - } - - // Checks then clears notifications for our extensions. - testing::AssertionResult CheckNotifications(chrome::NotificationType t1, - chrome::NotificationType t2, - chrome::NotificationType t3) { - std::vector<chrome::NotificationType> types; - types.push_back(t1); - types.push_back(t2); - types.push_back(t3); - return CheckNotifications(types); - } - - // Checks then clears notifications for our extensions. - testing::AssertionResult CheckNotifications(chrome::NotificationType t1, - chrome::NotificationType t2, - chrome::NotificationType t3, - chrome::NotificationType t4, - chrome::NotificationType t5, - chrome::NotificationType t6) { - std::vector<chrome::NotificationType> types; - types.push_back(t1); - types.push_back(t2); - types.push_back(t3); - types.push_back(t4); - types.push_back(t5); - types.push_back(t6); - return CheckNotifications(types); - } - - private: - // content::NotificationObserver implementation. - virtual void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) OVERRIDE { - switch (type) { - case chrome::NOTIFICATION_EXTENSION_INSTALLED: { - const Extension* extension = - content::Details<const InstalledExtensionInfo>(details)->extension; - if (extension_ids_.count(extension->id())) - notifications_.push_back(static_cast<chrome::NotificationType>(type)); - break; - } - - case chrome::NOTIFICATION_EXTENSION_LOADED: { - const Extension* extension = - content::Details<const Extension>(details).ptr(); - if (extension_ids_.count(extension->id())) - notifications_.push_back(static_cast<chrome::NotificationType>(type)); - break; - } - - case chrome::NOTIFICATION_EXTENSION_UNLOADED: { - UnloadedExtensionInfo* reason = - content::Details<UnloadedExtensionInfo>(details).ptr(); - if (extension_ids_.count(reason->extension->id())) { - notifications_.push_back(static_cast<chrome::NotificationType>(type)); - // The only way that extensions are unloaded in these tests is - // by blacklisting. - EXPECT_EQ(extension_misc::UNLOAD_REASON_BLACKLIST, - reason->reason); - } - break; - } - - default: - NOTREACHED(); - break; - } - } - - // Checks then clears notifications for our extensions. - testing::AssertionResult CheckNotifications( - const std::vector<chrome::NotificationType>& types) { - testing::AssertionResult result = (notifications_ == types) ? - testing::AssertionSuccess() : - testing::AssertionFailure() << "Expected " << Str(types) << ", " << - "Got " << Str(notifications_); - notifications_.clear(); - return result; - } - - std::string Str(const std::vector<chrome::NotificationType>& types) { - std::string str = "["; - bool needs_comma = false; - for (std::vector<chrome::NotificationType>::const_iterator it = - types.begin(); it != types.end(); ++it) { - if (needs_comma) - str += ","; - needs_comma = true; - str += base::StringPrintf("%d", *it); - } - return str + "]"; - } - - const std::set<std::string> extension_ids_; - - std::vector<chrome::NotificationType> notifications_; - - content::NotificationRegistrar registrar_; -}; - // Stores the paths to CRX files of extensions, and the extension's ID. // Use arbitrary extensions; we're just testing blacklisting behavior. class CrxInfo { @@ -243,7 +111,7 @@ class ExtensionBlacklistBrowserTest : public ExtensionBrowserTest { // Stage 1: blacklisting when there weren't any extensions installed when the // browser started. IN_PROC_BROWSER_TEST_F(ExtensionBlacklistBrowserTest, PRE_Blacklist) { - FilteringNotificationObserver notifications( + ExtensionNotificationObserver notifications( content::NotificationService::AllSources(), GetTestExtensionIDs()); scoped_refptr<const Extension> extension_a = @@ -361,7 +229,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionBlacklistBrowserTest, PRE_Blacklist) { // Stage 2: blacklisting with extensions A and B having been installed, // with A actually in the blacklist. IN_PROC_BROWSER_TEST_F(ExtensionBlacklistBrowserTest, Blacklist) { - FilteringNotificationObserver notifications( + ExtensionNotificationObserver notifications( content::Source<Profile>(profile()), GetTestExtensionIDs()); scoped_refptr<const Extension> extension_a = diff --git a/chrome/browser/extensions/extension_browsertest.cc b/chrome/browser/extensions/extension_browsertest.cc index f71864f..05e426c 100644 --- a/chrome/browser/extensions/extension_browsertest.cc +++ b/chrome/browser/extensions/extension_browsertest.cc @@ -159,7 +159,9 @@ const Extension* ExtensionBrowserTest::LoadExtensionWithFlags( // The call to OnExtensionInstalled ensures the other extension prefs // are set up with the defaults. service->extension_prefs()->OnExtensionInstalled( - extension, Extension::ENABLED, + extension, + Extension::ENABLED, + extensions::Blacklist::NOT_BLACKLISTED, syncer::StringOrdinal::CreateInitialOrdinal()); // Toggling incognito or file access will reload the extension, so wait for diff --git a/chrome/browser/extensions/extension_notification_observer.cc b/chrome/browser/extensions/extension_notification_observer.cc new file mode 100644 index 0000000..7f5baf9 --- /dev/null +++ b/chrome/browser/extensions/extension_notification_observer.cc @@ -0,0 +1,141 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/extension_notification_observer.h" + +#include <vector> + +#include "base/logging.h" +#include "base/strings/stringprintf.h" +#include "chrome/common/extensions/extension.h" + +namespace extensions { + +namespace { + +std::string Str(const std::vector<chrome::NotificationType>& types) { + std::string str = "["; + bool needs_comma = false; + for (std::vector<chrome::NotificationType>::const_iterator it = + types.begin(); it != types.end(); ++it) { + if (needs_comma) + str += ","; + needs_comma = true; + str += base::StringPrintf("%d", *it); + } + str += "]"; + return str; +} + +} // namespace + +ExtensionNotificationObserver::ExtensionNotificationObserver( + content::NotificationSource source, + const std::set<std::string>& extension_ids) + : extension_ids_(extension_ids) { + registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, source); + registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED, source); + registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, source); +} + +ExtensionNotificationObserver::~ExtensionNotificationObserver() {} + +testing::AssertionResult ExtensionNotificationObserver::CheckNotifications() { + return CheckNotifications(std::vector<chrome::NotificationType>()); +} + +testing::AssertionResult ExtensionNotificationObserver::CheckNotifications( + chrome::NotificationType type) { + return CheckNotifications(std::vector<chrome::NotificationType>(1, type)); +} + +testing::AssertionResult ExtensionNotificationObserver::CheckNotifications( + chrome::NotificationType t1, + chrome::NotificationType t2) { + std::vector<chrome::NotificationType> types; + types.push_back(t1); + types.push_back(t2); + return CheckNotifications(types); +} + +testing::AssertionResult ExtensionNotificationObserver::CheckNotifications( + chrome::NotificationType t1, + chrome::NotificationType t2, + chrome::NotificationType t3) { + std::vector<chrome::NotificationType> types; + types.push_back(t1); + types.push_back(t2); + types.push_back(t3); + return CheckNotifications(types); +} + +testing::AssertionResult ExtensionNotificationObserver::CheckNotifications( + chrome::NotificationType t1, + chrome::NotificationType t2, + chrome::NotificationType t3, + chrome::NotificationType t4, + chrome::NotificationType t5, + chrome::NotificationType t6) { + std::vector<chrome::NotificationType> types; + types.push_back(t1); + types.push_back(t2); + types.push_back(t3); + types.push_back(t4); + types.push_back(t5); + types.push_back(t6); + return CheckNotifications(types); +} + +// content::NotificationObserver implementation. +void ExtensionNotificationObserver::Observe( + int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + switch (type) { + case chrome::NOTIFICATION_EXTENSION_INSTALLED: { + const Extension* extension = + content::Details<const InstalledExtensionInfo>(details)->extension; + if (extension_ids_.count(extension->id())) + notifications_.push_back(static_cast<chrome::NotificationType>(type)); + break; + } + + case chrome::NOTIFICATION_EXTENSION_LOADED: { + const Extension* extension = + content::Details<const Extension>(details).ptr(); + if (extension_ids_.count(extension->id())) + notifications_.push_back(static_cast<chrome::NotificationType>(type)); + break; + } + + case chrome::NOTIFICATION_EXTENSION_UNLOADED: { + UnloadedExtensionInfo* reason = + content::Details<UnloadedExtensionInfo>(details).ptr(); + if (extension_ids_.count(reason->extension->id())) { + notifications_.push_back(static_cast<chrome::NotificationType>(type)); + // The only way that extensions are unloaded in these tests is + // by blacklisting. + EXPECT_EQ(extension_misc::UNLOAD_REASON_BLACKLIST, + reason->reason); + } + break; + } + + default: + NOTREACHED(); + break; + } +} + +testing::AssertionResult ExtensionNotificationObserver::CheckNotifications( + const std::vector<chrome::NotificationType>& types) { + testing::AssertionResult result = (notifications_ == types) ? + testing::AssertionSuccess() : + testing::AssertionFailure() << "Expected " << Str(types) << ", " << + "Got " << Str(notifications_); + notifications_.clear(); + return result; +} + +} // namespace extensions diff --git a/chrome/browser/extensions/extension_notification_observer.h b/chrome/browser/extensions/extension_notification_observer.h new file mode 100644 index 0000000..facb403 --- /dev/null +++ b/chrome/browser/extensions/extension_notification_observer.h @@ -0,0 +1,69 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_NOTIFICATION_OBSERVER_H_ +#define CHROME_BROWSER_EXTENSIONS_EXTENSION_NOTIFICATION_OBSERVER_H_ + +#include <set> +#include <string> + +#include "base/compiler_specific.h" +#include "chrome/browser/chrome_notification_types.h" +#include "content/public/browser/notification_details.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" +#include "content/public/browser/notification_service.h" +#include "content/public/browser/notification_source.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace extensions { + +// Records LOADED, INSTALLED, and UNLOADED notifications for extensions with +// specific IDs. Use in tests only. +class ExtensionNotificationObserver : public content::NotificationObserver { + public: + ExtensionNotificationObserver(content::NotificationSource source, + const std::set<std::string>& extension_ids); + + virtual ~ExtensionNotificationObserver(); + + // Each of these methods returns a testing::AssertionSuccess if exactly those + // notifications occurred for any extensions in |extension_ids|, and no more, + // since the last time any of these methods were called. + testing::AssertionResult CheckNotifications() WARN_UNUSED_RESULT; + testing::AssertionResult CheckNotifications( + chrome::NotificationType type) WARN_UNUSED_RESULT; + testing::AssertionResult CheckNotifications( + chrome::NotificationType t1, + chrome::NotificationType t2) WARN_UNUSED_RESULT; + testing::AssertionResult CheckNotifications( + chrome::NotificationType t1, + chrome::NotificationType t2, + chrome::NotificationType t3) WARN_UNUSED_RESULT; + testing::AssertionResult CheckNotifications( + chrome::NotificationType t1, + chrome::NotificationType t2, + chrome::NotificationType t3, + chrome::NotificationType t4, + chrome::NotificationType t5, + chrome::NotificationType t6) WARN_UNUSED_RESULT; + + private: + // content::NotificationObserver implementation. + virtual void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) OVERRIDE; + + // Checks then clears notifications for our extensions. + testing::AssertionResult CheckNotifications( + const std::vector<chrome::NotificationType>& types); + + const std::set<std::string> extension_ids_; + std::vector<chrome::NotificationType> notifications_; + content::NotificationRegistrar registrar_; +}; + +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_NOTIFICATION_OBSERVER_H_ diff --git a/chrome/browser/extensions/extension_prefs.cc b/chrome/browser/extensions/extension_prefs.cc index 904527d..6447ad3 100644 --- a/chrome/browser/extensions/extension_prefs.cc +++ b/chrome/browser/extensions/extension_prefs.cc @@ -1163,12 +1163,13 @@ void ExtensionPrefs::SetToolbarOrder(const ExtensionIdList& extension_ids) { void ExtensionPrefs::OnExtensionInstalled( const Extension* extension, Extension::State initial_state, + Blacklist::BlacklistState blacklist_state, const syncer::StringOrdinal& page_ordinal) { ScopedExtensionPrefUpdate update(prefs_, extension->id()); DictionaryValue* extension_dict = update.Get(); const base::Time install_time = time_provider_->GetCurrentTime(); PopulateExtensionInfoPrefs(extension, install_time, initial_state, - extension_dict); + blacklist_state, extension_dict); FinishExtensionInfoPrefs(extension->id(), install_time, extension->RequiresSortOrdinal(), page_ordinal, extension_dict); @@ -1329,11 +1330,12 @@ ExtensionPrefs::GetInstalledExtensionsInfo() const { void ExtensionPrefs::SetDelayedInstallInfo( const Extension* extension, Extension::State initial_state, + Blacklist::BlacklistState blacklist_state, DelayReason delay_reason, const syncer::StringOrdinal& page_ordinal) { DictionaryValue* extension_dict = new DictionaryValue(); PopulateExtensionInfoPrefs(extension, time_provider_->GetCurrentTime(), - initial_state, extension_dict); + initial_state, blacklist_state, extension_dict); // Add transient data that is needed by FinishDelayedInstallInfo(), but // should not be in the final extension prefs. All entries here should have @@ -1766,6 +1768,7 @@ void ExtensionPrefs::PopulateExtensionInfoPrefs( const Extension* extension, const base::Time install_time, Extension::State initial_state, + Blacklist::BlacklistState blacklist_state, DictionaryValue* extension_dict) { // Leave the state blank for component extensions so that old chrome versions // loading new profiles do not fail in GetInstalledExtensionInfo. Older @@ -1787,6 +1790,8 @@ void ExtensionPrefs::PopulateExtensionInfoPrefs( extension_dict->Set(kPrefInstallTime, Value::CreateStringValue( base::Int64ToString(install_time.ToInternalValue()))); + if (blacklist_state == Blacklist::BLACKLISTED) + extension_dict->Set(kPrefBlacklist, Value::CreateBooleanValue(true)); base::FilePath::StringType path = MakePathRelative(install_directory_, extension->path()); diff --git a/chrome/browser/extensions/extension_prefs.h b/chrome/browser/extensions/extension_prefs.h index 354420e..eb731c6 100644 --- a/chrome/browser/extensions/extension_prefs.h +++ b/chrome/browser/extensions/extension_prefs.h @@ -13,6 +13,7 @@ #include "base/memory/scoped_ptr.h" #include "base/time/time.h" #include "base/values.h" +#include "chrome/browser/extensions/blacklist.h" #include "chrome/browser/extensions/extension_scoped_prefs.h" #include "chrome/browser/prefs/scoped_user_pref_update.h" #include "chrome/common/extensions/extension.h" @@ -187,6 +188,7 @@ class ExtensionPrefs : public ExtensionScopedPrefs, // for the App. void OnExtensionInstalled(const Extension* extension, Extension::State initial_state, + Blacklist::BlacklistState blacklist_state, const syncer::StringOrdinal& page_ordinal); // Called when an extension is uninstalled, so that prefs get cleaned up. @@ -408,6 +410,7 @@ class ExtensionPrefs : public ExtensionScopedPrefs, // to install it. void SetDelayedInstallInfo(const Extension* extension, Extension::State initial_state, + Blacklist::BlacklistState blacklist_state, DelayReason delay_reason, const syncer::StringOrdinal& page_ordinal); @@ -585,6 +588,7 @@ class ExtensionPrefs : public ExtensionScopedPrefs, void PopulateExtensionInfoPrefs(const Extension* extension, const base::Time install_time, Extension::State initial_state, + Blacklist::BlacklistState blacklist_state, base::DictionaryValue* extension_dict); // Helper function to complete initialization of the values in diff --git a/chrome/browser/extensions/extension_prefs_unittest.cc b/chrome/browser/extensions/extension_prefs_unittest.cc index 08d07d6..c7034d1 100644 --- a/chrome/browser/extensions/extension_prefs_unittest.cc +++ b/chrome/browser/extensions/extension_prefs_unittest.cc @@ -451,7 +451,9 @@ class ExtensionPrefsDelayedInstallInfo : public ExtensionPrefsTest { path, Manifest::INTERNAL, manifest, Extension::NO_FLAGS, id, &errors); ASSERT_TRUE(extension.get()) << errors; ASSERT_EQ(id, extension->id()); - prefs()->SetDelayedInstallInfo(extension.get(), Extension::ENABLED, + prefs()->SetDelayedInstallInfo(extension.get(), + Extension::ENABLED, + Blacklist::NOT_BLACKLISTED, ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE, syncer::StringOrdinal()); } @@ -551,9 +553,10 @@ class ExtensionPrefsOnExtensionInstalled : public ExtensionPrefsTest { virtual void Initialize() OVERRIDE { extension_ = prefs_.AddExtension("on_extension_installed"); EXPECT_FALSE(prefs()->IsExtensionDisabled(extension_->id())); - prefs()->OnExtensionInstalled( - extension_.get(), Extension::DISABLED, - syncer::StringOrdinal()); + prefs()->OnExtensionInstalled(extension_.get(), + Extension::DISABLED, + Blacklist::NOT_BLACKLISTED, + syncer::StringOrdinal()); } virtual void Verify() OVERRIDE { @@ -571,7 +574,9 @@ class ExtensionPrefsAppDraggedByUser : public ExtensionPrefsTest { virtual void Initialize() OVERRIDE { extension_ = prefs_.AddExtension("on_extension_installed"); EXPECT_FALSE(prefs()->WasAppDraggedByUser(extension_->id())); - prefs()->OnExtensionInstalled(extension_.get(), Extension::ENABLED, + prefs()->OnExtensionInstalled(extension_.get(), + Extension::ENABLED, + Blacklist::NOT_BLACKLISTED, syncer::StringOrdinal()); } diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc index ec57c0a..42cb3fa 100644 --- a/chrome/browser/extensions/extension_service.cc +++ b/chrome/browser/extensions/extension_service.cc @@ -2038,7 +2038,8 @@ void ExtensionService::AddExtension(const Extension* extension) { if (extension_prefs_->IsExtensionBlacklisted(extension->id())) { // Only prefs is checked for the blacklist. We rely on callers to check the // blacklist before calling into here, e.g. CrxInstaller checks before - // installation, we check when loading installed extensions. + // installation then threads through the install and pending install flow + // of this class, and we check when loading installed extensions. blacklisted_extensions_.Insert(extension); } else if (!reloading && extension_prefs_->IsExtensionDisabled(extension->id())) { @@ -2090,6 +2091,7 @@ void ExtensionService::AddComponentExtension(const Extension* extension) { AddNewOrUpdatedExtension(extension, Extension::ENABLED_COMPONENT, + extensions::Blacklist::NOT_BLACKLISTED, syncer::StringOrdinal()); return; } @@ -2328,6 +2330,7 @@ void ExtensionService::OnExtensionInstalled( const Extension* extension, const syncer::StringOrdinal& page_ordinal, bool has_requirement_errors, + extensions::Blacklist::BlacklistState blacklist_state, bool wait_for_idle) { CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); @@ -2384,6 +2387,18 @@ void ExtensionService::OnExtensionInstalled( extension_prefs_->ClearDisableReasons(id); } + if (blacklist_state == extensions::Blacklist::BLACKLISTED) { + // Installation of a blacklisted extension can happen from sync, policy, + // etc, where to maintain consistency we need to install it, just never + // load it (see AddExtension). Usually it should be the job of callers to + // incercept blacklisted extension earlier (e.g. CrxInstaller, before even + // showing the install dialogue). + extension_prefs()->AcknowledgeBlacklistedExtension(id); + UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.SilentInstall", + extension->location(), + Manifest::NUM_LOCATIONS); + } + if (!GetInstalledExtension(extension->id())) { UMA_HISTOGRAM_ENUMERATION("Extensions.InstallType", extension->GetType(), 100); @@ -2405,8 +2420,12 @@ void ExtensionService::OnExtensionInstalled( const Extension::State initial_state = initial_enable ? Extension::ENABLED : Extension::DISABLED; if (ShouldDelayExtensionUpdate(id, wait_for_idle)) { - extension_prefs_->SetDelayedInstallInfo(extension, initial_state, - extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE, page_ordinal); + extension_prefs_->SetDelayedInstallInfo( + extension, + initial_state, + blacklist_state, + extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE, + page_ordinal); // Transfer ownership of |extension|. delayed_installs_.Insert(extension); @@ -2423,34 +2442,42 @@ void ExtensionService::OnExtensionInstalled( ImportStatus status = SatisfyImports(extension); if (installs_delayed_for_gc()) { - extension_prefs_->SetDelayedInstallInfo(extension, initial_state, - extensions::ExtensionPrefs::DELAY_REASON_GC, page_ordinal); + extension_prefs_->SetDelayedInstallInfo( + extension, + initial_state, + blacklist_state, + extensions::ExtensionPrefs::DELAY_REASON_GC, + page_ordinal); delayed_installs_.Insert(extension); } else if (status != IMPORT_STATUS_OK) { if (status == IMPORT_STATUS_UNSATISFIED) { - extension_prefs_->SetDelayedInstallInfo(extension, initial_state, + extension_prefs_->SetDelayedInstallInfo( + extension, + initial_state, + blacklist_state, extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS, page_ordinal); delayed_installs_.Insert(extension); } } else { - AddNewOrUpdatedExtension(extension, initial_state, page_ordinal); + AddNewOrUpdatedExtension(extension, + initial_state, + blacklist_state, + page_ordinal); } } void ExtensionService::AddNewOrUpdatedExtension( const Extension* extension, Extension::State initial_state, + extensions::Blacklist::BlacklistState blacklist_state, const syncer::StringOrdinal& page_ordinal) { CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - extension_prefs_->OnExtensionInstalled( - extension, - initial_state, - page_ordinal); - + extension_prefs_->OnExtensionInstalled(extension, + initial_state, + blacklist_state, + page_ordinal); delayed_installs_.Remove(extension->id()); - FinishInstallation(extension); } @@ -3056,7 +3083,8 @@ void ExtensionService::ManageBlacklist( it != no_longer_blacklisted.end(); ++it) { scoped_refptr<const Extension> extension = blacklisted_extensions_.GetByID(*it); - DCHECK(extension.get()); + DCHECK(extension.get()) << "Extension " << *it << " no longer blacklisted, " + << "but it was never blacklisted."; if (!extension.get()) continue; blacklisted_extensions_.Remove(*it); @@ -3069,7 +3097,8 @@ void ExtensionService::ManageBlacklist( for (std::set<std::string>::iterator it = not_yet_blacklisted.begin(); it != not_yet_blacklisted.end(); ++it) { scoped_refptr<const Extension> extension = GetInstalledExtension(*it); - DCHECK(extension.get()); + DCHECK(extension.get()) << "Extension " << *it << " needs to be " + << "blacklisted, but it's not installed."; if (!extension.get()) continue; blacklisted_extensions_.Insert(extension); diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h index a6ac7ee..1564587 100644 --- a/chrome/browser/extensions/extension_service.h +++ b/chrome/browser/extensions/extension_service.h @@ -432,12 +432,16 @@ class ExtensionService // Informs the service that an extension's files are in place for loading. // - // Please make sure the Blacklist is checked some time before calling this - // method. + // |page_ordinal| is the location of the extension in the app launcher. + // |has_requirement_errors| is true if requirements of the extension weren't + // met (for example graphics capabilities). + // |blacklist_state| will be BLACKLISTED if the extension is blacklisted. + // |wait_for_idle| may be false to install the extension immediately. void OnExtensionInstalled( const extensions::Extension* extension, const syncer::StringOrdinal& page_ordinal, bool has_requirement_errors, + extensions::Blacklist::BlacklistState blacklist_state, bool wait_for_idle); // Checks for delayed installation for all pending installs. @@ -737,9 +741,11 @@ class ExtensionService // the extension is installed, e.g., to update event handlers on background // pages; and perform other extension install tasks before calling // AddExtension. - void AddNewOrUpdatedExtension(const extensions::Extension* extension, - extensions::Extension::State initial_state, - const syncer::StringOrdinal& page_ordinal); + void AddNewOrUpdatedExtension( + const extensions::Extension* extension, + extensions::Extension::State initial_state, + extensions::Blacklist::BlacklistState blacklist_state, + const syncer::StringOrdinal& page_ordinal); // Handles sending notification that |extension| was loaded. void NotifyExtensionLoaded(const extensions::Extension* extension); diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc index 86dd4f1..bf6c949 100644 --- a/chrome/browser/extensions/extension_service_unittest.cc +++ b/chrome/browser/extensions/extension_service_unittest.cc @@ -37,6 +37,7 @@ #include "chrome/browser/extensions/extension_creator.h" #include "chrome/browser/extensions/extension_error_reporter.h" #include "chrome/browser/extensions/extension_error_ui.h" +#include "chrome/browser/extensions/extension_notification_observer.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_sorting.h" #include "chrome/browser/extensions/extension_special_storage_policy.h" @@ -69,12 +70,14 @@ #include "chrome/common/extensions/api/plugins/plugins_handler.h" #include "chrome/common/extensions/background_info.h" #include "chrome/common/extensions/extension.h" +#include "chrome/common/extensions/extension_builder.h" #include "chrome/common/extensions/extension_l10n_util.h" #include "chrome/common/extensions/extension_manifest_constants.h" #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" #include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h" #include "chrome/common/extensions/manifest_url_handler.h" #include "chrome/common/extensions/permissions/permission_set.h" +#include "chrome/common/extensions/value_builder.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" #include "chrome/test/base/testing_profile.h" @@ -3331,20 +3334,22 @@ TEST_F(ExtensionServiceTest, UnloadBlacklistedExtension) { // Unload installed extension from blacklist. TEST_F(ExtensionServiceTest, BlacklistedExtensionWillNotInstall) { InitializeEmptyExtensionService(); - std::vector<std::string> blacklist; - blacklist.push_back(good_crx); - ExtensionSystem::Get(profile_.get())->blacklist()->SetFromUpdater(blacklist, - "v1"); - // Make sure pref is updated - loop_.RunUntilIdle(); + // Fake the blacklisting of good_crx by pretending that we get an update + // which includes it. + extensions::Blacklist* blacklist = + ExtensionSystem::Get(profile_.get())->blacklist(); + blacklist->SetFromUpdater(std::vector<std::string>(1, good_crx), "v1"); - // Now, the good_crx is blacklisted. + // Now good_crx is blacklisted. ValidateBooleanPref(good_crx, "blacklist", true); - // We can not install good_crx. + // We cannot install good_crx. base::FilePath path = data_dir_.AppendASCII("good.crx"); - InstallCRX(path, INSTALL_FAILED); + // HACK: specify WAS_INSTALLED_BY_DEFAULT so that test machinery doesn't + // decide to install this silently. Somebody should fix these tests, all + // 6,000 lines of them. Hah! + InstallCRX(path, INSTALL_FAILED, Extension::WAS_INSTALLED_BY_DEFAULT); EXPECT_EQ(0u, service_->extensions()->size()); ValidateBooleanPref(good_crx, "blacklist", true); } @@ -6347,3 +6352,42 @@ TEST_F(ExtensionServiceTest, ExternalInstallUpdatesFromWebstoreNewProfile) { EXPECT_FALSE(extensions::HasExternalInstallBubble(service_)); EXPECT_FALSE(service_->IsExtensionEnabled(updates_from_webstore)); } + +TEST_F(ExtensionServiceTest, InstallBlacklistedExtension) { + InitializeEmptyExtensionService(); + + scoped_refptr<Extension> extension = extensions::ExtensionBuilder() + .SetManifest(extensions::DictionaryBuilder() + .Set("name", "extension") + .Set("version", "1.0") + .Set("manifest_version", 2).Build()) + .Build(); + ASSERT_TRUE(extension.get()); + const std::string& id = extension->id(); + + std::set<std::string> id_set; + id_set.insert(id); + extensions::ExtensionNotificationObserver notifications( + content::NotificationService::AllSources(), id_set); + + // Installation should be allowed but the extension should never have been + // loaded and it should be blacklisted in prefs. + service_->OnExtensionInstalled( + extension.get(), + syncer::StringOrdinal(), + false /* has requirement errors */, + extensions::Blacklist::BLACKLISTED, + false /* wait for idle */); + loop_.RunUntilIdle(); + + // Extension was installed but not loaded. + EXPECT_TRUE(notifications.CheckNotifications( + chrome::NOTIFICATION_EXTENSION_INSTALLED)); + + EXPECT_TRUE(service_->GetInstalledExtension(id)); + EXPECT_FALSE(service_->extensions()->Contains(id)); + EXPECT_TRUE(service_->blacklisted_extensions()->Contains(id)); + EXPECT_TRUE(service_->extension_prefs()->IsExtensionBlacklisted(id)); + EXPECT_TRUE( + service_->extension_prefs()->IsBlacklistedExtensionAcknowledged(id)); +} diff --git a/chrome/browser/extensions/extension_sorting_unittest.cc b/chrome/browser/extensions/extension_sorting_unittest.cc index ff219b3..b84535e 100644 --- a/chrome/browser/extensions/extension_sorting_unittest.cc +++ b/chrome/browser/extensions/extension_sorting_unittest.cc @@ -11,6 +11,7 @@ #include "sync/api/string_ordinal.h" #include "testing/gtest/include/gtest/gtest.h" +using extensions::Blacklist; using extensions::Extension; using extensions::Manifest; @@ -28,7 +29,9 @@ class ExtensionSortingAppLocation : public ExtensionSortingTest { virtual void Initialize() OVERRIDE { extension_ = prefs_.AddExtension("not_an_app"); // Non-apps should not have any app launch ordinal or page ordinal. - prefs()->OnExtensionInstalled(extension_.get(), Extension::ENABLED, + prefs()->OnExtensionInstalled(extension_.get(), + Extension::ENABLED, + Blacklist::NOT_BLACKLISTED, syncer::StringOrdinal()); } @@ -54,7 +57,9 @@ class ExtensionSortingAppLaunchOrdinal : public ExtensionSortingTest { extension_ = prefs_.AddApp("on_extension_installed"); EXPECT_FALSE(prefs()->IsExtensionDisabled(extension_->id())); - prefs()->OnExtensionInstalled(extension_.get(), Extension::ENABLED, + prefs()->OnExtensionInstalled(extension_.get(), + Extension::ENABLED, + Blacklist::NOT_BLACKLISTED, syncer::StringOrdinal()); } @@ -104,7 +109,9 @@ class ExtensionSortingPageOrdinal : public ExtensionSortingTest { extension_ = prefs_.AddApp("page_ordinal"); // Install with a page preference. first_page_ = syncer::StringOrdinal::CreateInitialOrdinal(); - prefs()->OnExtensionInstalled(extension_.get(), Extension::ENABLED, + prefs()->OnExtensionInstalled(extension_.get(), + Extension::ENABLED, + Blacklist::NOT_BLACKLISTED, first_page_); EXPECT_TRUE(first_page_.Equals( extension_sorting()->GetPageOrdinal(extension_->id()))); @@ -112,7 +119,9 @@ class ExtensionSortingPageOrdinal : public ExtensionSortingTest { scoped_refptr<Extension> extension2 = prefs_.AddApp("page_ordinal_2"); // Install without any page preference. - prefs()->OnExtensionInstalled(extension2.get(), Extension::ENABLED, + prefs()->OnExtensionInstalled(extension2.get(), + Extension::ENABLED, + Blacklist::NOT_BLACKLISTED, syncer::StringOrdinal()); EXPECT_TRUE(first_page_.Equals( extension_sorting()->GetPageOrdinal(extension2->id()))); @@ -638,6 +647,7 @@ class ExtensionSortingPreinstalledAppsBase simple_dict, Extension::NO_FLAGS, &error); prefs()->OnExtensionInstalled(app1_scoped_.get(), Extension::ENABLED, + Blacklist::NOT_BLACKLISTED, syncer::StringOrdinal()); app2_scoped_ = Extension::Create( @@ -645,6 +655,7 @@ class ExtensionSortingPreinstalledAppsBase simple_dict, Extension::NO_FLAGS, &error); prefs()->OnExtensionInstalled(app2_scoped_.get(), Extension::ENABLED, + Blacklist::NOT_BLACKLISTED, syncer::StringOrdinal()); app1_ = app1_scoped_.get(); @@ -828,7 +839,9 @@ class ExtensionSortingDefaultOrdinalsBase : public ExtensionSortingTest { virtual void SetupUserOrdinals() {} virtual void InstallApps() { - prefs()->OnExtensionInstalled(app_.get(), Extension::ENABLED, + prefs()->OnExtensionInstalled(app_.get(), + Extension::ENABLED, + Blacklist::NOT_BLACKLISTED, syncer::StringOrdinal()); } @@ -874,7 +887,9 @@ class ExtensionSortingDefaultOrdinalOverriddenByInstallPage protected: virtual void InstallApps() OVERRIDE { install_page_ = default_page_ordinal_.CreateAfter(); - prefs()->OnExtensionInstalled(app_.get(), Extension::ENABLED, + prefs()->OnExtensionInstalled(app_.get(), + Extension::ENABLED, + Blacklist::NOT_BLACKLISTED, install_page_); } diff --git a/chrome/browser/extensions/test_extension_prefs.cc b/chrome/browser/extensions/test_extension_prefs.cc index e2d8a70..018ff42 100644 --- a/chrome/browser/extensions/test_extension_prefs.cc +++ b/chrome/browser/extensions/test_extension_prefs.cc @@ -161,6 +161,7 @@ scoped_refptr<Extension> TestExtensionPrefs::AddExtensionWithManifestAndFlags( EXPECT_TRUE(Extension::IdIsValid(extension->id())); prefs_->OnExtensionInstalled(extension.get(), Extension::ENABLED, + Blacklist::NOT_BLACKLISTED, syncer::StringOrdinal::CreateInitialOrdinal()); return extension; } diff --git a/chrome/browser/extensions/unpacked_installer.cc b/chrome/browser/extensions/unpacked_installer.cc index b394f00..adfd3e5 100644 --- a/chrome/browser/extensions/unpacked_installer.cc +++ b/chrome/browser/extensions/unpacked_installer.cc @@ -274,10 +274,12 @@ void UnpackedInstaller::ConfirmInstall() { PermissionsUpdater perms_updater(service_weak_->profile()); perms_updater.GrantActivePermissions(installer_.extension().get()); - service_weak_->OnExtensionInstalled(installer_.extension().get(), - syncer::StringOrdinal(), - false /* no requirement errors */, - false /* don't wait for idle */); + service_weak_->OnExtensionInstalled( + installer_.extension().get(), + syncer::StringOrdinal(), + false /* no requirement errors */, + Blacklist::NOT_BLACKLISTED, + false /* don't wait for idle */); } } // namespace extensions |