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/profiles/profile_io_data.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 using content::BrowserThread
;
23 using content::ResourceThrottle
;
25 // TODO(eroman): Downgrade these CHECK()s to DCHECKs once there is more
26 // unit test coverage.
27 // TODO(sgurun) following the comment above, also provide tests for
28 // checking whether the headers are injected correctly and the SPDY proxy
29 // origin is tested properly.
31 const char* DataReductionProxyResourceThrottle::kUnsafeUrlProceedHeader
=
32 "X-Unsafe-Url-Proceed";
35 DataReductionProxyResourceThrottle
*
36 DataReductionProxyResourceThrottle::MaybeCreate(
37 net::URLRequest
* request
,
38 content::ResourceContext
* resource_context
,
39 content::ResourceType resource_type
,
40 SafeBrowsingService
* sb_service
) {
41 ProfileIOData
* io_data
= ProfileIOData::FromResourceContext(resource_context
);
42 // Don't create the throttle if we can't handle the request.
43 if (io_data
->IsOffTheRecord() || !io_data
->IsDataReductionProxyEnabled() ||
44 request
->url().SchemeIsCryptographic()) {
48 return new DataReductionProxyResourceThrottle(request
, resource_type
,
52 DataReductionProxyResourceThrottle::DataReductionProxyResourceThrottle(
53 net::URLRequest
* request
,
54 content::ResourceType resource_type
,
55 SafeBrowsingService
* safe_browsing
)
57 safe_browsing_(safe_browsing
),
59 is_subresource_(resource_type
!= content::RESOURCE_TYPE_MAIN_FRAME
),
60 is_subframe_(resource_type
== content::RESOURCE_TYPE_SUB_FRAME
) {
63 DataReductionProxyResourceThrottle::~DataReductionProxyResourceThrottle() { }
65 void DataReductionProxyResourceThrottle::WillRedirectRequest(
66 const net::RedirectInfo
& redirect_info
,
68 CHECK(state_
== STATE_NONE
);
70 // Save the redirect urls for possible malware detail reporting later.
71 redirect_urls_
.push_back(redirect_info
.new_url
);
73 // We need to check the new URL before following the redirect.
74 SBThreatType threat_type
= CheckUrl();
75 if (threat_type
== SB_THREAT_TYPE_SAFE
)
78 if (request_
->load_flags() & net::LOAD_PREFETCH
) {
79 controller()->Cancel();
82 const content::ResourceRequestInfo
* info
=
83 content::ResourceRequestInfo::ForRequest(request_
);
85 state_
= STATE_DISPLAYING_BLOCKING_PAGE
;
86 SafeBrowsingUIManager::UnsafeResource unsafe_resource
;
87 unsafe_resource
.url
= redirect_info
.new_url
;
88 unsafe_resource
.original_url
= request_
->original_url();
89 unsafe_resource
.redirect_urls
= redirect_urls_
;
90 unsafe_resource
.is_subresource
= is_subresource_
;
91 unsafe_resource
.is_subframe
= is_subframe_
;
92 unsafe_resource
.threat_type
= threat_type
;
93 unsafe_resource
.callback
= base::Bind(
94 &DataReductionProxyResourceThrottle::OnBlockingPageComplete
, AsWeakPtr());
95 unsafe_resource
.render_process_host_id
= info
->GetChildID();
96 unsafe_resource
.render_view_id
= info
->GetRouteID();
97 unsafe_resource
.threat_source
= SafeBrowsingUIManager::FROM_DATA_SAVER
;
101 content::BrowserThread::PostTask(
102 content::BrowserThread::UI
, FROM_HERE
,
104 &DataReductionProxyResourceThrottle::StartDisplayingBlockingPage
,
105 AsWeakPtr(), safe_browsing_
->ui_manager(), unsafe_resource
));
108 const char* DataReductionProxyResourceThrottle::GetNameForLogging() const {
109 return "DataReductionProxyResourceThrottle";
113 void DataReductionProxyResourceThrottle::StartDisplayingBlockingPage(
114 const base::WeakPtr
<DataReductionProxyResourceThrottle
>& throttle
,
115 scoped_refptr
<SafeBrowsingUIManager
> ui_manager
,
116 const SafeBrowsingUIManager::UnsafeResource
& resource
) {
117 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
119 content::RenderViewHost
* rvh
= content::RenderViewHost::FromID(
120 resource
.render_process_host_id
, resource
.render_view_id
);
122 content::WebContents
* web_contents
=
123 content::WebContents::FromRenderViewHost(rvh
);
124 prerender::PrerenderContents
* prerender_contents
=
125 prerender::PrerenderContents::FromWebContents(web_contents
);
126 if (prerender_contents
) {
127 prerender_contents
->Destroy(prerender::FINAL_STATUS_SAFE_BROWSING
);
128 content::BrowserThread::PostTask(
129 content::BrowserThread::IO
,
131 base::Bind(resource
.callback
, false));
135 ui_manager
->DisplayBlockingPage(resource
);
138 // SafeBrowsingService::UrlCheckCallback implementation, called on the IO
139 // thread when the user has decided to proceed with the current request, or
141 void DataReductionProxyResourceThrottle::OnBlockingPageComplete(bool proceed
) {
142 CHECK(state_
== STATE_DISPLAYING_BLOCKING_PAGE
);
148 controller()->Cancel();
151 SBThreatType
DataReductionProxyResourceThrottle::CheckUrl() {
152 SBThreatType result
= SB_THREAT_TYPE_SAFE
;
154 // TODO(sgurun) Check for spdy proxy origin.
155 if (request_
->response_headers() == NULL
)
158 if (request_
->response_headers()->HasHeader("X-Phishing-Url"))
159 result
= SB_THREAT_TYPE_URL_PHISHING
;
160 else if (request_
->response_headers()->HasHeader("X-Malware-Url"))
161 result
= SB_THREAT_TYPE_URL_MALWARE
;
163 // If safe browsing is disabled and the request is sent to the DRP server,
164 // we need to break the redirect loop by setting the extra header.
165 if (result
!= SB_THREAT_TYPE_SAFE
&& !safe_browsing_
->enabled()) {
166 request_
->SetExtraRequestHeaderByName(kUnsafeUrlProceedHeader
, "1", true);
167 result
= SB_THREAT_TYPE_SAFE
;
173 void DataReductionProxyResourceThrottle::ResumeRequest() {
174 CHECK(state_
== STATE_NONE
);
176 // Inject the header before resuming the request.
177 request_
->SetExtraRequestHeaderByName(kUnsafeUrlProceedHeader
, "1", true);
178 controller()->Resume();