blob: 45e69157ffdbc3d1505274b55d3cf154a30cbd0d [file] [log] [blame]
Yuzhu Shenfe5f3a52018-01-11 21:24:131// 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 Harrison9ba4c192018-04-13 17:27:227#include <utility>
8
Sebastien Marchandf1349f52019-01-25 03:16:419#include "base/bind.h"
Chris Mumford3f0eda92018-07-23 14:51:1710#include "base/command_line.h"
Yuzhu Shenfe5f3a52018-01-11 21:24:1311#include "base/feature_list.h"
Etienne Pierre-doray964b47ff2019-05-30 17:39:3212#include "base/threading/thread_task_runner_handle.h"
John Abd-El-Malek9fb60492018-08-02 04:28:5013#include "chrome/common/google_url_loader_throttle.h"
Yuzhu Shenfe5f3a52018-01-11 21:24:1314#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 Caidb3f93cc2018-07-09 21:54:5517#include "chrome/renderer/chrome_render_thread_observer.h"
Yuzhu Shenfe5f3a52018-01-11 21:24:1318#include "chrome/renderer/prerender/prerender_dispatcher.h"
19#include "chrome/renderer/prerender/prerender_helper.h"
Sean Harrisond1c17b6f2019-05-20 18:35:4620#include "chrome/renderer/subresource_redirect/subresource_redirect_params.h"
21#include "chrome/renderer/subresource_redirect/subresource_redirect_url_loader_throttle.h"
Clark DuVall92335842018-10-10 16:49:0922#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 Roman0e5952f2018-11-29 00:48:2924#include "components/data_reduction_proxy/core/common/data_reduction_proxy_throttle_manager.h"
Yuzhu Shencb3011f62018-02-08 02:51:5025#include "components/safe_browsing/features.h"
Yuzhu Shenfe5f3a52018-01-11 21:24:1326#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 Harrisonc314c3352019-06-12 02:43:5834#include "url/gurl.h"
Yuzhu Shenfe5f3a52018-01-11 21:24:1335
John Abd-El-Maleke6ee6e92018-03-05 20:31:0936#if BUILDFLAG(ENABLE_EXTENSIONS)
Chris Mumford3f0eda92018-07-23 14:51:1737#include "extensions/common/switches.h"
38#include "extensions/renderer/extension_throttle_manager.h"
John Abd-El-Maleke6ee6e92018-03-05 20:31:0939#include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h"
40#endif
41
Chris Mumford6b1696b2019-01-25 02:54:3042#if defined(OS_CHROMEOS)
43#include "chrome/renderer/chromeos_merge_session_loader_throttle.h"
44#endif // defined(OS_CHROMEOS)
45
Yuzhu Shenfe5f3a52018-01-11 21:24:1346namespace {
47
48chrome::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-doray964b47ff2019-05-30 17:39:3260 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, canceler);
Yuzhu Shenfe5f3a52018-01-11 21:24:1361 return canceler->get();
62}
63
Chris Mumford3f0eda92018-07-23 14:51:1764#if BUILDFLAG(ENABLE_EXTENSIONS)
65std::unique_ptr<extensions::ExtensionThrottleManager>
66CreateExtensionThrottleManager() {
67 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
68 extensions::switches::kDisableExtensionsHttpThrottling)) {
69 return nullptr;
70 }
71 return std::make_unique<extensions::ExtensionThrottleManager>();
72}
73
74void 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 Shenfe5f3a52018-01-11 21:24:13112} // namespace
113
114URLLoaderThrottleProviderImpl::URLLoaderThrottleProviderImpl(
Kenichi Ishibashi28032e002019-08-05 23:12:36115 service_manager::Connector* connector,
Yuzhu Shenfe5f3a52018-01-11 21:24:13116 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 Ishibashi28032e002019-08-05 23:12:36121 connector->BindInterface(content::mojom::kBrowserServiceName,
122 mojo::MakeRequest(&safe_browsing_info_));
Eric Romana00cf682018-11-01 20:09:11123
124 if (data_reduction_proxy::params::IsEnabledWithNetworkService()) {
Kenichi Ishibashi28032e002019-08-05 23:12:36125 connector->BindInterface(content::mojom::kBrowserServiceName,
126 mojo::MakeRequest(&data_reduction_proxy_info_));
Eric Romana00cf682018-11-01 20:09:11127 }
Yuzhu Shenfe5f3a52018-01-11 21:24:13128}
129
130URLLoaderThrottleProviderImpl::~URLLoaderThrottleProviderImpl() {
131 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
132}
133
Nate Chapin5390cdf2018-04-17 18:05:13134URLLoaderThrottleProviderImpl::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żanowski45380802019-04-29 14:50:32141 if (other.data_reduction_proxy_) {
142 other.data_reduction_proxy_->Clone(
143 mojo::MakeRequest(&data_reduction_proxy_info_));
Eric Romana00cf682018-11-01 20:09:11144 }
Nate Chapin5390cdf2018-04-17 18:05:13145 // An ad_delay_factory_ is created, rather than cloning the existing one.
146}
147
148std::unique_ptr<content::URLLoaderThrottleProvider>
149URLLoaderThrottleProviderImpl::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żanowski45380802019-04-29 14:50:32153 if (data_reduction_proxy_info_)
154 data_reduction_proxy_.Bind(std::move(data_reduction_proxy_info_));
Nate Chapin5390cdf2018-04-17 18:05:13155 return base::WrapUnique(new URLLoaderThrottleProviderImpl(*this));
156}
157
Minggang Wangf6840ecf2019-07-29 05:15:02158std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
Yuzhu Shenfe5f3a52018-01-11 21:24:13159URLLoaderThrottleProviderImpl::CreateThrottles(
160 int render_frame_id,
Charlie Harrison294b7422018-04-09 22:17:33161 const blink::WebURLRequest& request,
Yuzhu Shenfe5f3a52018-01-11 21:24:13162 content::ResourceType resource_type) {
163 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
164
Minggang Wangf6840ecf2019-07-29 05:15:02165 std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles;
Yuzhu Shenfe5f3a52018-01-11 21:24:13166
Yuzhu Shenfe5f3a52018-01-11 21:24:13167 // 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 Hoshi2dc94dc12019-04-25 19:15:12171 DCHECK(!is_frame_resource ||
172 type_ == content::URLLoaderThrottleProviderType::kFrame);
Yuzhu Shenfe5f3a52018-01-11 21:24:13173
Wojciech Dzierżanowski45380802019-04-29 14:50:32174 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 DuVall92335842018-10-10 16:49:09183 throttles.push_back(
184 std::make_unique<
185 data_reduction_proxy::DataReductionProxyURLLoaderThrottle>(
Eric Roman0e5952f2018-11-29 00:48:29186 net::HttpRequestHeaders(), data_reduction_proxy_manager_.get()));
Clark DuVall92335842018-10-10 16:49:09187 }
188
Robbie McElrathf6c3f962019-06-19 18:51:36189 if (!is_frame_resource) {
Hajime Hoshi2dc94dc12019-04-25 19:15:12190 if (safe_browsing_info_)
191 safe_browsing_.Bind(std::move(safe_browsing_info_));
Yuzhu Shenfe5f3a52018-01-11 21:24:13192 throttles.push_back(
193 std::make_unique<safe_browsing::RendererURLLoaderThrottle>(
194 safe_browsing_.get(), render_frame_id));
195 }
196
Hajime Hoshi2dc94dc12019-04-25 19:15:12197 if (type_ == content::URLLoaderThrottleProviderType::kFrame &&
198 !is_frame_resource) {
Yuzhu Shenfe5f3a52018-01-11 21:24:13199 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-doray964b47ff2019-05-30 17:39:32210 base::ThreadTaskRunnerHandle::Get());
Yuzhu Shenfe5f3a52018-01-11 21:24:13211 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 Carye689ce052018-03-23 18:35:44217 &prerender::PrerenderDispatcher::DecrementPrefetchCount,
218 base::Unretained(prerender_dispatcher)));
Yuzhu Shenfe5f3a52018-01-11 21:24:13219 }
220 throttles.push_back(std::move(throttle));
221 }
222 }
223
John Abd-El-Maleke6ee6e92018-03-05 20:31:09224#if BUILDFLAG(ENABLE_EXTENSIONS)
Robbie McElrathf6c3f962019-06-19 18:51:36225 if (type_ == content::URLLoaderThrottleProviderType::kFrame &&
Daniel Chengaee5c0312019-04-18 23:49:05226 resource_type == content::ResourceType::kObject) {
John Abd-El-Maleke6ee6e92018-03-05 20:31:09227 content::RenderFrame* render_frame =
228 content::RenderFrame::FromRoutingID(render_frame_id);
229 auto mime_handlers =
230 extensions::MimeHandlerViewContainer::FromRenderFrame(render_frame);
Charlie Harrison294b7422018-04-09 22:17:33231 GURL gurl(request.Url());
John Abd-El-Maleke6ee6e92018-03-05 20:31:09232 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 Mumford3f0eda92018-07-23 14:51:17240
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 Wangf6840ecf2019-07-29 05:15:02250 std::unique_ptr<blink::URLLoaderThrottle> throttle =
Chris Mumford3f0eda92018-07-23 14:51:17251 extension_throttle_manager_->MaybeCreateURLLoaderThrottle(request);
252 if (throttle)
253 throttles.push_back(std::move(throttle));
254 }
John Abd-El-Maleke6ee6e92018-03-05 20:31:09255#endif
256
John Abd-El-Malek9fb60492018-08-02 04:28:50257 throttles.push_back(std::make_unique<GoogleURLLoaderThrottle>(
258 ChromeRenderThreadObserver::is_incognito_process(),
Chris Mumford809d8fb2018-11-10 12:26:11259 ChromeRenderThreadObserver::GetDynamicParams()));
Jun Caidb3f93cc2018-07-09 21:54:55260
Chris Mumford6b1696b2019-01-25 02:54:30261#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 Harrisonc314c3352019-06-12 02:43:58267 if (subresource_redirect::ShouldForceEnableSubresourceRedirect() &&
268 resource_type == content::ResourceType::kImage &&
269 GURL(request.Url()).SchemeIs(url::kHttpsScheme)) {
Sean Harrisond1c17b6f2019-05-20 18:35:46270 throttles.push_back(
271 std::make_unique<
272 subresource_redirect::SubresourceRedirectURLLoaderThrottle>());
273 }
274
Yuzhu Shenfe5f3a52018-01-11 21:24:13275 return throttles;
276}
Chris Mumford3f0eda92018-07-23 14:51:17277
278void 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}