OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/sessions/session_restore.h" | 5 #include "chrome/browser/sessions/session_restore.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <list> | 8 #include <list> |
9 #include <set> | 9 #include <set> |
10 #include <vector> | 10 #include <vector> |
(...skipping 24 matching lines...) Expand all Loading... |
35 #include "content/browser/tab_contents/tab_contents_view.h" | 35 #include "content/browser/tab_contents/tab_contents_view.h" |
36 #include "content/public/browser/navigation_controller.h" | 36 #include "content/public/browser/navigation_controller.h" |
37 #include "content/public/browser/notification_registrar.h" | 37 #include "content/public/browser/notification_registrar.h" |
38 #include "content/public/browser/notification_service.h" | 38 #include "content/public/browser/notification_service.h" |
39 #include "net/base/network_change_notifier.h" | 39 #include "net/base/network_change_notifier.h" |
40 | 40 |
41 #if defined(OS_CHROMEOS) | 41 #if defined(OS_CHROMEOS) |
42 #include "chrome/browser/chromeos/boot_times_loader.h" | 42 #include "chrome/browser/chromeos/boot_times_loader.h" |
43 #endif | 43 #endif |
44 | 44 |
| 45 using content::NavigationController; |
45 using content::WebContents; | 46 using content::WebContents; |
46 | 47 |
47 // Are we in the process of restoring? | 48 // Are we in the process of restoring? |
48 static bool restoring = false; | 49 static bool restoring = false; |
49 | 50 |
50 namespace { | 51 namespace { |
51 | 52 |
52 // TabLoader ------------------------------------------------------------------ | 53 // TabLoader ------------------------------------------------------------------ |
53 | 54 |
54 // Initial delay (see class decription for details). | 55 // Initial delay (see class decription for details). |
55 static const int kInitialDelayTimerMS = 100; | 56 static const int kInitialDelayTimerMS = 100; |
56 | 57 |
57 // TabLoader is responsible for loading tabs after session restore creates | 58 // TabLoader is responsible for loading tabs after session restore creates |
58 // tabs. New tabs are loaded after the current tab finishes loading, or a delay | 59 // tabs. New tabs are loaded after the current tab finishes loading, or a delay |
59 // is reached (initially kInitialDelayTimerMS). If the delay is reached before | 60 // is reached (initially kInitialDelayTimerMS). If the delay is reached before |
60 // a tab finishes loading a new tab is loaded and the time of the delay | 61 // a tab finishes loading a new tab is loaded and the time of the delay |
61 // doubled. When all tabs are loading TabLoader deletes itself. | 62 // doubled. When all tabs are loading TabLoader deletes itself. |
62 // | 63 // |
63 // This is not part of SessionRestoreImpl so that synchronous destruction | 64 // This is not part of SessionRestoreImpl so that synchronous destruction |
64 // of SessionRestoreImpl doesn't have timing problems. | 65 // of SessionRestoreImpl doesn't have timing problems. |
65 class TabLoader : public content::NotificationObserver, | 66 class TabLoader : public content::NotificationObserver, |
66 public net::NetworkChangeNotifier::OnlineStateObserver { | 67 public net::NetworkChangeNotifier::OnlineStateObserver { |
67 public: | 68 public: |
68 explicit TabLoader(base::TimeTicks restore_started); | 69 explicit TabLoader(base::TimeTicks restore_started); |
69 virtual ~TabLoader(); | 70 virtual ~TabLoader(); |
70 | 71 |
71 // Schedules a tab for loading. | 72 // Schedules a tab for loading. |
72 void ScheduleLoad(content::NavigationController* controller); | 73 void ScheduleLoad(NavigationController* controller); |
73 | 74 |
74 // Notifies the loader that a tab has been scheduled for loading through | 75 // Notifies the loader that a tab has been scheduled for loading through |
75 // some other mechanism. | 76 // some other mechanism. |
76 void TabIsLoading(content::NavigationController* controller); | 77 void TabIsLoading(NavigationController* controller); |
77 | 78 |
78 // Invokes |LoadNextTab| to load a tab. | 79 // Invokes |LoadNextTab| to load a tab. |
79 // | 80 // |
80 // This must be invoked once to start loading. | 81 // This must be invoked once to start loading. |
81 void StartLoading(); | 82 void StartLoading(); |
82 | 83 |
83 private: | 84 private: |
84 typedef std::set<content::NavigationController*> TabsLoading; | 85 typedef std::set<NavigationController*> TabsLoading; |
85 typedef std::list<content::NavigationController*> TabsToLoad; | 86 typedef std::list<NavigationController*> TabsToLoad; |
86 typedef std::set<RenderWidgetHost*> RenderWidgetHostSet; | 87 typedef std::set<RenderWidgetHost*> RenderWidgetHostSet; |
87 | 88 |
88 // Loads the next tab. If there are no more tabs to load this deletes itself, | 89 // Loads the next tab. If there are no more tabs to load this deletes itself, |
89 // otherwise |force_load_timer_| is restarted. | 90 // otherwise |force_load_timer_| is restarted. |
90 void LoadNextTab(); | 91 void LoadNextTab(); |
91 | 92 |
92 // NotificationObserver method. Removes the specified tab and loads the next | 93 // NotificationObserver method. Removes the specified tab and loads the next |
93 // tab. | 94 // tab. |
94 virtual void Observe(int type, | 95 virtual void Observe(int type, |
95 const content::NotificationSource& source, | 96 const content::NotificationSource& source, |
96 const content::NotificationDetails& details) OVERRIDE; | 97 const content::NotificationDetails& details) OVERRIDE; |
97 | 98 |
98 // net::NetworkChangeNotifier::OnlineStateObserver overrides. | 99 // net::NetworkChangeNotifier::OnlineStateObserver overrides. |
99 virtual void OnOnlineStateChanged(bool online) OVERRIDE; | 100 virtual void OnOnlineStateChanged(bool online) OVERRIDE; |
100 | 101 |
101 // Removes the listeners from the specified tab and removes the tab from | 102 // Removes the listeners from the specified tab and removes the tab from |
102 // the set of tabs to load and list of tabs we're waiting to get a load | 103 // the set of tabs to load and list of tabs we're waiting to get a load |
103 // from. | 104 // from. |
104 void RemoveTab(content::NavigationController* tab); | 105 void RemoveTab(NavigationController* tab); |
105 | 106 |
106 // Invoked from |force_load_timer_|. Doubles |force_load_delay_| and invokes | 107 // Invoked from |force_load_timer_|. Doubles |force_load_delay_| and invokes |
107 // |LoadNextTab| to load the next tab | 108 // |LoadNextTab| to load the next tab |
108 void ForceLoadTimerFired(); | 109 void ForceLoadTimerFired(); |
109 | 110 |
110 // Returns the RenderWidgetHost associated with a tab if there is one, | 111 // Returns the RenderWidgetHost associated with a tab if there is one, |
111 // NULL otherwise. | 112 // NULL otherwise. |
112 static RenderWidgetHost* GetRenderWidgetHost( | 113 static RenderWidgetHost* GetRenderWidgetHost(NavigationController* tab); |
113 content::NavigationController* tab); | |
114 | 114 |
115 // Register for necessary notificaitons on a tab navigation controller. | 115 // Register for necessary notificaitons on a tab navigation controller. |
116 void RegisterForNotifications(content::NavigationController* controller); | 116 void RegisterForNotifications(NavigationController* controller); |
117 | 117 |
118 // Called when a tab goes away or a load completes. | 118 // Called when a tab goes away or a load completes. |
119 void HandleTabClosedOrLoaded(content::NavigationController* controller); | 119 void HandleTabClosedOrLoaded(NavigationController* controller); |
120 | 120 |
121 content::NotificationRegistrar registrar_; | 121 content::NotificationRegistrar registrar_; |
122 | 122 |
123 // Current delay before a new tab is loaded. See class description for | 123 // Current delay before a new tab is loaded. See class description for |
124 // details. | 124 // details. |
125 int64 force_load_delay_; | 125 int64 force_load_delay_; |
126 | 126 |
127 // Has Load been invoked? | 127 // Has Load been invoked? |
128 bool loading_; | 128 bool loading_; |
129 | 129 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 tab_count_(0), | 161 tab_count_(0), |
162 restore_started_(restore_started) { | 162 restore_started_(restore_started) { |
163 } | 163 } |
164 | 164 |
165 TabLoader::~TabLoader() { | 165 TabLoader::~TabLoader() { |
166 DCHECK((got_first_paint_ || render_widget_hosts_to_paint_.empty()) && | 166 DCHECK((got_first_paint_ || render_widget_hosts_to_paint_.empty()) && |
167 tabs_loading_.empty() && tabs_to_load_.empty()); | 167 tabs_loading_.empty() && tabs_to_load_.empty()); |
168 net::NetworkChangeNotifier::RemoveOnlineStateObserver(this); | 168 net::NetworkChangeNotifier::RemoveOnlineStateObserver(this); |
169 } | 169 } |
170 | 170 |
171 void TabLoader::ScheduleLoad(content::NavigationController* controller) { | 171 void TabLoader::ScheduleLoad(NavigationController* controller) { |
172 DCHECK(controller); | 172 DCHECK(controller); |
173 DCHECK(find(tabs_to_load_.begin(), tabs_to_load_.end(), controller) == | 173 DCHECK(find(tabs_to_load_.begin(), tabs_to_load_.end(), controller) == |
174 tabs_to_load_.end()); | 174 tabs_to_load_.end()); |
175 tabs_to_load_.push_back(controller); | 175 tabs_to_load_.push_back(controller); |
176 RegisterForNotifications(controller); | 176 RegisterForNotifications(controller); |
177 } | 177 } |
178 | 178 |
179 void TabLoader::TabIsLoading(content::NavigationController* controller) { | 179 void TabLoader::TabIsLoading(NavigationController* controller) { |
180 DCHECK(controller); | 180 DCHECK(controller); |
181 DCHECK(find(tabs_loading_.begin(), tabs_loading_.end(), controller) == | 181 DCHECK(find(tabs_loading_.begin(), tabs_loading_.end(), controller) == |
182 tabs_loading_.end()); | 182 tabs_loading_.end()); |
183 tabs_loading_.insert(controller); | 183 tabs_loading_.insert(controller); |
184 RenderWidgetHost* render_widget_host = GetRenderWidgetHost(controller); | 184 RenderWidgetHost* render_widget_host = GetRenderWidgetHost(controller); |
185 DCHECK(render_widget_host); | 185 DCHECK(render_widget_host); |
186 render_widget_hosts_loading_.insert(render_widget_host); | 186 render_widget_hosts_loading_.insert(render_widget_host); |
187 RegisterForNotifications(controller); | 187 RegisterForNotifications(controller); |
188 } | 188 } |
189 | 189 |
190 void TabLoader::StartLoading() { | 190 void TabLoader::StartLoading() { |
191 registrar_.Add(this, content::NOTIFICATION_RENDER_WIDGET_HOST_DID_PAINT, | 191 registrar_.Add(this, content::NOTIFICATION_RENDER_WIDGET_HOST_DID_PAINT, |
192 content::NotificationService::AllSources()); | 192 content::NotificationService::AllSources()); |
193 #if defined(OS_CHROMEOS) | 193 #if defined(OS_CHROMEOS) |
194 if (!net::NetworkChangeNotifier::IsOffline()) { | 194 if (!net::NetworkChangeNotifier::IsOffline()) { |
195 loading_ = true; | 195 loading_ = true; |
196 LoadNextTab(); | 196 LoadNextTab(); |
197 } else { | 197 } else { |
198 net::NetworkChangeNotifier::AddOnlineStateObserver(this); | 198 net::NetworkChangeNotifier::AddOnlineStateObserver(this); |
199 } | 199 } |
200 #else | 200 #else |
201 loading_ = true; | 201 loading_ = true; |
202 LoadNextTab(); | 202 LoadNextTab(); |
203 #endif | 203 #endif |
204 } | 204 } |
205 | 205 |
206 void TabLoader::LoadNextTab() { | 206 void TabLoader::LoadNextTab() { |
207 if (!tabs_to_load_.empty()) { | 207 if (!tabs_to_load_.empty()) { |
208 content::NavigationController* tab = tabs_to_load_.front(); | 208 NavigationController* tab = tabs_to_load_.front(); |
209 DCHECK(tab); | 209 DCHECK(tab); |
210 tabs_loading_.insert(tab); | 210 tabs_loading_.insert(tab); |
211 tabs_to_load_.pop_front(); | 211 tabs_to_load_.pop_front(); |
212 tab->LoadIfNecessary(); | 212 tab->LoadIfNecessary(); |
213 if (tab->GetWebContents()) { | 213 if (tab->GetWebContents()) { |
214 int tab_index; | 214 int tab_index; |
215 Browser* browser = Browser::GetBrowserForController(tab, &tab_index); | 215 Browser* browser = Browser::GetBrowserForController(tab, &tab_index); |
216 if (browser && browser->active_index() != tab_index) { | 216 if (browser && browser->active_index() != tab_index) { |
217 // By default tabs are marked as visible. As only the active tab is | 217 // By default tabs are marked as visible. As only the active tab is |
218 // visible we need to explicitly tell non-active tabs they are hidden. | 218 // visible we need to explicitly tell non-active tabs they are hidden. |
(...skipping 18 matching lines...) Expand all Loading... |
237 } | 237 } |
238 | 238 |
239 void TabLoader::Observe(int type, | 239 void TabLoader::Observe(int type, |
240 const content::NotificationSource& source, | 240 const content::NotificationSource& source, |
241 const content::NotificationDetails& details) { | 241 const content::NotificationDetails& details) { |
242 switch (type) { | 242 switch (type) { |
243 case content::NOTIFICATION_LOAD_START: { | 243 case content::NOTIFICATION_LOAD_START: { |
244 // Add this render_widget_host to the set of those we're waiting for | 244 // Add this render_widget_host to the set of those we're waiting for |
245 // paints on. We want to only record stats for paints that occur after | 245 // paints on. We want to only record stats for paints that occur after |
246 // a load has finished. | 246 // a load has finished. |
247 content::NavigationController* tab = | 247 NavigationController* tab = |
248 content::Source<content::NavigationController>(source).ptr(); | 248 content::Source<NavigationController>(source).ptr(); |
249 RenderWidgetHost* render_widget_host = GetRenderWidgetHost(tab); | 249 RenderWidgetHost* render_widget_host = GetRenderWidgetHost(tab); |
250 DCHECK(render_widget_host); | 250 DCHECK(render_widget_host); |
251 render_widget_hosts_loading_.insert(render_widget_host); | 251 render_widget_hosts_loading_.insert(render_widget_host); |
252 break; | 252 break; |
253 } | 253 } |
254 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { | 254 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { |
255 WebContents* web_contents = content::Source<WebContents>(source).ptr(); | 255 WebContents* web_contents = content::Source<WebContents>(source).ptr(); |
256 if (!got_first_paint_) { | 256 if (!got_first_paint_) { |
257 RenderWidgetHost* render_widget_host = | 257 RenderWidgetHost* render_widget_host = |
258 GetRenderWidgetHost(&web_contents->GetController()); | 258 GetRenderWidgetHost(&web_contents->GetController()); |
259 render_widget_hosts_loading_.erase(render_widget_host); | 259 render_widget_hosts_loading_.erase(render_widget_host); |
260 } | 260 } |
261 HandleTabClosedOrLoaded(&web_contents->GetController()); | 261 HandleTabClosedOrLoaded(&web_contents->GetController()); |
262 break; | 262 break; |
263 } | 263 } |
264 case content::NOTIFICATION_LOAD_STOP: { | 264 case content::NOTIFICATION_LOAD_STOP: { |
265 content::NavigationController* tab = | 265 NavigationController* tab = |
266 content::Source<content::NavigationController>(source).ptr(); | 266 content::Source<NavigationController>(source).ptr(); |
267 render_widget_hosts_to_paint_.insert(GetRenderWidgetHost(tab)); | 267 render_widget_hosts_to_paint_.insert(GetRenderWidgetHost(tab)); |
268 HandleTabClosedOrLoaded(tab); | 268 HandleTabClosedOrLoaded(tab); |
269 break; | 269 break; |
270 } | 270 } |
271 case content::NOTIFICATION_RENDER_WIDGET_HOST_DID_PAINT: { | 271 case content::NOTIFICATION_RENDER_WIDGET_HOST_DID_PAINT: { |
272 if (!got_first_paint_) { | 272 if (!got_first_paint_) { |
273 RenderWidgetHost* render_widget_host = | 273 RenderWidgetHost* render_widget_host = |
274 content::Source<RenderWidgetHost>(source).ptr(); | 274 content::Source<RenderWidgetHost>(source).ptr(); |
275 if (render_widget_hosts_to_paint_.find(render_widget_host) != | 275 if (render_widget_hosts_to_paint_.find(render_widget_host) != |
276 render_widget_hosts_to_paint_.end()) { | 276 render_widget_hosts_to_paint_.end()) { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 if (online) { | 321 if (online) { |
322 if (!loading_) { | 322 if (!loading_) { |
323 loading_ = true; | 323 loading_ = true; |
324 LoadNextTab(); | 324 LoadNextTab(); |
325 } | 325 } |
326 } else { | 326 } else { |
327 loading_ = false; | 327 loading_ = false; |
328 } | 328 } |
329 } | 329 } |
330 | 330 |
331 void TabLoader::RemoveTab(content::NavigationController* tab) { | 331 void TabLoader::RemoveTab(NavigationController* tab) { |
332 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 332 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
333 content::Source<WebContents>(tab->GetWebContents())); | 333 content::Source<WebContents>(tab->GetWebContents())); |
334 registrar_.Remove(this, content::NOTIFICATION_LOAD_STOP, | 334 registrar_.Remove(this, content::NOTIFICATION_LOAD_STOP, |
335 content::Source<content::NavigationController>(tab)); | 335 content::Source<NavigationController>(tab)); |
336 registrar_.Remove(this, content::NOTIFICATION_LOAD_START, | 336 registrar_.Remove(this, content::NOTIFICATION_LOAD_START, |
337 content::Source<content::NavigationController>(tab)); | 337 content::Source<NavigationController>(tab)); |
338 | 338 |
339 TabsLoading::iterator i = tabs_loading_.find(tab); | 339 TabsLoading::iterator i = tabs_loading_.find(tab); |
340 if (i != tabs_loading_.end()) | 340 if (i != tabs_loading_.end()) |
341 tabs_loading_.erase(i); | 341 tabs_loading_.erase(i); |
342 | 342 |
343 TabsToLoad::iterator j = | 343 TabsToLoad::iterator j = |
344 find(tabs_to_load_.begin(), tabs_to_load_.end(), tab); | 344 find(tabs_to_load_.begin(), tabs_to_load_.end(), tab); |
345 if (j != tabs_to_load_.end()) | 345 if (j != tabs_to_load_.end()) |
346 tabs_to_load_.erase(j); | 346 tabs_to_load_.erase(j); |
347 } | 347 } |
348 | 348 |
349 void TabLoader::ForceLoadTimerFired() { | 349 void TabLoader::ForceLoadTimerFired() { |
350 force_load_delay_ *= 2; | 350 force_load_delay_ *= 2; |
351 LoadNextTab(); | 351 LoadNextTab(); |
352 } | 352 } |
353 | 353 |
354 RenderWidgetHost* TabLoader::GetRenderWidgetHost( | 354 RenderWidgetHost* TabLoader::GetRenderWidgetHost(NavigationController* tab) { |
355 content::NavigationController* tab) { | |
356 WebContents* web_contents = tab->GetWebContents(); | 355 WebContents* web_contents = tab->GetWebContents(); |
357 if (web_contents) { | 356 if (web_contents) { |
358 RenderWidgetHostView* render_widget_host_view = | 357 RenderWidgetHostView* render_widget_host_view = |
359 web_contents->GetRenderWidgetHostView(); | 358 web_contents->GetRenderWidgetHostView(); |
360 if (render_widget_host_view) | 359 if (render_widget_host_view) |
361 return render_widget_host_view->GetRenderWidgetHost(); | 360 return render_widget_host_view->GetRenderWidgetHost(); |
362 } | 361 } |
363 return NULL; | 362 return NULL; |
364 } | 363 } |
365 | 364 |
366 void TabLoader::RegisterForNotifications( | 365 void TabLoader::RegisterForNotifications(NavigationController* controller) { |
367 content::NavigationController* controller) { | |
368 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 366 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
369 content::Source<WebContents>(controller->GetWebContents())); | 367 content::Source<WebContents>(controller->GetWebContents())); |
370 registrar_.Add(this, content::NOTIFICATION_LOAD_STOP, | 368 registrar_.Add(this, content::NOTIFICATION_LOAD_STOP, |
371 content::Source<content::NavigationController>(controller)); | 369 content::Source<NavigationController>(controller)); |
372 registrar_.Add(this, content::NOTIFICATION_LOAD_START, | 370 registrar_.Add(this, content::NOTIFICATION_LOAD_START, |
373 content::Source<content::NavigationController>(controller)); | 371 content::Source<NavigationController>(controller)); |
374 ++tab_count_; | 372 ++tab_count_; |
375 } | 373 } |
376 | 374 |
377 void TabLoader::HandleTabClosedOrLoaded(content::NavigationController* tab) { | 375 void TabLoader::HandleTabClosedOrLoaded(NavigationController* tab) { |
378 RemoveTab(tab); | 376 RemoveTab(tab); |
379 if (loading_) | 377 if (loading_) |
380 LoadNextTab(); | 378 LoadNextTab(); |
381 if (tabs_loading_.empty() && tabs_to_load_.empty()) { | 379 if (tabs_loading_.empty() && tabs_to_load_.empty()) { |
382 base::TimeDelta time_to_load = | 380 base::TimeDelta time_to_load = |
383 base::TimeTicks::Now() - restore_started_; | 381 base::TimeTicks::Now() - restore_started_; |
384 UMA_HISTOGRAM_CUSTOM_TIMES( | 382 UMA_HISTOGRAM_CUSTOM_TIMES( |
385 "SessionRestore.AllTabsLoaded", | 383 "SessionRestore.AllTabsLoaded", |
386 time_to_load, | 384 time_to_load, |
387 base::TimeDelta::FromMilliseconds(10), | 385 base::TimeDelta::FromMilliseconds(10), |
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
902 std::vector<GURL> gurls; | 900 std::vector<GURL> gurls; |
903 SessionRestoreImpl restorer(profile, | 901 SessionRestoreImpl restorer(profile, |
904 static_cast<Browser*>(NULL), true, false, true, gurls); | 902 static_cast<Browser*>(NULL), true, false, true, gurls); |
905 restorer.RestoreForeignTab(tab); | 903 restorer.RestoreForeignTab(tab); |
906 } | 904 } |
907 | 905 |
908 // static | 906 // static |
909 bool SessionRestore::IsRestoring() { | 907 bool SessionRestore::IsRestoring() { |
910 return restoring; | 908 return restoring; |
911 } | 909 } |
OLD | NEW |