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

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

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

Powered by Google App Engine
This is Rietveld 408576698