Yuzhu Shen | fe5f3a5 | 2018-01-11 21:24:13 | [diff] [blame] | 1 | // Copyright 2018 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/renderer/url_loader_throttle_provider_impl.h" |
| 6 | |
Charlie Harrison | 9ba4c19 | 2018-04-13 17:27:22 | [diff] [blame] | 7 | #include <utility> |
| 8 | |
Sebastien Marchand | f1349f5 | 2019-01-25 03:16:41 | [diff] [blame] | 9 | #include "base/bind.h" |
Chris Mumford | 3f0eda9 | 2018-07-23 14:51:17 | [diff] [blame] | 10 | #include "base/command_line.h" |
Yuzhu Shen | fe5f3a5 | 2018-01-11 21:24:13 | [diff] [blame] | 11 | #include "base/feature_list.h" |
Etienne Pierre-doray | 964b47ff | 2019-05-30 17:39:32 | [diff] [blame] | 12 | #include "base/threading/thread_task_runner_handle.h" |
John Abd-El-Malek | 9fb6049 | 2018-08-02 04:28:50 | [diff] [blame] | 13 | #include "chrome/common/google_url_loader_throttle.h" |
Yuzhu Shen | fe5f3a5 | 2018-01-11 21:24:13 | [diff] [blame] | 14 | #include "chrome/common/prerender.mojom.h" |
| 15 | #include "chrome/common/prerender_url_loader_throttle.h" |
| 16 | #include "chrome/renderer/chrome_content_renderer_client.h" |
Jun Cai | db3f93cc | 2018-07-09 21:54:55 | [diff] [blame] | 17 | #include "chrome/renderer/chrome_render_thread_observer.h" |
Yuzhu Shen | fe5f3a5 | 2018-01-11 21:24:13 | [diff] [blame] | 18 | #include "chrome/renderer/prerender/prerender_dispatcher.h" |
| 19 | #include "chrome/renderer/prerender/prerender_helper.h" |
Sean Harrison | d1c17b6f | 2019-05-20 18:35:46 | [diff] [blame] | 20 | #include "chrome/renderer/subresource_redirect/subresource_redirect_params.h" |
| 21 | #include "chrome/renderer/subresource_redirect/subresource_redirect_url_loader_throttle.h" |
Clark DuVall | 9233584 | 2018-10-10 16:49:09 | [diff] [blame] | 22 | #include "components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.h" |
| 23 | #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" |
Eric Roman | 0e5952f | 2018-11-29 00:48:29 | [diff] [blame] | 24 | #include "components/data_reduction_proxy/core/common/data_reduction_proxy_throttle_manager.h" |
Yuzhu Shen | cb3011f6 | 2018-02-08 02:51:50 | [diff] [blame] | 25 | #include "components/safe_browsing/features.h" |
Yuzhu Shen | fe5f3a5 | 2018-01-11 21:24:13 | [diff] [blame] | 26 | #include "components/safe_browsing/renderer/renderer_url_loader_throttle.h" |
| 27 | #include "content/public/common/content_features.h" |
| 28 | #include "content/public/common/service_names.mojom.h" |
| 29 | #include "content/public/renderer/render_frame.h" |
| 30 | #include "content/public/renderer/render_thread.h" |
| 31 | #include "content/public/renderer/render_view.h" |
| 32 | #include "services/service_manager/public/cpp/connector.h" |
| 33 | #include "services/service_manager/public/cpp/interface_provider.h" |
Sean Harrison | c314c335 | 2019-06-12 02:43:58 | [diff] [blame] | 34 | #include "url/gurl.h" |
Yuzhu Shen | fe5f3a5 | 2018-01-11 21:24:13 | [diff] [blame] | 35 | |
John Abd-El-Malek | e6ee6e9 | 2018-03-05 20:31:09 | [diff] [blame] | 36 | #if BUILDFLAG(ENABLE_EXTENSIONS) |
Chris Mumford | 3f0eda9 | 2018-07-23 14:51:17 | [diff] [blame] | 37 | #include "extensions/common/switches.h" |
| 38 | #include "extensions/renderer/extension_throttle_manager.h" |
John Abd-El-Malek | e6ee6e9 | 2018-03-05 20:31:09 | [diff] [blame] | 39 | #include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h" |
| 40 | #endif |
| 41 | |
Chris Mumford | 6b1696b | 2019-01-25 02:54:30 | [diff] [blame] | 42 | #if defined(OS_CHROMEOS) |
| 43 | #include "chrome/renderer/chromeos_merge_session_loader_throttle.h" |
| 44 | #endif // defined(OS_CHROMEOS) |
| 45 | |
Yuzhu Shen | fe5f3a5 | 2018-01-11 21:24:13 | [diff] [blame] | 46 | namespace { |
| 47 | |
| 48 | chrome::mojom::PrerenderCanceler* GetPrerenderCanceller(int render_frame_id) { |
| 49 | content::RenderFrame* render_frame = |
| 50 | content::RenderFrame::FromRoutingID(render_frame_id); |
| 51 | if (!render_frame) |
| 52 | return nullptr; |
| 53 | prerender::PrerenderHelper* helper = |
| 54 | prerender::PrerenderHelper::Get(render_frame); |
| 55 | if (!helper) |
| 56 | return nullptr; |
| 57 | |
| 58 | auto* canceler = new chrome::mojom::PrerenderCancelerPtr; |
| 59 | render_frame->GetRemoteInterfaces()->GetInterface(canceler); |
Etienne Pierre-doray | 964b47ff | 2019-05-30 17:39:32 | [diff] [blame] | 60 | base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, canceler); |
Yuzhu Shen | fe5f3a5 | 2018-01-11 21:24:13 | [diff] [blame] | 61 | return canceler->get(); |
| 62 | } |
| 63 | |
Chris Mumford | 3f0eda9 | 2018-07-23 14:51:17 | [diff] [blame] | 64 | #if BUILDFLAG(ENABLE_EXTENSIONS) |
| 65 | std::unique_ptr<extensions::ExtensionThrottleManager> |
| 66 | CreateExtensionThrottleManager() { |
| 67 | if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 68 | extensions::switches::kDisableExtensionsHttpThrottling)) { |
| 69 | return nullptr; |
| 70 | } |
| 71 | return std::make_unique<extensions::ExtensionThrottleManager>(); |
| 72 | } |
| 73 | |
| 74 | void SetExtensionThrottleManagerTestPolicy( |
| 75 | extensions::ExtensionThrottleManager* extension_throttle_manager) { |
| 76 | // Requests issued within within |kUserGestureWindowMs| of a user gesture |
| 77 | // are also considered as user gestures (see |
| 78 | // resource_dispatcher_host_impl.cc), so these tests need to bypass the |
| 79 | // checking of the net::LOAD_MAYBE_USER_GESTURE load flag in the manager |
| 80 | // in order to test the throttling logic. |
| 81 | extension_throttle_manager->SetIgnoreUserGestureLoadFlagForTests(true); |
| 82 | std::unique_ptr<net::BackoffEntry::Policy> policy( |
| 83 | new net::BackoffEntry::Policy{ |
| 84 | // Number of initial errors (in sequence) to ignore before |
| 85 | // applying exponential back-off rules. |
| 86 | 1, |
| 87 | |
| 88 | // Initial delay for exponential back-off in ms. |
| 89 | 10 * 60 * 1000, |
| 90 | |
| 91 | // Factor by which the waiting time will be multiplied. |
| 92 | 10, |
| 93 | |
| 94 | // Fuzzing percentage. ex: 10% will spread requests randomly |
| 95 | // between 90%-100% of the calculated time. |
| 96 | 0.1, |
| 97 | |
| 98 | // Maximum amount of time we are willing to delay our request in ms. |
| 99 | 15 * 60 * 1000, |
| 100 | |
| 101 | // Time to keep an entry from being discarded even when it |
| 102 | // has no significant state, -1 to never discard. |
| 103 | -1, |
| 104 | |
| 105 | // Don't use initial delay unless the last request was an error. |
| 106 | false, |
| 107 | }); |
| 108 | extension_throttle_manager->SetBackoffPolicyForTests(std::move(policy)); |
| 109 | } |
| 110 | #endif |
| 111 | |
Yuzhu Shen | fe5f3a5 | 2018-01-11 21:24:13 | [diff] [blame] | 112 | } // namespace |
| 113 | |
| 114 | URLLoaderThrottleProviderImpl::URLLoaderThrottleProviderImpl( |
Kenichi Ishibashi | 28032e00 | 2019-08-05 23:12:36 | [diff] [blame] | 115 | service_manager::Connector* connector, |
Yuzhu Shen | fe5f3a5 | 2018-01-11 21:24:13 | [diff] [blame] | 116 | content::URLLoaderThrottleProviderType type, |
| 117 | ChromeContentRendererClient* chrome_content_renderer_client) |
| 118 | : type_(type), |
| 119 | chrome_content_renderer_client_(chrome_content_renderer_client) { |
| 120 | DETACH_FROM_THREAD(thread_checker_); |
Kenichi Ishibashi | 28032e00 | 2019-08-05 23:12:36 | [diff] [blame] | 121 | connector->BindInterface(content::mojom::kBrowserServiceName, |
| 122 | mojo::MakeRequest(&safe_browsing_info_)); |
Eric Roman | a00cf68 | 2018-11-01 20:09:11 | [diff] [blame] | 123 | |
| 124 | if (data_reduction_proxy::params::IsEnabledWithNetworkService()) { |
Kenichi Ishibashi | 28032e00 | 2019-08-05 23:12:36 | [diff] [blame] | 125 | connector->BindInterface(content::mojom::kBrowserServiceName, |
| 126 | mojo::MakeRequest(&data_reduction_proxy_info_)); |
Eric Roman | a00cf68 | 2018-11-01 20:09:11 | [diff] [blame] | 127 | } |
Yuzhu Shen | fe5f3a5 | 2018-01-11 21:24:13 | [diff] [blame] | 128 | } |
| 129 | |
| 130 | URLLoaderThrottleProviderImpl::~URLLoaderThrottleProviderImpl() { |
| 131 | DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| 132 | } |
| 133 | |
Nate Chapin | 5390cdf | 2018-04-17 18:05:13 | [diff] [blame] | 134 | URLLoaderThrottleProviderImpl::URLLoaderThrottleProviderImpl( |
| 135 | const URLLoaderThrottleProviderImpl& other) |
| 136 | : type_(other.type_), |
| 137 | chrome_content_renderer_client_(other.chrome_content_renderer_client_) { |
| 138 | DETACH_FROM_THREAD(thread_checker_); |
| 139 | if (other.safe_browsing_) |
| 140 | other.safe_browsing_->Clone(mojo::MakeRequest(&safe_browsing_info_)); |
Wojciech Dzierżanowski | 4538080 | 2019-04-29 14:50:32 | [diff] [blame] | 141 | if (other.data_reduction_proxy_) { |
| 142 | other.data_reduction_proxy_->Clone( |
| 143 | mojo::MakeRequest(&data_reduction_proxy_info_)); |
Eric Roman | a00cf68 | 2018-11-01 20:09:11 | [diff] [blame] | 144 | } |
Nate Chapin | 5390cdf | 2018-04-17 18:05:13 | [diff] [blame] | 145 | // An ad_delay_factory_ is created, rather than cloning the existing one. |
| 146 | } |
| 147 | |
| 148 | std::unique_ptr<content::URLLoaderThrottleProvider> |
| 149 | URLLoaderThrottleProviderImpl::Clone() { |
| 150 | DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| 151 | if (safe_browsing_info_) |
| 152 | safe_browsing_.Bind(std::move(safe_browsing_info_)); |
Wojciech Dzierżanowski | 4538080 | 2019-04-29 14:50:32 | [diff] [blame] | 153 | if (data_reduction_proxy_info_) |
| 154 | data_reduction_proxy_.Bind(std::move(data_reduction_proxy_info_)); |
Nate Chapin | 5390cdf | 2018-04-17 18:05:13 | [diff] [blame] | 155 | return base::WrapUnique(new URLLoaderThrottleProviderImpl(*this)); |
| 156 | } |
| 157 | |
Minggang Wang | f6840ecf | 2019-07-29 05:15:02 | [diff] [blame] | 158 | std::vector<std::unique_ptr<blink::URLLoaderThrottle>> |
Yuzhu Shen | fe5f3a5 | 2018-01-11 21:24:13 | [diff] [blame] | 159 | URLLoaderThrottleProviderImpl::CreateThrottles( |
| 160 | int render_frame_id, |
Charlie Harrison | 294b742 | 2018-04-09 22:17:33 | [diff] [blame] | 161 | const blink::WebURLRequest& request, |
Yuzhu Shen | fe5f3a5 | 2018-01-11 21:24:13 | [diff] [blame] | 162 | content::ResourceType resource_type) { |
| 163 | DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| 164 | |
Minggang Wang | f6840ecf | 2019-07-29 05:15:02 | [diff] [blame] | 165 | std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles; |
Yuzhu Shen | fe5f3a5 | 2018-01-11 21:24:13 | [diff] [blame] | 166 | |
Yuzhu Shen | fe5f3a5 | 2018-01-11 21:24:13 | [diff] [blame] | 167 | // Some throttles have already been added in the browser for frame resources. |
| 168 | // Don't add them for frame requests. |
| 169 | bool is_frame_resource = content::IsResourceTypeFrame(resource_type); |
| 170 | |
Hajime Hoshi | 2dc94dc1 | 2019-04-25 19:15:12 | [diff] [blame] | 171 | DCHECK(!is_frame_resource || |
| 172 | type_ == content::URLLoaderThrottleProviderType::kFrame); |
Yuzhu Shen | fe5f3a5 | 2018-01-11 21:24:13 | [diff] [blame] | 173 | |
Wojciech Dzierżanowski | 4538080 | 2019-04-29 14:50:32 | [diff] [blame] | 174 | if (data_reduction_proxy::params::IsEnabledWithNetworkService()) { |
| 175 | if (data_reduction_proxy_info_) |
| 176 | data_reduction_proxy_.Bind(std::move(data_reduction_proxy_info_)); |
| 177 | if (!data_reduction_proxy_manager_) { |
| 178 | data_reduction_proxy_manager_ = std::make_unique< |
| 179 | data_reduction_proxy::DataReductionProxyThrottleManager>( |
| 180 | data_reduction_proxy_.get(), |
| 181 | data_reduction_proxy::mojom::DataReductionProxyThrottleConfigPtr()); |
| 182 | } |
Clark DuVall | 9233584 | 2018-10-10 16:49:09 | [diff] [blame] | 183 | throttles.push_back( |
| 184 | std::make_unique< |
| 185 | data_reduction_proxy::DataReductionProxyURLLoaderThrottle>( |
Eric Roman | 0e5952f | 2018-11-29 00:48:29 | [diff] [blame] | 186 | net::HttpRequestHeaders(), data_reduction_proxy_manager_.get())); |
Clark DuVall | 9233584 | 2018-10-10 16:49:09 | [diff] [blame] | 187 | } |
| 188 | |
Robbie McElrath | f6c3f96 | 2019-06-19 18:51:36 | [diff] [blame] | 189 | if (!is_frame_resource) { |
Hajime Hoshi | 2dc94dc1 | 2019-04-25 19:15:12 | [diff] [blame] | 190 | if (safe_browsing_info_) |
| 191 | safe_browsing_.Bind(std::move(safe_browsing_info_)); |
Yuzhu Shen | fe5f3a5 | 2018-01-11 21:24:13 | [diff] [blame] | 192 | throttles.push_back( |
| 193 | std::make_unique<safe_browsing::RendererURLLoaderThrottle>( |
| 194 | safe_browsing_.get(), render_frame_id)); |
| 195 | } |
| 196 | |
Hajime Hoshi | 2dc94dc1 | 2019-04-25 19:15:12 | [diff] [blame] | 197 | if (type_ == content::URLLoaderThrottleProviderType::kFrame && |
| 198 | !is_frame_resource) { |
Yuzhu Shen | fe5f3a5 | 2018-01-11 21:24:13 | [diff] [blame] | 199 | content::RenderFrame* render_frame = |
| 200 | content::RenderFrame::FromRoutingID(render_frame_id); |
| 201 | auto* prerender_helper = |
| 202 | render_frame ? prerender::PrerenderHelper::Get( |
| 203 | render_frame->GetRenderView()->GetMainRenderFrame()) |
| 204 | : nullptr; |
| 205 | if (prerender_helper) { |
| 206 | auto throttle = std::make_unique<prerender::PrerenderURLLoaderThrottle>( |
| 207 | prerender_helper->prerender_mode(), |
| 208 | prerender_helper->histogram_prefix(), |
| 209 | base::BindOnce(GetPrerenderCanceller, render_frame_id), |
Etienne Pierre-doray | 964b47ff | 2019-05-30 17:39:32 | [diff] [blame] | 210 | base::ThreadTaskRunnerHandle::Get()); |
Yuzhu Shen | fe5f3a5 | 2018-01-11 21:24:13 | [diff] [blame] | 211 | prerender_helper->AddThrottle(throttle->AsWeakPtr()); |
| 212 | if (prerender_helper->prerender_mode() == prerender::PREFETCH_ONLY) { |
| 213 | auto* prerender_dispatcher = |
| 214 | chrome_content_renderer_client_->prerender_dispatcher(); |
| 215 | prerender_dispatcher->IncrementPrefetchCount(); |
| 216 | throttle->set_destruction_closure(base::BindOnce( |
Matthew Cary | e689ce05 | 2018-03-23 18:35:44 | [diff] [blame] | 217 | &prerender::PrerenderDispatcher::DecrementPrefetchCount, |
| 218 | base::Unretained(prerender_dispatcher))); |
Yuzhu Shen | fe5f3a5 | 2018-01-11 21:24:13 | [diff] [blame] | 219 | } |
| 220 | throttles.push_back(std::move(throttle)); |
| 221 | } |
| 222 | } |
| 223 | |
John Abd-El-Malek | e6ee6e9 | 2018-03-05 20:31:09 | [diff] [blame] | 224 | #if BUILDFLAG(ENABLE_EXTENSIONS) |
Robbie McElrath | f6c3f96 | 2019-06-19 18:51:36 | [diff] [blame] | 225 | if (type_ == content::URLLoaderThrottleProviderType::kFrame && |
Daniel Cheng | aee5c031 | 2019-04-18 23:49:05 | [diff] [blame] | 226 | resource_type == content::ResourceType::kObject) { |
John Abd-El-Malek | e6ee6e9 | 2018-03-05 20:31:09 | [diff] [blame] | 227 | content::RenderFrame* render_frame = |
| 228 | content::RenderFrame::FromRoutingID(render_frame_id); |
| 229 | auto mime_handlers = |
| 230 | extensions::MimeHandlerViewContainer::FromRenderFrame(render_frame); |
Charlie Harrison | 294b742 | 2018-04-09 22:17:33 | [diff] [blame] | 231 | GURL gurl(request.Url()); |
John Abd-El-Malek | e6ee6e9 | 2018-03-05 20:31:09 | [diff] [blame] | 232 | for (auto* handler : mime_handlers) { |
| 233 | auto throttle = handler->MaybeCreatePluginThrottle(gurl); |
| 234 | if (throttle) { |
| 235 | throttles.push_back(std::move(throttle)); |
| 236 | break; |
| 237 | } |
| 238 | } |
| 239 | } |
Chris Mumford | 3f0eda9 | 2018-07-23 14:51:17 | [diff] [blame] | 240 | |
| 241 | if (!extension_throttle_manager_) |
| 242 | extension_throttle_manager_ = CreateExtensionThrottleManager(); |
| 243 | |
| 244 | if (extension_throttle_manager_) { |
| 245 | if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 246 | extensions::switches::kSetExtensionThrottleTestParams)) { |
| 247 | SetExtensionThrottleManagerTestPolicy(extension_throttle_manager_.get()); |
| 248 | } |
| 249 | |
Minggang Wang | f6840ecf | 2019-07-29 05:15:02 | [diff] [blame] | 250 | std::unique_ptr<blink::URLLoaderThrottle> throttle = |
Chris Mumford | 3f0eda9 | 2018-07-23 14:51:17 | [diff] [blame] | 251 | extension_throttle_manager_->MaybeCreateURLLoaderThrottle(request); |
| 252 | if (throttle) |
| 253 | throttles.push_back(std::move(throttle)); |
| 254 | } |
John Abd-El-Malek | e6ee6e9 | 2018-03-05 20:31:09 | [diff] [blame] | 255 | #endif |
| 256 | |
John Abd-El-Malek | 9fb6049 | 2018-08-02 04:28:50 | [diff] [blame] | 257 | throttles.push_back(std::make_unique<GoogleURLLoaderThrottle>( |
| 258 | ChromeRenderThreadObserver::is_incognito_process(), |
Chris Mumford | 809d8fb | 2018-11-10 12:26:11 | [diff] [blame] | 259 | ChromeRenderThreadObserver::GetDynamicParams())); |
Jun Cai | db3f93cc | 2018-07-09 21:54:55 | [diff] [blame] | 260 | |
Chris Mumford | 6b1696b | 2019-01-25 02:54:30 | [diff] [blame] | 261 | #if defined(OS_CHROMEOS) |
| 262 | throttles.push_back(std::make_unique<MergeSessionLoaderThrottle>( |
| 263 | chrome_content_renderer_client_->GetChromeObserver() |
| 264 | ->chromeos_listener())); |
| 265 | #endif // defined(OS_CHROMEOS) |
| 266 | |
Sean Harrison | c314c335 | 2019-06-12 02:43:58 | [diff] [blame] | 267 | if (subresource_redirect::ShouldForceEnableSubresourceRedirect() && |
| 268 | resource_type == content::ResourceType::kImage && |
| 269 | GURL(request.Url()).SchemeIs(url::kHttpsScheme)) { |
Sean Harrison | d1c17b6f | 2019-05-20 18:35:46 | [diff] [blame] | 270 | throttles.push_back( |
| 271 | std::make_unique< |
| 272 | subresource_redirect::SubresourceRedirectURLLoaderThrottle>()); |
| 273 | } |
| 274 | |
Yuzhu Shen | fe5f3a5 | 2018-01-11 21:24:13 | [diff] [blame] | 275 | return throttles; |
| 276 | } |
Chris Mumford | 3f0eda9 | 2018-07-23 14:51:17 | [diff] [blame] | 277 | |
| 278 | void URLLoaderThrottleProviderImpl::SetOnline(bool is_online) { |
| 279 | #if BUILDFLAG(ENABLE_EXTENSIONS) |
| 280 | if (extension_throttle_manager_) |
| 281 | extension_throttle_manager_->SetOnline(is_online); |
| 282 | #endif |
| 283 | } |