[sql] Remove _HAS_EXCEPTIONS=0 from build info.
[chromium-blink-merge.git] / chrome / browser / renderer_host / safe_browsing_resource_throttle.cc
blobd30e57a074f2aed37c9acb499ddd35150b7e89ca
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/renderer_host/safe_browsing_resource_throttle.h"
7 #include "base/logging.h"
8 #include "chrome/browser/browser_process.h"
9 #include "chrome/browser/prerender/prerender_contents.h"
10 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "content/public/browser/render_view_host.h"
13 #include "content/public/browser/resource_controller.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"
17 #include "net/url_request/redirect_info.h"
18 #include "net/url_request/url_request.h"
20 // Maximum time in milliseconds to wait for the safe browsing service to
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.
23 static const int kCheckUrlTimeoutMs = 5000;
25 // TODO(eroman): Downgrade these CHECK()s to DCHECKs once there is more
26 // unit test coverage.
28 SafeBrowsingResourceThrottle::SafeBrowsingResourceThrottle(
29 const net::URLRequest* request,
30 content::ResourceType resource_type,
31 SafeBrowsingService* safe_browsing,
32 bool defer_at_start)
33 : defer_at_start_(defer_at_start),
34 state_(STATE_NONE),
35 defer_state_(DEFERRED_NONE),
36 threat_type_(SB_THREAT_TYPE_SAFE),
37 database_manager_(safe_browsing->database_manager()),
38 ui_manager_(safe_browsing->ui_manager()),
39 request_(request),
40 is_subresource_(resource_type != content::RESOURCE_TYPE_MAIN_FRAME),
41 is_subframe_(resource_type == content::RESOURCE_TYPE_SUB_FRAME) {
44 SafeBrowsingResourceThrottle::~SafeBrowsingResourceThrottle() {
45 if (state_ == STATE_CHECKING_URL)
46 database_manager_->CancelCheck(this);
49 void SafeBrowsingResourceThrottle::WillStartRequest(bool* defer) {
50 // We need to check the new URL before starting the request.
51 if (CheckUrl(request_->url()))
52 return;
54 if (!defer_at_start_)
55 return;
57 // If the URL couldn't be verified synchronously, defer starting the
58 // request until the check has completed.
59 defer_state_ = DEFERRED_START;
60 defer_start_time_ = base::TimeTicks::Now();
61 *defer = true;
64 void SafeBrowsingResourceThrottle::WillProcessResponse(bool* defer) {
65 CHECK_EQ(defer_state_, DEFERRED_NONE);
66 if (defer_at_start_)
67 return;
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;
77 void SafeBrowsingResourceThrottle::WillRedirectRequest(
78 const net::RedirectInfo& redirect_info,
79 bool* defer) {
80 CHECK_EQ(defer_state_, DEFERRED_NONE);
82 // Prev check completed and was safe.
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);
87 // We need to check the new URL before following the redirect.
88 if (CheckUrl(redirect_info.new_url))
89 return;
90 defer_state_ = DEFERRED_REDIRECT;
91 } else {
92 CHECK(state_ == STATE_CHECKING_URL ||
93 state_ == STATE_DISPLAYING_BLOCKING_PAGE);
94 // We can't check this new URL until we have finished checking
95 // the prev one, or resumed from the blocking page.
96 unchecked_redirect_url_ = redirect_info.new_url;
97 defer_state_ = DEFERRED_UNCHECKED_REDIRECT;
100 defer_start_time_ = base::TimeTicks::Now();
101 *defer = true;
104 const char* SafeBrowsingResourceThrottle::GetNameForLogging() const {
105 return "SafeBrowsingResourceThrottle";
108 // SafeBrowsingService::Client implementation, called on the IO thread once
109 // the URL has been classified.
110 void SafeBrowsingResourceThrottle::OnCheckBrowseUrlResult(
111 const GURL& url,
112 SBThreatType threat_type,
113 const std::string& metadata) {
114 CHECK_EQ(state_, STATE_CHECKING_URL);
115 CHECK_EQ(url, url_being_checked_);
117 timer_.Stop(); // Cancel the timeout timer.
118 threat_type_ = threat_type;
119 state_ = STATE_NONE;
121 if (threat_type == SB_THREAT_TYPE_SAFE) {
122 if (defer_state_ != DEFERRED_NONE) {
123 // Log how much time the safe browsing check cost us.
124 ui_manager_->LogPauseDelay(base::TimeTicks::Now() - defer_start_time_);
125 ResumeRequest();
126 } else {
127 ui_manager_->LogPauseDelay(base::TimeDelta());
129 return;
132 if (request_->load_flags() & net::LOAD_PREFETCH) {
133 // Don't prefetch resources that fail safe browsing, disallow them.
134 controller()->Cancel();
135 return;
138 const content::ResourceRequestInfo* info =
139 content::ResourceRequestInfo::ForRequest(request_);
141 SafeBrowsingUIManager::UnsafeResource resource;
142 resource.url = url;
143 resource.original_url = request_->original_url();
144 resource.redirect_urls = redirect_urls_;
145 resource.is_subresource = is_subresource_;
146 resource.is_subframe = is_subframe_;
147 resource.threat_type = threat_type;
148 resource.threat_metadata = metadata;
149 resource.callback = base::Bind(
150 &SafeBrowsingResourceThrottle::OnBlockingPageComplete, AsWeakPtr());
151 resource.render_process_host_id = info->GetChildID();
152 resource.render_view_id = info->GetRouteID();
154 state_ = STATE_DISPLAYING_BLOCKING_PAGE;
156 content::BrowserThread::PostTask(
157 content::BrowserThread::UI,
158 FROM_HERE,
159 base::Bind(&SafeBrowsingResourceThrottle::StartDisplayingBlockingPage,
160 AsWeakPtr(), ui_manager_, resource));
163 void SafeBrowsingResourceThrottle::StartDisplayingBlockingPage(
164 const base::WeakPtr<SafeBrowsingResourceThrottle>& throttle,
165 scoped_refptr<SafeBrowsingUIManager> ui_manager,
166 const SafeBrowsingUIManager::UnsafeResource& resource) {
167 content::RenderViewHost* rvh = content::RenderViewHost::FromID(
168 resource.render_process_host_id, resource.render_view_id);
169 if (rvh) {
170 content::WebContents* web_contents =
171 content::WebContents::FromRenderViewHost(rvh);
172 prerender::PrerenderContents* prerender_contents =
173 prerender::PrerenderContents::FromWebContents(web_contents);
175 if (prerender_contents) {
176 prerender_contents->Destroy(prerender::FINAL_STATUS_SAFE_BROWSING);
177 } else {
178 ui_manager->DisplayBlockingPage(resource);
179 return;
183 // Tab is gone or it's being prerendered.
184 content::BrowserThread::PostTask(
185 content::BrowserThread::IO,
186 FROM_HERE,
187 base::Bind(&SafeBrowsingResourceThrottle::Cancel, throttle));
190 void SafeBrowsingResourceThrottle::Cancel() {
191 controller()->Cancel();
194 // SafeBrowsingService::UrlCheckCallback implementation, called on the IO
195 // thread when the user has decided to proceed with the current request, or
196 // go back.
197 void SafeBrowsingResourceThrottle::OnBlockingPageComplete(bool proceed) {
198 CHECK_EQ(state_, STATE_DISPLAYING_BLOCKING_PAGE);
199 state_ = STATE_NONE;
201 if (proceed) {
202 threat_type_ = SB_THREAT_TYPE_SAFE;
203 if (defer_state_ != DEFERRED_NONE) {
204 ResumeRequest();
206 } else {
207 controller()->Cancel();
211 bool SafeBrowsingResourceThrottle::CheckUrl(const GURL& url) {
212 CHECK_EQ(state_, STATE_NONE);
213 bool succeeded_synchronously = database_manager_->CheckBrowseUrl(url, this);
214 if (succeeded_synchronously) {
215 threat_type_ = SB_THREAT_TYPE_SAFE;
216 ui_manager_->LogPauseDelay(base::TimeDelta()); // No delay.
217 return true;
220 state_ = STATE_CHECKING_URL;
221 url_being_checked_ = url;
223 // Start a timer to abort the check if it takes too long.
224 // TODO(nparker): Set this only when we defer, based on remaining time,
225 // so we don't cancel earlier than necessary.
226 timer_.Start(FROM_HERE,
227 base::TimeDelta::FromMilliseconds(kCheckUrlTimeoutMs),
228 this, &SafeBrowsingResourceThrottle::OnCheckUrlTimeout);
230 return false;
233 void SafeBrowsingResourceThrottle::OnCheckUrlTimeout() {
234 CHECK_EQ(state_, STATE_CHECKING_URL);
236 database_manager_->CancelCheck(this);
237 OnCheckBrowseUrlResult(
238 url_being_checked_, SB_THREAT_TYPE_SAFE, std::string());
241 void SafeBrowsingResourceThrottle::ResumeRequest() {
242 CHECK_EQ(state_, STATE_NONE);
243 CHECK_NE(defer_state_, DEFERRED_NONE);
245 bool resume = true;
246 if (defer_state_ == DEFERRED_UNCHECKED_REDIRECT) {
247 // Save the redirect urls for possible malware detail reporting later.
248 redirect_urls_.push_back(unchecked_redirect_url_);
249 if (!CheckUrl(unchecked_redirect_url_)) {
250 // We're now waiting for the unchecked_redirect_url_.
251 defer_state_ = DEFERRED_REDIRECT;
252 resume = false;
256 if (resume) {
257 defer_state_ = DEFERRED_NONE;
258 controller()->Resume();