diff options
author | joaodasilva@chromium.org <joaodasilva@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-04 19:19:59 +0000 |
---|---|---|
committer | joaodasilva@chromium.org <joaodasilva@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-04 19:19:59 +0000 |
commit | 6a5f77c3df9771d76333e665df587f5a31e08f41 (patch) | |
tree | 939ccf8b37b01319781d5b2811b30ec7df9f9599 /chrome/browser | |
parent | e2f2ded6e71f88fd9d8fab165b29af458fb95713 (diff) | |
download | chromium_src-6a5f77c3df9771d76333e665df587f5a31e08f41.zip chromium_src-6a5f77c3df9771d76333e665df587f5a31e08f41.tar.gz chromium_src-6a5f77c3df9771d76333e665df587f5a31e08f41.tar.bz2 |
Introduced the URLBlacklistManager, and wired it to various places.
This is part of a work in progress (http://codereview.chromium.org/7716003).
This patch is meant to introduce the blacklist manager, which listens to prefs
changes on the UI thread (later to be managed by policies) and filters
URLRequests on the IO thread.
Subsequent patches will build the blacklist based on the preferences, and
block URLRequests that match the list. The policy will be introduced once
everything else is ready.
BUG=49612
TEST=URLBlacklistManagerTest; everything still works as before
Review URL: http://codereview.chromium.org/7747018
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@99608 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/extensions/extension_webrequest_api_unittest.cc | 4 | ||||
-rw-r--r-- | chrome/browser/io_thread.cc | 1 | ||||
-rw-r--r-- | chrome/browser/net/chrome_network_delegate.cc | 19 | ||||
-rw-r--r-- | chrome/browser/net/chrome_network_delegate.h | 8 | ||||
-rw-r--r-- | chrome/browser/policy/url_blacklist_manager.cc | 186 | ||||
-rw-r--r-- | chrome/browser/policy/url_blacklist_manager.h | 121 | ||||
-rw-r--r-- | chrome/browser/policy/url_blacklist_manager_unittest.cc | 193 | ||||
-rw-r--r-- | chrome/browser/prefs/browser_prefs.cc | 4 | ||||
-rw-r--r-- | chrome/browser/profiles/profile_impl.h | 3 | ||||
-rw-r--r-- | chrome/browser/profiles/profile_io_data.cc | 10 | ||||
-rw-r--r-- | chrome/browser/profiles/profile_io_data.h | 10 |
11 files changed, 554 insertions, 5 deletions
diff --git a/chrome/browser/extensions/extension_webrequest_api_unittest.cc b/chrome/browser/extensions/extension_webrequest_api_unittest.cc index 012d865..16dc5ce 100644 --- a/chrome/browser/extensions/extension_webrequest_api_unittest.cc +++ b/chrome/browser/extensions/extension_webrequest_api_unittest.cc @@ -84,7 +84,7 @@ class ExtensionWebRequestTest : public testing::Test { enable_referrers_.Init( prefs::kEnableReferrers, profile_.GetTestingPrefService(), NULL); network_delegate_.reset(new ChromeNetworkDelegate( - event_router_.get(), NULL, &profile_, &enable_referrers_)); + event_router_.get(), NULL, NULL, &profile_, &enable_referrers_)); context_ = new TestURLRequestContext(); context_->set_network_delegate(network_delegate_.get()); } @@ -329,7 +329,7 @@ class ExtensionWebRequestHeaderModificationTest : enable_referrers_.Init( prefs::kEnableReferrers, profile_.GetTestingPrefService(), NULL); network_delegate_.reset(new ChromeNetworkDelegate( - event_router_.get(), NULL, &profile_, &enable_referrers_)); + event_router_.get(), NULL, NULL, &profile_, &enable_referrers_)); context_ = new TestURLRequestContext(); context_->set_network_delegate(network_delegate_.get()); } diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index b8f3557..b018554 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc @@ -461,6 +461,7 @@ void IOThread::Init() { extension_event_router_forwarder_, NULL, NULL, + NULL, &system_enable_referrers_)); globals_->host_resolver.reset( CreateGlobalHostResolver(net_log_)); diff --git a/chrome/browser/net/chrome_network_delegate.cc b/chrome/browser/net/chrome_network_delegate.cc index 41cedf3..5532bd7 100644 --- a/chrome/browser/net/chrome_network_delegate.cc +++ b/chrome/browser/net/chrome_network_delegate.cc @@ -10,12 +10,14 @@ #include "chrome/browser/extensions/extension_info_map.h" #include "chrome/browser/extensions/extension_proxy_api.h" #include "chrome/browser/extensions/extension_webrequest_api.h" +#include "chrome/browser/policy/url_blacklist_manager.h" #include "chrome/browser/prefs/pref_member.h" #include "chrome/browser/task_manager/task_manager.h" #include "chrome/common/pref_names.h" #include "content/browser/browser_thread.h" #include "net/base/host_port_pair.h" #include "net/base/net_errors.h" +#include "net/base/net_log.h" #include "net/http/http_request_headers.h" #include "net/http/http_response_headers.h" #include "net/url_request/url_request.h" @@ -43,12 +45,14 @@ void ForwardProxyErrors(net::URLRequest* request, ChromeNetworkDelegate::ChromeNetworkDelegate( ExtensionEventRouterForwarder* event_router, ExtensionInfoMap* extension_info_map, + const policy::URLBlacklistManager* url_blacklist_manager, void* profile, BooleanPrefMember* enable_referrers) : event_router_(event_router), profile_(profile), extension_info_map_(extension_info_map), - enable_referrers_(enable_referrers) { + enable_referrers_(enable_referrers), + url_blacklist_manager_(url_blacklist_manager) { DCHECK(event_router); DCHECK(enable_referrers); } @@ -68,6 +72,19 @@ int ChromeNetworkDelegate::OnBeforeURLRequest( net::URLRequest* request, net::CompletionCallback* callback, GURL* new_url) { + // TODO(joaodasilva): This prevents extensions from seeing URLs that are + // blocked. However, an extension might redirect the request to another URL, + // which is not blocked. + if (url_blacklist_manager_ && + url_blacklist_manager_->IsURLBlocked(request->url())) { + // URL access blocked by policy. + scoped_refptr<net::NetLog::EventParameters> params; + params = new net::NetLogStringParameter("url", request->url().spec()); + request->net_log().AddEvent( + net::NetLog::TYPE_CHROME_POLICY_ABORTED_REQUEST, params); + return net::ERR_NETWORK_ACCESS_DENIED; + } + if (!enable_referrers_->GetValue()) request->set_referrer(std::string()); return ExtensionWebRequestEventRouter::GetInstance()->OnBeforeRequest( diff --git a/chrome/browser/net/chrome_network_delegate.h b/chrome/browser/net/chrome_network_delegate.h index 980a26b..f36df17 100644 --- a/chrome/browser/net/chrome_network_delegate.h +++ b/chrome/browser/net/chrome_network_delegate.h @@ -18,6 +18,10 @@ template<class T> class PrefMember; typedef PrefMember<bool> BooleanPrefMember; +namespace policy { +class URLBlacklistManager; +} + // ChromeNetworkDelegate is the central point from within the chrome code to // add hooks into the network stack. class ChromeNetworkDelegate : public net::NetworkDelegate { @@ -30,6 +34,7 @@ class ChromeNetworkDelegate : public net::NetworkDelegate { ChromeNetworkDelegate( ExtensionEventRouterForwarder* event_router, ExtensionInfoMap* extension_info_map, + const policy::URLBlacklistManager* url_blacklist_manager, void* profile, BooleanPrefMember* enable_referrers); virtual ~ChromeNetworkDelegate(); @@ -69,6 +74,9 @@ class ChromeNetworkDelegate : public net::NetworkDelegate { // Weak, owned by our owner. BooleanPrefMember* enable_referrers_; + // Weak, owned by our owner. + const policy::URLBlacklistManager* url_blacklist_manager_; + DISALLOW_COPY_AND_ASSIGN(ChromeNetworkDelegate); }; diff --git a/chrome/browser/policy/url_blacklist_manager.cc b/chrome/browser/policy/url_blacklist_manager.cc new file mode 100644 index 0000000..2003255 --- /dev/null +++ b/chrome/browser/policy/url_blacklist_manager.cc @@ -0,0 +1,186 @@ +// Copyright (c) 2011 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/policy/url_blacklist_manager.h" + +#include "base/bind.h" +#include "base/values.h" +#include "chrome/browser/prefs/pref_service.h" +#include "chrome/common/chrome_notification_types.h" +#include "chrome/common/pref_names.h" +#include "content/browser/browser_thread.h" +#include "content/common/notification_details.h" +#include "content/common/notification_source.h" +#include "googleurl/src/gurl.h" + +namespace policy { + +namespace { + +// Time to wait before starting an update of the blacklist. Scheduling another +// update during this period will reset the timer. +const int64 kUpdateDelayMs = 1000; + +// Maximum filters per policy. Filters over this index are ignored. +const size_t kMaxFiltersPerPolicy = 100; + +typedef std::vector<std::string> StringVector; + +StringVector* ListValueToStringVector(const base::ListValue* list) { + StringVector* vector = new StringVector; + + if (!list) + return vector; + + vector->reserve(list->GetSize()); + std::string s; + for (base::ListValue::const_iterator it = list->begin(); + it != list->end() && vector->size() < kMaxFiltersPerPolicy; ++it) { + if ((*it)->GetAsString(&s)) + vector->push_back(s); + } + + return vector; +} + +// A task that builds the blacklist on the FILE thread. Takes ownership +// of |block| and |allow| but not of |blacklist|. +void BuildBlacklist(URLBlacklist* blacklist, + StringVector* block, + StringVector* allow) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + + scoped_ptr<StringVector> scoped_block(block); + scoped_ptr<StringVector> scoped_allow(allow); + + // TODO(joaodasilva): This is a work in progress. http://crbug.com/49612 + // Builds |blacklist| using the filters in |block| and |allow|. +} + +// A task that owns the URLBlacklist, and passes it to the URLBlacklistManager +// on the IO thread, if the URLBlacklistManager still exists. +void SetBlacklistOnIO(base::WeakPtr<URLBlacklistManager> blacklist_manager, + URLBlacklist* blacklist) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + if (blacklist_manager) + blacklist_manager->SetBlacklist(blacklist); + else + delete blacklist; +} + +} // namespace + +URLBlacklist::URLBlacklist() { +} + +URLBlacklist::~URLBlacklist() { +} + +URLBlacklistManager::URLBlacklistManager(PrefService* pref_service) + : ALLOW_THIS_IN_INITIALIZER_LIST(ui_method_factory_(this)), + pref_service_(pref_service), + ALLOW_THIS_IN_INITIALIZER_LIST(io_weak_ptr_factory_(this)), + blacklist_(new URLBlacklist) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + pref_change_registrar_.Init(pref_service_); + pref_change_registrar_.Add(prefs::kUrlBlacklist, this); + pref_change_registrar_.Add(prefs::kUrlWhitelist, this); + + // Start enforcing the policies without a delay when they are present at + // startup. + if (pref_service_->HasPrefPath(prefs::kUrlBlacklist)) + Update(); +} + +void URLBlacklistManager::ShutdownOnUIThread() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + // Cancel any pending updates, and stop listening for pref change updates. + ui_method_factory_.RevokeAll(); + pref_change_registrar_.RemoveAll(); +} + +URLBlacklistManager::~URLBlacklistManager() { +} + +void URLBlacklistManager::Observe(int type, + const NotificationSource& source, + const NotificationDetails& details) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK(type == chrome::NOTIFICATION_PREF_CHANGED); + PrefService* prefs = Source<PrefService>(source).ptr(); + DCHECK(prefs == pref_service_); + std::string* pref_name = Details<std::string>(details).ptr(); + DCHECK(*pref_name == prefs::kUrlBlacklist || + *pref_name == prefs::kUrlWhitelist); + ScheduleUpdate(); +} + +void URLBlacklistManager::ScheduleUpdate() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + // Cancel pending updates, if any. + ui_method_factory_.RevokeAll(); + PostUpdateTask( + ui_method_factory_.NewRunnableMethod(&URLBlacklistManager::Update)); +} + +void URLBlacklistManager::PostUpdateTask(Task* task) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + // This is overridden in tests to post the task without the delay. + MessageLoop::current()->PostDelayedTask(FROM_HERE, task, kUpdateDelayMs); +} + +void URLBlacklistManager::Update() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + // The preferences can only be read on the UI thread. + StringVector* block = + ListValueToStringVector(pref_service_->GetList(prefs::kUrlBlacklist)); + StringVector* allow = + ListValueToStringVector(pref_service_->GetList(prefs::kUrlWhitelist)); + + // Go through the IO thread to grab a WeakPtr to |this|. This is safe from + // here, since this task will always execute before a potential deletion of + // ProfileIOData on IO. + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, + base::Bind(&URLBlacklistManager::UpdateOnIO, + base::Unretained(this), block, allow)); +} + +void URLBlacklistManager::UpdateOnIO(StringVector* block, StringVector* allow) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + URLBlacklist* blacklist = new URLBlacklist; + // The URLBlacklist is built on the FILE thread. Once it's ready, it is passed + // to the URLBlacklistManager on IO. + // |blacklist|, |block| and |allow| can leak on the unlikely event of a + // policy update and shutdown happening at the same time. + BrowserThread::PostTaskAndReply(BrowserThread::FILE, FROM_HERE, + base::Bind(&BuildBlacklist, + blacklist, block, allow), + base::Bind(&SetBlacklistOnIO, + io_weak_ptr_factory_.GetWeakPtr(), + blacklist)); +} + +void URLBlacklistManager::SetBlacklist(URLBlacklist* blacklist) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + blacklist_.reset(blacklist); +} + +bool URLBlacklistManager::IsURLBlocked(const GURL& url) const { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + // TODO(joaodasilva): this is a work in progress. http://crbug.com/49612 + return false; +} + +// static +void URLBlacklistManager::RegisterPrefs(PrefService* pref_service) { + pref_service->RegisterListPref(prefs::kUrlBlacklist, + PrefService::UNSYNCABLE_PREF); + pref_service->RegisterListPref(prefs::kUrlWhitelist, + PrefService::UNSYNCABLE_PREF); +} + +} // namespace policy diff --git a/chrome/browser/policy/url_blacklist_manager.h b/chrome/browser/policy/url_blacklist_manager.h new file mode 100644 index 0000000..e9b94a6 --- /dev/null +++ b/chrome/browser/policy/url_blacklist_manager.h @@ -0,0 +1,121 @@ +// Copyright (c) 2011 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_POLICY_URL_BLACKLIST_MANAGER_H_ +#define CHROME_BROWSER_POLICY_URL_BLACKLIST_MANAGER_H_ +#pragma once + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "base/task.h" +#include "chrome/browser/prefs/pref_change_registrar.h" +#include "content/common/notification_observer.h" + +class GURL; +class NotificationDetails; +class NotificationSource; +class PrefService; + +namespace base { +class ListValue; +} + +namespace policy { + +// TODO(joaodasilva): this is a work in progress. http://crbug.com/49612 +class URLBlacklist { + public: + URLBlacklist(); + virtual ~URLBlacklist(); + + private: + DISALLOW_COPY_AND_ASSIGN(URLBlacklist); +}; + +// Tracks the blacklist policies for a given profile, and updates it on changes. +// +// This class interacts with both the UI thread, where notifications of pref +// changes are received from, and the IO thread, which owns it (in the +// ProfileIOData) and checks for blacklisted URLs (from ChromeNetworkDelegate). +// +// It must be constructed on the UI thread, to set up |ui_method_factory_| and +// the prefs listeners. +// +// ShutdownOnUIThread must be called from UI before destruction, to release +// the prefs listeners on the UI thread. This is done from ProfileIOData. +// +// Update tasks from the UI thread can post safely to the IO thread, since the +// destruction order of Profile and ProfileIOData guarantees that if this +// exists in UI, then a potential destruction on IO will come after any task +// posted to IO from that method on UI. This is used to go through IO before +// the actual update starts, and grab a WeakPtr. +class URLBlacklistManager : public NotificationObserver { + public: + // Must be constructed on the UI thread. + explicit URLBlacklistManager(PrefService* pref_service); + virtual ~URLBlacklistManager(); + + // Must be called on the UI thread, before destruction. + void ShutdownOnUIThread(); + + // Returns true if |url| is blocked by the current blacklist. Must be called + // from the IO thread. + bool IsURLBlocked(const GURL& url) const; + + // Replaces the current blacklist. Must be called on the IO thread. + void SetBlacklist(URLBlacklist* blacklist); + + // Registers the preferences related to blacklisting in the given PrefService. + static void RegisterPrefs(PrefService* pref_service); + + protected: + typedef std::vector<std::string> StringVector; + + // These are used to delay updating the blacklist while the preferences are + // changing, and execute only one update per simultaneous prefs changes. + void ScheduleUpdate(); + virtual void PostUpdateTask(Task* task); // Virtual for testing. + virtual void Update(); // Virtual for testing. + + // Starts the blacklist update on the IO thread, using the filters in + // |block| and |allow|. Protected for testing. + void UpdateOnIO(StringVector* block, StringVector* allow); + + private: + virtual void Observe(int type, + const NotificationSource& source, + const NotificationDetails& details) OVERRIDE; + + // --------- + // UI thread + // --------- + + // Used to post update tasks to the UI thread. + ScopedRunnableMethodFactory<URLBlacklistManager> ui_method_factory_; + + // Used to track the policies and update the blacklist on changes. + PrefChangeRegistrar pref_change_registrar_; + PrefService* pref_service_; // Weak. + + // --------- + // IO thread + // --------- + + // Used to get |weak_ptr_| to self on the IO thread. + base::WeakPtrFactory<URLBlacklistManager> io_weak_ptr_factory_; + + // The current blacklist. + scoped_ptr<URLBlacklist> blacklist_; + + DISALLOW_COPY_AND_ASSIGN(URLBlacklistManager); +}; + +} // namespace policy + +#endif // CHROME_BROWSER_POLICY_URL_BLACKLIST_MANAGER_H_ diff --git a/chrome/browser/policy/url_blacklist_manager_unittest.cc b/chrome/browser/policy/url_blacklist_manager_unittest.cc new file mode 100644 index 0000000..3e42119 --- /dev/null +++ b/chrome/browser/policy/url_blacklist_manager_unittest.cc @@ -0,0 +1,193 @@ +// Copyright (c) 2011 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/policy/url_blacklist_manager.h" + +#include "base/basictypes.h" +#include "base/message_loop.h" +#include "chrome/common/pref_names.h" +#include "chrome/test/base/testing_pref_service.h" +#include "content/browser/browser_thread.h" +#include "content/common/notification_service.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace policy { + +namespace { + +using ::testing::_; +using ::testing::Invoke; +using ::testing::Mock; + +class TestingURLBlacklistManager : public URLBlacklistManager { + public: + explicit TestingURLBlacklistManager(PrefService* pref_service) + : URLBlacklistManager(pref_service) { + } + + virtual ~TestingURLBlacklistManager() { + } + + // Make this method public for testing. + using URLBlacklistManager::ScheduleUpdate; + + // Post tasks without a delay during tests. + virtual void PostUpdateTask(Task* task) OVERRIDE { + MessageLoop::current()->PostTask(FROM_HERE, task); + } + + // Makes a direct call to UpdateOnIO during tests. + void UpdateOnIO() { + StringVector* block = new StringVector; + block->push_back("example.com"); + StringVector* allow = new StringVector; + URLBlacklistManager::UpdateOnIO(block, allow); + } + + void UpdateNotMocked() { + URLBlacklistManager::Update(); + } + + MOCK_METHOD0(Update, void()); + MOCK_METHOD1(SetBlacklist, void(URLBlacklist*)); + + private: + DISALLOW_COPY_AND_ASSIGN(TestingURLBlacklistManager); +}; + +class URLBlacklistManagerTest : public testing::Test { + protected: + URLBlacklistManagerTest() + : ui_thread_(BrowserThread::UI, &loop_), + file_thread_(BrowserThread::FILE, &loop_), + io_thread_(BrowserThread::IO, &loop_) { + } + + virtual void SetUp() OVERRIDE { + pref_service_.RegisterListPref(prefs::kUrlBlacklist); + pref_service_.RegisterListPref(prefs::kUrlWhitelist); + blacklist_manager_.reset( + new TestingURLBlacklistManager(&pref_service_)); + loop_.RunAllPending(); + } + + virtual void TearDown() OVERRIDE { + if (blacklist_manager_.get()) + blacklist_manager_->ShutdownOnUIThread(); + loop_.RunAllPending(); + // Delete |blacklist_manager_| while |io_thread_| is mapping IO to + // |loop_|. + blacklist_manager_.reset(); + } + + void ExpectUpdate() { + EXPECT_CALL(*blacklist_manager_, Update()) + .WillOnce(Invoke(blacklist_manager_.get(), + &TestingURLBlacklistManager::UpdateNotMocked)); + } + + MessageLoop loop_; + TestingPrefService pref_service_; + scoped_ptr<TestingURLBlacklistManager> blacklist_manager_; + + private: + BrowserThread ui_thread_; + BrowserThread file_thread_; + BrowserThread io_thread_; + + DISALLOW_COPY_AND_ASSIGN(URLBlacklistManagerTest); +}; + +TEST_F(URLBlacklistManagerTest, SingleUpdateForTwoPrefChanges) { + ExpectUpdate(); + + ListValue* blacklist = new ListValue; + blacklist->Append(new StringValue("*.google.com")); + ListValue* whitelist = new ListValue; + whitelist->Append(new StringValue("mail.google.com")); + pref_service_.SetManagedPref(prefs::kUrlBlacklist, blacklist); + pref_service_.SetManagedPref(prefs::kUrlBlacklist, whitelist); + loop_.RunAllPending(); + + Mock::VerifyAndClearExpectations(blacklist_manager_.get()); +} + +TEST_F(URLBlacklistManagerTest, ShutdownWithPendingTask0) { + // Post an update task to the UI thread. + blacklist_manager_->ScheduleUpdate(); + // Shutdown comes before the task is executed. + blacklist_manager_->ShutdownOnUIThread(); + blacklist_manager_.reset(); + // Run the task after shutdown and deletion. + loop_.RunAllPending(); +} + +TEST_F(URLBlacklistManagerTest, ShutdownWithPendingTask1) { + EXPECT_CALL(*blacklist_manager_, Update()).Times(0); + // Post an update task. + blacklist_manager_->ScheduleUpdate(); + // Shutdown comes before the task is executed. + blacklist_manager_->ShutdownOnUIThread(); + // Run the task after shutdown, but before deletion. + loop_.RunAllPending(); + Mock::VerifyAndClearExpectations(blacklist_manager_.get()); + blacklist_manager_.reset(); + loop_.RunAllPending(); +} + +TEST_F(URLBlacklistManagerTest, ShutdownWithPendingTask2) { + // Update posts a BuildBlacklistTask to the FILE thread. + blacklist_manager_->UpdateNotMocked(); + // Shutdown comes before the task is executed. + blacklist_manager_->ShutdownOnUIThread(); + blacklist_manager_.reset(); + // Run the task after shutdown and deletion. + loop_.RunAllPending(); +} + +TEST_F(URLBlacklistManagerTest, ShutdownWithPendingTask3) { + EXPECT_CALL(*blacklist_manager_, SetBlacklist(_)).Times(0); + // Update posts a BuildBlacklistTask to the FILE thread. + blacklist_manager_->UpdateNotMocked(); + // Shutdown comes before the task is executed. + blacklist_manager_->ShutdownOnUIThread(); + // Run the task after shutdown, but before deletion. + loop_.RunAllPending(); + Mock::VerifyAndClearExpectations(blacklist_manager_.get()); + blacklist_manager_.reset(); + loop_.RunAllPending(); +} + +TEST_F(URLBlacklistManagerTest, ShutdownWithPendingTask4) { + EXPECT_CALL(*blacklist_manager_, SetBlacklist(_)).Times(0); + + // This posts a task to the FILE thread. + blacklist_manager_->UpdateOnIO(); + // But shutdown happens before it is done. + blacklist_manager_->ShutdownOnUIThread(); + blacklist_manager_.reset(); + loop_.RunAllPending(); + + Mock::VerifyAndClearExpectations(blacklist_manager_.get()); +} + +TEST_F(URLBlacklistManagerTest, ShutdownWithPendingTask5) { + EXPECT_CALL(*blacklist_manager_, SetBlacklist(_)).Times(0); + + // This posts a task to the FILE thread. + blacklist_manager_->UpdateOnIO(); + // But shutdown happens before it is done. + blacklist_manager_->ShutdownOnUIThread(); + // This time, shutdown on UI is done but the object is still alive. + loop_.RunAllPending(); + blacklist_manager_.reset(); + loop_.RunAllPending(); + + Mock::VerifyAndClearExpectations(blacklist_manager_.get()); +} + +} // namespace + +} // namespace policy diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index 635c276..d4d3daa 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc @@ -36,6 +36,7 @@ #include "chrome/browser/password_manager/password_manager.h" #include "chrome/browser/plugin_prefs.h" #include "chrome/browser/policy/cloud_policy_subsystem.h" +#include "chrome/browser/policy/url_blacklist_manager.h" #include "chrome/browser/prefs/incognito_mode_prefs.h" #include "chrome/browser/prefs/session_startup_pref.h" #include "chrome/browser/printing/print_job_manager.h" @@ -182,6 +183,9 @@ void RegisterUserPrefs(PrefService* user_prefs) { #if defined(OS_MACOSX) PresentationModePrefs::RegisterUserPrefs(user_prefs); #endif +#if defined(ENABLE_CONFIGURATION_POLICY) + policy::URLBlacklistManager::RegisterPrefs(user_prefs); +#endif } void MigrateBrowserPrefs(PrefService* user_prefs, PrefService* local_state) { diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h index b4276ca..cdc2985 100644 --- a/chrome/browser/profiles/profile_impl.h +++ b/chrome/browser/profiles/profile_impl.h @@ -22,6 +22,7 @@ class ChromeDownloadManagerDelegate; class ExtensionPrefs; class ExtensionPrefValueMap; class ExtensionSettings; +class NetPrefObserver; class PrefService; class SpellCheckProfile; @@ -33,8 +34,6 @@ class Preferences; } #endif -class NetPrefObserver; - // The default profile implementation. class ProfileImpl : public Profile, public NotificationObserver { diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc index e60dd6bd..d757ba2 100644 --- a/chrome/browser/profiles/profile_io_data.cc +++ b/chrome/browser/profiles/profile_io_data.cc @@ -28,6 +28,7 @@ #include "chrome/browser/net/pref_proxy_config_service.h" #include "chrome/browser/net/proxy_service_factory.h" #include "chrome/browser/notifications/desktop_notification_service_factory.h" +#include "chrome/browser/policy/url_blacklist_manager.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/prerender/prerender_manager.h" #include "chrome/browser/profiles/profile.h" @@ -243,6 +244,11 @@ void ProfileIOData::InitializeProfileParams(Profile* profile) { base::Bind(&GetPrerenderManagerOnUI, profile_getter); params->protocol_handler_registry = profile->GetProtocolHandlerRegistry(); +#if defined(ENABLE_CONFIGURATION_POLICY) + params->url_blacklist_manager.reset( + new policy::URLBlacklistManager(pref_service)); +#endif + params->proxy_config_service.reset( ProxyServiceFactory::CreateProxyConfigService( profile->GetProxyConfigTracker())); @@ -404,6 +410,7 @@ void ProfileIOData::LazyInitialize() const { network_delegate_.reset(new ChromeNetworkDelegate( io_thread_globals->extension_event_router_forwarder.get(), profile_params_->extension_info_map, + profile_params_->url_blacklist_manager.get(), profile_params_->profile, &enable_referrers_)); @@ -473,6 +480,7 @@ void ProfileIOData::LazyInitialize() const { notification_service_ = profile_params_->notification_service; extension_info_map_ = profile_params_->extension_info_map; prerender_manager_getter_ = profile_params_->prerender_manager_getter; + url_blacklist_manager_.swap(profile_params_->url_blacklist_manager); resource_context_.set_host_resolver(io_thread_globals->host_resolver.get()); resource_context_.set_request_context(main_request_context_); @@ -509,6 +517,8 @@ void ProfileIOData::ShutdownOnUIThread() { enable_referrers_.Destroy(); clear_local_state_on_exit_.Destroy(); safe_browsing_enabled_.Destroy(); + if (url_blacklist_manager_.get()) + url_blacklist_manager_->ShutdownOnUIThread(); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::Bind( diff --git a/chrome/browser/profiles/profile_io_data.h b/chrome/browser/profiles/profile_io_data.h index 14b1ef8..227abb0 100644 --- a/chrome/browser/profiles/profile_io_data.h +++ b/chrome/browser/profiles/profile_io_data.h @@ -46,6 +46,10 @@ class SSLConfigService; class TransportSecurityState; } // namespace net +namespace policy { +class URLBlacklistManager; +} // namespace policy + namespace prerender { class PrerenderManager; }; // namespace prerender @@ -152,6 +156,9 @@ class ProfileIOData { // because on linux it relies on initializing things through gconf, // and needs to be on the main thread. scoped_ptr<net::ProxyConfigService> proxy_config_service; + // Initialized on the UI thread because it needs to reference the + // Profile's PrefService. + scoped_ptr<policy::URLBlacklistManager> url_blacklist_manager; // The profile this struct was populated from. It's passed as a void* to // ensure it's not accidently used on the IO thread. Before using it on the // UI thread, call ProfileManager::IsValidProfile to ensure it's alive. @@ -258,6 +265,9 @@ class ProfileIOData { mutable BooleanPrefMember clear_local_state_on_exit_; mutable BooleanPrefMember safe_browsing_enabled_; + // Pointed to by NetworkDelegate. + mutable scoped_ptr<policy::URLBlacklistManager> url_blacklist_manager_; + // Pointed to by URLRequestContext. mutable scoped_ptr<ChromeURLDataManagerBackend> chrome_url_data_manager_backend_; |