javascript 如何在 Chrome 扩展中使用 AJAX 发出 POST 请求?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24016609/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 01:59:39  来源:igfitidea点击:

How to make a POST request using AJAX in a Chrome Extension?

javascriptphpajaxgoogle-chromegoogle-chrome-extension

提问by ProgrammerWannabe

I am attempting to make an ajax call when the browser is on my webpage it works perfectly but as soon as I leave my domain, it fails. This is for a closed system that user knows they are being tracked so nothing shady going on. I am receiving an error 406 on everything outside of my domain. For example if I on my url of www.mywebpage.com the script executes perfectly, but as soon as I visit www.yourwebpage.com it returns the error.

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

I have tried setting the permissions in the manifest.json to my URL, all urls, specific urls but it behaves the same way. Here is my background.js

我尝试将 manifest.json 中的权限设置为我的 URL、所有 URL、特定 URL,但它的行为方式相同。这是我的 background.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

Here is my current manifest file.

这是我当前的清单文件。

{
    "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"]
        }
    ]
}

Any thoughts or help on this would be greatly appreciated. According to the documentation herewhat I am trying to do is allowed by extensions and does work in a limited fashion. Or should this type of action being taking place in the extension page as suggested here? I am new to writing Chrome extensions and I am sure I am missing something stupid.

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

Thanks in advance.

提前致谢。

回答by ProgrammerWannabe

Here was the solution I had:

这是我的解决方案:

manifest.json:

清单.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:

背景.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:

popup.js:

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


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

From my webpage:

从我的网页:

function SendLearnerID(value)
                  {
                    try
                    {

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

                  }//end function

My problem was where my original event call happened, from within the web page....hence the 406 error. Hope this helps someone else.

我的问题是我原来的事件调用发生的地方,从网页中......因此 406 错误。希望这对其他人有帮助。

回答by Flak DiNenno

Cause:

原因:

Luckily you're right... you are only missing something simple:

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

You need permissions for ANY and EVERY page/domain/URL you want this to work on, and you have only requested permissionsfor www.mywebpage.comin your current manifest.json:

你需要的权限任何和每一个页/域/ URL你想这工作,你只要求权限www.mywebpage.com在当前的manifest.json

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

Solution:

解决方案:

If you want to do this within the context of the background page/script, you need to add all URLs in the permissionsentry in your manifest.json. If you want to do this from a content script, then you need to add it in the content_scriptsentry. If you plan on doing it in both places, then add in both entries/sections:

如果您想在后台页面/脚本的上下文中执行此操作,您需要permissionsmanifest.json. 如果要从内容脚本执行此操作,则需要将其添加到content_scripts条目中。如果您计划在两个地方都这样做,请添加两个条目/部分:

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

if you would also like the user to be able to use your extension when opening local filestoo, then add that a permission for the file schema/protocol, like so:

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

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