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

Side by Side Diff: components/safe_browsing/request_checker.cc

Issue 2876473003: [ABANDONED] [WIP] Refactor SafeBrowsingResourceThrottle in preparation for WebSocket (Closed)
Patch Set: Finish unit tests Created 3 years, 7 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
OLDNEW
1 // Copyright (c) 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 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 "components/safe_browsing/base_resource_throttle.h" 5 #include "components/safe_browsing/request_checker.h"
6
7 #include <memory>
8 #include <utility>
6 9
7 #include "base/metrics/histogram_macros.h" 10 #include "base/metrics/histogram_macros.h"
8 #include "base/trace_event/trace_event.h" 11 #include "base/trace_event/trace_event.h"
9 #include "base/values.h" 12 #include "base/values.h"
10 #include "components/safe_browsing/base_ui_manager.h" 13 #include "components/safe_browsing/base_ui_manager.h"
14 #include "components/safe_browsing_db/database_manager.h"
11 #include "components/safe_browsing_db/util.h" 15 #include "components/safe_browsing_db/util.h"
12 #include "components/security_interstitials/content/unsafe_resource.h" 16 #include "components/security_interstitials/content/unsafe_resource.h"
13 #include "content/public/browser/browser_thread.h" 17 #include "content/public/browser/browser_thread.h"
14 #include "content/public/browser/resource_request_info.h"
15 #include "content/public/browser/web_contents.h"
16 #include "net/base/load_flags.h" 18 #include "net/base/load_flags.h"
17 #include "net/log/net_log_capture_mode.h" 19 #include "net/log/net_log_capture_mode.h"
18 #include "net/log/net_log_source.h" 20 #include "net/log/net_log_source.h"
19 #include "net/log/net_log_source_type.h" 21 #include "net/log/net_log_source_type.h"
20 #include "net/url_request/redirect_info.h" 22 #include "net/url_request/redirect_info.h"
21 #include "net/url_request/url_request.h" 23 #include "net/url_request/url_request.h"
22 24
23 using net::NetLogEventType; 25 using net::NetLogEventType;
24 using net::NetLogSourceType; 26 using net::NetLogSourceType;
25 27
26 namespace safe_browsing { 28 namespace safe_browsing {
27 29
28 namespace { 30 namespace {
29 31
30 // Maximum time in milliseconds to wait for the safe browsing service to 32 // Maximum time in milliseconds to wait for the safe browsing service to
31 // verify a URL. After this amount of time the outstanding check will be 33 // verify a URL. After this amount of time the outstanding check will be
32 // aborted, and the URL will be treated as if it were safe. 34 // aborted, and the URL will be treated as if it were safe.
33 const int kCheckUrlTimeoutMs = 5000; 35 // Mutable for testing purposes.
36 int g_check_url_timeout_ms = 5000;
34 37
35 // Return a dictionary with "url"=|url-spec| and optionally 38 // Return a dictionary with "url"=|url-spec| and optionally
36 // |name|=|value| (if not null), for netlogging. 39 // |name|=|value| (if not null), for netlogging.
37 // This will also add a reference to the original request's net_log ID. 40 // This will also add a reference to the original request's net_log ID.
38 std::unique_ptr<base::Value> NetLogUrlCallback( 41 std::unique_ptr<base::Value> NetLogUrlCallback(
39 const net::URLRequest* request, 42 const net::URLRequest* request,
40 const GURL& url, 43 const GURL& url,
41 const char* name, 44 const char* name,
42 const char* value, 45 const char* value,
43 net::NetLogCaptureMode /* capture_mode */) { 46 net::NetLogCaptureMode /* capture_mode */) {
(...skipping 12 matching lines...) Expand all
56 net::NetLogCaptureMode) { 59 net::NetLogCaptureMode) {
57 std::unique_ptr<base::DictionaryValue> event_params( 60 std::unique_ptr<base::DictionaryValue> event_params(
58 new base::DictionaryValue()); 61 new base::DictionaryValue());
59 if (name && value) 62 if (name && value)
60 event_params->SetString(name, value); 63 event_params->SetString(name, value);
61 return std::move(event_params); 64 return std::move(event_params);
62 } 65 }
63 66
64 } // namespace 67 } // namespace
65 68
66 // TODO(eroman): Downgrade these CHECK()s to DCHECKs once there is more 69 RequestChecker::RequestChecker(
67 // unit test coverage.
68
69 BaseResourceThrottle::BaseResourceThrottle(
70 const net::URLRequest* request, 70 const net::URLRequest* request,
71 content::ResourceType resource_type, 71 content::ResourceType resource_type,
72 scoped_refptr<SafeBrowsingDatabaseManager> database_manager, 72 scoped_refptr<SafeBrowsingDatabaseManager> database_manager,
73 scoped_refptr<BaseUIManager> ui_manager) 73 scoped_refptr<BaseUIManager> ui_manager,
74 : ui_manager_(ui_manager), 74 Delegate* delegate)
75 threat_type_(SB_THREAT_TYPE_SAFE), 75 : state_(STATE_NONE),
76 database_manager_(database_manager),
77 request_(request),
78 state_(STATE_NONE),
79 defer_state_(DEFERRED_NONE), 76 defer_state_(DEFERRED_NONE),
80 resource_type_(resource_type), 77 resource_type_(resource_type),
78 threat_type_(SB_THREAT_TYPE_SAFE),
79 request_(request),
80 ui_manager_(std::move(ui_manager)),
81 database_manager_(std::move(database_manager)),
81 net_log_with_source_( 82 net_log_with_source_(
82 net::NetLogWithSource::Make(request->net_log().net_log(), 83 net::NetLogWithSource::Make(request->net_log().net_log(),
83 NetLogSourceType::SAFE_BROWSING)) {} 84 NetLogSourceType::SAFE_BROWSING)),
85 delegate_(std::move(delegate)),
86 weak_factory_(this) {}
84 87
85 // static 88 RequestChecker::~RequestChecker() {
86 BaseResourceThrottle* BaseResourceThrottle::MaybeCreate(
87 net::URLRequest* request,
88 content::ResourceType resource_type,
89 scoped_refptr<SafeBrowsingDatabaseManager> database_manager,
90 scoped_refptr<BaseUIManager> ui_manager) {
91 if (database_manager->IsSupported()) {
92 return new BaseResourceThrottle(request, resource_type,
93 database_manager, ui_manager);
94 }
95 return nullptr;
96 }
97
98 BaseResourceThrottle::~BaseResourceThrottle() {
99 if (defer_state_ != DEFERRED_NONE) { 89 if (defer_state_ != DEFERRED_NONE) {
100 EndNetLogEvent(NetLogEventType::SAFE_BROWSING_DEFERRED, nullptr, nullptr); 90 EndNetLogEvent(NetLogEventType::SAFE_BROWSING_DEFERRED, nullptr, nullptr);
101 } 91 }
102 92
103 if (state_ == STATE_CHECKING_URL) { 93 if (state_ == STATE_CHECKING_URL) {
104 database_manager_->CancelCheck(this); 94 database_manager_->CancelCheck(this);
105 EndNetLogEvent(NetLogEventType::SAFE_BROWSING_CHECKING_URL, "result", 95 EndNetLogEvent(NetLogEventType::SAFE_BROWSING_CHECKING_URL, "result",
106 "request_canceled"); 96 "request_canceled");
107 } 97 }
108 } 98 }
109 99
110 // Note on net_log calls: SAFE_BROWSING_DEFERRED events must be wholly 100 RequestChecker::DeferDecision RequestChecker::CheckNewRequest() {
111 // nested within SAFE_BROWSING_CHECKING_URL events. Synchronous checks
112 // are not logged at all.
113 void BaseResourceThrottle::BeginNetLogEvent(NetLogEventType type,
114 const GURL& url,
115 const char* name,
116 const char* value) {
117 net_log_with_source_.BeginEvent(
118 type, base::Bind(&NetLogUrlCallback, request_, url, name, value));
119 request_->net_log().AddEvent(
120 type, net_log_with_source_.source().ToEventParametersCallback());
121 }
122
123 void BaseResourceThrottle::EndNetLogEvent(NetLogEventType type,
124 const char* name,
125 const char* value) {
126 net_log_with_source_.EndEvent(type,
127 base::Bind(&NetLogStringCallback, name, value));
128 request_->net_log().AddEvent(
129 type, net_log_with_source_.source().ToEventParametersCallback());
130 }
131
132 void BaseResourceThrottle::WillStartRequest(bool* defer) {
133 // We need to check the new URL before starting the request. 101 // We need to check the new URL before starting the request.
134 if (CheckUrl(request_->url())) 102 DeferDecision decision = CheckUrl(request_->url());
135 return; 103 DCHECK_NE(decision, PROCEED_ALWAYS_ASYNC);
104 if (decision != DEFER)
105 return decision;
136 106
137 // We let the check run in parallel with resource load only if this 107 // We let the check run in parallel with resource load only if this
138 // db_manager only supports asynchronous checks, like on mobile. 108 // db_manager only supports asynchronous checks, like on mobile.
139 // Otherwise, we defer now. 109 // Otherwise, we defer now.
140 if (database_manager_->ChecksAreAlwaysAsync()) 110 if (database_manager_->ChecksAreAlwaysAsync())
141 return; 111 return PROCEED_ALWAYS_ASYNC;
142 112
143 // If the URL couldn't be verified synchronously, defer starting the 113 // If the URL couldn't be verified synchronously, defer starting the
144 // request until the check has completed. 114 // request until the check has completed.
145 defer_state_ = DEFERRED_START; 115 defer_state_ = DEFERRED_START;
146 defer_start_time_ = base::TimeTicks::Now(); 116 defer_start_time_ = base::TimeTicks::Now();
147 *defer = true;
148 BeginNetLogEvent(NetLogEventType::SAFE_BROWSING_DEFERRED, request_->url(), 117 BeginNetLogEvent(NetLogEventType::SAFE_BROWSING_DEFERRED, request_->url(),
149 "defer_reason", "at_start"); 118 "defer_reason", "at_start");
119 return DEFER;
150 } 120 }
151 121
152 void BaseResourceThrottle::WillProcessResponse(bool* defer) { 122 RequestChecker::DeferDecision RequestChecker::CheckRedirect(
153 CHECK_EQ(defer_state_, DEFERRED_NONE); 123 const GURL& new_url) {
154 // TODO(nparker): Maybe remove this check, since it should have no effect.
155 if (!database_manager_->ChecksAreAlwaysAsync())
156 return;
157
158 if (state_ == STATE_CHECKING_URL ||
159 state_ == STATE_DISPLAYING_BLOCKING_PAGE) {
160 defer_state_ = DEFERRED_PROCESSING;
161 defer_start_time_ = base::TimeTicks::Now();
162 *defer = true;
163 BeginNetLogEvent(NetLogEventType::SAFE_BROWSING_DEFERRED, request_->url(),
164 "defer_reason", "at_response");
165 }
166 }
167
168 bool BaseResourceThrottle::MustProcessResponseBeforeReadingBody() {
169 // On Android, SafeBrowsing may only decide to cancel the request when the
170 // response has been received. Therefore, no part of it should be cached
171 // until this ResourceThrottle has been able to check the response. This
172 // prevents the following scenario:
173 // 1) A request is made for foo.com which has been hacked.
174 // 2) The request is only canceled at WillProcessResponse stage, but part of
175 // it has been cached.
176 // 3) foo.com is no longer hacked and removed from the SafeBrowsing list.
177 // 4) The user requests foo.com, which is not on the SafeBrowsing list. This
178 // is deemed safe. However, the resource is actually served from cache,
179 // using the version that was previously stored.
180 // 5) This results in the user accessing an unsafe resource without being
181 // notified that it's dangerous.
182 // TODO(clamy): Add a browser test that checks this specific scenario.
183 return true;
184 }
185
186 void BaseResourceThrottle::WillRedirectRequest(
187 const net::RedirectInfo& redirect_info,
188 bool* defer) {
189 CHECK_EQ(defer_state_, DEFERRED_NONE); 124 CHECK_EQ(defer_state_, DEFERRED_NONE);
190 125
191 // Prev check completed and was safe. 126 // Prev check completed and was safe.
192 if (state_ == STATE_NONE) { 127 if (state_ == STATE_NONE) {
193 // Save the redirect urls for possible malware detail reporting later. 128 // Save the redirect urls for possible malware detail reporting later.
194 redirect_urls_.push_back(redirect_info.new_url); 129 redirect_urls_.push_back(new_url);
195 130
196 // We need to check the new URL before following the redirect. 131 // We need to check the new URL before following the redirect.
197 if (CheckUrl(redirect_info.new_url)) 132 DeferDecision decision = CheckUrl(new_url);
198 return; 133 if (decision == PROCEED_SAFE)
134 return PROCEED_SAFE;
135 DCHECK_EQ(decision, DEFER);
199 defer_state_ = DEFERRED_REDIRECT; 136 defer_state_ = DEFERRED_REDIRECT;
200 } else { 137 } else {
201 CHECK(state_ == STATE_CHECKING_URL || 138 DCHECK(state_ == STATE_CHECKING_URL ||
202 state_ == STATE_DISPLAYING_BLOCKING_PAGE); 139 state_ == STATE_DISPLAYING_BLOCKING_PAGE);
140 DCHECK(database_manager_->ChecksAreAlwaysAsync());
203 // We can't check this new URL until we have finished checking 141 // We can't check this new URL until we have finished checking
204 // the prev one, or resumed from the blocking page. 142 // the prev one, or resumed from the blocking page.
205 unchecked_redirect_url_ = redirect_info.new_url; 143 unchecked_redirect_url_ = new_url;
206 defer_state_ = DEFERRED_UNCHECKED_REDIRECT; 144 defer_state_ = DEFERRED_UNCHECKED_REDIRECT;
207 } 145 }
208 146
209 defer_start_time_ = base::TimeTicks::Now(); 147 defer_start_time_ = base::TimeTicks::Now();
210 *defer = true;
211 BeginNetLogEvent( 148 BeginNetLogEvent(
212 NetLogEventType::SAFE_BROWSING_DEFERRED, redirect_info.new_url, 149 NetLogEventType::SAFE_BROWSING_DEFERRED, new_url, "defer_reason",
213 "defer_reason",
214 defer_state_ == DEFERRED_REDIRECT ? "redirect" : "unchecked_redirect"); 150 defer_state_ == DEFERRED_REDIRECT ? "redirect" : "unchecked_redirect");
151 return DEFER;
215 } 152 }
216 153
217 const char* BaseResourceThrottle::GetNameForLogging() const { 154 RequestChecker::DeferDecision RequestChecker::ShouldDeferResponse() {
218 return "BaseResourceThrottle"; 155 CHECK_EQ(defer_state_, DEFERRED_NONE);
156 if (state_ == STATE_CHECKING_URL ||
157 state_ == STATE_DISPLAYING_BLOCKING_PAGE) {
158 DCHECK(database_manager_->ChecksAreAlwaysAsync());
159 defer_state_ = DEFERRED_PROCESSING;
160 defer_start_time_ = base::TimeTicks::Now();
161 BeginNetLogEvent(NetLogEventType::SAFE_BROWSING_DEFERRED, request_->url(),
162 "defer_reason", "at_response");
163 return DEFER;
164 }
165
166 return PROCEED_SAFE;
219 } 167 }
220 168
221 void BaseResourceThrottle::MaybeDestroyPrerenderContents(
222 const content::ResourceRequestInfo* info) {}
223
224 // SafeBrowsingService::Client implementation, called on the IO thread once 169 // SafeBrowsingService::Client implementation, called on the IO thread once
225 // the URL has been classified. 170 // the URL has been classified.
226 void BaseResourceThrottle::OnCheckBrowseUrlResult( 171 void RequestChecker::OnCheckBrowseUrlResult(const GURL& url,
227 const GURL& url, 172 SBThreatType threat_type,
228 SBThreatType threat_type, 173 const ThreatMetadata& metadata) {
229 const ThreatMetadata& metadata) { 174 DCHECK_EQ(state_, STATE_CHECKING_URL);
230 CHECK_EQ(state_, STATE_CHECKING_URL); 175 DCHECK(url.is_valid());
231 CHECK(url.is_valid()); 176 DCHECK(url_being_checked_.is_valid());
232 CHECK(url_being_checked_.is_valid()); 177 DCHECK_EQ(url, url_being_checked_);
233 CHECK_EQ(url, url_being_checked_);
234 178
235 timer_.Stop(); // Cancel the timeout timer. 179 timer_.Stop(); // Cancel the timeout timer.
236 threat_type_ = threat_type; 180 threat_type_ = threat_type;
237 state_ = STATE_NONE; 181 state_ = STATE_NONE;
238 182
239 if (defer_state_ != DEFERRED_NONE) { 183 if (defer_state_ != DEFERRED_NONE) {
240 EndNetLogEvent(NetLogEventType::SAFE_BROWSING_DEFERRED, nullptr, nullptr); 184 EndNetLogEvent(NetLogEventType::SAFE_BROWSING_DEFERRED, nullptr, nullptr);
241 } 185 }
242 EndNetLogEvent( 186 EndNetLogEvent(NetLogEventType::SAFE_BROWSING_CHECKING_URL, "result",
243 NetLogEventType::SAFE_BROWSING_CHECKING_URL, "result", 187 threat_type_ == SB_THREAT_TYPE_SAFE ? "safe" : "unsafe");
244 threat_type_ == SB_THREAT_TYPE_SAFE ? "safe" : "unsafe");
245 188
246 if (threat_type == SB_THREAT_TYPE_SAFE) { 189 if (threat_type == SB_THREAT_TYPE_SAFE) {
247 if (defer_state_ != DEFERRED_NONE) { 190 if (defer_state_ != DEFERRED_NONE) {
248 // Log how much time the safe browsing check cost us. 191 // Log how much time the safe browsing check cost us.
249 ui_manager_->LogPauseDelay(base::TimeTicks::Now() - defer_start_time_); 192 ui_manager_->LogPauseDelay(base::TimeTicks::Now() - defer_start_time_);
250 ResumeRequest(); 193 ResumeRequest();
251 } else { 194 } else {
252 ui_manager_->LogPauseDelay(base::TimeDelta()); 195 ui_manager_->LogPauseDelay(base::TimeDelta());
253 } 196 }
254 return; 197 return;
255 } 198 }
256 199
257 const content::ResourceRequestInfo* info =
258 content::ResourceRequestInfo::ForRequest(request_);
259
260 if (request_->load_flags() & net::LOAD_PREFETCH) { 200 if (request_->load_flags() & net::LOAD_PREFETCH) {
261 // Destroy the prefetch with FINAL_STATUS_SAFEBROSWING. 201 // Destroy the prefetch with FINAL_STATUS_SAFEBROWSING.
262 if (resource_type_ == content::RESOURCE_TYPE_MAIN_FRAME) { 202 if (resource_type_ == content::RESOURCE_TYPE_MAIN_FRAME) {
263 MaybeDestroyPrerenderContents(info); 203 delegate_->MaybeDestroyPrerenderContents(request_);
264 } 204 }
265 // Don't prefetch resources that fail safe browsing, disallow them. 205 // Don't prefetch resources that fail safe browsing, disallow them.
266 Cancel(); 206 delegate_->CancelResourceLoad();
267 UMA_HISTOGRAM_ENUMERATION("SB2.ResourceTypes2.UnsafePrefetchCanceled", 207 UMA_HISTOGRAM_ENUMERATION("SB2.ResourceTypes2.UnsafePrefetchCanceled",
268 resource_type_, content::RESOURCE_TYPE_LAST_TYPE); 208 resource_type_, content::RESOURCE_TYPE_LAST_TYPE);
269 return; 209 return;
270 } 210 }
271 211
272 UMA_HISTOGRAM_ENUMERATION("SB2.ResourceTypes2.Unsafe", resource_type_, 212 UMA_HISTOGRAM_ENUMERATION("SB2.ResourceTypes2.Unsafe", resource_type_,
273 content::RESOURCE_TYPE_LAST_TYPE); 213 content::RESOURCE_TYPE_LAST_TYPE);
274 214
275 security_interstitials::UnsafeResource resource; 215 security_interstitials::UnsafeResource resource;
276 resource.url = url; 216 resource.url = url;
277 resource.original_url = request_->original_url(); 217 resource.original_url = request_->original_url();
278 resource.redirect_urls = redirect_urls_; 218 resource.redirect_urls = redirect_urls_;
279 resource.is_subresource = resource_type_ != content::RESOURCE_TYPE_MAIN_FRAME; 219 resource.is_subresource = resource_type_ != content::RESOURCE_TYPE_MAIN_FRAME;
280 resource.is_subframe = resource_type_ == content::RESOURCE_TYPE_SUB_FRAME; 220 resource.is_subframe = resource_type_ == content::RESOURCE_TYPE_SUB_FRAME;
281 resource.threat_type = threat_type; 221 resource.threat_type = threat_type;
282 resource.threat_metadata = metadata; 222 resource.threat_metadata = metadata;
283 resource.callback = base::Bind( 223 resource.callback = base::Bind(&RequestChecker::OnBlockingPageComplete,
284 &BaseResourceThrottle::OnBlockingPageComplete, AsWeakPtr()); 224 weak_factory_.GetWeakPtr());
285 resource.callback_thread = content::BrowserThread::GetTaskRunnerForThread( 225 resource.callback_thread = content::BrowserThread::GetTaskRunnerForThread(
286 content::BrowserThread::IO); 226 content::BrowserThread::IO);
287 resource.web_contents_getter = info->GetWebContentsGetterForRequest(); 227 resource.web_contents_getter =
228 delegate_->GetWebContentsGetterForRequest(request_);
288 resource.threat_source = database_manager_->GetThreatSource(); 229 resource.threat_source = database_manager_->GetThreatSource();
289 230
290 state_ = STATE_DISPLAYING_BLOCKING_PAGE; 231 state_ = STATE_DISPLAYING_BLOCKING_PAGE;
291 232
292 StartDisplayingBlockingPageHelper(resource); 233 delegate_->StartDisplayingBlockingPage(std::move(resource), ui_manager_);
293 } 234 }
294 235
295 void BaseResourceThrottle::StartDisplayingBlockingPageHelper( 236 void RequestChecker::OnBlockingPageComplete(bool proceed) {
296 security_interstitials::UnsafeResource resource) {
297 content::BrowserThread::PostTask(
298 content::BrowserThread::UI, FROM_HERE,
299 base::Bind(&BaseResourceThrottle::StartDisplayingBlockingPage,
300 AsWeakPtr(), ui_manager_, resource));
301 }
302
303 // Static
304 void BaseResourceThrottle::StartDisplayingBlockingPage(
305 const base::WeakPtr<BaseResourceThrottle>& throttle,
306 scoped_refptr<BaseUIManager> ui_manager,
307 const security_interstitials::UnsafeResource& resource) {
308 content::WebContents* web_contents = resource.web_contents_getter.Run();
309 if (web_contents) {
310 ui_manager->DisplayBlockingPage(resource);
311 return;
312 }
313
314 // Tab is gone or it's being prerendered.
315 content::BrowserThread::PostTask(
316 content::BrowserThread::IO, FROM_HERE,
317 base::Bind(&BaseResourceThrottle::Cancel, throttle));
318 }
319
320 void BaseResourceThrottle::OnBlockingPageComplete(bool proceed) {
321 CHECK_EQ(state_, STATE_DISPLAYING_BLOCKING_PAGE); 237 CHECK_EQ(state_, STATE_DISPLAYING_BLOCKING_PAGE);
322 state_ = STATE_NONE; 238 state_ = STATE_NONE;
323 239
324 if (proceed) { 240 if (proceed) {
325 threat_type_ = SB_THREAT_TYPE_SAFE; 241 threat_type_ = SB_THREAT_TYPE_SAFE;
326 if (defer_state_ != DEFERRED_NONE) { 242 if (defer_state_ != DEFERRED_NONE) {
327 ResumeRequest(); 243 ResumeRequest();
328 } 244 }
329 } else { 245 } else {
330 CancelResourceLoad(); 246 delegate_->CancelResourceLoad();
331 } 247 }
332 } 248 }
333 249
334 void BaseResourceThrottle::CancelResourceLoad() { 250 RequestChecker::DeferDecision RequestChecker::CheckUrl(const GURL& url) {
335 Cancel(); 251 TRACE_EVENT1("loader", "RequestChecker::CheckUrl", "url", url.spec());
336 }
337
338 scoped_refptr<BaseUIManager> BaseResourceThrottle::ui_manager() {
339 return ui_manager_;
340 }
341
342 bool BaseResourceThrottle::CheckUrl(const GURL& url) {
343 TRACE_EVENT1("loader", "BaseResourceThrottle::CheckUrl", "url",
344 url.spec());
345 CHECK_EQ(state_, STATE_NONE); 252 CHECK_EQ(state_, STATE_NONE);
346 // To reduce aggregate latency on mobile, check only the most dangerous 253 // To reduce aggregate latency on mobile, check only the most dangerous
347 // resource types. 254 // resource types.
348 if (!database_manager_->CanCheckResourceType(resource_type_)) { 255 if (!database_manager_->CanCheckResourceType(resource_type_)) {
349 // TODO(vakh): Consider changing this metric to SafeBrowsing.V4ResourceType 256 // TODO(vakh): Consider changing this metric to SafeBrowsing.V4ResourceType
350 // to be consistent with the other PVer4 metrics. 257 // to be consistent with the other PVer4 metrics.
351 UMA_HISTOGRAM_ENUMERATION("SB2.ResourceTypes2.Skipped", resource_type_, 258 UMA_HISTOGRAM_ENUMERATION("SB2.ResourceTypes2.Skipped", resource_type_,
352 content::RESOURCE_TYPE_LAST_TYPE); 259 content::RESOURCE_TYPE_LAST_TYPE);
353 return true; 260 return PROCEED_SKIPPED;
354 } 261 }
355 262
356 // TODO(vakh): Consider changing this metric to SafeBrowsing.V4ResourceType to 263 // TODO(vakh): Consider changing this metric to SafeBrowsing.V4ResourceType to
357 // be consistent with the other PVer4 metrics. 264 // be consistent with the other PVer4 metrics.
358 UMA_HISTOGRAM_ENUMERATION("SB2.ResourceTypes2.Checked", resource_type_, 265 UMA_HISTOGRAM_ENUMERATION("SB2.ResourceTypes2.Checked", resource_type_,
359 content::RESOURCE_TYPE_LAST_TYPE); 266 content::RESOURCE_TYPE_LAST_TYPE);
360 267
361 if (database_manager_->CheckBrowseUrl(url, this)) { 268 if (database_manager_->CheckBrowseUrl(url, this)) {
362 threat_type_ = SB_THREAT_TYPE_SAFE; 269 threat_type_ = SB_THREAT_TYPE_SAFE;
363 ui_manager_->LogPauseDelay(base::TimeDelta()); // No delay. 270 ui_manager_->LogPauseDelay(base::TimeDelta()); // No delay.
364 return true; 271 return PROCEED_SAFE;
365 } 272 }
366 273
367 state_ = STATE_CHECKING_URL; 274 state_ = STATE_CHECKING_URL;
368 url_being_checked_ = url; 275 url_being_checked_ = url;
369 BeginNetLogEvent(NetLogEventType::SAFE_BROWSING_CHECKING_URL, url, nullptr, 276 BeginNetLogEvent(NetLogEventType::SAFE_BROWSING_CHECKING_URL, url, nullptr,
370 nullptr); 277 nullptr);
371 278
372 // Start a timer to abort the check if it takes too long. 279 // Start a timer to abort the check if it takes too long.
373 // TODO(nparker): Set this only when we defer, based on remaining time, 280 // TODO(nparker): Set this only when we defer, based on remaining time,
374 // so we don't cancel earlier than necessary. 281 // so we don't cancel earlier than necessary.
375 timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kCheckUrlTimeoutMs), 282 timer_.Start(FROM_HERE,
376 this, &BaseResourceThrottle::OnCheckUrlTimeout); 283 base::TimeDelta::FromMilliseconds(g_check_url_timeout_ms), this,
284 &RequestChecker::OnCheckUrlTimeout);
377 285
378 return false; 286 return DEFER;
379 } 287 }
380 288
381 void BaseResourceThrottle::OnCheckUrlTimeout() { 289 void RequestChecker::OnCheckUrlTimeout() {
382 CHECK_EQ(state_, STATE_CHECKING_URL); 290 CHECK_EQ(state_, STATE_CHECKING_URL);
383 291
384 database_manager_->CancelCheck(this); 292 database_manager_->CancelCheck(this);
385 293
386 OnCheckBrowseUrlResult(url_being_checked_, safe_browsing::SB_THREAT_TYPE_SAFE, 294 OnCheckBrowseUrlResult(url_being_checked_, safe_browsing::SB_THREAT_TYPE_SAFE,
387 ThreatMetadata()); 295 ThreatMetadata());
388 } 296 }
389 297
390 void BaseResourceThrottle::ResumeRequest() { 298 void RequestChecker::ResumeRequest() {
391 CHECK_EQ(state_, STATE_NONE); 299 CHECK_EQ(state_, STATE_NONE);
392 CHECK_NE(defer_state_, DEFERRED_NONE); 300 CHECK_NE(defer_state_, DEFERRED_NONE);
393 301
394 bool resume = true; 302 bool resume = true;
395 if (defer_state_ == DEFERRED_UNCHECKED_REDIRECT) { 303 if (defer_state_ == DEFERRED_UNCHECKED_REDIRECT) {
304 DCHECK(unchecked_redirect_url_.is_valid());
305 GURL unchecked_redirect_url;
306 unchecked_redirect_url_.Swap(&unchecked_redirect_url);
396 // Save the redirect urls for possible malware detail reporting later. 307 // Save the redirect urls for possible malware detail reporting later.
397 redirect_urls_.push_back(unchecked_redirect_url_); 308 redirect_urls_.push_back(unchecked_redirect_url);
398 if (!CheckUrl(unchecked_redirect_url_)) { 309 if (!CheckUrl(unchecked_redirect_url)) {
399 // We're now waiting for the unchecked_redirect_url_. 310 // We're now waiting for the unchecked_redirect_url.
400 defer_state_ = DEFERRED_REDIRECT; 311 defer_state_ = DEFERRED_REDIRECT;
401 resume = false; 312 resume = false;
402 BeginNetLogEvent(NetLogEventType::SAFE_BROWSING_DEFERRED, 313 BeginNetLogEvent(NetLogEventType::SAFE_BROWSING_DEFERRED,
403 unchecked_redirect_url_, "defer_reason", 314 unchecked_redirect_url, "defer_reason",
404 "resumed_redirect"); 315 "resumed_redirect");
405 } 316 }
406 } 317 }
407 318
408 if (resume) { 319 if (resume) {
409 defer_state_ = DEFERRED_NONE; 320 defer_state_ = DEFERRED_NONE;
410 Resume(); 321 delegate_->ResumeResourceRequest();
411 } 322 }
412 } 323 }
413 324
325 // Note on net_log calls: SAFE_BROWSING_DEFERRED events must be wholly
326 // nested within SAFE_BROWSING_CHECKING_URL events. Synchronous checks
327 // are not logged at all.
328 void RequestChecker::BeginNetLogEvent(NetLogEventType type,
329 const GURL& url,
330 const char* name,
331 const char* value) {
332 net_log_with_source_.BeginEvent(
333 type, base::Bind(&NetLogUrlCallback, request_, url, name, value));
334 request_->net_log().AddEvent(
335 type, net_log_with_source_.source().ToEventParametersCallback());
336 }
337
338 void RequestChecker::EndNetLogEvent(NetLogEventType type,
339 const char* name,
340 const char* value) {
341 net_log_with_source_.EndEvent(type,
342 base::Bind(&NetLogStringCallback, name, value));
343 request_->net_log().AddEvent(
344 type, net_log_with_source_.source().ToEventParametersCallback());
345 }
346
347 ScopedTimeoutForTesting::ScopedTimeoutForTesting(int new_timeout_ms)
348 : original_timeout_ms_(g_check_url_timeout_ms) {
349 g_check_url_timeout_ms = new_timeout_ms;
350 }
351
352 ScopedTimeoutForTesting::ScopedTimeoutForTesting(ScopedTimeoutForTesting&& rhs)
353 : original_timeout_ms_(rhs.original_timeout_ms_) {
354 rhs.original_timeout_ms_ = -1;
355 }
356
357 ScopedTimeoutForTesting::~ScopedTimeoutForTesting() {
358 if (original_timeout_ms_ != -1)
359 g_check_url_timeout_ms = original_timeout_ms_;
360 }
361
414 } // namespace safe_browsing 362 } // namespace safe_browsing
OLDNEW
« no previous file with comments | « components/safe_browsing/request_checker.h ('k') | components/safe_browsing/request_checker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698