1 // Copyright 2015 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/data_reduction_proxy_resource_throttle_android.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/renderer_host/safe_browsing_resource_throttle_factory.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "content/public/browser/render_view_host.h"
13 #include "content/public/browser/resource_context.h"
14 #include "content/public/browser/resource_controller.h"
15 #include "content/public/browser/resource_request_info.h"
16 #include "content/public/browser/web_contents.h"
17 #include "net/base/load_flags.h"
18 #include "net/http/http_response_headers.h"
19 #include "net/url_request/redirect_info.h"
20 #include "net/url_request/url_request.h"
22 #if defined(SAFE_BROWSING_DB_LOCAL) || defined(SAFE_BROWSING_DB_REMOTE)
23 #include "chrome/browser/profiles/profile_io_data.h"
24 #include "chrome/browser/renderer_host/safe_browsing_resource_throttle.h"
27 using content::BrowserThread
;
28 using content::ResourceThrottle
;
30 // TODO(eroman): Downgrade these CHECK()s to DCHECKs once there is more
31 // unit test coverage.
32 // TODO(sgurun) following the comment above, also provide tests for
33 // checking whether the headers are injected correctly and the SPDY proxy
34 // origin is tested properly.
36 const char* DataReductionProxyResourceThrottle::kUnsafeUrlProceedHeader
=
37 "X-Unsafe-Url-Proceed";
40 DataReductionProxyResourceThrottleFactory::CreateResourceThrottle(
41 net::URLRequest
* request
,
42 content::ResourceContext
* resource_context
,
43 content::ResourceType resource_type
,
44 SafeBrowsingService
* service
) {
45 #if defined(SAFE_BROWSING_DB_LOCAL) || defined(SAFE_BROWSING_DB_REMOTE)
46 ProfileIOData
* io_data
= ProfileIOData::FromResourceContext(resource_context
);
47 if (io_data
->IsOffTheRecord() || !io_data
->IsDataReductionProxyEnabled() ||
48 request
->url().SchemeIsSecure())
49 return new SafeBrowsingResourceThrottle(request
, resource_type
, service
);
51 return new DataReductionProxyResourceThrottle(request
, resource_type
,
55 DataReductionProxyResourceThrottle::DataReductionProxyResourceThrottle(
56 net::URLRequest
* request
,
57 content::ResourceType resource_type
,
58 SafeBrowsingService
* safe_browsing
)
60 safe_browsing_(safe_browsing
),
62 is_subresource_(resource_type
!= content::RESOURCE_TYPE_MAIN_FRAME
),
63 is_subframe_(resource_type
== content::RESOURCE_TYPE_SUB_FRAME
) {
66 DataReductionProxyResourceThrottle::~DataReductionProxyResourceThrottle() { }
68 void DataReductionProxyResourceThrottle::WillRedirectRequest(
69 const net::RedirectInfo
& redirect_info
,
71 CHECK(state_
== STATE_NONE
);
73 // Save the redirect urls for possible malware detail reporting later.
74 redirect_urls_
.push_back(redirect_info
.new_url
);
76 // We need to check the new URL before following the redirect.
77 SBThreatType threat_type
= CheckUrl();
78 if (threat_type
== SB_THREAT_TYPE_SAFE
)
81 if (request_
->load_flags() & net::LOAD_PREFETCH
) {
82 controller()->Cancel();
85 const content::ResourceRequestInfo
* info
=
86 content::ResourceRequestInfo::ForRequest(request_
);
88 state_
= STATE_DISPLAYING_BLOCKING_PAGE
;
89 SafeBrowsingUIManager::UnsafeResource unsafe_resource
;
90 unsafe_resource
.url
= redirect_info
.new_url
;
91 unsafe_resource
.original_url
= request_
->original_url();
92 unsafe_resource
.redirect_urls
= redirect_urls_
;
93 unsafe_resource
.is_subresource
= is_subresource_
;
94 unsafe_resource
.is_subframe
= is_subframe_
;
95 unsafe_resource
.threat_type
= threat_type
;
96 unsafe_resource
.callback
= base::Bind(
97 &DataReductionProxyResourceThrottle::OnBlockingPageComplete
, AsWeakPtr());
98 unsafe_resource
.render_process_host_id
= info
->GetChildID();
99 unsafe_resource
.render_view_id
= info
->GetRouteID();
103 content::BrowserThread::PostTask(
104 content::BrowserThread::UI
, FROM_HERE
,
106 &DataReductionProxyResourceThrottle::StartDisplayingBlockingPage
,
107 AsWeakPtr(), safe_browsing_
->ui_manager(), unsafe_resource
));
110 const char* DataReductionProxyResourceThrottle::GetNameForLogging() const {
111 return "DataReductionProxyResourceThrottle";
115 void DataReductionProxyResourceThrottle::StartDisplayingBlockingPage(
116 const base::WeakPtr
<DataReductionProxyResourceThrottle
>& throttle
,
117 scoped_refptr
<SafeBrowsingUIManager
> ui_manager
,
118 const SafeBrowsingUIManager::UnsafeResource
& resource
) {
119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
121 content::RenderViewHost
* rvh
= content::RenderViewHost::FromID(
122 resource
.render_process_host_id
, resource
.render_view_id
);
124 content::WebContents
* web_contents
=
125 content::WebContents::FromRenderViewHost(rvh
);
126 prerender::PrerenderContents
* prerender_contents
=
127 prerender::PrerenderContents::FromWebContents(web_contents
);
128 if (prerender_contents
) {
129 prerender_contents
->Destroy(prerender::FINAL_STATUS_SAFE_BROWSING
);
130 content::BrowserThread::PostTask(
131 content::BrowserThread::IO
,
133 base::Bind(resource
.callback
, false));
137 ui_manager
->DisplayBlockingPage(resource
);
140 // SafeBrowsingService::UrlCheckCallback implementation, called on the IO
141 // thread when the user has decided to proceed with the current request, or
143 void DataReductionProxyResourceThrottle::OnBlockingPageComplete(bool proceed
) {
144 CHECK(state_
== STATE_DISPLAYING_BLOCKING_PAGE
);
150 controller()->Cancel();
153 SBThreatType
DataReductionProxyResourceThrottle::CheckUrl() {
154 SBThreatType result
= SB_THREAT_TYPE_SAFE
;
156 // TODO(sgurun) Check for spdy proxy origin.
157 if (request_
->response_headers() == NULL
)
160 if (request_
->response_headers()->HasHeader("X-Phishing-Url"))
161 result
= SB_THREAT_TYPE_URL_PHISHING
;
162 else if (request_
->response_headers()->HasHeader("X-Malware-Url"))
163 result
= SB_THREAT_TYPE_URL_MALWARE
;
165 // If safe browsing is disabled and the request is sent to the DRP server,
166 // we need to break the redirect loop by setting the extra header.
167 if (result
!= SB_THREAT_TYPE_SAFE
&& !safe_browsing_
->enabled()) {
168 request_
->SetExtraRequestHeaderByName(kUnsafeUrlProceedHeader
, "1", true);
169 result
= SB_THREAT_TYPE_SAFE
;
175 void DataReductionProxyResourceThrottle::ResumeRequest() {
176 CHECK(state_
== STATE_NONE
);
178 // Inject the header before resuming the request.
179 request_
->SetExtraRequestHeaderByName(kUnsafeUrlProceedHeader
, "1", true);
180 controller()->Resume();