无法更改由Chrome扩展程序生成的iframe中的元素 [英] Can't change element from iframe generated by Chrome Extension

查看:74
本文介绍了无法更改由Chrome扩展程序生成的iframe中的元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发Chrome扩展程序。目前,有一个内容脚本返回单击元素的 XPath 。另一个内容脚本将 iframe 添加到当前的 html 页面中。在 iframe 中有一个 textarea 字段,它应该显示 xpath 元素的c>。

不幸的是,它不起作用。正确地生成了 xpath (使用 console.log(path)进行测试,但命令为:

$ b ('#xh-bar')。contents()。find('#product-path').val('some_val'); $ b

$ c $>

不改变 textarea 。你知道问题出在哪里吗?我试过了改变 bar.js xpathget.js 的顺序,但它没有帮助。



manifest.json

  {
manifest_version :2,
name:Product,
description:这是一个与product.com合作的插件,
version:1.0,
browser_action:{
default_icon:spy-icon.png,
default_popup:popup.html,
default_title:点击这里!

图标:{
64:spy-icon.png
},
background:{
脚本:[authentication.js]
},
content_scripts:[
{
matches:[ < all_urls>],
js:[jquery-3.1.1.min.js,xpathget.js,bar.js]
}
],
权限:[
activeTab,
https://ajax.googleapis.com/,
cookies,
<< ; all_urls>

web_accessible_resources:[
bar.html,
],
content_security_policy:script-src'self' https://ajax.googleapis.com; object-src'self'
}

xpathget.js

  document.onclick = function(event){
if(event === undefined)event = window。事件; // IE hack
var target ='target'in event?event.target:event.srcElement; //另一个IE hack

var root = document.compatMode ===' CSS1Compat'?document.documentElement:document.body;
var mxy = [event.clientX + root.scrollLeft,event.clientY + root.scrollTop];

var path = getPathTo(target );
var txy = getPageXY(target);

alert(path);
$('#xh-bar')。contents()。find('#product ('some_val');#这应该改变TEXTAREA
}

函数getPathTo(元素){
if(element.id!= ='')
return'id('+ element.id +')';
if(element === document.body)
return element.tagName;

var ix = 0;
var siblings = element.parentNode.childNodes;
for(var i = 0; i< siblings.length; i ++){
var sibling = siblings [i];
if(sibling === element)
return getPathTo(element.parentNode)+'/'+ element.tagName +'['+(ix + 1)+']';
if(sibling.nodeType === 1&& sibling.tagName === element.tagName)
ix ++;



函数getPageXY(元素){
var x = 0,y = 0;
while(element){
x + = element.offsetLeft;
y + = element.offsetTop;
element = element.offsetParent;
}
return [x,y];
}

bar.js

  $(document).ready(function(){
$('body')。append('< iframe src =chrome -extension://some_id/bar.htmlid =xh-barclass =>< / iframe>');

});

并且生成的iframe是:

 < iframe src =chrome-extension://haifbndknpepdhjlcnmpoemlmomnidpe/bar.htmlid =xh-barclass =>这里是BAR.HTML< / iframe> 

如果是 bar.html 它有助于:

 <!doctype html> 
< html>
< head>
< title>产品客户< / title>

< script src =https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js>< / script>
< script src =https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js>< / script>
< script src =bootstrap / bootstrap.min.js>< / script>
< script src =bootstrap / html5shiv.js>< / script>
< script src =bootstrap / respond.min.js>< / script>
< script src =bootstrap / usebootstrap.js>< / script>

< script src =popup.js>< / script>
< script src =productspy.js>< / script>
< script src =xpathget.js>< / script>
< script src =jsplugins / jquery.cookie.js>< / script>
< script src =authentication.js>< / script>

< link rel =stylesheethref =https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css> ;

< link href =theme / bootstrap.css =stylesheet>
< link href =theme / usebootstrap.css =stylesheet>
< / head>
< body>
< div class =smaller>
< h1>产品客户 - 选择产品价格< / h1>
< hr>
< form class =form-horizo​​ntal>
< fieldset>

<! - 表格名称 - >
<图例>表格名称< / legend>

<! - 文字输入 - >
< div class =form-group>
< label class =col-md-4 control-labelfor =textinput>产品名称< / label>
< div class =col-md-4>
< input id =textinputname =textinputtype =textplaceholder =Nissan Patrol
class =form-control input-mdrequired =>

< / div>
< / div>

<! - Textarea - >
< div class =form-group>
< label class =col-md-4 control-labelfor =price> Price< / label>
< div class =col-md-4>
< textarea class =form-controlid =product-spy-pricename =pricereadonly>这将显示价格< / textarea>
< / div>
< / div>

<! - Button - >
< div class =form-group>
< label class =col-md-4 control-labelfor =submit>发送产品< / label>
< div class =col-md-4>
< button id =submitname =submitclass =btn btn-primary>发送< / button>
< / div>
< / div>

< / fieldset>
< / form>


< / div>
< / body>
< / html>

这是在控制台之后: console.log($('#xh内容());


未捕获SecurityError:无法读取'contentDocument'属性来自'HTMLIFrameElement'的
:阻止了一个源自框架的
http://stackoverflow.com 原产地
chrome-extension:// haifbndknpepdhjlcnmpoemlmomnidpe。请求访问的帧
具有http协议,访问的帧
具有chrome-extension协议。协议必须匹配。


解决方案

上面已经回答 - 您无法访问iFrame的DOM从页面加载的不同于iFrame的URL,因为Some Origin Policy。



但是你可以发送消息到你的iFrame并在那里处理它以设置textarea的值。



你可以这样做:




发送消息xpathget.js em>

  ... 
//替换你的setter
// $('#xh-酒吧 ')内容()找到(' #产品间谍价格some_val') ')VAL('; //#这应该改变TEXTAREA
//带
var win = document.getElementById(xh-bar)。contentWindow
win.postMessage(
{command :click,value:path},
chrome.extension.getURL('')
);
...

bar.html 包含js文件,它监听你的消息并设置 textarea 值:

  ... 
函数监听器(事件){
if(event.data&& event.data.command =='click'中的command)
{
console.log (的document.getElementById( '产物间谍价格')值= event.data.value);



if(window.addEventListener){
addEventListener(message,listener,false)
} else {
attachEvent(onmessage,listener)
}
...

所有:)



PS>最好通过 chrome.extension.getURL('bar.html')来获取你的chrome页面的路径。 code>而不是硬编码 - 在这种情况下,您可以在不出现问题的情况下更改应用程序ID,并在支持您的应用程序时避免许多麻烦。


I'm working on a Chrome Extension. For now, there is one content script which returns an XPath of clicked element. Another content script adds an iframe into the current html page. In this iframe there is a textarea field which should show the xpath of the element when user clicks on it.

Unfortunately it does not work. The xpath is correctly generated (tested using console.log(path) but the command:

$('#xh-bar').contents().find('#product-path').val('some_val');

Doesn't alter the textarea. Do you know where is the problem? I've tried to change the order of bar.js and xpathget.js but it did not help.

manifest.json

{
  "manifest_version": 2,
  "name": "Product",
  "description": "This is a plugin collaborating with product.com",
  "version": "1.0",
  "browser_action": {
    "default_icon": "spy-icon.png",
    "default_popup": "popup.html",
    "default_title": "Click here!"
  },
  "icons":{
    "64":"spy-icon.png"
  },
  "background": {
    "scripts": ["authentication.js"]
  },
    "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["jquery-3.1.1.min.js","xpathget.js","bar.js"]
    }
  ],
  "permissions": [
    "activeTab",
    "https://ajax.googleapis.com/",
    "cookies",
    "<all_urls>"
  ],
  "web_accessible_resources": [
    "bar.html",
  ],
  "content_security_policy": "script-src 'self' https://ajax.googleapis.com; object-src 'self'"
}

xpathget.js

document.onclick = function (event) {
    if (event === undefined) event = window.event;                     // IE hack
    var target = 'target' in event ? event.target : event.srcElement; // another IE hack

    var root = document.compatMode === 'CSS1Compat' ? document.documentElement : document.body;
    var mxy = [event.clientX + root.scrollLeft, event.clientY + root.scrollTop];

    var path = getPathTo(target);
    var txy = getPageXY(target);

    alert(path);
    $('#xh-bar').contents().find('#product-spy-price').val('some_val'); # THIS SHOULD ALTER THE TEXTAREA
}

function getPathTo(element) {
    if (element.id !== '')
        return 'id("' + element.id + '")';
    if (element === document.body)
        return element.tagName;

    var ix = 0;
    var siblings = element.parentNode.childNodes;
    for (var i = 0; i < siblings.length; i++) {
        var sibling = siblings[i];
        if (sibling === element)
            return getPathTo(element.parentNode) + '/' + element.tagName + '[' + (ix + 1) + ']';
        if (sibling.nodeType === 1 && sibling.tagName === element.tagName)
            ix++;
    }
}

function getPageXY(element) {
    var x = 0, y = 0;
    while (element) {
        x += element.offsetLeft;
        y += element.offsetTop;
        element = element.offsetParent;
    }
    return [x, y];
}

bar.js

$(document).ready(function () {
    $('body').append('<iframe src="chrome-extension://some_id/bar.html" id="xh-bar" class=""></iframe>');

});

And the generated iframe is:

<iframe src="chrome-extension://haifbndknpepdhjlcnmpoemlmomnidpe/bar.html" id="xh-bar" class="">HERE IS THE BAR.HTML</iframe>

This is the bar.html in case it helps:

<!doctype html>
<html>
<head>
    <title>Product Client</title>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
    <script src="bootstrap/bootstrap.min.js"></script>
    <script src="bootstrap/html5shiv.js"></script>
    <script src="bootstrap/respond.min.js"></script>
    <script src="bootstrap/usebootstrap.js"></script>

    <script src="popup.js"></script>
    <script src="productspy.js"></script>
    <script src="xpathget.js"></script>
    <script src="jsplugins/jquery.cookie.js"></script>
    <script src="authentication.js"></script>

    <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">

    <link href="theme/bootstrap.css" rel="stylesheet">
    <link href="theme/usebootstrap.css" rel="stylesheet">
</head>
<body>
<div class="smaller">
    <h1>Product Client - Select the product price</h1>
    <hr>
    <form class="form-horizontal">
        <fieldset>

            <!-- Form Name -->
            <legend>Form Name</legend>

            <!-- Text input-->
            <div class="form-group">
                <label class="col-md-4 control-label" for="textinput">Product Name</label>
                <div class="col-md-4">
                    <input id="textinput" name="textinput" type="text" placeholder="Nissan Patrol"
                           class="form-control input-md" required="">

                </div>
            </div>

            <!-- Textarea -->
            <div class="form-group">
                <label class="col-md-4 control-label" for="price">Price</label>
                <div class="col-md-4">
                    <textarea class="form-control" id="product-spy-price" name="price" readonly>This will show the price</textarea>
                </div>
            </div>

            <!-- Button -->
            <div class="form-group">
                <label class="col-md-4 control-label" for="submit">Send product</label>
                <div class="col-md-4">
                    <button id="submit" name="submit" class="btn btn-primary">Send</button>
                </div>
            </div>

        </fieldset>
    </form>


</div>
</body>
</html>

This is in console after: console.log($('#xh-bar').contents());

Uncaught SecurityError: Failed to read the 'contentDocument' property from 'HTMLIFrameElement': Blocked a frame with origin "http://stackoverflow.com" from accessing a frame with origin "chrome-extension://haifbndknpepdhjlcnmpoemlmomnidpe". The frame requesting access has a protocol of "http", the frame being accessed has a protocol of "chrome-extension". Protocols must match.

解决方案

As it already answered above - you can not access to iFrame's DOM from page loaded from different than iFrame's URL because of Some Origin Policy.

But you can send message to your iFrame and process it there for setting value of textarea.

You can do it bu that way:

Send message from xpathget.js

...
// Replace your setter
// $('#xh-bar').contents().find('#product-spy-price').val('some_val'); //# THIS SHOULD ALTER THE TEXTAREA
// with
var win = document.getElementById("xh-bar").contentWindow
win.postMessage(
    {"command":"click","value":path},
    chrome.extension.getURL('')
);
...

In bar.html include js file, which listens your message and sets textarea value:

...
function listener(event){
  if("command" in event.data && event.data.command=='click')
  {
      console.log(document.getElementById('product-spy-price').value=event.data.value);
  }
}

if (window.addEventListener){
  addEventListener("message", listener, false)
} else {
  attachEvent("onmessage", listener)
}
...

That's all :)

P.S> It's better to get path to your chrome pages with chrome.extension.getURL('bar.html') instead of hardcoding it - in this case you can change application ID without problems and avoid many and many troubles while support your application.

这篇关于无法更改由Chrome扩展程序生成的iframe中的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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