Chrome扩展程序:将消息发送到加载到特定iframe中的页面 [英] Chrome Extension: Sending a message to the page loaded in a specific iframe

查看:186
本文介绍了Chrome扩展程序:将消息发送到加载到特定iframe中的页面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发Chrome扩展程序,以支持包含多个iframe的页面,每个iframe都加载一个来自其他域的页面。我需要将msg发送到加载了特定iframe的页面。顶级页面和iframe中的页面都有自己的内容脚本,因此可以使用完整的消息API。



从头版开始,当我使用chrome .runtime.sendMessage(),所有iframe都可以得到它(与顶部窗口一样,但是它的内容脚本很容易知道该特定的msg不适用于它)。有没有办法针对特定的一个iframe,或者所需的iframe页面知道msg是为了它?



请注意...

p>


  • 首页无法直接访问iframe页面中的任何内容,因为它们来自其他域。


  • 首页知道最初在每个框架中加载的URL,但用户可能从那里导航,因此将目标URL包含为接收脚本的msg参数以检查



有没有什么明显的我在这里失踪?






更新: @ wOxxOm的回答非常有用,但我仍然坚持如何获得我需要的frameIds。 / p>

更具体地说,我需要对这两个iframe做两件事,它们都需要frameId:


  • 向每个iframe注入脚本

  • 响应用户操作,将消息发送到特定的iframe o n顶级页面



所有这些都因为用户工作时动态创建和删除iframe而变得复杂。

我的一个想法是最初加载每个新的iFrame,其URL为about:blank?id = nnn,其中nnn是相应的iframe元素的DOM id 。这样,当我调用getAllFrames()时,我可以通过该URL识别新的iframe,并为每个DOM id构建一个frameIds查找。一旦完成,我可以加载真实URL,在加载后注入脚本。



这看起来很迂回,我希望我错过了一些支持API或其他简单的方法。

解决方案

我找到了解决方案,但它非常间接。我希望这很清楚。所有这些移动的部分都是我理解的野兽的本质。



这是我最终做的事情:


  1. 为每个iframe添加一个名称属性,与其DOM ID相同。

  2. 当每个iframe中的页面加载时,全局内容脚本将调用chrome.runtime.sendMessage(),并将该名称作为window.name访问。 b $ b
  3. 后台脚本获取该消息,该iframe的frameId为sender.frameId,并调用chrome.tabs.sendMessage(),传递frameId和窗口名称。
  4. 顶级页面的内容脚本根据这些窗口名称(AKA iframe DOM id)/ frameId对构建查找对象。

  5. 当顶级页面的内容脚本想要发送一条消息给任何一个iframe页面,它在那个查找对象中查找目标的frameId,然后调用chrome.runtime.sendMessage(),其中包含一个消息类型,指明它是否适用于特定的iframe,并包含该frameId。 >
  6. 作为响应,后台脚本使用chrome.tabs.sendMessage()将其发送到所请求的iframe内容脚本,并传递{frameId:request.frameId}作为第三个参数,如wOxxOm所示。 / li>

这是在这里工作,但通过一切手段让我知道是否有一个简单的方法来做到这一点。


I'm working on a Chrome extension to (among other things) support a page with multiple iframes, each of which loads a page from some other domain. I need to send a msg to the page loaded a specific one of those iframes. The top-level page and the pages in the iframe each have their own content scripts, so the full messaging API is available.

From the top page, when I do chrome.runtime.sendMessage(), all the iframes get it (as does the top window, but it's easy for its content script to know that that particular msg isn't intended for it). Is there any way to target a specific one of those iframes, or for the desired iframe page to know that the msg is for it?

Note that...

  • The top page can't access anything in iframe pages directly, because they're from other domains.

  • The top page knows the URL that was originally loaded in each frame, but the user may have navigated from there, so including the target URL as a msg parameter for the receiving script to check won't work.

Is there something obvious I'm missing here?


UPDATE: @wOxxOm's answer was very helpful, but I'm still stuck on how to get the frameIds I need.

More specifically, I need to do two things with those iframes, both of which need that frameId:

  • Inject a script into each iframe
  • Send msgs to a specific iframe in response to user actions on the top-level page

All of this is complicated by the fact that the iframes are created and removed dynamically as the user works.

One idea I had is to initially load each new iFrame with the URL "about:blank?id=nnn", where nnn is the DOM id of the corresponding iframe element. That way, when I call getAllFrames(), I can recognize the new iframes by that URL, and build a lookup of frameIds for each DOM id. Once that's done, I can load the real URL, inject the script once it's loaded.

That seems so roundabout, I'm hoping I've missed some supporting API or other straightforward approach.

解决方案

I did find a solution, but it's pretty indirect. I hope this is clear; all these moving parts are the nature of the beast as I understand it.

Here's what I ended up doing:

  1. Added a name attribute to each iframe, the same as its DOM id.
  2. When the page in each iframe loads, a global content script calls chrome.runtime.sendMessage(), passing that name, which it can access as window.name.
  3. The background script gets that msg, with the frameId of that iframe as sender.frameId, and calls chrome.tabs.sendMessage(), passing the frameId and window name.
  4. The top-level page's content script builds a lookup object from those window-name (AKA iframe DOM id) / frameId pairs.
  5. When the top-level page's content script wants to send a message to any of the iframe pages, it looks up the target's frameId in that lookup object, then calls chrome.runtime.sendMessage(), with a message type that indicates it's for a specific iframe, and including that frameId.
  6. In response, the background script sends it on to the requested iframe's content script with chrome.tabs.sendMessage(), passing {frameId: request.frameId} as the 3rd parameter, as wOxxOm suggested.

This is working here, but by all means let me know if there's a simpler way to do this.

这篇关于Chrome扩展程序:将消息发送到加载到特定iframe中的页面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆