Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(148)

Side by Side Diff: chrome/browser/safe_browsing/client_side_detection_host.cc

Issue 173133004: Separate pre-classification checks for client-side malware and phishing (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Set right enum type for boolean histograms. Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/safe_browsing/client_side_detection_host.h" 5 #include "chrome/browser/safe_browsing/client_side_detection_host.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/memory/ref_counted.h" 10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h" 11 #include "base/memory/scoped_ptr.h"
12 #include "base/metrics/histogram.h" 12 #include "base/metrics/histogram.h"
13 #include "base/prefs/pref_service.h" 13 #include "base/prefs/pref_service.h"
14 #include "base/sequenced_task_runner_helpers.h" 14 #include "base/sequenced_task_runner_helpers.h"
15 #include "base/strings/utf_string_conversions.h" 15 #include "base/strings/utf_string_conversions.h"
16 #include "chrome/browser/browser_process.h" 16 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/profiles/profile.h" 17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/safe_browsing/browser_feature_extractor.h" 18 #include "chrome/browser/safe_browsing/browser_feature_extractor.h"
19 #include "chrome/browser/safe_browsing/client_side_detection_service.h" 19 #include "chrome/browser/safe_browsing/client_side_detection_service.h"
20 #include "chrome/browser/safe_browsing/database_manager.h" 20 #include "chrome/browser/safe_browsing/database_manager.h"
21 #include "chrome/browser/safe_browsing/safe_browsing_service.h" 21 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
22 #include "chrome/common/chrome_switches.h"
23 #include "chrome/common/chrome_version_info.h"
24 #include "chrome/common/pref_names.h" 22 #include "chrome/common/pref_names.h"
25 #include "chrome/common/safe_browsing/csd.pb.h" 23 #include "chrome/common/safe_browsing/csd.pb.h"
26 #include "chrome/common/safe_browsing/safebrowsing_messages.h" 24 #include "chrome/common/safe_browsing/safebrowsing_messages.h"
27 #include "content/public/browser/browser_thread.h" 25 #include "content/public/browser/browser_thread.h"
28 #include "content/public/browser/navigation_controller.h" 26 #include "content/public/browser/navigation_controller.h"
29 #include "content/public/browser/navigation_details.h" 27 #include "content/public/browser/navigation_details.h"
30 #include "content/public/browser/navigation_entry.h" 28 #include "content/public/browser/navigation_entry.h"
31 #include "content/public/browser/notification_details.h" 29 #include "content/public/browser/notification_details.h"
32 #include "content/public/browser/notification_source.h" 30 #include "content/public/browser/notification_source.h"
33 #include "content/public/browser/notification_types.h" 31 #include "content/public/browser/notification_types.h"
34 #include "content/public/browser/render_process_host.h" 32 #include "content/public/browser/render_process_host.h"
35 #include "content/public/browser/render_view_host.h" 33 #include "content/public/browser/render_view_host.h"
36 #include "content/public/browser/resource_request_details.h" 34 #include "content/public/browser/resource_request_details.h"
37 #include "content/public/browser/web_contents.h" 35 #include "content/public/browser/web_contents.h"
38 #include "content/public/common/frame_navigate_params.h" 36 #include "content/public/common/frame_navigate_params.h"
37 #include "content/public/common/url_constants.h"
39 #include "url/gurl.h" 38 #include "url/gurl.h"
40 39
41 using content::BrowserThread; 40 using content::BrowserThread;
42 using content::NavigationEntry; 41 using content::NavigationEntry;
43 using content::ResourceRequestDetails; 42 using content::ResourceRequestDetails;
44 using content::WebContents; 43 using content::WebContents;
45 44
46 namespace safe_browsing { 45 namespace safe_browsing {
47 46
48 const int ClientSideDetectionHost::kMaxUrlsPerIP = 20; 47 const int ClientSideDetectionHost::kMaxUrlsPerIP = 20;
49 const int ClientSideDetectionHost::kMaxIPsPerBrowse = 200; 48 const int ClientSideDetectionHost::kMaxIPsPerBrowse = 200;
50 49
51 const char kSafeBrowsingMatchKey[] = "safe_browsing_match"; 50 const char kSafeBrowsingMatchKey[] = "safe_browsing_match";
52 51
52 typedef base::Callback<void(bool)> ShouldClassifyUrlCallback;
53
53 // This class is instantiated each time a new toplevel URL loads, and 54 // This class is instantiated each time a new toplevel URL loads, and
54 // asynchronously checks whether the phishing classifier should run for this 55 // asynchronously checks whether the malware and phishing classifiers should run
55 // URL. If so, it notifies the renderer with a StartPhishingDetection IPC. 56 // for this URL. If so, it notifies the host class by calling the provided
56 // Objects of this class are ref-counted and will be destroyed once nobody 57 // callback form the UI thread. Objects of this class are ref-counted and will
57 // uses it anymore. If |web_contents|, |csd_service| or |host| go away you need 58 // be destroyed once nobody uses it anymore. If |web_contents|, |csd_service|
58 // to call Cancel(). We keep the |database_manager| alive in a ref pointer for 59 // or |host| go away you need to call Cancel(). We keep the |database_manager|
59 // as long as it takes. 60 // alive in a ref pointer for as long as it takes.
60 class ClientSideDetectionHost::ShouldClassifyUrlRequest 61 class ClientSideDetectionHost::ShouldClassifyUrlRequest
61 : public base::RefCountedThreadSafe< 62 : public base::RefCountedThreadSafe<
62 ClientSideDetectionHost::ShouldClassifyUrlRequest> { 63 ClientSideDetectionHost::ShouldClassifyUrlRequest> {
63 public: 64 public:
64 ShouldClassifyUrlRequest(const content::FrameNavigateParams& params, 65 ShouldClassifyUrlRequest(
65 WebContents* web_contents, 66 const content::FrameNavigateParams& params,
66 ClientSideDetectionService* csd_service, 67 const ShouldClassifyUrlCallback& start_phishing_classification,
67 SafeBrowsingDatabaseManager* database_manager, 68 const ShouldClassifyUrlCallback& start_malware_classification,
68 ClientSideDetectionHost* host) 69 WebContents* web_contents,
69 : canceled_(false), 70 ClientSideDetectionService* csd_service,
70 params_(params), 71 SafeBrowsingDatabaseManager* database_manager,
72 ClientSideDetectionHost* host)
73 : params_(params),
71 web_contents_(web_contents), 74 web_contents_(web_contents),
72 csd_service_(csd_service), 75 csd_service_(csd_service),
73 database_manager_(database_manager), 76 database_manager_(database_manager),
74 host_(host) { 77 host_(host),
78 start_phishing_classification_cb_(start_phishing_classification),
79 start_malware_classification_cb_(start_malware_classification) {
75 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 80 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
76 DCHECK(web_contents_); 81 DCHECK(web_contents_);
77 DCHECK(csd_service_); 82 DCHECK(csd_service_);
78 DCHECK(database_manager_.get()); 83 DCHECK(database_manager_.get());
79 DCHECK(host_); 84 DCHECK(host_);
80 } 85 }
81 86
82 void Start() { 87 void Start() {
83 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 88 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
84 89
85 // We start by doing some simple checks that can run on the UI thread. 90 // We start by doing some simple checks that can run on the UI thread.
86 UMA_HISTOGRAM_COUNTS("SBClientPhishing.ClassificationStart", 1); 91 UMA_HISTOGRAM_BOOLEAN("SBClientPhishing.ClassificationStart", 1);
92 UMA_HISTOGRAM_BOOLEAN("SBClientMalware.ClassificationStart", 1);
87 93
88 // Only classify [X]HTML documents. 94 // Only classify [X]HTML documents.
89 if (params_.contents_mime_type != "text/html" && 95 if (params_.contents_mime_type != "text/html" &&
90 params_.contents_mime_type != "application/xhtml+xml") { 96 params_.contents_mime_type != "application/xhtml+xml") {
91 VLOG(1) << "Skipping phishing classification for URL: " << params_.url 97 VLOG(1) << "Skipping phishing classification for URL: " << params_.url
92 << " because it has an unsupported MIME type: " 98 << " because it has an unsupported MIME type: "
93 << params_.contents_mime_type; 99 << params_.contents_mime_type;
94 UMA_HISTOGRAM_ENUMERATION("SBClientPhishing.PreClassificationCheckFail", 100 DontClassifyForPhishing(NO_CLASSIFY_UNSUPPORTED_MIME_TYPE);
95 NO_CLASSIFY_UNSUPPORTED_MIME_TYPE,
96 NO_CLASSIFY_MAX);
97 return;
98 } 101 }
99 102
100 if (csd_service_->IsPrivateIPAddress(params_.socket_address.host())) { 103 if (csd_service_->IsPrivateIPAddress(params_.socket_address.host())) {
101 VLOG(1) << "Skipping phishing classification for URL: " << params_.url 104 VLOG(1) << "Skipping phishing classification for URL: " << params_.url
102 << " because of hosting on private IP: " 105 << " because of hosting on private IP: "
103 << params_.socket_address.host(); 106 << params_.socket_address.host();
104 UMA_HISTOGRAM_ENUMERATION("SBClientPhishing.PreClassificationCheckFail", 107 DontClassifyForPhishing(NO_CLASSIFY_PRIVATE_IP);
105 NO_CLASSIFY_PRIVATE_IP, 108 DontClassifyForMalware(NO_CLASSIFY_PRIVATE_IP);
106 NO_CLASSIFY_MAX);
107 return;
108 } 109 }
109 110
110 // Don't run the phishing classifier if the tab is incognito. 111 // For phishing we only classify HTTP pages.
112 if (!params_.url.SchemeIs(content::kHttpScheme)) {
113 VLOG(1) << "Skipping phishing classification for URL: " << params_.url
114 << " because it is not HTTP: "
115 << params_.socket_address.host();
116 DontClassifyForPhishing(NO_CLASSIFY_NOT_HTTP_URL);
117 }
118
119 // Don't run any classifier if the tab is incognito.
111 if (web_contents_->GetBrowserContext()->IsOffTheRecord()) { 120 if (web_contents_->GetBrowserContext()->IsOffTheRecord()) {
112 VLOG(1) << "Skipping phishing classification for URL: " << params_.url 121 VLOG(1) << "Skipping phishing and malware classification for URL: "
113 << " because we're browsing incognito."; 122 << params_.url << " because we're browsing incognito.";
114 UMA_HISTOGRAM_ENUMERATION("SBClientPhishing.PreClassificationCheckFail", 123 DontClassifyForPhishing(NO_CLASSIFY_OFF_THE_RECORD);
115 NO_CLASSIFY_OFF_THE_RECORD, 124 DontClassifyForMalware(NO_CLASSIFY_OFF_THE_RECORD);
116 NO_CLASSIFY_MAX);
117
118 return;
119 } 125 }
120 126
121 // We lookup the csd-whitelist before we lookup the cache because 127 // We lookup the csd-whitelist before we lookup the cache because
122 // a URL may have recently been whitelisted. If the URL matches 128 // a URL may have recently been whitelisted. If the URL matches
123 // the csd-whitelist we won't start classification. The 129 // the csd-whitelist we won't start phishing classification. The
124 // csd-whitelist check has to be done on the IO thread because it 130 // csd-whitelist check has to be done on the IO thread because it
125 // uses the SafeBrowsing service class. 131 // uses the SafeBrowsing service class.
126 BrowserThread::PostTask( 132 if (ShouldClassifyForPhishing() || ShouldClassifyForMalware()) {
127 BrowserThread::IO, 133 BrowserThread::PostTask(
128 FROM_HERE, 134 BrowserThread::IO,
129 base::Bind(&ShouldClassifyUrlRequest::CheckCsdWhitelist, 135 FROM_HERE,
130 this, params_.url)); 136 base::Bind(&ShouldClassifyUrlRequest::CheckSafeBrowsingDatabase,
137 this, params_.url));
138 }
131 } 139 }
132 140
133 void Cancel() { 141 void Cancel() {
134 canceled_ = true; 142 DontClassifyForPhishing(NO_CLASSIFY_CANCEL);
143 DontClassifyForMalware(NO_CLASSIFY_CANCEL);
135 // Just to make sure we don't do anything stupid we reset all these 144 // Just to make sure we don't do anything stupid we reset all these
136 // pointers except for the safebrowsing service class which may be 145 // pointers except for the safebrowsing service class which may be
137 // accessed by CheckCsdWhitelist(). 146 // accessed by CheckSafeBrowsingDatabase().
138 web_contents_ = NULL; 147 web_contents_ = NULL;
139 csd_service_ = NULL; 148 csd_service_ = NULL;
140 host_ = NULL; 149 host_ = NULL;
141 } 150 }
142 151
143 private: 152 private:
144 friend class base::RefCountedThreadSafe< 153 friend class base::RefCountedThreadSafe<
145 ClientSideDetectionHost::ShouldClassifyUrlRequest>; 154 ClientSideDetectionHost::ShouldClassifyUrlRequest>;
146 155
147 // Enum used to keep stats about why the pre-classification check failed. 156 // Enum used to keep stats about why the pre-classification check failed.
148 enum PreClassificationCheckFailures { 157 enum PreClassificationCheckFailures {
149 OBSOLETE_NO_CLASSIFY_PROXY_FETCH, 158 OBSOLETE_NO_CLASSIFY_PROXY_FETCH,
150 NO_CLASSIFY_PRIVATE_IP, 159 NO_CLASSIFY_PRIVATE_IP,
151 NO_CLASSIFY_OFF_THE_RECORD, 160 NO_CLASSIFY_OFF_THE_RECORD,
152 NO_CLASSIFY_MATCH_CSD_WHITELIST, 161 NO_CLASSIFY_MATCH_CSD_WHITELIST,
153 NO_CLASSIFY_TOO_MANY_REPORTS, 162 NO_CLASSIFY_TOO_MANY_REPORTS,
154 NO_CLASSIFY_UNSUPPORTED_MIME_TYPE, 163 NO_CLASSIFY_UNSUPPORTED_MIME_TYPE,
164 NO_CLASSIFY_NO_DATABASE_MANAGER,
165 NO_CLASSIFY_KILLSWITCH,
166 NO_CLASSIFY_CANCEL,
167 NO_CLASSIFY_RESULT_FROM_CACHE,
168 NO_CLASSIFY_NOT_HTTP_URL,
155 169
156 NO_CLASSIFY_MAX // Always add new values before this one. 170 NO_CLASSIFY_MAX // Always add new values before this one.
157 }; 171 };
158 172
159 // The destructor can be called either from the UI or the IO thread. 173 // The destructor can be called either from the UI or the IO thread.
160 virtual ~ShouldClassifyUrlRequest() { } 174 virtual ~ShouldClassifyUrlRequest() { }
161 175
162 void CheckCsdWhitelist(const GURL& url) { 176 bool ShouldClassifyForPhishing() const {
177 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
178 return !start_phishing_classification_cb_.is_null();
179 }
180
181 bool ShouldClassifyForMalware() const {
182 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
183 return !start_malware_classification_cb_.is_null();
184 }
185
186 void DontClassifyForPhishing(PreClassificationCheckFailures reason) {
187 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
188 if (ShouldClassifyForPhishing()) {
189 // Track the first reason why we stopped classifying for phishing.
190 UMA_HISTOGRAM_ENUMERATION("SBClientPhishing.PreClassificationCheckFail",
191 reason, NO_CLASSIFY_MAX);
192 DVLOG(2) << "Failed phishing pre-classification checks. Reason: "
193 << reason;
194 start_phishing_classification_cb_.Run(false);
195 }
196 start_phishing_classification_cb_.Reset();
197 }
198
199 void DontClassifyForMalware(PreClassificationCheckFailures reason) {
200 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
201 if (ShouldClassifyForMalware()) {
202 // Track the first reason why we stopped classifying for malware.
203 UMA_HISTOGRAM_ENUMERATION("SBClientMalware.PreClassificationCheckFail",
204 reason, NO_CLASSIFY_MAX);
205 DVLOG(2) << "Failed malware pre-classification checks. Reason: "
206 << reason;
207 start_malware_classification_cb_.Run(false);
208 }
209 start_malware_classification_cb_.Reset();
210 }
211
212 void CheckSafeBrowsingDatabase(const GURL& url) {
163 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 213 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
164 if (!database_manager_.get() || 214 // We don't want to call the classification callbacks from the IO
165 database_manager_->MatchCsdWhitelistUrl(url)) { 215 // thread so we simply pass the results of this method to CheckCache()
166 // We're done. There is no point in going back to the UI thread. 216 // which is called on the UI thread;
167 VLOG(1) << "Skipping phishing classification for URL: " << url 217 PreClassificationCheckFailures phishing_reason = NO_CLASSIFY_MAX;
168 << " because it matches the csd whitelist"; 218 PreClassificationCheckFailures malware_reason = NO_CLASSIFY_MAX;
169 UMA_HISTOGRAM_ENUMERATION("SBClientPhishing.PreClassificationCheckFail", 219 if (!database_manager_.get()) {
170 NO_CLASSIFY_MATCH_CSD_WHITELIST, 220 // We cannot check the Safe Browsing whitelists so we stop here
171 NO_CLASSIFY_MAX); 221 // for safety.
172 return; 222 malware_reason = phishing_reason = NO_CLASSIFY_NO_DATABASE_MANAGER;
223 } else {
224 if (database_manager_->MatchCsdWhitelistUrl(url)) {
225 VLOG(1) << "Skipping phishing classification for URL: " << url
226 << " because it matches the csd whitelist";
227 phishing_reason = NO_CLASSIFY_MATCH_CSD_WHITELIST;
228 }
229 if (database_manager_->IsMalwareKillSwitchOn()) {
230 malware_reason = NO_CLASSIFY_KILLSWITCH;
231 }
173 } 232 }
174
175 bool malware_killswitch_on = database_manager_->IsMalwareKillSwitchOn();
176
177 BrowserThread::PostTask( 233 BrowserThread::PostTask(
178 BrowserThread::UI, 234 BrowserThread::UI,
179 FROM_HERE, 235 FROM_HERE,
180 base::Bind(&ShouldClassifyUrlRequest::CheckCache, this, 236 base::Bind(&ShouldClassifyUrlRequest::CheckCache,
181 malware_killswitch_on)); 237 this,
238 phishing_reason,
239 malware_reason));
182 } 240 }
183 241
184 void CheckCache(bool malware_killswitch_on) { 242 void CheckCache(PreClassificationCheckFailures phishing_reason,
243 PreClassificationCheckFailures malware_reason) {
185 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 244 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
186 if (canceled_) { 245 if (phishing_reason != NO_CLASSIFY_MAX)
187 return; 246 DontClassifyForPhishing(phishing_reason);
247 if (malware_reason != NO_CLASSIFY_MAX)
248 DontClassifyForMalware(malware_reason);
249 if (!ShouldClassifyForMalware() && !ShouldClassifyForPhishing()) {
250 return; // No point in doing anything else.
188 } 251 }
189 252 // If result is cached, we don't want to run classification again.
190 host_->SetMalwareKillSwitch(malware_killswitch_on); 253 // In that case we're just trying to show the warning.
191 // If result is cached, we don't want to run classification again
192 bool is_phishing; 254 bool is_phishing;
193 if (csd_service_->GetValidCachedResult(params_.url, &is_phishing)) { 255 if (csd_service_->GetValidCachedResult(params_.url, &is_phishing)) {
194 VLOG(1) << "Satisfying request for " << params_.url << " from cache"; 256 VLOG(1) << "Satisfying request for " << params_.url << " from cache";
195 UMA_HISTOGRAM_COUNTS("SBClientPhishing.RequestSatisfiedFromCache", 1); 257 UMA_HISTOGRAM_BOOLEAN("SBClientPhishing.RequestSatisfiedFromCache", 1);
196 // Since we are already on the UI thread, this is safe. 258 // Since we are already on the UI thread, this is safe.
197 host_->MaybeShowPhishingWarning(params_.url, is_phishing); 259 host_->MaybeShowPhishingWarning(params_.url, is_phishing);
198 return; 260 DontClassifyForPhishing(NO_CLASSIFY_RESULT_FROM_CACHE);
199 } 261 }
200 262
201 // We want to limit the number of requests, though we will ignore the 263 // We want to limit the number of requests, though we will ignore the
202 // limit for urls in the cache. We don't want to start classifying 264 // limit for urls in the cache. We don't want to start classifying
203 // too many pages as phishing, but for those that we already think are 265 // too many pages as phishing, but for those that we already think are
204 // phishing we want to give ourselves a chance to fix false positives. 266 // phishing we want to send a request to the server to give ourselves
267 // a chance to fix misclassifications.
205 if (csd_service_->IsInCache(params_.url)) { 268 if (csd_service_->IsInCache(params_.url)) {
206 VLOG(1) << "Reporting limit skipped for " << params_.url 269 VLOG(1) << "Reporting limit skipped for " << params_.url
207 << " as it was in the cache."; 270 << " as it was in the cache.";
208 UMA_HISTOGRAM_COUNTS("SBClientPhishing.ReportLimitSkipped", 1); 271 UMA_HISTOGRAM_BOOLEAN("SBClientPhishing.ReportLimitSkipped", 1);
209 } else if (csd_service_->OverPhishingReportLimit()) { 272 } else if (csd_service_->OverPhishingReportLimit()) {
210 VLOG(1) << "Too many report phishing requests sent recently, " 273 VLOG(1) << "Too many report phishing requests sent recently, "
211 << "not running classification for " << params_.url; 274 << "not running classification for " << params_.url;
212 UMA_HISTOGRAM_ENUMERATION("SBClientPhishing.PreClassificationCheckFail", 275 DontClassifyForPhishing(NO_CLASSIFY_TOO_MANY_REPORTS);
213 NO_CLASSIFY_TOO_MANY_REPORTS, 276 }
214 NO_CLASSIFY_MAX); 277 if (csd_service_->OverMalwareReportLimit()) {
215 return; 278 DontClassifyForMalware(NO_CLASSIFY_TOO_MANY_REPORTS);
216 } 279 }
217 280
218 // Everything checks out, so start classification. 281 // Everything checks out, so start classification.
219 // |web_contents_| is safe to call as we will be destructed 282 // |web_contents_| is safe to call as we will be destructed
220 // before it is. 283 // before it is.
221 VLOG(1) << "Instruct renderer to start phishing detection for URL: " 284 if (ShouldClassifyForPhishing())
222 << params_.url; 285 start_phishing_classification_cb_.Run(true);
223 content::RenderViewHost* rvh = web_contents_->GetRenderViewHost(); 286 if (ShouldClassifyForMalware())
224 rvh->Send(new SafeBrowsingMsg_StartPhishingDetection( 287 start_malware_classification_cb_.Run(true);
225 rvh->GetRoutingID(), params_.url));
226 } 288 }
227 289
228 // No need to protect |canceled_| with a lock because it is only read and
229 // written by the UI thread.
230 bool canceled_;
231 content::FrameNavigateParams params_; 290 content::FrameNavigateParams params_;
232 WebContents* web_contents_; 291 WebContents* web_contents_;
233 ClientSideDetectionService* csd_service_; 292 ClientSideDetectionService* csd_service_;
234 // We keep a ref pointer here just to make sure the safe browsing 293 // We keep a ref pointer here just to make sure the safe browsing
235 // database manager stays alive long enough. 294 // database manager stays alive long enough.
236 scoped_refptr<SafeBrowsingDatabaseManager> database_manager_; 295 scoped_refptr<SafeBrowsingDatabaseManager> database_manager_;
237 ClientSideDetectionHost* host_; 296 ClientSideDetectionHost* host_;
238 297
298 ShouldClassifyUrlCallback start_phishing_classification_cb_;
299 ShouldClassifyUrlCallback start_malware_classification_cb_;
300
239 DISALLOW_COPY_AND_ASSIGN(ShouldClassifyUrlRequest); 301 DISALLOW_COPY_AND_ASSIGN(ShouldClassifyUrlRequest);
240 }; 302 };
241 303
242 // static 304 // static
243 ClientSideDetectionHost* ClientSideDetectionHost::Create( 305 ClientSideDetectionHost* ClientSideDetectionHost::Create(
244 WebContents* tab) { 306 WebContents* tab) {
245 return new ClientSideDetectionHost(tab); 307 return new ClientSideDetectionHost(tab);
246 } 308 }
247 309
248 ClientSideDetectionHost::ClientSideDetectionHost(WebContents* tab) 310 ClientSideDetectionHost::ClientSideDetectionHost(WebContents* tab)
249 : content::WebContentsObserver(tab), 311 : content::WebContentsObserver(tab),
250 csd_service_(NULL), 312 csd_service_(NULL),
313 classification_request_(NULL),
314 should_extract_malware_features_(true),
315 should_classify_for_malware_(false),
316 onload_complete_(false),
251 weak_factory_(this), 317 weak_factory_(this),
252 unsafe_unique_page_id_(-1), 318 unsafe_unique_page_id_(-1) {
253 malware_killswitch_on_(false),
254 malware_report_enabled_(false) {
255 DCHECK(tab); 319 DCHECK(tab);
256 // Note: csd_service_ and sb_service will be NULL here in testing. 320 // Note: csd_service_ and sb_service will be NULL here in testing.
257 csd_service_ = g_browser_process->safe_browsing_detection_service(); 321 csd_service_ = g_browser_process->safe_browsing_detection_service();
258 feature_extractor_.reset(new BrowserFeatureExtractor(tab, this)); 322 feature_extractor_.reset(new BrowserFeatureExtractor(tab, this));
259 registrar_.Add(this, content::NOTIFICATION_RESOURCE_RESPONSE_STARTED, 323 registrar_.Add(this, content::NOTIFICATION_RESOURCE_RESPONSE_STARTED,
260 content::Source<WebContents>(tab)); 324 content::Source<WebContents>(tab));
261 325
262 scoped_refptr<SafeBrowsingService> sb_service = 326 scoped_refptr<SafeBrowsingService> sb_service =
263 g_browser_process->safe_browsing_service(); 327 g_browser_process->safe_browsing_service();
264 if (sb_service.get()) { 328 if (sb_service.get()) {
265 ui_manager_ = sb_service->ui_manager(); 329 ui_manager_ = sb_service->ui_manager();
266 database_manager_ = sb_service->database_manager(); 330 database_manager_ = sb_service->database_manager();
267 ui_manager_->AddObserver(this); 331 ui_manager_->AddObserver(this);
268 } 332 }
269
270 // Only enable the malware bad IP matching and report feature for canary
271 // and dev channel.
272 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
273 malware_report_enabled_ = (
274 channel == chrome::VersionInfo::CHANNEL_DEV ||
275 channel == chrome::VersionInfo::CHANNEL_CANARY);
276 } 333 }
277 334
278 ClientSideDetectionHost::~ClientSideDetectionHost() { 335 ClientSideDetectionHost::~ClientSideDetectionHost() {
279 if (ui_manager_.get()) 336 if (ui_manager_.get())
280 ui_manager_->RemoveObserver(this); 337 ui_manager_->RemoveObserver(this);
281 } 338 }
282 339
283 bool ClientSideDetectionHost::OnMessageReceived(const IPC::Message& message) { 340 bool ClientSideDetectionHost::OnMessageReceived(const IPC::Message& message) {
284 bool handled = true; 341 bool handled = true;
285 IPC_BEGIN_MESSAGE_MAP(ClientSideDetectionHost, message) 342 IPC_BEGIN_MESSAGE_MAP(ClientSideDetectionHost, message)
286 IPC_MESSAGE_HANDLER(SafeBrowsingHostMsg_PhishingDetectionDone, 343 IPC_MESSAGE_HANDLER(SafeBrowsingHostMsg_PhishingDetectionDone,
287 OnPhishingDetectionDone) 344 OnPhishingDetectionDone)
288 IPC_MESSAGE_UNHANDLED(handled = false) 345 IPC_MESSAGE_UNHANDLED(handled = false)
289 IPC_END_MESSAGE_MAP() 346 IPC_END_MESSAGE_MAP()
290 return handled; 347 return handled;
291 } 348 }
292 349
293 void ClientSideDetectionHost::DidNavigateMainFrame( 350 void ClientSideDetectionHost::DidNavigateMainFrame(
294 const content::LoadCommittedDetails& details, 351 const content::LoadCommittedDetails& details,
295 const content::FrameNavigateParams& params) { 352 const content::FrameNavigateParams& params) {
296 // TODO(noelutz): move this DCHECK to WebContents and fix all the unit tests 353 // TODO(noelutz): move this DCHECK to WebContents and fix all the unit tests
297 // that don't call this method on the UI thread. 354 // that don't call this method on the UI thread.
298 // DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 355 // DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
299 if (details.is_in_page) { 356 if (details.is_in_page) {
300 // If the navigation is within the same page, the user isn't really 357 // If the navigation is within the same page, the user isn't really
301 // navigating away. We don't need to cancel a pending callback or 358 // navigating away. We don't need to cancel a pending callback or
302 // begin a new classification. 359 // begin a new classification.
303 return; 360 return;
304 } 361 }
362 // Cancel any pending classification request.
363 if (classification_request_.get()) {
364 classification_request_->Cancel();
365 }
305 // If we navigate away and there currently is a pending phishing 366 // If we navigate away and there currently is a pending phishing
306 // report request we have to cancel it to make sure we don't display 367 // report request we have to cancel it to make sure we don't display
307 // an interstitial for the wrong page. Note that this won't cancel 368 // an interstitial for the wrong page. Note that this won't cancel
308 // the server ping back but only cancel the showing of the 369 // the server ping back but only cancel the showing of the
309 // interstial. 370 // interstial.
310 weak_factory_.InvalidateWeakPtrs(); 371 weak_factory_.InvalidateWeakPtrs();
311 372
312 if (!csd_service_) { 373 if (!csd_service_) {
313 return; 374 return;
314 } 375 }
315
316 // Cancel any pending classification request.
317 if (classification_request_.get()) {
318 classification_request_->Cancel();
319 }
320 browse_info_.reset(new BrowseInfo); 376 browse_info_.reset(new BrowseInfo);
321 377
322 // Store redirect chain information. 378 // Store redirect chain information.
323 if (params.url.host() != cur_host_) { 379 if (params.url.host() != cur_host_) {
324 cur_host_ = params.url.host(); 380 cur_host_ = params.url.host();
325 cur_host_redirects_ = params.redirects; 381 cur_host_redirects_ = params.redirects;
326 } 382 }
383 browse_info_->url = params.url;
327 browse_info_->host_redirects = cur_host_redirects_; 384 browse_info_->host_redirects = cur_host_redirects_;
328 browse_info_->url_redirects = params.redirects; 385 browse_info_->url_redirects = params.redirects;
329 browse_info_->referrer = params.referrer.url; 386 browse_info_->referrer = params.referrer.url;
330 browse_info_->http_status_code = details.http_status_code; 387 browse_info_->http_status_code = details.http_status_code;
388 browse_info_->page_id = params.page_id;
331 389
332 // Notify the renderer if it should classify this URL. 390 should_extract_malware_features_ = true;
391 should_classify_for_malware_ = false;
392 onload_complete_ = false;
393
394 // Check whether we can cassify the current URL for phishing or malware.
333 classification_request_ = new ShouldClassifyUrlRequest( 395 classification_request_ = new ShouldClassifyUrlRequest(
334 params, web_contents(), csd_service_, database_manager_.get(), this); 396 params,
397 base::Bind(&ClientSideDetectionHost::OnPhishingPreClassificationDone,
398 weak_factory_.GetWeakPtr()),
399 base::Bind(&ClientSideDetectionHost::OnMalwarePreClassificationDone,
400 weak_factory_.GetWeakPtr()),
401 web_contents(), csd_service_, database_manager_.get(), this);
335 classification_request_->Start(); 402 classification_request_->Start();
336 } 403 }
337 404
338 void ClientSideDetectionHost::OnSafeBrowsingHit( 405 void ClientSideDetectionHost::OnSafeBrowsingHit(
339 const SafeBrowsingUIManager::UnsafeResource& resource) { 406 const SafeBrowsingUIManager::UnsafeResource& resource) {
340 if (!web_contents() || !web_contents()->GetController().GetActiveEntry()) 407 if (!web_contents() || !web_contents()->GetController().GetActiveEntry())
341 return; 408 return;
342 409
343 // Check that the hit is either malware or phishing. 410 // Check that the hit is either malware or phishing.
344 if (resource.threat_type != SB_THREAT_TYPE_URL_PHISHING && 411 if (resource.threat_type != SB_THREAT_TYPE_URL_PHISHING &&
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 void ClientSideDetectionHost::WebContentsDestroyed(WebContents* tab) { 474 void ClientSideDetectionHost::WebContentsDestroyed(WebContents* tab) {
408 DCHECK(tab); 475 DCHECK(tab);
409 // Tell any pending classification request that it is being canceled. 476 // Tell any pending classification request that it is being canceled.
410 if (classification_request_.get()) { 477 if (classification_request_.get()) {
411 classification_request_->Cancel(); 478 classification_request_->Cancel();
412 } 479 }
413 // Cancel all pending feature extractions. 480 // Cancel all pending feature extractions.
414 feature_extractor_.reset(); 481 feature_extractor_.reset();
415 } 482 }
416 483
484 void ClientSideDetectionHost::OnPhishingPreClassificationDone(
485 bool should_classify) {
486 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
487 if (browse_info_.get() && should_classify) {
488 VLOG(1) << "Instruct renderer to start phishing detection for URL: "
489 << browse_info_->url;
490 content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
491 rvh->Send(new SafeBrowsingMsg_StartPhishingDetection(
492 rvh->GetRoutingID(), browse_info_->url));
493 }
494 }
495
496 void ClientSideDetectionHost::OnMalwarePreClassificationDone(
497 bool should_classify) {
498 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
499 // If classification checks failed we should stop extracting malware features.
500 DVLOG(2) << "Malware pre-classification checks done. Should classify: "
501 << should_classify;
502 should_extract_malware_features_ = should_classify;
503 should_classify_for_malware_ = should_classify;
504 MaybeStartMalwareFeatureExtraction();
505 }
506
507 void ClientSideDetectionHost::DocumentOnLoadCompletedInMainFrame(
508 int32 page_id) {
509 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
510 if (!csd_service_ || !browse_info_.get())
511 return;
512 DVLOG(2) << "Main frame onload hander called.";
513 if (browse_info_->page_id != page_id) {
514 // Something weird is happening here. The BrowseInfo page ID
515 // should always be the same as the most recent load.
516 UMA_HISTOGRAM_BOOLEAN("SBClientMalware.UnexpectedPageId", 1);
517 return;
518 }
519 onload_complete_ = true;
520 MaybeStartMalwareFeatureExtraction();
521 }
522
523 void ClientSideDetectionHost::MaybeStartMalwareFeatureExtraction() {
524 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
525 if (csd_service_ && browse_info_.get() &&
526 should_classify_for_malware_ &&
527 onload_complete_) {
528 scoped_ptr<ClientMalwareRequest> malware_request(
529 new ClientMalwareRequest);
530 // Start browser-side malware feature extraction. Once we're done it will
531 // send the malware client verdict request.
532 malware_request->set_url(browse_info_->url.spec());
533 const GURL& referrer = browse_info_->referrer;
534 if (referrer.SchemeIs("http")) { // Only send http urls.
535 malware_request->set_referrer_url(referrer.spec());
536 }
537 // This function doesn't expect browse_info_ to stay around after this
538 // function returns.
539 feature_extractor_->ExtractMalwareFeatures(
540 browse_info_.get(),
541 malware_request.release(),
542 base::Bind(&ClientSideDetectionHost::MalwareFeatureExtractionDone,
543 weak_factory_.GetWeakPtr()));
544 should_classify_for_malware_ = false;
545 }
546 }
547
417 void ClientSideDetectionHost::OnPhishingDetectionDone( 548 void ClientSideDetectionHost::OnPhishingDetectionDone(
418 const std::string& verdict_str) { 549 const std::string& verdict_str) {
419 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 550 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
420 // There is something seriously wrong if there is no service class but 551 // There is something seriously wrong if there is no service class but
421 // this method is called. The renderer should not start phishing detection 552 // this method is called. The renderer should not start phishing detection
422 // if there isn't any service class in the browser. 553 // if there isn't any service class in the browser.
423 DCHECK(csd_service_); 554 DCHECK(csd_service_);
424 // There shouldn't be any pending requests because we revoke them everytime
425 // we navigate away.
426 DCHECK(!weak_factory_.HasWeakPtrs());
427 DCHECK(browse_info_.get()); 555 DCHECK(browse_info_.get());
428 556
429 // We parse the protocol buffer here. If we're unable to parse it we won't 557 // We parse the protocol buffer here. If we're unable to parse it we won't
430 // send the verdict further. 558 // send the verdict further.
431 scoped_ptr<ClientPhishingRequest> verdict(new ClientPhishingRequest); 559 scoped_ptr<ClientPhishingRequest> verdict(new ClientPhishingRequest);
432 if (csd_service_ && 560 if (csd_service_ &&
433 !weak_factory_.HasWeakPtrs() &&
434 browse_info_.get() && 561 browse_info_.get() &&
435 verdict->ParseFromString(verdict_str) && 562 verdict->ParseFromString(verdict_str) &&
436 verdict->IsInitialized()) { 563 verdict->IsInitialized()) {
437 // We do the malware IP matching and request sending if the feature
438 // is enabled.
439 if (malware_report_enabled_ && !MalwareKillSwitchIsOn()) {
440 scoped_ptr<ClientMalwareRequest> malware_verdict(
441 new ClientMalwareRequest);
442 // Start browser-side malware feature extraction. Once we're done it will
443 // send the malware client verdict request.
444 malware_verdict->set_url(verdict->url());
445 const GURL& referrer = browse_info_->referrer;
446 if (referrer.SchemeIs("http")) { // Only send http urls.
447 malware_verdict->set_referrer_url(referrer.spec());
448 }
449 // This function doesn't expect browse_info_ to stay around after this
450 // function returns.
451 feature_extractor_->ExtractMalwareFeatures(
452 browse_info_.get(),
453 malware_verdict.release(),
454 base::Bind(&ClientSideDetectionHost::MalwareFeatureExtractionDone,
455 weak_factory_.GetWeakPtr()));
456 }
457
458 // We only send phishing verdict to the server if the verdict is phishing or 564 // We only send phishing verdict to the server if the verdict is phishing or
459 // if a SafeBrowsing interstitial was already shown for this site. E.g., a 565 // if a SafeBrowsing interstitial was already shown for this site. E.g., a
460 // malware or phishing interstitial was shown but the user clicked 566 // malware or phishing interstitial was shown but the user clicked
461 // through. 567 // through.
462 if (verdict->is_phishing() || DidShowSBInterstitial()) { 568 if (verdict->is_phishing() || DidShowSBInterstitial()) {
463 if (DidShowSBInterstitial()) { 569 if (DidShowSBInterstitial()) {
464 browse_info_->unsafe_resource.reset(unsafe_resource_.release()); 570 browse_info_->unsafe_resource.reset(unsafe_resource_.release());
465 } 571 }
466 // Start browser-side feature extraction. Once we're done it will send 572 // Start browser-side feature extraction. Once we're done it will send
467 // the client verdict request. 573 // the client verdict request.
468 feature_extractor_->ExtractFeatures( 574 feature_extractor_->ExtractFeatures(
469 browse_info_.get(), 575 browse_info_.get(),
470 verdict.release(), 576 verdict.release(),
471 base::Bind(&ClientSideDetectionHost::FeatureExtractionDone, 577 base::Bind(&ClientSideDetectionHost::FeatureExtractionDone,
472 weak_factory_.GetWeakPtr())); 578 weak_factory_.GetWeakPtr()));
473 } 579 }
474 } 580 }
475 browse_info_.reset();
476 } 581 }
477 582
478 void ClientSideDetectionHost::MaybeShowPhishingWarning(GURL phishing_url, 583 void ClientSideDetectionHost::MaybeShowPhishingWarning(GURL phishing_url,
479 bool is_phishing) { 584 bool is_phishing) {
480 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 585 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
481 VLOG(2) << "Received server phishing verdict for URL:" << phishing_url 586 DVLOG(2) << "Received server phishing verdict for URL:" << phishing_url
482 << " is_phishing:" << is_phishing; 587 << " is_phishing:" << is_phishing;
483 if (is_phishing) { 588 if (is_phishing) {
484 DCHECK(web_contents()); 589 DCHECK(web_contents());
485 if (ui_manager_.get()) { 590 if (ui_manager_.get()) {
486 SafeBrowsingUIManager::UnsafeResource resource; 591 SafeBrowsingUIManager::UnsafeResource resource;
487 resource.url = phishing_url; 592 resource.url = phishing_url;
488 resource.original_url = phishing_url; 593 resource.original_url = phishing_url;
489 resource.is_subresource = false; 594 resource.is_subresource = false;
490 resource.threat_type = SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL; 595 resource.threat_type = SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL;
491 resource.render_process_host_id = 596 resource.render_process_host_id =
492 web_contents()->GetRenderProcessHost()->GetID(); 597 web_contents()->GetRenderProcessHost()->GetID();
493 resource.render_view_id = 598 resource.render_view_id =
494 web_contents()->GetRenderViewHost()->GetRoutingID(); 599 web_contents()->GetRenderViewHost()->GetRoutingID();
495 if (!ui_manager_->IsWhitelisted(resource)) { 600 if (!ui_manager_->IsWhitelisted(resource)) {
496 // We need to stop any pending navigations, otherwise the interstital 601 // We need to stop any pending navigations, otherwise the interstital
497 // might not get created properly. 602 // might not get created properly.
498 web_contents()->GetController().DiscardNonCommittedEntries(); 603 web_contents()->GetController().DiscardNonCommittedEntries();
499 } 604 }
500 ui_manager_->DisplayBlockingPage(resource); 605 ui_manager_->DisplayBlockingPage(resource);
501 } 606 }
502 // If there is true phishing verdict, invalidate weakptr so that no longer 607 // If there is true phishing verdict, invalidate weakptr so that no longer
503 // consider the malware vedict. 608 // consider the malware vedict.
504 weak_factory_.InvalidateWeakPtrs(); 609 weak_factory_.InvalidateWeakPtrs();
505 } 610 }
506 } 611 }
507 612
508 void ClientSideDetectionHost::MaybeShowMalwareWarning(GURL original_url, 613 void ClientSideDetectionHost::MaybeShowMalwareWarning(GURL original_url,
509 GURL malware_url, 614 GURL malware_url,
510 bool is_malware) { 615 bool is_malware) {
511 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 616 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
512 VLOG(2) << "Received server malawre IP verdict for URL:" << malware_url 617 DVLOG(2) << "Received server malawre IP verdict for URL:" << malware_url
513 << " is_malware:" << is_malware; 618 << " is_malware:" << is_malware;
514 if (is_malware && malware_url.is_valid() && original_url.is_valid()) { 619 if (is_malware && malware_url.is_valid() && original_url.is_valid()) {
515 DCHECK(web_contents()); 620 DCHECK(web_contents());
516 if (ui_manager_.get()) { 621 if (ui_manager_.get()) {
517 SafeBrowsingUIManager::UnsafeResource resource; 622 SafeBrowsingUIManager::UnsafeResource resource;
518 resource.url = malware_url; 623 resource.url = malware_url;
519 resource.original_url = original_url; 624 resource.original_url = original_url;
520 resource.is_subresource = (malware_url.host() != original_url.host()); 625 resource.is_subresource = (malware_url.host() != original_url.host());
521 resource.threat_type = SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL; 626 resource.threat_type = SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL;
522 resource.render_process_host_id = 627 resource.render_process_host_id =
523 web_contents()->GetRenderProcessHost()->GetID(); 628 web_contents()->GetRenderProcessHost()->GetID();
524 resource.render_view_id = 629 resource.render_view_id =
525 web_contents()->GetRenderViewHost()->GetRoutingID(); 630 web_contents()->GetRenderViewHost()->GetRoutingID();
526 if (!ui_manager_->IsWhitelisted(resource)) { 631 if (!ui_manager_->IsWhitelisted(resource)) {
527 // We need to stop any pending navigations, otherwise the interstital 632 // We need to stop any pending navigations, otherwise the interstital
528 // might not get created properly. 633 // might not get created properly.
529 web_contents()->GetController().DiscardNonCommittedEntries(); 634 web_contents()->GetController().DiscardNonCommittedEntries();
530 } 635 }
531 ui_manager_->DisplayBlockingPage(resource); 636 ui_manager_->DisplayBlockingPage(resource);
532 } 637 }
533 // If there is true malware verdict, invalidate weakptr so that no longer 638 // If there is true malware verdict, invalidate weakptr so that no longer
534 // consider the phishing vedict. 639 // consider the phishing vedict.
535 weak_factory_.InvalidateWeakPtrs(); 640 weak_factory_.InvalidateWeakPtrs();
536 } 641 }
537 } 642 }
538 643
539 void ClientSideDetectionHost::FeatureExtractionDone( 644 void ClientSideDetectionHost::FeatureExtractionDone(
540 bool success, 645 bool success,
541 ClientPhishingRequest* request) { 646 ClientPhishingRequest* request) {
542 DCHECK(request); 647 DCHECK(request);
543 VLOG(2) << "Feature extraction done (success:" << success << ") for URL: " 648 DVLOG(2) << "Feature extraction done (success:" << success << ") for URL: "
544 << request->url() << ". Start sending client phishing request."; 649 << request->url() << ". Start sending client phishing request.";
545 ClientSideDetectionService::ClientReportPhishingRequestCallback callback; 650 ClientSideDetectionService::ClientReportPhishingRequestCallback callback;
546 // If the client-side verdict isn't phishing we don't care about the server 651 // If the client-side verdict isn't phishing we don't care about the server
547 // response because we aren't going to display a warning. 652 // response because we aren't going to display a warning.
548 if (request->is_phishing()) { 653 if (request->is_phishing()) {
549 callback = base::Bind(&ClientSideDetectionHost::MaybeShowPhishingWarning, 654 callback = base::Bind(&ClientSideDetectionHost::MaybeShowPhishingWarning,
550 weak_factory_.GetWeakPtr()); 655 weak_factory_.GetWeakPtr());
551 } 656 }
552 // Send ping even if the browser feature extraction failed. 657 // Send ping even if the browser feature extraction failed.
553 csd_service_->SendClientReportPhishingRequest( 658 csd_service_->SendClientReportPhishingRequest(
554 request, // The service takes ownership of the request object. 659 request, // The service takes ownership of the request object.
555 callback); 660 callback);
556 } 661 }
557 662
558 void ClientSideDetectionHost::MalwareFeatureExtractionDone( 663 void ClientSideDetectionHost::MalwareFeatureExtractionDone(
559 bool feature_extraction_success, 664 bool feature_extraction_success,
560 scoped_ptr<ClientMalwareRequest> request) { 665 scoped_ptr<ClientMalwareRequest> request) {
561 DCHECK(request.get()); 666 DCHECK(request.get());
562 VLOG(2) << "Malware Feature extraction done for URL: " << request->url() 667 DVLOG(2) << "Malware Feature extraction done for URL: " << request->url()
563 << ", with badip url count:" << request->bad_ip_url_info_size(); 668 << ", with badip url count:" << request->bad_ip_url_info_size();
564 669
565 // Send ping if there is matching features. 670 // Send ping if there is matching features.
566 if (feature_extraction_success && request->bad_ip_url_info_size() > 0) { 671 if (feature_extraction_success && request->bad_ip_url_info_size() > 0) {
567 VLOG(1) << "Start sending client malware request."; 672 VLOG(1) << "Start sending client malware request.";
568 ClientSideDetectionService::ClientReportMalwareRequestCallback callback; 673 ClientSideDetectionService::ClientReportMalwareRequestCallback callback;
569 callback = base::Bind(&ClientSideDetectionHost::MaybeShowMalwareWarning, 674 callback = base::Bind(&ClientSideDetectionHost::MaybeShowMalwareWarning,
570 weak_factory_.GetWeakPtr()); 675 weak_factory_.GetWeakPtr());
571 csd_service_->SendClientReportMalwareRequest(request.release(), callback); 676 csd_service_->SendClientReportMalwareRequest(request.release(), callback);
572 } 677 }
573 } 678 }
(...skipping 20 matching lines...) Expand all
594 } 699 }
595 700
596 void ClientSideDetectionHost::Observe( 701 void ClientSideDetectionHost::Observe(
597 int type, 702 int type,
598 const content::NotificationSource& source, 703 const content::NotificationSource& source,
599 const content::NotificationDetails& details) { 704 const content::NotificationDetails& details) {
600 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 705 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
601 DCHECK_EQ(type, content::NOTIFICATION_RESOURCE_RESPONSE_STARTED); 706 DCHECK_EQ(type, content::NOTIFICATION_RESOURCE_RESPONSE_STARTED);
602 const ResourceRequestDetails* req = content::Details<ResourceRequestDetails>( 707 const ResourceRequestDetails* req = content::Details<ResourceRequestDetails>(
603 details).ptr(); 708 details).ptr();
604 if (req && browse_info_.get() && malware_report_enabled_ && 709 if (req && browse_info_.get() &&
605 !MalwareKillSwitchIsOn()) { 710 should_extract_malware_features_ && req->url.is_valid()) {
606 if (req->url.is_valid()) { 711 UpdateIPUrlMap(req->socket_address.host() /* ip */,
607 UpdateIPUrlMap(req->socket_address.host() /* ip */, 712 req->url.spec() /* url */,
608 req->url.spec() /* url */, 713 req->method,
609 req->method, 714 req->referrer,
610 req->referrer, 715 req->resource_type);
611 req->resource_type);
612 }
613 } 716 }
614 } 717 }
615 718
616 bool ClientSideDetectionHost::DidShowSBInterstitial() const { 719 bool ClientSideDetectionHost::DidShowSBInterstitial() const {
617 if (unsafe_unique_page_id_ <= 0 || !web_contents()) { 720 if (unsafe_unique_page_id_ <= 0 || !web_contents()) {
618 return false; 721 return false;
619 } 722 }
620 const NavigationEntry* nav_entry = 723 const NavigationEntry* nav_entry =
621 web_contents()->GetController().GetActiveEntry(); 724 web_contents()->GetController().GetActiveEntry();
622 return (nav_entry && nav_entry->GetUniqueID() == unsafe_unique_page_id_); 725 return (nav_entry && nav_entry->GetUniqueID() == unsafe_unique_page_id_);
(...skipping 10 matching lines...) Expand all
633 if (ui_manager_.get()) 736 if (ui_manager_.get())
634 ui_manager_->RemoveObserver(this); 737 ui_manager_->RemoveObserver(this);
635 738
636 ui_manager_ = ui_manager; 739 ui_manager_ = ui_manager;
637 if (ui_manager) 740 if (ui_manager)
638 ui_manager_->AddObserver(this); 741 ui_manager_->AddObserver(this);
639 742
640 database_manager_ = database_manager; 743 database_manager_ = database_manager;
641 } 744 }
642 745
643 bool ClientSideDetectionHost::MalwareKillSwitchIsOn() {
644 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
645 return malware_killswitch_on_;
646 }
647
648 void ClientSideDetectionHost::SetMalwareKillSwitch(bool killswitch_on) {
649 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
650 malware_killswitch_on_ = killswitch_on;
651 }
652
653 } // namespace safe_browsing 746 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698