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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/extensions/api/messaging/message_service.h" 6 7 #include "base/atomic_sequence_num.h" 8 #include "base/bind.h" 9 #include "base/callback.h" 10 #include "base/json/json_writer.h" 11 #include "base/lazy_instance.h" 12 #include "base/metrics/histogram.h" 13 #include "base/stl_util.h" 14 #include "base/values.h" 15 #include "chrome/browser/chrome_notification_types.h" 16 #include "chrome/browser/extensions/api/messaging/extension_message_port.h" 17 #include "chrome/browser/extensions/api/messaging/native_message_port.h" 18 #include "chrome/browser/extensions/extension_host.h" 19 #include "chrome/browser/extensions/extension_process_manager.h" 20 #include "chrome/browser/extensions/extension_service.h" 21 #include "chrome/browser/extensions/extension_system.h" 22 #include "chrome/browser/extensions/extension_tab_util.h" 23 #include "chrome/browser/extensions/lazy_background_task_queue.h" 24 #include "chrome/browser/extensions/process_map.h" 25 #include "chrome/browser/profiles/profile.h" 26 #include "chrome/browser/tab_contents/tab_util.h" 27 #include "chrome/common/extensions/background_info.h" 28 #include "chrome/common/extensions/extension.h" 29 #include "chrome/common/extensions/extension_manifest_constants.h" 30 #include "chrome/common/extensions/extension_messages.h" 31 #include "chrome/common/extensions/incognito_handler.h" 32 #include "chrome/common/extensions/manifest_handlers/externally_connectable.h" 33 #include "content/public/browser/browser_thread.h" 34 #include "content/public/browser/notification_service.h" 35 #include "content/public/browser/render_process_host.h" 36 #include "content/public/browser/render_view_host.h" 37 #include "content/public/browser/render_widget_host.h" 38 #include "content/public/browser/render_widget_host_view.h" 39 #include "content/public/browser/site_instance.h" 40 #include "content/public/browser/web_contents.h" 41 #include "url/gurl.h" 42 43 using content::SiteInstance; 44 using content::WebContents; 45 46 // Since we have 2 ports for every channel, we just index channels by half the 47 // port ID. 48 #define GET_CHANNEL_ID(port_id) ((port_id) / 2) 49 #define GET_CHANNEL_OPENER_ID(channel_id) ((channel_id) * 2) 50 #define GET_CHANNEL_RECEIVERS_ID(channel_id) ((channel_id) * 2 + 1) 51 52 // Port1 is always even, port2 is always odd. 53 #define IS_OPENER_PORT_ID(port_id) (((port_id) & 1) == 0) 54 55 // Change even to odd and vice versa, to get the other side of a given channel. 56 #define GET_OPPOSITE_PORT_ID(source_port_id) ((source_port_id) ^ 1) 57 58 namespace extensions { 59 60 namespace { 61 const char kReceivingEndDoesntExistError[] = 62 "Could not establish connection. Receiving end does not exist."; 63 const char kMissingPermissionError[] = 64 "Access to native messaging requires nativeMessaging permission."; 65 const char kNativeMessagingNotSupportedError[] = 66 "Native Messaging is not supported on this platform."; 67 } 68 69 struct MessageService::MessageChannel { 70 scoped_ptr<MessagePort> opener; 71 scoped_ptr<MessagePort> receiver; 72 }; 73 74 struct MessageService::OpenChannelParams { 75 content::RenderProcessHost* source; 76 base::DictionaryValue source_tab; 77 scoped_ptr<MessagePort> receiver; 78 int receiver_port_id; 79 std::string source_extension_id; 80 std::string target_extension_id; 81 GURL source_url; 82 std::string channel_name; 83 84 // Takes ownership of receiver. 85 OpenChannelParams(content::RenderProcessHost* source, 86 scoped_ptr<base::DictionaryValue> source_tab, 87 MessagePort* receiver, 88 int receiver_port_id, 89 const std::string& source_extension_id, 90 const std::string& target_extension_id, 91 const GURL& source_url, 92 const std::string& channel_name) 93 : source(source), 94 receiver(receiver), 95 receiver_port_id(receiver_port_id), 96 source_extension_id(source_extension_id), 97 target_extension_id(target_extension_id), 98 source_url(source_url), 99 channel_name(channel_name) { 100 if (source_tab) 101 this->source_tab.Swap(source_tab.get()); 102 } 103 104 private: 105 DISALLOW_COPY_AND_ASSIGN(OpenChannelParams); 106 }; 107 108 namespace { 109 110 static base::StaticAtomicSequenceNumber g_next_channel_id; 111 static base::StaticAtomicSequenceNumber g_channel_id_overflow_count; 112 113 static content::RenderProcessHost* GetExtensionProcess( 114 Profile* profile, const std::string& extension_id) { 115 SiteInstance* site_instance = 116 extensions::ExtensionSystem::Get(profile)->process_manager()-> 117 GetSiteInstanceForURL( 118 Extension::GetBaseURLFromExtensionId(extension_id)); 119 120 if (!site_instance->HasProcess()) 121 return NULL; 122 123 return site_instance->GetProcess(); 124 } 125 126 } // namespace 127 128 content::RenderProcessHost* 129 MessageService::MessagePort::GetRenderProcessHost() { 130 return NULL; 131 } 132 133 // static 134 void MessageService::AllocatePortIdPair(int* port1, int* port2) { 135 unsigned channel_id = 136 static_cast<unsigned>(g_next_channel_id.GetNext()) % (kint32max/2); 137 138 if (channel_id == 0) { 139 int overflow_count = g_channel_id_overflow_count.GetNext(); 140 if (overflow_count > 0) 141 UMA_HISTOGRAM_BOOLEAN("Extensions.AllocatePortIdPairOverflow", true); 142 } 143 144 unsigned port1_id = channel_id * 2; 145 unsigned port2_id = channel_id * 2 + 1; 146 147 // Sanity checks to make sure our channel<->port converters are correct. 148 DCHECK(IS_OPENER_PORT_ID(port1_id)); 149 DCHECK(GET_OPPOSITE_PORT_ID(port1_id) == port2_id); 150 DCHECK(GET_OPPOSITE_PORT_ID(port2_id) == port1_id); 151 DCHECK(GET_CHANNEL_ID(port1_id) == GET_CHANNEL_ID(port2_id)); 152 DCHECK(GET_CHANNEL_ID(port1_id) == channel_id); 153 DCHECK(GET_CHANNEL_OPENER_ID(channel_id) == port1_id); 154 DCHECK(GET_CHANNEL_RECEIVERS_ID(channel_id) == port2_id); 155 156 *port1 = port1_id; 157 *port2 = port2_id; 158 } 159 160 MessageService::MessageService(Profile* profile) 161 : lazy_background_task_queue_( 162 ExtensionSystem::Get(profile)->lazy_background_task_queue()), 163 weak_factory_(this) { 164 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, 165 content::NotificationService::AllBrowserContextsAndSources()); 166 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, 167 content::NotificationService::AllBrowserContextsAndSources()); 168 } 169 170 MessageService::~MessageService() { 171 STLDeleteContainerPairSecondPointers(channels_.begin(), channels_.end()); 172 channels_.clear(); 173 } 174 175 static base::LazyInstance<ProfileKeyedAPIFactory<MessageService> > 176 g_factory = LAZY_INSTANCE_INITIALIZER; 177 178 // static 179 ProfileKeyedAPIFactory<MessageService>* MessageService::GetFactoryInstance() { 180 return &g_factory.Get(); 181 } 182 183 // static 184 MessageService* MessageService::Get(Profile* profile) { 185 return ProfileKeyedAPIFactory<MessageService>::GetForProfile(profile); 186 } 187 188 void MessageService::OpenChannelToExtension( 189 int source_process_id, int source_routing_id, int receiver_port_id, 190 const std::string& source_extension_id, 191 const std::string& target_extension_id, 192 const GURL& source_url, 193 const std::string& channel_name) { 194 content::RenderProcessHost* source = 195 content::RenderProcessHost::FromID(source_process_id); 196 if (!source) 197 return; 198 Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext()); 199 200 const Extension* target_extension = ExtensionSystem::Get(profile)-> 201 extension_service()->extensions()->GetByID(target_extension_id); 202 if (!target_extension) { 203 DispatchOnDisconnect( 204 source, receiver_port_id, kReceivingEndDoesntExistError); 205 return; 206 } 207 208 ExtensionService* extension_service = 209 extensions::ExtensionSystem::Get(profile)->extension_service(); 210 211 if (profile->IsOffTheRecord() && 212 !extension_service->IsIncognitoEnabled(target_extension_id)) { 213 DispatchOnDisconnect( 214 source, receiver_port_id, kReceivingEndDoesntExistError); 215 return; 216 } 217 218 if (source_extension_id != target_extension_id) { 219 // It's an external connection. Check the externally_connectable manifest 220 // key if it's present. If it's not, we allow connection from any extension 221 // but not webpages. 222 ExternallyConnectableInfo* externally_connectable = 223 static_cast<ExternallyConnectableInfo*>( 224 target_extension->GetManifestData( 225 extension_manifest_keys::kExternallyConnectable)); 226 bool is_externally_connectable = false; 227 228 if (externally_connectable) { 229 if (source_extension_id.empty()) { 230 // No source extension ID so the source was a web page. Check that the 231 // URL matches. 232 is_externally_connectable = 233 externally_connectable->matches.MatchesURL(source_url); 234 } else { 235 // Source extension ID so the source was an extension. Check that the 236 // extension matches. 237 is_externally_connectable = 238 externally_connectable->IdCanConnect(source_extension_id); 239 } 240 } else { 241 // Default behaviour. Any extension, no webpages. 242 is_externally_connectable = !source_extension_id.empty(); 243 } 244 245 if (!is_externally_connectable) { 246 // Important: use kReceivingEndDoesntExistError here so that we don't 247 // leak information about this extension to callers. This way it's 248 // indistinguishable from the extension just not existing. 249 DispatchOnDisconnect( 250 source, receiver_port_id, kReceivingEndDoesntExistError); 251 return; 252 } 253 } 254 255 // Note: we use the source's profile here. If the source is an incognito 256 // process, we will use the incognito EPM to find the right extension process, 257 // which depends on whether the extension uses spanning or split mode. 258 MessagePort* receiver = new ExtensionMessagePort( 259 GetExtensionProcess(profile, target_extension_id), MSG_ROUTING_CONTROL, 260 target_extension_id); 261 WebContents* source_contents = tab_util::GetWebContentsByID( 262 source_process_id, source_routing_id); 263 264 // Include info about the opener's tab (if it was a tab). 265 scoped_ptr<base::DictionaryValue> source_tab; 266 GURL source_url_for_tab; 267 268 if (source_contents && ExtensionTabUtil::GetTabId(source_contents) >= 0) { 269 // Platform apps can be sent messages, but don't have a Tab concept. 270 if (!target_extension->is_platform_app()) 271 source_tab.reset(ExtensionTabUtil::CreateTabValue(source_contents)); 272 source_url_for_tab = source_url; 273 } 274 275 OpenChannelParams* params = new OpenChannelParams(source, 276 source_tab.Pass(), 277 receiver, 278 receiver_port_id, 279 source_extension_id, 280 target_extension_id, 281 source_url_for_tab, 282 channel_name); 283 284 // The target might be a lazy background page. In that case, we have to check 285 // if it is loaded and ready, and if not, queue up the task and load the 286 // page. 287 if (MaybeAddPendingOpenChannelTask(profile, target_extension, params)) { 288 return; 289 } 290 291 OpenChannelImpl(make_scoped_ptr(params)); 292 } 293 294 void MessageService::OpenChannelToNativeApp( 295 int source_process_id, 296 int source_routing_id, 297 int receiver_port_id, 298 const std::string& source_extension_id, 299 const std::string& native_app_name) { 300 content::RenderProcessHost* source = 301 content::RenderProcessHost::FromID(source_process_id); 302 if (!source) 303 return; 304 305 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) 306 Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext()); 307 ExtensionService* extension_service = 308 extensions::ExtensionSystem::Get(profile)->extension_service(); 309 bool has_permission = false; 310 if (extension_service) { 311 const Extension* extension = 312 extension_service->GetExtensionById(source_extension_id, false); 313 has_permission = extension && extension->HasAPIPermission( 314 APIPermission::kNativeMessaging); 315 } 316 317 if (!has_permission) { 318 DispatchOnDisconnect(source, receiver_port_id, kMissingPermissionError); 319 return; 320 } 321 322 scoped_ptr<MessageChannel> channel(new MessageChannel()); 323 channel->opener.reset(new ExtensionMessagePort(source, MSG_ROUTING_CONTROL, 324 source_extension_id)); 325 326 // Get handle of the native view and pass it to the native messaging host. 327 gfx::NativeView native_view = 328 content::RenderWidgetHost::FromID(source_process_id, source_routing_id)-> 329 GetView()->GetNativeView(); 330 331 scoped_ptr<NativeMessageProcessHost> native_process = 332 NativeMessageProcessHost::Create( 333 native_view, 334 base::WeakPtr<NativeMessageProcessHost::Client>( 335 weak_factory_.GetWeakPtr()), 336 source_extension_id, native_app_name, receiver_port_id); 337 338 // Abandon the channel. 339 if (!native_process.get()) { 340 LOG(ERROR) << "Failed to create native process."; 341 DispatchOnDisconnect( 342 source, receiver_port_id, kReceivingEndDoesntExistError); 343 return; 344 } 345 channel->receiver.reset(new NativeMessagePort(native_process.release())); 346 347 // Keep the opener alive until the channel is closed. 348 channel->opener->IncrementLazyKeepaliveCount(); 349 350 AddChannel(channel.release(), receiver_port_id); 351 #else // !(defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)) 352 DispatchOnDisconnect( 353 source, receiver_port_id, kNativeMessagingNotSupportedError); 354 #endif // !(defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)) 355 } 356 357 void MessageService::OpenChannelToTab( 358 int source_process_id, int source_routing_id, int receiver_port_id, 359 int tab_id, const std::string& extension_id, 360 const std::string& channel_name) { 361 content::RenderProcessHost* source = 362 content::RenderProcessHost::FromID(source_process_id); 363 if (!source) 364 return; 365 Profile* profile = Profile::FromBrowserContext(source->GetBrowserContext()); 366 367 WebContents* contents = NULL; 368 scoped_ptr<MessagePort> receiver; 369 if (ExtensionTabUtil::GetTabById(tab_id, profile, true, 370 NULL, NULL, &contents, NULL)) { 371 receiver.reset(new ExtensionMessagePort( 372 contents->GetRenderProcessHost(), 373 contents->GetRenderViewHost()->GetRoutingID(), 374 extension_id)); 375 } 376 377 if (contents && contents->GetController().NeedsReload()) { 378 // The tab isn't loaded yet. Don't attempt to connect. 379 DispatchOnDisconnect( 380 source, receiver_port_id, kReceivingEndDoesntExistError); 381 return; 382 } 383 384 scoped_ptr<OpenChannelParams> params(new OpenChannelParams( 385 source, 386 scoped_ptr<base::DictionaryValue>(), // Source tab doesn't make sense 387 // for opening to tabs. 388 receiver.release(), 389 receiver_port_id, 390 extension_id, 391 extension_id, 392 GURL(), // Source URL doesn't make sense for opening to tabs. 393 channel_name)); 394 OpenChannelImpl(params.Pass()); 395 } 396 397 bool MessageService::OpenChannelImpl(scoped_ptr<OpenChannelParams> params) { 398 if (!params->source) 399 return false; // Closed while in flight. 400 401 if (!params->receiver || !params->receiver->GetRenderProcessHost()) { 402 DispatchOnDisconnect(params->source, 403 params->receiver_port_id, 404 kReceivingEndDoesntExistError); 405 return false; 406 } 407 408 // Add extra paranoid CHECKs, since we have crash reports of this being NULL. 409 // http://code.google.com/p/chromium/issues/detail?id=19067 410 CHECK(params->receiver->GetRenderProcessHost()); 411 412 MessageChannel* channel(new MessageChannel); 413 channel->opener.reset(new ExtensionMessagePort(params->source, 414 MSG_ROUTING_CONTROL, 415 params->source_extension_id)); 416 channel->receiver.reset(params->receiver.release()); 417 418 CHECK(channel->receiver->GetRenderProcessHost()); 419 420 AddChannel(channel, params->receiver_port_id); 421 422 CHECK(channel->receiver->GetRenderProcessHost()); 423 424 // Send the connect event to the receiver. Give it the opener's port ID (the 425 // opener has the opposite port ID). 426 channel->receiver->DispatchOnConnect(params->receiver_port_id, 427 params->channel_name, 428 params->source_tab, 429 params->source_extension_id, 430 params->target_extension_id, 431 params->source_url); 432 433 // Keep both ends of the channel alive until the channel is closed. 434 channel->opener->IncrementLazyKeepaliveCount(); 435 channel->receiver->IncrementLazyKeepaliveCount(); 436 return true; 437 } 438 439 void MessageService::AddChannel(MessageChannel* channel, int receiver_port_id) { 440 int channel_id = GET_CHANNEL_ID(receiver_port_id); 441 CHECK(channels_.find(channel_id) == channels_.end()); 442 channels_[channel_id] = channel; 443 pending_channels_.erase(channel_id); 444 } 445 446 void MessageService::CloseChannel(int port_id, 447 const std::string& error_message) { 448 // Note: The channel might be gone already, if the other side closed first. 449 int channel_id = GET_CHANNEL_ID(port_id); 450 MessageChannelMap::iterator it = channels_.find(channel_id); 451 if (it == channels_.end()) { 452 PendingChannelMap::iterator pending = pending_channels_.find(channel_id); 453 if (pending != pending_channels_.end()) { 454 lazy_background_task_queue_->AddPendingTask( 455 pending->second.first, pending->second.second, 456 base::Bind(&MessageService::PendingCloseChannel, 457 weak_factory_.GetWeakPtr(), port_id, error_message)); 458 } 459 return; 460 } 461 CloseChannelImpl(it, port_id, error_message, true); 462 } 463 464 void MessageService::CloseChannelImpl( 465 MessageChannelMap::iterator channel_iter, 466 int closing_port_id, 467 const std::string& error_message, 468 bool notify_other_port) { 469 MessageChannel* channel = channel_iter->second; 470 471 // Notify the other side. 472 if (notify_other_port) { 473 MessagePort* port = IS_OPENER_PORT_ID(closing_port_id) ? 474 channel->receiver.get() : channel->opener.get(); 475 port->DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(closing_port_id), 476 error_message); 477 } 478 479 // Balance the IncrementLazyKeepaliveCount() in OpenChannelImpl. 480 channel->opener->DecrementLazyKeepaliveCount(); 481 channel->receiver->DecrementLazyKeepaliveCount(); 482 483 delete channel_iter->second; 484 channels_.erase(channel_iter); 485 } 486 487 void MessageService::PostMessage( 488 int source_port_id, const std::string& message) { 489 int channel_id = GET_CHANNEL_ID(source_port_id); 490 MessageChannelMap::iterator iter = channels_.find(channel_id); 491 if (iter == channels_.end()) { 492 // If this channel is pending, queue up the PostMessage to run once 493 // the channel opens. 494 PendingChannelMap::iterator pending = pending_channels_.find(channel_id); 495 if (pending != pending_channels_.end()) { 496 lazy_background_task_queue_->AddPendingTask( 497 pending->second.first, pending->second.second, 498 base::Bind(&MessageService::PendingPostMessage, 499 weak_factory_.GetWeakPtr(), source_port_id, message)); 500 } 501 return; 502 } 503 504 // Figure out which port the ID corresponds to. 505 int dest_port_id = GET_OPPOSITE_PORT_ID(source_port_id); 506 MessagePort* port = IS_OPENER_PORT_ID(dest_port_id) ? 507 iter->second->opener.get() : iter->second->receiver.get(); 508 509 port->DispatchOnMessage(message, dest_port_id); 510 } 511 512 void MessageService::PostMessageFromNativeProcess(int port_id, 513 const std::string& message) { 514 PostMessage(port_id, message); 515 } 516 517 void MessageService::Observe(int type, 518 const content::NotificationSource& source, 519 const content::NotificationDetails& details) { 520 switch (type) { 521 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: 522 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { 523 content::RenderProcessHost* renderer = 524 content::Source<content::RenderProcessHost>(source).ptr(); 525 OnProcessClosed(renderer); 526 break; 527 } 528 default: 529 NOTREACHED(); 530 return; 531 } 532 } 533 534 void MessageService::OnProcessClosed(content::RenderProcessHost* process) { 535 // Close any channels that share this renderer. We notify the opposite 536 // port that his pair has closed. 537 for (MessageChannelMap::iterator it = channels_.begin(); 538 it != channels_.end(); ) { 539 MessageChannelMap::iterator current = it++; 540 541 content::RenderProcessHost* opener_process = 542 current->second->opener->GetRenderProcessHost(); 543 content::RenderProcessHost* receiver_process = 544 current->second->receiver->GetRenderProcessHost(); 545 546 // Only notify the other side if it has a different porocess host. 547 bool notify_other_port = opener_process && receiver_process && 548 opener_process != receiver_process; 549 550 if (opener_process == process) { 551 CloseChannelImpl(current, GET_CHANNEL_OPENER_ID(current->first), 552 std::string(), notify_other_port); 553 } else if (receiver_process == process) { 554 CloseChannelImpl(current, GET_CHANNEL_RECEIVERS_ID(current->first), 555 std::string(), notify_other_port); 556 } 557 } 558 } 559 560 bool MessageService::MaybeAddPendingOpenChannelTask( 561 Profile* profile, 562 const Extension* extension, 563 OpenChannelParams* params) { 564 if (!BackgroundInfo::HasLazyBackgroundPage(extension)) 565 return false; 566 567 // If the extension uses spanning incognito mode, make sure we're always 568 // using the original profile since that is what the extension process 569 // will use. 570 if (!IncognitoInfo::IsSplitMode(extension)) 571 profile = profile->GetOriginalProfile(); 572 573 if (!lazy_background_task_queue_->ShouldEnqueueTask(profile, extension)) 574 return false; 575 576 pending_channels_[GET_CHANNEL_ID(params->receiver_port_id)] = 577 PendingChannel(profile, extension->id()); 578 scoped_ptr<OpenChannelParams> scoped_params(params); 579 lazy_background_task_queue_->AddPendingTask(profile, extension->id(), 580 base::Bind(&MessageService::PendingOpenChannel, 581 weak_factory_.GetWeakPtr(), base::Passed(&scoped_params), 582 params->source->GetID())); 583 return true; 584 } 585 586 void MessageService::PendingOpenChannel(scoped_ptr<OpenChannelParams> params, 587 int source_process_id, 588 ExtensionHost* host) { 589 if (!host) 590 return; // TODO(mpcomplete): notify source of disconnect? 591 592 // Re-lookup the source process since it may no longer be valid. 593 content::RenderProcessHost* source = 594 content::RenderProcessHost::FromID(source_process_id); 595 if (!source) 596 return; 597 598 params->source = source; 599 params->receiver.reset(new ExtensionMessagePort(host->render_process_host(), 600 MSG_ROUTING_CONTROL, 601 params->target_extension_id)); 602 OpenChannelImpl(params.Pass()); 603 } 604 605 void MessageService::DispatchOnDisconnect(content::RenderProcessHost* source, 606 int port_id, 607 const std::string& error_message) { 608 ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, ""); 609 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(port_id), error_message); 610 } 611 612 } // namespace extensions 613