| OLD | NEW |
| 1 // Copyright (c) 2017 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/safe_browsing/base_safe_browsing_resource_throttle.h" | 5 #include "components/safe_browsing/base_resource_throttle.h" |
| 6 | 6 |
| 7 #include <iterator> | 7 #include <iterator> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/debug/alias.h" | 10 #include "base/debug/alias.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/metrics/histogram_macros.h" | 12 #include "base/metrics/histogram_macros.h" |
| 13 #include "base/trace_event/trace_event.h" | 13 #include "base/trace_event/trace_event.h" |
| 14 #include "base/values.h" | 14 #include "base/values.h" |
| 15 #include "components/safe_browsing/base_ui_manager.h" | 15 #include "components/safe_browsing/base_ui_manager.h" |
| 16 #include "components/safe_browsing_db/util.h" | 16 #include "components/safe_browsing_db/util.h" |
| 17 #include "components/security_interstitials/content/unsafe_resource.h" | 17 #include "components/security_interstitials/content/unsafe_resource.h" |
| 18 #include "components/subresource_filter/content/browser/content_subresource_filt
er_driver_factory.h" | 18 #include "components/subresource_filter/content/browser/content_subresource_filt
er_driver_factory.h" |
| 19 #include "content/public/browser/browser_thread.h" | 19 #include "content/public/browser/browser_thread.h" |
| 20 #include "content/public/browser/resource_request_info.h" | 20 #include "content/public/browser/resource_request_info.h" |
| 21 #include "content/public/browser/web_contents.h" | 21 #include "content/public/browser/web_contents.h" |
| 22 #include "net/base/load_flags.h" | 22 #include "net/base/load_flags.h" |
| 23 #include "net/log/net_log_capture_mode.h" | 23 #include "net/log/net_log_capture_mode.h" |
| 24 #include "net/log/net_log_source.h" | 24 #include "net/log/net_log_source.h" |
| 25 #include "net/log/net_log_source_type.h" | 25 #include "net/log/net_log_source_type.h" |
| 26 #include "net/url_request/redirect_info.h" | 26 #include "net/url_request/redirect_info.h" |
| 27 #include "net/url_request/url_request.h" | 27 #include "net/url_request/url_request.h" |
| 28 | 28 |
| 29 using net::NetLogEventType; | 29 using net::NetLogEventType; |
| 30 using net::NetLogSourceType; | 30 using net::NetLogSourceType; |
| 31 using safe_browsing::BaseSafeBrowsingUIManager; | 31 |
| 32 namespace safe_browsing { |
| 32 | 33 |
| 33 namespace { | 34 namespace { |
| 34 | 35 |
| 35 // Maximum time in milliseconds to wait for the safe browsing service to | 36 // Maximum time in milliseconds to wait for the safe browsing service to |
| 36 // verify a URL. After this amount of time the outstanding check will be | 37 // verify a URL. After this amount of time the outstanding check will be |
| 37 // aborted, and the URL will be treated as if it were safe. | 38 // aborted, and the URL will be treated as if it were safe. |
| 38 const int kCheckUrlTimeoutMs = 5000; | 39 const int kCheckUrlTimeoutMs = 5000; |
| 39 | 40 |
| 40 // Return a dictionary with "url"=|url-spec| and optionally | 41 // Return a dictionary with "url"=|url-spec| and optionally |
| 41 // |name|=|value| (if not null), for netlogging. | 42 // |name|=|value| (if not null), for netlogging. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 64 if (name && value) | 65 if (name && value) |
| 65 event_params->SetString(name, value); | 66 event_params->SetString(name, value); |
| 66 return std::move(event_params); | 67 return std::move(event_params); |
| 67 } | 68 } |
| 68 | 69 |
| 69 } // namespace | 70 } // namespace |
| 70 | 71 |
| 71 // TODO(eroman): Downgrade these CHECK()s to DCHECKs once there is more | 72 // TODO(eroman): Downgrade these CHECK()s to DCHECKs once there is more |
| 72 // unit test coverage. | 73 // unit test coverage. |
| 73 | 74 |
| 74 BaseSafeBrowsingResourceThrottle::BaseSafeBrowsingResourceThrottle( | 75 BaseResourceThrottle::BaseResourceThrottle( |
| 75 const net::URLRequest* request, | 76 const net::URLRequest* request, |
| 76 content::ResourceType resource_type, | 77 content::ResourceType resource_type, |
| 77 scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> database_manager, | 78 scoped_refptr<SafeBrowsingDatabaseManager> database_manager, |
| 78 scoped_refptr<safe_browsing::BaseSafeBrowsingUIManager> ui_manager) | 79 scoped_refptr<BaseUIManager> ui_manager) |
| 79 : ui_manager_(ui_manager), | 80 : ui_manager_(ui_manager), |
| 80 threat_type_(safe_browsing::SB_THREAT_TYPE_SAFE), | 81 threat_type_(SB_THREAT_TYPE_SAFE), |
| 81 database_manager_(database_manager), | 82 database_manager_(database_manager), |
| 82 request_(request), | 83 request_(request), |
| 83 state_(STATE_NONE), | 84 state_(STATE_NONE), |
| 84 defer_state_(DEFERRED_NONE), | 85 defer_state_(DEFERRED_NONE), |
| 85 resource_type_(resource_type), | 86 resource_type_(resource_type), |
| 86 net_log_with_source_( | 87 net_log_with_source_( |
| 87 net::NetLogWithSource::Make(request->net_log().net_log(), | 88 net::NetLogWithSource::Make(request->net_log().net_log(), |
| 88 NetLogSourceType::SAFE_BROWSING)) {} | 89 NetLogSourceType::SAFE_BROWSING)) {} |
| 89 | 90 |
| 90 // static | 91 // static |
| 91 BaseSafeBrowsingResourceThrottle* BaseSafeBrowsingResourceThrottle::MaybeCreate( | 92 BaseResourceThrottle* BaseResourceThrottle::MaybeCreate( |
| 92 net::URLRequest* request, | 93 net::URLRequest* request, |
| 93 content::ResourceType resource_type, | 94 content::ResourceType resource_type, |
| 94 scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> database_manager, | 95 scoped_refptr<SafeBrowsingDatabaseManager> database_manager, |
| 95 scoped_refptr<safe_browsing::BaseSafeBrowsingUIManager> ui_manager) { | 96 scoped_refptr<BaseUIManager> ui_manager) { |
| 96 if (database_manager->IsSupported()) { | 97 if (database_manager->IsSupported()) { |
| 97 return new BaseSafeBrowsingResourceThrottle(request, resource_type, | 98 return new BaseResourceThrottle(request, resource_type, |
| 98 database_manager, ui_manager); | 99 database_manager, ui_manager); |
| 99 } | 100 } |
| 100 return nullptr; | 101 return nullptr; |
| 101 } | 102 } |
| 102 | 103 |
| 103 BaseSafeBrowsingResourceThrottle::~BaseSafeBrowsingResourceThrottle() { | 104 BaseResourceThrottle::~BaseResourceThrottle() { |
| 104 if (defer_state_ != DEFERRED_NONE) { | 105 if (defer_state_ != DEFERRED_NONE) { |
| 105 EndNetLogEvent(NetLogEventType::SAFE_BROWSING_DEFERRED, nullptr, nullptr); | 106 EndNetLogEvent(NetLogEventType::SAFE_BROWSING_DEFERRED, nullptr, nullptr); |
| 106 } | 107 } |
| 107 | 108 |
| 108 if (state_ == STATE_CHECKING_URL) { | 109 if (state_ == STATE_CHECKING_URL) { |
| 109 database_manager_->CancelCheck(this); | 110 database_manager_->CancelCheck(this); |
| 110 EndNetLogEvent(NetLogEventType::SAFE_BROWSING_CHECKING_URL, "result", | 111 EndNetLogEvent(NetLogEventType::SAFE_BROWSING_CHECKING_URL, "result", |
| 111 "request_canceled"); | 112 "request_canceled"); |
| 112 } | 113 } |
| 113 } | 114 } |
| 114 | 115 |
| 115 // Note on net_log calls: SAFE_BROWSING_DEFERRED events must be wholly | 116 // Note on net_log calls: SAFE_BROWSING_DEFERRED events must be wholly |
| 116 // nested within SAFE_BROWSING_CHECKING_URL events. Synchronous checks | 117 // nested within SAFE_BROWSING_CHECKING_URL events. Synchronous checks |
| 117 // are not logged at all. | 118 // are not logged at all. |
| 118 void BaseSafeBrowsingResourceThrottle::BeginNetLogEvent(NetLogEventType type, | 119 void BaseResourceThrottle::BeginNetLogEvent(NetLogEventType type, |
| 119 const GURL& url, | 120 const GURL& url, |
| 120 const char* name, | 121 const char* name, |
| 121 const char* value) { | 122 const char* value) { |
| 122 net_log_with_source_.BeginEvent( | 123 net_log_with_source_.BeginEvent( |
| 123 type, base::Bind(&NetLogUrlCallback, request_, url, name, value)); | 124 type, base::Bind(&NetLogUrlCallback, request_, url, name, value)); |
| 124 request_->net_log().AddEvent( | 125 request_->net_log().AddEvent( |
| 125 type, net_log_with_source_.source().ToEventParametersCallback()); | 126 type, net_log_with_source_.source().ToEventParametersCallback()); |
| 126 } | 127 } |
| 127 | 128 |
| 128 void BaseSafeBrowsingResourceThrottle::EndNetLogEvent(NetLogEventType type, | 129 void BaseResourceThrottle::EndNetLogEvent(NetLogEventType type, |
| 129 const char* name, | 130 const char* name, |
| 130 const char* value) { | 131 const char* value) { |
| 131 net_log_with_source_.EndEvent(type, | 132 net_log_with_source_.EndEvent(type, |
| 132 base::Bind(&NetLogStringCallback, name, value)); | 133 base::Bind(&NetLogStringCallback, name, value)); |
| 133 request_->net_log().AddEvent( | 134 request_->net_log().AddEvent( |
| 134 type, net_log_with_source_.source().ToEventParametersCallback()); | 135 type, net_log_with_source_.source().ToEventParametersCallback()); |
| 135 } | 136 } |
| 136 | 137 |
| 137 void BaseSafeBrowsingResourceThrottle::WillStartRequest(bool* defer) { | 138 void BaseResourceThrottle::WillStartRequest(bool* defer) { |
| 138 // We need to check the new URL before starting the request. | 139 // We need to check the new URL before starting the request. |
| 139 if (CheckUrl(request_->url())) | 140 if (CheckUrl(request_->url())) |
| 140 return; | 141 return; |
| 141 | 142 |
| 142 // We let the check run in parallel with resource load only if this | 143 // We let the check run in parallel with resource load only if this |
| 143 // db_manager only supports asynchronous checks, like on mobile. | 144 // db_manager only supports asynchronous checks, like on mobile. |
| 144 // Otherwise, we defer now. | 145 // Otherwise, we defer now. |
| 145 if (database_manager_->ChecksAreAlwaysAsync()) | 146 if (database_manager_->ChecksAreAlwaysAsync()) |
| 146 return; | 147 return; |
| 147 | 148 |
| 148 // If the URL couldn't be verified synchronously, defer starting the | 149 // If the URL couldn't be verified synchronously, defer starting the |
| 149 // request until the check has completed. | 150 // request until the check has completed. |
| 150 defer_state_ = DEFERRED_START; | 151 defer_state_ = DEFERRED_START; |
| 151 defer_start_time_ = base::TimeTicks::Now(); | 152 defer_start_time_ = base::TimeTicks::Now(); |
| 152 *defer = true; | 153 *defer = true; |
| 153 BeginNetLogEvent(NetLogEventType::SAFE_BROWSING_DEFERRED, request_->url(), | 154 BeginNetLogEvent(NetLogEventType::SAFE_BROWSING_DEFERRED, request_->url(), |
| 154 "defer_reason", "at_start"); | 155 "defer_reason", "at_start"); |
| 155 } | 156 } |
| 156 | 157 |
| 157 void BaseSafeBrowsingResourceThrottle::WillProcessResponse(bool* defer) { | 158 void BaseResourceThrottle::WillProcessResponse(bool* defer) { |
| 158 CHECK_EQ(defer_state_, DEFERRED_NONE); | 159 CHECK_EQ(defer_state_, DEFERRED_NONE); |
| 159 // TODO(nparker): Maybe remove this check, since it should have no effect. | 160 // TODO(nparker): Maybe remove this check, since it should have no effect. |
| 160 if (!database_manager_->ChecksAreAlwaysAsync()) | 161 if (!database_manager_->ChecksAreAlwaysAsync()) |
| 161 return; | 162 return; |
| 162 | 163 |
| 163 if (state_ == STATE_CHECKING_URL || | 164 if (state_ == STATE_CHECKING_URL || |
| 164 state_ == STATE_DISPLAYING_BLOCKING_PAGE) { | 165 state_ == STATE_DISPLAYING_BLOCKING_PAGE) { |
| 165 defer_state_ = DEFERRED_PROCESSING; | 166 defer_state_ = DEFERRED_PROCESSING; |
| 166 defer_start_time_ = base::TimeTicks::Now(); | 167 defer_start_time_ = base::TimeTicks::Now(); |
| 167 *defer = true; | 168 *defer = true; |
| 168 BeginNetLogEvent(NetLogEventType::SAFE_BROWSING_DEFERRED, request_->url(), | 169 BeginNetLogEvent(NetLogEventType::SAFE_BROWSING_DEFERRED, request_->url(), |
| 169 "defer_reason", "at_response"); | 170 "defer_reason", "at_response"); |
| 170 } | 171 } |
| 171 } | 172 } |
| 172 | 173 |
| 173 bool BaseSafeBrowsingResourceThrottle::MustProcessResponseBeforeReadingBody() { | 174 bool BaseResourceThrottle::MustProcessResponseBeforeReadingBody() { |
| 174 // On Android, SafeBrowsing may only decide to cancel the request when the | 175 // On Android, SafeBrowsing may only decide to cancel the request when the |
| 175 // response has been received. Therefore, no part of it should be cached | 176 // response has been received. Therefore, no part of it should be cached |
| 176 // until this ResourceThrottle has been able to check the response. This | 177 // until this ResourceThrottle has been able to check the response. This |
| 177 // prevents the following scenario: | 178 // prevents the following scenario: |
| 178 // 1) A request is made for foo.com which has been hacked. | 179 // 1) A request is made for foo.com which has been hacked. |
| 179 // 2) The request is only canceled at WillProcessResponse stage, but part of | 180 // 2) The request is only canceled at WillProcessResponse stage, but part of |
| 180 // it has been cached. | 181 // it has been cached. |
| 181 // 3) foo.com is no longer hacked and removed from the SafeBrowsing list. | 182 // 3) foo.com is no longer hacked and removed from the SafeBrowsing list. |
| 182 // 4) The user requests foo.com, which is not on the SafeBrowsing list. This | 183 // 4) The user requests foo.com, which is not on the SafeBrowsing list. This |
| 183 // is deemed safe. However, the resource is actually served from cache, | 184 // is deemed safe. However, the resource is actually served from cache, |
| 184 // using the version that was previously stored. | 185 // using the version that was previously stored. |
| 185 // 5) This results in the user accessing an unsafe resource without being | 186 // 5) This results in the user accessing an unsafe resource without being |
| 186 // notified that it's dangerous. | 187 // notified that it's dangerous. |
| 187 // TODO(clamy): Add a browser test that checks this specific scenario. | 188 // TODO(clamy): Add a browser test that checks this specific scenario. |
| 188 return true; | 189 return true; |
| 189 } | 190 } |
| 190 | 191 |
| 191 void BaseSafeBrowsingResourceThrottle::WillRedirectRequest( | 192 void BaseResourceThrottle::WillRedirectRequest( |
| 192 const net::RedirectInfo& redirect_info, | 193 const net::RedirectInfo& redirect_info, |
| 193 bool* defer) { | 194 bool* defer) { |
| 194 CHECK_EQ(defer_state_, DEFERRED_NONE); | 195 CHECK_EQ(defer_state_, DEFERRED_NONE); |
| 195 | 196 |
| 196 // Prev check completed and was safe. | 197 // Prev check completed and was safe. |
| 197 if (state_ == STATE_NONE) { | 198 if (state_ == STATE_NONE) { |
| 198 // Save the redirect urls for possible malware detail reporting later. | 199 // Save the redirect urls for possible malware detail reporting later. |
| 199 redirect_urls_.push_back(redirect_info.new_url); | 200 redirect_urls_.push_back(redirect_info.new_url); |
| 200 | 201 |
| 201 // We need to check the new URL before following the redirect. | 202 // We need to check the new URL before following the redirect. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 212 } | 213 } |
| 213 | 214 |
| 214 defer_start_time_ = base::TimeTicks::Now(); | 215 defer_start_time_ = base::TimeTicks::Now(); |
| 215 *defer = true; | 216 *defer = true; |
| 216 BeginNetLogEvent( | 217 BeginNetLogEvent( |
| 217 NetLogEventType::SAFE_BROWSING_DEFERRED, redirect_info.new_url, | 218 NetLogEventType::SAFE_BROWSING_DEFERRED, redirect_info.new_url, |
| 218 "defer_reason", | 219 "defer_reason", |
| 219 defer_state_ == DEFERRED_REDIRECT ? "redirect" : "unchecked_redirect"); | 220 defer_state_ == DEFERRED_REDIRECT ? "redirect" : "unchecked_redirect"); |
| 220 } | 221 } |
| 221 | 222 |
| 222 const char* BaseSafeBrowsingResourceThrottle::GetNameForLogging() const { | 223 const char* BaseResourceThrottle::GetNameForLogging() const { |
| 223 return "BaseSafeBrowsingResourceThrottle"; | 224 return "BaseResourceThrottle"; |
| 224 } | 225 } |
| 225 | 226 |
| 226 void BaseSafeBrowsingResourceThrottle::MaybeDestroyPrerenderContents( | 227 void BaseResourceThrottle::MaybeDestroyPrerenderContents( |
| 227 const content::ResourceRequestInfo* info) {} | 228 const content::ResourceRequestInfo* info) {} |
| 228 | 229 |
| 229 // SafeBrowsingService::Client implementation, called on the IO thread once | 230 // SafeBrowsingService::Client implementation, called on the IO thread once |
| 230 // the URL has been classified. | 231 // the URL has been classified. |
| 231 void BaseSafeBrowsingResourceThrottle::OnCheckBrowseUrlResult( | 232 void BaseResourceThrottle::OnCheckBrowseUrlResult( |
| 232 const GURL& url, | 233 const GURL& url, |
| 233 safe_browsing::SBThreatType threat_type, | 234 SBThreatType threat_type, |
| 234 const safe_browsing::ThreatMetadata& metadata) { | 235 const ThreatMetadata& metadata) { |
| 235 CHECK_EQ(state_, STATE_CHECKING_URL); | 236 CHECK_EQ(state_, STATE_CHECKING_URL); |
| 236 // TODO(vakh): The following base::debug::Alias() and CHECK calls should be | 237 // TODO(vakh): The following base::debug::Alias() and CHECK calls should be |
| 237 // removed after http://crbug.com/660293 is fixed. | 238 // removed after http://crbug.com/660293 is fixed. |
| 238 CHECK(url.is_valid()); | 239 CHECK(url.is_valid()); |
| 239 CHECK(url_being_checked_.is_valid()); | 240 CHECK(url_being_checked_.is_valid()); |
| 240 if (url != url_being_checked_) { | 241 if (url != url_being_checked_) { |
| 241 bool url_had_timed_out = timed_out_urls_.count(url) > 0; | 242 bool url_had_timed_out = timed_out_urls_.count(url) > 0; |
| 242 char buf[1000]; | 243 char buf[1000]; |
| 243 snprintf(buf, sizeof(buf), "sbtr::ocbur:%d:%s -- %s\n", url_had_timed_out, | 244 snprintf(buf, sizeof(buf), "sbtr::ocbur:%d:%s -- %s\n", url_had_timed_out, |
| 244 url.spec().c_str(), url_being_checked_.spec().c_str()); | 245 url.spec().c_str(), url_being_checked_.spec().c_str()); |
| 245 base::debug::Alias(buf); | 246 base::debug::Alias(buf); |
| 246 CHECK(false) << "buf: " << buf; | 247 CHECK(false) << "buf: " << buf; |
| 247 } | 248 } |
| 248 | 249 |
| 249 timer_.Stop(); // Cancel the timeout timer. | 250 timer_.Stop(); // Cancel the timeout timer. |
| 250 threat_type_ = threat_type; | 251 threat_type_ = threat_type; |
| 251 state_ = STATE_NONE; | 252 state_ = STATE_NONE; |
| 252 | 253 |
| 253 if (defer_state_ != DEFERRED_NONE) { | 254 if (defer_state_ != DEFERRED_NONE) { |
| 254 EndNetLogEvent(NetLogEventType::SAFE_BROWSING_DEFERRED, nullptr, nullptr); | 255 EndNetLogEvent(NetLogEventType::SAFE_BROWSING_DEFERRED, nullptr, nullptr); |
| 255 } | 256 } |
| 256 EndNetLogEvent( | 257 EndNetLogEvent( |
| 257 NetLogEventType::SAFE_BROWSING_CHECKING_URL, "result", | 258 NetLogEventType::SAFE_BROWSING_CHECKING_URL, "result", |
| 258 threat_type_ == safe_browsing::SB_THREAT_TYPE_SAFE ? "safe" : "unsafe"); | 259 threat_type_ == SB_THREAT_TYPE_SAFE ? "safe" : "unsafe"); |
| 259 | 260 |
| 260 if (threat_type == safe_browsing::SB_THREAT_TYPE_SAFE) { | 261 if (threat_type == SB_THREAT_TYPE_SAFE) { |
| 261 if (defer_state_ != DEFERRED_NONE) { | 262 if (defer_state_ != DEFERRED_NONE) { |
| 262 // Log how much time the safe browsing check cost us. | 263 // Log how much time the safe browsing check cost us. |
| 263 ui_manager_->LogPauseDelay(base::TimeTicks::Now() - defer_start_time_); | 264 ui_manager_->LogPauseDelay(base::TimeTicks::Now() - defer_start_time_); |
| 264 ResumeRequest(); | 265 ResumeRequest(); |
| 265 } else { | 266 } else { |
| 266 ui_manager_->LogPauseDelay(base::TimeDelta()); | 267 ui_manager_->LogPauseDelay(base::TimeDelta()); |
| 267 } | 268 } |
| 268 return; | 269 return; |
| 269 } | 270 } |
| 270 | 271 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 288 | 289 |
| 289 security_interstitials::UnsafeResource resource; | 290 security_interstitials::UnsafeResource resource; |
| 290 resource.url = url; | 291 resource.url = url; |
| 291 resource.original_url = request_->original_url(); | 292 resource.original_url = request_->original_url(); |
| 292 resource.redirect_urls = redirect_urls_; | 293 resource.redirect_urls = redirect_urls_; |
| 293 resource.is_subresource = resource_type_ != content::RESOURCE_TYPE_MAIN_FRAME; | 294 resource.is_subresource = resource_type_ != content::RESOURCE_TYPE_MAIN_FRAME; |
| 294 resource.is_subframe = resource_type_ == content::RESOURCE_TYPE_SUB_FRAME; | 295 resource.is_subframe = resource_type_ == content::RESOURCE_TYPE_SUB_FRAME; |
| 295 resource.threat_type = threat_type; | 296 resource.threat_type = threat_type; |
| 296 resource.threat_metadata = metadata; | 297 resource.threat_metadata = metadata; |
| 297 resource.callback = base::Bind( | 298 resource.callback = base::Bind( |
| 298 &BaseSafeBrowsingResourceThrottle::OnBlockingPageComplete, AsWeakPtr()); | 299 &BaseResourceThrottle::OnBlockingPageComplete, AsWeakPtr()); |
| 299 resource.callback_thread = content::BrowserThread::GetTaskRunnerForThread( | 300 resource.callback_thread = content::BrowserThread::GetTaskRunnerForThread( |
| 300 content::BrowserThread::IO); | 301 content::BrowserThread::IO); |
| 301 resource.web_contents_getter = info->GetWebContentsGetterForRequest(); | 302 resource.web_contents_getter = info->GetWebContentsGetterForRequest(); |
| 302 resource.threat_source = database_manager_->GetThreatSource(); | 303 resource.threat_source = database_manager_->GetThreatSource(); |
| 303 | 304 |
| 304 state_ = STATE_DISPLAYING_BLOCKING_PAGE; | 305 state_ = STATE_DISPLAYING_BLOCKING_PAGE; |
| 305 | 306 |
| 306 StartDisplayingBlockingPageHelper(resource); | 307 StartDisplayingBlockingPageHelper(resource); |
| 307 } | 308 } |
| 308 | 309 |
| 309 void BaseSafeBrowsingResourceThrottle::StartDisplayingBlockingPageHelper( | 310 void BaseResourceThrottle::StartDisplayingBlockingPageHelper( |
| 310 security_interstitials::UnsafeResource resource) { | 311 security_interstitials::UnsafeResource resource) { |
| 311 content::BrowserThread::PostTask( | 312 content::BrowserThread::PostTask( |
| 312 content::BrowserThread::UI, FROM_HERE, | 313 content::BrowserThread::UI, FROM_HERE, |
| 313 base::Bind(&BaseSafeBrowsingResourceThrottle::StartDisplayingBlockingPage, | 314 base::Bind(&BaseResourceThrottle::StartDisplayingBlockingPage, |
| 314 AsWeakPtr(), ui_manager_, resource)); | 315 AsWeakPtr(), ui_manager_, resource)); |
| 315 } | 316 } |
| 316 | 317 |
| 317 // Static | 318 // Static |
| 318 void BaseSafeBrowsingResourceThrottle::StartDisplayingBlockingPage( | 319 void BaseResourceThrottle::StartDisplayingBlockingPage( |
| 319 const base::WeakPtr<BaseSafeBrowsingResourceThrottle>& throttle, | 320 const base::WeakPtr<BaseResourceThrottle>& throttle, |
| 320 scoped_refptr<BaseSafeBrowsingUIManager> ui_manager, | 321 scoped_refptr<BaseUIManager> ui_manager, |
| 321 const security_interstitials::UnsafeResource& resource) { | 322 const security_interstitials::UnsafeResource& resource) { |
| 322 content::WebContents* web_contents = resource.web_contents_getter.Run(); | 323 content::WebContents* web_contents = resource.web_contents_getter.Run(); |
| 323 if (web_contents) { | 324 if (web_contents) { |
| 324 // Once activated, the subresource filter will filter subresources, but is | 325 // Once activated, the subresource filter will filter subresources, but is |
| 325 // triggered when the main frame document matches Safe Browsing blacklists. | 326 // triggered when the main frame document matches Safe Browsing blacklists. |
| 326 if (!resource.is_subresource) { | 327 if (!resource.is_subresource) { |
| 327 using subresource_filter::ContentSubresourceFilterDriverFactory; | 328 using subresource_filter::ContentSubresourceFilterDriverFactory; |
| 328 ContentSubresourceFilterDriverFactory* driver_factory = | 329 ContentSubresourceFilterDriverFactory* driver_factory = |
| 329 ContentSubresourceFilterDriverFactory::FromWebContents(web_contents); | 330 ContentSubresourceFilterDriverFactory::FromWebContents(web_contents); |
| 330 DCHECK(driver_factory); | 331 DCHECK(driver_factory); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 344 resource.threat_metadata.threat_pattern_type); | 345 resource.threat_metadata.threat_pattern_type); |
| 345 } | 346 } |
| 346 | 347 |
| 347 ui_manager->DisplayBlockingPage(resource); | 348 ui_manager->DisplayBlockingPage(resource); |
| 348 return; | 349 return; |
| 349 } | 350 } |
| 350 | 351 |
| 351 // Tab is gone or it's being prerendered. | 352 // Tab is gone or it's being prerendered. |
| 352 content::BrowserThread::PostTask( | 353 content::BrowserThread::PostTask( |
| 353 content::BrowserThread::IO, FROM_HERE, | 354 content::BrowserThread::IO, FROM_HERE, |
| 354 base::Bind(&BaseSafeBrowsingResourceThrottle::Cancel, throttle)); | 355 base::Bind(&BaseResourceThrottle::Cancel, throttle)); |
| 355 } | 356 } |
| 356 | 357 |
| 357 void BaseSafeBrowsingResourceThrottle::OnBlockingPageComplete(bool proceed) { | 358 void BaseResourceThrottle::OnBlockingPageComplete(bool proceed) { |
| 358 CHECK_EQ(state_, STATE_DISPLAYING_BLOCKING_PAGE); | 359 CHECK_EQ(state_, STATE_DISPLAYING_BLOCKING_PAGE); |
| 359 state_ = STATE_NONE; | 360 state_ = STATE_NONE; |
| 360 | 361 |
| 361 if (proceed) { | 362 if (proceed) { |
| 362 threat_type_ = safe_browsing::SB_THREAT_TYPE_SAFE; | 363 threat_type_ = SB_THREAT_TYPE_SAFE; |
| 363 if (defer_state_ != DEFERRED_NONE) { | 364 if (defer_state_ != DEFERRED_NONE) { |
| 364 ResumeRequest(); | 365 ResumeRequest(); |
| 365 } | 366 } |
| 366 } else { | 367 } else { |
| 367 Cancel(); | 368 Cancel(); |
| 368 } | 369 } |
| 369 } | 370 } |
| 370 | 371 |
| 371 bool BaseSafeBrowsingResourceThrottle::CheckUrl(const GURL& url) { | 372 bool BaseResourceThrottle::CheckUrl(const GURL& url) { |
| 372 TRACE_EVENT1("loader", "BaseSafeBrowsingResourceThrottle::CheckUrl", "url", | 373 TRACE_EVENT1("loader", "BaseResourceThrottle::CheckUrl", "url", |
| 373 url.spec()); | 374 url.spec()); |
| 374 CHECK_EQ(state_, STATE_NONE); | 375 CHECK_EQ(state_, STATE_NONE); |
| 375 // To reduce aggregate latency on mobile, check only the most dangerous | 376 // To reduce aggregate latency on mobile, check only the most dangerous |
| 376 // resource types. | 377 // resource types. |
| 377 if (!database_manager_->CanCheckResourceType(resource_type_)) { | 378 if (!database_manager_->CanCheckResourceType(resource_type_)) { |
| 378 // TODO(vakh): Consider changing this metric to SafeBrowsing.V4ResourceType | 379 // TODO(vakh): Consider changing this metric to SafeBrowsing.V4ResourceType |
| 379 // to be consistent with the other PVer4 metrics. | 380 // to be consistent with the other PVer4 metrics. |
| 380 UMA_HISTOGRAM_ENUMERATION("SB2.ResourceTypes2.Skipped", resource_type_, | 381 UMA_HISTOGRAM_ENUMERATION("SB2.ResourceTypes2.Skipped", resource_type_, |
| 381 content::RESOURCE_TYPE_LAST_TYPE); | 382 content::RESOURCE_TYPE_LAST_TYPE); |
| 382 return true; | 383 return true; |
| 383 } | 384 } |
| 384 | 385 |
| 385 // TODO(vakh): Consider changing this metric to SafeBrowsing.V4ResourceType to | 386 // TODO(vakh): Consider changing this metric to SafeBrowsing.V4ResourceType to |
| 386 // be consistent with the other PVer4 metrics. | 387 // be consistent with the other PVer4 metrics. |
| 387 UMA_HISTOGRAM_ENUMERATION("SB2.ResourceTypes2.Checked", resource_type_, | 388 UMA_HISTOGRAM_ENUMERATION("SB2.ResourceTypes2.Checked", resource_type_, |
| 388 content::RESOURCE_TYPE_LAST_TYPE); | 389 content::RESOURCE_TYPE_LAST_TYPE); |
| 389 | 390 |
| 390 if (database_manager_->CheckBrowseUrl(url, this)) { | 391 if (database_manager_->CheckBrowseUrl(url, this)) { |
| 391 threat_type_ = safe_browsing::SB_THREAT_TYPE_SAFE; | 392 threat_type_ = SB_THREAT_TYPE_SAFE; |
| 392 ui_manager_->LogPauseDelay(base::TimeDelta()); // No delay. | 393 ui_manager_->LogPauseDelay(base::TimeDelta()); // No delay. |
| 393 return true; | 394 return true; |
| 394 } | 395 } |
| 395 | 396 |
| 396 state_ = STATE_CHECKING_URL; | 397 state_ = STATE_CHECKING_URL; |
| 397 url_being_checked_ = url; | 398 url_being_checked_ = url; |
| 398 BeginNetLogEvent(NetLogEventType::SAFE_BROWSING_CHECKING_URL, url, nullptr, | 399 BeginNetLogEvent(NetLogEventType::SAFE_BROWSING_CHECKING_URL, url, nullptr, |
| 399 nullptr); | 400 nullptr); |
| 400 | 401 |
| 401 // Start a timer to abort the check if it takes too long. | 402 // Start a timer to abort the check if it takes too long. |
| 402 // TODO(nparker): Set this only when we defer, based on remaining time, | 403 // TODO(nparker): Set this only when we defer, based on remaining time, |
| 403 // so we don't cancel earlier than necessary. | 404 // so we don't cancel earlier than necessary. |
| 404 timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kCheckUrlTimeoutMs), | 405 timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kCheckUrlTimeoutMs), |
| 405 this, &BaseSafeBrowsingResourceThrottle::OnCheckUrlTimeout); | 406 this, &BaseResourceThrottle::OnCheckUrlTimeout); |
| 406 | 407 |
| 407 return false; | 408 return false; |
| 408 } | 409 } |
| 409 | 410 |
| 410 void BaseSafeBrowsingResourceThrottle::OnCheckUrlTimeout() { | 411 void BaseResourceThrottle::OnCheckUrlTimeout() { |
| 411 CHECK_EQ(state_, STATE_CHECKING_URL); | 412 CHECK_EQ(state_, STATE_CHECKING_URL); |
| 412 | 413 |
| 413 database_manager_->CancelCheck(this); | 414 database_manager_->CancelCheck(this); |
| 414 | 415 |
| 415 OnCheckBrowseUrlResult(url_being_checked_, safe_browsing::SB_THREAT_TYPE_SAFE, | 416 OnCheckBrowseUrlResult(url_being_checked_, safe_browsing::SB_THREAT_TYPE_SAFE, |
| 416 safe_browsing::ThreatMetadata()); | 417 ThreatMetadata()); |
| 417 | 418 |
| 418 timed_out_urls_.insert(url_being_checked_); | 419 timed_out_urls_.insert(url_being_checked_); |
| 419 } | 420 } |
| 420 | 421 |
| 421 void BaseSafeBrowsingResourceThrottle::ResumeRequest() { | 422 void BaseResourceThrottle::ResumeRequest() { |
| 422 CHECK_EQ(state_, STATE_NONE); | 423 CHECK_EQ(state_, STATE_NONE); |
| 423 CHECK_NE(defer_state_, DEFERRED_NONE); | 424 CHECK_NE(defer_state_, DEFERRED_NONE); |
| 424 | 425 |
| 425 bool resume = true; | 426 bool resume = true; |
| 426 if (defer_state_ == DEFERRED_UNCHECKED_REDIRECT) { | 427 if (defer_state_ == DEFERRED_UNCHECKED_REDIRECT) { |
| 427 // Save the redirect urls for possible malware detail reporting later. | 428 // Save the redirect urls for possible malware detail reporting later. |
| 428 redirect_urls_.push_back(unchecked_redirect_url_); | 429 redirect_urls_.push_back(unchecked_redirect_url_); |
| 429 if (!CheckUrl(unchecked_redirect_url_)) { | 430 if (!CheckUrl(unchecked_redirect_url_)) { |
| 430 // We're now waiting for the unchecked_redirect_url_. | 431 // We're now waiting for the unchecked_redirect_url_. |
| 431 defer_state_ = DEFERRED_REDIRECT; | 432 defer_state_ = DEFERRED_REDIRECT; |
| 432 resume = false; | 433 resume = false; |
| 433 BeginNetLogEvent(NetLogEventType::SAFE_BROWSING_DEFERRED, | 434 BeginNetLogEvent(NetLogEventType::SAFE_BROWSING_DEFERRED, |
| 434 unchecked_redirect_url_, "defer_reason", | 435 unchecked_redirect_url_, "defer_reason", |
| 435 "resumed_redirect"); | 436 "resumed_redirect"); |
| 436 } | 437 } |
| 437 } | 438 } |
| 438 | 439 |
| 439 if (resume) { | 440 if (resume) { |
| 440 defer_state_ = DEFERRED_NONE; | 441 defer_state_ = DEFERRED_NONE; |
| 441 Resume(); | 442 Resume(); |
| 442 } | 443 } |
| 443 } | 444 } |
| 445 |
| 446 } // namespace safe_browsing |
| OLD | NEW |