在iFrame中设置元素值 - Chrome扩展程序

时间:2016-03-08 09:24:22

标签: javascript iframe google-chrome-extension

我正在尝试将活动标签页面Url设置为我在chrome.browserAction.onClicked上注入的Iframe中的表单字段。

问题在于,由于安全策略(主页和iframe的不同来源),我无法从iframe访问content script。 主网页是外部页面。例如。 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引用,但无法找到解决方案。

任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:1)

如果您需要将简单数据传递到新创建的iFrame,则可以在iFrame的src中使用查询字符串。
在创建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 );
在您的iFrame脚本中拆分网址:

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

通过这种方式,您可以根据需要连接任意数量的“简单”数据

答案 1 :(得分: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');

另一方面,iframe(因为你可以控制它)必须包含或喜欢:

<!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

答案 2 :(得分:0)

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

原理

当我必须在特定的IFrame中执行某些操作而不是最终的其他加载的IFrame时,我在注入的内容脚本的开头添加了一个条件。

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

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

这样runOnIframe函数只会在加载myIframePage.html

的iframe上运行

为例

设一个带有两个IFrame的页面。第一个加载http://google.com/,第二个加载chrome.runtime.getURL('popup.html')(当然是您的IFrame)。

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

为了能够从后台脚本修改此输入的值,您必须发送消息以更正iframe。 Chrome API不允许(在未来更新之前)向页面中的spécifiqueIFrame发送消息。

诀窍是在注入的内容脚本中执行此操作:

<强> 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。