OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/extensions/extension_message_service.h" | 5 #include "chrome/browser/extensions/extension_message_service.h" |
6 | 6 |
7 #include "base/singleton.h" | 7 #include "base/singleton.h" |
8 #include "base/values.h" | 8 #include "base/values.h" |
9 #include "chrome/browser/chrome_thread.h" | 9 #include "chrome/browser/chrome_thread.h" |
10 #include "chrome/browser/extensions/extension.h" | 10 #include "chrome/browser/extensions/extension.h" |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 } | 57 } |
58 return instance; | 58 return instance; |
59 } | 59 } |
60 | 60 |
61 ExtensionMessageService::ExtensionMessageService() | 61 ExtensionMessageService::ExtensionMessageService() |
62 : next_port_id_(0), observing_renderer_shutdown_(false) { | 62 : next_port_id_(0), observing_renderer_shutdown_(false) { |
63 } | 63 } |
64 | 64 |
65 void ExtensionMessageService::RegisterExtension( | 65 void ExtensionMessageService::RegisterExtension( |
66 const std::string& extension_id, int render_process_id) { | 66 const std::string& extension_id, int render_process_id) { |
| 67 DCHECK(MessageLoop::current()->type() == MessageLoop::TYPE_UI); |
67 AutoLock lock(process_ids_lock_); | 68 AutoLock lock(process_ids_lock_); |
68 DCHECK(process_ids_.find(extension_id) == process_ids_.end() || | 69 DCHECK(process_ids_.find(extension_id) == process_ids_.end() || |
69 process_ids_[extension_id] == render_process_id); | 70 process_ids_[extension_id] == render_process_id); |
70 process_ids_[extension_id] = render_process_id; | 71 process_ids_[extension_id] = render_process_id; |
71 } | 72 } |
72 | 73 |
| 74 void ExtensionMessageService::AddEventListener(std::string event_name, |
| 75 int render_process_id) { |
| 76 DCHECK(MessageLoop::current()->type() == MessageLoop::TYPE_UI); |
| 77 AutoLock lock(listener_lock_); |
| 78 DCHECK(listeners_[event_name].count(render_process_id) == 0); |
| 79 listeners_[event_name].insert(render_process_id); |
| 80 } |
| 81 |
| 82 void ExtensionMessageService::RemoveEventListener(std::string event_name, |
| 83 int render_process_id) { |
| 84 DCHECK(MessageLoop::current()->type() == MessageLoop::TYPE_UI); |
| 85 AutoLock lock(listener_lock_); |
| 86 DCHECK(listeners_[event_name].count(render_process_id) == 1); |
| 87 listeners_[event_name].erase(render_process_id); |
| 88 } |
| 89 |
73 int ExtensionMessageService::OpenChannelToExtension( | 90 int ExtensionMessageService::OpenChannelToExtension( |
74 const std::string& extension_id, ResourceMessageFilter* source) { | 91 const std::string& extension_id, ResourceMessageFilter* source) { |
75 DCHECK(MessageLoop::current() == | 92 DCHECK(MessageLoop::current() == |
76 ChromeThread::GetMessageLoop(ChromeThread::IO)); | 93 ChromeThread::GetMessageLoop(ChromeThread::IO)); |
77 | 94 |
78 // Lookup the targeted extension process. | 95 // Lookup the targeted extension process. |
79 int process_id; | 96 int process_id; |
80 { | 97 { |
81 AutoLock lock(process_ids_lock_); | 98 AutoLock lock(process_ids_lock_); |
82 ProcessIDMap::iterator process_id_it = process_ids_.find( | 99 ProcessIDMap::iterator process_id_it = process_ids_.find( |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 dest = channel.port2; | 148 dest = channel.port2; |
132 DCHECK(source == channel.port1); | 149 DCHECK(source == channel.port1); |
133 } | 150 } |
134 | 151 |
135 int source_port_id = GET_OPPOSITE_PORT_ID(port_id); | 152 int source_port_id = GET_OPPOSITE_PORT_ID(port_id); |
136 dest->Send(new ViewMsg_ExtensionHandleMessage(message, source_port_id)); | 153 dest->Send(new ViewMsg_ExtensionHandleMessage(message, source_port_id)); |
137 } | 154 } |
138 | 155 |
139 void ExtensionMessageService::DispatchEventToRenderers( | 156 void ExtensionMessageService::DispatchEventToRenderers( |
140 const std::string& event_name, const std::string& event_args) { | 157 const std::string& event_name, const std::string& event_args) { |
| 158 std::set<int> pids; |
| 159 { |
| 160 AutoLock lock(listener_lock_); |
| 161 pids = listeners_[event_name]; |
| 162 if (pids.empty()) |
| 163 return; |
| 164 } |
141 MessageLoop* io_thread = ChromeThread::GetMessageLoop(ChromeThread::IO); | 165 MessageLoop* io_thread = ChromeThread::GetMessageLoop(ChromeThread::IO); |
142 if (MessageLoop::current() != io_thread) { | 166 if (MessageLoop::current() != io_thread) { |
143 // Do the actual work on the IO thread. | 167 // Do the actual work on the IO thread. |
144 io_thread->PostTask(FROM_HERE, NewRunnableMethod(this, | 168 io_thread->PostTask(FROM_HERE, NewRunnableMethod(this, |
145 &ExtensionMessageService::DispatchEventToRenderers, | 169 &ExtensionMessageService::DispatchEventToRenderers, |
146 event_name, event_args)); | 170 event_name, event_args)); |
147 return; | 171 return; |
148 } | 172 } |
149 | 173 |
150 // TODO(mpcomplete): we should only send messages to extension process | 174 // Send the event only to renderers that are listening for it. |
151 // renderers. | 175 for (std::set<int>::iterator pid = pids.begin(); pid != pids.end(); ++pid) { |
152 std::set<ResourceMessageFilter*>::iterator renderer; | 176 RendererMap::iterator renderer = renderers_.find(*pid); |
153 for (renderer = renderers_unique_.begin(); | 177 if (renderer == renderers_.end()) |
154 renderer != renderers_unique_.end(); ++renderer) { | 178 continue; |
155 (*renderer)->Send(new ViewMsg_ExtensionHandleEvent(event_name, event_args)); | 179 ResourceMessageFilter* filter = renderer->second; |
| 180 filter->Send(new ViewMsg_ExtensionHandleEvent(event_name, event_args)); |
156 } | 181 } |
157 } | 182 } |
158 | 183 |
159 void ExtensionMessageService::RendererReady(ResourceMessageFilter* renderer) { | 184 void ExtensionMessageService::RendererReady(ResourceMessageFilter* renderer) { |
160 DCHECK(MessageLoop::current() == | 185 DCHECK(MessageLoop::current() == |
161 ChromeThread::GetMessageLoop(ChromeThread::IO)); | 186 ChromeThread::GetMessageLoop(ChromeThread::IO)); |
162 | 187 |
163 DCHECK(renderers_.find(renderer->GetProcessId()) == renderers_.end()); | 188 DCHECK(renderers_.find(renderer->GetProcessId()) == renderers_.end()); |
164 renderers_[renderer->GetProcessId()] = renderer; | 189 renderers_[renderer->GetProcessId()] = renderer; |
165 renderers_unique_.insert(renderer); | 190 renderers_unique_.insert(renderer); |
166 | 191 |
167 if (!observing_renderer_shutdown_) { | 192 if (!observing_renderer_shutdown_) { |
168 observing_renderer_shutdown_ = true; | 193 observing_renderer_shutdown_ = true; |
169 NotificationService::current()->AddObserver( | 194 NotificationService::current()->AddObserver( |
170 this, | 195 this, |
171 NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN, | 196 NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN, |
172 NotificationService::AllSources()); | 197 NotificationService::AllSources()); |
173 } | 198 } |
174 } | 199 } |
175 | 200 |
176 void ExtensionMessageService::Observe(NotificationType type, | 201 void ExtensionMessageService::Observe(NotificationType type, |
177 const NotificationSource& source, | 202 const NotificationSource& source, |
178 const NotificationDetails& details) { | 203 const NotificationDetails& details) { |
179 DCHECK(MessageLoop::current() == | 204 DCHECK(MessageLoop::current() == |
180 ChromeThread::GetMessageLoop(ChromeThread::IO)); | 205 ChromeThread::GetMessageLoop(ChromeThread::IO)); |
181 | 206 |
182 DCHECK(type.value == NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN); | 207 DCHECK(type.value == NotificationType::RESOURCE_MESSAGE_FILTER_SHUTDOWN); |
183 ResourceMessageFilter* renderer = Source<ResourceMessageFilter>(source).ptr(); | 208 ResourceMessageFilter* renderer = Source<ResourceMessageFilter>(source).ptr(); |
184 | 209 |
185 renderers_.erase(renderer->GetProcessId()); | 210 renderers_.erase(renderer->GetProcessId()); |
186 renderers_unique_.erase(renderer); | 211 renderers_unique_.erase(renderer); |
187 | 212 |
188 // Close any channels that share this renderer. | 213 // Close any channels that share this renderer. |
189 // TODO(mpcomplete): should we notify the other side of the port? | 214 // TODO(mpcomplete): should we notify the other side of the port? |
190 for (MessageChannelMap::iterator it = channels_.begin(); | 215 for (MessageChannelMap::iterator it = channels_.begin(); |
191 it != channels_.end(); ) { | 216 it != channels_.end(); ) { |
192 MessageChannelMap::iterator current = it++; | 217 MessageChannelMap::iterator current = it++; |
193 if (current->second.port1 == renderer || current->second.port2 == renderer) | 218 if (current->second.port1 == renderer || current->second.port2 == renderer) |
194 channels_.erase(current); | 219 channels_.erase(current); |
195 } | 220 } |
196 } | 221 } |
OLD | NEW |