Home | History | Annotate | Download | only in renderer
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/renderer/load_progress_tracker.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "content/common/view_messages.h"
     10 #include "content/renderer/render_view_impl.h"
     11 
     12 namespace content {
     13 namespace {
     14 
     15 const int kMinimumDelayBetweenUpdatesMS = 100;
     16 
     17 }
     18 
     19 LoadProgressTracker::LoadProgressTracker(RenderViewImpl* render_view)
     20     : render_view_(render_view),
     21       tracked_frame_(NULL),
     22       progress_(0.0),
     23       weak_factory_(this) {
     24 }
     25 
     26 LoadProgressTracker::~LoadProgressTracker() {
     27 }
     28 
     29 void LoadProgressTracker::DidStopLoading() {
     30   if (!tracked_frame_)
     31     return;
     32 
     33   // Load stopped while we were still tracking load.  Make sure we notify the
     34   // browser that load is complete.
     35   progress_ = 1.0;
     36   SendChangeLoadProgress();
     37   // Then we clean-up our states.
     38   ResetStates();
     39 }
     40 
     41 void LoadProgressTracker::DidChangeLoadProgress(blink::WebFrame* frame,
     42                                                 double progress) {
     43   if (tracked_frame_ && frame != tracked_frame_)
     44     return;
     45 
     46   if (!tracked_frame_)
     47     tracked_frame_ = frame;
     48 
     49   progress_ = progress;
     50 
     51   // We send the progress change to the browser immediately for the first and
     52   // last updates.  Also, since the message loop may be pretty busy when a page
     53   // is loaded, it might not execute a posted task in a timely manner so we make
     54   // sure to immediately send progress report if enough time has passed.
     55   base::TimeDelta min_delay =
     56       base::TimeDelta::FromMilliseconds(kMinimumDelayBetweenUpdatesMS);
     57   if (progress == 1.0 || last_time_progress_sent_.is_null() ||
     58       base::TimeTicks::Now() - last_time_progress_sent_ >
     59       min_delay) {
     60     // If there is a pending task to send progress, it is now obsolete.
     61     weak_factory_.InvalidateWeakPtrs();
     62     SendChangeLoadProgress();
     63     if (progress == 1.0)
     64       ResetStates();
     65     return;
     66   }
     67 
     68   if (weak_factory_.HasWeakPtrs())
     69     return;
     70 
     71   base::MessageLoop::current()->PostDelayedTask(
     72       FROM_HERE,
     73       base::Bind(&LoadProgressTracker::SendChangeLoadProgress,
     74                  weak_factory_.GetWeakPtr()),
     75       min_delay);
     76 }
     77 
     78 void LoadProgressTracker::SendChangeLoadProgress() {
     79   last_time_progress_sent_ = base::TimeTicks::Now();
     80   render_view_->Send(
     81       new ViewHostMsg_DidChangeLoadProgress(render_view_->routing_id(),
     82                                             progress_));
     83 }
     84 
     85 void LoadProgressTracker::ResetStates() {
     86   tracked_frame_ = NULL;
     87   progress_ = 0.0;
     88   weak_factory_.InvalidateWeakPtrs();
     89   last_time_progress_sent_ = base::TimeTicks();
     90 }
     91 
     92 }  // namespace content
     93