summaryrefslogtreecommitdiffstats
path: root/chrome/browser/safe_browsing
diff options
context:
space:
mode:
authorkewang@google.com <kewang@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-24 06:46:43 +0000
committerkewang@google.com <kewang@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-24 06:46:43 +0000
commitdb9b9ef42d41951c20e135b7076fb72c9869e35f (patch)
tree29072ab2e2f4fd7b60060ec625b8ce88cc61a41d /chrome/browser/safe_browsing
parent03616ddad3438ddde91cbc2c405444346fb341f3 (diff)
downloadchromium_src-db9b9ef42d41951c20e135b7076fb72c9869e35f.zip
chromium_src-db9b9ef42d41951c20e135b7076fb72c9869e35f.tar.gz
chromium_src-db9b9ef42d41951c20e135b7076fb72c9869e35f.tar.bz2
Querying the history service to get the redirect information for urls.
Bug=60831 TEST=unit_tests Review URL: http://codereview.chromium.org/6710004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@86401 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/safe_browsing')
-rw-r--r--chrome/browser/safe_browsing/malware_details.cc35
-rw-r--r--chrome/browser/safe_browsing/malware_details.h15
-rw-r--r--chrome/browser/safe_browsing/malware_details_history.cc121
-rw-r--r--chrome/browser/safe_browsing/malware_details_history.h82
-rw-r--r--chrome/browser/safe_browsing/malware_details_unittest.cc79
5 files changed, 329 insertions, 3 deletions
diff --git a/chrome/browser/safe_browsing/malware_details.cc b/chrome/browser/safe_browsing/malware_details.cc
index 63d3f3a..bc35cec 100644
--- a/chrome/browser/safe_browsing/malware_details.cc
+++ b/chrome/browser/safe_browsing/malware_details.cc
@@ -11,6 +11,7 @@
#include "chrome/browser/net/chrome_url_request_context.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/safe_browsing/malware_details_cache.h"
+#include "chrome/browser/safe_browsing/malware_details_history.h"
#include "chrome/browser/safe_browsing/report.pb.h"
#include "chrome/browser/safe_browsing/safe_browsing_service.h"
#include "chrome/common/safe_browsing/safebrowsing_messages.h"
@@ -76,7 +77,8 @@ MalwareDetails::MalwareDetails(
request_context_getter_(tab_contents->profile()->GetRequestContext()),
sb_service_(sb_service),
resource_(resource),
- cache_collector_(new MalwareDetailsCacheCollector) {
+ cache_collector_(new MalwareDetailsCacheCollector),
+ redirects_collector_(new MalwareDetailsRedirectsCollector) {
StartCollection();
}
@@ -224,6 +226,11 @@ void MalwareDetails::AddDOMDetails(
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DVLOG(1) << "Nodes from the DOM: " << params.size();
+ // If we have already started getting redirects from history service,
+ // don't modify state, otherwise will invalidate the iterators.
+ if (redirects_collector_->HasStarted())
+ return;
+
// If we have already started collecting data from the HTTP cache, don't
// modify our state.
if (cache_collector_->HasStarted())
@@ -246,6 +253,25 @@ void MalwareDetails::AddDOMDetails(
void MalwareDetails::FinishCollection() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ std::vector<GURL> urls;
+ for (safe_browsing::ResourceMap::const_iterator it = resources_.begin();
+ it != resources_.end(); it++) {
+ urls.push_back(GURL(it->first));
+ }
+ redirects_collector_->StartHistoryCollection(
+ urls, tab_contents(),
+ NewRunnableMethod(this, &MalwareDetails::OnRedirectionCollectionReady));
+}
+
+void MalwareDetails::OnRedirectionCollectionReady() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ const std::vector<safe_browsing::RedirectChain>& redirects =
+ redirects_collector_->GetCollectedUrls();
+
+ for (size_t i = 0; i < redirects.size(); ++i)
+ AddRedirectUrlList(redirects[i]);
+
+ // Call the cache collector
cache_collector_->StartCacheCollection(
request_context_getter_,
&resources_,
@@ -253,6 +279,13 @@ void MalwareDetails::FinishCollection() {
NewRunnableMethod(this, &MalwareDetails::OnCacheCollectionReady));
}
+void MalwareDetails::AddRedirectUrlList(const std::vector<GURL>& urls) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ for (size_t i = 0; i < urls.size()-1; ++i) {
+ AddUrl(urls[i], urls[i+1], "", NULL);
+ }
+}
+
void MalwareDetails::OnCacheCollectionReady() {
DVLOG(1) << "OnCacheCollectionReady.";
// Add all the urls in our |resources_| maps to the |report_| protocol buffer.
diff --git a/chrome/browser/safe_browsing/malware_details.h b/chrome/browser/safe_browsing/malware_details.h
index 494837e..473eab8 100644
--- a/chrome/browser/safe_browsing/malware_details.h
+++ b/chrome/browser/safe_browsing/malware_details.h
@@ -21,6 +21,7 @@
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/safe_browsing/report.pb.h"
#include "chrome/browser/safe_browsing/safe_browsing_service.h"
+#include "content/browser/browser_thread.h"
#include "content/browser/tab_contents/tab_contents_observer.h"
#include "net/base/completion_callback.h"
@@ -28,6 +29,7 @@ class TabContents;
struct SafeBrowsingHostMsg_MalwareDOMDetails_Node;
class MalwareDetailsCacheCollector;
+class MalwareDetailsRedirectsCollector;
class MalwareDetailsFactory;
namespace safe_browsing {
@@ -54,12 +56,15 @@ class MalwareDetails : public base::RefCountedThreadSafe<MalwareDetails>,
// The SafeBrowsingBlockingPage calls this from the IO thread when
// the user is leaving the blocking page and has opted-in to sending
- // the report. We start the cache collection, and when we are done,
- // we send the report.
+ // the report. We start the redirection urls collection from history service
+ // in UI thread; then do cache collection back in IO thread.
+ // When we are done, we send the report.
void FinishCollection();
void OnCacheCollectionReady();
+ void OnRedirectionCollectionReady();
+
// TabContentsObserver implementation.
virtual bool OnMessageReceived(const IPC::Message& message);
@@ -108,6 +113,8 @@ class MalwareDetails : public base::RefCountedThreadSafe<MalwareDetails>,
void OnReceivedMalwareDOMDetails(
const std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node>& params);
+ void AddRedirectUrlList(const std::vector<GURL>& urls);
+
scoped_refptr<SafeBrowsingService> sb_service_;
const SafeBrowsingService::UnsafeResource resource_;
@@ -127,9 +134,13 @@ class MalwareDetails : public base::RefCountedThreadSafe<MalwareDetails>,
// Used to collect details from the HTTP Cache.
scoped_refptr<MalwareDetailsCacheCollector> cache_collector_;
+ // Used to collect redirect urls from the history service
+ scoped_refptr<MalwareDetailsRedirectsCollector> redirects_collector_;
+
FRIEND_TEST_ALL_PREFIXES(MalwareDetailsTest, MalwareDOMDetails);
FRIEND_TEST_ALL_PREFIXES(MalwareDetailsTest, HTTPCache);
FRIEND_TEST_ALL_PREFIXES(MalwareDetailsTest, HTTPCacheNoEntries);
+ FRIEND_TEST_ALL_PREFIXES(MalwareDetailsTest, HistoryServiceUrls);
DISALLOW_COPY_AND_ASSIGN(MalwareDetails);
};
diff --git a/chrome/browser/safe_browsing/malware_details_history.cc b/chrome/browser/safe_browsing/malware_details_history.cc
new file mode 100644
index 0000000..e28c729
--- /dev/null
+++ b/chrome/browser/safe_browsing/malware_details_history.cc
@@ -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.
+//
+// Implementation of the MalwareDetailsRedirectsCollector class.
+
+#include "chrome/browser/safe_browsing/malware_details_history.h"
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/safe_browsing/malware_details.h"
+#include "content/browser/browser_thread.h"
+#include "content/browser/renderer_host/render_view_host.h"
+#include "content/browser/tab_contents/navigation_entry.h"
+#include "content/browser/tab_contents/tab_contents.h"
+
+
+MalwareDetailsRedirectsCollector::MalwareDetailsRedirectsCollector()
+ : history_(NULL),
+ has_started_(false) {
+}
+
+MalwareDetailsRedirectsCollector::~MalwareDetailsRedirectsCollector() {
+}
+
+void MalwareDetailsRedirectsCollector::StartHistoryCollection(
+ const std::vector<GURL>& urls,
+ TabContents* tab_contents,
+ Task* callback) {
+ DVLOG(1) << "Num of urls to check in history service: " << urls.size();
+ tab_contents_ = tab_contents;
+ has_started_ = true;
+ callback_ = callback;
+
+ if (urls.size() == 0) {
+ AllDone();
+ return;
+ }
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(
+ this, &MalwareDetailsRedirectsCollector::StartGetRedirects, urls));
+}
+
+void MalwareDetailsRedirectsCollector::StartGetRedirects(
+ const std::vector<GURL>& urls) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ // History access from profile needs to happen in UI thread
+ if (history_ == NULL) {
+ DVLOG(1) << "Getting access to history service";
+ history_ = tab_contents_->profile()->GetHistoryService(
+ Profile::EXPLICIT_ACCESS);
+ }
+
+ if (history_ == NULL) {
+ DVLOG(1) << "Could not access history service.";
+ AllDone();
+ return;
+ }
+
+ for (size_t i = 0; i < urls.size(); ++i)
+ urls_.push_back(urls[i]);
+
+ urls_it_ = urls_.begin();
+ GetRedirects(*urls_it_);
+}
+
+void MalwareDetailsRedirectsCollector::GetRedirects(const GURL& url) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ history_->QueryRedirectsTo(
+ url,
+ &request_consumer_,
+ NewCallback(this,
+ &MalwareDetailsRedirectsCollector::OnGotQueryRedirectsTo));
+}
+
+void MalwareDetailsRedirectsCollector::OnGotQueryRedirectsTo(
+ HistoryService::Handle handle,
+ GURL url,
+ bool success,
+ history::RedirectList* redirect_list) {
+
+ if (success && redirect_list->size() > 0) {
+ std::vector<GURL> urllist;
+ urllist.push_back(url);
+ for (size_t i = 0; i < redirect_list->size(); i++) {
+ urllist.push_back(redirect_list->at(i));
+ }
+ redirects_urls_.push_back(urllist);
+ }
+
+ // Proceed to next url
+ ++urls_it_;
+
+ if (urls_it_ == urls_.end()) {
+ AllDone();
+ return;
+ }
+
+ GetRedirects(*urls_it_);
+}
+
+bool MalwareDetailsRedirectsCollector::HasStarted() const {
+ return has_started_;
+}
+
+void MalwareDetailsRedirectsCollector::AllDone() {
+ DVLOG(1) << "AllDone";
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, callback_);
+}
+
+const std::vector<safe_browsing::RedirectChain>&
+MalwareDetailsRedirectsCollector::GetCollectedUrls() const {
+ return redirects_urls_;
+}
+
+void MalwareDetailsRedirectsCollector::SetHistory(HistoryService* history) {
+ history_ = history;
+}
diff --git a/chrome/browser/safe_browsing/malware_details_history.h b/chrome/browser/safe_browsing/malware_details_history.h
new file mode 100644
index 0000000..23a2571
--- /dev/null
+++ b/chrome/browser/safe_browsing/malware_details_history.h
@@ -0,0 +1,82 @@
+// 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_SAFE_BROWSING_MALWARE_DETAILS_HISTORY_H_
+#define CHROME_BROWSER_SAFE_BROWSING_MALWARE_DETAILS_HISTORY_H_
+#pragma once
+
+// This class gets redirect chain for urls from the history service.
+
+#include <string>
+#include <vector>
+
+#include "base/hash_tables.h"
+#include "base/memory/linked_ptr.h"
+#include "base/memory/ref_counted.h"
+#include "chrome/browser/history/history.h"
+#include "net/base/completion_callback.h"
+
+class TabContents;
+
+namespace safe_browsing {
+typedef std::vector<GURL> RedirectChain;
+}
+
+class MalwareDetailsRedirectsCollector
+ : public base::RefCountedThreadSafe<MalwareDetailsRedirectsCollector> {
+
+ public:
+ MalwareDetailsRedirectsCollector();
+ virtual ~MalwareDetailsRedirectsCollector();
+
+ // Collects urls' redirects chain information from the history service.
+ // We get access to history service via tab_contents in UI thread.
+ // Notice the callback will be posted to the IO thread.
+ void StartHistoryCollection(const std::vector<GURL>& urls,
+ TabContents* tab_contents,
+ Task* callback);
+
+ // Returns whether or not StartCacheCollection has been called.
+ bool HasStarted() const;
+
+ // Returns the redirect urls we get from history service
+ const std::vector<safe_browsing::RedirectChain>& GetCollectedUrls() const;
+
+ // Sets the pointer to the history service. Use it in unittest.
+ void SetHistory(HistoryService* history);
+
+ private:
+ TabContents* tab_contents_;
+ HistoryService* history_;
+ CancelableRequestConsumer request_consumer_;
+
+ // Method we call when we are done. The caller must be alive for the
+ // whole time, we are modifying its state (see above).
+ Task* callback_;
+
+ // Sets to true once StartHistoryCollection is called
+ bool has_started_;
+
+ // The urls we need to get redirects for
+ std::vector<GURL> urls_;
+ // The iterator goes over urls_
+ std::vector<GURL>::iterator urls_it_;
+ // The collected directs from history service
+ std::vector<safe_browsing::RedirectChain> redirects_urls_;
+
+ void StartGetRedirects(const std::vector<GURL>& urls);
+ void GetRedirects(const GURL& url);
+ void OnGotQueryRedirectsTo(HistoryService::Handle handle,
+ GURL url,
+ bool success,
+ history::RedirectList* redirect_list);
+
+ // Posts the callback method back to IO thread when redirects collecting
+ // is all done.
+ void AllDone();
+
+ DISALLOW_COPY_AND_ASSIGN(MalwareDetailsRedirectsCollector);
+};
+
+#endif // CHROME_BROWSER_SAFE_BROWSING_MALWARE_DETAILS_HISTORY_H_
diff --git a/chrome/browser/safe_browsing/malware_details_unittest.cc b/chrome/browser/safe_browsing/malware_details_unittest.cc
index 73ccfdd..60a65f8 100644
--- a/chrome/browser/safe_browsing/malware_details_unittest.cc
+++ b/chrome/browser/safe_browsing/malware_details_unittest.cc
@@ -6,8 +6,11 @@
#include "base/pickle.h"
#include "base/time.h"
+#include "chrome/browser/history/history.h"
+#include "chrome/browser/history/history_backend.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/safe_browsing/malware_details.h"
+#include "chrome/browser/safe_browsing/malware_details_history.h"
#include "chrome/browser/safe_browsing/report.pb.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/safe_browsing/safebrowsing_messages.h"
@@ -176,10 +179,13 @@ class MalwareDetailsTest : public RenderViewHostTestHarness {
// The URLFetcher checks that the messageloop type is IO.
ASSERT_TRUE(io_thread_.StartWithOptions(
base::Thread::Options(MessageLoop::TYPE_IO, 0)));
+
+ profile_->CreateHistoryService(true /* delete_file */, false /* no_db */);
}
virtual void TearDown() {
io_thread_.Stop();
+ profile_->DestroyHistoryService();
RenderViewHostTestHarness::TearDown();
}
@@ -201,6 +207,10 @@ class MalwareDetailsTest : public RenderViewHostTestHarness {
return sb_service_->GetSerialized();
}
+ HistoryService* history_service() {
+ return profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
+ }
+
protected:
void InitResource(SafeBrowsingService::UnsafeResource* resource,
ResourceType::Type resource_type,
@@ -283,6 +293,18 @@ class MalwareDetailsTest : public RenderViewHostTestHarness {
resource->response().remote_ip());
}
+ // Adds a page to history.
+ // The redirects is the redirect url chain leading to the url.
+ void AddPageToHistory(const GURL& url,
+ history::RedirectList* redirects) {
+ // The last item of the redirect chain has to be the final url when adding
+ // to history backend.
+ redirects->push_back(url);
+ history_service()->AddPage(
+ url, static_cast<void*>(this), 0, GURL(), PageTransition::TYPED,
+ *redirects, history::SOURCE_BROWSED, false);
+ }
+
BrowserThread ui_thread_;
BrowserThread io_thread_;
scoped_refptr<MockSafeBrowsingService> sb_service_;
@@ -603,3 +625,60 @@ TEST_F(MalwareDetailsTest, HTTPCacheNoEntries) {
VerifyResults(actual, expected);
}
+
+// Test getting redirects from history service.
+TEST_F(MalwareDetailsTest, HistoryServiceUrls) {
+ // Add content to history service.
+ // There are two redirect urls before reacing malware url:
+ // kFirstRedirectURL -> kSecondRedirectURL -> kMalwareURL
+ GURL baseurl(kMalwareURL);
+ history::RedirectList redirects;
+ redirects.push_back(GURL(kFirstRedirectURL));
+ redirects.push_back(GURL(kSecondRedirectURL));
+ AddPageToHistory(baseurl, &redirects);
+ // Wait for history service operation finished.
+ profile_->BlockUntilHistoryProcessesPendingRequests();
+
+ controller().LoadURL(GURL(kLandingURL), GURL(), PageTransition::TYPED);
+
+ SafeBrowsingService::UnsafeResource resource;
+ InitResource(&resource, ResourceType::SUB_RESOURCE, GURL(kMalwareURL));
+ scoped_refptr<MalwareDetailsWrap> report = new MalwareDetailsWrap(
+ sb_service_.get(), contents(), resource, NULL);
+
+ // Reset the history service pointer.
+ report->redirects_collector_->SetHistory(history_service());
+
+ // The redirects collection starts after the IPC from the DOM is fired.
+ std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node> params;
+ report->OnReceivedMalwareDOMDetails(params);
+
+ // Let the redirects callbacks complete.
+ MessageLoop::current()->RunAllPending();
+
+ std::string serialized = WaitForSerializedReport(report);
+ ClientMalwareReportRequest actual;
+ actual.ParseFromString(serialized);
+
+ ClientMalwareReportRequest expected;
+ expected.set_malware_url(kMalwareURL);
+ expected.set_page_url(kLandingURL);
+ expected.set_referrer_url("");
+
+ ClientMalwareReportRequest::Resource* pb_resource = expected.add_resources();
+ pb_resource->set_id(0);
+ pb_resource->set_url(kLandingURL);
+ pb_resource = expected.add_resources();
+ pb_resource->set_id(1);
+ pb_resource->set_parent_id(2);
+ pb_resource->set_url(kMalwareURL);
+ pb_resource = expected.add_resources();
+ pb_resource->set_id(2);
+ pb_resource->set_parent_id(3);
+ pb_resource->set_url(kSecondRedirectURL);
+ pb_resource = expected.add_resources();
+ pb_resource->set_id(3);
+ pb_resource->set_url(kFirstRedirectURL);
+
+ VerifyResults(actual, expected);
+}