1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 // 5 // Implementation of the MalwareDetailsRedirectsCollector class. 6 7 #include "chrome/browser/safe_browsing/malware_details_history.h" 8 9 #include "base/bind.h" 10 #include "base/bind_helpers.h" 11 #include "chrome/browser/chrome_notification_types.h" 12 #include "chrome/browser/history/history_service_factory.h" 13 #include "chrome/browser/profiles/profile.h" 14 #include "chrome/browser/safe_browsing/malware_details.h" 15 #include "content/public/browser/browser_thread.h" 16 #include "content/public/browser/notification_details.h" 17 #include "content/public/browser/notification_source.h" 18 #include "content/public/browser/render_view_host.h" 19 #include "content/public/browser/web_contents.h" 20 21 using content::BrowserThread; 22 23 MalwareDetailsRedirectsCollector::MalwareDetailsRedirectsCollector( 24 Profile* profile) 25 : profile_(profile), 26 has_started_(false) { 27 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 28 if (profile) { 29 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, 30 content::Source<Profile>(profile)); 31 } 32 } 33 34 void MalwareDetailsRedirectsCollector::StartHistoryCollection( 35 const std::vector<GURL>& urls, 36 const base::Closure& callback) { 37 DVLOG(1) << "Num of urls to check in history service: " << urls.size(); 38 has_started_ = true; 39 callback_ = callback; 40 41 if (urls.size() == 0) { 42 AllDone(); 43 return; 44 } 45 46 BrowserThread::PostTask( 47 BrowserThread::UI, FROM_HERE, 48 base::Bind(&MalwareDetailsRedirectsCollector::StartGetRedirects, 49 this, urls)); 50 } 51 52 bool MalwareDetailsRedirectsCollector::HasStarted() const { 53 return has_started_; 54 } 55 56 const std::vector<safe_browsing::RedirectChain>& 57 MalwareDetailsRedirectsCollector::GetCollectedUrls() const { 58 return redirects_urls_; 59 } 60 61 void MalwareDetailsRedirectsCollector::Observe( 62 int type, 63 const content::NotificationSource& source, 64 const content::NotificationDetails& details) { 65 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 66 DCHECK_EQ(type, chrome::NOTIFICATION_PROFILE_DESTROYED); 67 DVLOG(1) << "Profile gone."; 68 profile_ = NULL; 69 } 70 71 MalwareDetailsRedirectsCollector::~MalwareDetailsRedirectsCollector() {} 72 73 void MalwareDetailsRedirectsCollector::StartGetRedirects( 74 const std::vector<GURL>& urls) { 75 // History access from profile needs to happen in UI thread 76 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 77 for (size_t i = 0; i < urls.size(); ++i) { 78 urls_.push_back(urls[i]); 79 } 80 urls_it_ = urls_.begin(); 81 GetRedirects(*urls_it_); 82 } 83 84 void MalwareDetailsRedirectsCollector::GetRedirects(const GURL& url) { 85 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 86 if (!profile_) { 87 AllDone(); 88 return; 89 } 90 91 HistoryService* history = HistoryServiceFactory::GetForProfile( 92 profile_, Profile::EXPLICIT_ACCESS); 93 if (!history) { 94 AllDone(); 95 return; 96 } 97 98 history->QueryRedirectsTo( 99 url, 100 &request_consumer_, 101 base::Bind(&MalwareDetailsRedirectsCollector::OnGotQueryRedirectsTo, 102 base::Unretained(this))); 103 } 104 105 void MalwareDetailsRedirectsCollector::OnGotQueryRedirectsTo( 106 HistoryService::Handle handle, 107 GURL url, 108 bool success, 109 history::RedirectList* redirect_list) { 110 111 if (success && redirect_list->size() > 0) { 112 std::vector<GURL> urllist; 113 urllist.push_back(url); 114 for (size_t i = 0; i < redirect_list->size(); i++) { 115 urllist.push_back(redirect_list->at(i)); 116 } 117 redirects_urls_.push_back(urllist); 118 } 119 120 // Proceed to next url 121 ++urls_it_; 122 123 if (urls_it_ == urls_.end()) { 124 AllDone(); 125 return; 126 } 127 128 GetRedirects(*urls_it_); 129 } 130 131 void MalwareDetailsRedirectsCollector::AllDone() { 132 DVLOG(1) << "AllDone"; 133 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, callback_); 134 callback_.Reset(); 135 } 136