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

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

Issue 14301016: Fix a couple of bugs relating to sending Tab info with chrome.runtime.connect and (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add key to app1/manifest.json Created 7 years, 8 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 | Annotate | Revision Log
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"
(...skipping 14 matching lines...) Expand all
25 #include "chrome/common/extensions/background_info.h" 25 #include "chrome/common/extensions/background_info.h"
26 #include "chrome/common/extensions/extension.h" 26 #include "chrome/common/extensions/extension.h"
27 #include "chrome/common/extensions/extension_messages.h" 27 #include "chrome/common/extensions/extension_messages.h"
28 #include "chrome/common/extensions/incognito_handler.h" 28 #include "chrome/common/extensions/incognito_handler.h"
29 #include "content/public/browser/browser_thread.h" 29 #include "content/public/browser/browser_thread.h"
30 #include "content/public/browser/notification_service.h" 30 #include "content/public/browser/notification_service.h"
31 #include "content/public/browser/render_process_host.h" 31 #include "content/public/browser/render_process_host.h"
32 #include "content/public/browser/render_view_host.h" 32 #include "content/public/browser/render_view_host.h"
33 #include "content/public/browser/site_instance.h" 33 #include "content/public/browser/site_instance.h"
34 #include "content/public/browser/web_contents.h" 34 #include "content/public/browser/web_contents.h"
35 #include "googleurl/src/gurl.h"
35 36
36 using content::SiteInstance; 37 using content::SiteInstance;
37 using content::WebContents; 38 using content::WebContents;
38 39
39 // Since we have 2 ports for every channel, we just index channels by half the 40 // Since we have 2 ports for every channel, we just index channels by half the
40 // port ID. 41 // port ID.
41 #define GET_CHANNEL_ID(port_id) ((port_id) / 2) 42 #define GET_CHANNEL_ID(port_id) ((port_id) / 2)
42 #define GET_CHANNEL_OPENER_ID(channel_id) ((channel_id) * 2) 43 #define GET_CHANNEL_OPENER_ID(channel_id) ((channel_id) * 2)
43 #define GET_CHANNEL_RECEIVERS_ID(channel_id) ((channel_id) * 2 + 1) 44 #define GET_CHANNEL_RECEIVERS_ID(channel_id) ((channel_id) * 2 + 1)
44 45
(...skipping 14 matching lines...) Expand all
59 "Native Messaging is not supported on this platform."; 60 "Native Messaging is not supported on this platform.";
60 } 61 }
61 62
62 struct MessageService::MessageChannel { 63 struct MessageService::MessageChannel {
63 scoped_ptr<MessagePort> opener; 64 scoped_ptr<MessagePort> opener;
64 scoped_ptr<MessagePort> receiver; 65 scoped_ptr<MessagePort> receiver;
65 }; 66 };
66 67
67 struct MessageService::OpenChannelParams { 68 struct MessageService::OpenChannelParams {
68 content::RenderProcessHost* source; 69 content::RenderProcessHost* source;
69 std::string tab_json; 70 DictionaryValue source_tab;
70 scoped_ptr<MessagePort> receiver; 71 scoped_ptr<MessagePort> receiver;
71 int receiver_port_id; 72 int receiver_port_id;
72 std::string source_extension_id; 73 std::string source_extension_id;
73 std::string target_extension_id; 74 std::string target_extension_id;
75 GURL source_url;
74 std::string channel_name; 76 std::string channel_name;
75 77
76 // Takes ownership of receiver. 78 // Takes ownership of receiver.
77 OpenChannelParams(content::RenderProcessHost* source, 79 OpenChannelParams(content::RenderProcessHost* source,
78 const std::string& tab_json, 80 scoped_ptr<DictionaryValue> source_tab,
79 MessagePort* receiver, 81 MessagePort* receiver,
80 int receiver_port_id, 82 int receiver_port_id,
81 const std::string& source_extension_id, 83 const std::string& source_extension_id,
82 const std::string& target_extension_id, 84 const std::string& target_extension_id,
85 const GURL& source_url,
83 const std::string& channel_name) 86 const std::string& channel_name)
84 : source(source), 87 : source(source),
85 tab_json(tab_json),
86 receiver(receiver), 88 receiver(receiver),
87 receiver_port_id(receiver_port_id), 89 receiver_port_id(receiver_port_id),
88 source_extension_id(source_extension_id), 90 source_extension_id(source_extension_id),
89 target_extension_id(target_extension_id), 91 target_extension_id(target_extension_id),
90 channel_name(channel_name) {} 92 source_url(source_url),
93 channel_name(channel_name) {
94 if (source_tab)
95 this->source_tab.Swap(source_tab.get());
96 }
97
98 private:
99 DISALLOW_COPY_AND_ASSIGN(OpenChannelParams);
91 }; 100 };
92 101
93 namespace { 102 namespace {
94 103
95 static base::StaticAtomicSequenceNumber g_next_channel_id; 104 static base::StaticAtomicSequenceNumber g_next_channel_id;
96 105
97 static content::RenderProcessHost* GetExtensionProcess( 106 static content::RenderProcessHost* GetExtensionProcess(
98 Profile* profile, const std::string& extension_id) { 107 Profile* profile, const std::string& extension_id) {
99 SiteInstance* site_instance = 108 SiteInstance* site_instance =
100 extensions::ExtensionSystem::Get(profile)->process_manager()-> 109 extensions::ExtensionSystem::Get(profile)->process_manager()->
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 154
146 MessageService::~MessageService() { 155 MessageService::~MessageService() {
147 STLDeleteContainerPairSecondPointers(channels_.begin(), channels_.end()); 156 STLDeleteContainerPairSecondPointers(channels_.begin(), channels_.end());
148 channels_.clear(); 157 channels_.clear();
149 } 158 }
150 159
151 void MessageService::OpenChannelToExtension( 160 void MessageService::OpenChannelToExtension(
152 int source_process_id, int source_routing_id, int receiver_port_id, 161 int source_process_id, int source_routing_id, int receiver_port_id,
153 const std::string& source_extension_id, 162 const std::string& source_extension_id,
154 const std::string& target_extension_id, 163 const std::string& target_extension_id,
164 const GURL& source_url,
155 const std::string& channel_name) { 165 const std::string& channel_name) {
156 content::RenderProcessHost* source = 166 content::RenderProcessHost* source =
157 content::RenderProcessHost::FromID(source_process_id); 167 content::RenderProcessHost::FromID(source_process_id);
158 if (!source) 168 if (!source)
159 return; 169 return;
160 Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext()); 170 Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext());
161 171
172 const Extension* target_extension = ExtensionSystem::Get(profile)->
173 extension_service()->extensions()->GetByID(target_extension_id);
174 if (!target_extension) {
175 // Treat it as a disconnect.
176 ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, std::string());
177 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(receiver_port_id),
178 kReceivingEndDoesntExistError);
179 return;
180 }
181
162 // Note: we use the source's profile here. If the source is an incognito 182 // Note: we use the source's profile here. If the source is an incognito
163 // process, we will use the incognito EPM to find the right extension process, 183 // process, we will use the incognito EPM to find the right extension process,
164 // which depends on whether the extension uses spanning or split mode. 184 // which depends on whether the extension uses spanning or split mode.
165 MessagePort* receiver = new ExtensionMessagePort( 185 MessagePort* receiver = new ExtensionMessagePort(
166 GetExtensionProcess(profile, target_extension_id), MSG_ROUTING_CONTROL, 186 GetExtensionProcess(profile, target_extension_id), MSG_ROUTING_CONTROL,
167 target_extension_id); 187 target_extension_id);
168 WebContents* source_contents = tab_util::GetWebContentsByID( 188 WebContents* source_contents = tab_util::GetWebContentsByID(
169 source_process_id, source_routing_id); 189 source_process_id, source_routing_id);
170 190
171 // Include info about the opener's tab (if it was a tab). 191 // Include info about the opener's tab (if it was a tab).
172 std::string tab_json = "null"; 192 scoped_ptr<DictionaryValue> source_tab;
173 if (source_contents) { 193 GURL source_url_for_tab;
174 scoped_ptr<DictionaryValue> tab_value(ExtensionTabUtil::CreateTabValue( 194
175 source_contents)); 195 if (source_contents && ExtensionTabUtil::GetTabId(source_contents) >= 0) {
176 base::JSONWriter::Write(tab_value.get(), &tab_json); 196 // Platform apps can be sent messages, but don't have a Tab concept.
197 if (!target_extension->is_platform_app())
198 source_tab.reset(ExtensionTabUtil::CreateTabValue(source_contents));
199 source_url_for_tab = source_url;
177 } 200 }
178 201
179 OpenChannelParams* params = new OpenChannelParams(source, tab_json, receiver, 202 OpenChannelParams* params = new OpenChannelParams(source,
203 source_tab.Pass(),
204 receiver,
180 receiver_port_id, 205 receiver_port_id,
181 source_extension_id, 206 source_extension_id,
182 target_extension_id, 207 target_extension_id,
208 source_url_for_tab,
183 channel_name); 209 channel_name);
184 210
185 // The target might be a lazy background page. In that case, we have to check 211 // The target might be a lazy background page. In that case, we have to check
186 // if it is loaded and ready, and if not, queue up the task and load the 212 // if it is loaded and ready, and if not, queue up the task and load the
187 // page. 213 // page.
188 if (MaybeAddPendingOpenChannelTask(profile, params)) { 214 if (MaybeAddPendingOpenChannelTask(profile, target_extension, params)) {
189 return; 215 return;
190 } 216 }
191 217
192 OpenChannelImpl(scoped_ptr<OpenChannelParams>(params)); 218 OpenChannelImpl(make_scoped_ptr(params));
193 } 219 }
194 220
195 void MessageService::OpenChannelToNativeApp( 221 void MessageService::OpenChannelToNativeApp(
196 int source_process_id, 222 int source_process_id,
197 int source_routing_id, 223 int source_routing_id,
198 int receiver_port_id, 224 int receiver_port_id,
199 const std::string& source_extension_id, 225 const std::string& source_extension_id,
200 const std::string& native_app_name) { 226 const std::string& native_app_name) {
201 content::RenderProcessHost* source = 227 content::RenderProcessHost* source =
202 content::RenderProcessHost::FromID(source_process_id); 228 content::RenderProcessHost::FromID(source_process_id);
(...skipping 12 matching lines...) Expand all
215 APIPermission::kNativeMessaging); 241 APIPermission::kNativeMessaging);
216 } 242 }
217 243
218 if (!has_permission) { 244 if (!has_permission) {
219 ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, std::string()); 245 ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, std::string());
220 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(receiver_port_id), 246 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(receiver_port_id),
221 kMissingPermissionError); 247 kMissingPermissionError);
222 return; 248 return;
223 } 249 }
224 250
225 WebContents* source_contents = tab_util::GetWebContentsByID(
226 source_process_id, source_routing_id);
227
228 // Include info about the opener's tab (if it was a tab).
229 std::string tab_json = "null";
230 if (source_contents) {
231 scoped_ptr<DictionaryValue> tab_value(ExtensionTabUtil::CreateTabValue(
232 source_contents));
233 base::JSONWriter::Write(tab_value.get(), &tab_json);
234 }
235
236 scoped_ptr<MessageChannel> channel(new MessageChannel()); 251 scoped_ptr<MessageChannel> channel(new MessageChannel());
237 channel->opener.reset(new ExtensionMessagePort(source, MSG_ROUTING_CONTROL, 252 channel->opener.reset(new ExtensionMessagePort(source, MSG_ROUTING_CONTROL,
238 source_extension_id)); 253 source_extension_id));
239 254
240 scoped_ptr<NativeMessageProcessHost> native_process = 255 scoped_ptr<NativeMessageProcessHost> native_process =
241 NativeMessageProcessHost::Create( 256 NativeMessageProcessHost::Create(
242 base::WeakPtr<NativeMessageProcessHost::Client>( 257 base::WeakPtr<NativeMessageProcessHost::Client>(
243 weak_factory_.GetWeakPtr()), 258 weak_factory_.GetWeakPtr()),
244 source_extension_id, native_app_name, receiver_port_id); 259 source_extension_id, native_app_name, receiver_port_id);
245 260
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 302
288 if (contents && contents->GetController().NeedsReload()) { 303 if (contents && contents->GetController().NeedsReload()) {
289 // The tab isn't loaded yet. Don't attempt to connect. Treat this as a 304 // The tab isn't loaded yet. Don't attempt to connect. Treat this as a
290 // disconnect. 305 // disconnect.
291 ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, extension_id); 306 ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, extension_id);
292 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(receiver_port_id), 307 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(receiver_port_id),
293 kReceivingEndDoesntExistError); 308 kReceivingEndDoesntExistError);
294 return; 309 return;
295 } 310 }
296 311
297 WebContents* source_contents = tab_util::GetWebContentsByID( 312 scoped_ptr<OpenChannelParams> params(new OpenChannelParams(
298 source_process_id, source_routing_id); 313 source,
299 314 scoped_ptr<DictionaryValue>(), // Source tab doesn't make sense for
300 // Include info about the opener's tab (if it was a tab). 315 // opening to tabs.
301 std::string tab_json = "null"; 316 receiver.release(),
302 if (source_contents) { 317 receiver_port_id,
303 scoped_ptr<DictionaryValue> tab_value(ExtensionTabUtil::CreateTabValue( 318 extension_id,
304 source_contents)); 319 extension_id,
305 base::JSONWriter::Write(tab_value.get(), &tab_json); 320 GURL(), // Source URL doesn't make sense for opening to tabs.
306 } 321 channel_name));
307
308 scoped_ptr<OpenChannelParams> params(new OpenChannelParams(source, tab_json,
309 receiver.release(),
310 receiver_port_id,
311 extension_id,
312 extension_id,
313 channel_name));
314 OpenChannelImpl(params.Pass()); 322 OpenChannelImpl(params.Pass());
315 } 323 }
316 324
317 bool MessageService::OpenChannelImpl(scoped_ptr<OpenChannelParams> params) { 325 bool MessageService::OpenChannelImpl(scoped_ptr<OpenChannelParams> params) {
318 if (!params->source) 326 if (!params->source)
319 return false; // Closed while in flight. 327 return false; // Closed while in flight.
320 328
321 if (!params->receiver.get() || !params->receiver->GetRenderProcessHost()) { 329 if (!params->receiver || !params->receiver->GetRenderProcessHost()) {
322 // Treat it as a disconnect. 330 // Treat it as a disconnect.
323 ExtensionMessagePort port( 331 ExtensionMessagePort port(
324 params->source, MSG_ROUTING_CONTROL, std::string()); 332 params->source, MSG_ROUTING_CONTROL, std::string());
325 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(params->receiver_port_id), 333 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(params->receiver_port_id),
326 kReceivingEndDoesntExistError); 334 kReceivingEndDoesntExistError);
327 return false; 335 return false;
328 } 336 }
329 337
330 // Add extra paranoid CHECKs, since we have crash reports of this being NULL. 338 // Add extra paranoid CHECKs, since we have crash reports of this being NULL.
331 // http://code.google.com/p/chromium/issues/detail?id=19067 339 // http://code.google.com/p/chromium/issues/detail?id=19067
332 CHECK(params->receiver->GetRenderProcessHost()); 340 CHECK(params->receiver->GetRenderProcessHost());
333 341
334 MessageChannel* channel(new MessageChannel); 342 MessageChannel* channel(new MessageChannel);
335 channel->opener.reset(new ExtensionMessagePort(params->source, 343 channel->opener.reset(new ExtensionMessagePort(params->source,
336 MSG_ROUTING_CONTROL, 344 MSG_ROUTING_CONTROL,
337 params->source_extension_id)); 345 params->source_extension_id));
338 channel->receiver.reset(params->receiver.release()); 346 channel->receiver.reset(params->receiver.release());
339 347
340 CHECK(channel->receiver->GetRenderProcessHost()); 348 CHECK(channel->receiver->GetRenderProcessHost());
341 349
342 AddChannel(channel, params->receiver_port_id); 350 AddChannel(channel, params->receiver_port_id);
343 351
344 CHECK(channel->receiver->GetRenderProcessHost()); 352 CHECK(channel->receiver->GetRenderProcessHost());
345 353
346 // Send the connect event to the receiver. Give it the opener's port ID (the 354 // Send the connect event to the receiver. Give it the opener's port ID (the
347 // opener has the opposite port ID). 355 // opener has the opposite port ID).
348 channel->receiver->DispatchOnConnect(params->receiver_port_id, 356 channel->receiver->DispatchOnConnect(params->receiver_port_id,
349 params->channel_name, params->tab_json, 357 params->channel_name,
358 params->source_tab,
350 params->source_extension_id, 359 params->source_extension_id,
351 params->target_extension_id); 360 params->target_extension_id,
361 params->source_url);
352 362
353 // Keep both ends of the channel alive until the channel is closed. 363 // Keep both ends of the channel alive until the channel is closed.
354 channel->opener->IncrementLazyKeepaliveCount(); 364 channel->opener->IncrementLazyKeepaliveCount();
355 channel->receiver->IncrementLazyKeepaliveCount(); 365 channel->receiver->IncrementLazyKeepaliveCount();
356 return true; 366 return true;
357 } 367 }
358 368
359 void MessageService::AddChannel(MessageChannel* channel, int receiver_port_id) { 369 void MessageService::AddChannel(MessageChannel* channel, int receiver_port_id) {
360 int channel_id = GET_CHANNEL_ID(receiver_port_id); 370 int channel_id = GET_CHANNEL_ID(receiver_port_id);
361 CHECK(channels_.find(channel_id) == channels_.end()); 371 CHECK(channels_.find(channel_id) == channels_.end());
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 std::string(), notify_other_port); 482 std::string(), notify_other_port);
473 } else if (receiver_process == process) { 483 } else if (receiver_process == process) {
474 CloseChannelImpl(current, GET_CHANNEL_RECEIVERS_ID(current->first), 484 CloseChannelImpl(current, GET_CHANNEL_RECEIVERS_ID(current->first),
475 std::string(), notify_other_port); 485 std::string(), notify_other_port);
476 } 486 }
477 } 487 }
478 } 488 }
479 489
480 bool MessageService::MaybeAddPendingOpenChannelTask( 490 bool MessageService::MaybeAddPendingOpenChannelTask(
481 Profile* profile, 491 Profile* profile,
492 const Extension* extension,
482 OpenChannelParams* params) { 493 OpenChannelParams* params) {
483 ExtensionService* service = profile->GetExtensionService(); 494 if (!BackgroundInfo::HasLazyBackgroundPage(extension))
484 const std::string& extension_id = params->target_extension_id; 495 return false;
485 const Extension* extension = service->extensions()->GetByID(extension_id);
486 if (extension && BackgroundInfo::HasLazyBackgroundPage(extension)) {
487 // If the extension uses spanning incognito mode, make sure we're always
488 // using the original profile since that is what the extension process
489 // will use.
490 if (!IncognitoInfo::IsSplitMode(extension))
491 profile = profile->GetOriginalProfile();
492 496
493 if (lazy_background_task_queue_->ShouldEnqueueTask(profile, extension)) { 497 // If the extension uses spanning incognito mode, make sure we're always
494 pending_channels_[GET_CHANNEL_ID(params->receiver_port_id)] = 498 // using the original profile since that is what the extension process
495 PendingChannel(profile, extension_id); 499 // will use.
496 scoped_ptr<OpenChannelParams> scoped_params(params); 500 if (!IncognitoInfo::IsSplitMode(extension))
497 lazy_background_task_queue_->AddPendingTask(profile, extension_id, 501 profile = profile->GetOriginalProfile();
498 base::Bind(&MessageService::PendingOpenChannel,
499 weak_factory_.GetWeakPtr(), base::Passed(&scoped_params),
500 params->source->GetID()));
501 return true;
502 }
503 }
504 502
505 return false; 503 if (!lazy_background_task_queue_->ShouldEnqueueTask(profile, extension))
504 return false;
505
506 pending_channels_[GET_CHANNEL_ID(params->receiver_port_id)] =
507 PendingChannel(profile, extension->id());
508 scoped_ptr<OpenChannelParams> scoped_params(params);
509 lazy_background_task_queue_->AddPendingTask(profile, extension->id(),
510 base::Bind(&MessageService::PendingOpenChannel,
511 weak_factory_.GetWeakPtr(), base::Passed(&scoped_params),
512 params->source->GetID()));
513 return true;
506 } 514 }
507 515
508 void MessageService::PendingOpenChannel(scoped_ptr<OpenChannelParams> params, 516 void MessageService::PendingOpenChannel(scoped_ptr<OpenChannelParams> params,
509 int source_process_id, 517 int source_process_id,
510 ExtensionHost* host) { 518 ExtensionHost* host) {
511 if (!host) 519 if (!host)
512 return; // TODO(mpcomplete): notify source of disconnect? 520 return; // TODO(mpcomplete): notify source of disconnect?
513 521
514 // Re-lookup the source process since it may no longer be valid. 522 // Re-lookup the source process since it may no longer be valid.
515 content::RenderProcessHost* source = 523 content::RenderProcessHost* source =
516 content::RenderProcessHost::FromID(source_process_id); 524 content::RenderProcessHost::FromID(source_process_id);
517 if (!source) 525 if (!source)
518 return; 526 return;
519 527
520 params->source = source; 528 params->source = source;
521 params->receiver.reset(new ExtensionMessagePort(host->render_process_host(), 529 params->receiver.reset(new ExtensionMessagePort(host->render_process_host(),
522 MSG_ROUTING_CONTROL, 530 MSG_ROUTING_CONTROL,
523 params->target_extension_id)); 531 params->target_extension_id));
524 OpenChannelImpl(params.Pass()); 532 OpenChannelImpl(params.Pass());
525 } 533 }
526 534
527 } // namespace extensions 535 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/extensions/api/messaging/message_service.h ('k') | chrome/browser/renderer_host/chrome_render_message_filter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698