Commit db9b9ef4 authored by kewang@google.com's avatar kewang@google.com

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
parent 03616dda
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "chrome/browser/net/chrome_url_request_context.h" #include "chrome/browser/net/chrome_url_request_context.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/safe_browsing/malware_details_cache.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/report.pb.h"
#include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h"
#include "chrome/common/safe_browsing/safebrowsing_messages.h" #include "chrome/common/safe_browsing/safebrowsing_messages.h"
...@@ -76,7 +77,8 @@ MalwareDetails::MalwareDetails( ...@@ -76,7 +77,8 @@ MalwareDetails::MalwareDetails(
request_context_getter_(tab_contents->profile()->GetRequestContext()), request_context_getter_(tab_contents->profile()->GetRequestContext()),
sb_service_(sb_service), sb_service_(sb_service),
resource_(resource), resource_(resource),
cache_collector_(new MalwareDetailsCacheCollector) { cache_collector_(new MalwareDetailsCacheCollector),
redirects_collector_(new MalwareDetailsRedirectsCollector) {
StartCollection(); StartCollection();
} }
...@@ -224,6 +226,11 @@ void MalwareDetails::AddDOMDetails( ...@@ -224,6 +226,11 @@ void MalwareDetails::AddDOMDetails(
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DVLOG(1) << "Nodes from the DOM: " << params.size(); 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 // If we have already started collecting data from the HTTP cache, don't
// modify our state. // modify our state.
if (cache_collector_->HasStarted()) if (cache_collector_->HasStarted())
...@@ -246,6 +253,25 @@ void MalwareDetails::AddDOMDetails( ...@@ -246,6 +253,25 @@ void MalwareDetails::AddDOMDetails(
void MalwareDetails::FinishCollection() { void MalwareDetails::FinishCollection() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 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( cache_collector_->StartCacheCollection(
request_context_getter_, request_context_getter_,
&resources_, &resources_,
...@@ -253,6 +279,13 @@ void MalwareDetails::FinishCollection() { ...@@ -253,6 +279,13 @@ void MalwareDetails::FinishCollection() {
NewRunnableMethod(this, &MalwareDetails::OnCacheCollectionReady)); 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() { void MalwareDetails::OnCacheCollectionReady() {
DVLOG(1) << "OnCacheCollectionReady."; DVLOG(1) << "OnCacheCollectionReady.";
// Add all the urls in our |resources_| maps to the |report_| protocol buffer. // Add all the urls in our |resources_| maps to the |report_| protocol buffer.
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "chrome/browser/safe_browsing/report.pb.h" #include "chrome/browser/safe_browsing/report.pb.h"
#include "chrome/browser/safe_browsing/safe_browsing_service.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 "content/browser/tab_contents/tab_contents_observer.h"
#include "net/base/completion_callback.h" #include "net/base/completion_callback.h"
...@@ -28,6 +29,7 @@ class TabContents; ...@@ -28,6 +29,7 @@ class TabContents;
struct SafeBrowsingHostMsg_MalwareDOMDetails_Node; struct SafeBrowsingHostMsg_MalwareDOMDetails_Node;
class MalwareDetailsCacheCollector; class MalwareDetailsCacheCollector;
class MalwareDetailsRedirectsCollector;
class MalwareDetailsFactory; class MalwareDetailsFactory;
namespace safe_browsing { namespace safe_browsing {
...@@ -54,12 +56,15 @@ class MalwareDetails : public base::RefCountedThreadSafe<MalwareDetails>, ...@@ -54,12 +56,15 @@ class MalwareDetails : public base::RefCountedThreadSafe<MalwareDetails>,
// The SafeBrowsingBlockingPage calls this from the IO thread when // The SafeBrowsingBlockingPage calls this from the IO thread when
// the user is leaving the blocking page and has opted-in to sending // 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, // the report. We start the redirection urls collection from history service
// we send the report. // in UI thread; then do cache collection back in IO thread.
// When we are done, we send the report.
void FinishCollection(); void FinishCollection();
void OnCacheCollectionReady(); void OnCacheCollectionReady();
void OnRedirectionCollectionReady();
// TabContentsObserver implementation. // TabContentsObserver implementation.
virtual bool OnMessageReceived(const IPC::Message& message); virtual bool OnMessageReceived(const IPC::Message& message);
...@@ -108,6 +113,8 @@ class MalwareDetails : public base::RefCountedThreadSafe<MalwareDetails>, ...@@ -108,6 +113,8 @@ class MalwareDetails : public base::RefCountedThreadSafe<MalwareDetails>,
void OnReceivedMalwareDOMDetails( void OnReceivedMalwareDOMDetails(
const std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node>& params); const std::vector<SafeBrowsingHostMsg_MalwareDOMDetails_Node>& params);
void AddRedirectUrlList(const std::vector<GURL>& urls);
scoped_refptr<SafeBrowsingService> sb_service_; scoped_refptr<SafeBrowsingService> sb_service_;
const SafeBrowsingService::UnsafeResource resource_; const SafeBrowsingService::UnsafeResource resource_;
...@@ -127,9 +134,13 @@ class MalwareDetails : public base::RefCountedThreadSafe<MalwareDetails>, ...@@ -127,9 +134,13 @@ class MalwareDetails : public base::RefCountedThreadSafe<MalwareDetails>,
// Used to collect details from the HTTP Cache. // Used to collect details from the HTTP Cache.
scoped_refptr<MalwareDetailsCacheCollector> cache_collector_; 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, MalwareDOMDetails);
FRIEND_TEST_ALL_PREFIXES(MalwareDetailsTest, HTTPCache); FRIEND_TEST_ALL_PREFIXES(MalwareDetailsTest, HTTPCache);
FRIEND_TEST_ALL_PREFIXES(MalwareDetailsTest, HTTPCacheNoEntries); FRIEND_TEST_ALL_PREFIXES(MalwareDetailsTest, HTTPCacheNoEntries);
FRIEND_TEST_ALL_PREFIXES(MalwareDetailsTest, HistoryServiceUrls);
DISALLOW_COPY_AND_ASSIGN(MalwareDetails); DISALLOW_COPY_AND_ASSIGN(MalwareDetails);
}; };
......
// 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;
}
// 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_
...@@ -6,8 +6,11 @@ ...@@ -6,8 +6,11 @@
#include "base/pickle.h" #include "base/pickle.h"
#include "base/time.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/profiles/profile.h"
#include "chrome/browser/safe_browsing/malware_details.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/browser/safe_browsing/report.pb.h"
#include "chrome/common/render_messages.h" #include "chrome/common/render_messages.h"
#include "chrome/common/safe_browsing/safebrowsing_messages.h" #include "chrome/common/safe_browsing/safebrowsing_messages.h"
...@@ -176,10 +179,13 @@ class MalwareDetailsTest : public RenderViewHostTestHarness { ...@@ -176,10 +179,13 @@ class MalwareDetailsTest : public RenderViewHostTestHarness {
// The URLFetcher checks that the messageloop type is IO. // The URLFetcher checks that the messageloop type is IO.
ASSERT_TRUE(io_thread_.StartWithOptions( ASSERT_TRUE(io_thread_.StartWithOptions(
base::Thread::Options(MessageLoop::TYPE_IO, 0))); base::Thread::Options(MessageLoop::TYPE_IO, 0)));
profile_->CreateHistoryService(true /* delete_file */, false /* no_db */);
} }
virtual void TearDown() { virtual void TearDown() {
io_thread_.Stop(); io_thread_.Stop();
profile_->DestroyHistoryService();
RenderViewHostTestHarness::TearDown(); RenderViewHostTestHarness::TearDown();
} }
...@@ -201,6 +207,10 @@ class MalwareDetailsTest : public RenderViewHostTestHarness { ...@@ -201,6 +207,10 @@ class MalwareDetailsTest : public RenderViewHostTestHarness {
return sb_service_->GetSerialized(); return sb_service_->GetSerialized();
} }
HistoryService* history_service() {
return profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
}
protected: protected:
void InitResource(SafeBrowsingService::UnsafeResource* resource, void InitResource(SafeBrowsingService::UnsafeResource* resource,
ResourceType::Type resource_type, ResourceType::Type resource_type,
...@@ -283,6 +293,18 @@ class MalwareDetailsTest : public RenderViewHostTestHarness { ...@@ -283,6 +293,18 @@ class MalwareDetailsTest : public RenderViewHostTestHarness {
resource->response().remote_ip()); 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 ui_thread_;
BrowserThread io_thread_; BrowserThread io_thread_;
scoped_refptr<MockSafeBrowsingService> sb_service_; scoped_refptr<MockSafeBrowsingService> sb_service_;
...@@ -603,3 +625,60 @@ TEST_F(MalwareDetailsTest, HTTPCacheNoEntries) { ...@@ -603,3 +625,60 @@ TEST_F(MalwareDetailsTest, HTTPCacheNoEntries) {
VerifyResults(actual, expected); 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);
}
...@@ -1776,6 +1776,8 @@ ...@@ -1776,6 +1776,8 @@
'browser/safe_browsing/malware_details.h', 'browser/safe_browsing/malware_details.h',
'browser/safe_browsing/malware_details_cache.cc', 'browser/safe_browsing/malware_details_cache.cc',
'browser/safe_browsing/malware_details_cache.h', 'browser/safe_browsing/malware_details_cache.h',
'browser/safe_browsing/malware_details_history.cc',
'browser/safe_browsing/malware_details_history.h',
'browser/safe_browsing/prefix_set.cc', 'browser/safe_browsing/prefix_set.cc',
'browser/safe_browsing/prefix_set.h', 'browser/safe_browsing/prefix_set.h',
'browser/safe_browsing/protocol_manager.cc', 'browser/safe_browsing/protocol_manager.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment