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; |