Index: content/browser/web_contents/web_contents_impl.cc |
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc |
index d47a6ef362c8157626ee30e86106e2604b0cfb80..a83ec56e45ef6a8ecf6b936e52df9d40dc44fdb5 100644 |
--- a/content/browser/web_contents/web_contents_impl.cc |
+++ b/content/browser/web_contents/web_contents_impl.cc |
@@ -121,11 +121,6 @@ namespace content { |
namespace { |
const int kMinimumDelayBetweenLoadingUpdatesMS = 100; |
- |
-// This matches what Blink's ProgressTracker has traditionally used for a |
-// minimum progress value. |
-const double kMinimumLoadingProgress = 0.1; |
- |
const char kDotGoogleDotCom[] = ".google.com"; |
#if defined(OS_ANDROID) |
@@ -166,6 +161,40 @@ bool CollectSites(BrowserContext* context, |
return true; |
} |
+// Helper function used with FrameTree::ForEach() for retrieving the total |
+// loading progress and number of frames in a frame tree. |
+bool CollectLoadProgress(double* progress, |
+ int* frame_count, |
+ FrameTreeNode* node) { |
+ // Ignore the current frame if it has not started loading. |
+ double frame_progress = node->GetLoadingProgress(); |
+ if (frame_progress == RenderFrameHostImpl::kLoadingProgressNotStarted) |
+ return true; |
+ |
+ // Collect progress. |
+ *progress += node->GetLoadingProgress(); |
+ (*frame_count)++; |
+ return true; |
+} |
+ |
+// Helper function used with FrameTree::ForEach() to check if at least one of |
+// the nodes is loading. |
+bool IsNodeLoading(bool* is_loading, FrameTreeNode* node) { |
+ if (node->IsLoading()) { |
+ // There is at least one node loading, so abort traversal. |
+ *is_loading = true; |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+// Helper function used with FrameTree::ForEach() to reset the load progress. |
+bool ResetLoadProgress(FrameTreeNode* node) { |
+ node->current_frame_host()->set_loading_progress( |
+ RenderFrameHostImpl::kLoadingProgressNotStarted); |
+ return true; |
+} |
+ |
bool ForEachFrameInternal( |
const base::Callback<void(RenderFrameHost*)>& on_frame, |
FrameTreeNode* node) { |
@@ -227,6 +256,13 @@ bool SuddenTerminationAllowed(bool* sudden_termination_allowed, |
return false; |
} |
+// Returns true if at least one of the nodes in the |frame_tree| is loading. |
+bool IsFrameTreeLoading(FrameTree& frame_tree) { |
+ bool is_loading = false; |
+ frame_tree.ForEach(base::Bind(&IsNodeLoading, &is_loading)); |
+ return is_loading; |
+} |
+ |
} // namespace |
WebContents* WebContents::Create(const WebContents::CreateParams& params) { |
@@ -336,7 +372,6 @@ WebContentsImpl::WebContentsImpl(BrowserContext* browser_context, |
waiting_for_response_(false), |
load_state_(net::LOAD_STATE_IDLE, base::string16()), |
loading_total_progress_(0.0), |
- loading_frames_in_progress_(0), |
upload_size_(0), |
upload_position_(0), |
displayed_insecure_content_(false), |
@@ -2864,42 +2899,26 @@ void WebContentsImpl::OnDidStartLoading(bool to_different_document) { |
RenderFrameHostImpl* rfh = |
static_cast<RenderFrameHostImpl*>(render_frame_message_source_); |
- int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id(); |
// Any main frame load to a new document should reset the load progress, since |
// it will replace the current page and any frames. |
if (to_different_document && !rfh->GetParent()) { |
ResetLoadProgressState(); |
- loading_frames_in_progress_ = 0; |
- rfh->frame_tree_node()->set_is_loading(false); |
+ rfh->set_is_loading(false); |
} |
- // It is possible to get multiple calls to OnDidStartLoading that don't have |
- // corresponding calls to OnDidStopLoading: |
- // - With "swappedout://" URLs, this happens when a RenderView gets swapped |
- // out for a cross-process navigation, and it turns into a placeholder for |
- // one being rendered in a different process. |
- // - Also, there might be more than one RenderFrameHost sharing the same |
- // FrameTreeNode (and thus sharing its ID) each sending a start. |
- // - But in the future, once clamy@ moves navigation network requests to the |
- // browser process, there's a good chance that callbacks about starting and |
- // stopping will all be handled by the browser. When that happens, there |
- // should no longer be a start/stop call imbalance. TODO(avi): When this |
- // future arrives, update this code to not allow this case. |
- if (rfh->frame_tree_node()->is_loading()) |
- return; |
+ // This method should never be called when the frame is loading. |
+ DCHECK(!rfh->is_loading()); |
- DCHECK_GE(loading_frames_in_progress_, 0); |
- if (loading_frames_in_progress_ == 0) |
+ if (!IsFrameTreeLoading(frame_tree_)) |
DidStartLoading(rfh, to_different_document); |
- ++loading_frames_in_progress_; |
- rfh->frame_tree_node()->set_is_loading(true); |
+ rfh->set_is_loading(true); |
+ rfh->set_loading_progress(RenderFrameHostImpl::kLoadingProgressMinimum); |
// Notify the RenderFrameHostManager of the event. |
rfh->frame_tree_node()->render_manager()->OnDidStartLoading(); |
- loading_progresses_[render_frame_id] = kMinimumLoadingProgress; |
SendLoadProgressChanged(); |
} |
@@ -2909,28 +2928,23 @@ void WebContentsImpl::OnDidStopLoading() { |
RenderFrameHostImpl* rfh = |
static_cast<RenderFrameHostImpl*>(render_frame_message_source_); |
- int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id(); |
- rfh->frame_tree_node()->set_is_loading(false); |
- if (loading_progresses_.find(render_frame_id) != loading_progresses_.end()) { |
- // Load stopped while we were still tracking load. Make sure we update |
- // progress based on this frame's completion. |
- loading_progresses_[render_frame_id] = 1.0; |
- SendLoadProgressChanged(); |
- // Then we clean-up our states. |
- if (loading_total_progress_ == 1.0) |
- ResetLoadProgressState(); |
- } |
+ // This method should never be called when the frame is not loading. |
+ DCHECK(rfh->is_loading()); |
+ rfh->set_is_loading(false); |
+ rfh->set_loading_progress(RenderFrameHostImpl::kLoadingProgressDone); |
+ |
+ // Update progress based on this frame's completion. |
+ SendLoadProgressChanged(); |
+ |
+ // Then clean-up the states. |
+ if (loading_total_progress_ == 1.0) |
+ ResetLoadProgressState(); |
// Notify the RenderFrameHostManager of the event. |
rfh->frame_tree_node()->render_manager()->OnDidStopLoading(); |
- // TODO(japhet): This should be a DCHECK, but the pdf plugin sometimes |
- // calls DidStopLoading() without a matching DidStartLoading(). |
- if (loading_frames_in_progress_ == 0) |
- return; |
- --loading_frames_in_progress_; |
- if (loading_frames_in_progress_ == 0) |
+ if (!IsFrameTreeLoading(frame_tree_)) |
DidStopLoading(rfh); |
} |
@@ -2940,9 +2954,8 @@ void WebContentsImpl::OnDidChangeLoadProgress(double load_progress) { |
RenderFrameHostImpl* rfh = |
static_cast<RenderFrameHostImpl*>(render_frame_message_source_); |
- int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id(); |
- loading_progresses_[render_frame_id] = load_progress; |
+ rfh->set_loading_progress(load_progress); |
// We notify progress change immediately for the first and last updates. |
// Also, since the message loop may be pretty busy when a page is loaded, it |
@@ -3420,16 +3433,11 @@ void WebContentsImpl::SendLoadProgressChanged() { |
double progress = 0.0; |
int frame_count = 0; |
- for (LoadingProgressMap::iterator it = loading_progresses_.begin(); |
- it != loading_progresses_.end(); |
- ++it) { |
- progress += it->second; |
- ++frame_count; |
- } |
- if (frame_count == 0) |
- return; |
- progress /= frame_count; |
- DCHECK(progress <= 1.0); |
+ frame_tree_.ForEach( |
+ base::Bind(&CollectLoadProgress, &progress, &frame_count)); |
+ if (frame_count != 0) |
+ progress /= frame_count; |
+ DCHECK_LE(progress, 1.0); |
if (progress <= loading_total_progress_) |
return; |
@@ -3440,7 +3448,7 @@ void WebContentsImpl::SendLoadProgressChanged() { |
} |
void WebContentsImpl::ResetLoadProgressState() { |
- loading_progresses_.clear(); |
+ frame_tree_.ForEach(base::Bind(&ResetLoadProgress)); |
loading_total_progress_ = 0.0; |
loading_weak_factory_.InvalidateWeakPtrs(); |
loading_last_progress_update_ = base::TimeTicks(); |
@@ -3745,7 +3753,6 @@ void WebContentsImpl::RenderViewTerminated(RenderViewHost* rvh, |
// webpage? Once this function is called at a more granular frame level, we |
// probably will need to more granularly reset the state here. |
ResetLoadProgressState(); |
- loading_frames_in_progress_ = 0; |
FOR_EACH_OBSERVER(WebContentsObserver, |
observers_, |