diff options
author | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-04 11:11:34 +0000 |
---|---|---|
committer | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-04 11:11:34 +0000 |
commit | 24e7a9d2b4d7925ca25d2cdf75808d3ff88b5f6e (patch) | |
tree | 809ce617d8e41b1ba284eba33694af966654fb87 | |
parent | a6cf2a3e9f1d7b44dda39975139f5ae39524e363 (diff) | |
download | chromium_src-24e7a9d2b4d7925ca25d2cdf75808d3ff88b5f6e.zip chromium_src-24e7a9d2b4d7925ca25d2cdf75808d3ff88b5f6e.tar.gz chromium_src-24e7a9d2b4d7925ca25d2cdf75808d3ff88b5f6e.tar.bz2 |
Implement loading blacklists from extensions.
It doesn't yet work in full-browser scenario, but allows me
to write a simple test.
TEST=Covered by browser_tests.
BUG=21541
Review URL: http://codereview.chromium.org/341050
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@30952 0039d316-1c4b-4281-b951-d872f2087c98
17 files changed, 294 insertions, 90 deletions
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc index 48e46d7..6dd5f0e 100644 --- a/chrome/browser/browser.cc +++ b/chrome/browser/browser.cc @@ -2221,7 +2221,10 @@ void Browser::Observe(NotificationType type, case NotificationType::EXTENSION_UPDATE_DISABLED: { // Show the UI. - ExtensionsService* service = Source<ExtensionsService>(source).ptr(); + Profile* profile = Source<Profile>(source).ptr(); + DCHECK_EQ(profile_, profile); + ExtensionsService* service = profile->GetExtensionsService(); + DCHECK(service); Extension* extension = Details<Extension>(details).ptr(); ShowExtensionDisabledUI(service, profile_, extension); break; diff --git a/chrome/browser/extensions/extension_disabled_infobar_delegate.cc b/chrome/browser/extensions/extension_disabled_infobar_delegate.cc index ea8de22..0d0d7b4 100644 --- a/chrome/browser/extensions/extension_disabled_infobar_delegate.cc +++ b/chrome/browser/extensions/extension_disabled_infobar_delegate.cc @@ -88,9 +88,9 @@ class ExtensionDisabledInfobarDelegate extension_(extension) { // The user might re-enable the extension in other ways, so watch for that. registrar_.Add(this, NotificationType::EXTENSION_LOADED, - Source<ExtensionsService>(service)); + Source<Profile>(service->profile())); registrar_.Add(this, NotificationType::EXTENSION_UNLOADED_DISABLED, - Source<ExtensionsService>(service)); + Source<Profile>(service->profile())); } virtual ~ExtensionDisabledInfobarDelegate() { } diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc index a468700..f9d6bd1 100644 --- a/chrome/browser/extensions/extension_host.cc +++ b/chrome/browser/extensions/extension_host.cc @@ -248,7 +248,7 @@ void ExtensionHost::RenderViewGone(RenderViewHost* render_view_host) { DCHECK_EQ(render_view_host_, render_view_host); NotificationService::current()->Notify( NotificationType::EXTENSION_PROCESS_CRASHED, - Source<ExtensionsService>(profile_->GetExtensionsService()), + Source<Profile>(profile_), Details<ExtensionHost>(this)); } diff --git a/chrome/browser/extensions/extension_process_manager.cc b/chrome/browser/extensions/extension_process_manager.cc index e9bb7c49..6718691 100644 --- a/chrome/browser/extensions/extension_process_manager.cc +++ b/chrome/browser/extensions/extension_process_manager.cc @@ -175,11 +175,12 @@ void ExtensionProcessManager::Observe(NotificationType type, switch (type.value) { case NotificationType::EXTENSIONS_READY: CreateBackgroundHosts(this, - Source<ExtensionsService>(source).ptr()->extensions()); + Source<Profile>(source).ptr()->GetExtensionsService()->extensions()); break; case NotificationType::EXTENSION_LOADED: { - ExtensionsService* service = Source<ExtensionsService>(source).ptr(); + ExtensionsService* service = + Source<Profile>(source).ptr()->GetExtensionsService(); if (service->is_ready()) { Extension* extension = Details<Extension>(details).ptr(); ::CreateBackgroundHost(this, extension); diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc index 1692e3f..dcca59e 100644 --- a/chrome/browser/extensions/extensions_service.cc +++ b/chrome/browser/extensions/extensions_service.cc @@ -333,7 +333,7 @@ void ExtensionsService::NotifyExtensionLoaded(Extension* extension) { NotificationService::current()->Notify( NotificationType::EXTENSION_LOADED, - Source<ExtensionsService>(this), + Source<Profile>(profile_), Details<Extension>(extension)); } @@ -342,7 +342,7 @@ void ExtensionsService::NotifyExtensionUnloaded(Extension* extension) { NotificationService::current()->Notify( NotificationType::EXTENSION_UNLOADED, - Source<ExtensionsService>(this), + Source<Profile>(profile_), Details<Extension>(extension)); if (profile_ && !profile_->IsOffTheRecord()) { @@ -417,7 +417,7 @@ void ExtensionsService::UnloadExtension(const std::string& extension_id) { disabled_extensions_.erase(iter); NotificationService::current()->Notify( NotificationType::EXTENSION_UNLOADED_DISABLED, - Source<ExtensionsService>(this), + Source<Profile>(profile_), Details<Extension>(extension.get())); return; } @@ -463,7 +463,7 @@ void ExtensionsService::OnLoadedInstalledExtensions() { } NotificationService::current()->Notify( NotificationType::EXTENSIONS_READY, - Source<ExtensionsService>(this), + Source<Profile>(profile_), NotificationService::NoDetails()); } @@ -494,7 +494,7 @@ void ExtensionsService::OnExtensionLoaded(Extension* extension, extension_prefs_->SetExtensionState(extension, Extension::DISABLED); NotificationService::current()->Notify( NotificationType::EXTENSION_UPDATE_DISABLED, - Source<ExtensionsService>(this), + Source<Profile>(profile_), Details<Extension>(extension)); } } else { @@ -528,7 +528,7 @@ void ExtensionsService::OnExtensionLoaded(Extension* extension, if (extension->IsTheme() && extension->location() == Extension::LOAD) { NotificationService::current()->Notify( NotificationType::THEME_INSTALLED, - Source<ExtensionsService>(this), + Source<Profile>(profile_), Details<Extension>(extension)); } else { ExtensionDOMUI::RegisterChromeURLOverrides(profile_, @@ -538,7 +538,7 @@ void ExtensionsService::OnExtensionLoaded(Extension* extension, case Extension::DISABLED: NotificationService::current()->Notify( NotificationType::EXTENSION_UPDATE_DISABLED, - Source<ExtensionsService>(this), + Source<Profile>(profile_), Details<Extension>(extension)); disabled_extensions_.push_back(scoped_extension.release()); break; @@ -558,12 +558,12 @@ void ExtensionsService::OnExtensionInstalled(Extension* extension, if (extension->IsTheme()) { NotificationService::current()->Notify( NotificationType::THEME_INSTALLED, - Source<ExtensionsService>(this), + Source<Profile>(profile_), Details<Extension>(extension)); } else { NotificationService::current()->Notify( NotificationType::EXTENSION_INSTALLED, - Source<ExtensionsService>(this), + Source<Profile>(profile_), Details<Extension>(extension)); } @@ -576,12 +576,12 @@ void ExtensionsService::OnExtensionOverinstallAttempted(const std::string& id) { if (extension && extension->IsTheme()) { NotificationService::current()->Notify( NotificationType::THEME_INSTALLED, - Source<ExtensionsService>(this), + Source<Profile>(profile_), Details<Extension>(extension)); } else { NotificationService::current()->Notify( NotificationType::NO_THEME_DETECTED, - Source<ExtensionsService>(this), + Source<Profile>(profile_), NotificationService::NoDetails()); } } @@ -666,7 +666,7 @@ void ExtensionsService::ReportExtensionLoadError( bool be_noisy) { NotificationService* service = NotificationService::current(); service->Notify(type, - Source<ExtensionsService>(this), + Source<Profile>(profile_), Details<const std::string>(&error)); // TODO(port): note that this isn't guaranteed to work properly on Linux. @@ -676,6 +676,42 @@ void ExtensionsService::ReportExtensionLoadError( ExtensionErrorReporter::GetInstance()->ReportError(message, be_noisy); } +std::vector<FilePath> ExtensionsService::GetPersistentBlacklistPaths() { + std::vector<FilePath> result; + for (ExtensionList::const_iterator extension_iter = extensions()->begin(); + extension_iter != extensions()->end(); ++extension_iter) { + if ((*extension_iter)->location() == Extension::LOAD) + continue; + + std::vector<Extension::PrivacyBlacklistInfo> blacklists( + (*extension_iter)->privacy_blacklists()); + std::vector<Extension::PrivacyBlacklistInfo>::const_iterator blacklist_iter; + for (blacklist_iter = blacklists.begin(); + blacklist_iter != blacklists.end(); ++blacklist_iter) { + result.push_back(blacklist_iter->path); + } + } + return result; +} + +std::vector<FilePath> ExtensionsService::GetTransientBlacklistPaths() { + std::vector<FilePath> result; + for (ExtensionList::const_iterator extension_iter = extensions()->begin(); + extension_iter != extensions()->end(); ++extension_iter) { + if ((*extension_iter)->location() != Extension::LOAD) + continue; + + std::vector<Extension::PrivacyBlacklistInfo> blacklists( + (*extension_iter)->privacy_blacklists()); + std::vector<Extension::PrivacyBlacklistInfo>::const_iterator blacklist_iter; + for (blacklist_iter = blacklists.begin(); + blacklist_iter != blacklists.end(); ++blacklist_iter) { + result.push_back(blacklist_iter->path); + } + } + return result; +} + // ExtensionsServicesBackend ExtensionsServiceBackend::ExtensionsServiceBackend( diff --git a/chrome/browser/extensions/extensions_service.h b/chrome/browser/extensions/extensions_service.h index 6d525d7..55e336d 100644 --- a/chrome/browser/extensions/extensions_service.h +++ b/chrome/browser/extensions/extensions_service.h @@ -21,6 +21,7 @@ #include "chrome/browser/extensions/extension_process_manager.h" #include "chrome/browser/extensions/external_extension_provider.h" #include "chrome/browser/extensions/sandboxed_extension_unpacker.h" +#include "chrome/browser/privacy_blacklist/blacklist_manager.h" #include "chrome/common/extensions/extension.h" class Browser; @@ -51,6 +52,7 @@ class ExtensionUpdateService { // Manages installed and running Chromium extensions. class ExtensionsService : public ExtensionUpdateService, + public BlacklistPathProvider, public base::RefCountedThreadSafe<ExtensionsService> { public: @@ -201,6 +203,8 @@ class ExtensionsService return show_extensions_prompts_; } + Profile* profile() { return profile_; } + // Profile calls this when it is destroyed so that we know not to call it. void ProfileDestroyed() { profile_ = NULL; } @@ -219,6 +223,10 @@ class ExtensionsService NotificationType type, bool be_noisy); + // BlacklistPathProvider: + virtual std::vector<FilePath> GetPersistentBlacklistPaths(); + virtual std::vector<FilePath> GetTransientBlacklistPaths(); + private: // Look up an extension by ID, optionally including either or both of enabled // and disabled extensions. diff --git a/chrome/browser/extensions/user_script_listener.cc b/chrome/browser/extensions/user_script_listener.cc index 31f0971..76a4ff5 100644 --- a/chrome/browser/extensions/user_script_listener.cc +++ b/chrome/browser/extensions/user_script_listener.cc @@ -6,6 +6,7 @@ #include "chrome/browser/chrome_thread.h" #include "chrome/browser/extensions/extensions_service.h" +#include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/notification_service.h" @@ -136,7 +137,8 @@ void UserScriptListener::Observe(NotificationType type, // Clear all our patterns and reregister all the still-loaded extensions. URLPatterns new_patterns; - ExtensionsService* service = Source<ExtensionsService>(source).ptr(); + ExtensionsService* service = + Source<Profile>(source).ptr()->GetExtensionsService(); for (ExtensionList::const_iterator it = service->extensions()->begin(); it != service->extensions()->end(); ++it) { if (*it != unloaded_extension) diff --git a/chrome/browser/extensions/user_script_listener_unittest.cc b/chrome/browser/extensions/user_script_listener_unittest.cc index 14a9d0e..2f87798 100644 --- a/chrome/browser/extensions/user_script_listener_unittest.cc +++ b/chrome/browser/extensions/user_script_listener_unittest.cc @@ -180,6 +180,38 @@ class ResourceDispatcherHostTester std::vector<int> completed_requests_; }; +class ExtensionTestingProfile : public TestingProfile { + public: + ExtensionTestingProfile() { + } + + FilePath GetExtensionsInstallDir() { + return GetPath().AppendASCII(ExtensionsService::kInstallDirectoryName); + } + + void InitializeExtensionsService() { + DCHECK(!GetExtensionsService()); + service_ = new ExtensionsService(this, + CommandLine::ForCurrentProcess(), + GetPrefs(), + GetExtensionsInstallDir(), + false); + service_->set_extensions_enabled(true); + service_->set_show_extensions_prompts(false); + service_->ClearProvidersForTesting(); + service_->Init(); + } + + virtual ExtensionsService* GetExtensionsService() { + return service_.get(); + } + + private: + scoped_refptr<ExtensionsService> service_; + + DISALLOW_COPY_AND_ASSIGN(ExtensionTestingProfile); +}; + class UserScriptListenerTest : public testing::Test { public: virtual void SetUp() { @@ -196,17 +228,9 @@ class UserScriptListenerTest : public testing::Test { resource_tester_ = new ResourceDispatcherHostTester(); - master_ = new MockUserScriptMaster(install_dir); + master_ = new MockUserScriptMaster(profile_.GetExtensionsInstallDir()); - service_ = new ExtensionsService(&profile_, - CommandLine::ForCurrentProcess(), - profile_.GetPrefs(), - install_dir, - false); - service_->set_extensions_enabled(true); - service_->set_show_extensions_prompts(false); - service_->ClearProvidersForTesting(); - service_->Init(); + profile_.InitializeExtensionsService(); } virtual void TearDown() { @@ -217,14 +241,13 @@ class UserScriptListenerTest : public testing::Test { } protected: - TestingProfile profile_; + ExtensionTestingProfile profile_; MessageLoopForUI loop_; scoped_ptr<ChromeThread> ui_thread_; scoped_ptr<ChromeThread> file_thread_; scoped_ptr<MockIOThread> io_thread_; scoped_refptr<ResourceDispatcherHostTester> resource_tester_; scoped_refptr<MockUserScriptMaster> master_; - scoped_refptr<ExtensionsService> service_; }; // Loads a single extension and ensures that requests to URLs with content @@ -238,9 +261,9 @@ TEST_F(UserScriptListenerTest, SingleExtension) { .AppendASCII("Extensions") .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj") .AppendASCII("1.0.0.0"); - service_->LoadExtension(ext1); + profile_.GetExtensionsService()->LoadExtension(ext1); loop_.RunAllPending(); - ASSERT_EQ(1u, service_->extensions()->size()); + ASSERT_EQ(1u, profile_.GetExtensionsService()->extensions()->size()); // Our extension has a content script on google.com. That request should be // delayed. @@ -271,18 +294,18 @@ TEST_F(UserScriptListenerTest, UnloadExtension) { .AppendASCII("Extensions") .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj") .AppendASCII("1.0.0.0"); - service_->LoadExtension(ext1); + profile_.GetExtensionsService()->LoadExtension(ext1); loop_.RunAllPending(); - ASSERT_EQ(1u, service_->extensions()->size()); + ASSERT_EQ(1u, profile_.GetExtensionsService()->extensions()->size()); FilePath ext2 = extensions_path .AppendASCII("good") .AppendASCII("Extensions") .AppendASCII("bjafgdebaacbbbecmhlhpofkepfkgcpa") .AppendASCII("1.0"); - service_->LoadExtension(ext2); + profile_.GetExtensionsService()->LoadExtension(ext2); loop_.RunAllPending(); - ASSERT_EQ(2u, service_->extensions()->size()); + ASSERT_EQ(2u, profile_.GetExtensionsService()->extensions()->size()); // Our extension has a content script on google.com. That request should be // delayed. @@ -294,7 +317,8 @@ TEST_F(UserScriptListenerTest, UnloadExtension) { EXPECT_TRUE(resource_tester_->IsRequestComplete(1)); // Unload the first extension and run a scan. Request should complete. - service_->UnloadExtension("behllobkkfkfnphdnhnkndlbkcpglgmj"); + profile_.GetExtensionsService()->UnloadExtension( + "behllobkkfkfnphdnhnkndlbkcpglgmj"); resource_tester_->WaitForScan(master_.get()); EXPECT_TRUE(resource_tester_->IsRequestStarted(0)); diff --git a/chrome/browser/gtk/browser_actions_toolbar_gtk.cc b/chrome/browser/gtk/browser_actions_toolbar_gtk.cc index 86aec26..176b4ee 100644 --- a/chrome/browser/gtk/browser_actions_toolbar_gtk.cc +++ b/chrome/browser/gtk/browser_actions_toolbar_gtk.cc @@ -201,13 +201,12 @@ BrowserActionsToolbarGtk::BrowserActionsToolbarGtk(Browser* browser) : browser_(browser), profile_(browser->profile()), hbox_(gtk_hbox_new(FALSE, kBrowserActionButtonPadding)) { - ExtensionsService* extension_service = profile_->GetExtensionsService(); registrar_.Add(this, NotificationType::EXTENSION_LOADED, - Source<ExtensionsService>(extension_service)); + Source<Profile>(profile_)); registrar_.Add(this, NotificationType::EXTENSION_UNLOADED, - Source<ExtensionsService>(extension_service)); + Source<Profile>(profile_)); registrar_.Add(this, NotificationType::EXTENSION_UNLOADED_DISABLED, - Source<ExtensionsService>(extension_service)); + Source<Profile>(profile_)); CreateAllButtons(); } diff --git a/chrome/browser/privacy_blacklist/blacklist_manager.cc b/chrome/browser/privacy_blacklist/blacklist_manager.cc index f7c9311..0629806 100644 --- a/chrome/browser/privacy_blacklist/blacklist_manager.cc +++ b/chrome/browser/privacy_blacklist/blacklist_manager.cc @@ -35,7 +35,7 @@ class BlacklistManagerTask : public Task { protected: BlacklistManager* blacklist_manager() const { return manager_; } - + MessageLoop* original_loop_; private: @@ -59,7 +59,7 @@ class BlacklistManager::CompileBlacklistTask : public BlacklistManagerTask { virtual void Run() { bool success = true; - + Blacklist blacklist; std::string error_string; @@ -107,7 +107,7 @@ class BlacklistManager::ReadBlacklistTask : public BlacklistManagerTask { ReportReadResult(NULL); return; } - + std::string error_string; std::vector<FilePath>::const_iterator i; for (i = transient_blacklists_.begin(); @@ -117,7 +117,7 @@ class BlacklistManager::ReadBlacklistTask : public BlacklistManagerTask { return; } } - + ReportReadResult(blacklist.release()); } @@ -128,7 +128,7 @@ class BlacklistManager::ReadBlacklistTask : public BlacklistManagerTask { &BlacklistManager::OnBlacklistReadFinished, blacklist)); } - + FilePath compiled_blacklist_; std::vector<FilePath> transient_blacklists_; @@ -145,7 +145,10 @@ BlacklistManager::BlacklistManager(Profile* profile, path_provider_(path_provider), backend_thread_(backend_thread) { registrar_.Add(this, - NotificationType::BLACKLIST_PATH_PROVIDER_UPDATED, + NotificationType::EXTENSION_LOADED, + Source<Profile>(profile)); + registrar_.Add(this, + NotificationType::EXTENSION_UNLOADED, Source<Profile>(profile)); ReadBlacklist(); } @@ -153,8 +156,15 @@ BlacklistManager::BlacklistManager(Profile* profile, void BlacklistManager::Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details) { - DCHECK(type == NotificationType::BLACKLIST_PATH_PROVIDER_UPDATED); - CompileBlacklist(); + switch (type.value) { + case NotificationType::EXTENSION_LOADED: + case NotificationType::EXTENSION_UNLOADED: + CompileBlacklist(); + break; + default: + NOTREACHED(); + break; + } } void BlacklistManager::CompileBlacklist() { @@ -167,7 +177,7 @@ void BlacklistManager::CompileBlacklist() { void BlacklistManager::ReadBlacklist() { DCHECK(CalledOnValidThread()); - + RunTaskOnBackendThread(new ReadBlacklistTask( this, compiled_blacklist_path_, path_provider_->GetTransientBlacklistPaths())); @@ -175,7 +185,7 @@ void BlacklistManager::ReadBlacklist() { void BlacklistManager::OnBlacklistCompilationFinished(bool success) { DCHECK(CalledOnValidThread()); - + if (success) { ReadBlacklist(); } else { @@ -189,7 +199,7 @@ void BlacklistManager::OnBlacklistCompilationFinished(bool success) { void BlacklistManager::OnBlacklistReadFinished(Blacklist* blacklist) { DCHECK(CalledOnValidThread()); - + if (!blacklist) { if (!first_read_finished_) { // If we're loading for the first time, the compiled blacklist could @@ -207,7 +217,7 @@ void BlacklistManager::OnBlacklistReadFinished(Blacklist* blacklist) { } first_read_finished_ = true; compiled_blacklist_.reset(blacklist); - + NotificationService::current()->Notify( NotificationType::BLACKLIST_MANAGER_BLACKLIST_READ_FINISHED, Source<Profile>(profile_), diff --git a/chrome/browser/privacy_blacklist/blacklist_manager_browsertest.cc b/chrome/browser/privacy_blacklist/blacklist_manager_browsertest.cc new file mode 100644 index 0000000..bbc30c4 --- /dev/null +++ b/chrome/browser/privacy_blacklist/blacklist_manager_browsertest.cc @@ -0,0 +1,92 @@ +// Copyright (c) 2009 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/privacy_blacklist/blacklist_manager.h" + +#include "chrome/browser/browser.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/extensions/extension_browsertest.h" +#include "chrome/browser/profile.h" +#include "chrome/common/notification_registrar.h" +#include "chrome/common/notification_source.h" +#include "chrome/test/in_process_browser_test.h" +#include "chrome/test/ui_test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +// Returns true if |blacklist| contains a match for |url|. +bool BlacklistHasMatch(const Blacklist* blacklist, const char* url) { + Blacklist::Match* match = blacklist->findMatch(GURL(url)); + + if (!match) + return false; + + delete match; + return true; +} + +} // namespace + +class BlacklistManagerBrowserTest : public ExtensionBrowserTest { + public: + void InitializeBlacklistManager() { + Profile* profile = browser()->profile(); + blacklist_manager_ = new BlacklistManager( + profile, profile->GetExtensionsService(), + g_browser_process->io_thread()); + WaitForBlacklistUpdate(); + } + + virtual void CleanUpOnMainThread() { + blacklist_manager_ = NULL; + ExtensionBrowserTest::CleanUpOnMainThread(); + } + + // NotificationObserver + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + if (type != NotificationType::BLACKLIST_MANAGER_ERROR && + type != NotificationType::BLACKLIST_MANAGER_BLACKLIST_READ_FINISHED) { + ExtensionBrowserTest::Observe(type, source, details); + return; + } + MessageLoop::current()->Quit(); + } + + protected: + void WaitForBlacklistUpdate() { + NotificationRegistrar registrar; + registrar.Add(this, + NotificationType::BLACKLIST_MANAGER_BLACKLIST_READ_FINISHED, + Source<Profile>(browser()->profile())); + ui_test_utils::RunMessageLoop(); + } + + scoped_refptr<BlacklistManager> blacklist_manager_; +}; + +IN_PROC_BROWSER_TEST_F(BlacklistManagerBrowserTest, Basic) { + InitializeBlacklistManager(); + ASSERT_TRUE(blacklist_manager_->GetCompiledBlacklist()); + EXPECT_FALSE(BlacklistHasMatch(blacklist_manager_->GetCompiledBlacklist(), + "http://host/annoying_ads/ad.jpg")); + + // Test loading an extension with blacklist. + ASSERT_TRUE(LoadExtension( + test_data_dir_.AppendASCII("common").AppendASCII("privacy_blacklist"))); + WaitForBlacklistUpdate(); + EXPECT_TRUE(BlacklistHasMatch(blacklist_manager_->GetCompiledBlacklist(), + "http://host/annoying_ads/ad.jpg")); + + // Make sure that after unloading the extension we update the blacklist. + ExtensionsService* extensions_service = + browser()->profile()->GetExtensionsService(); + ASSERT_EQ(1U, extensions_service->extensions()->size()); + UnloadExtension(extensions_service->extensions()->front()->id()); + WaitForBlacklistUpdate(); + EXPECT_FALSE(BlacklistHasMatch(blacklist_manager_->GetCompiledBlacklist(), + "http://host/annoying_ads/ad.jpg")); +} diff --git a/chrome/browser/privacy_blacklist/blacklist_manager_unittest.cc b/chrome/browser/privacy_blacklist/blacklist_manager_unittest.cc index b2e6996..e7d9f9d 100644 --- a/chrome/browser/privacy_blacklist/blacklist_manager_unittest.cc +++ b/chrome/browser/privacy_blacklist/blacklist_manager_unittest.cc @@ -10,6 +10,7 @@ #include "base/thread.h" #include "chrome/browser/privacy_blacklist/blacklist.h" #include "chrome/common/chrome_paths.h" +#include "chrome/common/extensions/extension.h" #include "chrome/common/notification_service.h" #include "chrome/test/testing_profile.h" #include "testing/gtest/include/gtest/gtest.h" @@ -37,7 +38,7 @@ class TestBlacklistPathProvider : public BlacklistPathProvider { virtual std::vector<FilePath> GetPersistentBlacklistPaths() { return persistent_paths_; } - + virtual std::vector<FilePath> GetTransientBlacklistPaths() { return transient_paths_; } @@ -46,12 +47,12 @@ class TestBlacklistPathProvider : public BlacklistPathProvider { persistent_paths_.push_back(path); SendUpdateNotification(); } - + void AddTransientPath(const FilePath& path) { transient_paths_.push_back(path); SendUpdateNotification(); } - + void clear() { persistent_paths_.clear(); transient_paths_.clear(); @@ -60,12 +61,18 @@ class TestBlacklistPathProvider : public BlacklistPathProvider { private: void SendUpdateNotification() { +#if defined(OS_WIN) + FilePath path(FILE_PATH_LITERAL("c:\\foo")); +#elif defined(OS_POSIX) + FilePath path(FILE_PATH_LITERAL("/foo")); +#endif + Extension extension(path); NotificationService::current()->Notify( - NotificationType::BLACKLIST_PATH_PROVIDER_UPDATED, + NotificationType::EXTENSION_LOADED, Source<Profile>(profile_), - Details<BlacklistPathProvider>(this)); + Details<Extension>(&extension)); } - + Profile* profile_; std::vector<FilePath> persistent_paths_; @@ -78,7 +85,7 @@ class BlacklistManagerTest : public testing::Test, public NotificationObserver { public: BlacklistManagerTest() : path_provider_(&profile_) { } - + virtual void SetUp() { ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_)); test_data_dir_ = test_data_dir_.AppendASCII("blacklist_samples"); @@ -103,7 +110,7 @@ class BlacklistManagerTest : public testing::Test, public NotificationObserver { Source<Profile>(&profile_)); MessageLoop::current()->Run(); } - + void WaitForBlacklistUpdate() { NotificationRegistrar registrar; registrar.Add(this, @@ -111,11 +118,11 @@ class BlacklistManagerTest : public testing::Test, public NotificationObserver { Source<Profile>(&profile_)); MessageLoop::current()->Run(); } - + FilePath test_data_dir_; MyTestingProfile profile_; - + TestBlacklistPathProvider path_provider_; private: @@ -157,24 +164,24 @@ TEST_F(BlacklistManagerTest, BlacklistPathProvider) { path_provider_.AddPersistentPath( test_data_dir_.AppendASCII("annoying_ads.pbl")); WaitForBlacklistUpdate(); - + const Blacklist* blacklist2 = manager->GetCompiledBlacklist(); // Added a real blacklist, the manager should recompile. EXPECT_NE(blacklist1, blacklist2); EXPECT_TRUE(BlacklistHasMatch(blacklist2, "http://host/annoying_ads/ad.jpg")); EXPECT_FALSE(BlacklistHasMatch(blacklist2, "http://host/other_ads/ad.jpg")); - + path_provider_.AddTransientPath(test_data_dir_.AppendASCII("other_ads.pbl")); WaitForBlacklistUpdate(); - + const Blacklist* blacklist3 = manager->GetCompiledBlacklist(); - + // In theory blacklist2 and blacklist3 could be the same object, so we're // not checking for inequality. EXPECT_TRUE(BlacklistHasMatch(blacklist3, "http://host/annoying_ads/ad.jpg")); EXPECT_TRUE(BlacklistHasMatch(blacklist3, "http://host/other_ads/ad.jpg")); - + // Now make sure that transient blacklists don't survive after re-creating // the BlacklistManager. manager = NULL; @@ -183,9 +190,9 @@ TEST_F(BlacklistManagerTest, BlacklistPathProvider) { test_data_dir_.AppendASCII("annoying_ads.pbl")); manager = new BlacklistManager(&profile_, &path_provider_, NULL); WaitForBlacklistUpdate(); - + const Blacklist* blacklist4 = manager->GetCompiledBlacklist(); - + EXPECT_TRUE(BlacklistHasMatch(blacklist4, "http://host/annoying_ads/ad.jpg")); EXPECT_FALSE(BlacklistHasMatch(blacklist4, "http://host/other_ads/ad.jpg")); } @@ -222,7 +229,7 @@ TEST_F(BlacklistManagerTest, BlacklistPathReadError) { ASSERT_FALSE(file_util::PathExists(bogus_path)); path_provider_.AddPersistentPath(bogus_path); WaitForBlacklistError(); - + const Blacklist* blacklist = manager->GetCompiledBlacklist(); EXPECT_TRUE(blacklist); } diff --git a/chrome/browser/views/browser_actions_container.cc b/chrome/browser/views/browser_actions_container.cc index 179677c..f6036dd 100644 --- a/chrome/browser/views/browser_actions_container.cc +++ b/chrome/browser/views/browser_actions_container.cc @@ -229,11 +229,11 @@ BrowserActionsContainer::BrowserActionsContainer( return; registrar_.Add(this, NotificationType::EXTENSION_LOADED, - Source<ExtensionsService>(extension_service)); + Source<Profile>(profile_)); registrar_.Add(this, NotificationType::EXTENSION_UNLOADED, - Source<ExtensionsService>(extension_service)); + Source<Profile>(profile_)); registrar_.Add(this, NotificationType::EXTENSION_UNLOADED_DISABLED, - Source<ExtensionsService>(extension_service)); + Source<Profile>(profile_)); registrar_.Add(this, NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE, Source<Profile>(profile_)); diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 4ef2bff..c1fe430 100755 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -78,6 +78,7 @@ 'browser/gtk/bookmark_manager_browsertest.cc', 'browser/gtk/view_id_util_browsertest.cc', 'browser/net/ftp_browsertest.cc', + 'browser/privacy_blacklist/blacklist_manager_browsertest.cc', 'browser/ssl/ssl_browser_tests.cc', ], 'browser_tests_sources_win_specific': [ @@ -117,6 +118,7 @@ 'browser/extensions/extension_toolstrip_apitest.cc', 'browser/extensions/isolated_world_apitest.cc', 'browser/extensions/page_action_apitest.cc', + 'browser/privacy_blacklist/blacklist_manager_browsertest.cc', 'browser/ssl/ssl_browser_tests.cc', ], # TODO(jcampan): move these vars to views.gyp. diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h index 5da2c6e..1ea5923 100644 --- a/chrome/common/notification_type.h +++ b/chrome/common/notification_type.h @@ -632,26 +632,30 @@ class NotificationType { // Sent when the known installed extensions have all been loaded. In // testing scenarios this can happen multiple times if extensions are - // unloaded and reloaded. + // unloaded and reloaded. The source is a Profile. EXTENSIONS_READY, - // Sent when a new extension is loaded. The details are an Extension. + // Sent when a new extension is loaded. The details are an Extension, and + // the source is a Profile. EXTENSION_LOADED, // Sent when attempting to load a new extension, but they are disabled. The - // details are an Extension*. + // details are an Extension*, and the source is a Profile*. EXTENSION_UPDATE_DISABLED, // Sent when a theme is ready to be installed, so we can alert the user. EXTENSION_READY_FOR_INSTALL, - // Sent on ExtensionOverinstallAttempted when no theme is detected. + // Sent on ExtensionOverinstallAttempted when no theme is detected. The + // source is a Profile. NO_THEME_DETECTED, - // Sent when a new theme is installed. The details are an Extension. + // Sent when a new theme is installed. The details are an Extension, and the + // source is a Profile. THEME_INSTALLED, - // Sent when new extensions are installed. The details are an Extension. + // Sent when new extensions are installed. The details are an Extension, and + // the source is a Profile. EXTENSION_INSTALLED, // An error occured during extension install. The details are a string with @@ -664,9 +668,10 @@ class NotificationType { // Sent when an extension is unloaded. This happens when an extension is // uninstalled. When we add a disable feature, it will also happen then. - // The details are an Extension. Note that when this notification is sent, - // ExtensionsService has already removed the extension from its internal - // state. + // The details are an Extension, and the source is a Profile. + // + // Note that when this notification is sent, ExtensionsService has already + // removed the extension from its internal state. EXTENSION_UNLOADED, // Same as above, but for a disabled extension. @@ -694,7 +699,7 @@ class NotificationType { EXTENSION_PROCESS_CREATED, // Sent when extension render process crashes. The details are - // an ExtensionHost* and the source is an ExtensionsService*. + // an ExtensionHost* and the source is a Profile*. EXTENSION_PROCESS_CRASHED, // Sent when the contents or order of toolstrips in the shelf model change. @@ -727,11 +732,6 @@ class NotificationType { // Privacy Blacklist ------------------------------------------------------- - // Sent when a privacy blacklist path provider changes the list of its - // blacklist paths (like adds/removes items). The details are - // a BlacklistPathProvider, and the source is a Profile. - BLACKLIST_PATH_PROVIDER_UPDATED, - // Sent when the blacklist manager successfully finishes reading // a blacklist. The details are a Blacklist, and the source is a Profile. BLACKLIST_MANAGER_BLACKLIST_READ_FINISHED, diff --git a/chrome/test/data/extensions/common/privacy_blacklist/manifest.json b/chrome/test/data/extensions/common/privacy_blacklist/manifest.json new file mode 100644 index 0000000..8e3b221 --- /dev/null +++ b/chrome/test/data/extensions/common/privacy_blacklist/manifest.json @@ -0,0 +1,8 @@ +{ + "description": "Extension which has a privacy blacklist", + "name": "privacy_blacklist", + "privacy_blacklists": [ + "privacy_blacklist.pbl" + ], + "version": "0.1" +}
\ No newline at end of file diff --git a/chrome/test/data/extensions/common/privacy_blacklist/privacy_blacklist.pbl b/chrome/test/data/extensions/common/privacy_blacklist/privacy_blacklist.pbl new file mode 100644 index 0000000..b9dc8d2 --- /dev/null +++ b/chrome/test/data/extensions/common/privacy_blacklist/privacy_blacklist.pbl @@ -0,0 +1,12 @@ +[Chromium::PrivacyBlacklist] +|Name: AnnoyingAds +|URL: http://www.ads.tv + +# Block Ads by servers +annoying.ads.tv/@ => kBlockAll + +# Block Ads by name +@/annoying/120x600.jpg => kBlockAll + +# Block Ads by path +@/annoying_ads/@ => kBlockAll |