// Copyright (c) 2012 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 "base/bind.h" #include "base/bind_helpers.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/safe_browsing/malware_details.h" #include "chrome/common/chrome_notification_types.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_source.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" using content::BrowserThread; MalwareDetailsRedirectsCollector::MalwareDetailsRedirectsCollector( Profile* profile) : profile_(profile), has_started_(false) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); if (profile) { registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, content::Source(profile)); } } void MalwareDetailsRedirectsCollector::StartHistoryCollection( const std::vector& urls, const base::Closure& callback) { DVLOG(1) << "Num of urls to check in history service: " << urls.size(); has_started_ = true; callback_ = callback; if (urls.size() == 0) { AllDone(); return; } BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind(&MalwareDetailsRedirectsCollector::StartGetRedirects, this, urls)); } bool MalwareDetailsRedirectsCollector::HasStarted() const { return has_started_; } const std::vector& MalwareDetailsRedirectsCollector::GetCollectedUrls() const { return redirects_urls_; } void MalwareDetailsRedirectsCollector::Observe( int type, const content::NotificationSource& source, const content::NotificationDetails& details) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK_EQ(type, chrome::NOTIFICATION_PROFILE_DESTROYED); DVLOG(1) << "Profile gone."; profile_ = NULL; } MalwareDetailsRedirectsCollector::~MalwareDetailsRedirectsCollector() {} void MalwareDetailsRedirectsCollector::StartGetRedirects( const std::vector& urls) { // History access from profile needs to happen in UI thread DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 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)); if (!profile_) { AllDone(); return; } HistoryService* history = HistoryServiceFactory::GetForProfile( profile_, Profile::EXPLICIT_ACCESS); if (!history) { AllDone(); return; } history->QueryRedirectsTo( url, &request_consumer_, base::Bind(&MalwareDetailsRedirectsCollector::OnGotQueryRedirectsTo, base::Unretained(this))); } void MalwareDetailsRedirectsCollector::OnGotQueryRedirectsTo( HistoryService::Handle handle, GURL url, bool success, history::RedirectList* redirect_list) { if (success && redirect_list->size() > 0) { std::vector 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_); } void MalwareDetailsRedirectsCollector::AllDone() { DVLOG(1) << "AllDone"; BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, callback_); callback_.Reset(); }