| 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 1db3d98e157c29ae3455281fdbd72dbf65d12d4a..87ddb0c3730fa150532e7544e1772e95f55f66b3 100644
|
| --- a/content/browser/loader/resource_dispatcher_host_impl.cc
|
| +++ b/content/browser/loader/resource_dispatcher_host_impl.cc
|
| @@ -39,6 +39,7 @@
|
| #include "content/browser/download/save_file_manager.h"
|
| #include "content/browser/download/save_file_resource_handler.h"
|
| #include "content/browser/fileapi/chrome_blob_storage_context.h"
|
| +#include "content/browser/frame_host/frame_tree.h"
|
| #include "content/browser/frame_host/navigation_request_info.h"
|
| #include "content/browser/frame_host/navigator.h"
|
| #include "content/browser/loader/async_resource_handler.h"
|
| @@ -466,8 +467,80 @@ void RecordAbortRapporOnUI(const GURL& url,
|
| GetContentClient()->browser()->RecordURLMetric("Net.ErrAborted.Slow", url);
|
| }
|
|
|
| +// The following functions simplify code paths where the UI thread notifies the
|
| +// ResourceDispatcherHostImpl of information pertaining to loading behavior of
|
| +// frame hosts.
|
| +void NotifyForRouteOnIO(
|
| + base::Callback<void(ResourceDispatcherHostImpl*,
|
| + const GlobalFrameRoutingId&)> frame_callback,
|
| + const GlobalFrameRoutingId& global_routing_id) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
|
| + if (rdh)
|
| + frame_callback.Run(rdh, global_routing_id);
|
| +}
|
| +
|
| +void NotifyForRouteFromUI(
|
| + const GlobalFrameRoutingId& global_routing_id,
|
| + base::Callback<void(ResourceDispatcherHostImpl*,
|
| + const GlobalFrameRoutingId&)> frame_callback) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&NotifyForRouteOnIO, frame_callback, global_routing_id));
|
| +}
|
| +
|
| +void NotifyForRouteSetOnIO(
|
| + base::Callback<void(ResourceDispatcherHostImpl*,
|
| + const GlobalFrameRoutingId&)> frame_callback,
|
| + scoped_ptr<std::set<GlobalFrameRoutingId>> routing_ids) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + for (const auto& routing_id : *routing_ids)
|
| + NotifyForRouteOnIO(frame_callback, routing_id);
|
| +}
|
| +
|
| +void NotifyForEachFrameFromUI(
|
| + RenderFrameHost* root_frame_host,
|
| + base::Callback<void(ResourceDispatcherHostImpl*,
|
| + const GlobalFrameRoutingId&)> frame_callback) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| + FrameTree* frame_tree = static_cast<RenderFrameHostImpl*>(root_frame_host)
|
| + ->frame_tree_node()
|
| + ->frame_tree();
|
| + DCHECK_EQ(root_frame_host, frame_tree->GetMainFrame());
|
| + scoped_ptr<std::set<GlobalFrameRoutingId>> routing_ids(
|
| + new std::set<GlobalFrameRoutingId>());
|
| + for (FrameTreeNode* node : frame_tree->Nodes()) {
|
| + RenderFrameHostImpl* frame_host = node->current_frame_host();
|
| + RenderFrameHostImpl* pending_frame_host =
|
| + IsBrowserSideNavigationEnabled()
|
| + ? node->render_manager()->speculative_frame_host()
|
| + : node->render_manager()->pending_frame_host();
|
| + if (frame_host)
|
| + routing_ids->insert(frame_host->GetGlobalFrameRoutingId());
|
| + if (pending_frame_host)
|
| + routing_ids->insert(pending_frame_host->GetGlobalFrameRoutingId());
|
| + }
|
| + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&NotifyForRouteSetOnIO, frame_callback,
|
| + base::Passed(std::move(routing_ids))));
|
| +}
|
| +
|
| } // namespace
|
|
|
| +LoaderIOThreadNotifier::LoaderIOThreadNotifier(WebContents* web_contents)
|
| + : WebContentsObserver(web_contents) {}
|
| +
|
| +LoaderIOThreadNotifier::~LoaderIOThreadNotifier() {}
|
| +
|
| +void LoaderIOThreadNotifier::RenderFrameDeleted(
|
| + RenderFrameHost* render_frame_host) {
|
| + NotifyForRouteFromUI(
|
| + static_cast<RenderFrameHostImpl*>(render_frame_host)
|
| + ->GetGlobalFrameRoutingId(),
|
| + base::Bind(&ResourceDispatcherHostImpl::OnRenderFrameDeleted));
|
| +}
|
| +
|
| // static
|
| ResourceDispatcherHost* ResourceDispatcherHost::Get() {
|
| return g_resource_dispatcher_host;
|
| @@ -534,6 +607,42 @@ ResourceDispatcherHostImpl* ResourceDispatcherHostImpl::Get() {
|
| return g_resource_dispatcher_host;
|
| }
|
|
|
| +// static
|
| +void ResourceDispatcherHostImpl::ResumeBlockedRequestsForRouteFromUI(
|
| + const GlobalFrameRoutingId& global_routing_id) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| + NotifyForRouteFromUI(
|
| + global_routing_id,
|
| + base::Bind(&ResourceDispatcherHostImpl::ResumeBlockedRequestsForRoute));
|
| +}
|
| +
|
| +// static
|
| +void ResourceDispatcherHostImpl::BlockRequestsForFrameFromUI(
|
| + RenderFrameHost* root_frame_host) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| + NotifyForEachFrameFromUI(
|
| + root_frame_host,
|
| + base::Bind(&ResourceDispatcherHostImpl::BlockRequestsForRoute));
|
| +}
|
| +
|
| +// static
|
| +void ResourceDispatcherHostImpl::ResumeBlockedRequestsForFrameFromUI(
|
| + RenderFrameHost* root_frame_host) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| + NotifyForEachFrameFromUI(
|
| + root_frame_host,
|
| + base::Bind(&ResourceDispatcherHostImpl::ResumeBlockedRequestsForRoute));
|
| +}
|
| +
|
| +// static
|
| +void ResourceDispatcherHostImpl::CancelBlockedRequestsForFrameFromUI(
|
| + RenderFrameHostImpl* root_frame_host) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| + NotifyForEachFrameFromUI(
|
| + root_frame_host,
|
| + base::Bind(&ResourceDispatcherHostImpl::CancelBlockedRequestsForRoute));
|
| +}
|
| +
|
| void ResourceDispatcherHostImpl::SetDelegate(
|
| ResourceDispatcherHostDelegate* delegate) {
|
| delegate_ = delegate;
|
| @@ -1090,15 +1199,15 @@ void ResourceDispatcherHostImpl::OnShutdown() {
|
| // Note that we have to do this in 2 passes as we cannot call
|
| // CancelBlockedRequestsForRoute while iterating over
|
| // blocked_loaders_map_, as it modifies it.
|
| - std::set<GlobalRoutingID> ids;
|
| + std::set<GlobalFrameRoutingId> ids;
|
| for (const auto& blocked_loaders : blocked_loaders_map_) {
|
| - std::pair<std::set<GlobalRoutingID>::iterator, bool> result =
|
| + std::pair<std::set<GlobalFrameRoutingId>::iterator, bool> result =
|
| ids.insert(blocked_loaders.first);
|
| // We should not have duplicates.
|
| DCHECK(result.second);
|
| }
|
| for (const auto& routing_id : ids) {
|
| - CancelBlockedRequestsForRoute(routing_id.child_id, routing_id.route_id);
|
| + CancelBlockedRequestsForRoute(routing_id);
|
| }
|
|
|
| scheduler_.reset();
|
| @@ -1208,11 +1317,11 @@ void ResourceDispatcherHostImpl::UpdateRequestForTransfer(
|
| const ResourceHostMsg_Request& request_data,
|
| LoaderMap::iterator iter) {
|
| ResourceRequestInfoImpl* info = iter->second->GetRequestInfo();
|
| - GlobalRoutingID old_routing_id(
|
| - request_data.transferred_request_child_id, info->GetRouteID());
|
| + GlobalFrameRoutingId old_routing_id(request_data.transferred_request_child_id,
|
| + info->GetRenderFrameID());
|
| GlobalRequestID old_request_id(request_data.transferred_request_child_id,
|
| request_data.transferred_request_request_id);
|
| - GlobalRoutingID new_routing_id(child_id, route_id);
|
| + GlobalFrameRoutingId new_routing_id(child_id, request_data.render_frame_id);
|
| GlobalRequestID new_request_id(child_id, request_id);
|
|
|
| // Clear out data that depends on |info| before updating it.
|
| @@ -1787,16 +1896,19 @@ ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo(
|
| std::string()); // original_headers
|
| }
|
|
|
| +void ResourceDispatcherHostImpl::OnRenderFrameDeleted(
|
| + const GlobalFrameRoutingId& global_routing_id) {
|
| + CancelRequestsForRoute(global_routing_id);
|
| +}
|
| +
|
| void ResourceDispatcherHostImpl::OnRenderViewHostCreated(int child_id,
|
| int route_id) {
|
| scheduler_->OnClientCreated(child_id, route_id);
|
| }
|
|
|
| -void ResourceDispatcherHostImpl::OnRenderViewHostDeleted(
|
| - int child_id,
|
| - int route_id) {
|
| +void ResourceDispatcherHostImpl::OnRenderViewHostDeleted(int child_id,
|
| + int route_id) {
|
| scheduler_->OnClientDeleted(child_id, route_id);
|
| - CancelRequestsForRoute(child_id, route_id);
|
| }
|
|
|
| void ResourceDispatcherHostImpl::OnRenderViewHostSetIsLoading(int child_id,
|
| @@ -1882,18 +1994,23 @@ void ResourceDispatcherHostImpl::ResumeDeferredNavigation(
|
| // for downloads and detachable resources, which belong to the browser process
|
| // even if initiated via a renderer.
|
| void ResourceDispatcherHostImpl::CancelRequestsForProcess(int child_id) {
|
| - CancelRequestsForRoute(child_id, -1 /* cancel all */);
|
| + CancelRequestsForRoute(
|
| + GlobalFrameRoutingId(child_id, MSG_ROUTING_NONE /* cancel all */));
|
| registered_temp_files_.erase(child_id);
|
| }
|
|
|
| -void ResourceDispatcherHostImpl::CancelRequestsForRoute(int child_id,
|
| - int route_id) {
|
| +void ResourceDispatcherHostImpl::CancelRequestsForRoute(
|
| + const GlobalFrameRoutingId& global_routing_id) {
|
| // Since pending_requests_ is a map, we first build up a list of all of the
|
| // matching requests to be cancelled, and then we cancel them. Since there
|
| // may be more than one request to cancel, we cannot simply hold onto the map
|
| // iterators found in the first loop.
|
|
|
| // Find the global ID of all matching elements.
|
| + int child_id = global_routing_id.child_id;
|
| + int route_id = global_routing_id.frame_routing_id;
|
| + bool cancel_all_routes = (route_id == MSG_ROUTING_NONE);
|
| +
|
| bool any_requests_transferring = false;
|
| std::vector<GlobalRequestID> matching_requests;
|
| for (const auto& loader : pending_loaders_) {
|
| @@ -1911,7 +2028,7 @@ void ResourceDispatcherHostImpl::CancelRequestsForRoute(int child_id,
|
| info->detachable_handler()->Detach();
|
| } else if (!info->IsDownload() && !info->is_stream() &&
|
| !IsTransferredNavigation(id) &&
|
| - (route_id == -1 || route_id == info->GetRouteID())) {
|
| + (cancel_all_routes || route_id == info->GetRenderFrameID())) {
|
| matching_requests.push_back(id);
|
| }
|
| }
|
| @@ -1941,23 +2058,23 @@ void ResourceDispatcherHostImpl::CancelRequestsForRoute(int child_id,
|
| return;
|
|
|
| // Now deal with blocked requests if any.
|
| - if (route_id != -1) {
|
| - if (blocked_loaders_map_.find(GlobalRoutingID(child_id, route_id)) !=
|
| + if (!cancel_all_routes) {
|
| + if (blocked_loaders_map_.find(global_routing_id) !=
|
| blocked_loaders_map_.end()) {
|
| - CancelBlockedRequestsForRoute(child_id, route_id);
|
| + CancelBlockedRequestsForRoute(global_routing_id);
|
| }
|
| } else {
|
| - // We have to do all render views for the process |child_id|.
|
| + // We have to do all render frames for the process |child_id|.
|
| // Note that we have to do this in 2 passes as we cannot call
|
| // CancelBlockedRequestsForRoute while iterating over
|
| - // blocked_loaders_map_, as it modifies it.
|
| - std::set<int> route_ids;
|
| + // blocked_loaders_map_, as blocking requests modifies the map.
|
| + std::set<GlobalFrameRoutingId> routing_ids;
|
| for (const auto& blocked_loaders : blocked_loaders_map_) {
|
| if (blocked_loaders.first.child_id == child_id)
|
| - route_ids.insert(blocked_loaders.first.route_id);
|
| + routing_ids.insert(blocked_loaders.first);
|
| }
|
| - for (int route_id : route_ids) {
|
| - CancelBlockedRequestsForRoute(child_id, route_id);
|
| + for (const GlobalFrameRoutingId& route_id : routing_ids) {
|
| + CancelBlockedRequestsForRoute(route_id);
|
| }
|
| }
|
| }
|
| @@ -2304,7 +2421,7 @@ void ResourceDispatcherHostImpl::BeginRequestInternal(
|
| scoped_ptr<ResourceLoader> loader(
|
| new ResourceLoader(std::move(request), std::move(handler), this));
|
|
|
| - GlobalRoutingID id(info->GetGlobalRoutingID());
|
| + GlobalFrameRoutingId id(info->GetChildID(), info->GetRenderFrameID());
|
| BlockedLoadersMap::const_iterator iter = blocked_loaders_map_.find(id);
|
| if (iter != blocked_loaders_map_.end()) {
|
| // The request should be blocked.
|
| @@ -2428,31 +2545,31 @@ void ResourceDispatcherHostImpl::UpdateLoadInfo() {
|
| base::Passed(&info_map)));
|
| }
|
|
|
| -void ResourceDispatcherHostImpl::BlockRequestsForRoute(int child_id,
|
| - int route_id) {
|
| +void ResourceDispatcherHostImpl::BlockRequestsForRoute(
|
| + const GlobalFrameRoutingId& global_routing_id) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - GlobalRoutingID key(child_id, route_id);
|
| - DCHECK(blocked_loaders_map_.find(key) == blocked_loaders_map_.end()) <<
|
| - "BlockRequestsForRoute called multiple time for the same RVH";
|
| - blocked_loaders_map_[key] = make_scoped_ptr(new BlockedLoadersList());
|
| + DCHECK(blocked_loaders_map_.find(global_routing_id) ==
|
| + blocked_loaders_map_.end())
|
| + << "BlockRequestsForRoute called multiple time for the same RFH";
|
| + blocked_loaders_map_[global_routing_id] =
|
| + make_scoped_ptr(new BlockedLoadersList());
|
| }
|
|
|
| -void ResourceDispatcherHostImpl::ResumeBlockedRequestsForRoute(int child_id,
|
| - int route_id) {
|
| - ProcessBlockedRequestsForRoute(child_id, route_id, false);
|
| +void ResourceDispatcherHostImpl::ResumeBlockedRequestsForRoute(
|
| + const GlobalFrameRoutingId& global_routing_id) {
|
| + ProcessBlockedRequestsForRoute(global_routing_id, false);
|
| }
|
|
|
| -void ResourceDispatcherHostImpl::CancelBlockedRequestsForRoute(int child_id,
|
| - int route_id) {
|
| - ProcessBlockedRequestsForRoute(child_id, route_id, true);
|
| +void ResourceDispatcherHostImpl::CancelBlockedRequestsForRoute(
|
| + const GlobalFrameRoutingId& global_routing_id) {
|
| + ProcessBlockedRequestsForRoute(global_routing_id, true);
|
| }
|
|
|
| void ResourceDispatcherHostImpl::ProcessBlockedRequestsForRoute(
|
| - int child_id,
|
| - int route_id,
|
| + const GlobalFrameRoutingId& global_routing_id,
|
| bool cancel_requests) {
|
| - BlockedLoadersMap::iterator iter = blocked_loaders_map_.find(
|
| - GlobalRoutingID(child_id, route_id));
|
| + BlockedLoadersMap::iterator iter =
|
| + blocked_loaders_map_.find(global_routing_id);
|
| if (iter == blocked_loaders_map_.end()) {
|
| // It's possible to reach here if the renderer crashed while an interstitial
|
| // page was showing.
|
|
|