OLD | NEW |
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 <stdint.h> | 7 #include <stdint.h> |
8 | |
9 #include <limits> | 8 #include <limits> |
| 9 #include <utility> |
10 | 10 |
11 #include "base/atomic_sequence_num.h" | 11 #include "base/atomic_sequence_num.h" |
12 #include "base/bind.h" | 12 #include "base/bind.h" |
13 #include "base/callback.h" | 13 #include "base/callback.h" |
14 #include "base/json/json_writer.h" | 14 #include "base/json/json_writer.h" |
15 #include "base/lazy_instance.h" | 15 #include "base/lazy_instance.h" |
16 #include "base/macros.h" | 16 #include "base/macros.h" |
17 #include "base/metrics/histogram.h" | 17 #include "base/metrics/histogram.h" |
18 #include "base/prefs/pref_service.h" | 18 #include "base/prefs/pref_service.h" |
19 #include "base/stl_util.h" | 19 #include "base/stl_util.h" |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 target_frame_id(target_frame_id), | 168 target_frame_id(target_frame_id), |
169 receiver(receiver), | 169 receiver(receiver), |
170 receiver_port_id(receiver_port_id), | 170 receiver_port_id(receiver_port_id), |
171 source_extension_id(source_extension_id), | 171 source_extension_id(source_extension_id), |
172 target_extension_id(target_extension_id), | 172 target_extension_id(target_extension_id), |
173 source_url(source_url), | 173 source_url(source_url), |
174 channel_name(channel_name), | 174 channel_name(channel_name), |
175 include_tls_channel_id(include_tls_channel_id), | 175 include_tls_channel_id(include_tls_channel_id), |
176 include_guest_process_info(include_guest_process_info) { | 176 include_guest_process_info(include_guest_process_info) { |
177 if (source_tab) | 177 if (source_tab) |
178 this->source_tab = source_tab.Pass(); | 178 this->source_tab = std::move(source_tab); |
179 } | 179 } |
180 | 180 |
181 private: | 181 private: |
182 DISALLOW_COPY_AND_ASSIGN(OpenChannelParams); | 182 DISALLOW_COPY_AND_ASSIGN(OpenChannelParams); |
183 }; | 183 }; |
184 | 184 |
185 namespace { | 185 namespace { |
186 | 186 |
187 static base::StaticAtomicSequenceNumber g_next_channel_id; | 187 static base::StaticAtomicSequenceNumber g_next_channel_id; |
188 | 188 |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
355 auto* rfh = content::RenderFrameHost::FromID(source_process_id, | 355 auto* rfh = content::RenderFrameHost::FromID(source_process_id, |
356 source_routing_id); | 356 source_routing_id); |
357 // Include |source_frame_id| so that we can retrieve the guest's frame | 357 // Include |source_frame_id| so that we can retrieve the guest's frame |
358 // routing id in OpenChannelImpl. | 358 // routing id in OpenChannelImpl. |
359 if (rfh) | 359 if (rfh) |
360 source_frame_id = source_routing_id; | 360 source_frame_id = source_routing_id; |
361 } | 361 } |
362 } | 362 } |
363 | 363 |
364 scoped_ptr<OpenChannelParams> params(new OpenChannelParams( | 364 scoped_ptr<OpenChannelParams> params(new OpenChannelParams( |
365 source_process_id, source_tab.Pass(), source_frame_id, -1, | 365 source_process_id, std::move(source_tab), source_frame_id, -1, |
366 -1, // no target_tab_id/target_frame_id for connections to extensions | 366 -1, // no target_tab_id/target_frame_id for connections to extensions |
367 nullptr, receiver_port_id, source_extension_id, target_extension_id, | 367 nullptr, receiver_port_id, source_extension_id, target_extension_id, |
368 source_url, channel_name, include_tls_channel_id, | 368 source_url, channel_name, include_tls_channel_id, |
369 include_guest_process_info)); | 369 include_guest_process_info)); |
370 | 370 |
371 pending_incognito_channels_[GET_CHANNEL_ID(params->receiver_port_id)] = | 371 pending_incognito_channels_[GET_CHANNEL_ID(params->receiver_port_id)] = |
372 PendingMessagesQueue(); | 372 PendingMessagesQueue(); |
373 if (context->IsOffTheRecord() && | 373 if (context->IsOffTheRecord() && |
374 !util::IsIncognitoEnabled(target_extension_id, context)) { | 374 !util::IsIncognitoEnabled(target_extension_id, context)) { |
375 // Give the user a chance to accept an incognito connection from the web if | 375 // Give the user a chance to accept an incognito connection from the web if |
376 // they haven't already, with the conditions: | 376 // they haven't already, with the conditions: |
377 // - Only for spanning-mode incognito. We don't want the complication of | 377 // - Only for spanning-mode incognito. We don't want the complication of |
378 // spinning up an additional process here which might need to do some | 378 // spinning up an additional process here which might need to do some |
379 // setup that we're not expecting. | 379 // setup that we're not expecting. |
380 // - Only for extensions that can't normally be enabled in incognito, since | 380 // - Only for extensions that can't normally be enabled in incognito, since |
381 // that surface (e.g. chrome://extensions) should be the only one for | 381 // that surface (e.g. chrome://extensions) should be the only one for |
382 // enabling in incognito. In practice this means platform apps only. | 382 // enabling in incognito. In practice this means platform apps only. |
383 if (!is_web_connection || IncognitoInfo::IsSplitMode(target_extension) || | 383 if (!is_web_connection || IncognitoInfo::IsSplitMode(target_extension) || |
384 util::CanBeIncognitoEnabled(target_extension)) { | 384 util::CanBeIncognitoEnabled(target_extension)) { |
385 OnOpenChannelAllowed(params.Pass(), false); | 385 OnOpenChannelAllowed(std::move(params), false); |
386 return; | 386 return; |
387 } | 387 } |
388 | 388 |
389 // If the target extension isn't even listening for connect/message events, | 389 // If the target extension isn't even listening for connect/message events, |
390 // there is no need to go any further and the connection should be | 390 // there is no need to go any further and the connection should be |
391 // rejected without showing a prompt. See http://crbug.com/442497 | 391 // rejected without showing a prompt. See http://crbug.com/442497 |
392 EventRouter* event_router = EventRouter::Get(context); | 392 EventRouter* event_router = EventRouter::Get(context); |
393 const char* const events[] = {"runtime.onConnectExternal", | 393 const char* const events[] = {"runtime.onConnectExternal", |
394 "runtime.onMessageExternal", | 394 "runtime.onMessageExternal", |
395 "extension.onRequestExternal", | 395 "extension.onRequestExternal", |
396 nullptr}; | 396 nullptr}; |
397 bool has_event_listener = false; | 397 bool has_event_listener = false; |
398 for (const char* const* event = events; *event; event++) { | 398 for (const char* const* event = events; *event; event++) { |
399 has_event_listener |= | 399 has_event_listener |= |
400 event_router->ExtensionHasEventListener(target_extension_id, *event); | 400 event_router->ExtensionHasEventListener(target_extension_id, *event); |
401 } | 401 } |
402 if (!has_event_listener) { | 402 if (!has_event_listener) { |
403 OnOpenChannelAllowed(params.Pass(), false); | 403 OnOpenChannelAllowed(std::move(params), false); |
404 return; | 404 return; |
405 } | 405 } |
406 | 406 |
407 // This check may show a dialog. | 407 // This check may show a dialog. |
408 IncognitoConnectability::Get(context) | 408 IncognitoConnectability::Get(context) |
409 ->Query(target_extension, source_contents, source_url, | 409 ->Query(target_extension, source_contents, source_url, |
410 base::Bind(&MessageService::OnOpenChannelAllowed, | 410 base::Bind(&MessageService::OnOpenChannelAllowed, |
411 weak_factory_.GetWeakPtr(), base::Passed(¶ms))); | 411 weak_factory_.GetWeakPtr(), base::Passed(¶ms))); |
412 return; | 412 return; |
413 } | 413 } |
414 | 414 |
415 OnOpenChannelAllowed(params.Pass(), true); | 415 OnOpenChannelAllowed(std::move(params), true); |
416 } | 416 } |
417 | 417 |
418 void MessageService::OpenChannelToNativeApp( | 418 void MessageService::OpenChannelToNativeApp( |
419 int source_process_id, | 419 int source_process_id, |
420 int source_routing_id, | 420 int source_routing_id, |
421 int receiver_port_id, | 421 int receiver_port_id, |
422 const std::string& source_extension_id, | 422 const std::string& source_extension_id, |
423 const std::string& native_app_name) { | 423 const std::string& native_app_name) { |
424 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 424 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
425 | 425 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
474 policy_permission == ALLOW_ALL, | 474 policy_permission == ALLOW_ALL, |
475 &error); | 475 &error); |
476 | 476 |
477 // Abandon the channel. | 477 // Abandon the channel. |
478 if (!native_host.get()) { | 478 if (!native_host.get()) { |
479 LOG(ERROR) << "Failed to create native process."; | 479 LOG(ERROR) << "Failed to create native process."; |
480 DispatchOnDisconnect(source, receiver_port_id, error); | 480 DispatchOnDisconnect(source, receiver_port_id, error); |
481 return; | 481 return; |
482 } | 482 } |
483 channel->receiver.reset(new NativeMessagePort( | 483 channel->receiver.reset(new NativeMessagePort( |
484 weak_factory_.GetWeakPtr(), receiver_port_id, native_host.Pass())); | 484 weak_factory_.GetWeakPtr(), receiver_port_id, std::move(native_host))); |
485 | 485 |
486 // Keep the opener alive until the channel is closed. | 486 // Keep the opener alive until the channel is closed. |
487 channel->opener->IncrementLazyKeepaliveCount(); | 487 channel->opener->IncrementLazyKeepaliveCount(); |
488 | 488 |
489 AddChannel(channel.release(), receiver_port_id); | 489 AddChannel(channel.release(), receiver_port_id); |
490 #else // !(defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)) | 490 #else // !(defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)) |
491 const char kNativeMessagingNotSupportedError[] = | 491 const char kNativeMessagingNotSupportedError[] = |
492 "Native Messaging is not supported on this platform."; | 492 "Native Messaging is not supported on this platform."; |
493 DispatchOnDisconnect( | 493 DispatchOnDisconnect( |
494 source, receiver_port_id, kNativeMessagingNotSupportedError); | 494 source, receiver_port_id, kNativeMessagingNotSupportedError); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
558 source_process_id, | 558 source_process_id, |
559 scoped_ptr<base::DictionaryValue>(), // Source tab doesn't make sense | 559 scoped_ptr<base::DictionaryValue>(), // Source tab doesn't make sense |
560 // for opening to tabs. | 560 // for opening to tabs. |
561 -1, // If there is no tab, then there is no frame either. | 561 -1, // If there is no tab, then there is no frame either. |
562 tab_id, frame_id, receiver.release(), receiver_port_id, extension_id, | 562 tab_id, frame_id, receiver.release(), receiver_port_id, extension_id, |
563 extension_id, | 563 extension_id, |
564 GURL(), // Source URL doesn't make sense for opening to tabs. | 564 GURL(), // Source URL doesn't make sense for opening to tabs. |
565 channel_name, | 565 channel_name, |
566 false, // Connections to tabs don't get TLS channel IDs. | 566 false, // Connections to tabs don't get TLS channel IDs. |
567 false)); // Connections to tabs aren't webview guests. | 567 false)); // Connections to tabs aren't webview guests. |
568 OpenChannelImpl(contents->GetBrowserContext(), params.Pass(), extension, | 568 OpenChannelImpl(contents->GetBrowserContext(), std::move(params), extension, |
569 false /* did_enqueue */); | 569 false /* did_enqueue */); |
570 } | 570 } |
571 | 571 |
572 void MessageService::OpenChannelImpl(BrowserContext* browser_context, | 572 void MessageService::OpenChannelImpl(BrowserContext* browser_context, |
573 scoped_ptr<OpenChannelParams> params, | 573 scoped_ptr<OpenChannelParams> params, |
574 const Extension* target_extension, | 574 const Extension* target_extension, |
575 bool did_enqueue) { | 575 bool did_enqueue) { |
576 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 576 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
577 DCHECK_EQ(target_extension != nullptr, !params->target_extension_id.empty()); | 577 DCHECK_EQ(target_extension != nullptr, !params->target_extension_id.empty()); |
578 | 578 |
(...skipping 25 matching lines...) Expand all Loading... |
604 params->source_frame_id = -1; | 604 params->source_frame_id = -1; |
605 | 605 |
606 DCHECK(guest_rfh == nullptr || | 606 DCHECK(guest_rfh == nullptr || |
607 WebViewGuest::FromWebContents( | 607 WebViewGuest::FromWebContents( |
608 WebContents::FromRenderFrameHost(guest_rfh)) != nullptr); | 608 WebContents::FromRenderFrameHost(guest_rfh)) != nullptr); |
609 } | 609 } |
610 | 610 |
611 // Send the connect event to the receiver. Give it the opener's port ID (the | 611 // Send the connect event to the receiver. Give it the opener's port ID (the |
612 // opener has the opposite port ID). | 612 // opener has the opposite port ID). |
613 channel->receiver->DispatchOnConnect( | 613 channel->receiver->DispatchOnConnect( |
614 params->receiver_port_id, params->channel_name, params->source_tab.Pass(), | 614 params->receiver_port_id, params->channel_name, |
615 params->source_frame_id, params->target_tab_id, params->target_frame_id, | 615 std::move(params->source_tab), params->source_frame_id, |
616 guest_process_id, guest_render_frame_routing_id, | 616 params->target_tab_id, params->target_frame_id, guest_process_id, |
617 params->source_extension_id, params->target_extension_id, | 617 guest_render_frame_routing_id, params->source_extension_id, |
618 params->source_url, params->tls_channel_id); | 618 params->target_extension_id, params->source_url, params->tls_channel_id); |
619 | 619 |
620 // Report the event to the event router, if the target is an extension. | 620 // Report the event to the event router, if the target is an extension. |
621 // | 621 // |
622 // First, determine what event this will be (runtime.onConnect vs | 622 // First, determine what event this will be (runtime.onConnect vs |
623 // runtime.onMessage etc), and what the event target is (view vs background | 623 // runtime.onMessage etc), and what the event target is (view vs background |
624 // page etc). | 624 // page etc). |
625 // | 625 // |
626 // Yes - even though this is opening a channel, they may actually be | 626 // Yes - even though this is opening a channel, they may actually be |
627 // runtime.onRequest/onMessage events because those single-use events are | 627 // runtime.onRequest/onMessage events because those single-use events are |
628 // built using the connect framework (see messaging.js). | 628 // built using the connect framework (see messaging.js). |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
926 DispatchOnDisconnect(source, params->receiver_port_id, | 926 DispatchOnDisconnect(source, params->receiver_port_id, |
927 kReceivingEndDoesntExistError); | 927 kReceivingEndDoesntExistError); |
928 return; | 928 return; |
929 } | 929 } |
930 | 930 |
931 // The target might be a lazy background page. In that case, we have to check | 931 // The target might be a lazy background page. In that case, we have to check |
932 // if it is loaded and ready, and if not, queue up the task and load the | 932 // if it is loaded and ready, and if not, queue up the task and load the |
933 // page. | 933 // page. |
934 if (!MaybeAddPendingLazyBackgroundPageOpenChannelTask( | 934 if (!MaybeAddPendingLazyBackgroundPageOpenChannelTask( |
935 context, target_extension, ¶ms, pending_messages)) { | 935 context, target_extension, ¶ms, pending_messages)) { |
936 OpenChannelImpl(context, params.Pass(), target_extension, | 936 OpenChannelImpl(context, std::move(params), target_extension, |
937 false /* did_enqueue */); | 937 false /* did_enqueue */); |
938 DispatchPendingMessages(pending_messages, channel_id); | 938 DispatchPendingMessages(pending_messages, channel_id); |
939 } | 939 } |
940 } | 940 } |
941 | 941 |
942 void MessageService::GotChannelID(scoped_ptr<OpenChannelParams> params, | 942 void MessageService::GotChannelID(scoped_ptr<OpenChannelParams> params, |
943 const std::string& tls_channel_id) { | 943 const std::string& tls_channel_id) { |
944 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 944 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
945 | 945 |
946 params->tls_channel_id.assign(tls_channel_id); | 946 params->tls_channel_id.assign(tls_channel_id); |
(...skipping 21 matching lines...) Expand all Loading... |
968 const Extension* target_extension = | 968 const Extension* target_extension = |
969 registry->enabled_extensions().GetByID(params->target_extension_id); | 969 registry->enabled_extensions().GetByID(params->target_extension_id); |
970 if (!target_extension) { | 970 if (!target_extension) { |
971 DispatchOnDisconnect(source, params->receiver_port_id, | 971 DispatchOnDisconnect(source, params->receiver_port_id, |
972 kReceivingEndDoesntExistError); | 972 kReceivingEndDoesntExistError); |
973 return; | 973 return; |
974 } | 974 } |
975 | 975 |
976 if (!MaybeAddPendingLazyBackgroundPageOpenChannelTask( | 976 if (!MaybeAddPendingLazyBackgroundPageOpenChannelTask( |
977 context, target_extension, ¶ms, pending_messages)) { | 977 context, target_extension, ¶ms, pending_messages)) { |
978 OpenChannelImpl(context, params.Pass(), target_extension, | 978 OpenChannelImpl(context, std::move(params), target_extension, |
979 false /* did_enqueue */); | 979 false /* did_enqueue */); |
980 DispatchPendingMessages(pending_messages, channel_id); | 980 DispatchPendingMessages(pending_messages, channel_id); |
981 } | 981 } |
982 } | 982 } |
983 | 983 |
984 void MessageService::PendingLazyBackgroundPageOpenChannel( | 984 void MessageService::PendingLazyBackgroundPageOpenChannel( |
985 scoped_ptr<OpenChannelParams> params, | 985 scoped_ptr<OpenChannelParams> params, |
986 int source_process_id, | 986 int source_process_id, |
987 ExtensionHost* host) { | 987 ExtensionHost* host) { |
988 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 988 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
989 | 989 |
990 if (!host) | 990 if (!host) |
991 return; // TODO(mpcomplete): notify source of disconnect? | 991 return; // TODO(mpcomplete): notify source of disconnect? |
992 | 992 |
993 params->receiver.reset(new ExtensionMessagePort(host->render_process_host(), | 993 params->receiver.reset(new ExtensionMessagePort(host->render_process_host(), |
994 MSG_ROUTING_CONTROL, | 994 MSG_ROUTING_CONTROL, |
995 params->target_extension_id)); | 995 params->target_extension_id)); |
996 OpenChannelImpl(host->browser_context(), params.Pass(), host->extension(), | 996 OpenChannelImpl(host->browser_context(), std::move(params), host->extension(), |
997 true /* did_enqueue */); | 997 true /* did_enqueue */); |
998 } | 998 } |
999 | 999 |
1000 void MessageService::DispatchOnDisconnect(content::RenderProcessHost* source, | 1000 void MessageService::DispatchOnDisconnect(content::RenderProcessHost* source, |
1001 int port_id, | 1001 int port_id, |
1002 const std::string& error_message) { | 1002 const std::string& error_message) { |
1003 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1003 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
1004 | 1004 |
1005 ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, ""); | 1005 ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, ""); |
1006 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(port_id), error_message); | 1006 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(port_id), error_message); |
1007 } | 1007 } |
1008 | 1008 |
1009 void MessageService::DispatchPendingMessages(const PendingMessagesQueue& queue, | 1009 void MessageService::DispatchPendingMessages(const PendingMessagesQueue& queue, |
1010 int channel_id) { | 1010 int channel_id) { |
1011 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1011 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
1012 | 1012 |
1013 MessageChannelMap::iterator channel_iter = channels_.find(channel_id); | 1013 MessageChannelMap::iterator channel_iter = channels_.find(channel_id); |
1014 if (channel_iter != channels_.end()) { | 1014 if (channel_iter != channels_.end()) { |
1015 for (const PendingMessage& message : queue) { | 1015 for (const PendingMessage& message : queue) { |
1016 DispatchMessage(message.first, channel_iter->second, message.second); | 1016 DispatchMessage(message.first, channel_iter->second, message.second); |
1017 } | 1017 } |
1018 } | 1018 } |
1019 } | 1019 } |
1020 | 1020 |
1021 } // namespace extensions | 1021 } // namespace extensions |
OLD | NEW |