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

Side by Side Diff: chrome/browser/renderer_host/safe_browsing_resource_throttle.cc

Issue 1241583009: Async Safe Browsing check, on mobile (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove logging, fixup comments Created 5 years, 5 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) 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/renderer_host/safe_browsing_resource_throttle.h" 5 #include "chrome/browser/renderer_host/safe_browsing_resource_throttle.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "chrome/browser/browser_process.h" 8 #include "chrome/browser/browser_process.h"
9 #include "chrome/browser/prerender/prerender_contents.h" 9 #include "chrome/browser/prerender/prerender_contents.h"
10 #include "chrome/browser/safe_browsing/safe_browsing_service.h" 10 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
(...skipping 10 matching lines...) Expand all
21 // verify a URL. After this amount of time the outstanding check will be 21 // verify a URL. After this amount of time the outstanding check will be
22 // aborted, and the URL will be treated as if it were safe. 22 // aborted, and the URL will be treated as if it were safe.
23 static const int kCheckUrlTimeoutMs = 5000; 23 static const int kCheckUrlTimeoutMs = 5000;
24 24
25 // TODO(eroman): Downgrade these CHECK()s to DCHECKs once there is more 25 // TODO(eroman): Downgrade these CHECK()s to DCHECKs once there is more
26 // unit test coverage. 26 // unit test coverage.
27 27
28 SafeBrowsingResourceThrottle::SafeBrowsingResourceThrottle( 28 SafeBrowsingResourceThrottle::SafeBrowsingResourceThrottle(
29 const net::URLRequest* request, 29 const net::URLRequest* request,
30 content::ResourceType resource_type, 30 content::ResourceType resource_type,
31 SafeBrowsingService* safe_browsing) 31 SafeBrowsingService* safe_browsing,
32 : state_(STATE_NONE), 32 bool defer_at_start)
33 : defer_at_start_(defer_at_start),
34 state_(STATE_NONE),
33 defer_state_(DEFERRED_NONE), 35 defer_state_(DEFERRED_NONE),
34 threat_type_(SB_THREAT_TYPE_SAFE), 36 threat_type_(SB_THREAT_TYPE_SAFE),
35 database_manager_(safe_browsing->database_manager()), 37 database_manager_(safe_browsing->database_manager()),
36 ui_manager_(safe_browsing->ui_manager()), 38 ui_manager_(safe_browsing->ui_manager()),
37 request_(request), 39 request_(request),
38 is_subresource_(resource_type != content::RESOURCE_TYPE_MAIN_FRAME), 40 is_subresource_(resource_type != content::RESOURCE_TYPE_MAIN_FRAME),
39 is_subframe_(resource_type == content::RESOURCE_TYPE_SUB_FRAME) { 41 is_subframe_(resource_type == content::RESOURCE_TYPE_SUB_FRAME) {
40 } 42 }
41 43
42 SafeBrowsingResourceThrottle::~SafeBrowsingResourceThrottle() { 44 SafeBrowsingResourceThrottle::~SafeBrowsingResourceThrottle() {
43 if (state_ == STATE_CHECKING_URL) 45 if (state_ == STATE_CHECKING_URL)
44 database_manager_->CancelCheck(this); 46 database_manager_->CancelCheck(this);
45 } 47 }
46 48
47 void SafeBrowsingResourceThrottle::WillStartRequest(bool* defer) { 49 void SafeBrowsingResourceThrottle::WillStartRequest(bool* defer) {
48 // We need to check the new URL before starting the request. 50 // We need to check the new URL before starting the request.
49 if (CheckUrl(request_->url())) 51 if (CheckUrl(request_->url()))
50 return; 52 return;
51 53
54 if (!defer_at_start_)
55 return;
56
52 // If the URL couldn't be verified synchronously, defer starting the 57 // If the URL couldn't be verified synchronously, defer starting the
53 // request until the check has completed. 58 // request until the check has completed.
54 defer_state_ = DEFERRED_START; 59 defer_state_ = DEFERRED_START;
60 defer_start_time_ = base::TimeTicks::Now();
55 *defer = true; 61 *defer = true;
56 } 62 }
57 63
64 void SafeBrowsingResourceThrottle::WillProcessResponse(bool* defer) {
65 CHECK_EQ(defer_state_, DEFERRED_NONE);
66 if (defer_at_start_)
67 return;
68
69 if (state_ == STATE_CHECKING_URL ||
70 state_ == STATE_DISPLAYING_BLOCKING_PAGE) {
71 defer_state_ = DEFERRED_PROCESSING;
72 defer_start_time_ = base::TimeTicks::Now();
73 *defer = true;
74 }
75 }
76
58 void SafeBrowsingResourceThrottle::WillRedirectRequest( 77 void SafeBrowsingResourceThrottle::WillRedirectRequest(
59 const net::RedirectInfo& redirect_info, 78 const net::RedirectInfo& redirect_info,
60 bool* defer) { 79 bool* defer) {
61 CHECK(state_ == STATE_NONE); 80 CHECK_EQ(defer_state_, DEFERRED_NONE);
62 CHECK(defer_state_ == DEFERRED_NONE);
63 81
64 // Save the redirect urls for possible malware detail reporting later. 82 // Prev check completed and was safe.
65 redirect_urls_.push_back(redirect_info.new_url); 83 if (state_ == STATE_NONE) {
84 // Save the redirect urls for possible malware detail reporting later.
85 redirect_urls_.push_back(redirect_info.new_url);
66 86
67 // We need to check the new URL before following the redirect. 87 // We need to check the new URL before following the redirect.
68 if (CheckUrl(redirect_info.new_url)) 88 if (CheckUrl(redirect_info.new_url))
69 return; 89 return;
70 90
71 // If the URL couldn't be verified synchronously, defer following the 91 defer_state_ = DEFERRED_REDIRECT;
72 // redirect until the SafeBrowsing check is complete. Store the redirect 92 } else {
73 // context so we can pass it on to other handlers once we have completed 93 CHECK(state_ == STATE_CHECKING_URL ||
74 // our check. 94 state_ == STATE_DISPLAYING_BLOCKING_PAGE);
75 defer_state_ = DEFERRED_REDIRECT; 95 // We can't check this new URL until we have finished checking
96 // the prev one, or resumed from the blocking page.
97 unchecked_redirect_url_ = redirect_info.new_url;
98 defer_state_ = DEFERRED_UNCHECKED_REDIRECT;
99 }
100
101 defer_start_time_ = base::TimeTicks::Now();
76 *defer = true; 102 *defer = true;
77 } 103 }
78 104
79 const char* SafeBrowsingResourceThrottle::GetNameForLogging() const { 105 const char* SafeBrowsingResourceThrottle::GetNameForLogging() const {
80 return "SafeBrowsingResourceThrottle"; 106 return "SafeBrowsingResourceThrottle";
81 } 107 }
82 108
83 // SafeBrowsingService::Client implementation, called on the IO thread once 109 // SafeBrowsingService::Client implementation, called on the IO thread once
84 // the URL has been classified. 110 // the URL has been classified.
85 void SafeBrowsingResourceThrottle::OnCheckBrowseUrlResult( 111 void SafeBrowsingResourceThrottle::OnCheckBrowseUrlResult(
86 const GURL& url, 112 const GURL& url,
87 SBThreatType threat_type, 113 SBThreatType threat_type,
88 const std::string& metadata) { 114 const std::string& metadata) {
89 CHECK(state_ == STATE_CHECKING_URL); 115 CHECK_EQ(state_, STATE_CHECKING_URL);
90 CHECK(defer_state_ != DEFERRED_NONE); 116 CHECK_EQ(url, url_being_checked_);
91 CHECK(url == url_being_checked_) << "Was expecting: " << url_being_checked_
92 << " but got: " << url;
93 117
94 timer_.Stop(); // Cancel the timeout timer. 118 timer_.Stop(); // Cancel the timeout timer.
95 threat_type_ = threat_type; 119 threat_type_ = threat_type;
96 state_ = STATE_NONE; 120 state_ = STATE_NONE;
97 121
98 if (threat_type == SB_THREAT_TYPE_SAFE) { 122 if (threat_type == SB_THREAT_TYPE_SAFE) {
99 // Log how much time the safe browsing check cost us. 123 if (defer_state_ != DEFERRED_NONE) {
100 ui_manager_->LogPauseDelay(base::TimeTicks::Now() - url_check_start_time_); 124 // Log how much time the safe browsing check cost us.
101 125 ui_manager_->LogPauseDelay(base::TimeTicks::Now() - defer_start_time_);
102 // Continue the request. 126 ResumeRequest();
103 ResumeRequest(); 127 } else {
128 ui_manager_->LogPauseDelay(base::TimeDelta());
129 }
104 return; 130 return;
105 } 131 }
106 132
107 if (request_->load_flags() & net::LOAD_PREFETCH) { 133 if (request_->load_flags() & net::LOAD_PREFETCH) {
108 // Don't prefetch resources that fail safe browsing, disallow 134 // Don't prefetch resources that fail safe browsing, disallow them.
109 // them.
110 controller()->Cancel(); 135 controller()->Cancel();
111 return; 136 return;
112 } 137 }
113 138
114 const content::ResourceRequestInfo* info = 139 const content::ResourceRequestInfo* info =
115 content::ResourceRequestInfo::ForRequest(request_); 140 content::ResourceRequestInfo::ForRequest(request_);
116 141
117 SafeBrowsingUIManager::UnsafeResource resource; 142 SafeBrowsingUIManager::UnsafeResource resource;
118 resource.url = url; 143 resource.url = url;
119 resource.original_url = request_->original_url(); 144 resource.original_url = request_->original_url();
(...skipping 13 matching lines...) Expand all
133 content::BrowserThread::UI, 158 content::BrowserThread::UI,
134 FROM_HERE, 159 FROM_HERE,
135 base::Bind(&SafeBrowsingResourceThrottle::StartDisplayingBlockingPage, 160 base::Bind(&SafeBrowsingResourceThrottle::StartDisplayingBlockingPage,
136 AsWeakPtr(), ui_manager_, resource)); 161 AsWeakPtr(), ui_manager_, resource));
137 } 162 }
138 163
139 void SafeBrowsingResourceThrottle::StartDisplayingBlockingPage( 164 void SafeBrowsingResourceThrottle::StartDisplayingBlockingPage(
140 const base::WeakPtr<SafeBrowsingResourceThrottle>& throttle, 165 const base::WeakPtr<SafeBrowsingResourceThrottle>& throttle,
141 scoped_refptr<SafeBrowsingUIManager> ui_manager, 166 scoped_refptr<SafeBrowsingUIManager> ui_manager,
142 const SafeBrowsingUIManager::UnsafeResource& resource) { 167 const SafeBrowsingUIManager::UnsafeResource& resource) {
143 bool should_show_blocking_page = true;
144
145 content::RenderViewHost* rvh = content::RenderViewHost::FromID( 168 content::RenderViewHost* rvh = content::RenderViewHost::FromID(
146 resource.render_process_host_id, resource.render_view_id); 169 resource.render_process_host_id, resource.render_view_id);
147 if (rvh) { 170 if (rvh) {
148 content::WebContents* web_contents = 171 content::WebContents* web_contents =
149 content::WebContents::FromRenderViewHost(rvh); 172 content::WebContents::FromRenderViewHost(rvh);
150 prerender::PrerenderContents* prerender_contents = 173 prerender::PrerenderContents* prerender_contents =
151 prerender::PrerenderContents::FromWebContents(web_contents); 174 prerender::PrerenderContents::FromWebContents(web_contents);
175
152 if (prerender_contents) { 176 if (prerender_contents) {
153 prerender_contents->Destroy(prerender::FINAL_STATUS_SAFE_BROWSING); 177 prerender_contents->Destroy(prerender::FINAL_STATUS_SAFE_BROWSING);
154 should_show_blocking_page = false; 178 } else {
155 }
156
157 if (should_show_blocking_page) {
158 ui_manager->DisplayBlockingPage(resource); 179 ui_manager->DisplayBlockingPage(resource);
159 return; 180 return;
160 } 181 }
161 } 182 }
162 183
163 // Tab is gone or it's being prerendered. 184 // Tab is gone or it's being prerendered.
164 content::BrowserThread::PostTask( 185 content::BrowserThread::PostTask(
165 content::BrowserThread::IO, 186 content::BrowserThread::IO,
166 FROM_HERE, 187 FROM_HERE,
167 base::Bind(&SafeBrowsingResourceThrottle::Cancel, throttle)); 188 base::Bind(&SafeBrowsingResourceThrottle::Cancel, throttle));
168 } 189 }
169 190
170 void SafeBrowsingResourceThrottle::Cancel() { 191 void SafeBrowsingResourceThrottle::Cancel() {
171 controller()->Cancel(); 192 controller()->Cancel();
172 } 193 }
173 194
174 // SafeBrowsingService::UrlCheckCallback implementation, called on the IO 195 // SafeBrowsingService::UrlCheckCallback implementation, called on the IO
175 // thread when the user has decided to proceed with the current request, or 196 // thread when the user has decided to proceed with the current request, or
176 // go back. 197 // go back.
177 void SafeBrowsingResourceThrottle::OnBlockingPageComplete(bool proceed) { 198 void SafeBrowsingResourceThrottle::OnBlockingPageComplete(bool proceed) {
178 CHECK(state_ == STATE_DISPLAYING_BLOCKING_PAGE); 199 CHECK_EQ(state_, STATE_DISPLAYING_BLOCKING_PAGE);
179 state_ = STATE_NONE; 200 state_ = STATE_NONE;
180 201
181 if (proceed) { 202 if (proceed) {
182 threat_type_ = SB_THREAT_TYPE_SAFE; 203 threat_type_ = SB_THREAT_TYPE_SAFE;
183 ResumeRequest(); 204 if (defer_state_ != DEFERRED_NONE) {
205 ResumeRequest();
206 }
184 } else { 207 } else {
185 controller()->Cancel(); 208 controller()->Cancel();
186 } 209 }
187 } 210 }
188 211
189 bool SafeBrowsingResourceThrottle::CheckUrl(const GURL& url) { 212 bool SafeBrowsingResourceThrottle::CheckUrl(const GURL& url) {
190 CHECK(state_ == STATE_NONE); 213 CHECK_EQ(state_, STATE_NONE);
191 bool succeeded_synchronously = database_manager_->CheckBrowseUrl(url, this); 214 bool succeeded_synchronously = database_manager_->CheckBrowseUrl(url, this);
192 if (succeeded_synchronously) { 215 if (succeeded_synchronously) {
193 threat_type_ = SB_THREAT_TYPE_SAFE; 216 threat_type_ = SB_THREAT_TYPE_SAFE;
194 ui_manager_->LogPauseDelay(base::TimeDelta()); // No delay. 217 ui_manager_->LogPauseDelay(base::TimeDelta()); // No delay.
195 return true; 218 return true;
196 } 219 }
197 220
198 state_ = STATE_CHECKING_URL; 221 state_ = STATE_CHECKING_URL;
199 url_being_checked_ = url; 222 url_being_checked_ = url;
200 223
201 // Record the start time of the check.
202 url_check_start_time_ = base::TimeTicks::Now();
203
204 // Start a timer to abort the check if it takes too long. 224 // Start a timer to abort the check if it takes too long.
225 // TODO(nparker): Set this only when we defer, based on remaining time,
226 // so we don't cancel earlier than necessary.
205 timer_.Start(FROM_HERE, 227 timer_.Start(FROM_HERE,
206 base::TimeDelta::FromMilliseconds(kCheckUrlTimeoutMs), 228 base::TimeDelta::FromMilliseconds(kCheckUrlTimeoutMs),
207 this, &SafeBrowsingResourceThrottle::OnCheckUrlTimeout); 229 this, &SafeBrowsingResourceThrottle::OnCheckUrlTimeout);
208 230
209 return false; 231 return false;
210 } 232 }
211 233
212 void SafeBrowsingResourceThrottle::OnCheckUrlTimeout() { 234 void SafeBrowsingResourceThrottle::OnCheckUrlTimeout() {
213 CHECK(state_ == STATE_CHECKING_URL); 235 CHECK_EQ(state_, STATE_CHECKING_URL);
214 CHECK(defer_state_ != DEFERRED_NONE);
215 236
216 database_manager_->CancelCheck(this); 237 database_manager_->CancelCheck(this);
217 OnCheckBrowseUrlResult( 238 OnCheckBrowseUrlResult(
218 url_being_checked_, SB_THREAT_TYPE_SAFE, std::string()); 239 url_being_checked_, SB_THREAT_TYPE_SAFE, std::string());
219 } 240 }
220 241
221 void SafeBrowsingResourceThrottle::ResumeRequest() { 242 void SafeBrowsingResourceThrottle::ResumeRequest() {
222 CHECK(state_ == STATE_NONE); 243 CHECK_EQ(state_, STATE_NONE);
223 CHECK(defer_state_ != DEFERRED_NONE); 244 CHECK_NE(defer_state_, DEFERRED_NONE);
224 245
225 defer_state_ = DEFERRED_NONE; 246 if (defer_state_ == DEFERRED_UNCHECKED_REDIRECT &&
mattm 2015/07/24 23:24:11 should do redirect_urls_.push_back(unchecked_redir
Nathan Parker 2015/07/28 17:42:12 Good catch. I changed WillRedirectRequest() to al
226 controller()->Resume(); 247 !CheckUrl(unchecked_redirect_url_)) {
248 defer_state_ = DEFERRED_REDIRECT;
249 // We're now waiting for the unchecked_redirect_url_.
250 } else {
251 defer_state_ = DEFERRED_NONE;
252 controller()->Resume();
253 }
227 } 254 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698