Index: content/browser/loader/resource_dispatcher_host_impl.cc |
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc |
index 4df00ab3f9cfd9d86e0dfcd117cc3ca23668288e..f1b49062f3b00cac57ddbcbee51cf0c7ce2b364a 100644 |
--- a/content/browser/loader/resource_dispatcher_host_impl.cc |
+++ b/content/browser/loader/resource_dispatcher_host_impl.cc |
@@ -36,6 +36,7 @@ |
#include "content/browser/loader/buffered_resource_handler.h" |
#include "content/browser/loader/cross_site_resource_handler.h" |
#include "content/browser/loader/detachable_resource_handler.h" |
+#include "content/browser/loader/navigation_resource_handler.h" |
#include "content/browser/loader/power_save_block_resource_throttle.h" |
#include "content/browser/loader/redirect_to_file_resource_handler.h" |
#include "content/browser/loader/resource_message_filter.h" |
@@ -65,6 +66,7 @@ |
#include "content/public/browser/resource_request_details.h" |
#include "content/public/browser/resource_throttle.h" |
#include "content/public/browser/stream_handle.h" |
+#include "content/public/browser/stream_info.h" |
#include "content/public/browser/user_metrics.h" |
#include "content/public/common/content_switches.h" |
#include "content/public/common/process_type.h" |
@@ -303,10 +305,10 @@ bool IsValidatedSCT( |
} |
storage::BlobStorageContext* GetBlobStorageContext( |
- ResourceMessageFilter* filter) { |
- if (!filter->blob_storage_context()) |
+ ChromeBlobStorageContext* blob_storage_context) { |
+ if (!blob_storage_context) |
return NULL; |
- return filter->blob_storage_context()->context(); |
+ return blob_storage_context->context(); |
} |
void AttachRequestBodyBlobDataHandles( |
@@ -467,15 +469,16 @@ void ResourceDispatcherHostImpl::CancelRequestsForContext( |
for (LoaderList::iterator i = loaders_to_cancel.begin(); |
i != loaders_to_cancel.end(); ++i) { |
// There is no strict requirement that this be the case, but currently |
- // downloads, streams, detachable requests, and transferred requests are the |
- // only requests that aren't cancelled when the associated processes go |
- // away. It may be OK for this invariant to change in the future, but if |
- // this assertion fires without the invariant changing, then it's indicative |
- // of a leak. |
+ // downloads, streams, detachable requests, transferred requests, and |
+ // browser-owned requests are the only requests that aren't cancelled when |
+ // the associated processes go away. It may be OK for this invariant to |
+ // change in the future, but if this assertion fires without the invariant |
+ // changing, then it's indicative of a leak. |
DCHECK((*i)->GetRequestInfo()->IsDownload() || |
(*i)->GetRequestInfo()->is_stream() || |
((*i)->GetRequestInfo()->detachable_handler() && |
(*i)->GetRequestInfo()->detachable_handler()->is_detached()) || |
+ (*i)->GetRequestInfo()->GetProcessType() == PROCESS_TYPE_BROWSER || |
(*i)->is_transferring()); |
} |
#endif |
@@ -663,12 +666,11 @@ ResourceDispatcherHostImpl::MaybeInterceptAsStream(net::URLRequest* request, |
origin)); |
info->set_is_stream(true); |
- delegate_->OnStreamCreated( |
- request, |
- handler->stream()->CreateHandle( |
- request->url(), |
- mime_type, |
- response->head.headers)); |
+ scoped_ptr<StreamInfo> stream_info(new StreamInfo); |
+ stream_info->handle = handler->stream()->CreateHandle(); |
+ stream_info->original_url = request->url(); |
+ stream_info->response = response; |
+ delegate_->OnStreamCreated(request, stream_info.Pass()); |
return handler.PassAs<ResourceHandler>(); |
} |
@@ -1081,7 +1083,7 @@ void ResourceDispatcherHostImpl::BeginRequest( |
new_request->SetLoadFlags(load_flags); |
storage::BlobStorageContext* blob_context = |
- GetBlobStorageContext(filter_); |
+ GetBlobStorageContext(filter_->blob_storage_context()); |
// Resolve elements from request_body and prepare upload data. |
if (request_data.request_body.get()) { |
// Attaches the BlobDataHandles to request_body not to free the blobs and |
@@ -1201,20 +1203,26 @@ scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::CreateResourceHandler( |
handler.Pass())); |
} |
- // Install a CrossSiteResourceHandler for all main frame requests. This will |
- // let us check whether a transfer is required and pause for the unload |
- // handler either if so or if a cross-process navigation is already under way. |
- bool is_swappable_navigation = |
- request_data.resource_type == RESOURCE_TYPE_MAIN_FRAME; |
- // If we are using --site-per-process, install it for subframes as well. |
- if (!is_swappable_navigation && |
- base::CommandLine::ForCurrentProcess()->HasSwitch( |
- switches::kSitePerProcess)) { |
- is_swappable_navigation = |
- request_data.resource_type == RESOURCE_TYPE_SUB_FRAME; |
+ // If using --enable-browser-side-navigation, the CrossSiteResourceHandler is |
+ // not needed. |
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch( |
+ switches::kEnableBrowserSideNavigation)) { |
+ // Install a CrossSiteResourceHandler for all main frame requests. This |
+ // will let us check whether a transfer is required and pause for the unload |
+ // handler either if so or if a cross-process navigation is already under |
+ // way. |
+ bool is_swappable_navigation = |
+ request_data.resource_type == RESOURCE_TYPE_MAIN_FRAME; |
+ // If we are using --site-per-process, install it for subframes as well. |
+ if (!is_swappable_navigation && |
+ base::CommandLine::ForCurrentProcess()->HasSwitch( |
+ switches::kSitePerProcess)) { |
+ is_swappable_navigation = |
+ request_data.resource_type == RESOURCE_TYPE_SUB_FRAME; |
+ } |
+ if (is_swappable_navigation && process_type == PROCESS_TYPE_RENDERER) |
+ handler.reset(new CrossSiteResourceHandler(handler.Pass(), request)); |
} |
- if (is_swappable_navigation && process_type == PROCESS_TYPE_RENDERER) |
- handler.reset(new CrossSiteResourceHandler(handler.Pass(), request)); |
// Insert a buffered event handler before the actual one. |
handler.reset( |
@@ -1661,18 +1669,176 @@ void ResourceDispatcherHostImpl::FinishedWithResourcesForRequest( |
IncrementOutstandingRequestsCount(-1, *info); |
} |
-void ResourceDispatcherHostImpl::StartNavigationRequest( |
+bool ResourceDispatcherHostImpl::BeginNavigationRequest( |
+ ResourceContext* resource_context, |
+ int64 frame_tree_node_id, |
const NavigationRequestInfo& info, |
scoped_refptr<ResourceRequestBody> request_body, |
- int64 navigation_request_id, |
- int64 frame_node_id) { |
- NOTIMPLEMENTED(); |
-} |
+ NavigationURLLoaderCore* loader) { |
clamy
2014/09/12 20:51:25
I would add a CHECK that browser side navigation i
davidben
2014/09/19 18:30:50
Good point. Done.
|
+ ResourceType resource_type = info.is_main_frame ? |
+ RESOURCE_TYPE_MAIN_FRAME : RESOURCE_TYPE_SUB_FRAME; |
+ |
+ if (is_shutdown_ || |
+ // TODO(davidben): Check ShouldServiceRequest here. This is important; it |
+ // needs to be checked relative to the child that /requested/ the |
+ // navigation. It's where file upload checks, etc., come in. |
+ (delegate_ && !delegate_->ShouldBeginRequest( |
+ info.navigation_params.method, |
+ info.navigation_params.url, |
+ resource_type, |
+ resource_context))) { |
+ return false; |
+ } |
+ |
+ // http://crbug.com/90971 |
+ char url_buf[128]; |
+ base::strlcpy( |
+ url_buf, info.navigation_params.url.spec().c_str(), arraysize(url_buf)); |
+ base::debug::Alias(url_buf); |
+ CHECK(ContainsKey(active_resource_contexts_, resource_context)); |
+ |
+ const net::URLRequestContext* request_context = |
+ resource_context->GetRequestContext(); |
+ |
+ int load_flags = info.navigation_params.load_flags; |
+ load_flags |= net::LOAD_VERIFY_EV_CERT; |
+ if (info.is_main_frame) { |
+ load_flags |= net::LOAD_MAIN_FRAME; |
+ } else { |
+ load_flags |= net::LOAD_SUB_FRAME; |
+ } |
+ // Add a flag to selectively bypass the data reduction proxy if the resource |
+ // type is not an image. |
+ load_flags |= net::LOAD_BYPASS_DATA_REDUCTION_PROXY; |
+ |
+ // TODO(davidben): BuildLoadFlagsForRequest includes logic for |
+ // CanSendCookiesForOrigin and CanReadRawCookies. Is this needed here? |
-void ResourceDispatcherHostImpl::CancelNavigationRequest( |
- int64 navigation_request_id, |
- int64 frame_node_id) { |
- NOTIMPLEMENTED(); |
+ // Sync loads should have maximum priority and should be the only |
+ // requests that have the ignore limits flag set. |
+ DCHECK_EQ(load_flags & net::LOAD_IGNORE_LIMITS, 0); |
+ |
+ // TODO(davidben): OverrideCookieStoreForRenderProcess handling for |
+ // prerender. There isn't a renderer process yet, so we need to use the |
+ // ResourceContext or something. |
+ scoped_ptr<net::URLRequest> new_request; |
+ new_request = request_context->CreateRequest( |
+ info.navigation_params.url, net::HIGHEST, NULL, NULL); |
+ |
+ new_request->set_method(info.navigation_params.method); |
+ new_request->set_first_party_for_cookies( |
+ info.first_party_for_cookies); |
+ if (info.is_main_frame) { |
+ new_request->set_first_party_url_policy( |
+ net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT); |
+ } |
+ |
+ SetReferrerForRequest(new_request.get(), info.navigation_params.referrer); |
+ |
+ net::HttpRequestHeaders headers; |
+ headers.AddHeadersFromString(info.navigation_params.headers); |
+ new_request->SetExtraRequestHeaders(headers); |
+ |
+ new_request->SetLoadFlags(load_flags); |
+ |
+ // Resolve elements from request_body and prepare upload data. |
+ if (info.navigation_params.request_body.get()) { |
+ storage::BlobStorageContext* blob_context = GetBlobStorageContext( |
+ GetChromeBlobStorageContextForResourceContext(resource_context)); |
+ AttachRequestBodyBlobDataHandles( |
+ info.navigation_params.request_body.get(), |
+ blob_context); |
+ // TODO(davidben): The FileSystemContext is NULL here. In the case where |
+ // another renderer requested this navigation, this should be the same |
+ // FileSystemContext passed into ShouldServiceRequest. |
+ new_request->set_upload(UploadDataStreamBuilder::Build( |
+ info.navigation_params.request_body.get(), |
+ blob_context, |
+ NULL, // file_system_context |
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE) |
+ .get())); |
+ } |
+ |
+ request_id_--; |
+ |
+ // Make extra info and read footer (contains request ID). |
+ // |
+ // TODO(davidben): Associate the request with the FrameTreeNode or tab so that |
+ // IO thread -> UI thread hops will work. |
+ ResourceRequestInfoImpl* extra_info = |
+ new ResourceRequestInfoImpl( |
+ PROCESS_TYPE_BROWSER, |
+ -1, // child_id |
+ -1, // route_id |
+ -1, // request_data.origin_pid, |
+ request_id_, |
+ -1, // request_data.render_frame_id, |
+ info.is_main_frame, |
+ info.parent_is_main_frame, |
+ -1, // request_data.parent_render_frame_id, |
+ resource_type, |
+ info.navigation_params.transition_type, |
+ info.navigation_params.should_replace_current_entry, |
+ false, // is download |
+ false, // is stream |
+ info.navigation_params.allow_download, |
+ info.navigation_params.has_user_gesture, |
+ true, |
+ info.navigation_params.referrer.policy, |
+ // TODO(davidben): This is only used for prerenders. Replace |
+ // is_showing with something for that. Or maybe it just comes from the |
+ // same mechanism as the cookie one. |
+ blink::WebPageVisibilityStateVisible, |
+ resource_context, |
+ base::WeakPtr<ResourceMessageFilter>(), // filter |
+ true); |
+ // Request takes ownership. |
+ extra_info->AssociateWithRequest(new_request.get()); |
+ |
+ if (new_request->url().SchemeIs(url::kBlobScheme)) { |
+ // Hang on to a reference to ensure the blob is not released prior |
+ // to the job being started. |
+ ChromeBlobStorageContext* blob_context = |
+ GetChromeBlobStorageContextForResourceContext(resource_context); |
+ storage::BlobProtocolHandler::SetRequestedBlobDataHandle( |
+ new_request.get(), |
+ blob_context->context()->GetBlobDataFromPublicURL(new_request->url())); |
+ } |
+ |
+ // TODO(davidben): Attach ServiceWorkerRequestHandler. |
+ |
+ // TODO(davidben): Attach AppCacheInterceptor. |
+ |
+ scoped_ptr<ResourceHandler> handler(new NavigationResourceHandler( |
+ new_request.get(), loader)); |
+ |
+ // Insert a buffered event handler before the actual one. |
+ handler.reset( |
+ new BufferedResourceHandler(handler.Pass(), this, new_request.get())); |
+ |
+ ScopedVector<ResourceThrottle> throttles; |
+ if (delegate_) { |
+ // TODO(davidben): appcache_service is currently NULL. |
+ delegate_->RequestBeginning(new_request.get(), |
+ resource_context, |
+ NULL, |
+ resource_type, |
+ &throttles); |
+ } |
+ |
+ if (new_request->has_upload()) { |
+ // Block power save while uploading data. |
+ throttles.push_back(new PowerSaveBlockResourceThrottle()); |
+ } |
+ |
+ // TODO(davidben): Attach ResourceScheduler's throttle. |
+ |
+ handler.reset(new ThrottlingResourceHandler( |
+ handler.Pass(), new_request.get(), throttles.Pass())); |
+ |
+ if (handler) |
+ BeginRequestInternal(new_request.Pass(), handler.Pass()); |
+ return true; |
} |
// static |