OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 // See http://dev.chromium.org/developers/design-documents/multi-process-resourc e-loading | 5 // See http://dev.chromium.org/developers/design-documents/multi-process-resourc e-loading |
6 | 6 |
7 #include "content/browser/loader/resource_dispatcher_host_impl.h" | 7 #include "content/browser/loader/resource_dispatcher_host_impl.h" |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <set> | 10 #include <set> |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
108 | 108 |
109 // ---------------------------------------------------------------------------- | 109 // ---------------------------------------------------------------------------- |
110 | 110 |
111 namespace content { | 111 namespace content { |
112 | 112 |
113 namespace { | 113 namespace { |
114 | 114 |
115 static ResourceDispatcherHostImpl* g_resource_dispatcher_host; | 115 static ResourceDispatcherHostImpl* g_resource_dispatcher_host; |
116 | 116 |
117 // The interval for calls to ResourceDispatcherHostImpl::UpdateLoadStates | 117 // The interval for calls to ResourceDispatcherHostImpl::UpdateLoadStates |
118 const int kUpdateLoadStatesIntervalMsec = 100; | 118 const int kUpdateLoadStatesIntervalMsec = 250; |
119 | 119 |
120 // Maximum byte "cost" of all the outstanding requests for a renderer. | 120 // Maximum byte "cost" of all the outstanding requests for a renderer. |
121 // See delcaration of |max_outstanding_requests_cost_per_process_| for details. | 121 // See delcaration of |max_outstanding_requests_cost_per_process_| for details. |
122 // This bound is 25MB, which allows for around 6000 outstanding requests. | 122 // This bound is 25MB, which allows for around 6000 outstanding requests. |
123 const int kMaxOutstandingRequestsCostPerProcess = 26214400; | 123 const int kMaxOutstandingRequestsCostPerProcess = 26214400; |
124 | 124 |
125 // The number of milliseconds after noting a user gesture that we will | 125 // The number of milliseconds after noting a user gesture that we will |
126 // tag newly-created URLRequest objects with the | 126 // tag newly-created URLRequest objects with the |
127 // net::LOAD_MAYBE_USER_GESTURE load flag. This is a fairly arbitrary | 127 // net::LOAD_MAYBE_USER_GESTURE load flag. This is a fairly arbitrary |
128 // guess at how long to expect direct impact from a user gesture, but | 128 // guess at how long to expect direct impact from a user gesture, but |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
446 ANNOTATE_BENIGN_RACE( | 446 ANNOTATE_BENIGN_RACE( |
447 &last_user_gesture_time_, | 447 &last_user_gesture_time_, |
448 "We don't care about the precise value, see http://crbug.com/92889"); | 448 "We don't care about the precise value, see http://crbug.com/92889"); |
449 | 449 |
450 BrowserThread::PostTask(BrowserThread::IO, | 450 BrowserThread::PostTask(BrowserThread::IO, |
451 FROM_HERE, | 451 FROM_HERE, |
452 base::Bind(&ResourceDispatcherHostImpl::OnInit, | 452 base::Bind(&ResourceDispatcherHostImpl::OnInit, |
453 base::Unretained(this))); | 453 base::Unretained(this))); |
454 | 454 |
455 update_load_states_timer_.reset( | 455 update_load_states_timer_.reset( |
456 new base::RepeatingTimer<ResourceDispatcherHostImpl>()); | 456 new base::OneShotTimer<ResourceDispatcherHostImpl>()); |
457 } | 457 } |
458 | 458 |
459 ResourceDispatcherHostImpl::~ResourceDispatcherHostImpl() { | 459 ResourceDispatcherHostImpl::~ResourceDispatcherHostImpl() { |
460 DCHECK(outstanding_requests_stats_map_.empty()); | 460 DCHECK(outstanding_requests_stats_map_.empty()); |
461 DCHECK(g_resource_dispatcher_host); | 461 DCHECK(g_resource_dispatcher_host); |
462 g_resource_dispatcher_host = NULL; | 462 g_resource_dispatcher_host = NULL; |
463 } | 463 } |
464 | 464 |
465 // static | 465 // static |
466 ResourceDispatcherHostImpl* ResourceDispatcherHostImpl::Get() { | 466 ResourceDispatcherHostImpl* ResourceDispatcherHostImpl::Get() { |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
781 info->GetContext()->GetRequestContext()->job_factory(); | 781 info->GetContext()->GetRequestContext()->job_factory(); |
782 if (job_factory->IsHandledURL(url)) | 782 if (job_factory->IsHandledURL(url)) |
783 return false; | 783 return false; |
784 | 784 |
785 return delegate_->HandleExternalProtocol( | 785 return delegate_->HandleExternalProtocol( |
786 url, info->GetChildID(), info->GetRouteID(), info->IsMainFrame(), | 786 url, info->GetChildID(), info->GetRouteID(), info->IsMainFrame(), |
787 info->GetPageTransition(), info->HasUserGesture()); | 787 info->GetPageTransition(), info->HasUserGesture()); |
788 } | 788 } |
789 | 789 |
790 void ResourceDispatcherHostImpl::DidStartRequest(ResourceLoader* loader) { | 790 void ResourceDispatcherHostImpl::DidStartRequest(ResourceLoader* loader) { |
791 // Make sure we have the load state monitor running | 791 if (scheduler_->HasLoadingClients()) |
792 if (!update_load_states_timer_->IsRunning()) { | 792 ScheduleUpdateLoadInfo(); |
793 update_load_states_timer_->Start( | |
794 FROM_HERE, TimeDelta::FromMilliseconds(kUpdateLoadStatesIntervalMsec), | |
795 this, &ResourceDispatcherHostImpl::UpdateLoadInfo); | |
796 } | |
797 } | 793 } |
798 | 794 |
799 void ResourceDispatcherHostImpl::DidReceiveRedirect(ResourceLoader* loader, | 795 void ResourceDispatcherHostImpl::DidReceiveRedirect(ResourceLoader* loader, |
800 const GURL& new_url) { | 796 const GURL& new_url) { |
801 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); | 797 ResourceRequestInfoImpl* info = loader->GetRequestInfo(); |
802 | 798 |
803 int render_process_id, render_frame_host; | 799 int render_process_id, render_frame_host; |
804 if (!info->GetAssociatedRenderFrame(&render_process_id, &render_frame_host)) | 800 if (!info->GetAssociatedRenderFrame(&render_process_id, &render_frame_host)) |
805 return; | 801 return; |
806 | 802 |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
933 } | 929 } |
934 | 930 |
935 void ResourceDispatcherHostImpl::OnShutdown() { | 931 void ResourceDispatcherHostImpl::OnShutdown() { |
936 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 932 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
937 | 933 |
938 is_shutdown_ = true; | 934 is_shutdown_ = true; |
939 pending_loaders_.clear(); | 935 pending_loaders_.clear(); |
940 | 936 |
941 // Make sure we shutdown the timer now, otherwise by the time our destructor | 937 // Make sure we shutdown the timer now, otherwise by the time our destructor |
942 // runs if the timer is still running the Task is deleted twice (once by | 938 // runs if the timer is still running the Task is deleted twice (once by |
943 // the MessageLoop and the second time by RepeatingTimer). | 939 // the MessageLoop and the second time by OneShotTimer). |
944 update_load_states_timer_.reset(); | 940 update_load_states_timer_.reset(); |
945 | 941 |
946 // Clear blocked requests if any left. | 942 // Clear blocked requests if any left. |
947 // Note that we have to do this in 2 passes as we cannot call | 943 // Note that we have to do this in 2 passes as we cannot call |
948 // CancelBlockedRequestsForRoute while iterating over | 944 // CancelBlockedRequestsForRoute while iterating over |
949 // blocked_loaders_map_, as it modifies it. | 945 // blocked_loaders_map_, as it modifies it. |
950 std::set<GlobalRoutingID> ids; | 946 std::set<GlobalRoutingID> ids; |
951 for (BlockedLoadersMap::const_iterator iter = blocked_loaders_map_.begin(); | 947 for (BlockedLoadersMap::const_iterator iter = blocked_loaders_map_.begin(); |
952 iter != blocked_loaders_map_.end(); ++iter) { | 948 iter != blocked_loaders_map_.end(); ++iter) { |
953 std::pair<std::set<GlobalRoutingID>::iterator, bool> result = | 949 std::pair<std::set<GlobalRoutingID>::iterator, bool> result = |
(...skipping 820 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1774 | 1770 |
1775 void ResourceDispatcherHostImpl::RemovePendingLoader( | 1771 void ResourceDispatcherHostImpl::RemovePendingLoader( |
1776 const LoaderMap::iterator& iter) { | 1772 const LoaderMap::iterator& iter) { |
1777 ResourceRequestInfoImpl* info = iter->second->GetRequestInfo(); | 1773 ResourceRequestInfoImpl* info = iter->second->GetRequestInfo(); |
1778 | 1774 |
1779 // Remove the memory credit that we added when pushing the request onto | 1775 // Remove the memory credit that we added when pushing the request onto |
1780 // the pending list. | 1776 // the pending list. |
1781 IncrementOutstandingRequestsMemory(-1, *info); | 1777 IncrementOutstandingRequestsMemory(-1, *info); |
1782 | 1778 |
1783 pending_loaders_.erase(iter); | 1779 pending_loaders_.erase(iter); |
1784 | |
1785 // If we have no more pending requests, then stop the load state monitor | |
1786 if (pending_loaders_.empty() && update_load_states_timer_) | |
1787 update_load_states_timer_->Stop(); | |
1788 } | 1780 } |
1789 | 1781 |
1790 void ResourceDispatcherHostImpl::CancelRequest(int child_id, | 1782 void ResourceDispatcherHostImpl::CancelRequest(int child_id, |
1791 int request_id) { | 1783 int request_id) { |
1792 ResourceLoader* loader = GetLoader(child_id, request_id); | 1784 ResourceLoader* loader = GetLoader(child_id, request_id); |
1793 if (!loader) { | 1785 if (!loader) { |
1794 // We probably want to remove this warning eventually, but I wanted to be | 1786 // We probably want to remove this warning eventually, but I wanted to be |
1795 // able to notice when this happens during initial development since it | 1787 // able to notice when this happens during initial development since it |
1796 // should be rare and may indicate a bug. | 1788 // should be rare and may indicate a bug. |
1797 DVLOG(1) << "Canceling a request that wasn't found"; | 1789 DVLOG(1) << "Canceling a request that wasn't found"; |
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2160 FROM_HERE_WITH_EXPLICIT_FUNCTION( | 2152 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
2161 "466285 ResourceDispatcherHostImpl::UpdateLoadInfoOnUIThread")); | 2153 "466285 ResourceDispatcherHostImpl::UpdateLoadInfoOnUIThread")); |
2162 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 2154 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
2163 for (const auto& load_info : *info_map) { | 2155 for (const auto& load_info : *info_map) { |
2164 RenderViewHostImpl* view = RenderViewHostImpl::FromID( | 2156 RenderViewHostImpl* view = RenderViewHostImpl::FromID( |
2165 load_info.first.child_id, load_info.first.route_id); | 2157 load_info.first.child_id, load_info.first.route_id); |
2166 // The view could be gone at this point. | 2158 // The view could be gone at this point. |
2167 if (view) { | 2159 if (view) { |
2168 view->LoadStateChanged(load_info.second.url, load_info.second.load_state, | 2160 view->LoadStateChanged(load_info.second.url, load_info.second.load_state, |
2169 load_info.second.upload_position, | 2161 load_info.second.upload_position, |
2170 load_info.second.upload_size); | 2162 load_info.second.upload_size); |
mmenke
2015/05/21 15:53:25
You should consider updating the GetLoadState() do
Andre
2015/05/21 22:05:39
Done.
| |
2171 } | 2163 } |
2172 } | 2164 } |
2173 } | 2165 } |
2174 | 2166 |
2175 scoped_ptr<ResourceDispatcherHostImpl::LoadInfoMap> | 2167 scoped_ptr<ResourceDispatcherHostImpl::LoadInfoMap> |
2176 ResourceDispatcherHostImpl::GetLoadInfoForAllRoutes() { | 2168 ResourceDispatcherHostImpl::GetLoadInfoForAllRoutes() { |
2177 // Populate this map with load state changes, and then send them on to the UI | 2169 // Populate this map with load state changes, and then send them on to the UI |
2178 // thread where they can be passed along to the respective RVHs. | 2170 // thread where they can be passed along to the respective RVHs. |
2179 scoped_ptr<LoadInfoMap> info_map(new LoadInfoMap()); | 2171 scoped_ptr<LoadInfoMap> info_map(new LoadInfoMap()); |
2180 | 2172 |
2181 for (const auto& loader : pending_loaders_) { | 2173 for (const auto& loader : pending_loaders_) { |
mmenke
2015/05/21 15:53:25
Should actually remove this call in the other CL.
Andre
2015/05/21 22:05:39
Done.
| |
2182 // Also poll for upload progress on this timer and send upload progress ipc | |
2183 // messages to the plugin process. | |
2184 loader.second->ReportUploadProgress(); | |
2185 | |
2186 net::URLRequest* request = loader.second->request(); | 2174 net::URLRequest* request = loader.second->request(); |
2187 net::UploadProgress upload_progress = request->GetUploadProgress(); | 2175 net::UploadProgress upload_progress = request->GetUploadProgress(); |
2188 | 2176 |
2189 LoadInfo load_info; | 2177 LoadInfo load_info; |
2190 load_info.url = request->url(); | 2178 load_info.url = request->url(); |
2191 load_info.load_state = request->GetLoadState(); | 2179 load_info.load_state = request->GetLoadState(); |
2192 load_info.upload_size = upload_progress.size(); | 2180 load_info.upload_size = upload_progress.size(); |
2193 load_info.upload_position = upload_progress.position(); | 2181 load_info.upload_position = upload_progress.position(); |
2194 | 2182 |
2195 GlobalRoutingID id(loader.second->GetRequestInfo()->GetGlobalRoutingID()); | 2183 GlobalRoutingID id(loader.second->GetRequestInfo()->GetGlobalRoutingID()); |
2196 LoadInfoMap::iterator existing = info_map->find(id); | 2184 LoadInfoMap::iterator existing = info_map->find(id); |
2197 | 2185 |
2198 if (existing == info_map->end() || | 2186 if (existing == info_map->end() || |
2199 LoadInfoIsMoreInteresting(load_info, existing->second)) { | 2187 LoadInfoIsMoreInteresting(load_info, existing->second)) { |
2200 (*info_map)[id] = load_info; | 2188 (*info_map)[id] = load_info; |
2201 } | 2189 } |
2202 } | 2190 } |
2203 return info_map.Pass(); | 2191 return info_map.Pass(); |
2204 } | 2192 } |
2205 | 2193 |
2206 void ResourceDispatcherHostImpl::UpdateLoadInfo() { | 2194 void ResourceDispatcherHostImpl::UpdateLoadInfo() { |
2207 scoped_ptr<LoadInfoMap> info_map(GetLoadInfoForAllRoutes()); | 2195 scoped_ptr<LoadInfoMap> info_map(GetLoadInfoForAllRoutes()); |
2208 | 2196 |
2209 if (info_map->empty()) | 2197 if (info_map->empty()) |
2210 return; | 2198 return; |
mmenke
2015/05/21 15:53:25
I think a repeating timer with an explicit Stop()
Andre
2015/05/21 22:05:39
You're right. Now that the upload progress code is
| |
2211 | 2199 |
2212 BrowserThread::PostTask( | 2200 BrowserThread::PostTask( |
2213 BrowserThread::UI, FROM_HERE, | 2201 BrowserThread::UI, FROM_HERE, |
2214 base::Bind(&ResourceDispatcherHostImpl::UpdateLoadInfoOnUIThread, | 2202 base::Bind(&ResourceDispatcherHostImpl::UpdateLoadInfoOnUIThread, |
2215 base::Passed(&info_map))); | 2203 base::Passed(&info_map))); |
2204 | |
2205 if (scheduler_->HasLoadingClients()) | |
2206 ScheduleUpdateLoadInfo(); | |
mmenke
2015/05/21 15:53:25
Should use 2 space indent here, not 3
Andre
2015/05/21 22:05:39
Done.
| |
2216 } | 2207 } |
2217 | 2208 |
2218 void ResourceDispatcherHostImpl::BlockRequestsForRoute(int child_id, | 2209 void ResourceDispatcherHostImpl::BlockRequestsForRoute(int child_id, |
2219 int route_id) { | 2210 int route_id) { |
2220 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 2211 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
2221 GlobalRoutingID key(child_id, route_id); | 2212 GlobalRoutingID key(child_id, route_id); |
2222 DCHECK(blocked_loaders_map_.find(key) == blocked_loaders_map_.end()) << | 2213 DCHECK(blocked_loaders_map_.find(key) == blocked_loaders_map_.end()) << |
2223 "BlockRequestsForRoute called multiple time for the same RVH"; | 2214 "BlockRequestsForRoute called multiple time for the same RVH"; |
2224 blocked_loaders_map_[key] = new BlockedLoadersList(); | 2215 blocked_loaders_map_[key] = new BlockedLoadersList(); |
2225 } | 2216 } |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2368 } | 2359 } |
2369 | 2360 |
2370 // Add a flag to selectively bypass the data reduction proxy if the resource | 2361 // Add a flag to selectively bypass the data reduction proxy if the resource |
2371 // type is not an image. | 2362 // type is not an image. |
2372 if (request_data.resource_type != RESOURCE_TYPE_IMAGE) | 2363 if (request_data.resource_type != RESOURCE_TYPE_IMAGE) |
2373 load_flags |= net::LOAD_BYPASS_DATA_REDUCTION_PROXY; | 2364 load_flags |= net::LOAD_BYPASS_DATA_REDUCTION_PROXY; |
2374 | 2365 |
2375 return load_flags; | 2366 return load_flags; |
2376 } | 2367 } |
2377 | 2368 |
2369 void ResourceDispatcherHostImpl::ScheduleUpdateLoadInfo() { | |
2370 if (!update_load_states_timer_->IsRunning()) { | |
mmenke
2015/05/21 15:53:25
Suggest early return instead - it's generally pref
Andre
2015/05/21 22:05:39
Done.
| |
2371 update_load_states_timer_->Start( | |
2372 FROM_HERE, TimeDelta::FromMilliseconds(kUpdateLoadStatesIntervalMsec), | |
2373 this, &ResourceDispatcherHostImpl::UpdateLoadInfo); | |
2374 } | |
2375 } | |
2376 | |
2378 } // namespace content | 2377 } // namespace content |
OLD | NEW |