summaryrefslogtreecommitdiffstats
path: root/chrome/browser/sessions/tab_loader.h
blob: d21bd7766111c29e916a0d376d3cc4daba08c6d7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// Copyright 2015 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.

#ifndef CHROME_BROWSER_SESSIONS_TAB_LOADER_H_
#define CHROME_BROWSER_SESSIONS_TAB_LOADER_H_

#include <list>
#include <set>

#include "base/memory/memory_pressure_listener.h"
#include "base/memory/scoped_ptr.h"
#include "base/timer/timer.h"
#include "chrome/browser/sessions/session_restore_delegate.h"
#include "chrome/browser/sessions/tab_loader_delegate.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"

namespace content {
class NavigationController;
class RenderWidgetHost;
}

class SessionRestoreStatsCollector;

// TabLoader is responsible for loading tabs after session restore has finished
// creating all the tabs. Tabs are loaded after a previously tab finishes
// loading or a timeout is reached. If the timeout is reached before a tab
// finishes loading the timeout delay is doubled.
//
// TabLoader keeps a reference to itself when it's loading. When it has finished
// loading, it drops the reference. If another profile is restored while the
// TabLoader is loading, it will schedule its tabs to get loaded by the same
// TabLoader. When doing the scheduling, it holds a reference to the TabLoader.
//
// This is not part of SessionRestoreImpl so that synchronous destruction
// of SessionRestoreImpl doesn't have timing problems.
class TabLoader : public content::NotificationObserver,
                  public base::RefCounted<TabLoader>,
                  public TabLoaderCallback {
 public:
  using RestoredTab = SessionRestoreDelegate::RestoredTab;

  // NotificationObserver method. Removes the specified tab and loads the next
  // tab.
  void Observe(int type,
               const content::NotificationSource& source,
               const content::NotificationDetails& details) override;

  // TabLoaderCallback:
  void SetTabLoadingEnabled(bool enable_tab_loading) override;

  // Called to start restoring tabs.
  static void RestoreTabs(const std::vector<RestoredTab>& tabs_,
                          const base::TimeTicks& restore_started);

 private:
  friend class base::RefCounted<TabLoader>;

  using TabsLoading = std::set<content::NavigationController*>;
  using TabsToLoad = std::list<content::NavigationController*>;

  explicit TabLoader(base::TimeTicks restore_started);
  ~TabLoader() override;

  // This is invoked once by RestoreTabs to start loading.
  void StartLoading(const std::vector<RestoredTab>& tabs);

  // Loads the next tab. If there are no more tabs to load this deletes itself,
  // otherwise |force_load_timer_| is restarted.
  void LoadNextTab();

  // Starts |force_load_timer_| to load the first non-visible tab if the timer
  // expires before a visible tab has finished loading. This uses the same
  // timer but a different timeout value than StartTimer.
  void StartFirstTimer();

  // Starts |force_load_timer_| to load the next tab if the timer expires
  // before the current tab loading is finished. This uses the same timer but a
  // different timeout value than StartFirstTimer.
  void StartTimer();

  // Removes the listeners from the specified tab and removes the tab from
  // the set of tabs to load and list of tabs we're waiting to get a load
  // from.
  void RemoveTab(content::NavigationController* controller);

  // Invoked from |force_load_timer_|. Doubles |force_load_delay_multiplier_|
  // and invokes |LoadNextTab| to load the next tab
  void ForceLoadTimerFired();

  // Returns the RenderWidgetHost associated with a tab if there is one,
  // NULL otherwise.
  static content::RenderWidgetHost* GetRenderWidgetHost(
      content::NavigationController* controller);

  // Register for necessary notifications on a tab navigation controller.
  void RegisterForNotifications(content::NavigationController* controller);

  // Called when a tab goes away or a load completes.
  void HandleTabClosedOrLoaded(content::NavigationController* controller);

  // Convenience function returning the current memory pressure level.
  base::MemoryPressureListener::MemoryPressureLevel
      CurrentMemoryPressureLevel();

  // React to memory pressure by stopping to load any more tabs.
  void OnMemoryPressure(
      base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);

  scoped_ptr<TabLoaderDelegate> delegate_;

  // Listens for system under memory pressure notifications and stops loading
  // of tabs when we start running out of memory.
  base::MemoryPressureListener memory_pressure_listener_;

  content::NotificationRegistrar registrar_;

  // The delay timer multiplier. See class description for details.
  size_t force_load_delay_multiplier_;

  // True if the tab loading is enabled.
  bool loading_enabled_;

  // The set of tabs we've initiated loading on. This does NOT include the
  // selected tabs.
  TabsLoading tabs_loading_;

  // The tabs we need to load.
  TabsToLoad tabs_to_load_;

  base::OneShotTimer<TabLoader> force_load_timer_;

  // The time the restore process started.
  base::TimeTicks restore_started_;

  // For keeping TabLoader alive while it's loading even if no
  // SessionRestoreImpls reference it.
  scoped_refptr<TabLoader> this_retainer_;

  // The SessionRestoreStatsCollector associated with this TabLoader. This is
  // explicitly referenced so that it can be notified of deferred tab loads due
  // to memory pressure.
  scoped_refptr<SessionRestoreStatsCollector> stats_collector_;

  static TabLoader* shared_tab_loader_;

  DISALLOW_COPY_AND_ASSIGN(TabLoader);
};

#endif  // CHROME_BROWSER_SESSIONS_TAB_LOADER_H_