Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/466.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 为什么可以';我不能将此消息传递到选项卡中运行的所有帧吗? 主题_Javascript_Google Chrome_Dom_Google Chrome Extension_Message Passing - Fatal编程技术网

Javascript 为什么可以';我不能将此消息传递到选项卡中运行的所有帧吗? 主题

Javascript 为什么可以';我不能将此消息传递到选项卡中运行的所有帧吗? 主题,javascript,google-chrome,dom,google-chrome-extension,message-passing,Javascript,Google Chrome,Dom,Google Chrome Extension,Message Passing,我正在创建一个chrome扩展,它要求我将消息从我的事件页面发送到运行在特定框架上的内容脚本 单击上下文菜单选项时,将调用消息传递操作。该选项仅在API将焦点元素分类为可编辑时可用。我需要将它发送到包含元素的最内层框架。(因此我可以通过访问document.activeElement对象来修改其内容) 从Chrome 41开始,您可以通过向函数填充options参数的frameID值,向特定帧发送消息 然而,Chrome41目前处于测试阶段,所以我显然不能期望这个功能与我用户的浏览器兼容 因此,

我正在创建一个chrome扩展,它要求我将消息从我的事件页面发送到运行在特定框架上的内容脚本

单击上下文菜单选项时,将调用消息传递操作。该选项仅在API将焦点元素分类为可编辑时可用。我需要将它发送到包含元素的最内层框架。(因此我可以通过访问
document.activeElement
对象来修改其内容)

从Chrome 41开始,您可以通过向函数填充
options
参数的
frameID
值,向特定帧发送消息

然而,Chrome41目前处于测试阶段,所以我显然不能期望这个功能与我用户的浏览器兼容

因此,我计划向选项卡中的所有帧发送消息(通过在属性设置为true的内容脚本上注册侦听器)。一旦进入内容脚本,我就可以通过比较
window.location.href
的值和我期望的值来检查这帧是否正确

问题 似乎我对事件侦听器或消息传递的工作方式有误解。文档非常清楚地表明,
chrome.tabs.sendMessage()
应该向选项卡中的每个帧发送一条消息,但看起来似乎每个消息只能调用一个
chrome.runtime.onMessage()
事件侦听器,即使注册了许多侦听器。实际调用哪一个似乎是由页面的初始加载决定的

这可以通过我的扩展的简化版本来演示:

manifest.json:

{
    "manifest_version":2,

    "name":"Demo",
    "description":"This is a demonstration",
    "version":"1.0",

    "permissions":[
     "<all_urls>",
     "contextMenus"
     ],

    "background": {
       "page":"background.html",
       "persistent":false
    },

    "content_scripts":[{
        "matches":["<all_urls>"],
        "js":["content.js"],
        "all_frames":true
     }]
}
content.js:

chrome.runtime.onMessage.addListener(handleRequest);

alert("Hi, i'm: " + window.location.host);
function handleRequest(message)
{
    alert("You tried to send a message to: " + message.destination);
    alert("I am: " + window.location.href);
}
如果您访问具有多个框架的页面,您应该注意以下行为:

  • 在初始加载页面时,您会收到许多警报,表明有许多帧正在加载(都有侦听器)

  • 单击关联菜单选项时,只会弹出一个警报,表示只有一个帧收到消息

  • 在多次单击上下文选项的过程中,接收消息的帧保持不变,但在刷新页面时可能会更改。这表明帧最初加载的顺序决定了要接收消息的帧


那么,我如何确保我试图与之交谈的框架能够真正收到我的信息,而不必求助于仅在chrome 41中可用的
frameID
选项

起初,我认为我可以从内容脚本返回一个响应,指示消息是否到达了正确的位置。我可以在事件页面的while循环中继续这样做,直到我收到一条消息告诉我停止,但正如我前面所说的,在刷新页面之前,消息似乎总是转到同一帧,所以这种方法对我来说没有任何作用

其他细节 我还注意到,如果一个页面上有两个相同来源的框架,比如plus.google.com,那么这两个框架都会响应消息,如果消息恰好传递到了这个框架集。因此,接收者似乎基于来源,而不是某个唯一的帧ID

以下是我所拍摄的有关我所谈论的现象的视频链接:

请注意,我最初收到的通知来自:youtube.com、accounts.google.com、plus.google.com和client6.google.com,但只有client6收到了我的消息

您的
chrome.runtime.onMessage
事件侦听器调用
alert
。此方法将阻止运行时,直到对话框关闭。出于某种原因,这也会阻止Chrome在其他帧中正确触发onMessage事件(报告为)

解决方法是使用
console.log
进行调试,而不是
alert
,或者将代码包装在
setTimeout
中,以异步处理
onMessage
事件。例如

chrome.runtime.onMessage.addListener(函数(消息){
setTimeout(函数(){
警报(“消息:”+消息);
});
});
您的
chrome.runtime.onMessage
事件侦听器调用
alert
。此方法将阻止运行时,直到对话框关闭。出于某种原因,这也会阻止Chrome在其他帧中正确触发onMessage事件(报告为)

解决方法是使用
console.log
进行调试,而不是
alert
,或者将代码包装在
setTimeout
中,以异步处理
onMessage
事件。例如

chrome.runtime.onMessage.addListener(函数(消息){
setTimeout(函数(){
警报(“消息:”+消息);
});
});

无法在Chromium 40.0.2214.91中复制,即使在修复代码中的语法错误并添加
“权限”:[“上下文菜单”]
“所有帧”:true
。在发布问题之前,请先试用您的代码,以确保代码确实代表了您的问题。@RobW抱歉,我已修复了错误,但您的系统会发生什么情况?就我而言,这种行为正如我所描述的那样。当页面加载时,你应该从youtube.com、accounts.google.com、plus.google.com以及其他网站发出警告。然后,当您单击该选项时,您应该注意到只有一个帧响应该消息。在这里,当我访问youtube.com并在youtube的搜索框中选择上下文菜单选项时,我会看到多个警报。你使用的是哪一个Chrome版本?@RobW版本40.0.2214.94(64位)我将在一个屏幕盖上嵌入video@RobW检查以确保单击c时加载的框架
chrome.contextMenus.onClicked.addListener(requestHandler);  
chrome.contextMenus.create({
    "title":"Click Me!!",
    "contexts":["editable"],
    "id":"1"                                                                                                                                               
});

function requestHandler(info, tab)
{
    chrome.tabs.sendMessage(tab.id, {"destination":info.frameUrl});

    //this should get sent to every frame in the tab
}
chrome.runtime.onMessage.addListener(handleRequest);

alert("Hi, i'm: " + window.location.host);
function handleRequest(message)
{
    alert("You tried to send a message to: " + message.destination);
    alert("I am: " + window.location.href);
}