| 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 da256df980413b76fe334efae34d9216b3394399..a17a812a47340939206faafa18cb90e315fcf6dc 100644
|
| --- a/content/browser/loader/resource_dispatcher_host_impl.cc
|
| +++ b/content/browser/loader/resource_dispatcher_host_impl.cc
|
| @@ -56,7 +56,6 @@
|
| #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"
|
| -#include "content/browser/loader/resource_request_info_impl.h"
|
| #include "content/browser/loader/stream_resource_handler.h"
|
| #include "content/browser/loader/sync_resource_handler.h"
|
| #include "content/browser/loader/throttling_resource_handler.h"
|
| @@ -2446,27 +2445,23 @@ net::URLRequest* ResourceDispatcherHostImpl::GetURLRequest(
|
| return loader->request();
|
| }
|
|
|
| -// static
|
| -bool ResourceDispatcherHostImpl::LoadInfoIsMoreInteresting(const LoadInfo& a,
|
| - const LoadInfo& b) {
|
| - // Set |*_uploading_size| to be the size of the corresponding upload body if
|
| - // it's currently being uploaded.
|
| +ResourceDispatcherHostImpl::LoadInfo::LoadInfo() {}
|
|
|
| - uint64_t a_uploading_size = 0;
|
| - if (a.load_state.state == net::LOAD_STATE_SENDING_REQUEST)
|
| - a_uploading_size = a.upload_size;
|
| +ResourceDispatcherHostImpl::LoadInfo::~LoadInfo() {}
|
|
|
| - uint64_t b_uploading_size = 0;
|
| - if (b.load_state.state == net::LOAD_STATE_SENDING_REQUEST)
|
| - b_uploading_size = b.upload_size;
|
| +ResourceDispatcherHostImpl::LoadInfo::LoadInfo(const LoadInfo& info) = default;
|
|
|
| - if (a_uploading_size != b_uploading_size)
|
| - return a_uploading_size > b_uploading_size;
|
| +bool ResourceDispatcherHostImpl::LoadInfo::IsUploading() const {
|
| + return load_state.state == net::LOAD_STATE_SENDING_REQUEST && upload_size > 0;
|
| +}
|
|
|
| - return a.load_state.state > b.load_state.state;
|
| +bool ResourceDispatcherHostImpl::LoadInfo::IsMoreInteresting(
|
| + const LoadInfo& other) const {
|
| + if (IsUploading())
|
| + return !other.IsUploading() || upload_size > other.upload_size;
|
| + return !other.IsUploading() && load_state.state > other.load_state.state;
|
| }
|
|
|
| -// static
|
| void ResourceDispatcherHostImpl::UpdateLoadInfoOnUIThread(
|
| std::unique_ptr<LoadInfoMap> info_map) {
|
| // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466285
|
| @@ -2475,14 +2470,26 @@ void ResourceDispatcherHostImpl::UpdateLoadInfoOnUIThread(
|
| FROM_HERE_WITH_EXPLICIT_FUNCTION(
|
| "466285 ResourceDispatcherHostImpl::UpdateLoadInfoOnUIThread"));
|
| DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| + std::map<WebContents*, const LoadInfo*> contents_map;
|
| for (const auto& load_info : *info_map) {
|
| - RenderViewHostImpl* view = RenderViewHostImpl::FromID(
|
| - load_info.first.child_id, load_info.first.route_id);
|
| - // The view could be gone at this point.
|
| - if (view) {
|
| - view->LoadStateChanged(load_info.second.url, load_info.second.load_state,
|
| - load_info.second.upload_position,
|
| - load_info.second.upload_size);
|
| + WebContents* web_contents = load_info.second.web_contents_getter.Run();
|
| + if (!web_contents)
|
| + continue;
|
| + auto existing = contents_map.find(web_contents);
|
| + if (existing == contents_map.end() ||
|
| + load_info.second.IsMoreInteresting(*existing->second)) {
|
| + contents_map[web_contents] = &load_info.second;
|
| + }
|
| + }
|
| + for (const auto& it : contents_map) {
|
| + // Re-run the getter to prevent use after free errors if calling
|
| + // LoadStateChanged on one WebContents deletes another one.
|
| + WebContentsImpl* web_contents =
|
| + static_cast<WebContentsImpl*>(it.second->web_contents_getter.Run());
|
| + if (web_contents) {
|
| + web_contents->LoadStateChanged(it.second->url, it.second->load_state,
|
| + it.second->upload_position,
|
| + it.second->upload_size);
|
| }
|
| }
|
| }
|
| @@ -2490,7 +2497,7 @@ void ResourceDispatcherHostImpl::UpdateLoadInfoOnUIThread(
|
| std::unique_ptr<ResourceDispatcherHostImpl::LoadInfoMap>
|
| ResourceDispatcherHostImpl::GetLoadInfoForAllRoutes() {
|
| // Populate this map with load state changes, and then send them on to the UI
|
| - // thread where they can be passed along to the respective RVHs.
|
| + // thread where they can be passed along to the respective WebContents.
|
| std::unique_ptr<LoadInfoMap> info_map(new LoadInfoMap());
|
|
|
| for (const auto& loader : pending_loaders_) {
|
| @@ -2502,12 +2509,26 @@ ResourceDispatcherHostImpl::GetLoadInfoForAllRoutes() {
|
| load_info.load_state = request->GetLoadState();
|
| load_info.upload_size = upload_progress.size();
|
| load_info.upload_position = upload_progress.position();
|
| + load_info.web_contents_getter =
|
| + loader.second->GetRequestInfo()->GetWebContentsGetterForRequest();
|
| +
|
| + ResourceType type = loader.second->GetRequestInfo()->GetResourceType();
|
| + // The WebContents is only really interested in navigation updates. Send
|
| + // those along with requests that are sending data.
|
| + // TODO(csharrison): Consider updating this logic to send separate updates
|
| + // for uploads and navigation requests.
|
| + if (!load_info.IsUploading() &&
|
| + type != ResourceType::RESOURCE_TYPE_MAIN_FRAME &&
|
| + type != ResourceType::RESOURCE_TYPE_SUB_FRAME) {
|
| + continue;
|
| + }
|
|
|
| - GlobalRoutingID id(loader.second->GetRequestInfo()->GetGlobalRoutingID());
|
| + GlobalFrameRoutingId id(
|
| + loader.second->GetRequestInfo()->GetGlobalFrameRoutingId());
|
| LoadInfoMap::iterator existing = info_map->find(id);
|
|
|
| if (existing == info_map->end() ||
|
| - LoadInfoIsMoreInteresting(load_info, existing->second)) {
|
| + load_info.IsMoreInteresting(existing->second)) {
|
| (*info_map)[id] = load_info;
|
| }
|
| }
|
| @@ -2515,6 +2536,8 @@ ResourceDispatcherHostImpl::GetLoadInfoForAllRoutes() {
|
| }
|
|
|
| void ResourceDispatcherHostImpl::UpdateLoadInfo() {
|
| + // Group LoadInfo by frame, then pass to the UI thread where each WebContents
|
| + // picks the most interesting one.
|
| std::unique_ptr<LoadInfoMap> info_map(GetLoadInfoForAllRoutes());
|
|
|
| // Stop the timer if there are no more pending requests. Future new requests
|
|
|