Chrome Extension Development - POST to new tab

2019-01-11 14:44发布

问题:

Is there an easy solution to POST dynamically aggregated data into a new tab?

chrome.tabs.create does not have a 'POST' option. Normally I would use

chrome.browserAction.onClicked.addListener(function (t) {
  chrome.tabs.create(
  {
    "url" : "http://super.url",
    "method" : "POST" // oops.. no option.
  });
});

回答1:

You can simply combine these two techniques:

  1. You may execute JavaScript commands by adding javascript: prefix at your address bar or in href values of <a> tags.
  2. Only with JavaScript, you can create a form element and fill it with your data then POST it.

.

function fakePost() {   
    var form = document.createElement("form");
    form.setAttribute("method", "post");
    form.setAttribute("action", "http://cvsguimaraes.altervista.org/fiddles/postcheck.php");
    var params = {userId: 2, action: "delete"};
    for(var key in params) {
        var hiddenField = document.createElement("input");
        hiddenField.setAttribute("type", "hidden");
        hiddenField.setAttribute("name", key);
        hiddenField.setAttribute("value", params[key]);
        form.appendChild(hiddenField);
    }
    document.body.appendChild(form); // Not sure if this step is necessary
    form.submit();
};
//minify function
fakePostCode = fakePost.toString().replace(/(\n|\t)/gm,'');

chrome.browserAction.onClicked.addListener(function (t) {
  chrome.tabs.create({"url" : "javascript:"+fakePostCode+"; fakePost();"});
});

Of course, that's just a dirty hack. If you need something better you can use a XHR Object or elaborate something more like @Xan's answer below.



回答2:

The code in cvsguimaraes' answer works for short data strings, that can fit into a URL. As evidenced by this question, it's not always the case.

Kenny Evitt's answer hints at the solution. I made an implementation for that question, and took time to generalize it. I present it here.

The idea is to open a page bundled with the extension (post.html), supply it with required information via messaging, and perform the POST from that page.

post.html

<html>
  <head>
    <title>Redirecting...</title>
  </head>
  <body>
    <h1>Redirecting...</h1>
    <!-- Decorate as you wish, this is a page that redirects to a final one -->
    <script src="post.js"></script>
  </body>
</html>

post.js

var onMessageHandler = function(message){
  // Ensure it is run only once, as we will try to message twice
  chrome.runtime.onMessage.removeListener(onMessageHandler);

  // code from https://stackoverflow.com/a/7404033/934239
  var form = document.createElement("form");
  form.setAttribute("method", "post");
  form.setAttribute("action", message.url);
  for(var key in message.data) {
    var hiddenField = document.createElement("input");
    hiddenField.setAttribute("type", "hidden");
    hiddenField.setAttribute("name", key);
    hiddenField.setAttribute("value", message.data[key]);
    form.appendChild(hiddenField);
  }
  document.body.appendChild(form);
  form.submit();
}

chrome.runtime.onMessage.addListener(onMessageHandler);

background.js (or other non-content script inside the extension)

function postData(url, data) {
  chrome.tabs.create(
    { url: chrome.runtime.getURL("post.html") },
    function(tab) {
      var handler = function(tabId, changeInfo) {
        if(tabId === tab.id && changeInfo.status === "complete"){
          chrome.tabs.onUpdated.removeListener(handler);
          chrome.tabs.sendMessage(tabId, {url: url, data: data});
        }
      }

      // in case we're faster than page load (usually):
      chrome.tabs.onUpdated.addListener(handler);
      // just in case we're too late with the listener:
      chrome.tabs.sendMessage(tab.id, {url: url, data: data});
    }
  );  
}

// Usage:
postData("http://httpbin.org/post", {"hello": "world", "lorem": "ipsum"});

Note the double messaging: with chrome.tabs.create callback we can't be sure that the listener is ready, nor can we be sure it's not done loading yet (though in my testing, it's always still loading). But better safe than sorry.



回答3:

From @Amman Cheval's comments on the question:

[send] your dynamic data to the background file, creating a new tab which includes a form. Fill up the form using your form using the content using the background file, and then submit the form.

Read up about content scripts on Google's docs first. Then read up on message passing. After you've understood all of that, it'd be fairly simple to send a message from the script, to the background, and to the script of a different tab.