OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/atomic_sequence_num.h" |
7 #include "base/json/json_writer.h" | 8 #include "base/json/json_writer.h" |
8 #include "base/singleton.h" | |
9 #include "base/stl_util-inl.h" | 9 #include "base/stl_util-inl.h" |
10 #include "base/values.h" | 10 #include "base/values.h" |
11 #include "chrome/browser/child_process_security_policy.h" | 11 #include "chrome/browser/child_process_security_policy.h" |
12 #include "chrome/browser/chrome_thread.h" | |
13 #include "chrome/browser/extensions/extension_process_manager.h" | 12 #include "chrome/browser/extensions/extension_process_manager.h" |
14 #include "chrome/browser/extensions/extension_tabs_module.h" | 13 #include "chrome/browser/extensions/extension_tabs_module.h" |
15 #include "chrome/browser/profile.h" | 14 #include "chrome/browser/profile.h" |
16 #include "chrome/browser/renderer_host/render_process_host.h" | 15 #include "chrome/browser/renderer_host/render_process_host.h" |
17 #include "chrome/browser/renderer_host/render_view_host.h" | 16 #include "chrome/browser/renderer_host/render_view_host.h" |
18 #include "chrome/browser/renderer_host/resource_message_filter.h" | 17 #include "chrome/browser/renderer_host/resource_message_filter.h" |
19 #include "chrome/browser/tab_contents/tab_contents.h" | 18 #include "chrome/browser/tab_contents/tab_contents.h" |
20 #include "chrome/browser/tab_contents/tab_util.h" | 19 #include "chrome/browser/tab_contents/tab_util.h" |
21 #include "chrome/common/extensions/extension.h" | 20 #include "chrome/common/extensions/extension.h" |
22 #include "chrome/common/notification_service.h" | 21 #include "chrome/common/notification_service.h" |
23 #include "chrome/common/render_messages.h" | 22 #include "chrome/common/render_messages.h" |
24 | 23 |
25 // Since we have 2 ports for every channel, we just index channels by half the | 24 // Since we have 2 ports for every channel, we just index channels by half the |
26 // port ID. | 25 // port ID. |
27 #define GET_CHANNEL_ID(port_id) ((port_id) / 2) | 26 #define GET_CHANNEL_ID(port_id) ((port_id) / 2) |
28 #define GET_CHANNEL_OPENER_ID(channel_id) ((channel_id) * 2) | 27 #define GET_CHANNEL_OPENER_ID(channel_id) ((channel_id) * 2) |
29 #define GET_CHANNEL_RECEIVERS_ID(channel_id) ((channel_id) * 2 + 1) | 28 #define GET_CHANNEL_RECEIVERS_ID(channel_id) ((channel_id) * 2 + 1) |
30 | 29 |
31 // Port1 is always even, port2 is always odd. | 30 // Port1 is always even, port2 is always odd. |
32 #define IS_OPENER_PORT_ID(port_id) (((port_id) & 1) == 0) | 31 #define IS_OPENER_PORT_ID(port_id) (((port_id) & 1) == 0) |
33 | 32 |
34 // Change even to odd and vice versa, to get the other side of a given channel. | 33 // Change even to odd and vice versa, to get the other side of a given channel. |
35 #define GET_OPPOSITE_PORT_ID(source_port_id) ((source_port_id) ^ 1) | 34 #define GET_OPPOSITE_PORT_ID(source_port_id) ((source_port_id) ^ 1) |
36 | 35 |
37 struct ExtensionMessageService::MessagePort { | 36 struct ExtensionMessageService::MessagePort { |
38 IPC::Message::Sender* sender; | 37 IPC::Message::Sender* sender; |
39 int routing_id; | 38 int routing_id; |
40 // TODO(mpcomplete): remove this when I track down the crasher. Hopefully | |
41 // this guy will show up in some stack traces and potentially give some | |
42 // insight. | |
43 // http://code.google.com/p/chromium/issues/detail?id=21201 | |
44 int debug_info; | |
45 | |
46 MessagePort(IPC::Message::Sender* sender = NULL, | 39 MessagePort(IPC::Message::Sender* sender = NULL, |
47 int routing_id = MSG_ROUTING_CONTROL) : | 40 int routing_id = MSG_ROUTING_CONTROL) : |
48 sender(sender), routing_id(routing_id), debug_info(0) {} | 41 sender(sender), routing_id(routing_id) {} |
49 }; | 42 }; |
50 | 43 |
51 struct ExtensionMessageService::MessageChannel { | 44 struct ExtensionMessageService::MessageChannel { |
52 ExtensionMessageService::MessagePort opener; | 45 ExtensionMessageService::MessagePort opener; |
53 ExtensionMessageService::MessagePort receiver; | 46 ExtensionMessageService::MessagePort receiver; |
54 }; | 47 }; |
55 | 48 |
| 49 const char ExtensionMessageService::kDispatchOnConnect[] = |
| 50 "Port.dispatchOnConnect"; |
| 51 const char ExtensionMessageService::kDispatchOnDisconnect[] = |
| 52 "Port.dispatchOnDisconnect"; |
| 53 const char ExtensionMessageService::kDispatchOnMessage[] = |
| 54 "Port.dispatchOnMessage"; |
| 55 const char ExtensionMessageService::kDispatchEvent[] = |
| 56 "Event.dispatchJSON"; |
56 | 57 |
57 namespace { | 58 namespace { |
58 | 59 |
| 60 static base::AtomicSequenceNumber g_next_channel_id(base::LINKER_INITIALIZED); |
| 61 |
59 static void DispatchOnConnect(const ExtensionMessageService::MessagePort& port, | 62 static void DispatchOnConnect(const ExtensionMessageService::MessagePort& port, |
60 int dest_port_id, | 63 int dest_port_id, |
61 const std::string& channel_name, | 64 const std::string& channel_name, |
62 const std::string& tab_json, | 65 const std::string& tab_json, |
63 const std::string& source_extension_id, | 66 const std::string& source_extension_id, |
64 const std::string& target_extension_id) { | 67 const std::string& target_extension_id) { |
65 ListValue args; | 68 ListValue args; |
66 args.Set(0, Value::CreateIntegerValue(dest_port_id)); | 69 args.Set(0, Value::CreateIntegerValue(dest_port_id)); |
67 args.Set(1, Value::CreateStringValue(channel_name)); | 70 args.Set(1, Value::CreateStringValue(channel_name)); |
68 args.Set(2, Value::CreateStringValue(tab_json)); | 71 args.Set(2, Value::CreateStringValue(tab_json)); |
(...skipping 29 matching lines...) Expand all Loading... |
98 ListValue args; | 101 ListValue args; |
99 args.Set(0, Value::CreateStringValue(event_name)); | 102 args.Set(0, Value::CreateStringValue(event_name)); |
100 args.Set(1, Value::CreateStringValue(event_args)); | 103 args.Set(1, Value::CreateStringValue(event_args)); |
101 port.sender->Send(new ViewMsg_ExtensionMessageInvoke(port.routing_id, | 104 port.sender->Send(new ViewMsg_ExtensionMessageInvoke(port.routing_id, |
102 ExtensionMessageService::kDispatchEvent, args, has_incognito_data, | 105 ExtensionMessageService::kDispatchEvent, args, has_incognito_data, |
103 event_url)); | 106 event_url)); |
104 } | 107 } |
105 | 108 |
106 } // namespace | 109 } // namespace |
107 | 110 |
108 const char ExtensionMessageService::kDispatchOnConnect[] = | |
109 "Port.dispatchOnConnect"; | |
110 const char ExtensionMessageService::kDispatchOnDisconnect[] = | |
111 "Port.dispatchOnDisconnect"; | |
112 const char ExtensionMessageService::kDispatchOnMessage[] = | |
113 "Port.dispatchOnMessage"; | |
114 const char ExtensionMessageService::kDispatchEvent[] = | |
115 "Event.dispatchJSON"; | |
116 | |
117 // static | 111 // static |
118 std::string ExtensionMessageService::GetPerExtensionEventName( | 112 std::string ExtensionMessageService::GetPerExtensionEventName( |
119 const std::string& event_name, const std::string& extension_id) { | 113 const std::string& event_name, const std::string& extension_id) { |
120 // This should match the method we use in extension_process_binding.js when | 114 // This should match the method we use in extension_process_binding.js when |
121 // setting up the corresponding chrome.Event object. | 115 // setting up the corresponding chrome.Event object. |
122 return event_name + "/" + extension_id; | 116 return event_name + "/" + extension_id; |
123 } | 117 } |
124 | 118 |
| 119 // static |
| 120 void ExtensionMessageService::AllocatePortIdPair(int* port1, int* port2) { |
| 121 int channel_id = g_next_channel_id.GetNext(); |
| 122 int port1_id = channel_id * 2; |
| 123 int port2_id = channel_id * 2 + 1; |
| 124 |
| 125 // Sanity checks to make sure our channel<->port converters are correct. |
| 126 DCHECK(IS_OPENER_PORT_ID(port1_id)); |
| 127 DCHECK(GET_OPPOSITE_PORT_ID(port1_id) == port2_id); |
| 128 DCHECK(GET_OPPOSITE_PORT_ID(port2_id) == port1_id); |
| 129 DCHECK(GET_CHANNEL_ID(port1_id) == GET_CHANNEL_ID(port2_id)); |
| 130 DCHECK(GET_CHANNEL_ID(port1_id) == channel_id); |
| 131 DCHECK(GET_CHANNEL_OPENER_ID(channel_id) == port1_id); |
| 132 DCHECK(GET_CHANNEL_RECEIVERS_ID(channel_id) == port2_id); |
| 133 |
| 134 *port1 = port1_id; |
| 135 *port2 = port2_id; |
| 136 } |
| 137 |
125 ExtensionMessageService::ExtensionMessageService(Profile* profile) | 138 ExtensionMessageService::ExtensionMessageService(Profile* profile) |
126 : profile_(profile), | 139 : profile_(profile), |
127 extension_devtools_manager_(NULL), | 140 extension_devtools_manager_(NULL) { |
128 next_port_id_(0) { | |
129 registrar_.Add(this, NotificationType::RENDERER_PROCESS_TERMINATED, | 141 registrar_.Add(this, NotificationType::RENDERER_PROCESS_TERMINATED, |
130 NotificationService::AllSources()); | 142 NotificationService::AllSources()); |
131 registrar_.Add(this, NotificationType::RENDERER_PROCESS_CLOSED, | 143 registrar_.Add(this, NotificationType::RENDERER_PROCESS_CLOSED, |
132 NotificationService::AllSources()); | 144 NotificationService::AllSources()); |
133 registrar_.Add(this, NotificationType::RENDER_VIEW_HOST_DELETED, | 145 registrar_.Add(this, NotificationType::RENDER_VIEW_HOST_DELETED, |
134 NotificationService::AllSources()); | 146 NotificationService::AllSources()); |
135 | 147 |
136 extension_devtools_manager_ = profile_->GetExtensionDevToolsManager(); | 148 extension_devtools_manager_ = profile_->GetExtensionDevToolsManager(); |
137 } | 149 } |
138 | 150 |
139 ExtensionMessageService::~ExtensionMessageService() { | 151 ExtensionMessageService::~ExtensionMessageService() { |
140 STLDeleteContainerPairSecondPointers(channels_.begin(), channels_.end()); | 152 STLDeleteContainerPairSecondPointers(channels_.begin(), channels_.end()); |
141 channels_.clear(); | 153 channels_.clear(); |
142 } | 154 } |
143 | 155 |
144 void ExtensionMessageService::ProfileDestroyed() { | 156 void ExtensionMessageService::ProfileDestroyed() { |
145 profile_ = NULL; | 157 profile_ = NULL; |
146 if (!registrar_.IsEmpty()) { | 158 if (!registrar_.IsEmpty()) |
147 CHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | |
148 registrar_.RemoveAll(); | 159 registrar_.RemoveAll(); |
149 } | |
150 } | 160 } |
151 | 161 |
152 void ExtensionMessageService::AddEventListener(const std::string& event_name, | 162 void ExtensionMessageService::AddEventListener(const std::string& event_name, |
153 int render_process_id) { | 163 int render_process_id) { |
154 // It is possible that this RenderProcessHost is being destroyed. If that is | 164 // It is possible that this RenderProcessHost is being destroyed. If that is |
155 // the case, we'll have already removed his listeners, so do nothing here. | 165 // the case, we'll have already removed his listeners, so do nothing here. |
156 RenderProcessHost* rph = RenderProcessHost::FromID(render_process_id); | 166 RenderProcessHost* rph = RenderProcessHost::FromID(render_process_id); |
157 if (!rph || rph->ListenersIterator().IsAtEnd()) | 167 if (!rph || rph->ListenersIterator().IsAtEnd()) |
158 return; | 168 return; |
159 | 169 |
160 DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI); | |
161 DCHECK_EQ(listeners_[event_name].count(render_process_id), 0u) << event_name; | 170 DCHECK_EQ(listeners_[event_name].count(render_process_id), 0u) << event_name; |
162 listeners_[event_name].insert(render_process_id); | 171 listeners_[event_name].insert(render_process_id); |
163 | 172 |
164 if (extension_devtools_manager_.get()) { | 173 if (extension_devtools_manager_.get()) { |
165 extension_devtools_manager_->AddEventListener(event_name, | 174 extension_devtools_manager_->AddEventListener(event_name, |
166 render_process_id); | 175 render_process_id); |
167 } | 176 } |
168 } | 177 } |
169 | 178 |
170 void ExtensionMessageService::RemoveEventListener(const std::string& event_name, | 179 void ExtensionMessageService::RemoveEventListener(const std::string& event_name, |
171 int render_process_id) { | 180 int render_process_id) { |
172 // The RenderProcessHost may be destroyed. See AddEventListener. | 181 // The RenderProcessHost may be destroyed. See AddEventListener. |
173 RenderProcessHost* rph = RenderProcessHost::FromID(render_process_id); | 182 RenderProcessHost* rph = RenderProcessHost::FromID(render_process_id); |
174 if (!rph || rph->ListenersIterator().IsAtEnd()) | 183 if (!rph || rph->ListenersIterator().IsAtEnd()) |
175 return; | 184 return; |
176 | 185 |
177 DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI); | |
178 DCHECK_EQ(listeners_[event_name].count(render_process_id), 1u) | 186 DCHECK_EQ(listeners_[event_name].count(render_process_id), 1u) |
179 << " PID=" << render_process_id << " event=" << event_name; | 187 << " PID=" << render_process_id << " event=" << event_name; |
180 listeners_[event_name].erase(render_process_id); | 188 listeners_[event_name].erase(render_process_id); |
181 | 189 |
182 if (extension_devtools_manager_.get()) { | 190 if (extension_devtools_manager_.get()) { |
183 extension_devtools_manager_->RemoveEventListener(event_name, | 191 extension_devtools_manager_->RemoveEventListener(event_name, |
184 render_process_id); | 192 render_process_id); |
185 } | 193 } |
186 } | 194 } |
187 | 195 |
188 bool ExtensionMessageService::HasEventListener( | 196 bool ExtensionMessageService::HasEventListener( |
189 const std::string& event_name) { | 197 const std::string& event_name) { |
190 return (listeners_.find(event_name) != listeners_.end() && | 198 return (listeners_.find(event_name) != listeners_.end() && |
191 !listeners_[event_name].empty()); | 199 !listeners_[event_name].empty()); |
192 } | 200 } |
193 | 201 |
194 void ExtensionMessageService::AllocatePortIdPair(int* port1, int* port2) { | 202 void ExtensionMessageService::OpenChannelToExtension( |
195 AutoLock lock(next_port_id_lock_); | |
196 | |
197 // TODO(mpcomplete): what happens when this wraps? | |
198 int port1_id = next_port_id_++; | |
199 int port2_id = next_port_id_++; | |
200 | |
201 DCHECK(IS_OPENER_PORT_ID(port1_id)); | |
202 DCHECK(GET_OPPOSITE_PORT_ID(port1_id) == port2_id); | |
203 DCHECK(GET_OPPOSITE_PORT_ID(port2_id) == port1_id); | |
204 DCHECK(GET_CHANNEL_ID(port1_id) == GET_CHANNEL_ID(port2_id)); | |
205 | |
206 int channel_id = GET_CHANNEL_ID(port1_id); | |
207 DCHECK(GET_CHANNEL_OPENER_ID(channel_id) == port1_id); | |
208 DCHECK(GET_CHANNEL_RECEIVERS_ID(channel_id) == port2_id); | |
209 | |
210 *port1 = port1_id; | |
211 *port2 = port2_id; | |
212 } | |
213 | |
214 int ExtensionMessageService::OpenChannelToExtension( | |
215 int routing_id, const std::string& source_extension_id, | |
216 const std::string& target_extension_id, | |
217 const std::string& channel_name, ResourceMessageFilter* source) { | |
218 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); | |
219 | |
220 // Create a channel ID for both sides of the channel. | |
221 int port1_id = -1; | |
222 int port2_id = -1; | |
223 AllocatePortIdPair(&port1_id, &port2_id); | |
224 | |
225 // Each side of the port is given his own port ID. When they send messages, | |
226 // we convert to the opposite port ID. See PostMessageFromRenderer. | |
227 ChromeThread::PostTask( | |
228 ChromeThread::UI, FROM_HERE, | |
229 NewRunnableMethod( | |
230 this, &ExtensionMessageService::OpenChannelToExtensionOnUIThread, | |
231 source->id(), routing_id, port2_id, source_extension_id, | |
232 target_extension_id, channel_name)); | |
233 | |
234 return port1_id; | |
235 } | |
236 | |
237 int ExtensionMessageService::OpenChannelToTab(int routing_id, | |
238 int tab_id, | |
239 const std::string& extension_id, | |
240 const std::string& channel_name, | |
241 ResourceMessageFilter* source) { | |
242 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); | |
243 | |
244 // Create a channel ID for both sides of the channel. | |
245 int port1_id = -1; | |
246 int port2_id = -1; | |
247 AllocatePortIdPair(&port1_id, &port2_id); | |
248 | |
249 // Each side of the port is given his own port ID. When they send messages, | |
250 // we convert to the opposite port ID. See PostMessageFromRenderer. | |
251 ChromeThread::PostTask( | |
252 ChromeThread::UI, FROM_HERE, | |
253 NewRunnableMethod( | |
254 this, &ExtensionMessageService::OpenChannelToTabOnUIThread, | |
255 source->id(), routing_id, port2_id, tab_id, extension_id, | |
256 channel_name)); | |
257 | |
258 return port1_id; | |
259 } | |
260 | |
261 void ExtensionMessageService::OpenChannelToExtensionOnUIThread( | |
262 int source_process_id, int source_routing_id, int receiver_port_id, | 203 int source_process_id, int source_routing_id, int receiver_port_id, |
263 const std::string& source_extension_id, | 204 const std::string& source_extension_id, |
264 const std::string& target_extension_id, | 205 const std::string& target_extension_id, |
265 const std::string& channel_name) { | 206 const std::string& channel_name) { |
266 if (!profile_) | 207 if (!profile_) |
267 return; | 208 return; |
268 | 209 |
269 RenderProcessHost* source = RenderProcessHost::FromID(source_process_id); | 210 RenderProcessHost* source = RenderProcessHost::FromID(source_process_id); |
270 if (!source) | 211 if (!source) |
271 return; | 212 return; |
272 | 213 |
273 MessagePort receiver( | 214 MessagePort receiver( |
274 profile_->GetExtensionProcessManager()->GetExtensionProcess( | 215 profile_->GetExtensionProcessManager()->GetExtensionProcess( |
275 target_extension_id), | 216 target_extension_id), |
276 MSG_ROUTING_CONTROL); | 217 MSG_ROUTING_CONTROL); |
277 receiver.debug_info = 1; | |
278 TabContents* source_contents = tab_util::GetTabContentsByID( | 218 TabContents* source_contents = tab_util::GetTabContentsByID( |
279 source_process_id, source_routing_id); | 219 source_process_id, source_routing_id); |
280 | 220 |
281 // Include info about the opener's tab (if it was a tab). | 221 // Include info about the opener's tab (if it was a tab). |
282 std::string tab_json = "null"; | 222 std::string tab_json = "null"; |
283 if (source_contents) { | 223 if (source_contents) { |
284 scoped_ptr<DictionaryValue> tab_value( | 224 scoped_ptr<DictionaryValue> tab_value( |
285 ExtensionTabUtil::CreateTabValue(source_contents)); | 225 ExtensionTabUtil::CreateTabValue(source_contents)); |
286 base::JSONWriter::Write(tab_value.get(), false, &tab_json); | 226 base::JSONWriter::Write(tab_value.get(), false, &tab_json); |
287 } | 227 } |
288 | 228 |
289 OpenChannelOnUIThreadImpl(source, tab_json, | 229 OpenChannelImpl(source, tab_json, receiver, receiver_port_id, |
290 receiver, receiver_port_id, | 230 source_extension_id, target_extension_id, channel_name); |
291 source_extension_id, target_extension_id, | |
292 channel_name); | |
293 } | 231 } |
294 | 232 |
295 void ExtensionMessageService::OpenChannelToTabOnUIThread( | 233 void ExtensionMessageService::OpenChannelToTab( |
296 int source_process_id, int source_routing_id, int receiver_port_id, | 234 int source_process_id, int source_routing_id, int receiver_port_id, |
297 int tab_id, const std::string& extension_id, | 235 int tab_id, const std::string& extension_id, |
298 const std::string& channel_name) { | 236 const std::string& channel_name) { |
299 RenderProcessHost* source = RenderProcessHost::FromID(source_process_id); | 237 RenderProcessHost* source = RenderProcessHost::FromID(source_process_id); |
300 if (!source) | 238 if (!source) |
301 return; | 239 return; |
302 | 240 |
303 TabContents* contents = NULL; | 241 TabContents* contents = NULL; |
304 MessagePort receiver; | 242 MessagePort receiver; |
305 receiver.debug_info = 2; | |
306 if (ExtensionTabUtil::GetTabById(tab_id, source->profile(), true, | 243 if (ExtensionTabUtil::GetTabById(tab_id, source->profile(), true, |
307 NULL, NULL, &contents, NULL)) { | 244 NULL, NULL, &contents, NULL)) { |
308 receiver.sender = contents->render_view_host(); | 245 receiver.sender = contents->render_view_host(); |
309 receiver.routing_id = contents->render_view_host()->routing_id(); | 246 receiver.routing_id = contents->render_view_host()->routing_id(); |
310 receiver.debug_info = 3; | |
311 } | 247 } |
312 | 248 |
313 if (contents && contents->controller().needs_reload()) { | 249 if (contents && contents->controller().needs_reload()) { |
314 // The tab isn't loaded yet (it may be phantom). Don't attempt to connect. | 250 // The tab isn't loaded yet (it may be phantom). Don't attempt to connect. |
315 // Treat this as a disconnect. | 251 // Treat this as a disconnect. |
316 DispatchOnDisconnect(MessagePort(source, MSG_ROUTING_CONTROL), | 252 DispatchOnDisconnect(MessagePort(source, MSG_ROUTING_CONTROL), |
317 GET_OPPOSITE_PORT_ID(receiver_port_id)); | 253 GET_OPPOSITE_PORT_ID(receiver_port_id)); |
318 return; | 254 return; |
319 } | 255 } |
320 | 256 |
321 TabContents* source_contents = tab_util::GetTabContentsByID( | 257 TabContents* source_contents = tab_util::GetTabContentsByID( |
322 source_process_id, source_routing_id); | 258 source_process_id, source_routing_id); |
323 | 259 |
324 // Include info about the opener's tab (if it was a tab). | 260 // Include info about the opener's tab (if it was a tab). |
325 std::string tab_json = "null"; | 261 std::string tab_json = "null"; |
326 if (source_contents) { | 262 if (source_contents) { |
327 scoped_ptr<DictionaryValue> tab_value( | 263 scoped_ptr<DictionaryValue> tab_value( |
328 ExtensionTabUtil::CreateTabValue(source_contents)); | 264 ExtensionTabUtil::CreateTabValue(source_contents)); |
329 base::JSONWriter::Write(tab_value.get(), false, &tab_json); | 265 base::JSONWriter::Write(tab_value.get(), false, &tab_json); |
330 } | 266 } |
331 | 267 |
332 OpenChannelOnUIThreadImpl(source, tab_json, | 268 OpenChannelImpl(source, tab_json, receiver, receiver_port_id, |
333 receiver, receiver_port_id, | 269 extension_id, extension_id, channel_name); |
334 extension_id, extension_id, channel_name); | |
335 } | 270 } |
336 | 271 |
337 bool ExtensionMessageService::OpenChannelOnUIThreadImpl( | 272 bool ExtensionMessageService::OpenChannelImpl( |
338 IPC::Message::Sender* source, | 273 IPC::Message::Sender* source, |
339 const std::string& tab_json, | 274 const std::string& tab_json, |
340 const MessagePort& receiver, int receiver_port_id, | 275 const MessagePort& receiver, int receiver_port_id, |
341 const std::string& source_extension_id, | 276 const std::string& source_extension_id, |
342 const std::string& target_extension_id, | 277 const std::string& target_extension_id, |
343 const std::string& channel_name) { | 278 const std::string& channel_name) { |
344 DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI); | |
345 | |
346 // TODO(mpcomplete): notify source if receiver doesn't exist | 279 // TODO(mpcomplete): notify source if receiver doesn't exist |
347 if (!source) | 280 if (!source) |
348 return false; // Closed while in flight. | 281 return false; // Closed while in flight. |
349 | 282 |
350 if (!receiver.sender) { | 283 if (!receiver.sender) { |
351 // Treat it as a disconnect. | 284 // Treat it as a disconnect. |
352 DispatchOnDisconnect(MessagePort(source, MSG_ROUTING_CONTROL), | 285 DispatchOnDisconnect(MessagePort(source, MSG_ROUTING_CONTROL), |
353 GET_OPPOSITE_PORT_ID(receiver_port_id)); | 286 GET_OPPOSITE_PORT_ID(receiver_port_id)); |
354 return false; | 287 return false; |
355 } | 288 } |
(...skipping 17 matching lines...) Expand all Loading... |
373 // opener has the opposite port ID). | 306 // opener has the opposite port ID). |
374 DispatchOnConnect(receiver, receiver_port_id, channel_name, tab_json, | 307 DispatchOnConnect(receiver, receiver_port_id, channel_name, tab_json, |
375 source_extension_id, target_extension_id); | 308 source_extension_id, target_extension_id); |
376 | 309 |
377 return true; | 310 return true; |
378 } | 311 } |
379 | 312 |
380 int ExtensionMessageService::OpenSpecialChannelToExtension( | 313 int ExtensionMessageService::OpenSpecialChannelToExtension( |
381 const std::string& extension_id, const std::string& channel_name, | 314 const std::string& extension_id, const std::string& channel_name, |
382 const std::string& tab_json, IPC::Message::Sender* source) { | 315 const std::string& tab_json, IPC::Message::Sender* source) { |
383 DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI); | |
384 DCHECK(profile_); | 316 DCHECK(profile_); |
385 | 317 |
386 int port1_id = -1; | 318 int port1_id = -1; |
387 int port2_id = -1; | 319 int port2_id = -1; |
388 // Create a channel ID for both sides of the channel. | 320 // Create a channel ID for both sides of the channel. |
389 AllocatePortIdPair(&port1_id, &port2_id); | 321 AllocatePortIdPair(&port1_id, &port2_id); |
390 | 322 |
391 MessagePort receiver( | 323 MessagePort receiver( |
392 profile_->GetExtensionProcessManager()-> | 324 profile_->GetExtensionProcessManager()-> |
393 GetExtensionProcess(extension_id), | 325 GetExtensionProcess(extension_id), |
394 MSG_ROUTING_CONTROL); | 326 MSG_ROUTING_CONTROL); |
395 receiver.debug_info = 4; | 327 if (!OpenChannelImpl(source, tab_json, receiver, port2_id, |
396 if (!OpenChannelOnUIThreadImpl( | 328 extension_id, extension_id, channel_name)) |
397 source, tab_json, receiver, port2_id, extension_id, extension_id, | |
398 channel_name)) | |
399 return -1; | 329 return -1; |
400 | 330 |
401 return port1_id; | 331 return port1_id; |
402 } | 332 } |
403 | 333 |
404 int ExtensionMessageService::OpenSpecialChannelToTab( | 334 int ExtensionMessageService::OpenSpecialChannelToTab( |
405 const std::string& extension_id, const std::string& channel_name, | 335 const std::string& extension_id, const std::string& channel_name, |
406 TabContents* target_tab_contents, IPC::Message::Sender* source) { | 336 TabContents* target_tab_contents, IPC::Message::Sender* source) { |
407 DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI); | |
408 DCHECK(target_tab_contents); | 337 DCHECK(target_tab_contents); |
409 | 338 |
410 if (target_tab_contents->controller().needs_reload()) { | 339 if (target_tab_contents->controller().needs_reload()) { |
411 // The tab isn't loaded yet (it may be phantom). Don't attempt to connect. | 340 // The tab isn't loaded yet (it may be phantom). Don't attempt to connect. |
412 return -1; | 341 return -1; |
413 } | 342 } |
414 | 343 |
415 int port1_id = -1; | 344 int port1_id = -1; |
416 int port2_id = -1; | 345 int port2_id = -1; |
417 // Create a channel ID for both sides of the channel. | 346 // Create a channel ID for both sides of the channel. |
418 AllocatePortIdPair(&port1_id, &port2_id); | 347 AllocatePortIdPair(&port1_id, &port2_id); |
419 | 348 |
420 MessagePort receiver( | 349 MessagePort receiver( |
421 target_tab_contents->render_view_host(), | 350 target_tab_contents->render_view_host(), |
422 target_tab_contents->render_view_host()->routing_id()); | 351 target_tab_contents->render_view_host()->routing_id()); |
423 receiver.debug_info = 5; | 352 if (!OpenChannelImpl(source, "null", receiver, port2_id, |
424 if (!OpenChannelOnUIThreadImpl(source, "null", | 353 extension_id, extension_id, channel_name)) |
425 receiver, port2_id, | |
426 extension_id, extension_id, channel_name)) | |
427 return -1; | 354 return -1; |
428 | 355 |
429 return port1_id; | 356 return port1_id; |
430 } | 357 } |
431 | 358 |
432 void ExtensionMessageService::CloseChannel(int port_id) { | 359 void ExtensionMessageService::CloseChannel(int port_id) { |
433 DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI); | |
434 | |
435 // Note: The channel might be gone already, if the other side closed first. | 360 // Note: The channel might be gone already, if the other side closed first. |
436 MessageChannelMap::iterator it = channels_.find(GET_CHANNEL_ID(port_id)); | 361 MessageChannelMap::iterator it = channels_.find(GET_CHANNEL_ID(port_id)); |
437 if (it != channels_.end()) | 362 if (it != channels_.end()) |
438 CloseChannelImpl(it, port_id, true); | 363 CloseChannelImpl(it, port_id, true); |
439 } | 364 } |
440 | 365 |
441 void ExtensionMessageService::CloseChannelImpl( | 366 void ExtensionMessageService::CloseChannelImpl( |
442 MessageChannelMap::iterator channel_iter, int closing_port_id, | 367 MessageChannelMap::iterator channel_iter, int closing_port_id, |
443 bool notify_other_port) { | 368 bool notify_other_port) { |
444 DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI); | |
445 | |
446 // Notify the other side. | 369 // Notify the other side. |
447 const MessagePort& port = IS_OPENER_PORT_ID(closing_port_id) ? | 370 const MessagePort& port = IS_OPENER_PORT_ID(closing_port_id) ? |
448 channel_iter->second->receiver : channel_iter->second->opener; | 371 channel_iter->second->receiver : channel_iter->second->opener; |
449 | 372 |
450 if (notify_other_port) | 373 if (notify_other_port) |
451 DispatchOnDisconnect(port, GET_OPPOSITE_PORT_ID(closing_port_id)); | 374 DispatchOnDisconnect(port, GET_OPPOSITE_PORT_ID(closing_port_id)); |
452 delete channel_iter->second; | 375 delete channel_iter->second; |
453 channels_.erase(channel_iter); | 376 channels_.erase(channel_iter); |
454 } | 377 } |
455 | 378 |
456 void ExtensionMessageService::PostMessageFromRenderer( | 379 void ExtensionMessageService::PostMessageFromRenderer( |
457 int source_port_id, const std::string& message) { | 380 int source_port_id, const std::string& message) { |
458 DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI); | |
459 | |
460 MessageChannelMap::iterator iter = | 381 MessageChannelMap::iterator iter = |
461 channels_.find(GET_CHANNEL_ID(source_port_id)); | 382 channels_.find(GET_CHANNEL_ID(source_port_id)); |
462 if (iter == channels_.end()) | 383 if (iter == channels_.end()) |
463 return; | 384 return; |
464 | 385 |
465 // Figure out which port the ID corresponds to. | 386 // Figure out which port the ID corresponds to. |
466 int dest_port_id = GET_OPPOSITE_PORT_ID(source_port_id); | 387 int dest_port_id = GET_OPPOSITE_PORT_ID(source_port_id); |
467 const MessagePort& port = IS_OPENER_PORT_ID(dest_port_id) ? | 388 const MessagePort& port = IS_OPENER_PORT_ID(dest_port_id) ? |
468 iter->second->opener : iter->second->receiver; | 389 iter->second->opener : iter->second->receiver; |
469 | 390 |
470 DispatchOnMessage(port, message, dest_port_id); | 391 DispatchOnMessage(port, message, dest_port_id); |
471 } | 392 } |
472 | 393 |
473 void ExtensionMessageService::DispatchEventToRenderers( | 394 void ExtensionMessageService::DispatchEventToRenderers( |
474 const std::string& event_name, const std::string& event_args, | 395 const std::string& event_name, const std::string& event_args, |
475 bool has_incognito_data, const GURL& event_url) { | 396 bool has_incognito_data, const GURL& event_url) { |
476 DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI); | |
477 ListenerMap::iterator it = listeners_.find(event_name); | 397 ListenerMap::iterator it = listeners_.find(event_name); |
478 if (it == listeners_.end()) | 398 if (it == listeners_.end()) |
479 return; | 399 return; |
480 | 400 |
481 std::set<int>& pids = it->second; | 401 std::set<int>& pids = it->second; |
482 | 402 |
483 // Send the event only to renderers that are listening for it. | 403 // Send the event only to renderers that are listening for it. |
484 for (std::set<int>::iterator pid = pids.begin(); pid != pids.end(); ++pid) { | 404 for (std::set<int>::iterator pid = pids.begin(); pid != pids.end(); ++pid) { |
485 RenderProcessHost* renderer = RenderProcessHost::FromID(*pid); | 405 RenderProcessHost* renderer = RenderProcessHost::FromID(*pid); |
486 if (!renderer) | 406 if (!renderer) |
(...skipping 13 matching lines...) Expand all Loading... |
500 const std::string& extension_id, | 420 const std::string& extension_id, |
501 const std::string& event_name, const std::string& event_args, | 421 const std::string& event_name, const std::string& event_args, |
502 bool has_incognito_data, const GURL& event_url) { | 422 bool has_incognito_data, const GURL& event_url) { |
503 DispatchEventToRenderers(GetPerExtensionEventName(event_name, extension_id), | 423 DispatchEventToRenderers(GetPerExtensionEventName(event_name, extension_id), |
504 event_args, has_incognito_data, event_url); | 424 event_args, has_incognito_data, event_url); |
505 } | 425 } |
506 | 426 |
507 void ExtensionMessageService::Observe(NotificationType type, | 427 void ExtensionMessageService::Observe(NotificationType type, |
508 const NotificationSource& source, | 428 const NotificationSource& source, |
509 const NotificationDetails& details) { | 429 const NotificationDetails& details) { |
510 DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI); | |
511 | |
512 switch (type.value) { | 430 switch (type.value) { |
513 case NotificationType::RENDERER_PROCESS_TERMINATED: | 431 case NotificationType::RENDERER_PROCESS_TERMINATED: |
514 case NotificationType::RENDERER_PROCESS_CLOSED: { | 432 case NotificationType::RENDERER_PROCESS_CLOSED: { |
515 RenderProcessHost* renderer = Source<RenderProcessHost>(source).ptr(); | 433 RenderProcessHost* renderer = Source<RenderProcessHost>(source).ptr(); |
516 OnSenderClosed(renderer); | 434 OnSenderClosed(renderer); |
517 | 435 |
518 // Remove all event listeners associated with this renderer | 436 // Remove all event listeners associated with this renderer |
519 for (ListenerMap::iterator it = listeners_.begin(); | 437 for (ListenerMap::iterator it = listeners_.begin(); |
520 it != listeners_.end(); ) { | 438 it != listeners_.end(); ) { |
521 ListenerMap::iterator current = it++; | 439 ListenerMap::iterator current = it++; |
522 if (current->second.count(renderer->id()) != 0) | 440 if (current->second.count(renderer->id()) != 0) |
523 RemoveEventListener(current->first, renderer->id()); | 441 RemoveEventListener(current->first, renderer->id()); |
524 } | 442 } |
525 break; | 443 break; |
526 } | 444 } |
527 case NotificationType::RENDER_VIEW_HOST_DELETED: | 445 case NotificationType::RENDER_VIEW_HOST_DELETED: |
528 OnSenderClosed(Details<RenderViewHost>(details).ptr()); | 446 OnSenderClosed(Details<RenderViewHost>(details).ptr()); |
529 break; | 447 break; |
530 | |
531 // We should already have removed this guy from our channel map by this | |
532 // point. | |
533 case NotificationType::EXTENSION_PORT_DELETED_DEBUG: { | |
534 IPC::Message::Sender* sender = | |
535 Details<IPC::Message::Sender>(details).ptr(); | |
536 for (MessageChannelMap::iterator it = channels_.begin(); | |
537 it != channels_.end(); ) { | |
538 MessageChannelMap::iterator current = it++; | |
539 int debug_info = current->second->receiver.debug_info; | |
540 if (current->second->opener.sender == sender) { | |
541 LOG(FATAL) << "Shouldn't happen:" << debug_info; | |
542 } else if (current->second->receiver.sender == sender) { | |
543 LOG(FATAL) << "Shouldn't happen either: " << debug_info; | |
544 } | |
545 } | |
546 OnSenderClosed(sender); | |
547 break; | |
548 } | |
549 | |
550 default: | 448 default: |
551 NOTREACHED(); | 449 NOTREACHED(); |
552 return; | 450 return; |
553 } | 451 } |
554 } | 452 } |
555 | 453 |
556 void ExtensionMessageService::OnSenderClosed(IPC::Message::Sender* sender) { | 454 void ExtensionMessageService::OnSenderClosed(IPC::Message::Sender* sender) { |
557 // Close any channels that share this renderer. We notify the opposite | 455 // Close any channels that share this renderer. We notify the opposite |
558 // port that his pair has closed. | 456 // port that his pair has closed. |
559 for (MessageChannelMap::iterator it = channels_.begin(); | 457 for (MessageChannelMap::iterator it = channels_.begin(); |
560 it != channels_.end(); ) { | 458 it != channels_.end(); ) { |
561 MessageChannelMap::iterator current = it++; | 459 MessageChannelMap::iterator current = it++; |
562 // If both sides are the same renderer, and it is closing, there is no | 460 // If both sides are the same renderer, and it is closing, there is no |
563 // "other" port, so there's no need to notify it. | 461 // "other" port, so there's no need to notify it. |
564 int debug_info = current->second->receiver.debug_info; | |
565 bool debug_check = debug_info == 4 || debug_info == 5; | |
566 bool notify_other_port = | 462 bool notify_other_port = |
567 current->second->opener.sender != current->second->receiver.sender || | 463 current->second->opener.sender != current->second->receiver.sender; |
568 debug_check; | |
569 | 464 |
570 if (current->second->opener.sender == sender) { | 465 if (current->second->opener.sender == sender) { |
571 CloseChannelImpl(current, GET_CHANNEL_OPENER_ID(current->first), | 466 CloseChannelImpl(current, GET_CHANNEL_OPENER_ID(current->first), |
572 notify_other_port); | 467 notify_other_port); |
573 } else if (current->second->receiver.sender == sender) { | 468 } else if (current->second->receiver.sender == sender) { |
574 CloseChannelImpl(current, GET_CHANNEL_RECEIVERS_ID(current->first), | 469 CloseChannelImpl(current, GET_CHANNEL_RECEIVERS_ID(current->first), |
575 notify_other_port); | 470 notify_other_port); |
576 } | 471 } |
577 } | 472 } |
578 } | 473 } |
OLD | NEW |