Skip to content

Commit

Permalink
Add frameId to MessageSender (extension messaging API).
Browse files Browse the repository at this point in the history
Moved IPC for extension messaging from RenderView to RenderFrame.

BUG=264286
R=kalman@chromium.org

Review URL: https://codereview.chromium.org/709933002

Cr-Commit-Position: refs/heads/master@{#305148}
  • Loading branch information
Rob--W authored and Commit bot committed Nov 21, 2014
1 parent 8327f71 commit 248d6a8
Show file tree
Hide file tree
Showing 22 changed files with 247 additions and 115 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,24 @@ ExtensionMessagePort::ExtensionMessagePort(content::RenderProcessHost* process,
void ExtensionMessagePort::DispatchOnConnect(
int dest_port_id,
const std::string& channel_name,
const base::DictionaryValue& source_tab,
scoped_ptr<base::DictionaryValue> source_tab,
int source_frame_id,
const std::string& source_extension_id,
const std::string& target_extension_id,
const GURL& source_url,
const std::string& tls_channel_id) {
ExtensionMsg_TabConnectionInfo source;
if (source_tab)
source.tab.Swap(source_tab.get());
source.frame_id = source_frame_id;

ExtensionMsg_ExternalConnectionInfo info;
info.target_id = target_extension_id;
info.source_id = source_extension_id;
info.source_url = source_url;

process_->Send(new ExtensionMsg_DispatchOnConnect(
routing_id_, dest_port_id, channel_name, source_tab, info,
tls_channel_id));
routing_id_, dest_port_id, channel_name, source, info, tls_channel_id));
}

void ExtensionMessagePort::DispatchOnDisconnect(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ class ExtensionMessagePort : public MessageService::MessagePort {
const std::string& extension_id);
void DispatchOnConnect(int dest_port_id,
const std::string& channel_name,
const base::DictionaryValue& source_tab,
scoped_ptr<base::DictionaryValue> source_tab,
int source_frame_id,
const std::string& source_extension_id,
const std::string& target_extension_id,
const GURL& source_url,
Expand Down
28 changes: 21 additions & 7 deletions chrome/browser/extensions/api/messaging/message_service.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
#include "base/metrics/histogram.h"
#include "base/prefs/pref_service.h"
#include "base/stl_util.h"
#include "base/values.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/api/messaging/extension_message_port.h"
#include "chrome/browser/extensions/api/messaging/incognito_connectability.h"
Expand All @@ -24,6 +23,7 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/tab_contents/tab_util.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
Expand Down Expand Up @@ -119,7 +119,8 @@ struct MessageService::MessageChannel {

struct MessageService::OpenChannelParams {
content::RenderProcessHost* source;
base::DictionaryValue source_tab;
scoped_ptr<base::DictionaryValue> source_tab;
int source_frame_id;
scoped_ptr<MessagePort> receiver;
int receiver_port_id;
std::string source_extension_id;
Expand All @@ -132,6 +133,7 @@ struct MessageService::OpenChannelParams {
// Takes ownership of receiver.
OpenChannelParams(content::RenderProcessHost* source,
scoped_ptr<base::DictionaryValue> source_tab,
int source_frame_id,
MessagePort* receiver,
int receiver_port_id,
const std::string& source_extension_id,
Expand All @@ -140,6 +142,7 @@ struct MessageService::OpenChannelParams {
const std::string& channel_name,
bool include_tls_channel_id)
: source(source),
source_frame_id(source_frame_id),
receiver(receiver),
receiver_port_id(receiver_port_id),
source_extension_id(source_extension_id),
Expand All @@ -148,7 +151,7 @@ struct MessageService::OpenChannelParams {
channel_name(channel_name),
include_tls_channel_id(include_tls_channel_id) {
if (source_tab)
this->source_tab.Swap(source_tab.get());
this->source_tab = source_tab.Pass();
}

private:
Expand Down Expand Up @@ -298,7 +301,7 @@ void MessageService::OpenChannelToExtension(
}
}

WebContents* source_contents = tab_util::GetWebContentsByID(
WebContents* source_contents = tab_util::GetWebContentsByFrameID(
source_process_id, source_routing_id);

if (context->IsOffTheRecord() &&
Expand Down Expand Up @@ -332,15 +335,22 @@ void MessageService::OpenChannelToExtension(

// Include info about the opener's tab (if it was a tab).
scoped_ptr<base::DictionaryValue> source_tab;
int source_frame_id = -1;
if (source_contents && ExtensionTabUtil::GetTabId(source_contents) >= 0) {
// Only the tab id is useful to platform apps for internal use. The
// unnecessary bits will be stripped out in
// MessagingBindings::DispatchOnConnect().
source_tab.reset(ExtensionTabUtil::CreateTabValue(source_contents));

content::RenderFrameHost* rfh =
content::RenderFrameHost::FromID(source_process_id, source_routing_id);
// Main frame's frameId is 0.
if (rfh)
source_frame_id = !rfh->GetParent() ? 0 : source_routing_id;
}

OpenChannelParams* params = new OpenChannelParams(
source, source_tab.Pass(), receiver, receiver_port_id,
source, source_tab.Pass(), source_frame_id, receiver, receiver_port_id,
source_extension_id, target_extension_id, source_url, channel_name,
include_tls_channel_id);

Expand Down Expand Up @@ -463,9 +473,11 @@ void MessageService::OpenChannelToTab(
scoped_ptr<MessagePort> receiver;
if (ExtensionTabUtil::GetTabById(tab_id, profile, true,
NULL, NULL, &contents, NULL)) {
// TODO(robwu): Update logic so that frames that are not hosted in the main
// frame's process can also receive the port.
receiver.reset(new ExtensionMessagePort(
contents->GetRenderProcessHost(),
contents->GetRenderViewHost()->GetRoutingID(),
contents->GetMainFrame()->GetRoutingID(),
extension_id));
}

Expand All @@ -480,6 +492,7 @@ void MessageService::OpenChannelToTab(
source,
scoped_ptr<base::DictionaryValue>(), // Source tab doesn't make sense
// for opening to tabs.
-1, // If there is no tab, then there is no frame either.
receiver.release(),
receiver_port_id,
extension_id,
Expand Down Expand Up @@ -521,7 +534,8 @@ bool MessageService::OpenChannelImpl(scoped_ptr<OpenChannelParams> params) {
// opener has the opposite port ID).
channel->receiver->DispatchOnConnect(params->receiver_port_id,
params->channel_name,
params->source_tab,
params->source_tab.Pass(),
params->source_frame_id,
params->source_extension_id,
params->target_extension_id,
params->source_url,
Expand Down
8 changes: 3 additions & 5 deletions chrome/browser/extensions/api/messaging/message_service.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/values.h"
#include "chrome/browser/extensions/api/messaging/message_property_provider.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
Expand All @@ -23,10 +24,6 @@
class GURL;
class Profile;

namespace base {
class DictionaryValue;
}

namespace content {
class BrowserContext;
class RenderProcessHost;
Expand Down Expand Up @@ -74,7 +71,8 @@ class MessageService : public BrowserContextKeyedAPI,
// Notify the port that the channel has been opened.
virtual void DispatchOnConnect(int dest_port_id,
const std::string& channel_name,
const base::DictionaryValue& source_tab,
scoped_ptr<base::DictionaryValue> source_tab,
int source_frame_id,
const std::string& source_extension_id,
const std::string& target_extension_id,
const GURL& source_url,
Expand Down
11 changes: 11 additions & 0 deletions chrome/browser/tab_contents/tab_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h"
#include "chrome/common/chrome_switches.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/web_contents.h"
Expand All @@ -16,6 +17,7 @@
#include "extensions/browser/extension_registry.h"
#endif

using content::RenderFrameHost;
using content::RenderViewHost;
using content::SiteInstance;
using content::WebContents;
Expand All @@ -31,6 +33,15 @@ content::WebContents* GetWebContentsByID(int render_process_id,
return WebContents::FromRenderViewHost(render_view_host);
}

content::WebContents* GetWebContentsByFrameID(int render_process_id,
int render_frame_id) {
RenderFrameHost* render_frame_host =
RenderFrameHost::FromID(render_process_id, render_frame_id);
if (!render_frame_host)
return NULL;
return WebContents::FromRenderFrameHost(render_frame_host);
}

SiteInstance* GetSiteInstanceForNewTab(Profile* profile,
const GURL& url) {
// If |url| is a WebUI or extension, we set the SiteInstance up front so that
Expand Down
3 changes: 3 additions & 0 deletions chrome/browser/tab_contents/tab_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ namespace tab_util {
content::WebContents* GetWebContentsByID(int render_process_id,
int render_view_id);

content::WebContents* GetWebContentsByFrameID(int render_process_id,
int render_frame_id);

// Returns a new SiteInstance for WebUI and app URLs. Returns NULL otherwise.
content::SiteInstance* GetSiteInstanceForNewTab(
Profile* profile,
Expand Down
38 changes: 38 additions & 0 deletions chrome/renderer/extensions/extension_frame_helper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
#include "chrome/renderer/extensions/extension_frame_helper.h"

#include "content/public/renderer/render_frame.h"
#include "extensions/common/api/messaging/message.h"
#include "extensions/common/extension_messages.h"
#include "extensions/renderer/console.h"
#include "extensions/renderer/dispatcher.h"
#include "extensions/renderer/messaging_bindings.h"
#include "third_party/WebKit/public/web/WebConsoleMessage.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"

Expand All @@ -34,6 +36,11 @@ bool ExtensionFrameHelper::OnMessageReceived(const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(ExtensionFrameHelper, message)
IPC_MESSAGE_HANDLER(ExtensionMsg_AddMessageToConsole,
OnAddMessageToConsole)
IPC_MESSAGE_HANDLER(ExtensionMsg_DispatchOnConnect,
OnExtensionDispatchOnConnect)
IPC_MESSAGE_HANDLER(ExtensionMsg_DeliverMessage, OnExtensionDeliverMessage)
IPC_MESSAGE_HANDLER(ExtensionMsg_DispatchOnDisconnect,
OnExtensionDispatchOnDisconnect)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
Expand All @@ -45,4 +52,35 @@ void ExtensionFrameHelper::OnAddMessageToConsole(
console::AddMessage(render_frame()->GetRenderView(), level, message);
}

void ExtensionFrameHelper::OnExtensionDispatchOnConnect(
int target_port_id,
const std::string& channel_name,
const ExtensionMsg_TabConnectionInfo& source,
const ExtensionMsg_ExternalConnectionInfo& info,
const std::string& tls_channel_id) {
MessagingBindings::DispatchOnConnect(
extension_dispatcher_->script_context_set(),
target_port_id,
channel_name,
source,
info,
tls_channel_id,
render_frame());
}

void ExtensionFrameHelper::OnExtensionDeliverMessage(int target_id,
const Message& message) {
MessagingBindings::DeliverMessage(
extension_dispatcher_->script_context_set(), target_id, message,
render_frame());
}

void ExtensionFrameHelper::OnExtensionDispatchOnDisconnect(
int port_id,
const std::string& error_message) {
MessagingBindings::DispatchOnDisconnect(
extension_dispatcher_->script_context_set(), port_id, error_message,
render_frame());
}

} // namespace extensions
14 changes: 14 additions & 0 deletions chrome/renderer/extensions/extension_frame_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@
#include "content/public/renderer/render_frame_observer.h"
#include "content/public/renderer/render_frame_observer_tracker.h"

struct ExtensionMsg_ExternalConnectionInfo;
struct ExtensionMsg_TabConnectionInfo;

namespace extensions {

class Dispatcher;
struct Message;

// RenderFrame-level plumbing for extension features.
class ExtensionFrameHelper
Expand All @@ -30,6 +34,16 @@ class ExtensionFrameHelper
// IPC handlers.
void OnAddMessageToConsole(content::ConsoleMessageLevel level,
const std::string& message);
void OnExtensionDispatchOnConnect(
int target_port_id,
const std::string& channel_name,
const ExtensionMsg_TabConnectionInfo& source,
const ExtensionMsg_ExternalConnectionInfo& info,
const std::string& tls_channel_id);
void OnExtensionDeliverMessage(int target_port_id,
const Message& message);
void OnExtensionDispatchOnDisconnect(int port_id,
const std::string& error_message);

Dispatcher* extension_dispatcher_;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright (c) 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// continuation of testSendMessageFromFrame()
chrome.runtime.sendMessage({frameUrl: location.href});
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "1.0",
"manifest_version": 2,
"description": "Tests connect from a content script.",
"permissions": ["tabs"],
"permissions": ["tabs", "webNavigation"],
"background": {
"persistent": false,
"scripts": ["test.js"]
Expand All @@ -12,6 +12,11 @@
{
"matches": ["http://*/*"],
"js": ["page.js"]
},
{
"all_frames": true,
"matches": ["http://*/*?testSendMessageFromFrame*"],
"js": ["frame.js"]
}
]
}
14 changes: 14 additions & 0 deletions chrome/test/data/extensions/api_test/messaging/connect/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ chrome.runtime.onConnect.addListener(function(port) {
testPostMessageFromTab(port);
} else if (msg.testSendMessageFromTab) {
testSendMessageFromTab();
} else if (msg.testSendMessageFromFrame) {
testSendMessageFromFrame();
} else if (msg.testDisconnect) {
port.disconnect();
} else if (msg.testDisconnectOnClose) {
Expand Down Expand Up @@ -65,6 +67,18 @@ function testSendMessageFromTab() {
});
}

function testSendMessageFromFrame() {
// Add two frames. The content script declared in manifest.json (frame.js)
// runs in frames whose URL matches ?testSendMessageFromFrame.
// frame.js sends a message to the background page, which checks that
// sender.frameId exists and is different for both frames.
for (var i = 0; i < 2; ++i) {
var f = document.createElement('iframe');
f.src = '?testSendMessageFromFrame' + i;
document.body.appendChild(f);
}
}

// Tests sendMessage to an invalid extension.
function testSendMessageFromTabError() {
// try sending a request to a bad extension id
Expand Down
Loading

0 comments on commit 248d6a8

Please sign in to comment.