Add support for message sending to fenced frames and documentIds
- Add ability when connecting to include_child_frames this descends into fenced frames. - Ensure that the documentId is provided for connections from a tab to an extension. - Ensure that fenced frames are considered subframes for content injection. - Add a messaging test that checks the above changed code. BUG=1264911 Change-Id: I71f8e7302dbd834ce25eb3784650f0c49be19476 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3396242 Reviewed-by: Devlin Cronin <rdevlin.cronin@chromium.org> Reviewed-by: Joe Mason <joenotcharles@google.com> Commit-Queue: Dave Tapuska <dtapuska@chromium.org> Cr-Commit-Position: refs/heads/main@{#962142}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
1f8b86ee7b
commit
f9b64cf593
chrome
browser
extensions
api
messaging
test
data
extensions
api_test
messaging
extensions
@ -64,6 +64,7 @@
|
||||
#include "net/dns/mock_host_resolver.h"
|
||||
#include "net/test/embedded_test_server/embedded_test_server.h"
|
||||
#include "services/network/public/cpp/features.h"
|
||||
#include "third_party/blink/public/common/features.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
namespace extensions {
|
||||
@ -1466,6 +1467,31 @@ IN_PROC_BROWSER_TEST_F(MessagingApiTest, LargeMessages) {
|
||||
ASSERT_TRUE(RunExtensionTest("messaging/large_messages"));
|
||||
}
|
||||
|
||||
class MessagingApiFencedFrameTest
|
||||
: public MessagingApiTest,
|
||||
public testing::WithParamInterface<bool /* shadow_dom_fenced_frame */> {
|
||||
protected:
|
||||
MessagingApiFencedFrameTest() {
|
||||
feature_list_.InitAndEnableFeatureWithParameters(
|
||||
blink::features::kFencedFrames,
|
||||
{{"implementation_type", GetParam() ? "shadow_dom" : "mparch"}});
|
||||
}
|
||||
~MessagingApiFencedFrameTest() override = default;
|
||||
|
||||
private:
|
||||
base::test::ScopedFeatureList feature_list_;
|
||||
};
|
||||
|
||||
IN_PROC_BROWSER_TEST_P(MessagingApiFencedFrameTest, Load) {
|
||||
ASSERT_TRUE(RunExtensionTest("messaging/connect_fenced_frames",
|
||||
{.custom_arg = GetParam() ? "" : "MPArch"}))
|
||||
<< message_;
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(MessagingApiFencedFrameTest,
|
||||
MessagingApiFencedFrameTest,
|
||||
testing::Bool());
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace extensions
|
||||
|
22
chrome/test/data/extensions/api_test/messaging/connect_fenced_frames/content_script.js
Normal file
22
chrome/test/data/extensions/api_test/messaging/connect_fenced_frames/content_script.js
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2022 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.
|
||||
|
||||
chrome.runtime.onConnect.addListener(function onConnect(port) {
|
||||
port.onMessage.addListener(function(msg) {
|
||||
if (msg.testPostMessage) {
|
||||
port.postMessage({success: true});
|
||||
} else if (msg.testDisconnect) {
|
||||
port.disconnect();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// For test onMessage.
|
||||
function testSendMessageFromTab() {
|
||||
chrome.runtime.sendMessage({connected: true});
|
||||
}
|
||||
|
||||
// The background script has to wait for the fenced frame to load so
|
||||
// we start respond to the first test case here.
|
||||
testSendMessageFromTab();
|
1
chrome/test/data/extensions/api_test/messaging/connect_fenced_frames/fenced_frame.html
Normal file
1
chrome/test/data/extensions/api_test/messaging/connect_fenced_frames/fenced_frame.html
Normal file
@ -0,0 +1 @@
|
||||
Nothing here. .mock-http-headers specifies this resource should be served as a fenced frame.
|
3
chrome/test/data/extensions/api_test/messaging/connect_fenced_frames/fenced_frame.html.mock-http-headers
Normal file
3
chrome/test/data/extensions/api_test/messaging/connect_fenced_frames/fenced_frame.html.mock-http-headers
Normal file
@ -0,0 +1,3 @@
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/html
|
||||
Supports-Loading-Mode: fenced-frame
|
@ -0,0 +1 @@
|
||||
<fencedframe src="fenced_frame.html"></fencedframe>
|
@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "connect_external",
|
||||
"version": "1.0",
|
||||
"manifest_version": 2,
|
||||
"description": "Tests connect from a content script.",
|
||||
"permissions": ["tabs", "webNavigation"],
|
||||
"background": {
|
||||
"persistent": false,
|
||||
"scripts": ["test.js"]
|
||||
},
|
||||
"content_scripts": [
|
||||
{
|
||||
"all_frames": true,
|
||||
"matches": [
|
||||
"http://*/*fenced_frame.html"
|
||||
],
|
||||
"js": ["content_script.js"]
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
// Copyright 2022 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.
|
||||
|
||||
var listenOnce = chrome.test.listenOnce;
|
||||
var listenForever = chrome.test.listenForever;
|
||||
|
||||
// Keep track of the tab that we're running tests in, for simplicity.
|
||||
var testTab = null;
|
||||
|
||||
function compareSenders(expected, actual) {
|
||||
// documentId is a unique ID so we can't assume anything about it, just
|
||||
// that it is provided.
|
||||
chrome.test.assertTrue(actual.documentId != undefined);
|
||||
chrome.test.assertEq(expected.frameId, actual.frameId);
|
||||
chrome.test.assertEq(expected.url, actual.url);
|
||||
chrome.test.assertEq(serverOrigin, actual.origin);
|
||||
chrome.test.assertEq(chrome.runtime.id, actual.id);
|
||||
}
|
||||
|
||||
function createExpectedSender(frameId, url) {
|
||||
return {frameId: frameId, url: url};
|
||||
}
|
||||
|
||||
var mparchEnabled;
|
||||
var serverOrigin;
|
||||
var serverURL;
|
||||
|
||||
var tests = [
|
||||
// Tests that sendMessage from the fenced frame works.
|
||||
async function sendMessageFromTab() {
|
||||
const url = serverURL + 'main.html';
|
||||
|
||||
// Because there is no way to observe that a fenced frame has loaded we
|
||||
// need to first wait for a message from the fenced frame indicating it
|
||||
// has loaded. To avoid racy behavior we first bind a listener, then load
|
||||
// the tab and wait for that message.
|
||||
let actualSender;
|
||||
let messagePromise = new Promise((resolve) => {
|
||||
chrome.runtime.onMessage.addListener(function messageListener(message,
|
||||
sender) {
|
||||
chrome.test.assertEq(message.connected, true);
|
||||
chrome.runtime.onMessage.removeListener(messageListener);
|
||||
actualSender = sender;
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
// This tab will be used for the other tests as well.
|
||||
testTab = await new Promise(function(resolve, reject) {
|
||||
chrome.tabs.create({url: url}, (value) => {
|
||||
resolve(value);
|
||||
});
|
||||
});
|
||||
await messagePromise;
|
||||
expectedSender = createExpectedSender(
|
||||
mparchEnabled ? 5 : 4, serverURL + 'fenced_frame.html');
|
||||
compareSenders(expectedSender, actualSender);
|
||||
chrome.test.succeed();
|
||||
},
|
||||
|
||||
// Tests that postMessage to the fenced frame and its response works.
|
||||
function postMessage() {
|
||||
var port = chrome.tabs.connect(testTab.id);
|
||||
port.postMessage({testPostMessage: true});
|
||||
listenOnce(port.onMessage, function(msg) {
|
||||
port.disconnect();
|
||||
});
|
||||
},
|
||||
|
||||
// Tests that we get the disconnect event when the tab disconnect.
|
||||
function disconnect() {
|
||||
var port = chrome.tabs.connect(testTab.id);
|
||||
port.postMessage({testDisconnect: true});
|
||||
listenOnce(port.onDisconnect, function() {});
|
||||
}
|
||||
];
|
||||
|
||||
chrome.test.getConfig(async (config) => {
|
||||
mparchEnabled = config.customArg == 'MPArch';
|
||||
serverOrigin = `http://localhost:${config.testServer.port}`;
|
||||
serverURL = serverOrigin + '/extensions/api_test/messaging/'
|
||||
+ 'connect_fenced_frames/';
|
||||
chrome.test.runTests(tests);
|
||||
});
|
@ -147,13 +147,12 @@ ExtensionMessagePort::ExtensionMessagePort(
|
||||
CHECK(tab);
|
||||
frame_tracker_->TrackTabFrames(tab);
|
||||
if (include_child_frames) {
|
||||
// TODO(https://crbug.com/1227787) We don't yet support MParch so make sure
|
||||
// `include_child_frames` is only provided for primary pages. If `rfh`
|
||||
// belongs to a non-primary page, then the ForEachFrame iteration below
|
||||
// would actually correspond to a different page than `rfh`'s page.
|
||||
CHECK(rfh->GetPage().IsPrimary());
|
||||
tab->ForEachFrame(base::BindRepeating(&ExtensionMessagePort::RegisterFrame,
|
||||
base::Unretained(this)));
|
||||
// TODO(https://crbug.com/1227787) We don't yet support MParch for
|
||||
// prerender so make sure `include_child_frames` is only provided for
|
||||
// primary main frames.
|
||||
CHECK(rfh->IsInPrimaryMainFrame());
|
||||
rfh->ForEachRenderFrameHost(base::BindRepeating(
|
||||
&ExtensionMessagePort::RegisterFrame, base::Unretained(this)));
|
||||
} else {
|
||||
RegisterFrame(rfh);
|
||||
}
|
||||
@ -276,6 +275,7 @@ void ExtensionMessagePort::DispatchOnConnect(
|
||||
const std::string& channel_name,
|
||||
std::unique_ptr<base::DictionaryValue> source_tab,
|
||||
int source_frame_id,
|
||||
const ExtensionApiFrameIdMap::DocumentId& source_document_id,
|
||||
int guest_process_id,
|
||||
int guest_render_frame_routing_id,
|
||||
const MessagingEndpoint& source_endpoint,
|
||||
@ -286,8 +286,8 @@ void ExtensionMessagePort::DispatchOnConnect(
|
||||
&ExtensionMessagePort::BuildDispatchOnConnectIPC,
|
||||
// Called synchronously.
|
||||
base::Unretained(this), channel_name, source_tab.get(), source_frame_id,
|
||||
guest_process_id, guest_render_frame_routing_id, source_endpoint,
|
||||
target_extension_id, source_url, source_origin));
|
||||
source_document_id, guest_process_id, guest_render_frame_routing_id,
|
||||
source_endpoint, target_extension_id, source_url, source_origin));
|
||||
}
|
||||
|
||||
void ExtensionMessagePort::DispatchOnDisconnect(
|
||||
@ -486,6 +486,7 @@ std::unique_ptr<IPC::Message> ExtensionMessagePort::BuildDispatchOnConnectIPC(
|
||||
const std::string& channel_name,
|
||||
const base::DictionaryValue* source_tab,
|
||||
int source_frame_id,
|
||||
const ExtensionApiFrameIdMap::DocumentId& source_document_id,
|
||||
int guest_process_id,
|
||||
int guest_render_frame_routing_id,
|
||||
const MessagingEndpoint& source_endpoint,
|
||||
@ -494,6 +495,9 @@ std::unique_ptr<IPC::Message> ExtensionMessagePort::BuildDispatchOnConnectIPC(
|
||||
absl::optional<url::Origin> source_origin,
|
||||
const IPCTarget& target) {
|
||||
ExtensionMsg_TabConnectionInfo source;
|
||||
|
||||
// Source document ID should exist if and only if there is a source tab.
|
||||
DCHECK_EQ(!!source_tab, !!source_document_id);
|
||||
if (source_tab) {
|
||||
std::unique_ptr<base::Value> source_tab_value =
|
||||
base::Value::ToUniquePtrValue(source_tab->Clone());
|
||||
@ -501,6 +505,7 @@ std::unique_ptr<IPC::Message> ExtensionMessagePort::BuildDispatchOnConnectIPC(
|
||||
// remove this cast.
|
||||
source.tab.Swap(
|
||||
static_cast<base::DictionaryValue*>(source_tab_value.get()));
|
||||
source.document_id = source_document_id.ToString();
|
||||
}
|
||||
source.frame_id = source_frame_id;
|
||||
|
||||
|
@ -81,15 +81,17 @@ class ExtensionMessagePort : public MessagePort {
|
||||
bool HasFrame(content::RenderFrameHost* rfh) const override;
|
||||
bool IsValidPort() override;
|
||||
void RevalidatePort() override;
|
||||
void DispatchOnConnect(const std::string& channel_name,
|
||||
std::unique_ptr<base::DictionaryValue> source_tab,
|
||||
int source_frame_id,
|
||||
int guest_process_id,
|
||||
int guest_render_frame_routing_id,
|
||||
const MessagingEndpoint& source_endpoint,
|
||||
const std::string& target_extension_id,
|
||||
const GURL& source_url,
|
||||
absl::optional<url::Origin> source_origin) override;
|
||||
void DispatchOnConnect(
|
||||
const std::string& channel_name,
|
||||
std::unique_ptr<base::DictionaryValue> source_tab,
|
||||
int source_frame_id,
|
||||
const ExtensionApiFrameIdMap::DocumentId& source_document_id,
|
||||
int guest_process_id,
|
||||
int guest_render_frame_routing_id,
|
||||
const MessagingEndpoint& source_endpoint,
|
||||
const std::string& target_extension_id,
|
||||
const GURL& source_url,
|
||||
absl::optional<url::Origin> source_origin) override;
|
||||
void DispatchOnDisconnect(const std::string& error_message) override;
|
||||
void DispatchOnMessage(const Message& message) override;
|
||||
void IncrementLazyKeepaliveCount() override;
|
||||
@ -134,6 +136,7 @@ class ExtensionMessagePort : public MessagePort {
|
||||
const std::string& channel_name,
|
||||
const base::DictionaryValue* source_tab,
|
||||
int source_frame_id,
|
||||
const ExtensionApiFrameIdMap::DocumentId& source_document_id,
|
||||
int guest_process_id,
|
||||
int guest_render_frame_routing_id,
|
||||
const MessagingEndpoint& source_endpoint,
|
||||
|
@ -21,6 +21,7 @@ void MessagePort::DispatchOnConnect(
|
||||
const std::string& channel_name,
|
||||
std::unique_ptr<base::DictionaryValue> source_tab,
|
||||
int source_frame_id,
|
||||
const ExtensionApiFrameIdMap::DocumentId& source_document_id,
|
||||
int guest_process_id,
|
||||
int guest_render_frame_routing_id,
|
||||
const MessagingEndpoint& source_endpoint,
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "base/values.h"
|
||||
#include "extensions/browser/extension_api_frame_id_map.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
#include "url/origin.h"
|
||||
|
||||
@ -67,6 +68,7 @@ class MessagePort {
|
||||
const std::string& channel_name,
|
||||
std::unique_ptr<base::DictionaryValue> source_tab,
|
||||
int source_frame_id,
|
||||
const ExtensionApiFrameIdMap::DocumentId& source_document_id,
|
||||
int guest_process_id,
|
||||
int guest_render_frame_routing_id,
|
||||
const MessagingEndpoint& source_endpoint,
|
||||
|
@ -150,6 +150,7 @@ struct MessageService::OpenChannelParams {
|
||||
ChannelEndpoint source;
|
||||
std::unique_ptr<base::DictionaryValue> source_tab;
|
||||
int source_frame_id;
|
||||
ExtensionApiFrameIdMap::DocumentId source_document_id;
|
||||
std::unique_ptr<MessagePort> receiver;
|
||||
PortId receiver_port_id;
|
||||
MessagingEndpoint source_endpoint;
|
||||
@ -161,21 +162,24 @@ struct MessageService::OpenChannelParams {
|
||||
bool include_guest_process_info;
|
||||
|
||||
// Takes ownership of receiver.
|
||||
OpenChannelParams(const ChannelEndpoint& source,
|
||||
std::unique_ptr<base::DictionaryValue> source_tab,
|
||||
int source_frame_id,
|
||||
MessagePort* receiver,
|
||||
const PortId& receiver_port_id,
|
||||
const MessagingEndpoint& source_endpoint,
|
||||
std::unique_ptr<MessagePort> opener_port,
|
||||
const std::string& target_extension_id,
|
||||
const GURL& source_url,
|
||||
absl::optional<url::Origin> source_origin,
|
||||
const std::string& channel_name,
|
||||
bool include_guest_process_info)
|
||||
OpenChannelParams(
|
||||
const ChannelEndpoint& source,
|
||||
std::unique_ptr<base::DictionaryValue> source_tab,
|
||||
int source_frame_id,
|
||||
const ExtensionApiFrameIdMap::DocumentId& source_document_id,
|
||||
MessagePort* receiver,
|
||||
const PortId& receiver_port_id,
|
||||
const MessagingEndpoint& source_endpoint,
|
||||
std::unique_ptr<MessagePort> opener_port,
|
||||
const std::string& target_extension_id,
|
||||
const GURL& source_url,
|
||||
absl::optional<url::Origin> source_origin,
|
||||
const std::string& channel_name,
|
||||
bool include_guest_process_info)
|
||||
: source(source),
|
||||
source_tab(std::move(source_tab)),
|
||||
source_frame_id(source_frame_id),
|
||||
source_document_id(source_document_id),
|
||||
receiver(receiver),
|
||||
receiver_port_id(receiver_port_id),
|
||||
source_endpoint(source_endpoint),
|
||||
@ -342,6 +346,7 @@ void MessageService::OpenChannelToExtension(
|
||||
}
|
||||
|
||||
int source_frame_id = -1;
|
||||
ExtensionApiFrameIdMap::DocumentId source_document_id;
|
||||
bool include_guest_process_info = false;
|
||||
|
||||
// Get information about the opener's tab, if applicable.
|
||||
@ -356,6 +361,8 @@ void MessageService::OpenChannelToExtension(
|
||||
DCHECK(source_render_frame_host);
|
||||
source_frame_id =
|
||||
ExtensionApiFrameIdMap::GetFrameId(source_render_frame_host);
|
||||
source_document_id =
|
||||
ExtensionApiFrameIdMap::GetDocumentId(source_render_frame_host);
|
||||
} else {
|
||||
// Check to see if it was a WebView making the request.
|
||||
// Sending messages from WebViews to extensions breaks webview isolation,
|
||||
@ -367,11 +374,12 @@ void MessageService::OpenChannelToExtension(
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<OpenChannelParams> params(new OpenChannelParams(
|
||||
source, std::move(source_tab), source_frame_id, nullptr,
|
||||
source_port_id.GetOppositePortId(), source_endpoint,
|
||||
std::move(opener_port), target_extension_id, source_url,
|
||||
std::move(source_origin), channel_name, include_guest_process_info));
|
||||
std::unique_ptr<OpenChannelParams> params =
|
||||
std::make_unique<OpenChannelParams>(
|
||||
source, std::move(source_tab), source_frame_id, source_document_id,
|
||||
nullptr, source_port_id.GetOppositePortId(), source_endpoint,
|
||||
std::move(opener_port), target_extension_id, source_url,
|
||||
std::move(source_origin), channel_name, include_guest_process_info);
|
||||
pending_incognito_channels_[params->receiver_port_id.GetChannelId()] =
|
||||
PendingMessagesQueue();
|
||||
if (context->IsOffTheRecord() &&
|
||||
@ -557,19 +565,22 @@ void MessageService::OpenChannelToTab(const ChannelEndpoint& source,
|
||||
BrowserContext* receiver_context = receiver_contents->GetBrowserContext();
|
||||
DCHECK(ExtensionsBrowserClient::Get()->IsSameContext(receiver_context,
|
||||
context_));
|
||||
std::unique_ptr<OpenChannelParams> params(new OpenChannelParams(
|
||||
source,
|
||||
std::unique_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,
|
||||
MessagingEndpoint::ForExtension(extension_id), std::move(opener_port),
|
||||
extension_id,
|
||||
GURL(), // Source URL doesn't make sense for opening to tabs.
|
||||
url::Origin(), // Origin URL doesn't make sense for opening to tabs.
|
||||
channel_name,
|
||||
false)); // Connections to tabs aren't webview guests.
|
||||
std::unique_ptr<OpenChannelParams> params =
|
||||
std::make_unique<OpenChannelParams>(
|
||||
source,
|
||||
std::unique_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.
|
||||
ExtensionApiFrameIdMap::DocumentId(), // If there is no frame, there
|
||||
// is no document either.
|
||||
receiver.release(), receiver_port_id,
|
||||
MessagingEndpoint::ForExtension(extension_id), std::move(opener_port),
|
||||
extension_id,
|
||||
GURL(), // Source URL doesn't make sense for opening to tabs.
|
||||
url::Origin(), // Origin URL doesn't make sense for opening to tabs.
|
||||
channel_name,
|
||||
false); // Connections to tabs aren't webview guests.
|
||||
OpenChannelImpl(receiver_context, std::move(params), extension,
|
||||
false /* did_enqueue */);
|
||||
}
|
||||
@ -629,9 +640,9 @@ void MessageService::OpenChannelImpl(BrowserContext* browser_context,
|
||||
// opener has the opposite port ID).
|
||||
channel->receiver->DispatchOnConnect(
|
||||
params->channel_name, std::move(params->source_tab),
|
||||
params->source_frame_id, guest_process_id, guest_render_frame_routing_id,
|
||||
params->source_endpoint, params->target_extension_id, params->source_url,
|
||||
params->source_origin);
|
||||
params->source_frame_id, params->source_document_id, guest_process_id,
|
||||
guest_render_frame_routing_id, params->source_endpoint,
|
||||
params->target_extension_id, params->source_url, params->source_origin);
|
||||
|
||||
// Report the event to the event router, if the target is an extension.
|
||||
//
|
||||
|
@ -70,8 +70,9 @@
|
||||
"url": {"type": "string", "optional": true, "description": "The URL of the page or frame that opened the connection. If the sender is in an iframe, it will be iframe's URL not the URL of the page which hosts it."},
|
||||
"nativeApplication": {"type": "string", "optional": true, "description": "The name of the native application that opened the connection, if any."},
|
||||
"tlsChannelId": {"type": "string", "optional": true, "description": "The TLS channel ID of the page or frame that opened the connection, if requested by the extension or app, and if available."},
|
||||
"origin": {"type": "string", "optional": true, "description": "The origin of the page or frame that opened the connection. It can vary from the url property (e.g., about:blank) or can be opaque (e.g., sandboxed iframes). This is useful for identifying if the origin can be trusted if we can't immediately tell from the URL."}
|
||||
}
|
||||
"origin": {"type": "string", "optional": true, "description": "The origin of the page or frame that opened the connection. It can vary from the url property (e.g., about:blank) or can be opaque (e.g., sandboxed iframes). This is useful for identifying if the origin can be trusted if we can't immediately tell from the URL."},
|
||||
"documentId": {"type": "string", "description": "A UUID of the document that opened the connection.", "nodoc": true}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "PlatformOs",
|
||||
|
@ -168,6 +168,9 @@ IPC_STRUCT_BEGIN(ExtensionMsg_TabConnectionInfo)
|
||||
// The ID of the frame that initiated the connection.
|
||||
// 0 if main frame, positive otherwise. -1 if not initiated from a frame.
|
||||
IPC_STRUCT_MEMBER(int, frame_id)
|
||||
|
||||
// The unique ID of the document of the frame that initiated the connection.
|
||||
IPC_STRUCT_MEMBER(std::string, document_id)
|
||||
IPC_STRUCT_END()
|
||||
|
||||
// Struct containing information about the destination of tab.connect().
|
||||
|
@ -447,6 +447,8 @@ void NativeRendererMessagingService::DispatchOnConnectToListeners(
|
||||
sender_builder.Set("origin", info.source_origin->Serialize());
|
||||
if (source->frame_id >= 0)
|
||||
sender_builder.Set("frameId", source->frame_id);
|
||||
if (!source->document_id.empty())
|
||||
sender_builder.Set("documentId", source->document_id);
|
||||
|
||||
const Extension* extension = script_context->extension();
|
||||
if (extension) {
|
||||
|
@ -208,7 +208,7 @@ std::unique_ptr<ScriptInjection> UserScriptSet::GetInjectionForScript(
|
||||
ScriptContext::GetEffectiveDocumentURLForInjection(
|
||||
web_frame, document_url, script->match_origin_as_fallback());
|
||||
|
||||
bool is_subframe = web_frame->Parent();
|
||||
bool is_subframe = web_frame->Parent() || web_frame->IsInFencedFrameTree();
|
||||
if (!script->MatchesDocument(effective_document_url, is_subframe))
|
||||
return injection;
|
||||
|
||||
|
Reference in New Issue
Block a user