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