Zach
Zach

Reputation: 5

chrome.storage.local.get returns undefined during browser startup, but only for a specific value

I am developing a chrome extension, and inside the background script during browser startup I try to get stored variables to update the extension. This works fine the first time, however once I get the variables I then call a networking script, and when that file tries to get a variable it stops working.

Background script:

chrome.storage.local.get(["accessToken", "fileId", "date"], (result) => {
            if(result.accessToken && result.fileId && result.date) {
                axios.defaults.headers.common["Authorization"] = "Bearer " + result.accessToken;

                getLastChanged(result.fileId)
                    .then(date => {
                        if(date !== result.date) {
                            getFile(result.fileId)
                                .then(file => {
                                    chrome.storage.local.set({links:file, date:date});
                                });
                        }
                    })
        });

Networking Script:

 chrome.storage.local.get(["refreshToken"], (result) => {
                if(result.refreshToken){
                    axios.post("https://oauth2.googleapis.com/token", {
                        refresh_token:result.refreshToken,
                        client_id:clientId.installed.client_id,
                        client_secret:clientId.installed.client_secret,
                        grant_type:"refresh_token"
                    }).then(res => {
                        axios.defaults.headers.common["Authorization"] = "Bearer " + res.data.accessToken;
                        chrome.storage.local.set({accessToken:res.data.access_token});
                        resolve();
                    }).catch(err => reject(err));
                }

                reject("no refresh token");
            });

The background script is able to get those three values just fine, but when the networking script tries to get the refresh token it returns undefined. When I check local storage the refresh token is there, and when I open the extension window I run this exact same networking script to check that is it up to date, and it works fine. It is only during browser startup, and only with this one value that is fails.

Upvotes: 0

Views: 1092

Answers (2)

Yuvals
Yuvals

Reputation: 3266

You better access the localStorage from the background script rather than content script directly. Either use chrome.extension.getBackgroundPage to get background script, and then access the storage, or send a message to background_script to get the value you need, and return it back to your content ("network") script. As @wOxxOm suggested turn persistent: false for the background script

Upvotes: 0

woxxom
woxxom

Reputation: 73526

The problem is caused by the fact that during startup Chrome starts the active web page and its content scripts before it starts the extension's persistent background page (declared without "persistent": false in manifest.json), see crbug.com/314686 and crbug.com/767844.

You can wait until the background page sets the value:

readOrWaitStorage('refreshToken').then(refreshToken => {
  axios.post('https://oauth2.googleapis.com/token', {
    refresh_token: refreshToken,
    // ......................
  });
});

function readOrWaitStorage(key) {
  return new Promise(resolve => {
    chrome.storage.local.get(key, data => {
      if (key in data) {
        resolve(data[key]);
        return;
      }
      chrome.storage.onChanged.addListener(function fn(changes) {
        if (key in changes) {
          chrome.storage.onChanged.removeListener(fn);
          resolve(changes[key].newValue);
        }
      });
    });
  });
}

Or you can switch to "persistent": false background script and use messaging.

Upvotes: 2

Related Questions