2016-03-08 30 views
0

我想将活动标签Url设置为我在chrome.browserAction.onClicked上注入的iframe中的表单字段。在iFrame中设置元素值 - Chrome扩展

问题是由于安全策略(主页和iframe的不同来源),我无法访问content script中的iframe。 主网页是一个外部页面。例如。 wikipedia.com

这就是我到目前为止所尝试过的。

content_script.js

function onExtensionMessage(request) { 
    if (request['iconClicked'] != undefined) { 
    var extensionOrigin = 'chrome-extension://' + chrome.runtime.id; 
    if (!location.ancestorOrigins.contains(extensionOrigin)) { 
     var urlvalue = location.href; 
     var iframe = document.createElement('iframe'); 
     iframe.setAttribute("id", "iFrameS"); 
     iframe.src = chrome.runtime.getURL('popup.html'); 
     iframe.addEventListener('load', function (e) { 
      // Either set the value of input element in Iframe 
      // here or pass an event to background.js and set it from there 
      chrome.extension.sendRequest({'frameloaded': true}); 
     }, false);      
     document.body.appendChild(iframe); 
    } 
    return; 
    } 
} 

function initContentScript() {  
    chrome.extension.onRequest.addListener(onExtensionMessage); 
} 

initContentScript(); 

popup.html

<form method="post"> 
    <input id="url" type="text"> 
</form> 

当被点击扩展图标,我传递一个消息,内容脚本注入的iframe,一旦它被加载,我想要设置字段值。

我已经提到这个链接Access iframe from content script但找不到解决方案。

任何帮助,将不胜感激。

+0

all_frames已在清单文件中设置为true。如何在内容脚本中设置id = url的输入字段的值? – Vaulstein

+0

@gaemaf:我知道如何在内容脚本和背景页面之间传递消息。我如何在Iframe中设置字段的值? – Vaulstein

+0

@gaemaf:如果我使用弹出窗口,解决方案很简单,但如果在弹出窗口外单击任何位置,弹出窗口将关闭。除了在弹出窗口上执行检查元素外,没有办法强制弹出窗口保持打开状态。我唯一的选择是使用iframe。 – Vaulstein

回答

1

如果您需要将简单数据传递到新创建的iFrame,则可以在iFrame的src中使用查询字符串。
创建的iFrame时:在您的iFrame的脚本拆分网址

var winLoc = window.location.href; //I think this is what you want to send to your iFrame and populate field value 

iframe.src = chrome.runtime.getURL('popup.html?'+winLoc); 

var activeUrl = location.href.split('?')[1]; 
//activeUrl now contains passed data 

这种方式,你喜欢

+0

简单,适用于我的需求,谢谢! – Vaulstein

0

处理IFrame和内容脚本不是一件容易的事。没有一个非常正式和很好的方法来做到这一点。

原理

当我必须做在一个特定的IFrame一些行动,而不是最终的其他加载IFRAME,我把一个条件在注入的内容脚本的开头。

if(_.contains(window.location.href, "myIframePage.html")) runOnIframe() 

function runOnIframe() 
{ 
    // Do what you want 
} 

这样的runOnIframe功能将只在IFRAME运行加载myIframePage.html


为例

让用丝束iframe网页。第一个加载http://google.com/和第二个chrome.runtime.getURL('popup.html')(当然你的IFrame)。

该页面popup.html包含<input id="myInput" name="myInput">

为了能够从后台脚本中修改此输入的值,必须发送消息以更正iframe。 Chrome API不允许(直到将来更新)将消息发送到页面中的精美IFrame。

关键是要做到这一点在你的注入内容脚本:

contentScript.js

if(_contains(window.location.href, "myIframePage.html")) runOnIframe 

function runOnIframe() 
{ 
    chrome.extension.onRequest.addListener(onExtensionMessage); 
} 

function onExtensionMessage(request) 
{ 
    if(request.destination !== "iframe.popup.html") return 

    document.getElementById("myInput").value = request.value 
} 

而在你的后台页面中,你只需要发送的对象:

{ 
    destination : "iframe.popup.html", 
    value : "Some value to put in the input" 
} 

目的地的内容可以是你想要的,它只是为了识别你是谁发送了信息。通过这种方式,您可以通过更改此字段将消息发送到同一页中的不同iframe。

+0

所以在我的情况下,我应该在iframe加载时调用runOnIframe()(iframe.addEventListener('load',function(e)')? – Vaulstein

+0

否。使用'all_frame'标志,contentsScript将被注入因此你必须把你的专用代码放在内容脚本中,并且只有当你检测到你在你想要的iframe中时才能调用它 –

1

因为你想,你可以连接尽可能多的“简单”数据在Chrome中的网页中动态创建的Iframe中设置一个值,并且您只需使用JavaScript参考postMessage即可将数据从主页面分发到Iframe。

想象,喜欢你的主页:

<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <meta charset="UTF-8"> 
    <title></title> 
    <style> 
     iframe { 
      background: #FFF; 
      border: 3px solid #000; 
      width: 100%; 
      height: 50%; 
     } 
    </style> 
    <script> 
     window.onload = function() { 
      document.getElementById('titleH2').textContent = 'Main page: ' + window.location.href; 
      var myIframe = document.getElementById('myIframe').contentWindow; 
      document.getElementById('btnSend').addEventListener('click', function(e) { 
       e.preventDefault(); 
       var dataToSendToIframe = { 
        inputValue: document.getElementById('testToSend').value, 
        inputId: 'url' 
       } 
       // post message to the Iframe running on other domain 
       myIframe.postMessage(dataToSendToIframe, 'http://localhost:63342'); 
      }); 
     } 
    </script> 
</head> 
<body> 
    <h2 id="titleH2">Main page:</h2> 
    <p> 
     <input id="testToSend" type="text"> 
    </p> 
    <p> 
     <button id="btnSend">Send Message</button> 
    </p> 

    <iframe id="myIframe" src="http://localhost:63342/Projects/StackOverflow/z.html"> 
    <p>Your browser does not support iframes.</p> 
</body> 
</html> 

在这个页面中,你看到的iframe指向不同的域名,所以你不能在里面的内容出于安全原因直接作用(指CORS) 。 使用的postMessage您可以将数据发送到iframe简单:

myIframe.postMessage(dataToSendToIframe, 'http://localhost:63342'); 

另一方面,I帧(因为你可以控制好它)必须包含或者是想:

<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <meta charset="UTF-8"> 
    <title></title> 
    <style> 
    </style> 
    <script> 
     window.onload = function() { 
      document.getElementById('titleH1').textContent = 'Iframe on different domain: ' + window.location.href; 
      var inputUrl = document.getElementById('url'); 
      function receiveMessage(e) { 
       var origin = e.origin || e.originalEvent.origin; 
       // verify the message arrive from the right origin, if not reject 
       if (e.origin !== "http://localhost:33232") 
        return; 
       document.getElementById(e.data.inputId).value = e.data.inputValue; 
      } 
      window.addEventListener('message', receiveMessage); 
     } 
    </script> 
</head> 
<body> 
<h1 id="titleH1">Iframe on different domain</h1> 
<form method="post"> 
    <input id="url" type="text"> 
</form> 
</body> 
</html> 

在iframe中,你可以看到监听传入的消息:

function receiveMessage(e) { 

在监听器中,如果接受或不接收传入的消息,您必须使用域/来源进行控制。

在下面的快照(从主页我写在输入字段中的东西,然后按下按钮等等PostMessage的这个数据发送到在不同的域中运行设置输入字段的IFRAME):

enter image description here