【问题标题】:How to make a POST request using AJAX in a Chrome Extension?如何在 Chrome 扩展中使用 AJAX 发出 POST 请求?
【发布时间】:2014-07-23 20:58:34
【问题描述】:

当浏览器在我的网页上时,我试图进行 ajax 调用,它运行良好,但一旦我离开我的域,它就会失败。这是一个封闭的系统,用户知道他们正在被跟踪,所以没有任何可疑的事情发生。我在域外的所有内容上都收到错误 406。例如,如果我在 www.mywebpage.com 的 URL 上,脚本可以完美执行,但是一旦我访问 www.yourwebpage.com,它就会返回错误。

我尝试将 manifest.json 中的权限设置为我的 URL、所有 url、特定 url,但它的行为方式相同。这是我的背景.js

chrome.runtime.onMessage.addListener
(
    function(message, sender, sendResponse) 
    {
        if(message.applicationcode=="VALIDAPPLICATIONKEY")
        {
            var salt=message.salt;
            var learnerid=message.learnerid;
            var behaviorkey=message.behaviorkey;
            var behaviorname=message.behaviorname;
            var behaviorkeyname=message.behaviorkeyname;
            chrome.tabs.query
            (
                {active: true}, 
                function(arrayOfTabs) 
                {
                    var data = new FormData();
                    data.append('Salt', salt);
                    data.append('LearnerID', learnerid);
                    data.append('BehaviorKey', behaviorkey);
                    data.append('BehaviorName', behaviorname);
                    data.append('BehaviorKeyName', behaviorkeyname);
                    data.append('BehaviorValue', arrayOfTabs[0].url);
                    var xhr = new XMLHttpRequest();
                    xhr.open('POST', 'https://www.mywebpage.com/myservice.php', true);
                    xhr.onreadystatechange = function() 
                    {
                        if (xhr.readyState == 4) 
                        {
                            // JSON.parse does not evaluate the attacker's scripts.
                            var resp = JSON.parse(xhr.responseText);
                            console.log(resp);
                        }
                    }
                    xhr.send(data);     
                }
            );//end query
            return true;
        }
    }
);//end listener

这是我当前的清单文件。

{
    "manifest_version": 2,
    "name": "Application",
    "description": "Plugin",
    "version": "1.0",
    "background": 
    {
        "scripts": ["jquery.js","background.js"],
         "persistent": true
    },
    "permissions": [
        "tabs","http://www.mywebpage.com/*","https://www.mywebpage.com/*"

    ],
    "browser_action": 
    {
        "default_icon": "icon.png",
        "default_popup": "popup.html"
    },
    "content_scripts": 
    [
        {
            "matches": ["<all_urls>"],
            "js": ["jquery.js","popup.js"]
        }
    ]
}

对此的任何想法或帮助将不胜感激。根据文档here,我正在尝试做的事情是被扩展允许的,并且以有限的方式工作。还是应该按照here 的建议在扩展页面中进行这种类型的操作?我是编写 Chrome 扩展程序的新手,我确信我错过了一些愚蠢的东西。

提前致谢。

【问题讨论】:

  • 您的清单文件在这里至关重要。
  • 出于兴趣,你为什么在onMessage监听器中return true?它告诉 Chrome 期望 sendResponse 被异步调用,但它不会发生在你的 sn-p 中。
  • 这是link 的推荐。我一直在寻找 Stack Overflow 的解决方案:)。如果不需要,请帮助我理解为什么与另一篇文章接受的回复相反。感谢您的疯狂快速响应!
  • 从背景制作ajax而不是内容
  • ajax 请求来自后台。

标签: javascript php ajax google-chrome google-chrome-extension


【解决方案1】:

这是我的解决方案:

manifest.json:

{
    "manifest_version": 2,
    "name": "My Name",
    "description": "My Description.",
    "version": "0.1",
    "background": 
    {
        "scripts": ["jquery.js","background.js"],
        "persistent": true
    },
    "permissions": 
    [
        "tabs",
        "storage"
    ],
    "browser_action": 
    {
        "default_icon": "icon.png",
        "default_popup": "popup.html"
    },
    "content_scripts": 
    [
        {
            "matches": ["https://www.myurl.com/*"],
            "js": ["jquery.js","popup.js"],
            "run_at": "document_end"
        }
    ]
  }

background.js:

var learnerid=0;
// Called when the user clicks on the browser action.
chrome.tabs.onUpdated.addListener
( 
    function (tabId, changeInfo, tab) 
    {
        if (changeInfo.status == 'complete') 
        {
            chrome.tabs.query
            (
                { 
                    active: true 
                }, 
                function (tabs) 
                {
                    if(learnerid!=0)
                    {
                        TrackURL(tabs);
                    }
                    else
                    {
                        console.log("User not logged in yet!");
                    }//end if
                }
            );//end query
        }
    }
);

chrome.runtime.onMessage.addListener
(
    function(message, sender, sendResponse) 
    {
        if(message.applicationcode=="appname")
        {
            learnerid=message.learnerid;
        }//end if
    }
);//end function


function TrackURL(tabs)
{
    $.ajax
    (
        {
            type: "POST",
            url: "http://www.myurl.com/action.php",
            dataType:"json",
            data: 
            {               
                Action: 'TrackURL',
                URL:tabs[0].url,
                Title:tabs[0].title,
                LearnerID:learnerid
            },
            success: function(msg)
            {
                console.log("URL Tracked");
            }//end function
        }
    );//End ajax 

}//end function

popup.js:

document.addEventListener
(
    "starttrack", 
    function(e) 
    {
        startPoll(e.detail);
    }
); 


function startPoll(e)
{
    chrome.runtime.sendMessage
    (
        {
            applicationcode: "myapp",
            learnerid: e,
        }
    ); 
}

来自我的网页:

function SendLearnerID(value)
                  {
                    try
                    {

                        var event = new CustomEvent("starttrack",{'detail': value});
                        document.dispatchEvent(event);
                    }
                    catch(err) 
                    {
                        console.log(err);
                    }   

                  }//end function

我的问题是我的原始事件调用发生在网页内....因此出现 406 错误。希望这对其他人有帮助。

【讨论】:

    【解决方案2】:

    原因:

    幸运的是你是对的......你只是缺少一些简单的东西:

    您需要对您希望此操作处理的任何和每个页面/域/URL 的权限,并且您只为 www.mywebpage.com 在当前manifest.json:

        "permissions": [
          "tabs","http://www.mywebpage.com/*","https://www.mywebpage.com/*"
        ],
    

    解决方案:

    如果您想在背景页面/脚本的上下文中执行此操作,您需要在您的manifest.json中的permissions条目中添加所有网址.如果您想从 内容脚本 执行此操作,则需要将其添加到 content_scripts 条目中。如果您打算在两个地方都这样做,那么在两个条目/部分中添加:

        "permissions": [                //needed for background script
          "tabs","http://*/*","https://*/*"
        ],
        "content_scripts":[             //needed for content script
          ...
          "http://*/*","https://*/*"
          ...
        ]
    

    如果您还希望用户在打开 本地文件 时也能够使用您的扩展程序,则为文件架构/协议添加该权限,如下所示:

        "permissions": [                //needed for background script
          "tabs","http://*/*","https://*/*","file://*/*"
        ],
        "content_scripts":[             //needed for content script
          ...
          "http://*/*","https://*/*"
          ...
        ]
    

    【讨论】:

    • 坦率地说,我不喜欢这个答案。如果 XHR 是从 背景页面的上下文 发送的,这应该不是问题。
    • @Xan:不正确。如果您使用的是后台页面,则需要权限。如果您使用的是内容脚本,那么您也需要在那里设置它们。
    • 我应用 b/c 脚本不在 www.mywebpage.com 的上下文中执行,它在浏览器中加载的页面的上下文中执行,即 document.location 的值.href。因此,内容或后台脚本中的任何代码都将根据它执行或失败,而不是在 XHR 请求的地址上。
    • 这是完全错误的。 对于从后台脚本上下文执行的 XHR,document.location.href 与任何打开的页面无关(准确地说是 chrome-extension://[extension id here]/_generated_background_page.html) .而且这样的XHR不用担心跨域,只要请求地址有主机权限即可。 OP 实际上链接到relevant documentation
    • 其实Content Scripts docs说是允许跨域请求和后台页面策略一致的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多