OLD | NEW |
| (Empty) |
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 // This matches what blink's ProgrssTracker has traditionally used for a | |
18 // minimum progress value. | |
19 const double kMinimumProgress = 0.1; | |
20 | |
21 } | |
22 | |
23 LoadProgressTracker::LoadProgressTracker(RenderViewImpl* render_view) | |
24 : render_view_(render_view), | |
25 total_progress_(0.0), | |
26 weak_factory_(this) { | |
27 } | |
28 | |
29 LoadProgressTracker::~LoadProgressTracker() { | |
30 } | |
31 | |
32 void LoadProgressTracker::DidStartLoading(int frame_routing_id) { | |
33 progresses_[frame_routing_id] = kMinimumProgress; | |
34 SendChangeLoadProgress(); | |
35 } | |
36 | |
37 void LoadProgressTracker::DidStopLoading(int frame_routing_id) { | |
38 if (progresses_.find(frame_routing_id) == progresses_.end()) | |
39 return; | |
40 | |
41 // Load stopped while we were still tracking load. Make sure we update | |
42 // progress based on this frame's completion. | |
43 progresses_[frame_routing_id] = 1.0; | |
44 SendChangeLoadProgress(); | |
45 // Then we clean-up our states. | |
46 if (total_progress_ == 1.0) | |
47 ResetStates(); | |
48 } | |
49 | |
50 void LoadProgressTracker::DidChangeLoadProgress(int frame_routing_id, | |
51 double progress) { | |
52 progresses_[frame_routing_id] = progress; | |
53 | |
54 // We send the progress change to the browser immediately for the first and | |
55 // last updates. Also, since the message loop may be pretty busy when a page | |
56 // is loaded, it might not execute a posted task in a timely manner so we make | |
57 // sure to immediately send progress report if enough time has passed. | |
58 base::TimeDelta min_delay = | |
59 base::TimeDelta::FromMilliseconds(kMinimumDelayBetweenUpdatesMS); | |
60 if (progress == 1.0 || last_time_progress_sent_.is_null() || | |
61 base::TimeTicks::Now() - last_time_progress_sent_ > min_delay) { | |
62 // If there is a pending task to send progress, it is now obsolete. | |
63 weak_factory_.InvalidateWeakPtrs(); | |
64 SendChangeLoadProgress(); | |
65 if (total_progress_ == 1.0) | |
66 ResetStates(); | |
67 return; | |
68 } | |
69 | |
70 if (weak_factory_.HasWeakPtrs()) | |
71 return; | |
72 | |
73 base::MessageLoop::current()->PostDelayedTask( | |
74 FROM_HERE, | |
75 base::Bind(&LoadProgressTracker::SendChangeLoadProgress, | |
76 weak_factory_.GetWeakPtr()), | |
77 min_delay); | |
78 } | |
79 | |
80 void LoadProgressTracker::SendChangeLoadProgress() { | |
81 last_time_progress_sent_ = base::TimeTicks::Now(); | |
82 double progress = 0.0; | |
83 unsigned frameCount = 0; | |
84 ProgressMap::iterator end = progresses_.end(); | |
85 for (ProgressMap::iterator it = progresses_.begin(); it != end; ++it) { | |
86 progress += it->second; | |
87 frameCount++; | |
88 } | |
89 if (frameCount == 0) | |
90 return; | |
91 progress /= frameCount; | |
92 DCHECK(progress <= 1.0); | |
93 | |
94 if (progress <= total_progress_) | |
95 return; | |
96 total_progress_ = progress; | |
97 | |
98 render_view_->Send( | |
99 new ViewHostMsg_DidChangeLoadProgress(render_view_->routing_id(), | |
100 progress)); | |
101 } | |
102 | |
103 void LoadProgressTracker::ResetStates() { | |
104 progresses_.clear(); | |
105 total_progress_ = 0.0; | |
106 weak_factory_.InvalidateWeakPtrs(); | |
107 last_time_progress_sent_ = base::TimeTicks(); | |
108 } | |
109 | |
110 } // namespace content | |
OLD | NEW |