OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 #include "chrome/browser/android/spdy_proxy_resource_throttle.h" |
| 6 |
| 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" |
| 21 |
| 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" |
| 25 #endif |
| 26 |
| 27 using content::BrowserThread; |
| 28 using content::ResourceThrottle; |
| 29 |
| 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. |
| 35 |
| 36 const char* SpdyProxyResourceThrottle::kUnsafeUrlProceedHeader = |
| 37 "X-Unsafe-Url-Proceed"; |
| 38 |
| 39 ResourceThrottle* SpdyProxyResourceThrottleFactory::CreateResourceThrottle( |
| 40 net::URLRequest* request, |
| 41 content::ResourceContext* resource_context, |
| 42 content::ResourceType resource_type, |
| 43 SafeBrowsingService* service) { |
| 44 #if defined(SAFE_BROWSING_DB_LOCAL) || defined(SAFE_BROWSING_DB_REMOTE) |
| 45 ProfileIOData* io_data = ProfileIOData::FromResourceContext(resource_context); |
| 46 if (io_data->IsOffTheRecord() || |
| 47 !io_data->IsDataReductionProxyEnabled() || |
| 48 request->url().SchemeIsSecure()) |
| 49 return new SafeBrowsingResourceThrottle(request, resource_type, service); |
| 50 #endif |
| 51 return new SpdyProxyResourceThrottle(request, resource_type, service); |
| 52 } |
| 53 |
| 54 SpdyProxyResourceThrottle::SpdyProxyResourceThrottle( |
| 55 net::URLRequest* request, |
| 56 content::ResourceType resource_type, |
| 57 SafeBrowsingService* safe_browsing) |
| 58 : state_(STATE_NONE), |
| 59 safe_browsing_(safe_browsing), |
| 60 request_(request), |
| 61 is_subresource_(resource_type != content::RESOURCE_TYPE_MAIN_FRAME), |
| 62 is_subframe_(resource_type == content::RESOURCE_TYPE_SUB_FRAME) { |
| 63 } |
| 64 |
| 65 SpdyProxyResourceThrottle::~SpdyProxyResourceThrottle() { } |
| 66 |
| 67 void SpdyProxyResourceThrottle::WillRedirectRequest( |
| 68 const net::RedirectInfo& redirect_info, |
| 69 bool* defer) { |
| 70 CHECK(state_ == STATE_NONE); |
| 71 |
| 72 // Save the redirect urls for possible malware detail reporting later. |
| 73 redirect_urls_.push_back(redirect_info.new_url); |
| 74 |
| 75 // We need to check the new URL before following the redirect. |
| 76 SBThreatType threat_type = CheckUrl(); |
| 77 if (threat_type == SB_THREAT_TYPE_SAFE) |
| 78 return; |
| 79 |
| 80 if (request_->load_flags() & net::LOAD_PREFETCH) { |
| 81 controller()->Cancel(); |
| 82 return; |
| 83 } |
| 84 const content::ResourceRequestInfo* info = |
| 85 content::ResourceRequestInfo::ForRequest(request_); |
| 86 |
| 87 state_ = STATE_DISPLAYING_BLOCKING_PAGE; |
| 88 SafeBrowsingUIManager::UnsafeResource unsafe_resource; |
| 89 unsafe_resource.url = redirect_info.new_url; |
| 90 unsafe_resource.original_url = request_->original_url(); |
| 91 unsafe_resource.redirect_urls = redirect_urls_; |
| 92 unsafe_resource.is_subresource = is_subresource_; |
| 93 unsafe_resource.is_subframe = is_subframe_; |
| 94 unsafe_resource.threat_type = threat_type; |
| 95 unsafe_resource.callback = base::Bind( |
| 96 &SpdyProxyResourceThrottle::OnBlockingPageComplete, AsWeakPtr()); |
| 97 unsafe_resource.render_process_host_id = info->GetChildID(); |
| 98 unsafe_resource.render_view_id = info->GetRouteID(); |
| 99 |
| 100 *defer = true; |
| 101 |
| 102 content::BrowserThread::PostTask( |
| 103 content::BrowserThread::UI, |
| 104 FROM_HERE, |
| 105 base::Bind(&SpdyProxyResourceThrottle::StartDisplayingBlockingPage, |
| 106 AsWeakPtr(), |
| 107 safe_browsing_->ui_manager(), |
| 108 unsafe_resource)); |
| 109 } |
| 110 |
| 111 const char* SpdyProxyResourceThrottle::GetNameForLogging() const { |
| 112 return "SpdyProxyResourceThrottle"; |
| 113 } |
| 114 |
| 115 // static |
| 116 void SpdyProxyResourceThrottle::StartDisplayingBlockingPage( |
| 117 const base::WeakPtr<SpdyProxyResourceThrottle>& throttle, |
| 118 scoped_refptr<SafeBrowsingUIManager> ui_manager, |
| 119 const SafeBrowsingUIManager::UnsafeResource& resource) { |
| 120 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 121 |
| 122 content::RenderViewHost* rvh = content::RenderViewHost::FromID( |
| 123 resource.render_process_host_id, resource.render_view_id); |
| 124 if (rvh) { |
| 125 content::WebContents* web_contents = |
| 126 content::WebContents::FromRenderViewHost(rvh); |
| 127 prerender::PrerenderContents* prerender_contents = |
| 128 prerender::PrerenderContents::FromWebContents(web_contents); |
| 129 if (prerender_contents) { |
| 130 prerender_contents->Destroy(prerender::FINAL_STATUS_SAFE_BROWSING); |
| 131 content::BrowserThread::PostTask( |
| 132 content::BrowserThread::IO, |
| 133 FROM_HERE, |
| 134 base::Bind(resource.callback, false)); |
| 135 return; |
| 136 } |
| 137 } |
| 138 ui_manager->DisplayBlockingPage(resource); |
| 139 } |
| 140 |
| 141 // SafeBrowsingService::UrlCheckCallback implementation, called on the IO |
| 142 // thread when the user has decided to proceed with the current request, or |
| 143 // go back. |
| 144 void SpdyProxyResourceThrottle::OnBlockingPageComplete(bool proceed) { |
| 145 CHECK(state_ == STATE_DISPLAYING_BLOCKING_PAGE); |
| 146 state_ = STATE_NONE; |
| 147 |
| 148 if (proceed) |
| 149 ResumeRequest(); |
| 150 else |
| 151 controller()->Cancel(); |
| 152 } |
| 153 |
| 154 SBThreatType SpdyProxyResourceThrottle::CheckUrl() { |
| 155 SBThreatType result = SB_THREAT_TYPE_SAFE; |
| 156 |
| 157 // TODO(sgurun) Check for spdy proxy origin. |
| 158 if (request_->response_headers() == NULL) |
| 159 return result; |
| 160 |
| 161 if (request_->response_headers()->HasHeader("X-Phishing-Url")) |
| 162 result = SB_THREAT_TYPE_URL_PHISHING; |
| 163 else if (request_->response_headers()->HasHeader("X-Malware-Url")) |
| 164 result = SB_THREAT_TYPE_URL_MALWARE; |
| 165 |
| 166 // If safe browsing is disabled and the request is sent to the DRP server, |
| 167 // we need to break the redirect loop by setting the extra header. |
| 168 if (result != SB_THREAT_TYPE_SAFE && !safe_browsing_->enabled()) { |
| 169 request_->SetExtraRequestHeaderByName(kUnsafeUrlProceedHeader, "1", true); |
| 170 result = SB_THREAT_TYPE_SAFE; |
| 171 } |
| 172 |
| 173 return result; |
| 174 } |
| 175 |
| 176 void SpdyProxyResourceThrottle::ResumeRequest() { |
| 177 CHECK(state_ == STATE_NONE); |
| 178 |
| 179 // Inject the header before resuming the request. |
| 180 request_->SetExtraRequestHeaderByName(kUnsafeUrlProceedHeader, "1", true); |
| 181 controller()->Resume(); |
| 182 } |
OLD | NEW |