Chrome Extensions: Background Script Catch Network

2019-02-15 14:05发布

问题:

I'm developing a small Chrome extension for personal use on a very specific case (website automation) but I've a problem. How can I catch a network error on a background script and call a certain function.

I've implemented this method:

chrome.webRequest.onErrorOccurred.addListener(
  handleNetworkError,
  {urls: ["http://*/*", "https://*/*"]
});

It catches some network errors, from what I see manly ::net errors, DNS failing, networks changed etc.

However today I noticed that HTTP errors like:

GET https://example.com 522 (Origin Connection Time-out)

didn't trigger the listener, how can I make it work on those too?

回答1:

I assume that from the perspective of webRequest / Chrome's network stack, this request actually completed. So you need to hook to some other event, e.g.

function extractStatus(line) {
  var match = line.match(/[^ ]* (\d{3}) (.*)/);
  if(match) {
    return {code: match[1], message: match[2]};
  } else {
    return undefined;
  }
}

chrome.webRequest.onHeadersReceived.addListener(
  function(details) {
    var status = extractStatus(details.statusLine);
    if(status) {
      // Do something based on status.code
    }
  },
  {urls: ["<all_urls>"]}
);

Note that this event is optionally blocking: you can redirect the request if needed.

Obviously, this will create a lot of work for your extension; in the above snippet, the listener is not blocking, but if you do make it blocking it will slow down your Chrome considerably - only use it when absolutely necessary and filter by URL when appropriate.



回答2:

With help of the the user @Xan, I managed to come up with this:

function extractStatus(line) {
    var match = line.match(/[^ ]* (\d{3}) (.*)/);
    if (match)
        return {code: match[1], message: match[2]};
    else
        return undefined;
}   

chrome.tabs.query({active: true, lastFocusedWindow: true }, function(tabsArray) {
    tab = tabsArray[0];
    scope = {urls: ["https://example.com/*"], tabId: tab.id};
    console.log("Listening for errors...");

    // ::net errors
    chrome.webRequest.onErrorOccurred.addListener(handleNetworkError, scope);

    // HTTP errors
    chrome.webRequest.onHeadersReceived.addListener(function(details) {

        var status = extractStatus(details.statusLine);
        if (!status)
            return;

        if (status.code.charAt(0) == '5' || status.code.charAt(0) == '4')
            handleNetworkError();           

    }, scope);
});