Seeking guidance on waiting for chrome.storage.sync.get after adding a listener in Chrome

My extension has been successfully modifying some URLs. However, I now need to determine whether the modification feature is enabled in the settings.

chrome.webRequest.onBeforeRequest.addListener
(
    modifyUrl,
    {urls: ['http://somewebsite/*'], types: ['main_frame']},
    ['blocking']
);

The challenge lies in finding a way to wait for the value of the setting within the modifyUrl function before proceeding. Is there a method to achieve this? In languages like C#, I would have utilized something like ManualResetEvent after making the sync.get call.

function modifyUrl(details)
{
    chrome.storage.sync.get("someSetting",
          function (data)
          {
            //I can access the setting here
          }
    );

    //how can I check the setting at this point?
    if(enabled in the setting)
    {
        return {redirectUrl: some different url};
    }
}

Answer №1

Check out this solution on how to return Chrome storage API value without using a function for more details.

To summarize, a blocking onBeforeRequest event is synchronous, meaning it cannot rely on asynchronous functions like chrome.* API callbacks to determine its return value.

The recommended approach is to store the data in a global variable and utilize chrome.storage.onChanged to update it when changes occur elsewhere, particularly if chrome.storage.sync is being used (as it gets updated during profile sync).

var settingEnabled; // global variable
chrome.storage.sync.get("someSetting", function (data) {
    settingEnabled = data.someSetting;
});

chrome.webRequest.onBeforeRequest.addListener(
    modifyUrl,
    {urls: ['http://somewebsite/*'], types: ['main_frame']},
    ['blocking']
);

function modifyUrl(details) {
    if (settingEnabled) {
        return {redirectUrl: 'http://example.com'};
    }
}

chrome.storage.onChanged.addListener(function(changes, area) {
    if (area == "sync" && "someSetting" in changes) {
        settingEnabled = changes.someSetting.newValue;
    }
});

If you want to completely disable processing, you can simply detach the listener:

function toggleListener(enable) {
    if (enable) {
        chrome.webRequest.onBeforeRequest.addListener(
            modifyUrl,
            {urls: ['http://somewebsite/*'], types: ['main_frame']},
            ['blocking']
        );
    } else {
        chrome.webRequest.onBeforeRequest.removeListener(modifyUrl);
    }
}

chrome.storage.onChanged.addListener(function(changes, area) {
    if (area == "sync" && "someSetting" in changes) {
        toggleListener(changes.someSetting.newValue);
    }
});

chrome.storage.sync.get("someSetting", function (data) {
    toggleListener(data.someSetting);
});

Another interesting suggestion is to re-attach onBeforeRequest within the storage.get callback upon updates.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The iOS app icon for React Native is not appearing on the screen

After using XCode 12, I encountered an issue while trying to archive my iOS app. Despite no errors and no issues with app assets, the app icon mysteriously fails to show up. I've tried various solutions, including modifying codes in the pod file and r ...

What is the best way to pinpoint the origin of the element.style being injected by JavaScript?

I've been tasked with updating a client's WordPress website, but I'm still getting acquainted with the overall structure of the site. When looking at the blog page (), I noticed that posts are displayed within a wrapper labeled #blogleft, a ...

Sending Data in Angular JS

Looking for guidance on Angular JS as a newcomer. I have set up a form on my index.html page, and when the user fills in the details and hits submit, I want it to redirect to a details.html page where all the filled-in information can be displayed. HTML ...

What is the best way to create fading text effects in an AngularJS application?

Running an AngularJS web application that showcases three words for 5 seconds each: Hello, World & Goodbye. The controller setup is as follows: self.currentIndex = 0; self.myTexts = ['Hello', 'World', 'Goodbye']; self.cu ...

Follow each step to see the final outcome

I have a Step-by-step form that includes a simple calculation. To calculate section 08, I have a function that subtracts liabilities from assets and displays the result as net equity. $(document).ready(function () { // Calculate section 08 ...

Dynamically divide canvas screens based on fabricjs dropdown selection

I am attempting to implement split screens in fabric js, such as 1, 2, 4, 8, and 16. The screen should split based on the selection from the dropdown menu. Check out my current code where I have successfully uploaded images. If I click on the images, th ...

How can I break down an object with hyphenated key names?

Attempting to perform object destructuring on the following: { name: "Bryan", last-name: "Enid" } However, trying to destructure it like this is not successful: const {name, last-name} = req.body Is there an alternative method to destructure this ...

Is it possible to use Gulp.js to serve src files without browserSync enabled?

Started a fresh project using Yeoman Gulp-Angular generator. I grasp the concept of BrowserSync, but I simply cannot fathom why anyone would put up with their network requests being overwhelmed by it: I am inclined to eliminate BrowserSync from my projec ...

Error encountered in ES6 destructuring syntax

Could you please assist me in figuring out what is causing the issue here: var foo = { bar: 1, baz: 2 }; var { bar, baz } = foo; I encountered an error SyntaxError: Unexpected token {. I am using node v5.4.1 and I am unsure if the problem lies wit ...

Guide to creating a React Hooks counter that relies on the functionality of both a start and stop button

I am looking to create a counter that starts incrementing when the start button is clicked and stops when the stop button is pressed. Additionally, I want the counter to reset to 1 when it reaches a certain value, for example 10. I have tried using setInte ...

Exploring the functionality of Vue.js Multiselect with data

After making a Mounted axios call, I have received some response data from the server which is quite promising. Now, I want to extract a specific part of this data to use as an option in a multiselect :options. Here is what my Vue component looks like: ...

Dragging and Dropping Electron Files into an Inactive Window

I am exploring the implementation of drag and drop functionality within an electron window, utilizing the suggested approach of sandboxing processes. This involves isolating ipcMain from ipcRenderer and creating a bridge through a preload.js script (refer ...

Append a constant string to the conclusion of the route parameter

Using React Router v6.4.1, I am aiming for a consistent conclusion to a series of dynamic routes. Specifically, I want my product detail routes to always end with "-product". For example, if the path is "/shaver-900-product", it should activate my Produc ...

Using the hash(#) symbol in Vue 3 for routing

Even though I am using createWebHistory, my URL still contains a hash symbol like localhost/#/projects. Am I overlooking something in my code? How can I get rid of the # symbol? router const routes: Array<RouteRecordRaw> = [ { path: " ...

How to make multiple requests to populate a single object in MongoDB

I am in the process of developing a forum and I need to find out the number of messages in each topic. In my GetListTopic method, I retrieve the list of topics and then I query the forum_message table to count the messages for each topic in my list: db. ...

Ways to conceal and reveal a different section at the same time (like an accordion)

Looking for guidance on implementing an accordion-style functionality, where clicking a navigation link hides one section and reveals another seamlessly with automatic scrolling to the start of the section (end of the navigation). Any tips or starting poin ...

Next JS throwing internal server error when authenticating with axios

I'm encountering a 500 internal server error when trying to authenticate with Next Auth. I followed the documentation from Next Auth for implementation. import NextAuth from "next-auth"; import CredentialsProvider from "next-auth/provi ...

What are some strategies for establishing communication between sibling components in Vue?

Currently, my Vue app has a structure that includes a "blackout" component for displaying modals and a router-view for various sub-menus. These components are siblings at the same level. <blackout v-if="this.popup.currentPopup"></blacko ...

Attempting to console.log data from within useEffect, but unfortunately no information is being logged

function FetchUserAccounts() { const [userAccounts, setUserAccounts] = useState(); useEffect(() => { async function fetchUserAccountsData() { const response = await fetch( 'https://proton.api.atomicassets.io/atomicassets/v1/a ...

How to customize the color of Navbar pills in Bootstrap 4 to fill the entire height

Is there a way to ensure that the background of nav-items is completely filled with color rather than just partially? I attempted to use Bootstrap pills, but it did not achieve the desired effect. I also experimented with my own CSS, but encountered simil ...