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

Side by Side Diff: chrome/browser/extensions/api/messaging/message_service.cc

Issue 10990064: Revert 156678 - Native messaging now uses the MessageService back-end. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 8 years, 2 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/api/messaging/message_service.h" 5 #include "chrome/browser/extensions/api/messaging/message_service.h"
6 6
7 #include "base/atomic_sequence_num.h" 7 #include "base/atomic_sequence_num.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/callback.h" 9 #include "base/callback.h"
10 #include "base/json/json_writer.h" 10 #include "base/json/json_writer.h"
11 #include "base/stl_util.h" 11 #include "base/stl_util.h"
12 #include "base/values.h" 12 #include "base/values.h"
13 #include "chrome/browser/extensions/api/messaging/extension_message_port.h"
14 #include "chrome/browser/extensions/api/messaging/native_message_port.h"
15 #include "chrome/browser/extensions/extension_host.h" 13 #include "chrome/browser/extensions/extension_host.h"
16 #include "chrome/browser/extensions/extension_process_manager.h" 14 #include "chrome/browser/extensions/extension_process_manager.h"
17 #include "chrome/browser/extensions/extension_service.h" 15 #include "chrome/browser/extensions/extension_service.h"
18 #include "chrome/browser/extensions/extension_system.h" 16 #include "chrome/browser/extensions/extension_system.h"
19 #include "chrome/browser/extensions/extension_tab_util.h" 17 #include "chrome/browser/extensions/extension_tab_util.h"
20 #include "chrome/browser/extensions/lazy_background_task_queue.h" 18 #include "chrome/browser/extensions/lazy_background_task_queue.h"
21 #include "chrome/browser/extensions/process_map.h" 19 #include "chrome/browser/extensions/process_map.h"
22 #include "chrome/browser/profiles/profile.h" 20 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/browser/tab_contents/tab_util.h" 21 #include "chrome/browser/tab_contents/tab_util.h"
24 #include "chrome/browser/ui/tab_contents/tab_contents.h" 22 #include "chrome/browser/ui/tab_contents/tab_contents.h"
25 #include "chrome/common/chrome_notification_types.h" 23 #include "chrome/common/chrome_notification_types.h"
26 #include "chrome/common/extensions/extension.h" 24 #include "chrome/common/extensions/extension.h"
27 #include "chrome/common/extensions/extension_messages.h" 25 #include "chrome/common/extensions/extension_messages.h"
28 #include "chrome/common/view_type.h" 26 #include "chrome/common/view_type.h"
29 #include "content/public/browser/browser_thread.h"
30 #include "content/public/browser/notification_service.h" 27 #include "content/public/browser/notification_service.h"
31 #include "content/public/browser/render_process_host.h" 28 #include "content/public/browser/render_process_host.h"
32 #include "content/public/browser/render_view_host.h" 29 #include "content/public/browser/render_view_host.h"
33 #include "content/public/browser/site_instance.h" 30 #include "content/public/browser/site_instance.h"
34 #include "content/public/browser/web_contents.h" 31 #include "content/public/browser/web_contents.h"
35 32
36 using content::SiteInstance; 33 using content::SiteInstance;
37 using content::WebContents; 34 using content::WebContents;
38 35
39 // Since we have 2 ports for every channel, we just index channels by half the 36 // Since we have 2 ports for every channel, we just index channels by half the
40 // port ID. 37 // port ID.
41 #define GET_CHANNEL_ID(port_id) ((port_id) / 2) 38 #define GET_CHANNEL_ID(port_id) ((port_id) / 2)
42 #define GET_CHANNEL_OPENER_ID(channel_id) ((channel_id) * 2) 39 #define GET_CHANNEL_OPENER_ID(channel_id) ((channel_id) * 2)
43 #define GET_CHANNEL_RECEIVERS_ID(channel_id) ((channel_id) * 2 + 1) 40 #define GET_CHANNEL_RECEIVERS_ID(channel_id) ((channel_id) * 2 + 1)
44 41
45 // Port1 is always even, port2 is always odd. 42 // Port1 is always even, port2 is always odd.
46 #define IS_OPENER_PORT_ID(port_id) (((port_id) & 1) == 0) 43 #define IS_OPENER_PORT_ID(port_id) (((port_id) & 1) == 0)
47 44
48 // Change even to odd and vice versa, to get the other side of a given channel. 45 // Change even to odd and vice versa, to get the other side of a given channel.
49 #define GET_OPPOSITE_PORT_ID(source_port_id) ((source_port_id) ^ 1) 46 #define GET_OPPOSITE_PORT_ID(source_port_id) ((source_port_id) ^ 1)
50 47
51 namespace extensions { 48 namespace extensions {
52 49
50 struct MessageService::MessagePort {
51 content::RenderProcessHost* process;
52 int routing_id;
53 std::string extension_id;
54 void* background_host_ptr; // used in IncrementLazyKeepaliveCount
55
56 MessagePort()
57 : process(NULL),
58 routing_id(MSG_ROUTING_CONTROL),
59 background_host_ptr(NULL) {}
60 MessagePort(content::RenderProcessHost* process,
61 int routing_id,
62 const std::string& extension_id)
63 : process(process),
64 routing_id(routing_id),
65 extension_id(extension_id),
66 background_host_ptr(NULL) {}
67 };
68
53 struct MessageService::MessageChannel { 69 struct MessageService::MessageChannel {
54 scoped_ptr<MessagePort> opener; 70 MessageService::MessagePort opener;
55 scoped_ptr<MessagePort> receiver; 71 MessageService::MessagePort receiver;
56 }; 72 };
57 73
58 struct MessageService::OpenChannelParams { 74 struct MessageService::OpenChannelParams {
59 content::RenderProcessHost* source; 75 content::RenderProcessHost* source;
60 std::string tab_json; 76 std::string tab_json;
61 scoped_ptr<MessagePort> receiver; 77 MessagePort receiver;
62 int receiver_port_id; 78 int receiver_port_id;
63 std::string source_extension_id; 79 std::string source_extension_id;
64 std::string target_extension_id; 80 std::string target_extension_id;
65 std::string channel_name; 81 std::string channel_name;
66 82
67 // Takes ownership of receiver.
68 OpenChannelParams(content::RenderProcessHost* source, 83 OpenChannelParams(content::RenderProcessHost* source,
69 const std::string& tab_json, 84 const std::string& tab_json,
70 MessagePort* receiver, 85 const MessagePort& receiver,
71 int receiver_port_id, 86 int receiver_port_id,
72 const std::string& source_extension_id, 87 const std::string& source_extension_id,
73 const std::string& target_extension_id, 88 const std::string& target_extension_id,
74 const std::string& channel_name) 89 const std::string& channel_name)
75 : source(source), 90 : source(source),
76 tab_json(tab_json), 91 tab_json(tab_json),
77 receiver(receiver), 92 receiver(receiver),
78 receiver_port_id(receiver_port_id), 93 receiver_port_id(receiver_port_id),
79 source_extension_id(source_extension_id), 94 source_extension_id(source_extension_id),
80 target_extension_id(target_extension_id), 95 target_extension_id(target_extension_id),
81 channel_name(channel_name) {} 96 channel_name(channel_name) {}
82 }; 97 };
83 98
84 namespace { 99 namespace {
85 100
86 static base::StaticAtomicSequenceNumber g_next_channel_id; 101 static base::StaticAtomicSequenceNumber g_next_channel_id;
87 102
103 static void DispatchOnConnect(const MessageService::MessagePort& port,
104 int dest_port_id,
105 const std::string& channel_name,
106 const std::string& tab_json,
107 const std::string& source_extension_id,
108 const std::string& target_extension_id) {
109 port.process->Send(new ExtensionMsg_DispatchOnConnect(
110 port.routing_id, dest_port_id, channel_name,
111 tab_json, source_extension_id, target_extension_id));
112 }
113
114 static void DispatchOnDisconnect(const MessageService::MessagePort& port,
115 int source_port_id,
116 bool connection_error) {
117 port.process->Send(new ExtensionMsg_DispatchOnDisconnect(
118 port.routing_id, source_port_id, connection_error));
119 }
120
121 static void DispatchOnMessage(const MessageService::MessagePort& port,
122 const std::string& message,
123 int target_port_id) {
124 port.process->Send(new ExtensionMsg_DeliverMessage(
125 port.routing_id, target_port_id, message));
126 }
127
88 static content::RenderProcessHost* GetExtensionProcess( 128 static content::RenderProcessHost* GetExtensionProcess(
89 Profile* profile, const std::string& extension_id) { 129 Profile* profile, const std::string& extension_id) {
90 SiteInstance* site_instance = 130 SiteInstance* site_instance =
91 profile->GetExtensionProcessManager()->GetSiteInstanceForURL( 131 profile->GetExtensionProcessManager()->GetSiteInstanceForURL(
92 Extension::GetBaseURLFromExtensionId(extension_id)); 132 Extension::GetBaseURLFromExtensionId(extension_id));
93 133
94 if (!site_instance->HasProcess()) 134 if (!site_instance->HasProcess())
95 return NULL; 135 return NULL;
96 136
97 return site_instance->GetProcess(); 137 return site_instance->GetProcess();
98 } 138 }
99 139
140 static void IncrementLazyKeepaliveCount(MessageService::MessagePort* port) {
141 Profile* profile =
142 Profile::FromBrowserContext(port->process->GetBrowserContext());
143 ExtensionProcessManager* pm =
144 ExtensionSystem::Get(profile)->process_manager();
145 ExtensionHost* host = pm->GetBackgroundHostForExtension(port->extension_id);
146 if (host && host->extension()->has_lazy_background_page())
147 pm->IncrementLazyKeepaliveCount(host->extension());
148
149 // Keep track of the background host, so when we decrement, we only do so if
150 // the host hasn't reloaded.
151 port->background_host_ptr = host;
152 }
153
154 static void DecrementLazyKeepaliveCount(MessageService::MessagePort* port) {
155 Profile* profile =
156 Profile::FromBrowserContext(port->process->GetBrowserContext());
157 ExtensionProcessManager* pm =
158 ExtensionSystem::Get(profile)->process_manager();
159 ExtensionHost* host = pm->GetBackgroundHostForExtension(port->extension_id);
160 if (host && host == port->background_host_ptr)
161 pm->DecrementLazyKeepaliveCount(host->extension());
162 }
163
100 } // namespace 164 } // namespace
101 165
102 content::RenderProcessHost*
103 MessageService::MessagePort::GetRenderProcessHost() {
104 return NULL;
105 }
106
107 // static 166 // static
108 void MessageService::AllocatePortIdPair(int* port1, int* port2) { 167 void MessageService::AllocatePortIdPair(int* port1, int* port2) {
109 int channel_id = g_next_channel_id.GetNext(); 168 int channel_id = g_next_channel_id.GetNext();
110 int port1_id = channel_id * 2; 169 int port1_id = channel_id * 2;
111 int port2_id = channel_id * 2 + 1; 170 int port2_id = channel_id * 2 + 1;
112 171
113 // Sanity checks to make sure our channel<->port converters are correct. 172 // Sanity checks to make sure our channel<->port converters are correct.
114 DCHECK(IS_OPENER_PORT_ID(port1_id)); 173 DCHECK(IS_OPENER_PORT_ID(port1_id));
115 DCHECK(GET_OPPOSITE_PORT_ID(port1_id) == port2_id); 174 DCHECK(GET_OPPOSITE_PORT_ID(port1_id) == port2_id);
116 DCHECK(GET_OPPOSITE_PORT_ID(port2_id) == port1_id); 175 DCHECK(GET_OPPOSITE_PORT_ID(port2_id) == port1_id);
117 DCHECK(GET_CHANNEL_ID(port1_id) == GET_CHANNEL_ID(port2_id)); 176 DCHECK(GET_CHANNEL_ID(port1_id) == GET_CHANNEL_ID(port2_id));
118 DCHECK(GET_CHANNEL_ID(port1_id) == channel_id); 177 DCHECK(GET_CHANNEL_ID(port1_id) == channel_id);
119 DCHECK(GET_CHANNEL_OPENER_ID(channel_id) == port1_id); 178 DCHECK(GET_CHANNEL_OPENER_ID(channel_id) == port1_id);
120 DCHECK(GET_CHANNEL_RECEIVERS_ID(channel_id) == port2_id); 179 DCHECK(GET_CHANNEL_RECEIVERS_ID(channel_id) == port2_id);
121 180
122 *port1 = port1_id; 181 *port1 = port1_id;
123 *port2 = port2_id; 182 *port2 = port2_id;
124 } 183 }
125 184
126 MessageService::MessageService( 185 MessageService::MessageService(
127 LazyBackgroundTaskQueue* queue) 186 LazyBackgroundTaskQueue* queue)
128 : lazy_background_task_queue_(queue), 187 : lazy_background_task_queue_(queue) {
129 weak_factory_(this) {
130 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, 188 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
131 content::NotificationService::AllBrowserContextsAndSources()); 189 content::NotificationService::AllBrowserContextsAndSources());
132 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, 190 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
133 content::NotificationService::AllBrowserContextsAndSources()); 191 content::NotificationService::AllBrowserContextsAndSources());
134 } 192 }
135 193
136 MessageService::~MessageService() { 194 MessageService::~MessageService() {
137 STLDeleteContainerPairSecondPointers(channels_.begin(), channels_.end()); 195 STLDeleteContainerPairSecondPointers(channels_.begin(), channels_.end());
138 channels_.clear(); 196 channels_.clear();
139 } 197 }
140 198
141 void MessageService::OpenChannelToExtension( 199 void MessageService::OpenChannelToExtension(
142 int source_process_id, int source_routing_id, int receiver_port_id, 200 int source_process_id, int source_routing_id, int receiver_port_id,
143 const std::string& source_extension_id, 201 const std::string& source_extension_id,
144 const std::string& target_extension_id, 202 const std::string& target_extension_id,
145 const std::string& channel_name) { 203 const std::string& channel_name) {
146 content::RenderProcessHost* source = 204 content::RenderProcessHost* source =
147 content::RenderProcessHost::FromID(source_process_id); 205 content::RenderProcessHost::FromID(source_process_id);
148 if (!source) 206 if (!source)
149 return; 207 return;
150 Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext()); 208 Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext());
151 209
152 // Note: we use the source's profile here. If the source is an incognito 210 // Note: we use the source's profile here. If the source is an incognito
153 // process, we will use the incognito EPM to find the right extension process, 211 // process, we will use the incognito EPM to find the right extension process,
154 // which depends on whether the extension uses spanning or split mode. 212 // which depends on whether the extension uses spanning or split mode.
155 MessagePort* receiver = new ExtensionMessagePort( 213 MessagePort receiver(GetExtensionProcess(profile, target_extension_id),
156 GetExtensionProcess(profile, target_extension_id), MSG_ROUTING_CONTROL, 214 MSG_ROUTING_CONTROL,
157 target_extension_id); 215 target_extension_id);
158 WebContents* source_contents = tab_util::GetWebContentsByID( 216 WebContents* source_contents = tab_util::GetWebContentsByID(
159 source_process_id, source_routing_id); 217 source_process_id, source_routing_id);
160 218
161 // Include info about the opener's tab (if it was a tab). 219 // Include info about the opener's tab (if it was a tab).
162 std::string tab_json = "null"; 220 std::string tab_json = "null";
163 if (source_contents) { 221 if (source_contents) {
164 scoped_ptr<DictionaryValue> tab_value(ExtensionTabUtil::CreateTabValue( 222 scoped_ptr<DictionaryValue> tab_value(ExtensionTabUtil::CreateTabValue(
165 source_contents, ExtensionTabUtil::INCLUDE_PRIVACY_SENSITIVE_FIELDS)); 223 source_contents, ExtensionTabUtil::INCLUDE_PRIVACY_SENSITIVE_FIELDS));
166 base::JSONWriter::Write(tab_value.get(), &tab_json); 224 base::JSONWriter::Write(tab_value.get(), &tab_json);
167 } 225 }
168 226
169 OpenChannelParams* params = new OpenChannelParams(source, tab_json, receiver, 227 OpenChannelParams params(source, tab_json, receiver, receiver_port_id,
170 receiver_port_id, 228 source_extension_id, target_extension_id,
171 source_extension_id, 229 channel_name);
172 target_extension_id,
173 channel_name);
174 230
175 // The target might be a lazy background page. In that case, we have to check 231 // The target might be a lazy background page. In that case, we have to check
176 // if it is loaded and ready, and if not, queue up the task and load the 232 // if it is loaded and ready, and if not, queue up the task and load the
177 // page. 233 // page.
178 if (MaybeAddPendingOpenChannelTask(profile, params)) { 234 if (MaybeAddPendingOpenChannelTask(profile, params))
179 return;
180 }
181
182 OpenChannelImpl(scoped_ptr<OpenChannelParams>(params));
183 }
184
185 void MessageService::OpenChannelToNativeApp(
186 int source_process_id,
187 int source_routing_id,
188 int receiver_port_id,
189 const std::string& source_extension_id,
190 const std::string& native_app_name,
191 const std::string& channel_name,
192 const std::string& connect_message) {
193 content::RenderProcessHost* source =
194 content::RenderProcessHost::FromID(source_process_id);
195 if (!source)
196 return; 235 return;
197 236
198 WebContents* source_contents = tab_util::GetWebContentsByID( 237 OpenChannelImpl(params);
199 source_process_id, source_routing_id);
200
201 // Include info about the opener's tab (if it was a tab).
202 std::string tab_json = "null";
203 if (source_contents) {
204 scoped_ptr<DictionaryValue> tab_value(ExtensionTabUtil::CreateTabValue(
205 source_contents, ExtensionTabUtil::INCLUDE_PRIVACY_SENSITIVE_FIELDS));
206 base::JSONWriter::Write(tab_value.get(), &tab_json);
207 }
208
209 scoped_ptr<MessageChannel> channel(new MessageChannel());
210 channel->opener.reset(new ExtensionMessagePort(source, MSG_ROUTING_CONTROL,
211 source_extension_id));
212
213 NativeMessageProcessHost::MessageType type =
214 channel_name == "chrome.extension.sendNativeMessage" ?
215 NativeMessageProcessHost::TYPE_SEND_MESSAGE_REQUEST :
216 NativeMessageProcessHost::TYPE_CONNECT;
217
218 content::BrowserThread::PostTask(
219 content::BrowserThread::FILE,
220 FROM_HERE,
221 base::Bind(&NativeMessageProcessHost::Create,
222 base::WeakPtr<NativeMessageProcessHost::Client>(
223 weak_factory_.GetWeakPtr()),
224 native_app_name, connect_message, receiver_port_id,
225 type,
226 base::Bind(&MessageService::FinalizeOpenChannelToNativeApp,
227 weak_factory_.GetWeakPtr(),
228 receiver_port_id,
229 channel_name,
230 base::Passed(&channel),
231 tab_json)));
232 }
233
234 void MessageService::FinalizeOpenChannelToNativeApp(
235 int receiver_port_id,
236 const std::string& channel_name,
237 scoped_ptr<MessageChannel> channel,
238 const std::string& tab_json,
239 NativeMessageProcessHost::ScopedHost native_process) {
240 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
241
242 // Abandon the channel
243 if (!native_process.get()) {
244 LOG(ERROR) << "Failed to create native process.";
245 return;
246 }
247 channel->receiver.reset(new NativeMessagePort(native_process.release()));
248
249 // Keep the opener alive until the channel is closed.
250 channel->opener->IncrementLazyKeepaliveCount();
251
252 AddChannel(channel.release(), receiver_port_id);
253 } 238 }
254 239
255 void MessageService::OpenChannelToTab( 240 void MessageService::OpenChannelToTab(
256 int source_process_id, int source_routing_id, int receiver_port_id, 241 int source_process_id, int source_routing_id, int receiver_port_id,
257 int tab_id, const std::string& extension_id, 242 int tab_id, const std::string& extension_id,
258 const std::string& channel_name) { 243 const std::string& channel_name) {
259 content::RenderProcessHost* source = 244 content::RenderProcessHost* source =
260 content::RenderProcessHost::FromID(source_process_id); 245 content::RenderProcessHost::FromID(source_process_id);
261 if (!source) 246 if (!source)
262 return; 247 return;
263 Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext()); 248 Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext());
264 249
265 TabContents* contents = NULL; 250 TabContents* contents = NULL;
266 scoped_ptr<MessagePort> receiver; 251 MessagePort receiver;
267 if (ExtensionTabUtil::GetTabById(tab_id, profile, true, 252 if (ExtensionTabUtil::GetTabById(tab_id, profile, true,
268 NULL, NULL, &contents, NULL)) { 253 NULL, NULL, &contents, NULL)) {
269 receiver.reset(new ExtensionMessagePort( 254 receiver.process = contents->web_contents()->GetRenderProcessHost();
270 contents->web_contents()->GetRenderProcessHost(), 255 receiver.routing_id =
271 contents->web_contents()->GetRenderViewHost()->GetRoutingID(), 256 contents->web_contents()->GetRenderViewHost()->GetRoutingID();
272 extension_id)); 257 receiver.extension_id = extension_id;
273 } 258 }
274 259
275 if (contents && contents->web_contents()->GetController().NeedsReload()) { 260 if (contents && contents->web_contents()->GetController().NeedsReload()) {
276 // The tab isn't loaded yet. Don't attempt to connect. Treat this as a 261 // The tab isn't loaded yet. Don't attempt to connect. Treat this as a
277 // disconnect. 262 // disconnect.
278 ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, extension_id); 263 DispatchOnDisconnect(MessagePort(source, MSG_ROUTING_CONTROL, extension_id),
279 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(receiver_port_id), true); 264 GET_OPPOSITE_PORT_ID(receiver_port_id), true);
280 return; 265 return;
281 } 266 }
282 267
283 WebContents* source_contents = tab_util::GetWebContentsByID( 268 WebContents* source_contents = tab_util::GetWebContentsByID(
284 source_process_id, source_routing_id); 269 source_process_id, source_routing_id);
285 270
286 // Include info about the opener's tab (if it was a tab). 271 // Include info about the opener's tab (if it was a tab).
287 std::string tab_json = "null"; 272 std::string tab_json = "null";
288 if (source_contents) { 273 if (source_contents) {
289 scoped_ptr<DictionaryValue> tab_value(ExtensionTabUtil::CreateTabValue( 274 scoped_ptr<DictionaryValue> tab_value(ExtensionTabUtil::CreateTabValue(
290 source_contents, ExtensionTabUtil::INCLUDE_PRIVACY_SENSITIVE_FIELDS)); 275 source_contents, ExtensionTabUtil::INCLUDE_PRIVACY_SENSITIVE_FIELDS));
291 base::JSONWriter::Write(tab_value.get(), &tab_json); 276 base::JSONWriter::Write(tab_value.get(), &tab_json);
292 } 277 }
293 278
294 scoped_ptr<OpenChannelParams> params(new OpenChannelParams(source, tab_json, 279 OpenChannelParams params(source, tab_json, receiver, receiver_port_id,
295 receiver.release(), 280 extension_id, extension_id, channel_name);
296 receiver_port_id, 281 OpenChannelImpl(params);
297 extension_id,
298 extension_id,
299 channel_name));
300 OpenChannelImpl(params.Pass());
301 } 282 }
302 283
303 bool MessageService::OpenChannelImpl(scoped_ptr<OpenChannelParams> params) { 284 bool MessageService::OpenChannelImpl(const OpenChannelParams& params) {
304 if (!params->source) 285 if (!params.source)
305 return false; // Closed while in flight. 286 return false; // Closed while in flight.
306 287
307 if (!params->receiver.get() || !params->receiver->GetRenderProcessHost()) { 288 if (!params.receiver.process) {
308 // Treat it as a disconnect. 289 // Treat it as a disconnect.
309 ExtensionMessagePort port(params->source, MSG_ROUTING_CONTROL, ""); 290 DispatchOnDisconnect(MessagePort(params.source, MSG_ROUTING_CONTROL, ""),
310 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(params->receiver_port_id), 291 GET_OPPOSITE_PORT_ID(params.receiver_port_id), true);
311 true);
312 return false; 292 return false;
313 } 293 }
314 294
315 // Add extra paranoid CHECKs, since we have crash reports of this being NULL. 295 // Add extra paranoid CHECKs, since we have crash reports of this being NULL.
316 // http://code.google.com/p/chromium/issues/detail?id=19067 296 // http://code.google.com/p/chromium/issues/detail?id=19067
317 CHECK(params->receiver->GetRenderProcessHost()); 297 CHECK(params.receiver.process);
318 298
319 MessageChannel* channel(new MessageChannel); 299 MessageChannel* channel(new MessageChannel);
320 channel->opener.reset(new ExtensionMessagePort(params->source, 300 channel->opener = MessagePort(params.source, MSG_ROUTING_CONTROL,
321 MSG_ROUTING_CONTROL, 301 params.source_extension_id);
322 params->source_extension_id)); 302 channel->receiver = params.receiver;
323 channel->receiver.reset(params->receiver.release());
324 303
325 CHECK(channel->receiver->GetRenderProcessHost()); 304 CHECK(params.receiver.process);
326 305
327 AddChannel(channel, params->receiver_port_id); 306 int channel_id = GET_CHANNEL_ID(params.receiver_port_id);
307 CHECK(channels_.find(channel_id) == channels_.end());
308 channels_[channel_id] = channel;
309 pending_channels_.erase(channel_id);
328 310
329 CHECK(channel->receiver->GetRenderProcessHost()); 311 CHECK(params.receiver.process);
330 312
331 // Send the connect event to the receiver. Give it the opener's port ID (the 313 // Send the connect event to the receiver. Give it the opener's port ID (the
332 // opener has the opposite port ID). 314 // opener has the opposite port ID).
333 channel->receiver->DispatchOnConnect(params->receiver_port_id, 315 DispatchOnConnect(params.receiver, params.receiver_port_id,
334 params->channel_name, params->tab_json, 316 params.channel_name, params.tab_json,
335 params->source_extension_id, 317 params.source_extension_id, params.target_extension_id);
336 params->target_extension_id);
337 318
338 // Keep both ends of the channel alive until the channel is closed. 319 // Keep both ends of the channel alive until the channel is closed.
339 channel->opener->IncrementLazyKeepaliveCount(); 320 IncrementLazyKeepaliveCount(&channel->opener);
340 channel->receiver->IncrementLazyKeepaliveCount(); 321 IncrementLazyKeepaliveCount(&channel->receiver);
341 return true; 322 return true;
342 } 323 }
343 324
344 void MessageService::AddChannel(MessageChannel* channel, int receiver_port_id) {
345 int channel_id = GET_CHANNEL_ID(receiver_port_id);
346 CHECK(channels_.find(channel_id) == channels_.end());
347 channels_[channel_id] = channel;
348 pending_channels_.erase(channel_id);
349 }
350
351 void MessageService::CloseChannel(int port_id, bool connection_error) { 325 void MessageService::CloseChannel(int port_id, bool connection_error) {
352 // Note: The channel might be gone already, if the other side closed first. 326 // Note: The channel might be gone already, if the other side closed first.
353 int channel_id = GET_CHANNEL_ID(port_id); 327 int channel_id = GET_CHANNEL_ID(port_id);
354 MessageChannelMap::iterator it = channels_.find(channel_id); 328 MessageChannelMap::iterator it = channels_.find(channel_id);
355 if (it == channels_.end()) { 329 if (it == channels_.end()) {
356 PendingChannelMap::iterator pending = pending_channels_.find(channel_id); 330 PendingChannelMap::iterator pending = pending_channels_.find(channel_id);
357 if (pending != pending_channels_.end()) { 331 if (pending != pending_channels_.end()) {
358 lazy_background_task_queue_->AddPendingTask( 332 lazy_background_task_queue_->AddPendingTask(
359 pending->second.first, pending->second.second, 333 pending->second.first, pending->second.second,
360 base::Bind(&MessageService::PendingCloseChannel, 334 base::Bind(&MessageService::PendingCloseChannel,
361 weak_factory_.GetWeakPtr(), port_id, connection_error)); 335 base::Unretained(this), port_id, connection_error));
362 } 336 }
363 return; 337 return;
364 } 338 }
365 CloseChannelImpl(it, port_id, connection_error, true); 339 CloseChannelImpl(it, port_id, connection_error, true);
366 } 340 }
367 341
368 void MessageService::CloseChannelImpl( 342 void MessageService::CloseChannelImpl(
369 MessageChannelMap::iterator channel_iter, int closing_port_id, 343 MessageChannelMap::iterator channel_iter, int closing_port_id,
370 bool connection_error, bool notify_other_port) { 344 bool connection_error, bool notify_other_port) {
371 MessageChannel* channel = channel_iter->second; 345 MessageChannel* channel = channel_iter->second;
372 346
373 // Notify the other side. 347 // Notify the other side.
374 if (notify_other_port) { 348 if (notify_other_port) {
375 MessagePort* port = IS_OPENER_PORT_ID(closing_port_id) ? 349 const MessagePort& port = IS_OPENER_PORT_ID(closing_port_id) ?
376 channel->receiver.get() : channel->opener.get(); 350 channel->receiver : channel->opener;
377 port->DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(closing_port_id), 351 DispatchOnDisconnect(port, GET_OPPOSITE_PORT_ID(closing_port_id),
378 connection_error); 352 connection_error);
379 } 353 }
380 354
381 // Balance the IncrementLazyKeepaliveCount() in OpenChannelImpl. 355 // Balance the addrefs in OpenChannelImpl.
382 channel->opener->DecrementLazyKeepaliveCount(); 356 DecrementLazyKeepaliveCount(&channel->opener);
383 channel->receiver->DecrementLazyKeepaliveCount(); 357 DecrementLazyKeepaliveCount(&channel->receiver);
384 358
385 delete channel_iter->second; 359 delete channel_iter->second;
386 channels_.erase(channel_iter); 360 channels_.erase(channel_iter);
387 } 361 }
388 362
389 void MessageService::PostMessage( 363 void MessageService::PostMessageFromRenderer(
390 int source_port_id, const std::string& message) { 364 int source_port_id, const std::string& message) {
391 int channel_id = GET_CHANNEL_ID(source_port_id); 365 int channel_id = GET_CHANNEL_ID(source_port_id);
392 MessageChannelMap::iterator iter = channels_.find(channel_id); 366 MessageChannelMap::iterator iter = channels_.find(channel_id);
393 if (iter == channels_.end()) { 367 if (iter == channels_.end()) {
394 // If this channel is pending, queue up the PostMessage to run once 368 // If this channel is pending, queue up the PostMessage to run once
395 // the channel opens. 369 // the channel opens.
396 PendingChannelMap::iterator pending = pending_channels_.find(channel_id); 370 PendingChannelMap::iterator pending = pending_channels_.find(channel_id);
397 if (pending != pending_channels_.end()) { 371 if (pending != pending_channels_.end()) {
398 lazy_background_task_queue_->AddPendingTask( 372 lazy_background_task_queue_->AddPendingTask(
399 pending->second.first, pending->second.second, 373 pending->second.first, pending->second.second,
400 base::Bind(&MessageService::PendingPostMessage, 374 base::Bind(&MessageService::PendingPostMessage,
401 weak_factory_.GetWeakPtr(), source_port_id, message)); 375 base::Unretained(this), source_port_id, message));
402 } 376 }
403 return; 377 return;
404 } 378 }
405 379
406 // Figure out which port the ID corresponds to. 380 // Figure out which port the ID corresponds to.
407 int dest_port_id = GET_OPPOSITE_PORT_ID(source_port_id); 381 int dest_port_id = GET_OPPOSITE_PORT_ID(source_port_id);
408 MessagePort* port = IS_OPENER_PORT_ID(dest_port_id) ? 382 const MessagePort& port = IS_OPENER_PORT_ID(dest_port_id) ?
409 iter->second->opener.get() : iter->second->receiver.get(); 383 iter->second->opener : iter->second->receiver;
410 384
411 port->DispatchOnMessage(message, dest_port_id); 385 DispatchOnMessage(port, message, dest_port_id);
412 }
413
414 void MessageService::PostMessageFromNativeProcess(int port_id,
415 const std::string& message) {
416 PostMessage(port_id, message);
417 } 386 }
418 387
419 void MessageService::Observe(int type, 388 void MessageService::Observe(int type,
420 const content::NotificationSource& source, 389 const content::NotificationSource& source,
421 const content::NotificationDetails& details) { 390 const content::NotificationDetails& details) {
422 switch (type) { 391 switch (type) {
423 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: 392 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED:
424 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { 393 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
425 content::RenderProcessHost* renderer = 394 content::RenderProcessHost* renderer =
426 content::Source<content::RenderProcessHost>(source).ptr(); 395 content::Source<content::RenderProcessHost>(source).ptr();
427 OnProcessClosed(renderer); 396 OnProcessClosed(renderer);
428 break; 397 break;
429 } 398 }
430 default: 399 default:
431 NOTREACHED(); 400 NOTREACHED();
432 return; 401 return;
433 } 402 }
434 } 403 }
435 404
436 void MessageService::OnProcessClosed(content::RenderProcessHost* process) { 405 void MessageService::OnProcessClosed(content::RenderProcessHost* process) {
437 // Close any channels that share this renderer. We notify the opposite 406 // Close any channels that share this renderer. We notify the opposite
438 // port that his pair has closed. 407 // port that his pair has closed.
439 for (MessageChannelMap::iterator it = channels_.begin(); 408 for (MessageChannelMap::iterator it = channels_.begin();
440 it != channels_.end(); ) { 409 it != channels_.end(); ) {
441 MessageChannelMap::iterator current = it++; 410 MessageChannelMap::iterator current = it++;
411 // If both sides are the same renderer, and it is closing, there is no
412 // "other" port, so there's no need to notify it.
413 bool notify_other_port =
414 current->second->opener.process != current->second->receiver.process;
442 415
443 content::RenderProcessHost* opener_process = 416 if (current->second->opener.process == process) {
444 current->second->opener->GetRenderProcessHost();
445 content::RenderProcessHost* receiver_process =
446 current->second->receiver->GetRenderProcessHost();
447
448 bool notify_other_port = opener_process &&
449 opener_process == receiver_process;
450
451 if (opener_process == process) {
452 CloseChannelImpl(current, GET_CHANNEL_OPENER_ID(current->first), 417 CloseChannelImpl(current, GET_CHANNEL_OPENER_ID(current->first),
453 false, notify_other_port); 418 false, notify_other_port);
454 } else if (receiver_process == process) { 419 } else if (current->second->receiver.process == process) {
455 CloseChannelImpl(current, GET_CHANNEL_RECEIVERS_ID(current->first), 420 CloseChannelImpl(current, GET_CHANNEL_RECEIVERS_ID(current->first),
456 false, notify_other_port); 421 false, notify_other_port);
457 } 422 }
458 } 423 }
459 } 424 }
460 425
461 bool MessageService::MaybeAddPendingOpenChannelTask( 426 bool MessageService::MaybeAddPendingOpenChannelTask(
462 Profile* profile, 427 Profile* profile,
463 OpenChannelParams* params) { 428 const OpenChannelParams& params) {
464 ExtensionService* service = profile->GetExtensionService(); 429 ExtensionService* service = profile->GetExtensionService();
465 const std::string& extension_id = params->target_extension_id; 430 const std::string& extension_id = params.target_extension_id;
466 const Extension* extension = service->extensions()->GetByID(extension_id); 431 const Extension* extension = service->extensions()->GetByID(
432 extension_id);
467 if (extension && extension->has_lazy_background_page()) { 433 if (extension && extension->has_lazy_background_page()) {
468 // If the extension uses spanning incognito mode, make sure we're always 434 // If the extension uses spanning incognito mode, make sure we're always
469 // using the original profile since that is what the extension process 435 // using the original profile since that is what the extension process
470 // will use. 436 // will use.
471 if (!extension->incognito_split_mode()) 437 if (!extension->incognito_split_mode())
472 profile = profile->GetOriginalProfile(); 438 profile = profile->GetOriginalProfile();
473 439
474 if (lazy_background_task_queue_->ShouldEnqueueTask(profile, extension)) { 440 if (lazy_background_task_queue_->ShouldEnqueueTask(profile, extension)) {
475 pending_channels_[GET_CHANNEL_ID(params->receiver_port_id)] =
476 PendingChannel(profile, extension_id);
477 scoped_ptr<OpenChannelParams> scoped_params(params);
478 lazy_background_task_queue_->AddPendingTask(profile, extension_id, 441 lazy_background_task_queue_->AddPendingTask(profile, extension_id,
479 base::Bind(&MessageService::PendingOpenChannel, 442 base::Bind(&MessageService::PendingOpenChannel,
480 weak_factory_.GetWeakPtr(), base::Passed(&scoped_params), 443 base::Unretained(this), params, params.source->GetID()));
481 params->source->GetID())); 444 pending_channels_[GET_CHANNEL_ID(params.receiver_port_id)] =
445 PendingChannel(profile, extension_id);
482 return true; 446 return true;
483 } 447 }
484 } 448 }
485 449
486 return false; 450 return false;
487 } 451 }
488 452
489 void MessageService::PendingOpenChannel(scoped_ptr<OpenChannelParams> params, 453 void MessageService::PendingOpenChannel(const OpenChannelParams& params_in,
490 int source_process_id, 454 int source_process_id,
491 ExtensionHost* host) { 455 ExtensionHost* host) {
492 if (!host) 456 if (!host)
493 return; // TODO(mpcomplete): notify source of disconnect? 457 return; // TODO(mpcomplete): notify source of disconnect?
494 458
495 // Re-lookup the source process since it may no longer be valid. 459 // Re-lookup the source process since it may no longer be valid.
496 content::RenderProcessHost* source = 460 OpenChannelParams params = params_in;
497 content::RenderProcessHost::FromID(source_process_id); 461 params.source = content::RenderProcessHost::FromID(source_process_id);
498 if (!source) 462 if (!params.source)
499 return; 463 return;
500 464
501 params->source = source; 465 params.receiver = MessagePort(host->render_process_host(),
502 params->receiver.reset(new ExtensionMessagePort(host->render_process_host(), 466 MSG_ROUTING_CONTROL,
503 MSG_ROUTING_CONTROL, 467 params.target_extension_id);
504 params->target_extension_id)); 468 OpenChannelImpl(params);
505 OpenChannelImpl(params.Pass());
506 } 469 }
507 470
508 } // namespace extensions 471 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698