我正在开发一个带有清单的Chrome扩展程序,目前可以访问所有主机.后台脚本将内容脚本注入所有帧.加载DOM后,首页/框架中的内容脚本开始遍历DOM树.当walker遇到iframe时,它需要发送与该iframe窗口相关联的特定内容脚本(可能是跨源)以开始它的工作并包含一些带有此消息的序列化数据.父窗口暂停执行并等待孩子完成它的步行并发回消息,它与序列化数据一起完成.然后父母继续工作.我尝试了两种解决这个问题的方法:
frameElement.contentWindow.postMessage
:这大部分时间都有效,但并非总是如此.有时,与iframe窗口关联的内容脚本消息事件侦听器永远不会收到该消息.我无法确认原因,但我认为在听众打电话之前是听众event.stopImmediatePropagation()
.例如,在雅虎主页(https://www.yahoo.com)上,将消息发布到与iframe源关联的内容脚本https://s.yimg.com/rq/darla/2-9- 9/html/r-sf.html,永远不会收到该消息.这是与广告相关的iframe.也许阻止消息是故意的.发布消息时没有错误,我使用targetOrigin为"*".chrome.runtime.sendMessage
:我可以向后台页面发送消息,但无法弄清楚如何告诉后台页面中继消息的帧.父窗口内容脚本不知道与在DOM漫游中遇到的子帧元素关联的chrome扩展frameId.所以它无法告诉后台页面如何指导消息.对于第2点,我尝试了两种在stackoverflow上找到的技术:
window.frames
数组中的位置,并使用此索引将消息发布到后台页面.后台页面将消息发布到消息数据中具有所需索引的所有帧.只有在window.parent.frames数组中找到它的窗口对象位置的iframe才能匹配从消息中收到的索引,并继续它的行走.这工作正常但window.frames
在异步消息传递过程中容易受到数组中的更改的影响(如果在发送消息后删除了iframe,则索引值可能不再与所需的帧匹配).frameElement.name
在父窗口中使用.使用相同的消息传递技术,将名称发送到子iframe以与其window.name
值进行比较.我相信window.name
从frameElement.name
iframe元素创建时获得它的价值.但是,由于我不控制框架元素的创建,因此name属性通常是一个空字符串,不能依赖它来将iframe元素唯一地匹配到它们的窗口.有没有办法让我可靠地将消息发送到与在DOM树中行走时找到的iframe元素关联的内容脚本?
javascript iframe google-chrome-extension firefox-addon-webextensions
背景:这个问题与 Chrome 最新版本扩展的开发有关。它依赖于 javascript 功能,例如并非在所有浏览器上都可用的 HTML 导入和自定义元素,但在这种情况下是可以的。
我正在尝试实现一个简化的 HTML 自定义元素,如下所示:
<custom-el>
<span slot="head">Great</span>
<span slot="item">Item one</span>
<span slot="item">Item two</span>
<span slot="foot">done</span>
</custom-el>
Run Code Online (Sandbox Code Playgroud)
我注册了<custom-el>
. 每次创建元素时,我的代码的自定义元素类都会附加一个影子根并附加到以下模板中的影子根内容:
<template id="main">
<h1><slot name="head"></slot></h1>
<ul>
<slot name="item"></slot>
</ul>
<i><slot name="foot"></slot></i>
</template>
Run Code Online (Sandbox Code Playgroud)
我想将每个<span>
属性重新分配slot="item"
给负责呈现单个项目的辅助模板:
<template id="sub">
<li><slot name="item"></slot></li>
</template>
Run Code Online (Sandbox Code Playgroud)
带属性的槽数name="item"
不固定。它从数据库生成并定期更改。
我知道可以通过将 shadowRoot 附加到插槽的父元素并设置插槽的插槽属性来重新分配插槽,例如<slot name="item" slot="newItem">
. 但我认为这在我的情况下不起作用,因为子模板需要包装每个项目实例,而不是项目列表。
我可以将影子根和子模板附加到主文档中的每个项目。这会起作用,但我的偏好是主模板导入并应用任何嵌套的 shadowRoots 和模板。这样,主文档只需要导入包含主模板的文件。组件细节的实现被封装在主模板html文件中。
我还可以使用slotchange
事件和HTMLSlotElement.assignedNodes
方法来拼凑脚本解决方案。但我宁愿不走那条路。
还有另一种方法吗?我的实际用例涉及更复杂的 HTML 结构。或者我的架构或对 Web 组件的理解有缺陷?
html web-component google-chrome-extension shadow-dom custom-element