Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(333)

Side by Side Diff: chrome/browser/sessions/tab_loader.cc

Issue 2370753002: Make TabLoader a client of memory coordinator (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/sessions/tab_loader.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/tab_loader.h" 5 #include "chrome/browser/sessions/tab_loader.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 9
10 #include "base/memory/memory_coordinator_client_registry.h"
10 #include "base/memory/memory_pressure_monitor.h" 11 #include "base/memory/memory_pressure_monitor.h"
11 #include "base/memory/ptr_util.h" 12 #include "base/memory/ptr_util.h"
12 #include "base/metrics/histogram_macros.h" 13 #include "base/metrics/histogram_macros.h"
13 #include "base/strings/stringprintf.h" 14 #include "base/strings/stringprintf.h"
14 #include "build/build_config.h" 15 #include "build/build_config.h"
15 #include "chrome/browser/sessions/session_restore_stats_collector.h" 16 #include "chrome/browser/sessions/session_restore_stats_collector.h"
16 #include "chrome/browser/ui/browser.h" 17 #include "chrome/browser/ui/browser.h"
17 #include "chrome/browser/ui/browser_finder.h" 18 #include "chrome/browser/ui/browser_finder.h"
18 #include "chrome/browser/ui/tabs/tab_strip_model.h" 19 #include "chrome/browser/ui/tabs/tab_strip_model.h"
19 #include "components/favicon/content/content_favicon_driver.h" 20 #include "components/favicon/content/content_favicon_driver.h"
20 #include "components/variations/variations_associated_data.h" 21 #include "components/variations/variations_associated_data.h"
21 #include "content/public/browser/navigation_controller.h" 22 #include "content/public/browser/navigation_controller.h"
22 #include "content/public/browser/notification_service.h" 23 #include "content/public/browser/notification_service.h"
23 #include "content/public/browser/notification_types.h" 24 #include "content/public/browser/notification_types.h"
24 #include "content/public/browser/render_widget_host.h" 25 #include "content/public/browser/render_widget_host.h"
25 #include "content/public/browser/render_widget_host_view.h" 26 #include "content/public/browser/render_widget_host_view.h"
26 #include "content/public/browser/web_contents.h" 27 #include "content/public/browser/web_contents.h"
28 #include "content/public/common/content_features.h"
27 29
28 using content::NavigationController; 30 using content::NavigationController;
29 using content::RenderWidgetHost; 31 using content::RenderWidgetHost;
30 using content::WebContents; 32 using content::WebContents;
31 33
32 void TabLoader::Observe(int type, 34 void TabLoader::Observe(int type,
33 const content::NotificationSource& source, 35 const content::NotificationSource& source,
34 const content::NotificationDetails& details) { 36 const content::NotificationDetails& details) {
35 switch (type) { 37 switch (type) {
36 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { 38 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
72 if (!shared_tab_loader_) 74 if (!shared_tab_loader_)
73 shared_tab_loader_ = new TabLoader(restore_started); 75 shared_tab_loader_ = new TabLoader(restore_started);
74 76
75 shared_tab_loader_->stats_collector_->TrackTabs(tabs); 77 shared_tab_loader_->stats_collector_->TrackTabs(tabs);
76 shared_tab_loader_->StartLoading(tabs); 78 shared_tab_loader_->StartLoading(tabs);
77 } 79 }
78 80
79 TabLoader::TabLoader(base::TimeTicks restore_started) 81 TabLoader::TabLoader(base::TimeTicks restore_started)
80 : memory_pressure_listener_( 82 : memory_pressure_listener_(
81 base::Bind(&TabLoader::OnMemoryPressure, base::Unretained(this))), 83 base::Bind(&TabLoader::OnMemoryPressure, base::Unretained(this))),
84 memory_state_(base::MemoryState::NORMAL),
sky 2016/09/26 16:41:57 Should this be initialized to the real value? By t
hajimehoshi 2016/09/27 05:59:16 chrisha@: IIUC the initial value should always be
bashi 2016/09/29 06:30:52 Yes. Current plan is that the initial state is NOR
82 force_load_delay_multiplier_(1), 85 force_load_delay_multiplier_(1),
83 loading_enabled_(true), 86 loading_enabled_(true),
84 restore_started_(restore_started) { 87 restore_started_(restore_started) {
85 stats_collector_ = new SessionRestoreStatsCollector( 88 stats_collector_ = new SessionRestoreStatsCollector(
86 restore_started, 89 restore_started,
87 base::MakeUnique< 90 base::MakeUnique<
88 SessionRestoreStatsCollector::UmaStatsReportingDelegate>()); 91 SessionRestoreStatsCollector::UmaStatsReportingDelegate>());
89 shared_tab_loader_ = this; 92 shared_tab_loader_ = this;
90 this_retainer_ = this; 93 this_retainer_ = this;
94 base::MemoryCoordinatorClientRegistry::GetInstance()->Register(this);
91 } 95 }
92 96
93 TabLoader::~TabLoader() { 97 TabLoader::~TabLoader() {
94 DCHECK(tabs_loading_.empty() && tabs_to_load_.empty()); 98 DCHECK(tabs_loading_.empty() && tabs_to_load_.empty());
95 DCHECK(shared_tab_loader_ == this); 99 DCHECK(shared_tab_loader_ == this);
96 shared_tab_loader_ = nullptr; 100 shared_tab_loader_ = nullptr;
101 base::MemoryCoordinatorClientRegistry::GetInstance()->Unregister(this);
97 } 102 }
98 103
99 void TabLoader::StartLoading(const std::vector<RestoredTab>& tabs) { 104 void TabLoader::StartLoading(const std::vector<RestoredTab>& tabs) {
100 // Add the tabs to the list of tabs loading/to load and register them for 105 // Add the tabs to the list of tabs loading/to load and register them for
101 // notifications. Also, restore the favicons of the background tabs (the title 106 // notifications. Also, restore the favicons of the background tabs (the title
102 // has already been set by now).This avoids having blank icons in case the 107 // has already been set by now).This avoids having blank icons in case the
103 // restore is halted due to memory pressure. Also, when multiple tabs are 108 // restore is halted due to memory pressure. Also, when multiple tabs are
104 // restored to a single window, the title may not appear, and the user will 109 // restored to a single window, the title may not appear, and the user will
105 // have no way of finding out which tabs corresponds to which page if the icon 110 // have no way of finding out which tabs corresponds to which page if the icon
106 // is a generic grey one. 111 // is a generic grey one.
(...skipping 17 matching lines...) Expand all
124 if (delegate_) 129 if (delegate_)
125 return; 130 return;
126 131
127 // Create a TabLoaderDelegate which will allow OS specific behavior for tab 132 // Create a TabLoaderDelegate which will allow OS specific behavior for tab
128 // loading. 133 // loading.
129 if (!delegate_) { 134 if (!delegate_) {
130 delegate_ = TabLoaderDelegate::Create(this); 135 delegate_ = TabLoaderDelegate::Create(this);
131 // There is already at least one tab loading (the active tab). As such we 136 // There is already at least one tab loading (the active tab). As such we
132 // only have to start the timeout timer here. But, don't restore background 137 // only have to start the timeout timer here. But, don't restore background
133 // tabs if the system is under memory pressure. 138 // tabs if the system is under memory pressure.
134 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level = 139 if (ShouldPurgeMemory()) {
135 CurrentMemoryPressureLevel(); 140 PurgeMemory();
136
137 if (memory_pressure_level !=
138 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE) {
139 OnMemoryPressure(memory_pressure_level);
140 return; 141 return;
141 } 142 }
142 143
143 StartFirstTimer(); 144 StartFirstTimer();
144 } 145 }
145 } 146 }
146 147
147 void TabLoader::LoadNextTab() { 148 void TabLoader::LoadNextTab() {
148 // LoadNextTab should only get called after we have started the tab 149 // LoadNextTab should only get called after we have started the tab
149 // loading. 150 // loading.
150 CHECK(delegate_); 151 CHECK(delegate_);
151 152
152 // Abort if loading is not enabled. 153 // Abort if loading is not enabled.
153 if (!loading_enabled_) 154 if (!loading_enabled_)
154 return; 155 return;
155 156
156 if (!tabs_to_load_.empty()) { 157 if (!tabs_to_load_.empty()) {
157 // Check the memory pressure before restoring the next tab, and abort if 158 // Check the memory pressure before restoring the next tab, and abort if
158 // there is pressure. This is important on the Mac because of the sometimes 159 // there is pressure. This is important on the Mac because of the sometimes
159 // large delay between a memory pressure event and receiving a notification 160 // large delay between a memory pressure event and receiving a notification
160 // of that event (in that case tab restore can trigger memory pressure but 161 // of that event (in that case tab restore can trigger memory pressure but
161 // will complete before the notification arrives). 162 // will complete before the notification arrives).
162 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level = 163 if (ShouldPurgeMemory()) {
163 CurrentMemoryPressureLevel(); 164 PurgeMemory();
164 if (memory_pressure_level !=
165 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE) {
166 OnMemoryPressure(memory_pressure_level);
167 return; 165 return;
168 } 166 }
169 167
170 NavigationController* controller = tabs_to_load_.front(); 168 NavigationController* controller = tabs_to_load_.front();
171 DCHECK(controller); 169 DCHECK(controller);
172 tabs_loading_.insert(controller); 170 tabs_loading_.insert(controller);
173 tabs_to_load_.pop_front(); 171 tabs_to_load_.pop_front();
174 controller->LoadIfNecessary(); 172 controller->LoadIfNecessary();
175 content::WebContents* contents = controller->GetWebContents(); 173 content::WebContents* contents = controller->GetWebContents();
176 if (contents) { 174 if (contents) {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 registrar_.Add(this, content::NOTIFICATION_LOAD_STOP, 233 registrar_.Add(this, content::NOTIFICATION_LOAD_STOP,
236 content::Source<NavigationController>(controller)); 234 content::Source<NavigationController>(controller));
237 } 235 }
238 236
239 void TabLoader::HandleTabClosedOrLoaded(NavigationController* controller) { 237 void TabLoader::HandleTabClosedOrLoaded(NavigationController* controller) {
240 RemoveTab(controller); 238 RemoveTab(controller);
241 if (delegate_) 239 if (delegate_)
242 LoadNextTab(); 240 LoadNextTab();
243 } 241 }
244 242
245 base::MemoryPressureListener::MemoryPressureLevel 243 bool TabLoader::ShouldPurgeMemory() const {
246 TabLoader::CurrentMemoryPressureLevel() { 244 if (base::FeatureList::IsEnabled(features::kMemoryCoordinator)) {
sky 2016/09/26 16:41:57 no {}
hajimehoshi 2016/09/27 05:59:15 Done.
247 if (base::MemoryPressureMonitor::Get()) 245 return memory_state_ != base::MemoryState::NORMAL;
248 return base::MemoryPressureMonitor::Get()->GetCurrentPressureLevel(); 246 }
249 247 if (base::MemoryPressureMonitor::Get()) {
250 return base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE; 248 return base::MemoryPressureMonitor::Get()->GetCurrentPressureLevel() !=
249 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE;
250 }
251 return false;
251 } 252 }
252 253
253 void TabLoader::OnMemoryPressure( 254 void TabLoader::OnMemoryPressure(
254 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { 255 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
256 PurgeMemory();
257 }
258
259 void TabLoader::OnMemoryStateChange(base::MemoryState state) {
260 memory_state_ = state;
261 switch (state) {
262 case base::MemoryState::NORMAL:
263 break;
264 case base::MemoryState::THROTTLED:
265 PurgeMemory();
266 break;
267 case base::MemoryState::SUSPENDED:
268 // Note that SUSPENDED never occurs in the main browser process so far.
269 // Fall through.
270 case base::MemoryState::UNKNOWN:
271 NOTREACHED();
272 break;
273 }
274 }
275
276 void TabLoader::PurgeMemory() {
chrisha 2016/09/26 14:18:53 PurgeMemory isn't the best name here, as it's not
sky 2016/09/26 16:41:57 SGTM
hajimehoshi 2016/09/27 05:59:16 Done.
255 // When receiving a resource pressure level warning, we stop pre-loading more 277 // When receiving a resource pressure level warning, we stop pre-loading more
256 // tabs since we are running in danger of loading more tabs by throwing out 278 // tabs since we are running in danger of loading more tabs by throwing out
257 // old ones. 279 // old ones.
258 if (tabs_to_load_.empty()) 280 if (tabs_to_load_.empty())
259 return; 281 return;
260 // Stop the timer and suppress any tab loads while we clean the list. 282 // Stop the timer and suppress any tab loads while we clean the list.
261 SetTabLoadingEnabled(false); 283 SetTabLoadingEnabled(false);
262 while (!tabs_to_load_.empty()) { 284 while (!tabs_to_load_.empty()) {
263 NavigationController* tab = tabs_to_load_.front(); 285 NavigationController* tab = tabs_to_load_.front();
264 tabs_to_load_.pop_front(); 286 tabs_to_load_.pop_front();
265 RemoveTab(tab); 287 RemoveTab(tab);
266 288
267 // Notify the stats collector that a tab's loading has been deferred due to 289 // Notify the stats collector that a tab's loading has been deferred due to
268 // memory pressure. 290 // memory pressure.
269 stats_collector_->DeferTab(tab); 291 stats_collector_->DeferTab(tab);
270 } 292 }
271 // By calling |LoadNextTab| explicitly, we make sure that the 293 // By calling |LoadNextTab| explicitly, we make sure that the
272 // |NOTIFICATION_SESSION_RESTORE_DONE| event gets sent. 294 // |NOTIFICATION_SESSION_RESTORE_DONE| event gets sent.
273 LoadNextTab(); 295 LoadNextTab();
274 } 296 }
275 297
276 // static 298 // static
277 TabLoader* TabLoader::shared_tab_loader_ = nullptr; 299 TabLoader* TabLoader::shared_tab_loader_ = nullptr;
OLDNEW
« no previous file with comments | « chrome/browser/sessions/tab_loader.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698