| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/renderer/load_progress_tracker.h" |
| |
| #include "base/bind.h" |
| #include "base/message_loop/message_loop.h" |
| #include "content/common/view_messages.h" |
| #include "content/renderer/render_view_impl.h" |
| |
| namespace content { |
| namespace { |
| |
| const int kMinimumDelayBetweenUpdatesMS = 100; |
| |
| } |
| |
| LoadProgressTracker::LoadProgressTracker(RenderViewImpl* render_view) |
| : render_view_(render_view), |
| tracked_frame_(NULL), |
| progress_(0.0), |
| weak_factory_(this) { |
| } |
| |
| LoadProgressTracker::~LoadProgressTracker() { |
| } |
| |
| void LoadProgressTracker::DidStopLoading() { |
| if (!tracked_frame_) |
| return; |
| |
| // Load stopped while we were still tracking load. Make sure we notify the |
| // browser that load is complete. |
| progress_ = 1.0; |
| SendChangeLoadProgress(); |
| // Then we clean-up our states. |
| ResetStates(); |
| } |
| |
| void LoadProgressTracker::DidChangeLoadProgress(WebKit::WebFrame* frame, |
| double progress) { |
| if (tracked_frame_ && frame != tracked_frame_) |
| return; |
| |
| if (!tracked_frame_) |
| tracked_frame_ = frame; |
| |
| progress_ = progress; |
| |
| // We send the progress change to the browser 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(kMinimumDelayBetweenUpdatesMS); |
| if (progress == 1.0 || last_time_progress_sent_.is_null() || |
| base::TimeTicks::Now() - last_time_progress_sent_ > |
| min_delay) { |
| // If there is a pending task to send progress, it is now obsolete. |
| weak_factory_.InvalidateWeakPtrs(); |
| SendChangeLoadProgress(); |
| if (progress == 1.0) |
| ResetStates(); |
| return; |
| } |
| |
| if (weak_factory_.HasWeakPtrs()) |
| return; |
| |
| base::MessageLoop::current()->PostDelayedTask( |
| FROM_HERE, |
| base::Bind(&LoadProgressTracker::SendChangeLoadProgress, |
| weak_factory_.GetWeakPtr()), |
| min_delay); |
| } |
| |
| void LoadProgressTracker::SendChangeLoadProgress() { |
| last_time_progress_sent_ = base::TimeTicks::Now(); |
| render_view_->Send( |
| new ViewHostMsg_DidChangeLoadProgress(render_view_->routing_id(), |
| progress_)); |
| } |
| |
| void LoadProgressTracker::ResetStates() { |
| tracked_frame_ = NULL; |
| progress_ = 0.0; |
| weak_factory_.InvalidateWeakPtrs(); |
| last_time_progress_sent_ = base::TimeTicks(); |
| } |
| |
| } // namespace content |