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

Side by Side Diff: content/browser/memory/memory_coordinator_impl.cc

Issue 2718963002: Drop the global memory state from memory coordinator (Closed)
Patch Set: comments Created 3 years, 9 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
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 "content/browser/memory/memory_coordinator_impl.h" 5 #include "content/browser/memory/memory_coordinator_impl.h"
6 6
7 #include "base/memory/memory_coordinator_client_registry.h" 7 #include "base/memory/memory_coordinator_client_registry.h"
8 #include "base/memory/ptr_util.h" 8 #include "base/memory/ptr_util.h"
9 #include "base/metrics/histogram_macros.h" 9 #include "base/metrics/histogram_macros.h"
10 #include "base/process/process_handle.h" 10 #include "base/process/process_handle.h"
11 #include "base/threading/thread_task_runner_handle.h" 11 #include "base/threading/thread_task_runner_handle.h"
12 #include "base/trace_event/trace_event.h" 12 #include "base/trace_event/trace_event.h"
13 #include "content/browser/memory/memory_condition_observer.h"
13 #include "content/browser/memory/memory_monitor.h" 14 #include "content/browser/memory/memory_monitor.h"
14 #include "content/browser/memory/memory_state_updater.h"
15 #include "content/public/browser/content_browser_client.h" 15 #include "content/public/browser/content_browser_client.h"
16 #include "content/public/browser/notification_service.h" 16 #include "content/public/browser/notification_service.h"
17 #include "content/public/browser/notification_types.h" 17 #include "content/public/browser/notification_types.h"
18 #include "content/public/browser/render_process_host.h" 18 #include "content/public/browser/render_process_host.h"
19 #include "content/public/browser/render_widget_host.h" 19 #include "content/public/browser/render_widget_host.h"
20 #include "content/public/common/content_features.h" 20 #include "content/public/common/content_features.h"
21 #include "mojo/public/cpp/bindings/binding.h" 21 #include "mojo/public/cpp/bindings/binding.h"
22 22
23 namespace content { 23 namespace content {
24 24
25 using MemoryState = base::MemoryState;
26
25 namespace { 27 namespace {
26 28
27 mojom::MemoryState ToMojomMemoryState(base::MemoryState state) { 29 const int kDefaultMinimumTransitionPeriodSeconds = 30;
30
31 mojom::MemoryState ToMojomMemoryState(MemoryState state) {
28 switch (state) { 32 switch (state) {
29 case base::MemoryState::UNKNOWN: 33 case MemoryState::UNKNOWN:
30 return mojom::MemoryState::UNKNOWN; 34 return mojom::MemoryState::UNKNOWN;
31 case base::MemoryState::NORMAL: 35 case MemoryState::NORMAL:
32 return mojom::MemoryState::NORMAL; 36 return mojom::MemoryState::NORMAL;
33 case base::MemoryState::THROTTLED: 37 case MemoryState::THROTTLED:
34 return mojom::MemoryState::THROTTLED; 38 return mojom::MemoryState::THROTTLED;
35 case base::MemoryState::SUSPENDED: 39 case MemoryState::SUSPENDED:
36 return mojom::MemoryState::SUSPENDED; 40 return mojom::MemoryState::SUSPENDED;
37 default: 41 default:
38 NOTREACHED(); 42 NOTREACHED();
39 return mojom::MemoryState::UNKNOWN; 43 return mojom::MemoryState::UNKNOWN;
40 } 44 }
41 } 45 }
42 46
47 const char* MemoryConditionToString(MemoryCondition condition) {
48 switch (condition) {
49 case MemoryCondition::NORMAL:
50 return "normal";
51 case MemoryCondition::WARNING:
52 return "warning";
53 case MemoryCondition::CRITICAL:
54 return "critical";
55 }
56 NOTREACHED();
57 return "N/A";
58 }
59
43 } // namespace 60 } // namespace
44 61
45 // The implementation of MemoryCoordinatorHandle. See memory_coordinator.mojom 62 // The implementation of MemoryCoordinatorHandle. See memory_coordinator.mojom
46 // for the role of this class. 63 // for the role of this class.
47 class MemoryCoordinatorHandleImpl : public mojom::MemoryCoordinatorHandle { 64 class MemoryCoordinatorHandleImpl : public mojom::MemoryCoordinatorHandle {
48 public: 65 public:
49 MemoryCoordinatorHandleImpl(mojom::MemoryCoordinatorHandleRequest request, 66 MemoryCoordinatorHandleImpl(mojom::MemoryCoordinatorHandleRequest request,
50 MemoryCoordinatorImpl* coordinator, 67 MemoryCoordinatorImpl* coordinator,
51 int render_process_id); 68 int render_process_id);
52 ~MemoryCoordinatorHandleImpl() override; 69 ~MemoryCoordinatorHandleImpl() override;
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 return nullptr; 123 return nullptr;
107 return base::Singleton<MemoryCoordinatorImpl, 124 return base::Singleton<MemoryCoordinatorImpl,
108 MemoryCoordinatorImplSingletonTraits>::get(); 125 MemoryCoordinatorImplSingletonTraits>::get();
109 } 126 }
110 127
111 MemoryCoordinatorImpl::MemoryCoordinatorImpl( 128 MemoryCoordinatorImpl::MemoryCoordinatorImpl(
112 scoped_refptr<base::SingleThreadTaskRunner> task_runner, 129 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
113 std::unique_ptr<MemoryMonitor> memory_monitor) 130 std::unique_ptr<MemoryMonitor> memory_monitor)
114 : delegate_(GetContentClient()->browser()->GetMemoryCoordinatorDelegate()), 131 : delegate_(GetContentClient()->browser()->GetMemoryCoordinatorDelegate()),
115 memory_monitor_(std::move(memory_monitor)), 132 memory_monitor_(std::move(memory_monitor)),
116 state_updater_(base::MakeUnique<MemoryStateUpdater>(this, task_runner)) { 133 condition_observer_(
134 base::MakeUnique<MemoryConditionObserver>(this, task_runner)),
135 minimum_state_transition_period_(base::TimeDelta::FromSeconds(
136 kDefaultMinimumTransitionPeriodSeconds)) {
117 DCHECK(memory_monitor_.get()); 137 DCHECK(memory_monitor_.get());
118 base::MemoryCoordinatorProxy::SetMemoryCoordinator(this); 138 base::MemoryCoordinatorProxy::SetMemoryCoordinator(this);
119 } 139 }
120 140
121 MemoryCoordinatorImpl::~MemoryCoordinatorImpl() {} 141 MemoryCoordinatorImpl::~MemoryCoordinatorImpl() {}
122 142
123 void MemoryCoordinatorImpl::Start() { 143 void MemoryCoordinatorImpl::Start() {
124 DCHECK(CalledOnValidThread()); 144 DCHECK(CalledOnValidThread());
125 DCHECK(last_state_change_.is_null()); 145 DCHECK(last_state_change_.is_null());
126 146
127 notification_registrar_.Add( 147 notification_registrar_.Add(
128 this, NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED, 148 this, NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
129 NotificationService::AllBrowserContextsAndSources()); 149 NotificationService::AllBrowserContextsAndSources());
130 last_state_change_ = base::TimeTicks::Now(); 150 condition_observer_->ScheduleUpdateCondition(base::TimeDelta());
131 state_updater_->ScheduleUpdateState(base::TimeDelta());
132 } 151 }
133 152
134 void MemoryCoordinatorImpl::CreateHandle( 153 void MemoryCoordinatorImpl::CreateHandle(
135 int render_process_id, 154 int render_process_id,
136 mojom::MemoryCoordinatorHandleRequest request) { 155 mojom::MemoryCoordinatorHandleRequest request) {
137 std::unique_ptr<MemoryCoordinatorHandleImpl> handle( 156 std::unique_ptr<MemoryCoordinatorHandleImpl> handle(
138 new MemoryCoordinatorHandleImpl(std::move(request), this, 157 new MemoryCoordinatorHandleImpl(std::move(request), this,
139 render_process_id)); 158 render_process_id));
140 handle->binding().set_connection_error_handler( 159 handle->binding().set_connection_error_handler(
141 base::Bind(&MemoryCoordinatorImpl::OnConnectionError, 160 base::Bind(&MemoryCoordinatorImpl::OnConnectionError,
142 base::Unretained(this), render_process_id)); 161 base::Unretained(this), render_process_id));
143 CreateChildInfoMapEntry(render_process_id, std::move(handle)); 162 CreateChildInfoMapEntry(render_process_id, std::move(handle));
144 } 163 }
145 164
146 bool MemoryCoordinatorImpl::SetChildMemoryState(int render_process_id, 165 bool MemoryCoordinatorImpl::SetChildMemoryState(int render_process_id,
147 MemoryState memory_state) { 166 MemoryState memory_state) {
148 // Can't set an invalid memory state. 167 // Can't set an invalid memory state.
149 if (memory_state == MemoryState::UNKNOWN) 168 if (memory_state == MemoryState::UNKNOWN)
150 return false; 169 return false;
151 170
152 // Can't send a message to a child that doesn't exist. 171 // Can't send a message to a child that doesn't exist.
153 auto iter = children_.find(render_process_id); 172 auto iter = children_.find(render_process_id);
154 if (iter == children_.end()) 173 if (iter == children_.end())
155 return false; 174 return false;
156 175
157 // Can't send a message to a child that isn't bound. 176 // Can't send a message to a child that isn't bound.
158 if (!iter->second.handle->child().is_bound()) 177 if (!iter->second.handle->child().is_bound())
159 return false; 178 return false;
160 179
161 memory_state = OverrideGlobalState(memory_state, iter->second); 180 memory_state = OverrideState(memory_state, iter->second);
162 181
163 // A nop doesn't need to be sent, but is considered successful. 182 // A nop doesn't need to be sent, but is considered successful.
164 if (iter->second.memory_state == memory_state) 183 if (iter->second.memory_state == memory_state)
165 return true; 184 return true;
166 185
167 // Can't suspend the given renderer. 186 // Can't suspend the given renderer.
168 if (memory_state == MemoryState::SUSPENDED && 187 if (memory_state == MemoryState::SUSPENDED &&
169 !CanSuspendRenderer(render_process_id)) 188 !CanSuspendRenderer(render_process_id))
170 return false; 189 return false;
171 190
172 // Update the internal state and send the message. 191 // Update the internal state and send the message.
173 iter->second.memory_state = memory_state; 192 iter->second.memory_state = memory_state;
174 iter->second.handle->child()->OnStateChange(ToMojomMemoryState(memory_state)); 193 iter->second.handle->child()->OnStateChange(ToMojomMemoryState(memory_state));
175 return true; 194 return true;
176 } 195 }
177 196
178 base::MemoryState MemoryCoordinatorImpl::GetChildMemoryState( 197 MemoryState MemoryCoordinatorImpl::GetChildMemoryState(
179 int render_process_id) const { 198 int render_process_id) const {
180 auto iter = children_.find(render_process_id); 199 auto iter = children_.find(render_process_id);
181 if (iter == children_.end()) 200 if (iter == children_.end())
182 return base::MemoryState::UNKNOWN; 201 return MemoryState::UNKNOWN;
183 return iter->second.memory_state; 202 return iter->second.memory_state;
184 } 203 }
185 204
186 void MemoryCoordinatorImpl::RecordMemoryPressure( 205 void MemoryCoordinatorImpl::RecordMemoryPressure(
187 base::MemoryPressureMonitor::MemoryPressureLevel level) { 206 base::MemoryPressureMonitor::MemoryPressureLevel level) {
188 // TODO(bashi): Record memory pressure level. 207 // TODO(bashi): Record memory pressure level.
189 } 208 }
190 209
191 base::MemoryState MemoryCoordinatorImpl::GetGlobalMemoryState() const { 210 MemoryState MemoryCoordinatorImpl::GetBrowserMemoryState() const {
192 return current_state_; 211 return browser_memory_state_;
193 } 212 }
194 213
195 base::MemoryState MemoryCoordinatorImpl::GetCurrentMemoryState() const { 214 MemoryState MemoryCoordinatorImpl::GetCurrentMemoryState() const {
196 // SUSPENDED state may not make sense to the browser process. Use THROTTLED 215 return GetBrowserMemoryState();
197 // instead when the global state is SUSPENDED.
198 // TODO(bashi): Maybe worth considering another state for the browser.
199 return current_state_ == MemoryState::SUSPENDED ? MemoryState::THROTTLED
200 : current_state_;
201 } 216 }
202 217
203 void MemoryCoordinatorImpl::SetCurrentMemoryStateForTesting( 218 void MemoryCoordinatorImpl::SetCurrentMemoryStateForTesting(
204 base::MemoryState memory_state) { 219 MemoryState memory_state) {
205 // This changes the current state temporariy for testing. The state will be 220 // Resets |last_state_change_| so that
206 // updated 1 minute later. 221 // UpdateBrowserStateAndNotifyStateToClients() to set memory state forcibly.
207 ForceSetGlobalState(memory_state, base::TimeDelta::FromMinutes(1)); 222 last_state_change_ = base::TimeTicks();
223 UpdateBrowserStateAndNotifyStateToClients(memory_state);
208 } 224 }
209 225
210 void MemoryCoordinatorImpl::ForceSetGlobalState(base::MemoryState new_state, 226 void MemoryCoordinatorImpl::ForceSetMemoryCondition(MemoryCondition condition,
211 base::TimeDelta duration) { 227 base::TimeDelta duration) {
212 DCHECK(new_state != MemoryState::UNKNOWN); 228 UpdateConditionIfNeeded(condition);
213 ChangeStateIfNeeded(current_state_, new_state); 229 condition_observer_->ScheduleUpdateCondition(duration);
214 state_updater_->ScheduleUpdateState(duration);
215 } 230 }
216 231
217 void MemoryCoordinatorImpl::Observe(int type, 232 void MemoryCoordinatorImpl::Observe(int type,
218 const NotificationSource& source, 233 const NotificationSource& source,
219 const NotificationDetails& details) { 234 const NotificationDetails& details) {
220 DCHECK(type == NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED); 235 DCHECK(type == NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED);
221 RenderWidgetHost* render_widget_host = Source<RenderWidgetHost>(source).ptr(); 236 RenderWidgetHost* render_widget_host = Source<RenderWidgetHost>(source).ptr();
222 RenderProcessHost* process = render_widget_host->GetProcess(); 237 RenderProcessHost* process = render_widget_host->GetProcess();
223 if (!process) 238 if (!process)
224 return; 239 return;
225 auto iter = children().find(process->GetID()); 240 auto iter = children().find(process->GetID());
226 if (iter == children().end()) 241 if (iter == children().end())
227 return; 242 return;
243
228 iter->second.is_visible = *Details<bool>(details).ptr(); 244 iter->second.is_visible = *Details<bool>(details).ptr();
229 auto new_state = GetGlobalMemoryState(); 245 // The current heuristics for state calculation:
246 // - Foregrounded renderers: THROTTLED when condition is CRITICAL, otherwise
247 // NORMAL.
248 // - Backgrounded renderers: THROTTLED when condition is WARNING/CRITICAL,
249 // otherwise NORMAL.
250 MemoryState new_state = MemoryState::NORMAL;
251 MemoryCondition condition = GetMemoryCondition();
252 if (condition == MemoryCondition::WARNING) {
253 new_state =
254 iter->second.is_visible ? MemoryState::NORMAL : MemoryState::THROTTLED;
255 } else if (condition == MemoryCondition::CRITICAL) {
256 new_state = MemoryState::THROTTLED;
257 }
230 SetChildMemoryState(iter->first, new_state); 258 SetChildMemoryState(iter->first, new_state);
231 } 259 }
232 260
233 base::MemoryState MemoryCoordinatorImpl::GetStateForProcess( 261 MemoryState MemoryCoordinatorImpl::GetStateForProcess(
234 base::ProcessHandle handle) { 262 base::ProcessHandle handle) {
235 DCHECK(CalledOnValidThread()); 263 DCHECK(CalledOnValidThread());
236 if (handle == base::kNullProcessHandle) 264 if (handle == base::kNullProcessHandle)
237 return MemoryState::UNKNOWN; 265 return MemoryState::UNKNOWN;
238 if (handle == base::GetCurrentProcessHandle()) 266 if (handle == base::GetCurrentProcessHandle())
239 return GetCurrentMemoryState(); 267 return browser_memory_state_;
240 268
241 for (auto& iter : children()) { 269 for (auto& iter : children()) {
242 auto* render_process_host = GetRenderProcessHost(iter.first); 270 auto* render_process_host = GetRenderProcessHost(iter.first);
243 if (render_process_host && render_process_host->GetHandle() == handle) 271 if (render_process_host && render_process_host->GetHandle() == handle)
244 return iter.second.memory_state; 272 return iter.second.memory_state;
245 } 273 }
246 return MemoryState::UNKNOWN; 274 return MemoryState::UNKNOWN;
247 } 275 }
248 276
249 bool MemoryCoordinatorImpl::ChangeStateIfNeeded(base::MemoryState prev_state, 277 void MemoryCoordinatorImpl::UpdateConditionIfNeeded(
250 base::MemoryState next_state) { 278 MemoryCondition next_condition) {
251 DCHECK(CalledOnValidThread()); 279 DCHECK(CalledOnValidThread());
252 if (prev_state == next_state) 280 if (memory_condition_ == next_condition)
253 return false; 281 return;
254 282
255 last_state_change_ = base::TimeTicks::Now(); 283 MemoryCondition prev_condition = memory_condition_;
256 current_state_ = next_state; 284 memory_condition_ = next_condition;
257 285
258 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("memory-infra"), 286 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("memory-infra"),
259 "MemoryCoordinatorImpl::ChangeStateIfNeeded", "prev", 287 "MemoryCoordinatorImpl::UpdateConditionIfNeeded", "prev",
260 MemoryStateToString(prev_state), "next", 288 MemoryConditionToString(prev_condition), "next",
261 MemoryStateToString(next_state)); 289 MemoryConditionToString(next_condition));
262 NotifyStateToClients(); 290
263 NotifyStateToChildren(); 291 // TODO(bashi): Following actions are tentative. We might want to prioritize
264 return true; 292 // processes and handle them one-by-one.
293
294 if (next_condition == MemoryCondition::NORMAL) {
295 // Set NORMAL state to all clients/processes.
296 UpdateBrowserStateAndNotifyStateToClients(MemoryState::NORMAL);
297 NotifyStateToChildren(MemoryState::NORMAL);
298 } else if (next_condition == MemoryCondition::WARNING) {
299 // Set NORMAL state to foreground proceses and clients in the browser
300 // process. Set THROTTLED state to background processes.
301 UpdateBrowserStateAndNotifyStateToClients(MemoryState::NORMAL);
302 for (auto& iter : children()) {
303 auto state =
304 iter.second.is_visible ? MemoryState::NORMAL : MemoryState::THROTTLED;
305 SetChildMemoryState(iter.first, state);
306 }
307 // Idea: Purge memory from background processes.
308 } else if (next_condition == MemoryCondition::CRITICAL) {
309 // Set THROTTLED state to all clients/processes.
310 UpdateBrowserStateAndNotifyStateToClients(MemoryState::THROTTLED);
311 NotifyStateToChildren(MemoryState::THROTTLED);
312 // Idea: Start discarding tabs.
313 }
265 } 314 }
266 315
267 void MemoryCoordinatorImpl::DiscardTab() { 316 void MemoryCoordinatorImpl::DiscardTab() {
268 if (delegate_) 317 if (delegate_)
269 delegate_->DiscardTab(); 318 delegate_->DiscardTab();
270 } 319 }
271 320
272 RenderProcessHost* MemoryCoordinatorImpl::GetRenderProcessHost( 321 RenderProcessHost* MemoryCoordinatorImpl::GetRenderProcessHost(
273 int render_process_id) { 322 int render_process_id) {
274 return RenderProcessHost::FromID(render_process_id); 323 return RenderProcessHost::FromID(render_process_id);
(...skipping 26 matching lines...) Expand all
301 return false; 350 return false;
302 if (render_process_host->GetWorkerRefCount() > 0) 351 if (render_process_host->GetWorkerRefCount() > 0)
303 return false; 352 return false;
304 // Assumes that we can't suspend renderers if there is no delegate. 353 // Assumes that we can't suspend renderers if there is no delegate.
305 if (!delegate_) 354 if (!delegate_)
306 return false; 355 return false;
307 return delegate_->CanSuspendBackgroundedRenderer(render_process_id); 356 return delegate_->CanSuspendBackgroundedRenderer(render_process_id);
308 } 357 }
309 358
310 void MemoryCoordinatorImpl::OnChildAdded(int render_process_id) { 359 void MemoryCoordinatorImpl::OnChildAdded(int render_process_id) {
311 // Populate the global state as an initial state of a newly created process. 360 // Populate an initial state of a newly created process, assuming it's
312 auto new_state = GetGlobalMemoryState(); 361 // foregrounded.
362 // TODO(bashi): Don't assume the process is foregrounded. It can be added
363 // as a background process.
364 auto new_state = GetMemoryCondition() == MemoryCondition::CRITICAL
365 ? MemoryState::THROTTLED
366 : MemoryState::NORMAL;
313 SetChildMemoryState(render_process_id, new_state); 367 SetChildMemoryState(render_process_id, new_state);
314 } 368 }
315 369
316 base::MemoryState MemoryCoordinatorImpl::OverrideGlobalState( 370 MemoryState MemoryCoordinatorImpl::OverrideState(MemoryState memory_state,
317 MemoryState memory_state, 371 const ChildInfo& child) {
318 const ChildInfo& child) {
319 // We don't suspend foreground renderers. Throttle them instead. 372 // We don't suspend foreground renderers. Throttle them instead.
320 if (child.is_visible && memory_state == MemoryState::SUSPENDED) 373 if (child.is_visible && memory_state == MemoryState::SUSPENDED)
321 return MemoryState::THROTTLED; 374 return MemoryState::THROTTLED;
322 #if defined(OS_ANDROID) 375 #if defined(OS_ANDROID)
323 // On Android, we throttle background renderers immediately. 376 // On Android, we throttle background renderers immediately.
324 // TODO(bashi): Create a specialized class of MemoryCoordinator for Android 377 // TODO(bashi): Create a specialized class of MemoryCoordinator for Android
325 // and move this ifdef to the class. 378 // and move this ifdef to the class.
326 if (!child.is_visible && memory_state == MemoryState::NORMAL) 379 if (!child.is_visible && memory_state == MemoryState::NORMAL)
327 return MemoryState::THROTTLED; 380 return MemoryState::THROTTLED;
328 // TODO(bashi): Suspend background renderers after a certain period of time. 381 // TODO(bashi): Suspend background renderers after a certain period of time.
329 #endif // defined(OS_ANDROID) 382 #endif // defined(OS_ANDROID)
330 return memory_state; 383 return memory_state;
331 } 384 }
332 385
333 void MemoryCoordinatorImpl::CreateChildInfoMapEntry( 386 void MemoryCoordinatorImpl::CreateChildInfoMapEntry(
334 int render_process_id, 387 int render_process_id,
335 std::unique_ptr<MemoryCoordinatorHandleImpl> handle) { 388 std::unique_ptr<MemoryCoordinatorHandleImpl> handle) {
336 auto& child_info = children_[render_process_id]; 389 auto& child_info = children_[render_process_id];
337 // Process always start with normal memory state. 390 // Process always start with normal memory state.
338 // We'll set renderer's memory state to the current global state when the 391 // We'll set renderer's memory state to the current global state when the
339 // corresponding renderer process is ready to communicate. Renderer processes 392 // corresponding renderer process is ready to communicate. Renderer processes
340 // call AddChild() when they are ready. 393 // call AddChild() when they are ready.
341 child_info.memory_state = MemoryState::NORMAL; 394 child_info.memory_state = MemoryState::NORMAL;
342 child_info.is_visible = true; 395 child_info.is_visible = true;
343 child_info.handle = std::move(handle); 396 child_info.handle = std::move(handle);
344 } 397 }
345 398
346 void MemoryCoordinatorImpl::NotifyStateToClients() { 399 void MemoryCoordinatorImpl::UpdateBrowserStateAndNotifyStateToClients(
347 auto state = GetCurrentMemoryState(); 400 MemoryState memory_state) {
401 if (memory_state == browser_memory_state_)
402 return;
403
404 base::TimeTicks now = base::TimeTicks::Now();
405 if (!last_state_change_.is_null() &&
406 (now - last_state_change_ < minimum_state_transition_period_))
407 return;
408
409 last_state_change_ = now;
410 browser_memory_state_ = memory_state;
411 NotifyStateToClients(memory_state);
412 }
413
414 void MemoryCoordinatorImpl::NotifyStateToClients(MemoryState state) {
348 base::MemoryCoordinatorClientRegistry::GetInstance()->Notify(state); 415 base::MemoryCoordinatorClientRegistry::GetInstance()->Notify(state);
349 } 416 }
350 417
351 void MemoryCoordinatorImpl::NotifyStateToChildren() { 418 void MemoryCoordinatorImpl::NotifyStateToChildren(MemoryState state) {
352 // It's OK to call SetChildMemoryState() unconditionally because it checks 419 // It's OK to call SetChildMemoryState() unconditionally because it checks
353 // whether this state transition is valid. 420 // whether this state transition is valid.
354 for (auto& iter : children()) 421 for (auto& iter : children())
355 SetChildMemoryState(iter.first, current_state_); 422 SetChildMemoryState(iter.first, state);
356 } 423 }
357 424
358 MemoryCoordinatorImpl::ChildInfo::ChildInfo() {} 425 MemoryCoordinatorImpl::ChildInfo::ChildInfo() {}
359 426
360 MemoryCoordinatorImpl::ChildInfo::ChildInfo(const ChildInfo& rhs) { 427 MemoryCoordinatorImpl::ChildInfo::ChildInfo(const ChildInfo& rhs) {
361 // This is a nop, but exists for compatibility with STL containers. 428 // This is a nop, but exists for compatibility with STL containers.
362 } 429 }
363 430
364 MemoryCoordinatorImpl::ChildInfo::~ChildInfo() {} 431 MemoryCoordinatorImpl::ChildInfo::~ChildInfo() {}
365 432
366 } // namespace content 433 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/memory/memory_coordinator_impl.h ('k') | content/browser/memory/memory_coordinator_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698