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

Side by Side Diff: chrome/browser/extensions/extension_message_service.cc

Issue 3117024: Clean up ExtensionMessageService. (Closed)
Patch Set: comments fixed Created 10 years, 4 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 (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
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
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
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 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extension_message_service.h ('k') | chrome/browser/renderer_host/browser_render_process_host.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698