You must be completely rewrite the code for Firefox, note tabCapture does not support Firefox. Fully code without comments 

```js
var _gaq = _gaq || [];

function scope() {
    var J = chrome.runtime.getManifest().version;
    var e = "11/22/2017";
    _gaq.push(["_setAccount", "UA-64913318-2"]);
    _gaq.push(["_trackPageview"]);
    _gaq.push(["_trackEvent", "backgroundOpen", J]);
    var U = "VERSION";
    var i = "PRESETS";
    var a = "PRESETS.";
    var s = {
        get: function(e, t) {
            t({})
        },
        set: function(e, t) {
            t()
        },
        remove: function(e, t) {
            t()
        }
    };
    var W = null;
    var t = "ears_pro";
    var n = "ears_pro_1";
    var r = "ACTIVE";
    localStorage[" "] = " ";
    s = chrome.storage.sync;
    W = null;
    var o = false;

    function D(e) {
        if (o) {
            console.log(e)
        }
    }(function() {
        var e = document.createElement("script");
        e.type = "text/javascript";
        e.async = true;
        e.src = "https://ssl.google-analytics.com/ga.js";
        var t = document.getElementsByTagName("script")[0];
        t.parentNode.insertBefore(e, t)
    })();
    var M = null;
    var B = null;
    var G = null;
    var Q = null;
    var L = null;
    var V = [];
    var z = [20, 40, 80, 160, 320, 640, 1280, 2560, 5120, 10240, 20480];
    var H = [.7071, .7071, .7071, .7071, .7071, .7071, .7071, .7071, .7071, .7071, .7071];
    var K = 11;
    var X = function() {};
    var Y = {};
    var Z = false;
    var $;

    function l(e) {
        return a + e
    }

    function ee(n) {
        if (!localStorage[i]) {
            localStorage[i] = JSON.stringify({})
        }
        var r = JSON.parse(localStorage[i]);
        if (r == null || typeof r != "object") {
            r = {}
        }
        s.get(null, function(e) {
            if (chrome.runtime.lastError) {
                console.log(chrome.runtime.lastError)
            }
            for (var t in e) {
                if (t.startsWith(a)) {
                    r[t.slice(a.length)] = e[t]
                }
            }
            n(r)
        })
    }

    function te(e, t, n) {
        var r = JSON.parse(localStorage[i]);
        if (r == null || typeof r != "object") {
            r = {}
        }
        var a = Object.keys(r).length;
        r[e] = t;
        var o = Object.keys(r).length;
        if (W && Object.keys(r) > W && o >= a) {
            n();
            return
        }
        localStorage[i] = JSON.stringify(r);
        syncPresets = {};
        syncPresets[l(e)] = t;
        s.set(syncPresets, function() {
            if (chrome.runtime.lastError) {
                console.log(chrome.runtime.lastError)
            }
            n()
        })
    }

    function ne(e, t) {
        _gaq.push(["_trackEvent", "deletePreset", e.preset]);
        var n = JSON.parse(localStorage[i]);
        if (n == null || typeof n != "object") {
            n = {}
        }
        delete n[e.preset];
        localStorage[i] = JSON.stringify(n);
        s.remove(l(e.preset), t)
    }
    chrome.storage.onChanged.addListener(function(e, t) {});

    function c() {
        if (Z) {
            M.close();
            M = null;
            Z = false;
            chrome.runtime.onMessage.removeListener($);
            var e = Object.keys(Y);
            for (var t = 0; t < e.length; t++) {
                var n = e[t];
                Y[n].stream.getTracks()[0].stop();
                delete Y[n]
            }
        }
    }

    function re() {
        return new AudioContext({
            latencyHint: "playback"
        })
    }

    function ae() {
        if (Z) {
            M.close();
            M = null;
            Z = false;
            Q = null;
            L = null;
            var e = Object.values(Y);
            Y = {};
            for (var t = 0; t < e.length; t++) {
                var n = e[t].audioSource;
                n.disconnect(B)
            }
            u(e)
        }
    }

    function u(e) {
        var t = null;
        if (Z) {
            return
        }
        Z = true;
        M = re();
        M.suspend();
        console.log("starting sampleRate: " + M.sampleRate);
        var n = false;
        X = function() {
            if (n) {
                return
            }
            var e = re();
            var t = M.sampleRate && e.sampleRate && M.sampleRate != e.sampleRate;
            if (t) {
                console.log(e);
                console.log(M);
                n = true
            }
            e.close();
            if (t) {
                console.log("sampleRate changed... reloading AudioContext");
                ae()
            }
        };
        B = M.createGain();
        B.gain.value = 1;
        G = M.createGain();
        G.gain.value = m();
        if (t) {
            var r = M.createScriptProcessor(t);
            r.onaudioprocess = function(e) {
                var t = e.inputBuffer;
                var n = e.outputBuffer;
                for (var r = 0; r < n.numberOfChannels; r++) {
                    n.copyToChannel(t.getChannelData(r), r)
                }
            };
            G.connect(r);
            r.connect(M.destination)
        } else {
            G.connect(M.destination)
        }
        if (!localStorage[U]) {
            localStorage[U] = "0.0.0"
        }
        if (localStorage[" "] == " ") {
            if (localStorage["sync"] != " ") {
                ee(function(e) {
                    var t = Object.keys(e);
                    for (var n = 0; n < t.length; n++) {
                        var r = t[n];
                        te(r, e[r], function() {})
                    }
                });
                localStorage["sync"] = " "
            }
        }
        localStorage[U] = J;
        V = [];
        var a = {};

        function o() {
            var e = G;
            var t = false;
            for (var n = V.length - 1; n >= 0; n--) {
                if (V[n].gain.value != 0) {
                    if (!a[n]) {
                        t = true
                    }
                    if (t) {
                        D(n + " -> " + e.idx);
                        V[n].disconnect();
                        V[n].connect(e)
                    }
                    if (a[n]) {
                        t = false
                    }
                    a[n] = true;
                    e = V[n];
                    e.idx = n
                } else {
                    if (a[n]) {
                        a[n] = false;
                        t = true
                    }
                }
            }
            if (t) {
                D("preGain -> " + e.idx);
                B.disconnect();
                B.connect(e)
            }
        }
        for (var i = 0; i < K; i++) {
            var s = M.createBiquadFilter();
            if (i == 0) {
                s.type = "lowshelf"
            } else if (i == K - 1) {
                s.type = "highshelf"
            } else {
                s.type = "peaking"
            }
            var l = "filter" + i;
            var c = localStorage[l];
            if (c) {
                c = JSON.parse(c);
                s.frequency.value = c.f;
                s.gain.value = c.g;
                s.Q.value = c.q
            } else {
                s.frequency.value = z[i];
                s.gain.value = 0;
                s.Q.value = H[i]
            }
            V.push(s);
            localStorage[l] = JSON.stringify({
                f: s.frequency.value,
                g: s.gain.value,
                q: s.Q.value
            })
        }
        B.connect(G);

        function u(e) {
            f = V[e.index];
            f.gain.value = v(e.gain);
            f.frequency.value = p(e.frequency);
            f.Q.value = d(e.q);
            var t = "filter" + e.index;
            localStorage[t] = JSON.stringify({
                f: f.frequency.value,
                g: f.gain.value,
                q: f.Q.value
            });
            o()
        }

        function g(e) {
            if (e > 10) {
                return 10
            }
            if (e < .00316) {
                return .00316
            }
            return e
        }

        function v(e) {
            if (e < -30) {
                return -30
            }
            if (e > 30) {
                return 30
            }
            return e
        }

        function p(e) {
            if (e < 5) {
                return 5
            }
            if (e > 2e4) {
                return 2e4
            }
            return e
        }

        function d(e) {
            if (e < .2) {
                e = .2
            }
            if (e > 11) {
                e = 11
            }
            return e
        }

        function y(e) {
            var t = g(e.gain);
            G.gain.value = g(t);
            h(t)
        }

        function m() {
            if (!localStorage["GAIN"]) {
                localStorage["GAIN"] = JSON.stringify(1)
            }
            return JSON.parse(localStorage["GAIN"])
        }

        function h(e) {
            localStorage["GAIN"] = JSON.stringify(e)
        }

        function S(e) {
            _gaq.push(["_trackEvent", "preset", "save"]);
            var t = [];
            var n = [];
            var r = [];
            for (var a = 0; a < V.length; a++) {
                var o = V[a];
                t.push(o.frequency.value);
                n.push(o.gain.value);
                r.push(o.Q.value)
            }
            var i = {
                frequencies: t,
                gains: n,
                qs: r
            };
            te(e.preset, i, E)
        }

        function q(i) {
            ee(function(e) {
                var t = [];
                var n = [];
                var r = [];
                if (i.preset == "bassBoost") {
                    for (var a = 0; a < z.length; a++) {
                        t.push(z[a]);
                        n.push(0);
                        r.push(H[a])
                    }
                    t[0] = 340;
                    n[0] = 5
                } else {
                    var o = e[i.preset];
                    if (o) {
                        t = o.frequencies;
                        n = o.gains;
                        r = o.qs
                    } else {
                        return
                    }
                }
                _gaq.push(["_trackEvent", "preset", "set"]);
                for (var a = 0; a < t.length; a++) {
                    u({
                        index: a,
                        frequency: t[a],
                        gain: n[a],
                        q: r[a]
                    })
                }
                E()
            })
        }

        function b(t) {
            N(function(e) {
                T(t, e, true);
                o();
                E()
            })
        }

        function _() {
            var e = {
                type: "sendWorkspaceStatus",
                eqFilters: [],
                streams: [],
                gain: G.gain.value
            };
            for (var t = 0; t < V.length; t++) {
                var n = V[t];
                e.eqFilters.push({
                    frequency: n.frequency.value,
                    gain: n.gain.value,
                    type: n.type,
                    q: n.Q.value
                })
            }
            for (var r in Y) {
                var a = Y[r].tab;
                e.streams.push(Y[r].tab)
            }
            chrome.runtime.sendMessage(e)
        }

        function k() {
            chrome.runtime.sendMessage({
                type: "sendSampleRate",
                Fs: M.sampleRate
            })
        }

        function O() {
            ee(function(e) {
                chrome.runtime.sendMessage({
                    type: "sendPresets",
                    presets: e
                })
            })
        }

        function E() {
            w();
            _();
            k();
            O()
        }

        function N(t) {
            chrome.tabs.query({
                currentWindow: true,
                active: true
            }, function(e) {
                if (e.length != 1) {
                    console.error("num active tabs != 1")
                } else {
                    t(e[0])
                }
            })
        }

        function w() {
            N(function(e) {
                chrome.runtime.sendMessage({
                    type: "sendCurrentTabStatus",
                    streaming: e.id in Y
                })
            })
        }

        function T(e, t, n) {
            if (!e) {
                console.log("null stream, aborting");
                return
            }
            if (n) {
                _gaq.push(["_trackEvent", "tabStream", "added"])
            }
            if (Object.keys(Y).length == 0) {
                M.resume()
            }
            if (t.id in Y) {
                console.log("had stream, stopping");
                _gaq.push(["_trackEvent", "tabStream", "hadDuplicate"]);
                Y[t.id].stream.getTracks()[0].stop();
                delete Y[t.id]
            }
            var r = M.createMediaStreamSource(e);
            r.connect(B);
            Y[t.id] = {
                stream: e,
                tab: t,
                audioSource: r
            }
        }
        var R = {};
        var C = {};

        function x(t) {
            console.log(t);
            chrome.windows.get(chrome.windows.WINDOW_ID_CURRENT, null, function(e) {
                if (e.state != "fullscreen") {
                    C[e.id] = e.state
                }
                if (t.fullscreen) {
                    chrome.windows.update(chrome.windows.WINDOW_ID_CURRENT, {
                        state: "fullscreen"
                    }, null)
                } else {
                    chrome.windows.update(chrome.windows.WINDOW_ID_CURRENT, {
                        state: C[e.id] || "fullscreen"
                    }, null)
                }
            });
            if (t.status == "active") {
                R[t.tabId] = t
            } else if (t.status == "stopped" || t.status == "error") {
                delete R[t.tabId]
            }
        }

        function j() {
            _gaq.push(["_trackEvent", "currentTab", "removed"]);
            N(I)
        }

        function I(e) {
            console.log("disconnectedTab id " + e.id);
            if (e.id in Y) {
                _gaq.push(["_trackEvent", "tabStream", "removed"]);
                var t = Y[e.id].stream;
                t.getTracks()[0].stop();
                delete Y[e.id]
            }
            if (Object.keys(Y).length == 0) {
                M.suspend()
            }
            E()
        }

        function P() {
            for (var e = 0; e < K; e++) {
                u({
                    index: e,
                    gain: 0,
                    frequency: z[e],
                    q: H[e]
                })
            }
            y({
                gain: 1
            });
            _gaq.push(["_trackEvent", "filterUpdated", "resetAll"]);
            E()
        }

        function A(e) {
            u({
                index: e.index,
                gain: 0,
                frequency: z[e.index],
                q: H[e.index]
            });
            _gaq.push(["_trackEvent", "filterUpdated", "reset"])
        }

        function F() {
            function t(e, t) {
                var n = document.createElement("a");
                var r = new Blob([t], {
                    type: "text/plain;charset=UTF-8"
                });
                n.href = window.URL.createObjectURL(r);
                n.download = e;
                n.style.display = "none";
                document.body.appendChild(n);
                n.click();
                delete n
            }
            ee(function(e) {
                t("EarsAudioToolkitPresets.json", JSON.stringify(e, null, 2))
            })
        }
        $ = function(e, t, n) {
            if (e.type == "eqTab") {
                if (e.on) {
                    chrome.tabs.getSelected(null, function(e) {
                        if (e.url.startsWith("chrome-extension://" + chrome.runtime.id)) {
                            return
                        }
                        chrome.tabCapture.capture({
                            audio: true,
                            video: false
                        }, b)
                    })
                } else {
                    j()
                }
            }
            if (e.type == "getCurrentTabStatus") {
                w()
            }
            if (e.type == "getWorkspaceStatus") {
                _()
            }
            if (e.type == "getFullRefresh") {
                E()
            }
            if (e.type == "onPopupOpen") {
                X()
            }
            if (e.type == "modifyFilter") {
                u(e)
            }
            if (e.type == "modifyGain") {
                y(e)
            }
            if (e.type == "gainUpdated") {
                _gaq.push(["_trackEvent", "gainUpdated", "gain"])
            }
            if (e.type == "filterUpdated") {
                _gaq.push(["_trackEvent", "filterUpdated", e.filterType])
            }
            if (e.type == "disconnectTab") {
                I(e.tab)
            }
            if (e.type == "resetFilters") {
                P()
            }
            if (e.type == "resetFilter") {
                A(e)
            }
            if (e.type == "preset") {
                q(e)
            }
            if (e.type == "savePreset") {
                S(e)
            }
            if (e.type == "importPresets") {
                var r = e.presets;
                var a = Object.keys(r);
                for (var o = 0; o < a.length; o++) {
                    te(a[o], r[a[o]], E)
                }
            }
            if (e.type == "deletePreset") {
                ne(e, E)
            }
            if (e.type == "exportPresets") {
                F()
            }
            if (e.type == "getFFT") {
                if (W) {
                    chrome.runtime.sendMessage({
                        type: "fft",
                        fft: []
                    });
                    return
                }
                if (Q) {
                    L = performance.now();
                    var i = new Float32Array(Q.frequencyBinCount);
                    Q.getFloatFrequencyData(i);
                    n({
                        type: "fft",
                        fft: Array.from(i)
                    })
                } else {
                    Q = M.createAnalyser();
                    Q.fftSize = 4096 * 2;
                    Q.smoothingTimeConstant = .5;
                    console.log("created analyser");
                    console.log(Q);
                    G.connect(Q);
                    n({
                        type: "fft",
                        fft: []
                    })
                }
            }
        };
        if (e) {
            for (var i = 0; i < e.length; i++) {
                T(e[i].stream, e[i].tab, false)
            }
            o();
            E()
        } else {
            chrome.runtime.onMessage.addListener($);
            chrome.tabCapture.onStatusChanged.addListener(x)
        }
    }
    u();
    setInterval(function() {
        if (L) {
            if (performance.now() - L > 1e3) {
                if (G && Q) {
                    G.disconnect(Q);
                    Q = null;
                    console.log("disconnected analyser")
                }
            }
        }
    }, 1e3)
}
scope();
```