summaryrefslogtreecommitdiffstats
path: root/chrome/browser/privacy_blacklist
diff options
context:
space:
mode:
authorphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-05 18:14:49 +0000
committerphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-05 18:14:49 +0000
commit363119947a1e9111c19c326a2844bc60a29fabba (patch)
treea008f948a2591ffec99b7b25040d6c74815b6a01 /chrome/browser/privacy_blacklist
parent4f67d8a72d73ca17ae35434e3301e708fddd2970 (diff)
downloadchromium_src-363119947a1e9111c19c326a2844bc60a29fabba.zip
chromium_src-363119947a1e9111c19c326a2844bc60a29fabba.tar.gz
chromium_src-363119947a1e9111c19c326a2844bc60a29fabba.tar.bz2
Implement delaying resource requests until privacy blacklists are ready.
Associate a BlacklistRequestInfo with each URLRequest started by ResourceDispatcherHost so that in various places we get access to the right BlacklistManager (each Profile has its own), and lazily cache a Blacklist::Match. BlacklistListener controls delaying requests until the privacy blacklist is ready for the request. BlacklistInterceptor handles substituting real response with a blocking page or blocking image. I've temporarily removed support for unblocking things. It was too hacky. This change also removes a large block of blacklist-related code from RDH to more focused classes. Should make it a little more readable. This should also make BlacklistManagerBrowserTest not flaky. TEST=Covered by browser_tests and unit_tests. BUG=21541, 29113 Review URL: http://codereview.chromium.org/501082 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35538 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/privacy_blacklist')
-rw-r--r--chrome/browser/privacy_blacklist/blacklist.cc3
-rw-r--r--chrome/browser/privacy_blacklist/blacklist.h3
-rw-r--r--chrome/browser/privacy_blacklist/blacklist_interceptor.cc141
-rw-r--r--chrome/browser/privacy_blacklist/blacklist_interceptor.h23
-rw-r--r--chrome/browser/privacy_blacklist/blacklist_interceptor_unittest.cc94
-rw-r--r--chrome/browser/privacy_blacklist/blacklist_listener.cc92
-rw-r--r--chrome/browser/privacy_blacklist/blacklist_listener.h68
-rw-r--r--chrome/browser/privacy_blacklist/blacklist_listener_unittest.cc183
-rw-r--r--chrome/browser/privacy_blacklist/blacklist_manager.cc49
-rw-r--r--chrome/browser/privacy_blacklist/blacklist_manager.h5
-rw-r--r--chrome/browser/privacy_blacklist/blacklist_manager_browsertest.cc49
-rw-r--r--chrome/browser/privacy_blacklist/blacklist_manager_unittest.cc97
-rw-r--r--chrome/browser/privacy_blacklist/blacklist_request_info.cc29
-rw-r--r--chrome/browser/privacy_blacklist/blacklist_request_info.h47
-rw-r--r--chrome/browser/privacy_blacklist/blacklist_test_util.cc76
-rw-r--r--chrome/browser/privacy_blacklist/blacklist_test_util.h64
-rw-r--r--chrome/browser/privacy_blacklist/blacklist_ui.cc56
-rw-r--r--chrome/browser/privacy_blacklist/blocked_response.cc104
-rw-r--r--chrome/browser/privacy_blacklist/blocked_response.h57
19 files changed, 912 insertions, 328 deletions
diff --git a/chrome/browser/privacy_blacklist/blacklist.cc b/chrome/browser/privacy_blacklist/blacklist.cc
index bbb8a38..1bec742 100644
--- a/chrome/browser/privacy_blacklist/blacklist.cc
+++ b/chrome/browser/privacy_blacklist/blacklist.cc
@@ -40,9 +40,6 @@ const unsigned int Blacklist::kModifyReceivedHeaders =
const unsigned int Blacklist::kFilterByHeaders =
kModifyReceivedHeaders | kBlockByType;
-// Value is not important, here just that the object has an address.
-const void* const Blacklist::kRequestDataKey = 0;
-
unsigned int Blacklist::String2Attribute(const std::string& s) {
if (s == STRINGIZE(kBlockAll))
return kBlockAll;
diff --git a/chrome/browser/privacy_blacklist/blacklist.h b/chrome/browser/privacy_blacklist/blacklist.h
index 1999a09..2fba5fb 100644
--- a/chrome/browser/privacy_blacklist/blacklist.h
+++ b/chrome/browser/privacy_blacklist/blacklist.h
@@ -49,9 +49,6 @@ class Blacklist {
static const unsigned int kModifyReceivedHeaders;
static const unsigned int kFilterByHeaders;
- // Key used to access data attached to URLRequest objects.
- static const void* const kRequestDataKey;
-
// Converts a stringized filter attribute (see above) back to its integer
// value. Returns 0 on error.
static unsigned int String2Attribute(const std::string&);
diff --git a/chrome/browser/privacy_blacklist/blacklist_interceptor.cc b/chrome/browser/privacy_blacklist/blacklist_interceptor.cc
new file mode 100644
index 0000000..79c47fb
--- /dev/null
+++ b/chrome/browser/privacy_blacklist/blacklist_interceptor.cc
@@ -0,0 +1,141 @@
+// 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_interceptor.h"
+
+#include "app/l10n_util.h"
+#include "app/resource_bundle.h"
+#include "base/string_util.h"
+#include "base/values.h"
+#include "chrome/browser/privacy_blacklist/blacklist.h"
+#include "chrome/browser/privacy_blacklist/blacklist_manager.h"
+#include "chrome/browser/privacy_blacklist/blacklist_request_info.h"
+#include "chrome/common/jstemplate_builder.h"
+#include "net/url_request/url_request_simple_job.h"
+#include "grit/browser_resources.h"
+#include "grit/generated_resources.h"
+
+namespace {
+
+class URLRequestBlacklistJob : public URLRequestSimpleJob {
+ public:
+ URLRequestBlacklistJob(URLRequest* request,
+ const BlacklistRequestInfo& request_info)
+ : URLRequestSimpleJob(request),
+ request_info_(request_info) {
+ }
+
+ virtual bool GetData(std::string* mime_type,
+ std::string* charset,
+ std::string* data) const {
+ if (ResourceType::IsFrame(request_info_.resource_type())) {
+ *mime_type = "text/html";
+ *charset = "utf-8";
+ *data = GetHTMLResponse();
+ } else {
+ // TODO(phajdan.jr): For some resources (like script) we may want to
+ // simulate an error instead or return other MIME type.
+ *mime_type = "image/png";
+ *data = GetImageResponse();
+ }
+ return true;
+ }
+
+ private:
+ std::string GetHTMLResponse() const {
+ return "HTTP/1.1 200 OK\r\n"
+ "Content-Type: text/html;charset=utf-8\r\n"
+ "Cache-Control: no-store\r\n\r\n" + GetHTML();
+ }
+
+ static std::string GetImageResponse() {
+ return "HTTP/1.1 200 OK\r\n"
+ "Content-Type: image/png\r\n"
+ "Cache-Control: no-store\r\n\r\n" + GetImage();
+ }
+
+ static std::string GetImage() {
+ return ResourceBundle::GetSharedInstance().
+ GetDataResource(IDR_BLACKLIST_IMAGE);
+ }
+
+ std::string GetHTML() const {
+ DictionaryValue strings;
+ strings.SetString(L"title", l10n_util::GetString(IDS_BLACKLIST_TITLE));
+ strings.SetString(L"message", l10n_util::GetString(IDS_BLACKLIST_MESSAGE));
+
+ const Blacklist::Provider* provider = GetBestMatchingEntryProvider();
+ strings.SetString(L"name", provider->name());
+ strings.SetString(L"url", provider->url());
+
+ const base::StringPiece html =
+ ResourceBundle::GetSharedInstance().GetRawDataResource(
+ IDR_BLACKLIST_HTML);
+ return jstemplate_builder::GetI18nTemplateHtml(html, &strings);
+ }
+
+ const Blacklist::Provider* GetBestMatchingEntryProvider() const {
+ // If kBlockAll is specified, assign blame to such an entry.
+ // Otherwise pick the first one.
+ const BlacklistManager* blacklist_manager =
+ request_info_.GetBlacklistManager();
+ const Blacklist* blacklist = blacklist_manager->GetCompiledBlacklist();
+ scoped_ptr<Blacklist::Match> match(blacklist->findMatch(request_->url()));
+ const Blacklist::Entry* entry = NULL;
+ if (match->attributes() & Blacklist::kBlockAll) {
+ for (std::vector<const Blacklist::Entry*>::const_iterator i =
+ match->entries().begin(); i != match->entries().end(); ++i) {
+ if ((*i)->attributes() == Blacklist::kBlockAll) {
+ entry = *i;
+ break;
+ }
+ }
+ } else {
+ entry = match->entries().front();
+ }
+ return entry->provider();
+ }
+
+ const BlacklistRequestInfo& request_info_;
+
+ DISALLOW_COPY_AND_ASSIGN(URLRequestBlacklistJob);
+};
+
+} // namespace
+
+BlacklistInterceptor::BlacklistInterceptor() {
+ URLRequest::RegisterRequestInterceptor(this);
+}
+
+BlacklistInterceptor::~BlacklistInterceptor() {
+ URLRequest::UnregisterRequestInterceptor(this);
+}
+
+URLRequestJob* BlacklistInterceptor::MaybeIntercept(URLRequest* request) {
+ BlacklistRequestInfo* request_info =
+ BlacklistRequestInfo::FromURLRequest(request);
+ if (!request_info) {
+ // Not all requests have privacy blacklist data, for example downloads.
+ return NULL;
+ }
+
+ const BlacklistManager* blacklist_manager =
+ request_info->GetBlacklistManager();
+ const Blacklist* blacklist = blacklist_manager->GetCompiledBlacklist();
+ scoped_ptr<Blacklist::Match> match(blacklist->findMatch(request->url()));
+
+ if (!match.get()) {
+ // Nothing is blacklisted for this request. Do not intercept.
+ return NULL;
+ }
+
+ // TODO(phajdan.jr): Should we have some UI to notify about blocked referrer?
+ if (match->attributes() & Blacklist::kDontSendReferrer)
+ request->set_referrer(std::string());
+
+ if (match->IsBlocked(request->url()))
+ return new URLRequestBlacklistJob(request, *request_info);
+
+ return NULL;
+}
diff --git a/chrome/browser/privacy_blacklist/blacklist_interceptor.h b/chrome/browser/privacy_blacklist/blacklist_interceptor.h
new file mode 100644
index 0000000..308ce9c
--- /dev/null
+++ b/chrome/browser/privacy_blacklist/blacklist_interceptor.h
@@ -0,0 +1,23 @@
+// 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.
+
+#ifndef CHROME_BROWSER_PRIVACY_BLACKLIST_BLACKLIST_INTERCEPTOR_H_
+#define CHROME_BROWSER_PRIVACY_BLACKLIST_BLACKLIST_INTERCEPTOR_H_
+
+#include "net/url_request/url_request.h"
+
+// Intercepts requests matched by a privacy blacklist.
+class BlacklistInterceptor : public URLRequest::Interceptor {
+ public:
+ BlacklistInterceptor();
+ ~BlacklistInterceptor();
+
+ // URLRequest::Interceptor:
+ virtual URLRequestJob* MaybeIntercept(URLRequest* request);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BlacklistInterceptor);
+};
+
+#endif // CHROME_BROWSER_PRIVACY_BLACKLIST_BLACKLIST_INTERCEPTOR_H_
diff --git a/chrome/browser/privacy_blacklist/blacklist_interceptor_unittest.cc b/chrome/browser/privacy_blacklist/blacklist_interceptor_unittest.cc
new file mode 100644
index 0000000..f1cadcf
--- /dev/null
+++ b/chrome/browser/privacy_blacklist/blacklist_interceptor_unittest.cc
@@ -0,0 +1,94 @@
+// 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 "app/l10n_util.h"
+#include "base/message_loop.h"
+#include "base/path_service.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/privacy_blacklist/blacklist_interceptor.h"
+#include "chrome/browser/privacy_blacklist/blacklist_manager.h"
+#include "chrome/browser/privacy_blacklist/blacklist_request_info.h"
+#include "chrome/browser/privacy_blacklist/blacklist_test_util.h"
+#include "chrome/common/chrome_paths.h"
+#include "grit/browser_resources.h"
+#include "grit/generated_resources.h"
+#include "net/base/io_buffer.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_status.h"
+#include "net/url_request/url_request_unittest.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+const char kDataUrl[] = "data:text/plain,Hello World!";
+const char kBlockedUrl[] = "http://example.com/annoying_ads/ad.jpg";
+
+class BlacklistInterceptorTest : public testing::Test {
+ public:
+ BlacklistInterceptorTest()
+ : loop_(MessageLoop::TYPE_IO),
+ ui_thread_(ChromeThread::UI, &loop_),
+ file_thread_(ChromeThread::FILE, &loop_),
+ io_thread_(ChromeThread::IO, &loop_) {
+ }
+
+ virtual void SetUp() {
+ ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_));
+ test_data_dir_ = test_data_dir_.AppendASCII("blacklist_samples");
+ }
+
+ protected:
+ bool InterceptedTestRequest(const std::string& url,
+ BlacklistRequestInfo* request_info) {
+ TestDelegate delegate;
+ TestURLRequest request(GURL(url), &delegate);
+ request.SetUserData(&BlacklistRequestInfo::kURLRequestDataKey,
+ request_info);
+ request.Start();
+ MessageLoop::current()->Run();
+
+ std::string response(delegate.data_received());
+ return (ContainsResourceString(response, IDS_BLACKLIST_TITLE) &&
+ ContainsResourceString(response, IDS_BLACKLIST_MESSAGE));
+ }
+
+ BlacklistInterceptor interceptor_;
+
+ FilePath test_data_dir_;
+
+ private:
+ bool ContainsResourceString(const std::string& text, int string_id) {
+ return text.find(l10n_util::GetStringUTF8(string_id)) != std::string::npos;
+ }
+
+ MessageLoop loop_;
+
+ ChromeThread ui_thread_;
+ ChromeThread file_thread_;
+ ChromeThread io_thread_;
+};
+
+TEST_F(BlacklistInterceptorTest, Basic) {
+ EXPECT_FALSE(InterceptedTestRequest(kDataUrl, NULL));
+}
+
+TEST_F(BlacklistInterceptorTest, Intercepted) {
+ BlacklistTestingProfile profile;
+ TestBlacklistPathProvider path_provider(&profile);
+ path_provider.AddTransientPath(
+ test_data_dir_.AppendASCII("annoying_ads.pbl"));
+ scoped_refptr<BlacklistManager> blacklist_manager(
+ new BlacklistManager(&profile, &path_provider));
+ blacklist_manager->Initialize();
+ MessageLoop::current()->RunAllPending();
+
+ EXPECT_FALSE(InterceptedTestRequest(kDataUrl, NULL));
+
+ BlacklistRequestInfo* request_info =
+ new BlacklistRequestInfo(GURL(kBlockedUrl), ResourceType::MAIN_FRAME,
+ blacklist_manager.get());
+ EXPECT_TRUE(InterceptedTestRequest(kBlockedUrl, request_info));
+}
+
+} // namespace
diff --git a/chrome/browser/privacy_blacklist/blacklist_listener.cc b/chrome/browser/privacy_blacklist/blacklist_listener.cc
new file mode 100644
index 0000000..5e00236
--- /dev/null
+++ b/chrome/browser/privacy_blacklist/blacklist_listener.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_listener.h"
+
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/privacy_blacklist/blacklist.h"
+#include "chrome/browser/privacy_blacklist/blacklist_manager.h"
+#include "chrome/browser/privacy_blacklist/blacklist_request_info.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/renderer_host/global_request_id.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_type.h"
+#include "net/url_request/url_request.h"
+
+BlacklistListener::BlacklistListener(ResourceQueue* resource_queue)
+ : resource_queue_(resource_queue) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+
+ registrar_.Add(this,
+ NotificationType::BLACKLIST_MANAGER_ERROR,
+ NotificationService::AllSources());
+ registrar_.Add(this,
+ NotificationType::BLACKLIST_MANAGER_BLACKLIST_READ_FINISHED,
+ NotificationService::AllSources());
+}
+
+BlacklistListener::~BlacklistListener() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+}
+
+void BlacklistListener::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+
+ switch (type.value) {
+ // TODO(phajdan.jr): Do not resume requests silently after an error.
+ case NotificationType::BLACKLIST_MANAGER_ERROR:
+ case NotificationType::BLACKLIST_MANAGER_BLACKLIST_READ_FINISHED:
+ {
+ Profile* profile = Source<Profile>(source).ptr();
+ ChromeThread::PostTask(ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(this, &BlacklistListener::StartDelayedRequests,
+ profile->GetBlacklistManager()));
+ }
+ break;
+ default:
+ NOTREACHED();
+ }
+}
+
+bool BlacklistListener::ShouldDelayRequest(
+ URLRequest* request,
+ const ResourceDispatcherHostRequestInfo& request_info,
+ const GlobalRequestID& request_id) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+
+ BlacklistRequestInfo* blacklist_request_info =
+ BlacklistRequestInfo::FromURLRequest(request);
+ const BlacklistManager* blacklist_manager =
+ blacklist_request_info->GetBlacklistManager();
+
+ if (blacklist_manager->GetCompiledBlacklist()) {
+ // We have a blacklist ready. No need to delay the request.
+ return false;
+ }
+
+ delayed_requests_[blacklist_manager].push_back(request_id);
+ return true;
+}
+
+void BlacklistListener::WillShutdownResourceQueue() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ resource_queue_ = NULL;
+}
+
+void BlacklistListener::StartDelayedRequests(
+ BlacklistManager* blacklist_manager) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+
+ if (resource_queue_) {
+ const RequestList& requests = delayed_requests_[blacklist_manager];
+ for (RequestList::const_iterator i = requests.begin();
+ i != requests.end(); ++i) {
+ resource_queue_->StartDelayedRequest(this, *i);
+ }
+ }
+
+ delayed_requests_[blacklist_manager].clear();
+}
diff --git a/chrome/browser/privacy_blacklist/blacklist_listener.h b/chrome/browser/privacy_blacklist/blacklist_listener.h
new file mode 100644
index 0000000..a74ed8e
--- /dev/null
+++ b/chrome/browser/privacy_blacklist/blacklist_listener.h
@@ -0,0 +1,68 @@
+// 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.
+
+#ifndef CHROME_BROWSER_PRIVACY_BLACKLIST_BLACKLIST_LISTENER_H_
+#define CHROME_BROWSER_PRIVACY_BLACKLIST_BLACKLIST_LISTENER_H_
+
+#include <map>
+#include <vector>
+
+#include "base/ref_counted.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/renderer_host/resource_queue.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+
+class BlacklistManager;
+
+// Delays requests until privacy blacklists are ready.
+class BlacklistListener
+ : public ResourceQueueDelegate,
+ public NotificationObserver,
+ public base::RefCountedThreadSafe<BlacklistListener,
+ ChromeThread::DeleteOnUIThread> {
+ public:
+ // UI THREAD ONLY ------------------------------------------------------------
+
+ explicit BlacklistListener(ResourceQueue* resource_queue);
+ virtual ~BlacklistListener();
+
+ // NotificationObserver:
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ // IO THREAD ONLY ------------------------------------------------------------
+
+ // ResourceQueueDelegate:
+ virtual bool ShouldDelayRequest(
+ URLRequest* request,
+ const ResourceDispatcherHostRequestInfo& request_info,
+ const GlobalRequestID& request_id);
+ virtual void WillShutdownResourceQueue();
+
+ private:
+ friend class ChromeThread;
+ friend class DeleteTask<BlacklistListener>;
+
+ // Tell our resource queue to start the requests we requested to be delayed.
+ void StartDelayedRequests(BlacklistManager* blacklist_manager);
+
+ // Resource queue we're delegate of.
+ ResourceQueue* resource_queue_;
+
+ typedef std::vector<GlobalRequestID> RequestList;
+ typedef std::map<const BlacklistManager*, RequestList> DelayedRequestMap;
+
+ // Keep track of requests we have requested to delay so that we can resume
+ // them as the blacklists load (note that we have a request list per blacklist
+ // manager).
+ DelayedRequestMap delayed_requests_;
+
+ NotificationRegistrar registrar_;
+
+ DISALLOW_COPY_AND_ASSIGN(BlacklistListener);
+};
+
+#endif // CHROME_BROWSER_PRIVACY_BLACKLIST_BLACKLIST_LISTENER_H_
diff --git a/chrome/browser/privacy_blacklist/blacklist_listener_unittest.cc b/chrome/browser/privacy_blacklist/blacklist_listener_unittest.cc
new file mode 100644
index 0000000..0625009
--- /dev/null
+++ b/chrome/browser/privacy_blacklist/blacklist_listener_unittest.cc
@@ -0,0 +1,183 @@
+// 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_listener.h"
+
+#include "base/message_loop.h"
+#include "base/thread.h"
+#include "chrome/browser/privacy_blacklist/blacklist.h"
+#include "chrome/browser/privacy_blacklist/blacklist_request_info.h"
+#include "chrome/browser/privacy_blacklist/blacklist_test_util.h"
+#include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h"
+#include "chrome/browser/renderer_host/resource_handler.h"
+#include "chrome/browser/renderer_host/resource_queue.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "chrome/common/notification_source.h"
+#include "chrome/common/notification_type.h"
+#include "net/url_request/url_request_unittest.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+const char kTestUrl[] = "data:text/plain,Hello World!";
+
+// Dummy ResourceHandler required for ResourceDispatcherHostRequestInfo.
+class DummyResourceHandler : public ResourceHandler {
+ public:
+ DummyResourceHandler() {
+ }
+
+ virtual bool OnRequestRedirected(int request_id, const GURL& url,
+ ResourceResponse* response,
+ bool* defer) {
+ NOTREACHED();
+ return true;
+ }
+
+ virtual bool OnResponseStarted(int request_id,
+ ResourceResponse* response) {
+ NOTREACHED();
+ return true;
+ }
+
+ virtual bool OnWillRead(int request_id,
+ net::IOBuffer** buf,
+ int* buf_size,
+ int min_size) {
+ NOTREACHED();
+ return true;
+ }
+
+ virtual bool OnReadCompleted(int request_id, int* bytes_read) {
+ NOTREACHED();
+ return true;
+ }
+
+ virtual bool OnResponseCompleted(int request_id,
+ const URLRequestStatus& status,
+ const std::string& security_info) {
+ NOTREACHED();
+ return true;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DummyResourceHandler);
+};
+
+ResourceDispatcherHostRequestInfo* GetRequestInfo(int request_id) {
+ return new ResourceDispatcherHostRequestInfo(
+ new DummyResourceHandler(), ChildProcessInfo::RENDER_PROCESS, 0, 0,
+ request_id, "null", "null", ResourceType::MAIN_FRAME,
+ 0, false, false, -1, -1);
+}
+
+class BlacklistListenerTest
+ : public testing::Test,
+ public NotificationObserver {
+ public:
+ BlacklistListenerTest()
+ : path_provider_(&profile_),
+ loop_(MessageLoop::TYPE_IO),
+ mock_ui_thread_(ChromeThread::UI, MessageLoop::current()),
+ mock_file_thread_(ChromeThread::FILE, MessageLoop::current()),
+ mock_io_thread_(ChromeThread::IO, MessageLoop::current()) {
+ }
+
+ virtual void SetUp() {
+ blacklist_manager_ = new BlacklistManager(&profile_, &path_provider_);
+ blacklist_listener_ = new BlacklistListener(&resource_queue_);
+
+ profile_.set_blacklist_manager(blacklist_manager_.get());
+
+ ResourceQueue::DelegateSet delegates;
+ delegates.insert(blacklist_listener_.get());
+ resource_queue_.Initialize(delegates);
+ }
+
+ virtual void TearDown() {
+ resource_queue_.Shutdown();
+ blacklist_listener_ = NULL;
+ blacklist_manager_ = NULL;
+ loop_.RunAllPending();
+ }
+
+ // NotificationObserver
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ MessageLoop::current()->Quit();
+ }
+
+ protected:
+ void WaitForBlacklistUpdate() {
+ NotificationRegistrar registrar;
+ registrar.Add(this,
+ NotificationType::BLACKLIST_MANAGER_BLACKLIST_READ_FINISHED,
+ Source<Profile>(&profile_));
+ MessageLoop::current()->Run();
+ }
+
+ TestURLRequest* StartTestRequest(URLRequest::Delegate* delegate) {
+ TestURLRequest* request = new TestURLRequest(GURL(kTestUrl), delegate);
+ BlacklistRequestInfo* request_info =
+ new BlacklistRequestInfo(request->url(), ResourceType::MAIN_FRAME,
+ blacklist_manager_.get());
+ request->SetUserData(&BlacklistRequestInfo::kURLRequestDataKey,
+ request_info);
+ scoped_ptr<ResourceDispatcherHostRequestInfo> rdh_info(GetRequestInfo(0));
+ resource_queue_.AddRequest(request, *rdh_info.get());
+ return request;
+ }
+
+ BlacklistTestingProfile profile_;
+
+ TestBlacklistPathProvider path_provider_;
+
+ scoped_refptr<BlacklistManager> blacklist_manager_;
+
+ scoped_refptr<BlacklistListener> blacklist_listener_;
+
+ private:
+ MessageLoop loop_;
+
+ ChromeThread mock_ui_thread_;
+ ChromeThread mock_file_thread_;
+ ChromeThread mock_io_thread_;
+
+ ResourceQueue resource_queue_;
+};
+
+TEST_F(BlacklistListenerTest, Delay) {
+ blacklist_manager_->Initialize();
+
+ TestDelegate delegate;
+ scoped_ptr<TestURLRequest> request(StartTestRequest(&delegate));
+
+ // The request should get delayed, because the BlacklistManager is not yet
+ // ready. When we run pending tasks, it should initialize itself, notify
+ // the BlacklistListener, and start the request.
+ ASSERT_FALSE(request->is_pending());
+
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ("Hello World!", delegate.data_received());
+}
+
+TEST_F(BlacklistListenerTest, NoDelay) {
+ blacklist_manager_->Initialize();
+
+ // Make sure that the BlacklistManager is ready before we start the request.
+ WaitForBlacklistUpdate();
+
+ TestDelegate delegate;
+ scoped_ptr<TestURLRequest> request(StartTestRequest(&delegate));
+
+ // The request should be started immediately.
+ ASSERT_TRUE(request->is_pending());
+
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ("Hello World!", delegate.data_received());
+}
+
+} // namespace
diff --git a/chrome/browser/privacy_blacklist/blacklist_manager.cc b/chrome/browser/privacy_blacklist/blacklist_manager.cc
index ca8dc0b..c2253ef 100644
--- a/chrome/browser/privacy_blacklist/blacklist_manager.cc
+++ b/chrome/browser/privacy_blacklist/blacklist_manager.cc
@@ -8,6 +8,7 @@
#include "base/string_util.h"
#include "base/task.h"
#include "base/thread.h"
+#include "base/utf_string_conversions.h"
#include "chrome/browser/privacy_blacklist/blacklist.h"
#include "chrome/browser/privacy_blacklist/blacklist_io.h"
#include "chrome/browser/profile.h"
@@ -89,6 +90,14 @@ void BlacklistManager::CompileBlacklist() {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
DCHECK(path_provider_->AreBlacklistPathsReady());
+ // The compiled blacklist is going to change. Make sure our clients don't use
+ // the old one and wait for the update instead by indicating that the compiled
+ // blacklist is not ready.
+ ChromeThread::PostTask(ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(this,
+ &BlacklistManager::ResetPublishedCompiledBlacklist));
+
+ // Schedule actual compilation on the background thread.
ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE,
NewRunnableMethod(this, &BlacklistManager::DoCompileBlacklist,
path_provider_->GetPersistentBlacklistPaths()));
@@ -98,22 +107,28 @@ void BlacklistManager::DoCompileBlacklist(
const std::vector<FilePath>& source_blacklists) {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
- bool success = true;
Blacklist blacklist;
std::string error_string;
+ std::vector<string16> errors;
for (std::vector<FilePath>::const_iterator i = source_blacklists.begin();
i != source_blacklists.end(); ++i) {
+ std::string error_string;
if (!BlacklistIO::ReadText(&blacklist, *i, &error_string)) {
- success = false;
- break;
+ string16 path = WideToUTF16(i->ToWStringHack());
+ errors.push_back(path + ASCIIToUTF16(": " + error_string));
}
}
- // Only overwrite the current compiled blacklist if we read all source
- // files successfully.
- if (success)
- success = BlacklistIO::WriteBinary(&blacklist, compiled_blacklist_path_);
+ if (!errors.empty()) {
+ ChromeThread::PostTask(ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(this,
+ &BlacklistManager::OnBlacklistCompilationReadErrors,
+ errors));
+ }
+ // Write the new compiled blacklist based on the data we could read
+ // successfully.
+ bool success = BlacklistIO::WriteBinary(&blacklist, compiled_blacklist_path_);
ChromeThread::PostTask(ChromeThread::UI, FROM_HERE,
NewRunnableMethod(this, &BlacklistManager::OnBlacklistCompilationFinished,
success));
@@ -133,6 +148,21 @@ void BlacklistManager::OnBlacklistCompilationFinished(bool success) {
}
}
+void BlacklistManager::OnBlacklistCompilationReadErrors(
+ const std::vector<string16>& errors) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+
+ string16 error_message(ASCIIToUTF16("Blacklist compilation failed.\n"));
+ for (std::vector<string16>::const_iterator i = errors.begin();
+ i != errors.end(); ++i) {
+ error_message += *i + ASCIIToUTF16("\n");
+ }
+ NotificationService::current()->Notify(
+ NotificationType::BLACKLIST_MANAGER_ERROR,
+ Source<Profile>(profile_),
+ Details<string16>(&error_message));
+}
+
void BlacklistManager::ReadBlacklist() {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
DCHECK(path_provider_->AreBlacklistPathsReady());
@@ -197,3 +227,8 @@ void BlacklistManager::OnBlacklistReadFinished(bool success) {
}
first_read_finished_ = true;
}
+
+void BlacklistManager::ResetPublishedCompiledBlacklist() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ compiled_blacklist_.reset();
+}
diff --git a/chrome/browser/privacy_blacklist/blacklist_manager.h b/chrome/browser/privacy_blacklist/blacklist_manager.h
index 5d6e97b..1ababd6 100644
--- a/chrome/browser/privacy_blacklist/blacklist_manager.h
+++ b/chrome/browser/privacy_blacklist/blacklist_manager.h
@@ -70,6 +70,7 @@ class BlacklistManager
// Compile all persistent blacklists to one binary blacklist stored on disk.
void CompileBlacklist();
void DoCompileBlacklist(const std::vector<FilePath>& source_blacklists);
+ void OnBlacklistCompilationReadErrors(const std::vector<string16>& errors);
void OnBlacklistCompilationFinished(bool success);
// Read all blacklists from disk (the compiled one and also the transient
@@ -80,6 +81,10 @@ class BlacklistManager
void UpdatePublishedCompiledBlacklist(Blacklist* blacklist);
void OnBlacklistReadFinished(bool success);
+ // Sets the |compiled_blacklist_| to NULL to indicate that the blacklist is
+ // not ready.
+ void ResetPublishedCompiledBlacklist();
+
// True after the first blacklist read has finished (regardless of success).
// Used to avoid an infinite loop.
bool first_read_finished_;
diff --git a/chrome/browser/privacy_blacklist/blacklist_manager_browsertest.cc b/chrome/browser/privacy_blacklist/blacklist_manager_browsertest.cc
index 46bba29..8bbd8ac 100644
--- a/chrome/browser/privacy_blacklist/blacklist_manager_browsertest.cc
+++ b/chrome/browser/privacy_blacklist/blacklist_manager_browsertest.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/privacy_blacklist/blacklist_manager.h"
+#include "app/l10n_util.h"
#include "base/command_line.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_process.h"
@@ -13,10 +14,10 @@
#include "chrome/browser/privacy_blacklist/blacklist_manager.h"
#include "chrome/browser/profile.h"
#include "chrome/common/chrome_switches.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 "grit/browser_resources.h"
+#include "grit/generated_resources.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
@@ -45,34 +46,14 @@ class BlacklistManagerBrowserTest : public ExtensionBrowserTest {
virtual void SetUpInProcessBrowserTestFixture() {
ExtensionBrowserTest::SetUpInProcessBrowserTestFixture();
- received_blacklist_notification_ = false;
host_resolver()->AddSimulatedFailure("www.example.com");
}
- // 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;
- }
- received_blacklist_notification_ = true;
- MessageLoop::current()->Quit();
- }
-
protected:
BlacklistManager* GetBlacklistManager() {
return browser()->profile()->GetBlacklistManager();
}
- bool GetAndResetReceivedBlacklistNotification() {
- bool result = received_blacklist_notification_;
- received_blacklist_notification_ = false;
- return result;
- }
-
bool BlacklistHasMatch(const std::string& url) {
bool has_match = false;
ChromeThread::PostTask(ChromeThread::IO, FROM_HERE,
@@ -83,30 +64,20 @@ class BlacklistManagerBrowserTest : public ExtensionBrowserTest {
ui_test_utils::RunMessageLoop();
return has_match;
}
-
- private:
- bool received_blacklist_notification_;
};
-IN_PROC_BROWSER_TEST_F(BlacklistManagerBrowserTest, FLAKY_Basic) {
+IN_PROC_BROWSER_TEST_F(BlacklistManagerBrowserTest, Basic) {
static const char kTestUrl[] = "http://www.example.com/annoying_ads/ad.jpg";
- NotificationRegistrar registrar;
- registrar.Add(this,
- NotificationType::BLACKLIST_MANAGER_BLACKLIST_READ_FINISHED,
- Source<Profile>(browser()->profile()));
-
// Test loading an extension with blacklist.
ASSERT_TRUE(LoadExtension(
test_data_dir_.AppendASCII("common").AppendASCII("privacy_blacklist")));
- // Wait until the blacklist is loaded and ready.
- if (!GetAndResetReceivedBlacklistNotification())
- ui_test_utils::RunMessageLoop();
-
- // The blacklist should block our test URL.
- EXPECT_TRUE(BlacklistHasMatch(kTestUrl));
-
- // TODO(phajdan.jr): Verify that we really blocked the request etc.
+ // Navigate to a blacklisted URL. The request should be blocked.
ui_test_utils::NavigateToURL(browser(), GURL(kTestUrl));
+ string16 expected_title(l10n_util::GetStringUTF16(IDS_BLACKLIST_TITLE));
+ string16 tab_title;
+ ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title));
+ EXPECT_EQ(expected_title, tab_title);
+ EXPECT_TRUE(BlacklistHasMatch(kTestUrl));
}
diff --git a/chrome/browser/privacy_blacklist/blacklist_manager_unittest.cc b/chrome/browser/privacy_blacklist/blacklist_manager_unittest.cc
index 2b48b5c..a2b0a17 100644
--- a/chrome/browser/privacy_blacklist/blacklist_manager_unittest.cc
+++ b/chrome/browser/privacy_blacklist/blacklist_manager_unittest.cc
@@ -6,100 +6,18 @@
#include "base/message_loop.h"
#include "base/path_service.h"
-#include "base/scoped_temp_dir.h"
#include "base/thread.h"
-#include "base/values.h"
#include "chrome/browser/privacy_blacklist/blacklist.h"
+#include "chrome/browser/privacy_blacklist/blacklist_test_util.h"
#include "chrome/common/chrome_paths.h"
-#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/extension_constants.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/test/testing_profile.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "chrome/common/notification_source.h"
+#include "chrome/common/notification_type.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
-class MyTestingProfile : public TestingProfile {
- public:
- MyTestingProfile() {
- EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
- path_ = temp_dir_.path();
- }
-
- private:
- ScopedTempDir temp_dir_;
-
- DISALLOW_COPY_AND_ASSIGN(MyTestingProfile);
-};
-
-class TestBlacklistPathProvider : public BlacklistPathProvider {
- public:
- explicit TestBlacklistPathProvider(Profile* profile) : profile_(profile) {
- }
-
- virtual bool AreBlacklistPathsReady() const {
- return true;
- }
-
- virtual std::vector<FilePath> GetPersistentBlacklistPaths() {
- return persistent_paths_;
- }
-
- virtual std::vector<FilePath> GetTransientBlacklistPaths() {
- return transient_paths_;
- }
-
- void AddPersistentPath(const FilePath& path) {
- 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();
- SendUpdateNotification();
- }
-
- private:
- void SendUpdateNotification() {
- ListValue* privacy_blacklists = new ListValue;
- privacy_blacklists->Append(new StringValue("dummy.pbl"));
-
- DictionaryValue manifest;
- manifest.SetString(extension_manifest_keys::kVersion, "1.0");
- manifest.SetString(extension_manifest_keys::kName, "test");
- manifest.Set(extension_manifest_keys::kPrivacyBlacklists,
- privacy_blacklists);
-
-#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);
- std::string error;
- ASSERT_TRUE(extension.InitFromValue(manifest, false, &error));
- ASSERT_TRUE(error.empty());
-
- NotificationService::current()->Notify(
- NotificationType::EXTENSION_LOADED,
- Source<Profile>(profile_),
- Details<Extension>(&extension));
- }
-
- Profile* profile_;
-
- std::vector<FilePath> persistent_paths_;
- std::vector<FilePath> transient_paths_;
-
- DISALLOW_COPY_AND_ASSIGN(TestBlacklistPathProvider);
-};
-
class BlacklistManagerTest : public testing::Test, public NotificationObserver {
public:
BlacklistManagerTest()
@@ -146,7 +64,7 @@ class BlacklistManagerTest : public testing::Test, public NotificationObserver {
FilePath test_data_dir_;
- MyTestingProfile profile_;
+ BlacklistTestingProfile profile_;
TestBlacklistPathProvider path_provider_;
@@ -199,7 +117,6 @@ TEST_F(BlacklistManagerTest, BlacklistPathProvider) {
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"));
@@ -238,7 +155,7 @@ TEST_F(BlacklistManagerTest, BlacklistPathReadError) {
FilePath bogus_path(test_data_dir_.AppendASCII("does_not_exist_randomness"));
ASSERT_FALSE(file_util::PathExists(bogus_path));
path_provider_.AddPersistentPath(bogus_path);
- WaitForBlacklistError();
+ WaitForBlacklistUpdate();
const Blacklist* blacklist = manager->GetCompiledBlacklist();
EXPECT_TRUE(blacklist);
diff --git a/chrome/browser/privacy_blacklist/blacklist_request_info.cc b/chrome/browser/privacy_blacklist/blacklist_request_info.cc
new file mode 100644
index 0000000..b5ecfb5
--- /dev/null
+++ b/chrome/browser/privacy_blacklist/blacklist_request_info.cc
@@ -0,0 +1,29 @@
+// 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_request_info.h"
+
+#include "chrome/browser/privacy_blacklist/blacklist_manager.h"
+
+// static
+const void* const BlacklistRequestInfo::kURLRequestDataKey = 0;
+
+BlacklistRequestInfo::BlacklistRequestInfo(const GURL& url,
+ ResourceType::Type resource_type,
+ BlacklistManager* blacklist_manager)
+ : url_(url),
+ resource_type_(resource_type),
+ blacklist_manager_(blacklist_manager) {
+}
+
+BlacklistRequestInfo::~BlacklistRequestInfo() {
+}
+
+// static
+BlacklistRequestInfo* BlacklistRequestInfo::FromURLRequest(
+ const URLRequest* request) {
+ URLRequest::UserData* user_data =
+ request->GetUserData(&kURLRequestDataKey);
+ return (user_data ? static_cast<BlacklistRequestInfo*>(user_data) : NULL);
+}
diff --git a/chrome/browser/privacy_blacklist/blacklist_request_info.h b/chrome/browser/privacy_blacklist/blacklist_request_info.h
new file mode 100644
index 0000000..84a74d1
--- /dev/null
+++ b/chrome/browser/privacy_blacklist/blacklist_request_info.h
@@ -0,0 +1,47 @@
+// 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.
+
+#ifndef CHROME_BROWSER_PRIVACY_BLACKLIST_BLACKLIST_REQUEST_INFO_H_
+#define CHROME_BROWSER_PRIVACY_BLACKLIST_BLACKLIST_REQUEST_INFO_H_
+
+#include "chrome/browser/privacy_blacklist/blacklist.h"
+#include "googleurl/src/gurl.h"
+#include "net/url_request/url_request.h"
+#include "webkit/glue/resource_type.h"
+
+class BlacklistManager;
+
+// Privacy blacklist-related information attached to each request.
+class BlacklistRequestInfo : public URLRequest::UserData {
+ public:
+ // Key used to access data attached to URLRequest objects.
+ static const void* const kURLRequestDataKey;
+
+ BlacklistRequestInfo(const GURL& url, ResourceType::Type resource_type,
+ BlacklistManager* blacklist_manager);
+ ~BlacklistRequestInfo();
+
+ ResourceType::Type resource_type() const { return resource_type_; }
+ const BlacklistManager* GetBlacklistManager() const {
+ return blacklist_manager_.get();
+ }
+
+ // Get the blacklist request info stored in |request|, or NULL if there is no
+ // one. The object is owned by |request|.
+ static BlacklistRequestInfo* FromURLRequest(const URLRequest* request);
+
+ private:
+ // URL of the request.
+ const GURL url_;
+
+ // Type of the requested resource (main frame, image, etc).
+ const ResourceType::Type resource_type_;
+
+ // BlacklistManager used for the request.
+ scoped_refptr<BlacklistManager> blacklist_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(BlacklistRequestInfo);
+};
+
+#endif // CHROME_BROWSER_PRIVACY_BLACKLIST_BLACKLIST_REQUEST_INFO_H_
diff --git a/chrome/browser/privacy_blacklist/blacklist_test_util.cc b/chrome/browser/privacy_blacklist/blacklist_test_util.cc
new file mode 100644
index 0000000..da4fdc9
--- /dev/null
+++ b/chrome/browser/privacy_blacklist/blacklist_test_util.cc
@@ -0,0 +1,76 @@
+// 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_test_util.h"
+
+#include "base/file_path.h"
+#include "base/values.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_constants.h"
+#include "chrome/common/notification_service.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+BlacklistTestingProfile::BlacklistTestingProfile() {
+ EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
+ path_ = temp_dir_.path();
+}
+
+TestBlacklistPathProvider::TestBlacklistPathProvider(Profile* profile)
+ : profile_(profile) {
+}
+
+bool TestBlacklistPathProvider::AreBlacklistPathsReady() const {
+ return true;
+}
+
+std::vector<FilePath> TestBlacklistPathProvider::GetPersistentBlacklistPaths() {
+ return persistent_paths_;
+}
+
+std::vector<FilePath> TestBlacklistPathProvider::GetTransientBlacklistPaths() {
+ return transient_paths_;
+}
+
+void TestBlacklistPathProvider::AddPersistentPath(const FilePath& path) {
+ persistent_paths_.push_back(path);
+ SendUpdateNotification();
+}
+
+void TestBlacklistPathProvider::AddTransientPath(const FilePath& path) {
+ transient_paths_.push_back(path);
+ SendUpdateNotification();
+}
+
+void TestBlacklistPathProvider::clear() {
+ persistent_paths_.clear();
+ transient_paths_.clear();
+ SendUpdateNotification();
+}
+
+void TestBlacklistPathProvider::SendUpdateNotification() {
+ ListValue* privacy_blacklists = new ListValue;
+ privacy_blacklists->Append(new StringValue("dummy.pbl"));
+
+ DictionaryValue manifest;
+ manifest.SetString(extension_manifest_keys::kVersion, "1.0");
+ manifest.SetString(extension_manifest_keys::kName, "test");
+ manifest.Set(extension_manifest_keys::kPrivacyBlacklists,
+ privacy_blacklists);
+
+ // Create an extension with dummy path.
+#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);
+ std::string error;
+ ASSERT_TRUE(extension.InitFromValue(manifest, false, &error));
+ ASSERT_TRUE(error.empty());
+
+ NotificationService::current()->Notify(
+ NotificationType::EXTENSION_LOADED,
+ Source<Profile>(profile_),
+ Details<Extension>(&extension));
+}
diff --git a/chrome/browser/privacy_blacklist/blacklist_test_util.h b/chrome/browser/privacy_blacklist/blacklist_test_util.h
new file mode 100644
index 0000000..1b79c3d
--- /dev/null
+++ b/chrome/browser/privacy_blacklist/blacklist_test_util.h
@@ -0,0 +1,64 @@
+// 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.
+
+#ifndef CHROME_BROWSER_PRIVACY_BLACKLIST_BLACKLIST_TEST_UTIL_H_
+#define CHROME_BROWSER_PRIVACY_BLACKLIST_BLACKLIST_TEST_UTIL_H_
+
+#include <vector>
+
+#include "base/scoped_temp_dir.h"
+#include "chrome/browser/privacy_blacklist/blacklist_manager.h"
+#include "chrome/test/testing_profile.h"
+
+class FilePath;
+
+// Testing profile which uses a temporary directory.
+class BlacklistTestingProfile : public TestingProfile {
+ public:
+ BlacklistTestingProfile();
+
+ BlacklistManager* GetBlacklistManager() { return blacklist_manager_; }
+ void set_blacklist_manager(BlacklistManager* manager) {
+ blacklist_manager_ = manager;
+ }
+
+ private:
+ ScopedTempDir temp_dir_;
+
+ BlacklistManager* blacklist_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(BlacklistTestingProfile);
+};
+
+// Path provider which allows easy updates from the outside and sends
+// notifications for each change.
+class TestBlacklistPathProvider : public BlacklistPathProvider {
+ public:
+ explicit TestBlacklistPathProvider(Profile* profile);
+
+ // BlacklistPathProvider:
+ virtual bool AreBlacklistPathsReady() const;
+ virtual std::vector<FilePath> GetPersistentBlacklistPaths();
+ virtual std::vector<FilePath> GetTransientBlacklistPaths();
+
+ // Adds a path to the provder and sends an update notification.
+ void AddPersistentPath(const FilePath& path);
+ void AddTransientPath(const FilePath& path);
+
+ // Removes all paths from the provider and send an update notification.
+ void clear();
+
+ private:
+ void SendUpdateNotification();
+
+ Profile* profile_;
+
+ // Keep track of added paths.
+ std::vector<FilePath> persistent_paths_;
+ std::vector<FilePath> transient_paths_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestBlacklistPathProvider);
+};
+
+#endif // CHROME_BROWSER_PRIVACY_BLACKLIST_BLACKLIST_TEST_UTIL_H_
diff --git a/chrome/browser/privacy_blacklist/blacklist_ui.cc b/chrome/browser/privacy_blacklist/blacklist_ui.cc
index 6d2327e..846ddb9 100644
--- a/chrome/browser/privacy_blacklist/blacklist_ui.cc
+++ b/chrome/browser/privacy_blacklist/blacklist_ui.cc
@@ -10,6 +10,8 @@
#include "chrome/browser/blocked_popup_container.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/privacy_blacklist/blacklist.h"
+#include "chrome/browser/privacy_blacklist/blacklist_manager.h"
+#include "chrome/browser/privacy_blacklist/blacklist_request_info.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
#include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h"
@@ -19,40 +21,42 @@
// Displays more info why some content has been blocked.
class DisplayBlockedContentNoticeTask : public Task {
public:
- DisplayBlockedContentNoticeTask(const GURL& gurl,
+ DisplayBlockedContentNoticeTask(const GURL& url,
const Blacklist::Match* match,
const ResourceDispatcherHostRequestInfo* info)
- : gurl_(gurl),
- match_(match),
+ : url_(url),
child_id_(info->child_id()),
route_id_(info->route_id()) {
- }
-
- virtual void Run() {
- RenderViewHost* view = RenderViewHost::FromID(child_id_, route_id_);
- if (!view)
- return; // The view may be gone by the time we get here.
-
- string16 reason;
- if (match_->attributes() & Blacklist::kDontStoreCookies) {
+ if (match->attributes() & Blacklist::kDontStoreCookies) {
// No cookies stored.
- reason = l10n_util::GetStringUTF16(IDS_BLACKLIST_BLOCKED_COOKIES);
- } else if (match_->attributes() & Blacklist::kDontSendCookies) {
+ details_ = l10n_util::GetStringUTF16(IDS_BLACKLIST_BLOCKED_COOKIES);
+ } else if (match->attributes() & Blacklist::kDontSendCookies) {
// No cookies sent.
- reason = l10n_util::GetStringUTF16(IDS_BLACKLIST_BLOCKED_COOKIES);
- } else if (match_->attributes() & Blacklist::kDontSendReferrer) {
+ details_ = l10n_util::GetStringUTF16(IDS_BLACKLIST_BLOCKED_COOKIES);
+ } else if (match->attributes() & Blacklist::kDontSendReferrer) {
// No referrer sent.
- reason = l10n_util::GetStringUTF16(IDS_BLACKLIST_BLOCKED_REFERRER);
+ details_ = l10n_util::GetStringUTF16(IDS_BLACKLIST_BLOCKED_REFERRER);
} else {
NOTREACHED();
}
+ }
- view->delegate()->AddBlockedNotice(gurl_, reason);
+ virtual void Run() {
+ RenderViewHost* view = RenderViewHost::FromID(child_id_, route_id_);
+ if (!view)
+ return; // The view may be gone by the time we get here.
+
+ view->delegate()->AddBlockedNotice(url_, details_);
}
private:
- const GURL gurl_;
- const Blacklist::Match* match_;
+ // URL for which we blocked content.
+ const GURL url_;
+
+ // More detailed info what has been blocked.
+ string16 details_;
+
+ // Information that allows us to identify the right tab to display the notice.
const int child_id_;
const int route_id_;
@@ -63,15 +67,17 @@ class DisplayBlockedContentNoticeTask : public Task {
void BlacklistUI::OnNonvisualContentBlocked(const URLRequest* request) {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
- const URLRequest::UserData* d =
- request->GetUserData(&Blacklist::kRequestDataKey);
- const Blacklist::Match* match = static_cast<const Blacklist::Match*>(d);
+ BlacklistRequestInfo* request_info =
+ BlacklistRequestInfo::FromURLRequest(request);
+ const BlacklistManager* blacklist_manager =
+ request_info->GetBlacklistManager();
+ const Blacklist* blacklist = blacklist_manager->GetCompiledBlacklist();
+ scoped_ptr<Blacklist::Match> match(blacklist->findMatch(request->url()));
const ResourceDispatcherHostRequestInfo* info =
ResourceDispatcherHost::InfoForRequest(request);
- const GURL& gurl = request->url();
// Notify the UI that something non-visual has been blocked.
ChromeThread::PostTask(
ChromeThread::UI, FROM_HERE,
- new DisplayBlockedContentNoticeTask(gurl, match, info));
+ new DisplayBlockedContentNoticeTask(request->url(), match.get(), info));
}
diff --git a/chrome/browser/privacy_blacklist/blocked_response.cc b/chrome/browser/privacy_blacklist/blocked_response.cc
deleted file mode 100644
index c0c00a9..0000000
--- a/chrome/browser/privacy_blacklist/blocked_response.cc
+++ /dev/null
@@ -1,104 +0,0 @@
-// 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/blocked_response.h"
-
-#include "app/l10n_util.h"
-#include "app/resource_bundle.h"
-#include "base/logging.h"
-#include "base/string_util.h"
-#include "base/values.h"
-#include "chrome/browser/privacy_blacklist/blacklist.h"
-#include "chrome/common/jstemplate_builder.h"
-#include "chrome/common/url_constants.h"
-#include "grit/browser_resources.h"
-#include "grit/generated_resources.h"
-
-namespace {
-
-unsigned long Hash(std::set<std::string>::iterator i) {
- return (unsigned long)(i.operator->());
-}
-
-std::string Dehash(unsigned long l) {
- return *(std::string*)l;
-}
-
-} // namespace
-
-namespace chrome {
-
-const char kUnblockScheme[] = "chrome-unblock";
-
-const char kBlockScheme[] = "chrome-block";
-
-std::string BlockedResponse::GetHTML(const std::string& url,
- const Blacklist::Match* match) {
- DictionaryValue strings;
- strings.SetString(L"title", l10n_util::GetString(IDS_BLACKLIST_TITLE));
- strings.SetString(L"message", l10n_util::GetString(IDS_BLACKLIST_MESSAGE));
- strings.SetString(L"unblock", l10n_util::GetString(IDS_BLACKLIST_UNBLOCK));
-
- // If kBlockAll is specified, assign blame to such an entry.
- // Otherwise pick the first one.
- const Blacklist::Entry* entry = NULL;
- if (match->attributes() & Blacklist::kBlockAll) {
- for (std::vector<const Blacklist::Entry*>::const_iterator i =
- match->entries().begin(); i != match->entries().end(); ++i) {
- if ((*i)->attributes() == Blacklist::kBlockAll) {
- entry = *i;
- break;
- }
- }
- } else {
- entry = match->entries().front();
- }
- DCHECK(entry);
-
- strings.SetString(L"name", entry->provider()->name());
- strings.SetString(L"url", entry->provider()->url());
- strings.SetString(L"bypass", GetUnblockedURL(url));
-
- const base::StringPiece html =
- ResourceBundle::GetSharedInstance().GetRawDataResource(IDR_BLACKLIST_HTML);
- return jstemplate_builder::GetI18nTemplateHtml(html, &strings);
-}
-
-std::string BlockedResponse::GetImage(const Blacklist::Match*) {
- return ResourceBundle::GetSharedInstance().
- GetDataResource(IDR_BLACKLIST_IMAGE);
-}
-
-std::string BlockedResponse::GetHeaders(const std::string& url) {
- return
- "HTTP/1.1 200 OK\nContent-Type: text/html\nlocation: "
- + GetBlockedURL(url) + "\n" + "Cache-Control: no-store";
-}
-
-std::string BlockedResponse::GetBlockedURL(const std::string& url) {
- return std::string(kBlockScheme) + "://" + url;
-}
-
-std::string BlockedResponse::GetUnblockedURL(const std::string& url) {
- std::set<std::string>::iterator i = blocked_.insert(blocked_.end(), url);
-
- char buf[64];
- base::snprintf(buf, 64, "%s://%lX", kUnblockScheme, Hash(i));
- return buf;
-}
-
-std::string BlockedResponse::GetOriginalURL(const std::string& url) {
- unsigned long l = 0;
-
- // Read the address of the url.
- if (sscanf(url.c_str() + sizeof(kUnblockScheme) + 2, "%lX", &l)) {
- std::size_t p = url.find('/', sizeof(kUnblockScheme) + 2);
- if (p != std::string::npos)
- return Dehash(l) + url.substr(p+1);
- return Dehash(l);
- }
- return chrome::kAboutBlankURL;
-}
-
-} // namespace chrome
diff --git a/chrome/browser/privacy_blacklist/blocked_response.h b/chrome/browser/privacy_blacklist/blocked_response.h
deleted file mode 100644
index 2d38b6e..0000000
--- a/chrome/browser/privacy_blacklist/blocked_response.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// 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.
-
-#ifndef CHROME_BROWSER_PRIVACY_BLACKLIST_BLOCKED_RESPONSE_H_
-#define CHROME_BROWSER_PRIVACY_BLACKLIST_BLOCKED_RESPONSE_H_
-
-#include <string>
-#include <set>
-
-#include "chrome/browser/privacy_blacklist/blacklist.h"
-
-namespace chrome {
-
-extern const char kUnblockScheme[];
-extern const char kBlockScheme[];
-
-// Generate localized responses to replace blacklisted resources.
-// Blacklisted resources such as frames and iframes are replaced
-// by HTML. Non visual resources such as Javascript and CSS are
-// simply be cancelled so there is no blocked response for them.
-
-class BlockedResponse {
- public:
- BlockedResponse() {}
-
- // Returns the HTML document used as substituted content for blacklisted
- // elements.
- std::string GetHTML(const std::string& url, const Blacklist::Match* match);
-
- // Returns the image (as a string because that is what is expected by callers)
- // used as substituted content for blacklisted elements.
- std::string GetImage(const Blacklist::Match* match);
-
- // Returns HTTP headers for a blocked response replacing the given url.
- std::string GetHeaders(const std::string& url);
-
- // Gets the original url of a blocked resource from its blocked url.
- // The input must be a chome-unblock://XXX url. If the unblock url is
- // not found, then about:blank is returned.
- std::string GetOriginalURL(const std::string& url);
-
- private:
- // Returns a chrome-block://XXX link for the given requested URL.
- std::string GetBlockedURL(const std::string& url);
-
- // Returns a chrome-unblock://XXX link for the given chrome-block://YYY url.
- std::string GetUnblockedURL(const std::string& url);
-
- std::set<std::string> blocked_;
-
- DISALLOW_COPY_AND_ASSIGN(BlockedResponse);
-};
-
-}
-
-#endif // CHROME_BROWSER_PRIVACY_BLACKLIST_BLOCKED_RESPONSE_H_