OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "content/browser/memory/memory_pressure_controller.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "content/browser/memory/memory_message_filter.h" | |
9 #include "content/public/browser/browser_thread.h" | |
10 | |
11 namespace content { | |
12 | |
13 MemoryPressureController::MemoryPressureController() {} | |
14 | |
15 MemoryPressureController::~MemoryPressureController() {} | |
16 | |
17 void MemoryPressureController::OnMemoryMessageFilterAdded( | |
18 MemoryMessageFilter* filter) { | |
19 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
20 | |
21 // Add the message filter to the set of all memory message filters and check | |
22 // that it wasn't there beforehand. | |
23 const bool success = | |
24 memory_message_filters_.insert( | |
25 std::make_pair(filter->process_host(), filter)) | |
26 .second; | |
27 DCHECK(success); | |
28 | |
29 // There's no need to send a message to the child process if memory pressure | |
30 // notifications are not suppressed. | |
31 if (base::MemoryPressureListener::AreNotificationsSuppressed()) | |
32 filter->SendSetPressureNotificationsSuppressed(true); | |
33 } | |
34 | |
35 void MemoryPressureController::OnMemoryMessageFilterRemoved( | |
36 MemoryMessageFilter* filter) { | |
37 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
38 | |
39 // Remove the message filter from the set of all memory message filters, | |
40 // ensuring that it was there beforehand. | |
41 auto it = memory_message_filters_.find(filter->process_host()); | |
42 DCHECK(it != memory_message_filters_.end()); | |
43 DCHECK_EQ(filter, it->second); | |
44 memory_message_filters_.erase(it); | |
45 } | |
46 | |
47 // static | |
48 MemoryPressureController* MemoryPressureController::GetInstance() { | |
49 return base::Singleton< | |
50 MemoryPressureController, | |
51 base::LeakySingletonTraits<MemoryPressureController>>::get(); | |
52 } | |
53 | |
54 void MemoryPressureController::SetPressureNotificationsSuppressedInAllProcesses( | |
55 bool suppressed) { | |
56 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | |
57 // Note that passing base::Unretained(this) is safe here because the | |
58 // controller is a leaky singleton. | |
59 BrowserThread::PostTask( | |
60 BrowserThread::IO, FROM_HERE, | |
61 base::Bind(&MemoryPressureController:: | |
62 SetPressureNotificationsSuppressedInAllProcesses, | |
63 base::Unretained(this), suppressed)); | |
64 return; | |
65 } | |
66 | |
67 // Enable/disable suppressing memory notifications in the browser process. | |
68 base::MemoryPressureListener::SetNotificationsSuppressed(suppressed); | |
69 | |
70 // Enable/disable suppressing memory notifications in all child processes. | |
71 for (const auto& filter_pair : memory_message_filters_) | |
72 filter_pair.second->SendSetPressureNotificationsSuppressed(suppressed); | |
73 } | |
74 | |
75 void MemoryPressureController::SimulatePressureNotificationInAllProcesses( | |
76 base::MemoryPressureListener::MemoryPressureLevel level) { | |
77 DCHECK_NE(level, base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE); | |
78 | |
79 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | |
80 // Note that passing base::Unretained(this) is safe here because the | |
81 // controller is a leaky singleton. | |
82 BrowserThread::PostTask( | |
83 BrowserThread::IO, FROM_HERE, | |
84 base::Bind(&MemoryPressureController:: | |
85 SimulatePressureNotificationInAllProcesses, | |
86 base::Unretained(this), level)); | |
87 return; | |
88 } | |
89 | |
90 // Simulate memory pressure notification in the browser process. | |
91 base::MemoryPressureListener::SimulatePressureNotification(level); | |
92 | |
93 // Simulate memory pressure notification in all child processes. | |
94 for (const auto& filter_pair : memory_message_filters_) | |
95 filter_pair.second->SendSimulatePressureNotification(level); | |
96 } | |
97 | |
98 void MemoryPressureController::SendPressureNotification( | |
99 const BrowserChildProcessHost* child_process_host, | |
100 base::MemoryPressureListener::MemoryPressureLevel level) { | |
101 SendPressureNotificationImpl(child_process_host, level); | |
102 } | |
103 | |
104 void MemoryPressureController::SendPressureNotification( | |
105 const RenderProcessHost* render_process_host, | |
106 base::MemoryPressureListener::MemoryPressureLevel level) { | |
107 SendPressureNotificationImpl(render_process_host, level); | |
108 } | |
109 | |
110 void MemoryPressureController::SendPressureNotificationImpl( | |
111 const void* child_process_host, | |
112 base::MemoryPressureListener::MemoryPressureLevel level) { | |
113 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { | |
114 // Note that passing base::Unretained(this) is safe here because the | |
115 // controller is a leaky singleton. It's also safe to pass an untyped | |
116 // child process pointer as the address is only used as a key for lookup in | |
117 // a map; at no point is it dereferenced. | |
118 BrowserThread::PostTask( | |
119 BrowserThread::IO, FROM_HERE, | |
120 base::Bind(&MemoryPressureController::SendPressureNotificationImpl, | |
121 base::Unretained(this), child_process_host, level)); | |
122 return; | |
123 } | |
124 | |
125 if (base::MemoryPressureListener::AreNotificationsSuppressed()) | |
126 return; | |
127 | |
128 // Find the appropriate message filter and dispatch the message. | |
129 auto it = memory_message_filters_.find(child_process_host); | |
130 if (it != memory_message_filters_.end()) | |
131 it->second->SendPressureNotification(level); | |
132 } | |
133 | |
134 } // namespace content | |
OLD | NEW |