Chrome extension (onBeforeRequest) with async functions?

Is it possible within chrome extension to have some async actions?
So, I want to interfere some requests inside the extension, but only in case if some option is checked by the user.

That option is being kept inside chrome.storage, and that is method is not sync.
So, I wrote a small function that makes a promise out of that:

function getIsEnabled() {
    return new Promise(function(resolve) {
      chrome.storage.sync.get(["isEnabled"], function(result) {
        resolve(result.isEnabled);
      });
    });
  }

But I’ve tried to use it like this:

  async function logURL(requestDetails) {


    const enabled = await getIsEnabled();
    if (enabled && someOtherCondition) {
      return { cancel: true };
    }
  }

  chrome.webRequest.onBeforeRequest.addListener(
    logURL,
    {
      urls: [""]
    },
    ["blocking"]
  );

It doesn’t work like this. It does block the needed requests without async/await, but then it does it all the time.

I assume it’s because request happens and it’s not going wait for me to return something.

So, how could I go about this? Maybe there is some other solution.

Selenium Testing – Read Text Injected Into HTML By a Chrome Extension

I’m trying to use Selenium to read text injected by a Chrome Extension. The text is being injected as expected but I cannot figure out how to make the Selenium test to wait for the div to show up and then save the inner text to a variable. I think I’m close but I’m obviously missing something, any pointers would be greatly appreciated! Thanks!

Currently the console.log is returning “Promise { < pending> }”

Snippets:

Chrome Extension Content Script-

chrome.runtime.onMessage.addListener(
  function(request, sender, sendResponse) {

    var para = document.createElement("p");
    para.id = "selenium-container";
    var node = document.createTextNode(request.queryParameters);
    para.appendChild(node);

    window.document.body.appendChild(para);

});

Selenium Test Script –

async function Test() {

    let driver = builder
                    .forBrowser('chrome')
                    .withCapabilities({
                        'browserName': 'chrome',
                        'chromeOptions':
                        {
                            binary: '...',
                            args: [],
                            extensions: ['...']
                        }
                    })
                    .setChromeOptions(options)
                    .build();

    // Tests

    await driver.get('URL-HERE');

    const seleniumContainerElement = By.id("selenium-container");

    await driver.wait(until.elementLocated(seleniumContainerElement, 10000))
                .then( (seleniumContainerElement) => {
                    console.log(seleniumContainerElement.getAttribute('innerHTML'));
                });

...

Forcing Promise resolve order

I have a parser function macroBuilder() going through text and parsing macros.
Some macros resolve to text, and there are also nested macros that require another pass. The function returns a string.

I deal with nesting as:

let fragments = [];
fragments.promises = [];
fragments.push = function() {
  let fragments = this;
  for (let i = 0; i < arguments.length; i++) {
    if (typeof arguments[i].then === 'function') {
      let id =  Date.now() + i + this.length;
      let promise = arguments[i]
        .then( function(id, val) {
          fragments[fragments.indexOf(id)] = val;
        }
        .bind(undefined, id))
        .catch( function(id, err) {
          fragments[fragments.indexOf(id)] = '';
        }
        .bind(undefined, id) );
      this.promises.push(promise);
      arguments[i] = id;
    }
  }
  return Array.prototype.push.apply(this, arguments);
}

At the end, I do:

await Promise.all(fragments.promises).then(pieces => {
  console.log('Promise.all(fragments.promises) resolved');
});

Then when I go through my tokenized text, in a loop, I do:

textMacro(obj) {
  fragments.push(obj['text'])
},
anotherMacro(obj) {
  ...
},
nestedMacro(obj) {
  fragments.push(
    resolveMacro(obj['name'])
      .then(res => {
          return macroBuilder(res);
      }
  );
}

This works fine, expect that my macros that get decoded as text are pushed into the fragments array immediately, while nested macros are decoded on the next pass after all regular macros have been already resolved to text.

I need macros to be processed in the order in which they appear, because processing some macros have side effects and those need to be accounted for, then the next in the order macro is being processed.

Tried dealing with this by converting regular text results into promises so textMacro() function looks like the below:

textMacro(obj) {
  fragments.push(
    new Promise((resolve, reject) => {
      resolve(obj['text']);
    })
  );
}

This way, I hoped everything gets resolved in the correct order. However, my textMacro() and other not-nested type macro resolvers have the Promise resolved right away.

What am I doing wrong?

Any way to make Chrome DevTools break on uncaught errors in nested async functions?

Chrome DevTool’s ability to break on uncaught errors in Promise handlers is a great productivity boost. However, with async/await, it seems to only breaks on uncaught errors thrown from the outermost async function.

As an example, this does break on the uncaught error (try opening the codepen link, opening DevTools, ensuring the debugger is set to break on uncaught errors, and refreshing the page):

https://codepen.io/yaaang/pen/pdmWvp

function sleep() {
  return new Promise(resolve => setTimeout(resolve, 1));
}
async function thrower() {
  await sleep();
  throw '!';
}
thrower();

But nesting the call to thrower in just one more level of async does not trigger a break:

https://codepen.io/yaaang/pen/OOYxyb

...
(async function() {
  await thrower();
})();

Is there any way to make this work? Interestingly, it does work in Firefox (debugger breaks in both examples).

How to debug async functions using Chrome?

Take a look at the following code

async function example () {
  const a = await resolveAfter2Secs(20);
  const b = await resolveAfter4Secs(30);
  return a + b;
}

Is there a recommended standard way to debug this using Chrome dev tools? I’ve read about some options using Canary, but I’m looking for anything similar in Chrome.

Is there currently a way to enable async call stack feature in Chrome?