2

I have a Chrome extension I'm trying to adapt to FF. When I try to access local storage, the code is failing. There is no JS error in the console. I am new to FF, so the problem is probably basic. Why is execution stopping on var gettingItem = browser.local.storage.get();

Also, when I load my extension in FF, I don't see an options menu like I do in Chrome. How do I open the options pane?

My manifest:

{
    "manifest_version": 2,
    "name": "My name's mod",
    "short_name": "Mod",
    "version": "1.2.0",
    "description": "Make the ",
    "web_accessible_resources": [
        "base-theme.css",
        "light-theme.css",
        "wider-theme.css",
        "nobg-theme.css"
    ],
    "permissions": [
        "storage",
        "cookies",
        "*://forums.site.com/*"
    ],
    "content_scripts": [{
        "js": [
            "cg-mod.js",
            "cg-forum-class.js",
            "cg-forum-writer.js",           
            "cg-onload.js"
        ],
        "matches": ["https://forums.site.com/*", "http://forums.site.com/*" ]
    }],
    "icons": { 
        "16": "icon16.png",
        "48": "icon48.png",
        "128": "icon128.png" },
    "options_ui": {
        "page": "options.html",
        "chrome_style": true
    }
}

This is the first file being called:

//https://stackoverflow.com/questions/2400935/browser-detection-in-javascript
function IsChrome(){
    var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
    var isChrome = !!window.chrome && !isOpera;              // Chrome 1+
    return isChrome;
}

function IsFirefox()
{
    var isFirefox = typeof InstallTrigger !== 'undefined';   // Firefox 1.0+
    return isFirefox;
}

function GetStorage( callback ){    

    var defaultOptions = {
        Theme: 'wider',
        ShowSignatures: true,
        TheNewlyArrived: false,
        Kickstarter: false,
        Recruitment: false,
        Off: false
    };

    if( IsChrome() )
    {
        chrome.storage.sync.get( defaultOptions, function(items) {
            console.log( "Get Storage for Chrome");
            console.log( items );
            callback( items );
        }); 
    }else if( IsFirefox() ) {
        console.log("is firefox: "+ IsFirefox());
        //browser.storage.sync.get
        var gettingItem = browser.local.storage.get();
        console.log(gettingItem);
        console.log("THE PROBLEM IS HERE ^^");
/*      gettingItem.then((items) => {
            console.log( "Get Storage for Firefox");
            callback( items );
        }); */
    }
}

Then in my onload file, I have this:

/*
Run these commands on startup.
*/

// link the custom CSS as a stylesheet to give it higher priority
function Onload( storage )
{
    console.log( "storage: ");
    console.log( storage );

    // If off is true, they don't want to load the extension...
    if( storage.Off )
        return;

    var link = document.createElement('link');
    if( IsChrome() ){
        link.href = chrome.extension.getURL( 'base-theme.css' );        
    } else if( IsFirefox() ) {
        link.href = browser.extension.getURL( 'base-theme.css' );       
    }
    link.type = 'text/css';
    link.rel = 'stylesheet';
    document.getElementsByTagName("head")[0].appendChild(link);

    var link = document.createElement('link');
    if( IsChrome() ){
        link.href = chrome.extension.getURL( storage.Theme +'-theme.css');
    } else if( IsFirefox() ) {
        link.href = browser.extension.getURL( storage.Theme +'-theme.css');
    }
    link.type = 'text/css';
    link.rel = 'stylesheet';
    document.getElementsByTagName("head")[0].appendChild(link);

    if( ! storage.ShowSignatures )
        ForumWriter.ToggleVisibility( 'Signature' );
}

console.log("get storage pre");
// Call the Google values through a callback
GetStorage( Onload );   
console.log("get storage post"); 

The console reads:

Name says hello! (proves the files are loading in the right oder)
get storage pre  
is firefox: true
phpmeh
  • 1,690
  • 2
  • 19
  • 40
  • `The console reads:` - so, what should it read? – Jaromanda X Aug 11 '17 at 06:31
  • Hi @JaromandaX I added a clarifying edit. It should read `THE PROBLEM IS HERE ^^` – phpmeh Aug 11 '17 at 06:33
  • have you read https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/storage/sync ... at first glance, it looks llike you should be using the same API call, or perhaps `browser.storage.sync.get` – Jaromanda X Aug 11 '17 at 06:35
  • so, if you actually add that console.log to the extension, does it actually log that to the console? – Jaromanda X Aug 11 '17 at 06:36
  • Thanks @JaromandaX I did read that. Based on the parent page, I thought local vs sync'ed storage was just a matter of preference. https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/storage I'll go ahead and see if I can't build it with synced storage. I am concerned that I don't see an options.html page either from the about:debugging menu. Not sure where it is supposed to show up. – phpmeh Aug 11 '17 at 06:39
  • The console.log stops at is firefox: true. It doesn't hit THE PROBLEM IS HERE ^^. I tried that. – phpmeh Aug 11 '17 at 06:39
  • odd that the extension doesn't log any error then! perhaps you need to change your console settings to see the error - or open the browser console (as opposed to the Developer tools console) using Ctrl+Shift+J – Jaromanda X Aug 11 '17 at 06:40
  • Why are you switching between using the `browser.*` and `chrome.*` namespaces based on being in Chrome vs. Firefox. Firefox implements the `chrome.*` namespace (using callbacks, just like Chrome). Thus, for almost everything you should just be able to use `chrome.*` in both Chrome and Firefox. – Makyen Aug 11 '17 at 06:48
  • 1
    `browser.local.storage.get` should be `browser.storage.local.get`. – Makyen Aug 11 '17 at 06:49
  • The design pattern you are using to determine if you are in Firefox or Chrome is inefficient. You are using a function for each one to recompute the information every time you want it. Don't have the functions. Just set a couple variables like `isFirefox` and `isChrome` at the start of your code. It's not something that's going to change part way through executing your code. Thus, there's no reason to calculate it more than once. Given you're only using it to determine `browser.*` vs. `chrome.*`, better would be to set some other variable (e.g. `namespace`) to the one you want and use that. – Makyen Aug 11 '17 at 06:53
  • I agree @Makyen. I'm just trying to make the FF work ATM. Learning the FF side of thing. It only checks in like 3 spots total, but I see how to make it one line too. I didn't know what I was even going for when I started. – phpmeh Aug 11 '17 at 06:55
  • Ha... I had to add an application ID to my manifest, and then the extension worked as is with 0 edits. Thanks for that tip @Makyen !! – phpmeh Aug 11 '17 at 07:03
  • I'm glad I was able to help. I'm quite frustrated with Mozilla only mentioning the `chrome.*` namespace in a small blurb on two pages (one I added). While there are some things that need to be handled differently between Chrome and Firefox, they are largely code-compatible, using the `chrome.*` namespace. Personally, the only time I use the `browser.*` namespace is when answering a WebExtensions question here on SO where the OP is already using `browser.*` and promises. IMO, the use of promises is nice, but it doesn't hold a candle to being able to use the same code in both Chrome and Firefox. – Makyen Aug 11 '17 at 07:28
  • I agree it wasn't readily apparent that you could use the Chrome namespace. Thanks again! Keep doing the good work. :) – phpmeh Aug 13 '17 at 18:26

1 Answers1

1

The problem comes from this line:

browser.local.storage.get()

You've mixed it up a bit, local is a property of storage, and storage a property of browser.

browser.storage.local.get()

But looking at your chrome implementation, you seem to want to access the sync storage instead...

browser.storage.sync.get()

Also. I'd really like to point out that you are doubling your code base and that should be avoided, to ease future maintenance. I suggest you this snippet of code:

var client;
if( IsChrome() ){
    client= chrome;        
} else if( IsFirefox() ) {
    client = browser;       
}

So then you can replace all the snippets that look like this

if( IsChrome() ){
    link.href = chrome.extension.getURL( 'base-theme.css' );        
} else if( IsFirefox() ) {
    link.href = browser.extension.getURL( 'base-theme.css' );       
}

With

link.href = client.extension.getURL( 'base-theme.css' );
Salketer
  • 11,628
  • 2
  • 23
  • 56
  • mannn... i knew there had to be a single keyword, but I couldn't figure it out. I knew browser wasn't working on Chrome! I'll give this a shot. Thanks man – phpmeh Aug 11 '17 at 06:44
  • Weird thing is that you should be seeing an error like "cannot access property storage of undefined" – Salketer Aug 11 '17 at 06:45
  • Thanks. client didn't work on Chrome, which was my problem w/ browser too. I probably could and should have mapped a var. I'll refactor later. Also, I get the Promise { : "pending" } now. I'll work on that now. – phpmeh Aug 11 '17 at 06:51
  • Yes, client wasn't supposed to work right off the bat. You need to define it before. I suggest you start using it now, even if you refactor later... You wouldn't have got this problem if you did. – Salketer Aug 11 '17 at 07:04
  • @Salketer, While using a variable to hold `browser` vs. `chrome` is better then having the exact same code, except the namespace, being switched each time, there's no need for it. Firefox already implements the `chrome.*` namespace with callbacks, just like Chrome. Thus, there is no need to perform any switching or assign `client`. Just use `chrome.*` in both Chrome and Firefox. Firefox is largely code-compatible with Chrome (for those things which Firefox does implement). Obviously, there are some differences, but those are generally in less common areas. – Makyen Aug 11 '17 at 07:43
  • thanks for the addition @Makyen I did not know that. Then yes, that would be the way to go. My suggestion was a generalist approach. – Salketer Aug 11 '17 at 08:01