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 // Send requests through Safe Browsing if we can't process them.
47 ProfileIOData
* io_data
= ProfileIOData::FromResourceContext(resource_context
);
48 if (io_data
->IsOffTheRecord() || !io_data
->IsDataReductionProxyEnabled() ||
49 request
->url().SchemeIsSecure()) {
50 // *this is already registered as the SafeBrowsingResourceThrottleFactory,
51 // so need to bypass that and use its base implementation.
52 return SafeBrowsingResourceThrottleFactory::CreateWithoutRegisteredFactory(
53 request
, resource_type
, service
);
56 return new DataReductionProxyResourceThrottle(request
, resource_type
,
60 DataReductionProxyResourceThrottle::DataReductionProxyResourceThrottle(
61 net::URLRequest
* request
,
62 content::ResourceType resource_type
,
63 SafeBrowsingService
* safe_browsing
)
65 safe_browsing_(safe_browsing
),
67 is_subresource_(resource_type
!= content::RESOURCE_TYPE_MAIN_FRAME
),
68 is_subframe_(resource_type
== content::RESOURCE_TYPE_SUB_FRAME
) {
71 DataReductionProxyResourceThrottle::~DataReductionProxyResourceThrottle() { }
73 void DataReductionProxyResourceThrottle::WillRedirectRequest(
74 const net::RedirectInfo
& redirect_info
,
76 CHECK(state_
== STATE_NONE
);
78 // Save the redirect urls for possible malware detail reporting later.
79 redirect_urls_
.push_back(redirect_info
.new_url
);
81 // We need to check the new URL before following the redirect.
82 SBThreatType threat_type
= CheckUrl();
83 if (threat_type
== SB_THREAT_TYPE_SAFE
)
86 if (request_
->load_flags() & net::LOAD_PREFETCH
) {
87 controller()->Cancel();
90 const content::ResourceRequestInfo
* info
=
91 content::ResourceRequestInfo::ForRequest(request_
);
93 state_
= STATE_DISPLAYING_BLOCKING_PAGE
;
94 SafeBrowsingUIManager::UnsafeResource unsafe_resource
;
95 unsafe_resource
.url
= redirect_info
.new_url
;
96 unsafe_resource
.original_url
= request_
->original_url();
97 unsafe_resource
.redirect_urls
= redirect_urls_
;
98 unsafe_resource
.is_subresource
= is_subresource_
;
99 unsafe_resource
.is_subframe
= is_subframe_
;
100 unsafe_resource
.threat_type
= threat_type
;
101 unsafe_resource
.callback
= base::Bind(
102 &DataReductionProxyResourceThrottle::OnBlockingPageComplete
, AsWeakPtr());
103 unsafe_resource
.render_process_host_id
= info
->GetChildID();
104 unsafe_resource
.render_view_id
= info
->GetRouteID();
108 content::BrowserThread::PostTask(
109 content::BrowserThread::UI
, FROM_HERE
,
111 &DataReductionProxyResourceThrottle::StartDisplayingBlockingPage
,
112 AsWeakPtr(), safe_browsing_
->ui_manager(), unsafe_resource
));
115 const char* DataReductionProxyResourceThrottle::GetNameForLogging() const {
116 return "DataReductionProxyResourceThrottle";
120 void DataReductionProxyResourceThrottle::StartDisplayingBlockingPage(
121 const base::WeakPtr
<DataReductionProxyResourceThrottle
>& throttle
,
122 scoped_refptr
<SafeBrowsingUIManager
> ui_manager
,
123 const SafeBrowsingUIManager::UnsafeResource
& resource
) {
124 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
126 content::RenderViewHost
* rvh
= content::RenderViewHost::FromID(
127 resource
.render_process_host_id
, resource
.render_view_id
);
129 content::WebContents
* web_contents
=
130 content::WebContents::FromRenderViewHost(rvh
);
131 prerender::PrerenderContents
* prerender_contents
=
132 prerender::PrerenderContents::FromWebContents(web_contents
);
133 if (prerender_contents
) {
134 prerender_contents
->Destroy(prerender::FINAL_STATUS_SAFE_BROWSING
);
135 content::BrowserThread::PostTask(
136 content::BrowserThread::IO
,
138 base::Bind(resource
.callback
, false));
142 ui_manager
->DisplayBlockingPage(resource
);
145 // SafeBrowsingService::UrlCheckCallback implementation, called on the IO
146 // thread when the user has decided to proceed with the current request, or
148 void DataReductionProxyResourceThrottle::OnBlockingPageComplete(bool proceed
) {
149 CHECK(state_
== STATE_DISPLAYING_BLOCKING_PAGE
);
155 controller()->Cancel();
158 SBThreatType
DataReductionProxyResourceThrottle::CheckUrl() {
159 SBThreatType result
= SB_THREAT_TYPE_SAFE
;
161 // TODO(sgurun) Check for spdy proxy origin.
162 if (request_
->response_headers() == NULL
)
165 if (request_
->response_headers()->HasHeader("X-Phishing-Url"))
166 result
= SB_THREAT_TYPE_URL_PHISHING
;
167 else if (request_
->response_headers()->HasHeader("X-Malware-Url"))
168 result
= SB_THREAT_TYPE_URL_MALWARE
;
170 // If safe browsing is disabled and the request is sent to the DRP server,
171 // we need to break the redirect loop by setting the extra header.
172 if (result
!= SB_THREAT_TYPE_SAFE
&& !safe_browsing_
->enabled()) {
173 request_
->SetExtraRequestHeaderByName(kUnsafeUrlProceedHeader
, "1", true);
174 result
= SB_THREAT_TYPE_SAFE
;
180 void DataReductionProxyResourceThrottle::ResumeRequest() {
181 CHECK(state_
== STATE_NONE
);
183 // Inject the header before resuming the request.
184 request_
->SetExtraRequestHeaderByName(kUnsafeUrlProceedHeader
, "1", true);
185 controller()->Resume();