OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 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 "content/browser/loader/navigation_url_loader_network_service.h" | 5 #include "content/browser/loader/navigation_url_loader_network_service.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
11 #include "base/trace_event/trace_event.h" | 11 #include "base/trace_event/trace_event.h" |
12 #include "content/browser/blob_storage/chrome_blob_storage_context.h" | 12 #include "content/browser/blob_storage/chrome_blob_storage_context.h" |
13 #include "content/browser/frame_host/frame_tree_node.h" | 13 #include "content/browser/frame_host/frame_tree_node.h" |
14 #include "content/browser/frame_host/navigation_request_info.h" | 14 #include "content/browser/frame_host/navigation_request_info.h" |
15 #include "content/browser/loader/navigation_resource_handler.h" | 15 #include "content/browser/loader/navigation_resource_handler.h" |
16 #include "content/browser/loader/navigation_resource_throttle.h" | 16 #include "content/browser/loader/navigation_resource_throttle.h" |
17 #include "content/browser/loader/navigation_url_loader_delegate.h" | 17 #include "content/browser/loader/navigation_url_loader_delegate.h" |
| 18 #include "content/browser/resource_context_impl.h" |
| 19 #include "content/browser/service_worker/service_worker_context_wrapper.h" |
| 20 #include "content/browser/service_worker/service_worker_navigation_handle.h" |
| 21 #include "content/browser/service_worker/service_worker_navigation_handle_core.h
" |
| 22 #include "content/browser/service_worker/service_worker_request_handler.h" |
| 23 #include "content/browser/web_contents/web_contents_impl.h" |
18 #include "content/browser/webui/url_data_manager_backend.h" | 24 #include "content/browser/webui/url_data_manager_backend.h" |
19 #include "content/browser/webui/web_ui_url_loader_factory.h" | 25 #include "content/browser/webui/web_ui_url_loader_factory.h" |
20 #include "content/public/browser/browser_thread.h" | 26 #include "content/public/browser/browser_thread.h" |
21 #include "content/public/browser/global_request_id.h" | 27 #include "content/public/browser/global_request_id.h" |
22 #include "content/public/browser/navigation_data.h" | 28 #include "content/public/browser/navigation_data.h" |
23 #include "content/public/browser/navigation_ui_data.h" | 29 #include "content/public/browser/navigation_ui_data.h" |
24 #include "content/public/browser/ssl_status.h" | 30 #include "content/public/browser/ssl_status.h" |
25 #include "content/public/browser/stream_handle.h" | 31 #include "content/public/browser/stream_handle.h" |
26 #include "content/public/common/referrer.h" | 32 #include "content/public/common/referrer.h" |
27 #include "content/public/common/service_manager_connection.h" | 33 #include "content/public/common/service_manager_connection.h" |
28 #include "content/public/common/service_names.mojom.h" | 34 #include "content/public/common/service_names.mojom.h" |
29 #include "content/public/common/url_constants.h" | 35 #include "content/public/common/url_constants.h" |
30 #include "net/base/load_flags.h" | 36 #include "net/base/load_flags.h" |
31 #include "net/url_request/url_request_context.h" | 37 #include "net/url_request/url_request_context.h" |
32 #include "services/service_manager/public/cpp/connector.h" | 38 #include "services/service_manager/public/cpp/connector.h" |
33 | 39 |
34 namespace content { | 40 namespace content { |
35 | 41 |
36 namespace { | 42 namespace { |
37 | 43 |
38 static base::LazyInstance<mojom::URLLoaderFactoryPtr>::Leaky | 44 static base::LazyInstance<mojom::URLLoaderFactoryPtr>::Leaky |
39 g_url_loader_factory = LAZY_INSTANCE_INITIALIZER; | 45 g_url_loader_factory = LAZY_INSTANCE_INITIALIZER; |
40 | 46 |
41 // This function is called on the IO thread for POST/PUT requests for | 47 using CompleteNavigationStartCallback = |
42 // attaching blob information to the request body. | 48 base::Callback<void(mojom::URLLoaderFactoryPtrInfo, |
43 void HandleRequestsWithBody( | 49 std::unique_ptr<ResourceRequest>)>; |
44 std::unique_ptr<ResourceRequest> request, | 50 |
| 51 void PrepareNavigationStartOnIOThread( |
| 52 std::unique_ptr<ResourceRequest> resource_request, |
45 ResourceContext* resource_context, | 53 ResourceContext* resource_context, |
46 base::WeakPtr<NavigationURLLoaderNetworkService> url_loader) { | 54 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core, |
| 55 bool skip_service_worker, |
| 56 ResourceType resource_type, |
| 57 RequestContextType request_context_type, |
| 58 RequestContextFrameType frame_type, |
| 59 bool is_parent_frame_secure, |
| 60 scoped_refptr<ResourceRequestBodyImpl> body, |
| 61 const base::Callback<WebContents*(void)>& web_contents_getter, |
| 62 CompleteNavigationStartCallback complete_request) { |
47 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 63 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
48 DCHECK(request->request_body.get()); | 64 DCHECK(service_worker_navigation_handle_core || |
| 65 resource_request->request_body.get()); |
49 | 66 |
50 AttachRequestBodyBlobDataHandles(request->request_body.get(), | 67 mojom::URLLoaderFactoryPtrInfo url_loader_factory_ptr_info; |
51 resource_context); | 68 if (service_worker_navigation_handle_core) { |
| 69 storage::BlobStorageContext* blob_storage_context = GetBlobStorageContext( |
| 70 GetChromeBlobStorageContextForResourceContext(resource_context)); |
| 71 url_loader_factory_ptr_info = |
| 72 ServiceWorkerRequestHandler::InitializeForNavigationNetworkService( |
| 73 *resource_request, resource_context, |
| 74 service_worker_navigation_handle_core, blob_storage_context, |
| 75 skip_service_worker, resource_type, request_context_type, |
| 76 frame_type, is_parent_frame_secure, body, web_contents_getter, |
| 77 // This is a fallback callback if the service worker handler decides |
| 78 // later that the request should fallback to the network. |
| 79 base::Bind( |
| 80 complete_request, |
| 81 base::Passed(std::move(mojom::URLLoaderFactoryPtrInfo())))); |
| 82 } |
| 83 |
| 84 if (resource_request->request_body) { |
| 85 AttachRequestBodyBlobDataHandles(resource_request->request_body.get(), |
| 86 resource_context); |
| 87 } |
| 88 |
52 BrowserThread::PostTask( | 89 BrowserThread::PostTask( |
53 BrowserThread::UI, FROM_HERE, | 90 BrowserThread::UI, FROM_HERE, |
54 base::Bind(&NavigationURLLoaderNetworkService::StartURLRequest, | 91 base::Bind(complete_request, |
55 url_loader, base::Passed(&request))); | 92 base::Passed(std::move(url_loader_factory_ptr_info)), |
| 93 base::Passed(std::move(resource_request)))); |
| 94 } |
| 95 |
| 96 WebContents* GetWebContentsFromFrameTreeNodeID(int frame_tree_node_id) { |
| 97 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 98 FrameTreeNode* frame_tree_node = |
| 99 FrameTreeNode::GloballyFindByID(frame_tree_node_id); |
| 100 if (!frame_tree_node) |
| 101 return nullptr; |
| 102 |
| 103 return WebContentsImpl::FromFrameTreeNode(frame_tree_node); |
56 } | 104 } |
57 | 105 |
58 } // namespace | 106 } // namespace |
59 | 107 |
60 NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService( | 108 NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService( |
61 ResourceContext* resource_context, | 109 ResourceContext* resource_context, |
62 StoragePartition* storage_partition, | 110 StoragePartition* storage_partition, |
63 std::unique_ptr<NavigationRequestInfo> request_info, | 111 std::unique_ptr<NavigationRequestInfo> request_info, |
64 std::unique_ptr<NavigationUIData> navigation_ui_data, | 112 std::unique_ptr<NavigationUIData> navigation_ui_data, |
65 ServiceWorkerNavigationHandle* service_worker_handle, | 113 ServiceWorkerNavigationHandle* service_worker_navigation_handle, |
66 AppCacheNavigationHandle* appcache_handle, | 114 AppCacheNavigationHandle* appcache_handle, |
67 NavigationURLLoaderDelegate* delegate) | 115 NavigationURLLoaderDelegate* delegate) |
68 : delegate_(delegate), | 116 : delegate_(delegate), |
69 binding_(this), | 117 binding_(this), |
70 request_info_(std::move(request_info)), | 118 request_info_(std::move(request_info)), |
71 weak_factory_(this) { | 119 weak_factory_(this) { |
72 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 120 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
73 | 121 |
74 TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1( | 122 TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1( |
75 "navigation", "Navigation timeToResponseStarted", this, | 123 "navigation", "Navigation timeToResponseStarted", this, |
(...skipping 22 matching lines...) Expand all Loading... |
98 if (request_info_->is_main_frame) | 146 if (request_info_->is_main_frame) |
99 load_flags |= net::LOAD_MAIN_FRAME_DEPRECATED; | 147 load_flags |= net::LOAD_MAIN_FRAME_DEPRECATED; |
100 | 148 |
101 // Sync loads should have maximum priority and should be the only | 149 // Sync loads should have maximum priority and should be the only |
102 // requests that have the ignore limits flag set. | 150 // requests that have the ignore limits flag set. |
103 DCHECK(!(load_flags & net::LOAD_IGNORE_LIMITS)); | 151 DCHECK(!(load_flags & net::LOAD_IGNORE_LIMITS)); |
104 | 152 |
105 new_request->load_flags = load_flags; | 153 new_request->load_flags = load_flags; |
106 | 154 |
107 new_request->request_body = request_info_->common_params.post_data.get(); | 155 new_request->request_body = request_info_->common_params.post_data.get(); |
108 if (new_request->request_body.get()) { | 156 |
109 // The request body may need blob handles to be added to it. This | 157 ResourceType resource_type = request_info_->is_main_frame |
110 // functionality has to be invoked on the IO thread. | 158 ? RESOURCE_TYPE_MAIN_FRAME |
| 159 : RESOURCE_TYPE_SUB_FRAME; |
| 160 RequestContextFrameType frame_type = |
| 161 request_info_->is_main_frame ? REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL |
| 162 : REQUEST_CONTEXT_FRAME_TYPE_NESTED; |
| 163 |
| 164 // Determine where the request will be serviced. If there's work that needs to |
| 165 // be done on the IO thread due to Service Worker or POST body, then post to |
| 166 // the IO thread to have it do that work, and then continue on to |
| 167 // StartURLRequest. Otherwise, handle the request directly. |
| 168 const bool need_to_work_on_io = |
| 169 service_worker_navigation_handle || new_request->request_body; |
| 170 if (need_to_work_on_io) { |
111 BrowserThread::PostTask( | 171 BrowserThread::PostTask( |
112 BrowserThread::IO, FROM_HERE, | 172 BrowserThread::IO, FROM_HERE, |
113 base::Bind(&HandleRequestsWithBody, | 173 base::Bind( |
114 base::Passed(&new_request), | 174 &PrepareNavigationStartOnIOThread, |
115 resource_context, | 175 base::Passed(std::move(new_request)), resource_context, |
116 weak_factory_.GetWeakPtr())); | 176 service_worker_navigation_handle |
| 177 ? service_worker_navigation_handle->core() |
| 178 : nullptr, |
| 179 request_info_->begin_params.skip_service_worker, resource_type, |
| 180 request_info_->begin_params.request_context_type, frame_type, |
| 181 request_info_->are_ancestors_secure, |
| 182 request_info_->common_params.post_data, |
| 183 base::Bind(&GetWebContentsFromFrameTreeNodeID, |
| 184 request_info_->frame_tree_node_id), |
| 185 base::Bind(&NavigationURLLoaderNetworkService::StartURLRequest, |
| 186 weak_factory_.GetWeakPtr()))); |
117 return; | 187 return; |
118 } | 188 } |
119 | 189 |
120 StartURLRequest(std::move(new_request)); | 190 StartURLRequest(mojom::URLLoaderFactoryPtrInfo(), std::move(new_request)); |
121 } | 191 } |
122 | 192 |
123 NavigationURLLoaderNetworkService::~NavigationURLLoaderNetworkService() {} | 193 NavigationURLLoaderNetworkService::~NavigationURLLoaderNetworkService() {} |
124 | 194 |
125 void NavigationURLLoaderNetworkService::OverrideURLLoaderFactoryForTesting( | 195 void NavigationURLLoaderNetworkService::OverrideURLLoaderFactoryForTesting( |
126 mojom::URLLoaderFactoryPtr url_loader_factory) { | 196 mojom::URLLoaderFactoryPtr url_loader_factory) { |
127 g_url_loader_factory.Get() = std::move(url_loader_factory); | 197 g_url_loader_factory.Get() = std::move(url_loader_factory); |
128 } | 198 } |
129 | 199 |
130 void NavigationURLLoaderNetworkService::FollowRedirect() { | 200 void NavigationURLLoaderNetworkService::FollowRedirect() { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", | 263 TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", |
194 this, "&NavigationURLLoaderNetworkService", this, | 264 this, "&NavigationURLLoaderNetworkService", this, |
195 "success", false); | 265 "success", false); |
196 | 266 |
197 delegate_->OnRequestFailed(completion_status.exists_in_cache, | 267 delegate_->OnRequestFailed(completion_status.exists_in_cache, |
198 completion_status.error_code); | 268 completion_status.error_code); |
199 } | 269 } |
200 } | 270 } |
201 | 271 |
202 void NavigationURLLoaderNetworkService::StartURLRequest( | 272 void NavigationURLLoaderNetworkService::StartURLRequest( |
| 273 mojom::URLLoaderFactoryPtrInfo url_loader_factory_info, |
203 std::unique_ptr<ResourceRequest> request) { | 274 std::unique_ptr<ResourceRequest> request) { |
204 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 275 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
205 | 276 |
| 277 // Bind the URLClient implementation to this object to pass to the URLLoader. |
| 278 if (binding_.is_bound()) |
| 279 binding_.Unbind(); |
206 mojom::URLLoaderClientPtr url_loader_client_ptr_to_pass; | 280 mojom::URLLoaderClientPtr url_loader_client_ptr_to_pass; |
207 binding_.Bind(&url_loader_client_ptr_to_pass); | 281 binding_.Bind(&url_loader_client_ptr_to_pass); |
208 | 282 |
209 mojom::URLLoaderFactory* factory = nullptr; | 283 mojom::URLLoaderFactory* factory = nullptr; |
210 // This |factory_ptr| will be destroyed when it goes out of scope. Because | 284 // This |factory_ptr| will be destroyed when it goes out of scope. Because |
211 // |url_loader_associated_ptr_| is associated with it, it will be disconnected | 285 // |url_loader_associated_ptr_| is associated with it, it will be disconnected |
212 // as well. That means NavigationURLLoaderNetworkService::FollowRedirect() | 286 // as well. That means NavigationURLLoaderNetworkService::FollowRedirect() |
213 // won't work as expected, the |url_loader_associated_ptr_| will silently drop | 287 // won't work as expected, the |url_loader_associated_ptr_| will silently drop |
214 // calls. | 288 // calls. |
215 // This is fine for now since the only user of this is WebUI which doesn't | 289 // This is fine for now since the only user of this is WebUI which doesn't |
216 // need this, but we'll have to fix this when other consumers come up. | 290 // need this, but we'll have to fix this when other consumers come up. |
217 mojom::URLLoaderFactoryPtr factory_ptr; | 291 mojom::URLLoaderFactoryPtr factory_ptr; |
218 const auto& schemes = URLDataManagerBackend::GetWebUISchemes(); | 292 const auto& schemes = URLDataManagerBackend::GetWebUISchemes(); |
219 if (std::find(schemes.begin(), schemes.end(), request->url.scheme()) != | 293 if (std::find(schemes.begin(), schemes.end(), request->url.scheme()) != |
220 schemes.end()) { | 294 schemes.end()) { |
221 FrameTreeNode* frame_tree_node = | 295 FrameTreeNode* frame_tree_node = |
222 FrameTreeNode::GloballyFindByID(request_info_->frame_tree_node_id); | 296 FrameTreeNode::GloballyFindByID(request_info_->frame_tree_node_id); |
223 factory_ptr = GetWebUIURLLoader(frame_tree_node); | 297 factory_ptr = GetWebUIURLLoader(frame_tree_node); |
224 factory = factory_ptr.get(); | 298 factory = factory_ptr.get(); |
225 } | 299 } |
226 | 300 |
227 if (!factory) | 301 if (!factory) { |
228 factory = GetURLLoaderFactory(); | 302 // If a URLLoaderFactory was provided, then we use that one, otherwise |
| 303 // fall back to connecting directly to the network service. |
| 304 if (url_loader_factory_info.is_valid()) { |
| 305 url_loader_factory_.Bind(std::move(url_loader_factory_info)); |
| 306 factory = url_loader_factory_.get(); |
| 307 } else { |
| 308 factory = GetURLLoaderFactory(); |
| 309 } |
| 310 } |
229 | 311 |
230 factory->CreateLoaderAndStart(mojo::MakeRequest(&url_loader_associated_ptr_), | 312 factory->CreateLoaderAndStart(mojo::MakeRequest(&url_loader_associated_ptr_), |
231 0 /* routing_id? */, 0 /* request_id? */, | 313 0 /* routing_id? */, 0 /* request_id? */, |
232 mojom::kURLLoadOptionSendSSLInfo, *request, | 314 mojom::kURLLoadOptionSendSSLInfo, *request, |
233 std::move(url_loader_client_ptr_to_pass)); | 315 std::move(url_loader_client_ptr_to_pass)); |
234 } | 316 } |
235 | 317 |
236 mojom::URLLoaderFactory* | 318 mojom::URLLoaderFactory* |
237 NavigationURLLoaderNetworkService::GetURLLoaderFactory() { | 319 NavigationURLLoaderNetworkService::GetURLLoaderFactory() { |
238 // TODO(yzshen): We will need the ability to customize the factory per frame | 320 // TODO(yzshen): We will need the ability to customize the factory per frame |
239 // e.g., for appcache or service worker. | 321 // e.g., for appcache or service worker. |
240 if (!g_url_loader_factory.Get()) { | 322 if (!g_url_loader_factory.Get()) { |
241 ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface( | 323 ServiceManagerConnection::GetForProcess()->GetConnector()->BindInterface( |
242 mojom::kNetworkServiceName, &g_url_loader_factory.Get()); | 324 mojom::kNetworkServiceName, &g_url_loader_factory.Get()); |
243 } | 325 } |
244 | 326 |
245 return g_url_loader_factory.Get().get(); | 327 return g_url_loader_factory.Get().get(); |
246 } | 328 } |
247 | 329 |
248 } // namespace content | 330 } // namespace content |
OLD | NEW |