Chromium Code Reviews| 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 08b4da90632f4172e3b296c674525ac3b568a2ab..0d85eacba57a1be2b56eb5b42e647d55f81d6620 100644 |
| --- a/content/browser/web_contents/web_contents_impl.cc |
| +++ b/content/browser/web_contents/web_contents_impl.cc |
| @@ -161,6 +161,12 @@ |
| 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) |
| @@ -332,6 +338,9 @@ WebContentsImpl::WebContentsImpl( |
| crashed_error_code_(0), |
| waiting_for_response_(false), |
| load_state_(net::LOAD_STATE_IDLE, base::string16()), |
| + loading_total_progress_(0.0), |
| + loading_weak_factory_(this), |
| + loading_frames_in_progress_(0), |
| upload_size_(0), |
| upload_position_(0), |
| displayed_insecure_content_(false), |
| @@ -510,6 +519,10 @@ bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host, |
| IPC_MESSAGE_HANDLER(FrameHostMsg_DidFinishDocumentLoad, |
| OnDocumentLoadedInFrame) |
| IPC_MESSAGE_HANDLER(FrameHostMsg_DidFinishLoad, OnDidFinishLoad) |
| + IPC_MESSAGE_HANDLER(FrameHostMsg_DidStartLoading, OnDidStartLoading) |
| + IPC_MESSAGE_HANDLER(FrameHostMsg_DidStopLoading, OnDidStopLoading) |
| + IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeLoadProgress, |
| + OnDidChangeLoadProgress) |
| IPC_MESSAGE_HANDLER(FrameHostMsg_OpenColorChooser, OnOpenColorChooser) |
| IPC_MESSAGE_HANDLER(FrameHostMsg_EndColorChooser, OnEndColorChooser) |
| IPC_MESSAGE_HANDLER(FrameHostMsg_SetSelectedColorInColorChooser, |
| @@ -2326,8 +2339,6 @@ void WebContentsImpl::DidStartProvisionalLoad( |
| bool is_error_page, |
| bool is_iframe_srcdoc) { |
| bool is_main_frame = render_frame_host->frame_tree_node()->IsMainFrame(); |
| - if (is_main_frame) |
|
nasko
2014/05/05 23:51:12
Why did you remove this call?
Avi (use Gerrit)
2014/05/06 00:03:39
By the time DidStartProvisionalLoad is called, the
|
| - DidChangeLoadProgress(0); |
| // Notify observers about the start of the provisional load. |
| int render_frame_id = render_frame_host->GetRoutingID(); |
| @@ -2632,6 +2643,77 @@ void WebContentsImpl::OnDidFinishLoad( |
| is_main_frame, render_view_host)); |
| } |
| +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(); |
| + |
| + DCHECK_GE(loading_frames_in_progress_, 0); |
| + if (loading_frames_in_progress_ == 0) |
| + DidStartLoading(rfh, to_different_document); |
| + ++loading_frames_in_progress_; |
| + |
| + loading_progresses_[render_frame_id] = kMinimumLoadingProgress; |
| + SendLoadProgressChanged(); |
| +} |
| + |
| +void WebContentsImpl::OnDidStopLoading() { |
| + RenderFrameHostImpl* rfh = |
| + static_cast<RenderFrameHostImpl*>(render_frame_message_source_); |
| + int64 render_frame_id = rfh->frame_tree_node()->frame_tree_node_id(); |
| + |
| + 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(); |
| + } |
| + |
| + // 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) |
| + DidStopLoading(rfh); |
| +} |
| + |
| +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; |
| + |
| + // 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 |
| + // might not execute a posted task in a timely manner so we make sure to |
| + // immediately send progress report if enough time has passed. |
| + base::TimeDelta min_delay = |
| + base::TimeDelta::FromMilliseconds(kMinimumDelayBetweenLoadingUpdatesMS); |
| + if (load_progress == 1.0 || loading_last_progress_update_.is_null() || |
| + base::TimeTicks::Now() - loading_last_progress_update_ > min_delay) { |
| + // If there is a pending task to send progress, it is now obsolete. |
| + loading_weak_factory_.InvalidateWeakPtrs(); |
| + SendLoadProgressChanged(); |
| + if (loading_total_progress_ == 1.0) |
| + ResetLoadProgressState(); |
| + return; |
| + } |
| + |
| + if (loading_weak_factory_.HasWeakPtrs()) |
| + return; |
| + |
| + base::MessageLoop::current()->PostDelayedTask( |
| + FROM_HERE, |
| + base::Bind(&WebContentsImpl::SendLoadProgressChanged, |
| + loading_weak_factory_.GetWeakPtr()), |
| + min_delay); |
| +} |
| + |
| void WebContentsImpl::OnGoToEntryAtOffset(int offset) { |
| if (!delegate_ || delegate_->OnGoToEntryOffset(offset)) |
| controller_.GoToOffset(offset); |
| @@ -3023,6 +3105,37 @@ bool WebContentsImpl::UpdateTitleForEntry(NavigationEntryImpl* entry, |
| return true; |
| } |
| +void WebContentsImpl::SendLoadProgressChanged() { |
| + loading_last_progress_update_ = base::TimeTicks::Now(); |
| + 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); |
| + |
| + if (progress <= loading_total_progress_) |
| + return; |
| + loading_total_progress_ = progress; |
| + |
| + if (delegate_) |
| + delegate_->LoadProgressChanged(this, progress); |
| +} |
| + |
| +void WebContentsImpl::ResetLoadProgressState() { |
| + loading_progresses_.clear(); |
| + loading_total_progress_ = 0.0; |
| + loading_weak_factory_.InvalidateWeakPtrs(); |
| + loading_last_progress_update_ = base::TimeTicks(); |
| +} |
| + |
| void WebContentsImpl::NotifySwapped(RenderViewHost* old_host, |
| RenderViewHost* new_host) { |
| // After sending out a swap notification, we need to send a disconnect |
| @@ -3456,11 +3569,6 @@ void WebContentsImpl::DidCancelLoading() { |
| NotifyNavigationStateChanged(INVALIDATE_TYPE_URL); |
| } |
| -void WebContentsImpl::DidChangeLoadProgress(double progress) { |
| - if (delegate_) |
| - delegate_->LoadProgressChanged(this, progress); |
| -} |
| - |
| void WebContentsImpl::DidAccessInitialDocument() { |
| has_accessed_initial_document_ = true; |