Bug 1336308: Part 4 - Rename `tab` variables that refer to native tabs to avoid confusion. r=aswan
authorKris Maglione <maglione.k@gmail.com>
Fri, 03 Feb 2017 12:57:43 -0800
changeset 340948 ed963c260aef0284094facd6cd14cca29a4fd1e4
parent 340947 4b08a6a4a7faa12759cd3b6cba50cdc9f9761730
child 340949 7129bea759429f6670c350db880431cfed385456
push id86601
push usermaglione.k@gmail.com
push dateMon, 06 Feb 2017 20:27:30 +0000
treeherdermozilla-inbound@7129bea75942 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaswan
bugs1336308
milestone54.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1336308: Part 4 - Rename `tab` variables that refer to native tabs to avoid confusion. r=aswan MozReview-Commit-ID: 5An7K1crYRS
browser/components/extensions/ext-tabs.js
browser/components/extensions/ext-utils.js
mobile/android/components/extensions/ext-tabs.js
mobile/android/components/extensions/ext-utils.js
toolkit/components/extensions/ExtensionTabs.jsm
--- a/browser/components/extensions/ext-tabs.js
+++ b/browser/components/extensions/ext-tabs.js
@@ -53,19 +53,19 @@ extensions.on("page-shutdown", (type, co
     if (context.extension.id !== context.xulBrowser.contentPrincipal.addonId) {
       // Only close extension tabs.
       // This check prevents about:addons from closing when it contains a
       // WebExtension as an embedded inline options page.
       return;
     }
     let {gBrowser} = context.xulBrowser.ownerGlobal;
     if (gBrowser) {
-      let tab = gBrowser.getTabForBrowser(context.xulBrowser);
-      if (tab) {
-        gBrowser.removeTab(tab);
+      let nativeTab = gBrowser.getTabForBrowser(context.xulBrowser);
+      if (nativeTab) {
+        gBrowser.removeTab(nativeTab);
       }
     }
   }
 });
 /* eslint-enable mozilla/balanced-listeners */
 
 let tabListener = {
   tabReadyInitialized: false,
@@ -78,49 +78,50 @@ let tabListener = {
 
       this.tabReadyInitialized = true;
     }
   },
 
   onLocationChange(browser, webProgress, request, locationURI, flags) {
     if (webProgress.isTopLevel) {
       let {gBrowser} = browser.ownerGlobal;
-      let tab = gBrowser.getTabForBrowser(browser);
+      let nativeTab = gBrowser.getTabForBrowser(browser);
 
       // Now we are certain that the first page in the tab was loaded.
-      this.initializingTabs.delete(tab);
+      this.initializingTabs.delete(nativeTab);
 
       // browser.innerWindowID is now set, resolve the promises if any.
-      let deferred = this.tabReadyPromises.get(tab);
+      let deferred = this.tabReadyPromises.get(nativeTab);
       if (deferred) {
-        deferred.resolve(tab);
-        this.tabReadyPromises.delete(tab);
+        deferred.resolve(nativeTab);
+        this.tabReadyPromises.delete(nativeTab);
       }
     }
   },
 
   /**
    * Returns a promise that resolves when the tab is ready.
    * Tabs created via the `tabs.create` method are "ready" once the location
    * changes to the requested URL. Other tabs are assumed to be ready once their
    * inner window ID is known.
    *
-   * @param {XULElement} tab The <tab> element.
+   * @param {XULElement} nativeTab The <tab> element.
    * @returns {Promise} Resolves with the given tab once ready.
    */
-  awaitTabReady(tab) {
-    let deferred = this.tabReadyPromises.get(tab);
+  awaitTabReady(nativeTab) {
+    let deferred = this.tabReadyPromises.get(nativeTab);
     if (!deferred) {
       deferred = PromiseUtils.defer();
-      if (!this.initializingTabs.has(tab) && (tab.linkedBrowser.innerWindowID ||
-                                              tab.linkedBrowser.currentURI.spec === "about:blank")) {
-        deferred.resolve(tab);
+      if (!this.initializingTabs.has(nativeTab) &&
+          (nativeTab.linkedBrowser.innerWindowID ||
+           nativeTab.linkedBrowser.currentURI.spec === "about:blank")) {
+        deferred.resolve(nativeTab);
       } else {
         this.initTabReady();
-        this.tabReadyPromises.set(tab, deferred);
+        this.tabReadyPromises.set(nativeTab, deferred);
       }
     }
     return deferred.promise;
   },
 };
 
 extensions.registerSchemaAPI("tabs", "addon_parent", context => {
   let {extension} = context;
@@ -137,51 +138,51 @@ extensions.registerSchemaAPI("tabs", "ad
   async function promiseTabWhenReady(tabId) {
     let tab;
     if (tabId !== null) {
       tab = tabManager.get(tabId);
     } else {
       tab = tabManager.getWrapper(tabTracker.activeTab);
     }
 
-    await tabListener.awaitTabReady(tab.tab);
+    await tabListener.awaitTabReady(tab.nativeTab);
 
     return tab;
   }
 
   let self = {
     tabs: {
       onActivated: new WindowEventManager(context, "tabs.onActivated", "TabSelect", (fire, event) => {
-        let tab = event.originalTarget;
-        let tabId = tabTracker.getId(tab);
-        let windowId = windowTracker.getId(tab.ownerGlobal);
+        let nativeTab = event.originalTarget;
+        let tabId = tabTracker.getId(nativeTab);
+        let windowId = windowTracker.getId(nativeTab.ownerGlobal);
         fire.async({tabId, windowId});
       }).api(),
 
       onCreated: new SingletonEventManager(context, "tabs.onCreated", fire => {
         let listener = (eventName, event) => {
-          fire.async(tabManager.convert(event.tab));
+          fire.async(tabManager.convert(event.nativeTab));
         };
 
         tabTracker.on("tab-created", listener);
         return () => {
           tabTracker.off("tab-created", listener);
         };
       }).api(),
 
       /**
        * Since multiple tabs currently can't be highlighted, onHighlighted
        * essentially acts an alias for self.tabs.onActivated but returns
        * the tabId in an array to match the API.
        * @see  https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/Tabs/onHighlighted
       */
       onHighlighted: new WindowEventManager(context, "tabs.onHighlighted", "TabSelect", (fire, event) => {
-        let tab = event.originalTarget;
-        let tabIds = [tabTracker.getId(tab)];
-        let windowId = windowTracker.getId(tab.ownerGlobal);
+        let nativeTab = event.originalTarget;
+        let tabIds = [tabTracker.getId(nativeTab)];
+        let windowId = windowTracker.getId(nativeTab.ownerGlobal);
         fire.async({tabIds, windowId});
       }).api(),
 
       onAttached: new SingletonEventManager(context, "tabs.onAttached", fire => {
         let listener = (eventName, event) => {
           fire.async(event.tabId, {newWindowId: event.newWindowId, newPosition: event.newPosition});
         };
 
@@ -231,27 +232,27 @@ extensions.registerSchemaAPI("tabs", "ad
           // Remove the tab from the set on the next tick, since it will already
           // have been moved by then.
           Promise.resolve().then(() => {
             ignoreNextMove.delete(event.target);
           });
         };
 
         let moveListener = event => {
-          let tab = event.originalTarget;
+          let nativeTab = event.originalTarget;
 
-          if (ignoreNextMove.has(tab)) {
-            ignoreNextMove.delete(tab);
+          if (ignoreNextMove.has(nativeTab)) {
+            ignoreNextMove.delete(nativeTab);
             return;
           }
 
-          fire.async(tabTracker.getId(tab), {
-            windowId: windowTracker.getId(tab.ownerGlobal),
+          fire.async(tabTracker.getId(nativeTab), {
+            windowId: windowTracker.getId(nativeTab.ownerGlobal),
             fromIndex: event.detail,
-            toIndex: tab._tPos,
+            toIndex: nativeTab._tPos,
           });
         };
 
         windowTracker.addListener("TabMove", moveListener);
         windowTracker.addListener("TabOpen", openListener);
         return () => {
           windowTracker.removeListener("TabMove", moveListener);
           windowTracker.removeListener("TabOpen", openListener);
@@ -395,122 +396,120 @@ extensions.registerSchemaAPI("tabs", "ad
             }
           }
 
           // Make sure things like about:blank and data: URIs never inherit,
           // and instead always get a NullPrincipal.
           options.disallowInheritPrincipal = true;
 
           tabListener.initTabReady();
-          let tab = window.gBrowser.addTab(url || window.BROWSER_NEW_TAB_URL, options);
+          let nativeTab = window.gBrowser.addTab(url || window.BROWSER_NEW_TAB_URL, options);
 
           let active = true;
           if (createProperties.active !== null) {
             active = createProperties.active;
           }
           if (active) {
-            window.gBrowser.selectedTab = tab;
+            window.gBrowser.selectedTab = nativeTab;
           }
 
           if (createProperties.index !== null) {
-            window.gBrowser.moveTabTo(tab, createProperties.index);
+            window.gBrowser.moveTabTo(nativeTab, createProperties.index);
           }
 
           if (createProperties.pinned) {
-            window.gBrowser.pinTab(tab);
+            window.gBrowser.pinTab(nativeTab);
           }
 
           if (createProperties.url && createProperties.url !== window.BROWSER_NEW_TAB_URL) {
             // We can't wait for a location change event for about:newtab,
             // since it may be pre-rendered, in which case its initial
             // location change event has already fired.
 
             // Mark the tab as initializing, so that operations like
             // `executeScript` wait until the requested URL is loaded in
             // the tab before dispatching messages to the inner window
             // that contains the URL we're attempting to load.
-            tabListener.initializingTabs.add(tab);
+            tabListener.initializingTabs.add(nativeTab);
           }
 
-          return tabManager.convert(tab);
+          return tabManager.convert(nativeTab);
         });
       },
 
       async remove(tabs) {
         if (!Array.isArray(tabs)) {
           tabs = [tabs];
         }
 
         for (let tabId of tabs) {
-          let tab = tabTracker.getTab(tabId);
-          tab.ownerGlobal.gBrowser.removeTab(tab);
+          let nativeTab = tabTracker.getTab(tabId);
+          nativeTab.ownerGlobal.gBrowser.removeTab(nativeTab);
         }
       },
 
       async update(tabId, updateProperties) {
-        let tab = getTabOrActive(tabId);
+        let nativeTab = getTabOrActive(tabId);
 
-        let tabbrowser = tab.ownerGlobal.gBrowser;
+        let tabbrowser = nativeTab.ownerGlobal.gBrowser;
 
         if (updateProperties.url !== null) {
           let url = context.uri.resolve(updateProperties.url);
 
           if (!context.checkLoadURL(url, {dontReportErrors: true})) {
             return Promise.reject({message: `Illegal URL: ${url}`});
           }
 
-          tab.linkedBrowser.loadURI(url);
+          nativeTab.linkedBrowser.loadURI(url);
         }
 
         if (updateProperties.active !== null) {
           if (updateProperties.active) {
-            tabbrowser.selectedTab = tab;
+            tabbrowser.selectedTab = nativeTab;
           } else {
             // Not sure what to do here? Which tab should we select?
           }
         }
         if (updateProperties.muted !== null) {
-          if (tab.muted != updateProperties.muted) {
-            tab.toggleMuteAudio(extension.uuid);
+          if (nativeTab.muted != updateProperties.muted) {
+            nativeTab.toggleMuteAudio(extension.uuid);
           }
         }
         if (updateProperties.pinned !== null) {
           if (updateProperties.pinned) {
-            tabbrowser.pinTab(tab);
+            tabbrowser.pinTab(nativeTab);
           } else {
-            tabbrowser.unpinTab(tab);
+            tabbrowser.unpinTab(nativeTab);
           }
         }
         // FIXME: highlighted/selected, openerTabId
 
-        return tabManager.convert(tab);
+        return tabManager.convert(nativeTab);
       },
 
       async reload(tabId, reloadProperties) {
-        let tab = getTabOrActive(tabId);
+        let nativeTab = getTabOrActive(tabId);
 
         let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
         if (reloadProperties && reloadProperties.bypassCache) {
           flags |= Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE;
         }
-        tab.linkedBrowser.reloadWithFlags(flags);
+        nativeTab.linkedBrowser.reloadWithFlags(flags);
       },
 
       async get(tabId) {
-        let tab = tabTracker.getTab(tabId);
-
-        return tabManager.convert(tab);
+        return tabManager.get(tabId).convert();
       },
 
       getCurrent() {
-        let tab;
+        let tabData;
         if (context.tabId) {
-          tab = tabManager.get(context.tabId).convert();
+          tabData = tabManager.get(context.tabId).convert();
         }
-        return Promise.resolve(tab);
+        return Promise.resolve(tabData);
       },
 
       async query(queryInfo) {
         if (queryInfo.url !== null) {
           if (!extension.hasPermission("tabs")) {
             return Promise.reject({message: 'The "tabs" permission is required to use the query API with the "url" parameter'});
           }
 
@@ -523,17 +522,17 @@ extensions.registerSchemaAPI("tabs", "ad
       },
 
       async captureVisibleTab(windowId, options) {
         let window = windowId == null ?
           windowTracker.topWindow :
           windowTracker.getWindow(windowId, context);
 
         let tab = tabManager.wrapTab(window.gBrowser.selectedTab);
-        await tabListener.awaitTabReady(tab.tab);
+        await tabListener.awaitTabReady(tab.nativeTab);
 
         return tab.capture(context, options);
       },
 
       async detectLanguage(tabId) {
         let tab = await promiseTabWhenReady(tabId);
 
         return tab.sendMessage(context, "Extension:DetectLanguage");
@@ -578,131 +577,131 @@ extensions.registerSchemaAPI("tabs", "ad
             move([tabA, tabB], {index: 0})
               -> tabA to 0, tabB to 1 if tabA and tabB are in the same window
             move([tabA, tabB], {index: 0})
               -> tabA to 0, tabB to 0 if tabA and tabB are in different windows
         */
         let indexMap = new Map();
 
         let tabs = tabIds.map(tabId => tabTracker.getTab(tabId));
-        for (let tab of tabs) {
+        for (let nativeTab of tabs) {
           // If the window is not specified, use the window from the tab.
-          let window = destinationWindow || tab.ownerGlobal;
+          let window = destinationWindow || nativeTab.ownerGlobal;
           let gBrowser = window.gBrowser;
 
           let insertionPoint = indexMap.get(window) || index;
           // If the index is -1 it should go to the end of the tabs.
           if (insertionPoint == -1) {
             insertionPoint = gBrowser.tabs.length;
           }
 
           // We can only move pinned tabs to a point within, or just after,
           // the current set of pinned tabs. Unpinned tabs, likewise, can only
           // be moved to a position after the current set of pinned tabs.
           // Attempts to move a tab to an illegal position are ignored.
           let numPinned = gBrowser._numPinnedTabs;
-          let ok = tab.pinned ? insertionPoint <= numPinned : insertionPoint >= numPinned;
+          let ok = nativeTab.pinned ? insertionPoint <= numPinned : insertionPoint >= numPinned;
           if (!ok) {
             continue;
           }
 
           indexMap.set(window, insertionPoint + 1);
 
-          if (tab.ownerGlobal != window) {
+          if (nativeTab.ownerGlobal != window) {
             // If the window we are moving the tab in is different, then move the tab
             // to the new window.
-            tab = gBrowser.adoptTab(tab, insertionPoint, false);
+            nativeTab = gBrowser.adoptTab(nativeTab, insertionPoint, false);
           } else {
             // If the window we are moving is the same, just move the tab.
-            gBrowser.moveTabTo(tab, insertionPoint);
+            gBrowser.moveTabTo(nativeTab, insertionPoint);
           }
-          tabsMoved.push(tab);
+          tabsMoved.push(nativeTab);
         }
 
-        return tabsMoved.map(tab => tabManager.convert(tab));
+        return tabsMoved.map(nativeTab => tabManager.convert(nativeTab));
       },
 
       duplicate(tabId) {
-        let tab = tabTracker.getTab(tabId);
+        let nativeTab = tabTracker.getTab(tabId);
 
-        let gBrowser = tab.ownerGlobal.gBrowser;
-        let newTab = gBrowser.duplicateTab(tab);
+        let gBrowser = nativeTab.ownerGlobal.gBrowser;
+        let newTab = gBrowser.duplicateTab(nativeTab);
 
         return new Promise(resolve => {
           // We need to use SSTabRestoring because any attributes set before
           // are ignored. SSTabRestored is too late and results in a jump in
           // the UI. See http://bit.ly/session-store-api for more information.
           newTab.addEventListener("SSTabRestoring", function() {
             // As the tab is restoring, move it to the correct position.
 
             // Pinned tabs that are duplicated are inserted
             // after the existing pinned tab and pinned.
-            if (tab.pinned) {
+            if (nativeTab.pinned) {
               gBrowser.pinTab(newTab);
             }
-            gBrowser.moveTabTo(newTab, tab._tPos + 1);
+            gBrowser.moveTabTo(newTab, nativeTab._tPos + 1);
           }, {once: true});
 
           newTab.addEventListener("SSTabRestored", function() {
             // Once it has been restored, select it and return the promise.
             gBrowser.selectedTab = newTab;
 
             resolve(tabManager.convert(newTab));
           }, {once: true});
         });
       },
 
       getZoom(tabId) {
-        let tab = getTabOrActive(tabId);
+        let nativeTab = getTabOrActive(tabId);
 
-        let {ZoomManager} = tab.ownerGlobal;
-        let zoom = ZoomManager.getZoomForBrowser(tab.linkedBrowser);
+        let {ZoomManager} = nativeTab.ownerGlobal;
+        let zoom = ZoomManager.getZoomForBrowser(nativeTab.linkedBrowser);
 
         return Promise.resolve(zoom);
       },
 
       setZoom(tabId, zoom) {
-        let tab = getTabOrActive(tabId);
+        let nativeTab = getTabOrActive(tabId);
 
-        let {FullZoom, ZoomManager} = tab.ownerGlobal;
+        let {FullZoom, ZoomManager} = nativeTab.ownerGlobal;
 
         if (zoom === 0) {
           // A value of zero means use the default zoom factor.
-          return FullZoom.reset(tab.linkedBrowser);
+          return FullZoom.reset(nativeTab.linkedBrowser);
         } else if (zoom >= ZoomManager.MIN && zoom <= ZoomManager.MAX) {
-          FullZoom.setZoom(zoom, tab.linkedBrowser);
+          FullZoom.setZoom(zoom, nativeTab.linkedBrowser);
         } else {
           return Promise.reject({
             message: `Zoom value ${zoom} out of range (must be between ${ZoomManager.MIN} and ${ZoomManager.MAX})`,
           });
         }
 
         return Promise.resolve();
       },
 
       _getZoomSettings(tabId) {
-        let tab = getTabOrActive(tabId);
+        let nativeTab = getTabOrActive(tabId);
 
-        let {FullZoom} = tab.ownerGlobal;
+        let {FullZoom} = nativeTab.ownerGlobal;
 
         return {
           mode: "automatic",
           scope: FullZoom.siteSpecific ? "per-origin" : "per-tab",
           defaultZoomFactor: 1,
         };
       },
 
       getZoomSettings(tabId) {
         return Promise.resolve(this._getZoomSettings(tabId));
       },
 
       setZoomSettings(tabId, settings) {
-        let tab = getTabOrActive(tabId);
+        let nativeTab = getTabOrActive(tabId);
 
-        let currentSettings = this._getZoomSettings(tab.id);
+        let currentSettings = this._getZoomSettings(tabTracker.getId(nativeTab));
 
         if (!Object.keys(settings).every(key => settings[key] === currentSettings[key])) {
           return Promise.reject(`Unsupported zoom settings: ${JSON.stringify(settings)}`);
         }
         return Promise.resolve();
       },
 
       onZoomChange: new SingletonEventManager(context, "tabs.onZoomChange", fire => {
@@ -713,53 +712,53 @@ extensions.registerSchemaAPI("tabs", "ad
         };
 
         // Stores the last known zoom level for each tab's browser.
         // WeakMap[<browser> -> number]
         let zoomLevels = new WeakMap();
 
         // Store the zoom level for all existing tabs.
         for (let window of windowTracker.browserWindows()) {
-          for (let tab of window.gBrowser.tabs) {
-            let browser = tab.linkedBrowser;
+          for (let nativeTab of window.gBrowser.tabs) {
+            let browser = nativeTab.linkedBrowser;
             zoomLevels.set(browser, getZoomLevel(browser));
           }
         }
 
         let tabCreated = (eventName, event) => {
-          let browser = event.tab.linkedBrowser;
+          let browser = event.nativeTab.linkedBrowser;
           zoomLevels.set(browser, getZoomLevel(browser));
         };
 
 
         let zoomListener = event => {
           let browser = event.originalTarget;
 
           // For non-remote browsers, this event is dispatched on the document
           // rather than on the <browser>.
           if (browser instanceof Ci.nsIDOMDocument) {
             browser = browser.defaultView.QueryInterface(Ci.nsIInterfaceRequestor)
                              .getInterface(Ci.nsIDocShell)
                              .chromeEventHandler;
           }
 
           let {gBrowser} = browser.ownerGlobal;
-          let tab = gBrowser.getTabForBrowser(browser);
-          if (!tab) {
+          let nativeTab = gBrowser.getTabForBrowser(browser);
+          if (!nativeTab) {
             // We only care about zoom events in the top-level browser of a tab.
             return;
           }
 
           let oldZoomFactor = zoomLevels.get(browser);
           let newZoomFactor = getZoomLevel(browser);
 
           if (oldZoomFactor != newZoomFactor) {
             zoomLevels.set(browser, newZoomFactor);
 
-            let tabId = tabTracker.getId(tab);
+            let tabId = tabTracker.getId(nativeTab);
             fire.async({
               tabId,
               oldZoomFactor,
               newZoomFactor,
               zoomSettings: self.tabs._getZoomSettings(tabId),
             });
           }
         };
--- a/browser/components/extensions/ext-utils.js
+++ b/browser/components/extensions/ext-utils.js
@@ -44,33 +44,33 @@ global.TabContext = function TabContext(
 
   windowTracker.addListener("progress", this);
   windowTracker.addListener("TabSelect", this);
 
   EventEmitter.decorate(this);
 };
 
 TabContext.prototype = {
-  get(tab) {
-    if (!this.tabData.has(tab)) {
-      this.tabData.set(tab, this.getDefaults(tab));
+  get(nativeTab) {
+    if (!this.tabData.has(nativeTab)) {
+      this.tabData.set(nativeTab, this.getDefaults(nativeTab));
     }
 
-    return this.tabData.get(tab);
+    return this.tabData.get(nativeTab);
   },
 
-  clear(tab) {
-    this.tabData.delete(tab);
+  clear(nativeTab) {
+    this.tabData.delete(nativeTab);
   },
 
   handleEvent(event) {
     if (event.type == "TabSelect") {
-      let tab = event.target;
-      this.emit("tab-select", tab);
-      this.emit("location-change", tab);
+      let nativeTab = event.target;
+      this.emit("tab-select", nativeTab);
+      this.emit("location-change", nativeTab);
     }
   },
 
   onStateChange(browser, webProgress, request, stateFlags, statusCode) {
     let flags = Ci.nsIWebProgressListener;
 
     if (!(~stateFlags & (flags.STATE_IS_WINDOW | flags.STATE_START) ||
           this.lastLocation.has(browser))) {
@@ -78,18 +78,18 @@ TabContext.prototype = {
     }
   },
 
   onLocationChange(browser, webProgress, request, locationURI, flags) {
     let gBrowser = browser.ownerGlobal.gBrowser;
     let lastLocation = this.lastLocation.get(browser);
     if (browser === gBrowser.selectedBrowser &&
         !(lastLocation && lastLocation.equalsExceptRef(browser.currentURI))) {
-      let tab = gBrowser.getTabForBrowser(browser);
-      this.emit("location-change", tab, true);
+      let nativeTab = gBrowser.getTabForBrowser(browser);
+      this.emit("location-change", nativeTab, true);
     }
     this.lastLocation.set(browser, browser.currentURI);
   },
 
   shutdown() {
     windowTracker.removeListener("progress", this);
     windowTracker.removeListener("TabSelect", this);
   },
@@ -147,38 +147,38 @@ class TabTracker extends TabTrackerBase 
     windowTracker.addCloseListener(this._handleWindowClose);
 
     /* eslint-disable mozilla/balanced-listeners */
     this.on("tab-detached", this._handleTabDestroyed);
     this.on("tab-removed", this._handleTabDestroyed);
     /* eslint-enable mozilla/balanced-listeners */
   }
 
-  getId(tab) {
-    if (this._tabs.has(tab)) {
-      return this._tabs.get(tab);
+  getId(nativeTab) {
+    if (this._tabs.has(nativeTab)) {
+      return this._tabs.get(nativeTab);
     }
 
     this.init();
 
     let id = this._nextId++;
-    this.setId(tab, id);
+    this.setId(nativeTab, id);
     return id;
   }
 
-  setId(tab, id) {
-    this._tabs.set(tab, id);
-    this._tabIds.set(id, tab);
+  setId(nativeTab, id) {
+    this._tabs.set(nativeTab, id);
+    this._tabIds.set(id, nativeTab);
   }
 
-  _handleTabDestroyed(event, {tab}) {
-    let id = this._tabs.get(tab);
+  _handleTabDestroyed(event, {nativeTab}) {
+    let id = this._tabs.get(nativeTab);
     if (id) {
-      this._tabs.delete(tab);
-      if (this._tabIds.get(id) === tab) {
+      this._tabs.delete(nativeTab);
+      if (this._tabIds.get(id) === nativeTab) {
         this._tabIds.delete(id);
       }
     }
   }
 
   /**
    * Returns the XUL <tab> element associated with the given tab ID. If no tab
    * with the given ID exists, and no default value is provided, an error is
@@ -187,46 +187,46 @@ class TabTracker extends TabTrackerBase 
    * @param {integer} tabId
    *        The ID of the tab to retrieve.
    * @param {*} default_
    *        The value to return if no tab exists with the given ID.
    * @returns {Element<tab>}
    *        A XUL <tab> element.
    */
   getTab(tabId, default_ = undefined) {
-    let tab = this._tabIds.get(tabId);
-    if (tab) {
-      return tab;
+    let nativeTab = this._tabIds.get(tabId);
+    if (nativeTab) {
+      return nativeTab;
     }
     if (default_ !== undefined) {
       return default_;
     }
     throw new ExtensionError(`Invalid tab ID: ${tabId}`);
   }
 
   /**
    * @param {Event} event
    *        The DOM Event to handle.
    * @private
    */
   handleEvent(event) {
-    let tab = event.target;
+    let nativeTab = event.target;
 
     switch (event.type) {
       case "TabOpen":
         let {adoptedTab} = event.detail;
         if (adoptedTab) {
           this.adoptedTabs.set(adoptedTab, event.target);
 
           // This tab is being created to adopt a tab from a different window.
           // Copy the ID from the old tab to the new.
-          this.setId(tab, this.getId(adoptedTab));
+          this.setId(nativeTab, this.getId(adoptedTab));
 
           adoptedTab.linkedBrowser.messageManager.sendAsyncMessage("Extension:SetTabAndWindowId", {
-            windowId: windowTracker.getId(tab.ownerGlobal),
+            windowId: windowTracker.getId(nativeTab.ownerGlobal),
           });
         }
 
         // We need to delay sending this event until the next tick, since the
         // tab does not have its final index when the TabOpen event is dispatched.
         Promise.resolve().then(() => {
           if (event.detail.adoptedTab) {
             this.emitAttached(event.originalTarget);
@@ -238,21 +238,21 @@ class TabTracker extends TabTrackerBase 
 
       case "TabClose":
         let {adoptedBy} = event.detail;
         if (adoptedBy) {
           // This tab is being closed because it was adopted by a new window.
           // Copy its ID to the new tab, in case it was created as the first tab
           // of a new window, and did not have an `adoptedTab` detail when it was
           // opened.
-          this.setId(adoptedBy, this.getId(tab));
+          this.setId(adoptedBy, this.getId(nativeTab));
 
-          this.emitDetached(tab, adoptedBy);
+          this.emitDetached(nativeTab, adoptedBy);
         } else {
-          this.emitRemoved(tab, false);
+          this.emitRemoved(nativeTab, false);
         }
         break;
     }
   }
 
   /**
    * A private method which is called whenever a new browser window is opened,
    * and dispatches the necessary events for it.
@@ -267,127 +267,127 @@ class TabTracker extends TabTrackerBase 
       // window is about to adopt a tab from another window to replace its
       // initial tab.
       //
       // Note that this event handler depends on running before the
       // delayed startup code in browser.js, which is currently triggered
       // by the first MozAfterPaint event. That code handles finally
       // adopting the tab, and clears it from the arguments list in the
       // process, so if we run later than it, we're too late.
-      let tab = window.arguments[0];
+      let nativeTab = window.arguments[0];
       let adoptedBy = window.gBrowser.tabs[0];
 
-      this.adoptedTabs.set(tab, adoptedBy);
-      this.setId(adoptedBy, this.getId(tab));
+      this.adoptedTabs.set(nativeTab, adoptedBy);
+      this.setId(adoptedBy, this.getId(nativeTab));
 
       // We need to be sure to fire this event after the onDetached event
       // for the original tab.
       let listener = (event, details) => {
-        if (details.tab === tab) {
+        if (details.nativeTab === nativeTab) {
           this.off("tab-detached", listener);
 
           Promise.resolve().then(() => {
             this.emitAttached(details.adoptedBy);
           });
         }
       };
 
       this.on("tab-detached", listener);
     } else {
-      for (let tab of window.gBrowser.tabs) {
-        this.emitCreated(tab);
+      for (let nativeTab of window.gBrowser.tabs) {
+        this.emitCreated(nativeTab);
       }
     }
   }
 
   /**
    * A private method which is called whenever a browser window is closed,
    * and dispatches the necessary events for it.
    *
    * @param {DOMWindow} window
    *        The window being closed.
    * @private
    */
   _handleWindowClose(window) {
-    for (let tab of window.gBrowser.tabs) {
-      if (this.adoptedTabs.has(tab)) {
-        this.emitDetached(tab, this.adoptedTabs.get(tab));
+    for (let nativeTab of window.gBrowser.tabs) {
+      if (this.adoptedTabs.has(nativeTab)) {
+        this.emitDetached(nativeTab, this.adoptedTabs.get(nativeTab));
       } else {
-        this.emitRemoved(tab, true);
+        this.emitRemoved(nativeTab, true);
       }
     }
   }
 
   /**
    * Emits a "tab-attached" event for the given tab element.
    *
-   * @param {NativeTab} tab
+   * @param {NativeTab} nativeTab
    *        The tab element in the window to which the tab is being attached.
    * @private
    */
-  emitAttached(tab) {
-    let newWindowId = windowTracker.getId(tab.ownerGlobal);
-    let tabId = this.getId(tab);
+  emitAttached(nativeTab) {
+    let newWindowId = windowTracker.getId(nativeTab.ownerGlobal);
+    let tabId = this.getId(nativeTab);
 
-    this.emit("tab-attached", {tab, tabId, newWindowId, newPosition: tab._tPos});
+    this.emit("tab-attached", {nativeTab, tabId, newWindowId, newPosition: nativeTab._tPos});
   }
 
   /**
    * Emits a "tab-detached" event for the given tab element.
    *
-   * @param {NativeTab} tab
+   * @param {NativeTab} nativeTab
    *        The tab element in the window from which the tab is being detached.
    * @param {NativeTab} adoptedBy
    *        The tab element in the window to which detached tab is being moved,
    *        and will adopt this tab's contents.
    * @private
    */
-  emitDetached(tab, adoptedBy) {
-    let oldWindowId = windowTracker.getId(tab.ownerGlobal);
-    let tabId = this.getId(tab);
+  emitDetached(nativeTab, adoptedBy) {
+    let oldWindowId = windowTracker.getId(nativeTab.ownerGlobal);
+    let tabId = this.getId(nativeTab);
 
-    this.emit("tab-detached", {tab, adoptedBy, tabId, oldWindowId, oldPosition: tab._tPos});
+    this.emit("tab-detached", {nativeTab, adoptedBy, tabId, oldWindowId, oldPosition: nativeTab._tPos});
   }
 
   /**
    * Emits a "tab-created" event for the given tab element.
    *
-   * @param {NativeTab} tab
+   * @param {NativeTab} nativeTab
    *        The tab element which is being created.
    * @private
    */
-  emitCreated(tab) {
-    this.emit("tab-created", {tab});
+  emitCreated(nativeTab) {
+    this.emit("tab-created", {nativeTab});
   }
 
   /**
    * Emits a "tab-removed" event for the given tab element.
    *
-   * @param {NativeTab} tab
+   * @param {NativeTab} nativeTab
    *        The tab element which is being removed.
    * @param {boolean} isWindowClosing
    *        True if the tab is being removed because the browser window is
    *        closing.
    * @private
    */
-  emitRemoved(tab, isWindowClosing) {
-    let windowId = windowTracker.getId(tab.ownerGlobal);
-    let tabId = this.getId(tab);
+  emitRemoved(nativeTab, isWindowClosing) {
+    let windowId = windowTracker.getId(nativeTab.ownerGlobal);
+    let tabId = this.getId(nativeTab);
 
     // When addons run in-process, `window.close()` is synchronous. Most other
     // addon-invoked calls are asynchronous since they go through a proxy
     // context via the message manager. This includes event registrations such
     // as `tabs.onRemoved.addListener`.
     //
     // So, even if `window.close()` were to be called (in-process) after calling
     // `tabs.onRemoved.addListener`, then the tab would be closed before the
     // event listener is registered. To make sure that the event listener is
     // notified, we dispatch `tabs.onRemoved` asynchronously.
     Services.tm.mainThread.dispatch(() => {
-      this.emit("tab-removed", {tab, tabId, windowId, isWindowClosing});
+      this.emit("tab-removed", {nativeTab, tabId, windowId, isWindowClosing});
     }, Ci.nsIThread.DISPATCH_NORMAL);
   }
 
   getBrowserData(browser) {
     if (browser.ownerGlobal.location.href === "about:addons") {
       // When we're loaded into a <browser> inside about:addons, we need to go up
       // one more level.
       browser = browser.ownerGlobal.QueryInterface(Ci.nsIInterfaceRequestor)
@@ -401,19 +401,19 @@ class TabTracker extends TabTrackerBase 
     };
 
     let {gBrowser} = browser.ownerGlobal;
     // Some non-browser windows have gBrowser but not
     // getTabForBrowser!
     if (gBrowser && gBrowser.getTabForBrowser) {
       result.windowId = windowTracker.getId(browser.ownerGlobal);
 
-      let tab = gBrowser.getTabForBrowser(browser);
-      if (tab) {
-        result.tabId = this.getId(tab);
+      let nativeTab = gBrowser.getTabForBrowser(browser);
+      if (nativeTab) {
+        result.tabId = this.getId(nativeTab);
       }
     }
 
     return result;
   }
 
   get activeTab() {
     let window = windowTracker.topWindow;
@@ -426,78 +426,78 @@ class TabTracker extends TabTrackerBase 
 
 windowTracker = new WindowTracker();
 tabTracker = new TabTracker();
 
 Object.assign(global, {tabTracker, windowTracker});
 
 class Tab extends TabBase {
   get _favIconUrl() {
-    return this.window.gBrowser.getIcon(this.tab);
+    return this.window.gBrowser.getIcon(this.nativeTab);
   }
 
   get audible() {
-    return this.tab.soundPlaying;
+    return this.nativeTab.soundPlaying;
   }
 
   get browser() {
-    return this.tab.linkedBrowser;
+    return this.nativeTab.linkedBrowser;
   }
 
   get cookieStoreId() {
-    return getCookieStoreIdForTab(this, this.tab);
+    return getCookieStoreIdForTab(this, this.nativeTab);
   }
 
   get height() {
     return this.browser.clientHeight;
   }
 
   get index() {
-    return this.tab._tPos;
+    return this.nativeTab._tPos;
   }
 
   get mutedInfo() {
-    let tab = this.tab;
+    let {nativeTab} = this;
 
-    let mutedInfo = {muted: tab.muted};
-    if (tab.muteReason === null) {
+    let mutedInfo = {muted: nativeTab.muted};
+    if (nativeTab.muteReason === null) {
       mutedInfo.reason = "user";
-    } else if (tab.muteReason) {
+    } else if (nativeTab.muteReason) {
       mutedInfo.reason = "extension";
-      mutedInfo.extensionId = tab.muteReason;
+      mutedInfo.extensionId = nativeTab.muteReason;
     }
 
     return mutedInfo;
   }
 
   get pinned() {
-    return this.tab.pinned;
+    return this.nativeTab.pinned;
   }
 
   get active() {
-    return this.tab.selected;
+    return this.nativeTab.selected;
   }
 
   get selected() {
-    return this.tab.selected;
+    return this.nativeTab.selected;
   }
 
   get status() {
-    if (this.tab.getAttribute("busy") === "true") {
+    if (this.nativeTab.getAttribute("busy") === "true") {
       return "loading";
     }
     return "complete";
   }
 
   get width() {
     return this.browser.clientWidth;
   }
 
   get window() {
-    return this.tab.ownerGlobal;
+    return this.nativeTab.ownerGlobal;
   }
 
   get windowId() {
     return windowTracker.getId(this.window);
   }
 
   /**
    * Converts session store data to an object compatible with the return value
@@ -660,18 +660,18 @@ class Window extends WindowBase {
       default:
         throw new Error(`Unexpected window state: ${state}`);
     }
   }
 
   * getTabs() {
     let {tabManager} = this.extension;
 
-    for (let tab of this.window.gBrowser.tabs) {
-      yield tabManager.getWrapper(tab);
+    for (let nativeTab of this.window.gBrowser.tabs) {
+      yield tabManager.getWrapper(nativeTab);
     }
   }
 
   /**
    * Converts session store data to an object compatible with the return value
    * of the convert() method, representing that data.
    *
    * @param {Extension} extension
@@ -690,47 +690,47 @@ class Window extends WindowBase {
       incognito: false,
       type: "normal", // this is always "normal" for a closed window
       // Surely this does not actually work?
       state: this.getState(windowData),
       alwaysOnTop: false,
     };
 
     if (windowData.tabs.length) {
-      result.tabs = windowData.tabs.map(tab => {
-        return Tab.convertFromSessionStoreClosedData(extension, tab);
+      result.tabs = windowData.tabs.map(tabData => {
+        return Tab.convertFromSessionStoreClosedData(extension, tabData);
       });
     }
 
     return result;
   }
 }
 
 Object.assign(global, {Tab, Window});
 
 class TabManager extends TabManagerBase {
   get(tabId, default_ = undefined) {
-    let tab = tabTracker.getTab(tabId, default_);
+    let nativeTab = tabTracker.getTab(tabId, default_);
 
-    if (tab) {
-      return this.getWrapper(tab);
+    if (nativeTab) {
+      return this.getWrapper(nativeTab);
     }
     return default_;
   }
 
-  addActiveTabPermission(tab = tabTracker.activeTab) {
-    return super.addActiveTabPermission(tab);
+  addActiveTabPermission(nativeTab = tabTracker.activeTab) {
+    return super.addActiveTabPermission(nativeTab);
   }
 
-  revokeActiveTabPermission(tab = tabTracker.activeTab) {
-    return super.revokeActiveTabPermission(tab);
+  revokeActiveTabPermission(nativeTab = tabTracker.activeTab) {
+    return super.revokeActiveTabPermission(nativeTab);
   }
 
-  wrapTab(tab) {
-    return new Tab(this.extension, tab, tabTracker.getId(tab));
+  wrapTab(nativeTab) {
+    return new Tab(this.extension, nativeTab, tabTracker.getId(nativeTab));
   }
 }
 
 class WindowManager extends WindowManagerBase {
   get(windowId, context) {
     let window = windowTracker.getWindow(windowId, context);
 
     return this.getWrapper(window);
--- a/mobile/android/components/extensions/ext-tabs.js
+++ b/mobile/android/components/extensions/ext-tabs.js
@@ -53,19 +53,19 @@ extensions.on("page-shutdown", (type, co
     if (context.extension.id !== context.xulBrowser.contentPrincipal.addonId) {
       // Only close extension tabs.
       // This check prevents about:addons from closing when it contains a
       // WebExtension as an embedded inline options page.
       return;
     }
     let {BrowserApp} = context.xulBrowser.ownerGlobal;
     if (BrowserApp) {
-      let tab = BrowserApp.getTabForBrowser(context.xulBrowser);
-      if (tab) {
-        BrowserApp.closeTab(tab);
+      let nativeTab = BrowserApp.getTabForBrowser(context.xulBrowser);
+      if (nativeTab) {
+        BrowserApp.closeTab(nativeTab);
       }
     }
   }
 });
 /* eslint-enable mozilla/balanced-listeners */
 
 function getBrowserWindow(window) {
   return window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDocShell)
@@ -84,49 +84,50 @@ let tabListener = {
 
       this.tabReadyInitialized = true;
     }
   },
 
   onLocationChange(browser, webProgress, request, locationURI, flags) {
     if (webProgress.isTopLevel) {
       let {BrowserApp} = browser.ownerGlobal;
-      let tab = BrowserApp.getTabForBrowser(browser);
+      let nativeTab = BrowserApp.getTabForBrowser(browser);
 
       // Now we are certain that the first page in the tab was loaded.
-      this.initializingTabs.delete(tab);
+      this.initializingTabs.delete(nativeTab);
 
       // browser.innerWindowID is now set, resolve the promises if any.
-      let deferred = this.tabReadyPromises.get(tab);
+      let deferred = this.tabReadyPromises.get(nativeTab);
       if (deferred) {
-        deferred.resolve(tab);
-        this.tabReadyPromises.delete(tab);
+        deferred.resolve(nativeTab);
+        this.tabReadyPromises.delete(nativeTab);
       }
     }
   },
 
   /**
    * Returns a promise that resolves when the tab is ready.
    * Tabs created via the `tabs.create` method are "ready" once the location
    * changes to the requested URL. Other tabs are assumed to be ready once their
    * inner window ID is known.
    *
-   * @param {XULElement} tab The <tab> element.
+   * @param {NativeTab} nativeTab The native tab object.
    * @returns {Promise} Resolves with the given tab once ready.
    */
-  awaitTabReady(tab) {
-    let deferred = this.tabReadyPromises.get(tab);
+  awaitTabReady(nativeTab) {
+    let deferred = this.tabReadyPromises.get(nativeTab);
     if (!deferred) {
       deferred = PromiseUtils.defer();
-      if (!this.initializingTabs.has(tab) && (tab.browser.innerWindowID ||
-                                              tab.browser.currentURI.spec === "about:blank")) {
-        deferred.resolve(tab);
+      if (!this.initializingTabs.has(nativeTab) &&
+          (nativeTab.browser.innerWindowID ||
+           nativeTab.browser.currentURI.spec === "about:blank")) {
+        deferred.resolve(nativeTab);
       } else {
         this.initTabReady();
-        this.tabReadyPromises.set(tab, deferred);
+        this.tabReadyPromises.set(nativeTab, deferred);
       }
     }
     return deferred.promise;
   },
 };
 
 extensions.registerSchemaAPI("tabs", "addon_parent", context => {
   let {extension} = context;
@@ -143,32 +144,32 @@ extensions.registerSchemaAPI("tabs", "ad
   async function promiseTabWhenReady(tabId) {
     let tab;
     if (tabId !== null) {
       tab = tabManager.get(tabId);
     } else {
       tab = tabManager.getWrapper(tabTracker.activeTab);
     }
 
-    await tabListener.awaitTabReady(tab.tab);
+    await tabListener.awaitTabReady(tab.nativeTab);
 
     return tab;
   }
 
   let self = {
     tabs: {
       onActivated: new GlobalEventManager(context, "tabs.onActivated", "Tab:Selected", (fire, data) => {
         let tab = tabManager.get(data.id);
 
         fire.async({tabId: tab.id, windowId: tab.windowId});
       }).api(),
 
       onCreated: new SingletonEventManager(context, "tabs.onCreated", fire => {
         let listener = (eventName, event) => {
-          fire.async(tabManager.convert(event.tab));
+          fire.async(tabManager.convert(event.nativeTab));
         };
 
         tabTracker.on("tab-created", listener);
         return () => {
           tabTracker.off("tab-created", listener);
         };
       }).api(),
 
@@ -228,58 +229,58 @@ extensions.registerSchemaAPI("tabs", "ad
           let [needed, changeInfo] = sanitize(extension, changed);
           if (needed) {
             fire.async(tab.id, changeInfo, tab.convert());
           }
         };
 
         let listener = event => {
           let needed = [];
-          let tab;
+          let nativeTab;
           switch (event.type) {
             case "DOMTitleChanged": {
               let {BrowserApp} = getBrowserWindow(event.target.ownerGlobal);
 
-              tab = BrowserApp.getTabForWindow(event.target.ownerGlobal);
+              nativeTab = BrowserApp.getTabForWindow(event.target.ownerGlobal);
               needed.push("title");
               break;
             }
 
             case "DOMAudioPlaybackStarted":
             case "DOMAudioPlaybackStopped": {
               let {BrowserApp} = event.target.ownerGlobal;
-              tab = BrowserApp.getTabForBrowser(event.originalTarget);
+              nativeTab = BrowserApp.getTabForBrowser(event.originalTarget);
               needed.push("audible");
               break;
             }
           }
 
-          if (!tab) {
+          if (!nativeTab) {
             return;
           }
 
-          tab = tabManager.getWrapper(tab);
+          let tab = tabManager.getWrapper(nativeTab);
           let changeInfo = {};
           for (let prop of needed) {
             changeInfo[prop] = tab[prop];
           }
 
           fireForTab(tab, changeInfo);
         };
 
         let statusListener = ({browser, status, url}) => {
           let {BrowserApp} = browser.ownerGlobal;
-          let tab = BrowserApp.getTabForBrowser(browser);
-          if (tab) {
+          let nativeTab = BrowserApp.getTabForBrowser(browser);
+          if (nativeTab) {
             let changed = {status};
             if (url) {
               changed.url = url;
             }
 
-            fireForTab(tabManager.wrapTab(tab), changed);
+            fireForTab(tabManager.wrapTab(nativeTab), changed);
           }
         };
 
         windowTracker.addListener("status", statusListener);
         windowTracker.addListener("DOMTitleChanged", listener);
         return () => {
           windowTracker.removeListener("status", statusListener);
           windowTracker.removeListener("DOMTitleChanged", listener);
@@ -314,71 +315,71 @@ extensions.registerSchemaAPI("tabs", "ad
           options.tabIndex = createProperties.index;
         }
 
         // Make sure things like about:blank and data: URIs never inherit,
         // and instead always get a NullPrincipal.
         options.disallowInheritPrincipal = true;
 
         tabListener.initTabReady();
-        let tab = BrowserApp.addTab(url, options);
+        let nativeTab = BrowserApp.addTab(url, options);
 
         if (createProperties.url) {
-          tabListener.initializingTabs.add(tab);
+          tabListener.initializingTabs.add(nativeTab);
         }
 
-        return tabManager.convert(tab);
+        return tabManager.convert(nativeTab);
       },
 
       async remove(tabs) {
         if (!Array.isArray(tabs)) {
           tabs = [tabs];
         }
 
         for (let tabId of tabs) {
-          let tab = tabTracker.getTab(tabId);
-          tab.browser.ownerGlobal.BrowserApp.closeTab(tab);
+          let nativeTab = tabTracker.getTab(tabId);
+          nativeTab.browser.ownerGlobal.BrowserApp.closeTab(nativeTab);
         }
       },
 
       async update(tabId, updateProperties) {
-        let tab = getTabOrActive(tabId);
+        let nativeTab = getTabOrActive(tabId);
 
-        let {BrowserApp} = tab.browser.ownerGlobal;
+        let {BrowserApp} = nativeTab.browser.ownerGlobal;
 
         if (updateProperties.url !== null) {
           let url = context.uri.resolve(updateProperties.url);
 
           if (!context.checkLoadURL(url, {dontReportErrors: true})) {
             return Promise.reject({message: `Illegal URL: ${url}`});
           }
 
-          tab.browser.loadURI(url);
+          nativeTab.browser.loadURI(url);
         }
 
         if (updateProperties.active !== null) {
           if (updateProperties.active) {
-            BrowserApp.selectTab(tab);
+            BrowserApp.selectTab(nativeTab);
           } else {
             // Not sure what to do here? Which tab should we select?
           }
         }
         // FIXME: highlighted/selected, muted, pinned, openerTabId
 
-        return tabManager.convert(tab);
+        return tabManager.convert(nativeTab);
       },
 
       async reload(tabId, reloadProperties) {
-        let tab = getTabOrActive(tabId);
+        let nativeTab = getTabOrActive(tabId);
 
         let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
         if (reloadProperties && reloadProperties.bypassCache) {
           flags |= Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE;
         }
-        tab.browser.reloadWithFlags(flags);
+        nativeTab.browser.reloadWithFlags(flags);
       },
 
       async get(tabId) {
         return tabManager.get(tabId).convert();
       },
 
       async getCurrent() {
         if (context.tabId) {
@@ -401,17 +402,17 @@ extensions.registerSchemaAPI("tabs", "ad
       },
 
       async captureVisibleTab(windowId, options) {
         let window = windowId == null ?
           windowTracker.topWindow :
           windowTracker.getWindow(windowId, context);
 
         let tab = tabManager.wrapTab(window.BrowserApp.selectedTab);
-        await tabListener.awaitTabReady(tab.tab);
+        await tabListener.awaitTabReady(tab.nativeTab);
 
         return tab.capture(context, options);
       },
 
       async executeScript(tabId, details) {
         let tab = await promiseTabWhenReady(tabId);
 
         return tab.executeScript(context, details);
--- a/mobile/android/components/extensions/ext-utils.js
+++ b/mobile/android/components/extensions/ext-utils.js
@@ -61,28 +61,28 @@ class ProgressListenerWrapper {
   constructor(window, listener) {
     this.window = window;
     this.listener = listener;
     this.listeners = new WeakMap();
 
     this.flags = Ci.nsIWebProgress.NOTIFY_STATE_ALL |
                  Ci.nsIWebProgress.NOTIFY_LOCATION;
 
-    for (let tab of this.window.BrowserApp.tabs) {
-      this.addBrowserProgressListener(tab.browser);
+    for (let nativeTab of this.window.BrowserApp.tabs) {
+      this.addBrowserProgressListener(nativeTab.browser);
     }
 
     this.window.BrowserApp.deck.addEventListener("TabOpen", this);
   }
 
   destroy() {
     this.window.BrowserApp.deck.removeEventListener("TabOpen", this);
 
-    for (let tab of this.window.BrowserApp.tabs) {
-      this.removeProgressListener(tab.browser);
+    for (let nativeTab of this.window.BrowserApp.tabs) {
+      this.removeProgressListener(nativeTab.browser);
     }
   }
 
   addBrowserProgressListener(browser) {
     this.removeProgressListener(browser);
 
     let listener = new BrowserProgressListener(browser, this.listener, this.flags);
     this.listeners.set(browser, listener);
@@ -168,75 +168,75 @@ class TabTracker extends TabTrackerBase 
       return;
     }
     this.initialized = true;
 
     windowTracker.addListener("TabClose", this);
     windowTracker.addListener("TabOpen", this);
   }
 
-  getId(tab) {
-    return tab.id;
+  getId(nativeTab) {
+    return nativeTab.id;
   }
 
   getTab(id, default_ = undefined) {
     let win = windowTracker.topWindow;
     if (win) {
-      let tab = win.BrowserApp.getTabForId(id);
-      if (tab) {
-        return tab;
+      let nativeTab = win.BrowserApp.getTabForId(id);
+      if (nativeTab) {
+        return nativeTab;
       }
     }
     if (default_ !== undefined) {
       return default_;
     }
     throw new ExtensionError(`Invalid tab ID: ${id}`);
   }
 
   handleEvent(event) {
     const {BrowserApp} = event.target.ownerGlobal;
-    let tab = BrowserApp.getTabForBrowser(event.target);
+    let nativeTab = BrowserApp.getTabForBrowser(event.target);
 
     switch (event.type) {
       case "TabOpen":
-        this.emitCreated(tab);
+        this.emitCreated(nativeTab);
         break;
 
       case "TabClose":
-        this.emitRemoved(tab, false);
+        this.emitRemoved(nativeTab, false);
         break;
     }
   }
 
-  emitCreated(tab) {
-    this.emit("tab-created", {tab});
+  emitCreated(nativeTab) {
+    this.emit("tab-created", {nativeTab});
   }
 
-  emitRemoved(tab, isWindowClosing) {
-    let windowId = windowTracker.getId(tab.browser.ownerGlobal);
-    let tabId = this.getId(tab);
+  emitRemoved(nativeTab, isWindowClosing) {
+    let windowId = windowTracker.getId(nativeTab.browser.ownerGlobal);
+    let tabId = this.getId(nativeTab);
 
     Services.tm.mainThread.dispatch(() => {
-      this.emit("tab-removed", {tab, tabId, windowId, isWindowClosing});
+      this.emit("tab-removed", {nativeTab, tabId, windowId, isWindowClosing});
     }, Ci.nsIThread.DISPATCH_NORMAL);
   }
 
   getBrowserData(browser) {
     let result = {
       tabId: -1,
       windowId: -1,
     };
 
     let {BrowserApp} = browser.ownerGlobal;
     if (BrowserApp) {
       result.windowId = windowTracker.getId(browser.ownerGlobal);
 
-      let tab = BrowserApp.getTabForBrowser(browser);
-      if (tab) {
-        result.tabId = this.getId(tab);
+      let nativeTab = BrowserApp.getTabForBrowser(browser);
+      if (nativeTab) {
+        result.tabId = this.getId(nativeTab);
       }
     }
 
     return result;
   }
 
   get activeTab() {
     let window = windowTracker.topWindow;
@@ -253,53 +253,53 @@ tabTracker = new TabTracker();
 Object.assign(global, {tabTracker, windowTracker});
 
 class Tab extends TabBase {
   get _favIconUrl() {
     return undefined;
   }
 
   get audible() {
-    return this.tab.playingAudio;
+    return this.nativeTab.playingAudio;
   }
 
   get browser() {
-    return this.tab.browser;
+    return this.nativeTab.browser;
   }
 
   get cookieStoreId() {
-    return getCookieStoreIdForTab(this, this.tab);
+    return getCookieStoreIdForTab(this, this.nativeTab);
   }
 
   get height() {
     return this.browser.clientHeight;
   }
 
   get incognito() {
     return PrivateBrowsingUtils.isBrowserPrivate(this.browser);
   }
 
   get index() {
-    return this.window.BrowserApp.tabs.indexOf(this.tab);
+    return this.window.BrowserApp.tabs.indexOf(this.nativeTab);
   }
 
   get mutedInfo() {
     return {muted: false};
   }
 
   get pinned() {
     return false;
   }
 
   get active() {
-    return this.tab.getActive();
+    return this.nativeTab.getActive();
   }
 
   get selected() {
-    return this.tab.getActive();
+    return this.nativeTab.getActive();
   }
 
   get status() {
     if (this.browser.webProgress.isLoadingDocument) {
       return "loading";
     }
     return "complete";
   }
@@ -352,44 +352,44 @@ class Window extends WindowBase {
 
   get state() {
     return "fullscreen";
   }
 
   * getTabs() {
     let {tabManager} = this.extension;
 
-    for (let tab of this.window.BrowserApp.tabs) {
-      yield tabManager.getWrapper(tab);
+    for (let nativeTab of this.window.BrowserApp.tabs) {
+      yield tabManager.getWrapper(nativeTab);
     }
   }
 }
 
 Object.assign(global, {Tab, Window});
 
 class TabManager extends TabManagerBase {
   get(tabId, default_ = undefined) {
-    let tab = tabTracker.getTab(tabId, default_);
+    let nativeTab = tabTracker.getTab(tabId, default_);
 
-    if (tab) {
-      return this.getWrapper(tab);
+    if (nativeTab) {
+      return this.getWrapper(nativeTab);
     }
     return default_;
   }
 
-  addActiveTabPermission(tab = tabTracker.activeTab) {
-    return super.addActiveTabPermission(tab);
+  addActiveTabPermission(nativeTab = tabTracker.activeTab) {
+    return super.addActiveTabPermission(nativeTab);
   }
 
-  revokeActiveTabPermission(tab = tabTracker.activeTab) {
-    return super.revokeActiveTabPermission(tab);
+  revokeActiveTabPermission(nativeTab = tabTracker.activeTab) {
+    return super.revokeActiveTabPermission(nativeTab);
   }
 
-  wrapTab(tab) {
-    return new Tab(this.extension, tab, tab.id);
+  wrapTab(nativeTab) {
+    return new Tab(this.extension, nativeTab, nativeTab.id);
   }
 }
 
 class WindowManager extends WindowManagerBase {
   get(windowId, context) {
     let window = windowTracker.getWindow(windowId, context);
 
     return this.getWrapper(window);
--- a/toolkit/components/extensions/ExtensionTabs.jsm
+++ b/toolkit/components/extensions/ExtensionTabs.jsm
@@ -49,29 +49,29 @@ const {
 /**
  * A platform-independent base class for extension-specific wrappers around
  * native tab objects.
  *
  * @param {Extension} extension
  *        The extension object for which this wrapper is being created. Used to
  *        determine permissions for access to certain properties and
  *        functionality.
- * @param {NativeTab} tab
+ * @param {NativeTab} nativeTab
  *        The native tab object which is being wrapped. The type of this object
  *        varies by platform.
  * @param {integer} id
  *        The numeric ID of this tab object. This ID should be the same for
  *        every extension, and for the lifetime of the tab.
  */
 class TabBase {
-  constructor(extension, tab, id) {
+  constructor(extension, nativeTab, id) {
     this.extension = extension;
     this.tabManager = extension.tabManager;
     this.id = id;
-    this.tab = tab;
+    this.nativeTab = nativeTab;
     this.activeTabWindowID = null;
   }
 
   /**
    * Sends a message, via the given context, to the ExtensionContent running in
    * this tab. The tab's current innerWindowID is automatically added to the
    * recipient filter for the message, and is used to ensure that the message is
    * not processed if the content process navigates to a different content page
@@ -219,17 +219,17 @@ class TabBase {
 
   /**
    * @property {string} _title
    *        Returns the current title of this tab. Does not do any permission
    *        checks.
    *        @readonly
    */
   get _title() {
-    return this.browser.contentTitle || this.tab.label;
+    return this.browser.contentTitle || this.nativeTab.label;
   }
 
 
   /**
    * @property {nsIURI | null} title
    *        Returns the current title of this tab if the extension has permission
    *        to read it, or null otherwise.
    *        @readonly
@@ -1015,24 +1015,24 @@ class TabTrackerBase extends EventEmitte
   }
 
   // The JSDoc validator does not support @returns tags in abstract functions or
   // star functions without return statements.
   /* eslint-disable valid-jsdoc */
   /**
    * Returns the numeric ID for the given native tab.
    *
-   * @param {NativeTab} tab
+   * @param {NativeTab} nativeTab
    *        The native tab for which to return an ID.
    *
    * @returns {integer}
    *        The tab's numeric ID.
    * @abstract
    */
-  getId(tab) {
+  getId(nativeTab) {
     throw new Error("Not implemented");
   }
 
   /**
    * Returns the native tab with the given numeric ID.
    *
    * @param {integer} tabId
    *        The numeric ID of the tab to return.
@@ -1551,95 +1551,95 @@ class TabManagerBase {
 
     this._tabs = new DefaultWeakMap(tab => this.wrapTab(tab));
   }
 
   /**
    * If the extension has requested activeTab permission, grant it those
    * permissions for the current inner window in the given native tab.
    *
-   * @param {NativeTab} tab
+   * @param {NativeTab} nativeTab
    *        The native tab for which to grant permissions.
    */
-  addActiveTabPermission(tab) {
+  addActiveTabPermission(nativeTab) {
     if (this.extension.hasPermission("activeTab")) {
       // Note that, unlike Chrome, we don't currently clear this permission with
       // the tab navigates. If the inner window is revived from BFCache before
       // we've granted this permission to a new inner window, the extension
       // maintains its permissions for it.
-      tab = this.getWrapper(tab);
+      let tab = this.getWrapper(nativeTab);
       tab.activeTabWindowID = tab.innerWindowID;
     }
   }
 
   /**
    * Revoke the extension's activeTab permissions for the current inner window
    * of the given native tab.
    *
-   * @param {NativeTab} tab
+   * @param {NativeTab} nativeTab
    *        The native tab for which to revoke permissions.
    */
-  revokeActiveTabPermission(tab) {
-    this.getWrapper(tab).activeTabWindowID = null;
+  revokeActiveTabPermission(nativeTab) {
+    this.getWrapper(nativeTab).activeTabWindowID = null;
   }
 
   /**
    * Returns true if the extension has requested activeTab permission, and has
    * been granted permissions for the current inner window if this tab.
    *
-   * @param {NativeTab} tab
+   * @param {NativeTab} nativeTab
    *        The native tab for which to check permissions.
    * @returns {boolean}
    *        True if the extension has activeTab permissions for this tab.
    */
-  hasActiveTabPermission(tab) {
-    return this.getWrapper(tab).hasActiveTabPermission;
+  hasActiveTabPermission(nativeTab) {
+    return this.getWrapper(nativeTab).hasActiveTabPermission;
   }
 
   /**
    * Returns true if the extension has permissions to access restricted
    * properties of the given native tab. In practice, this means that it has
    * either requested the "tabs" permission or has activeTab permissions for the
    * given tab.
    *
-   * @param {NativeTab} tab
+   * @param {NativeTab} nativeTab
    *        The native tab for which to check permissions.
    * @returns {boolean}
    *        True if the extension has permissions for this tab.
    */
-  hasTabPermission(tab) {
-    return this.getWrapper(tab).hasTabPermission;
+  hasTabPermission(nativeTab) {
+    return this.getWrapper(nativeTab).hasTabPermission;
   }
 
   /**
    * Returns this extension's TabBase wrapper for the given native tab. This
    * method will always return the same wrapper object for any given native tab.
    *
-   * @param {NativeTab} tab
+   * @param {NativeTab} nativeTab
    *        The tab for which to return a wrapper.
    *
    * @returns {TabBase}
    *        The wrapper for this tab.
    */
-  getWrapper(tab) {
-    return this._tabs.get(tab);
+  getWrapper(nativeTab) {
+    return this._tabs.get(nativeTab);
   }
 
   /**
    * Converts the given native tab to a JSON-compatible object, in the format
    * requried to be returned by WebExtension APIs, which may be safely passed to
    * extension code.
    *
-   * @param {NativeTab} tab
+   * @param {NativeTab} nativeTab
    *        The native tab to convert.
    *
    * @returns {Object}
    */
-  convert(tab) {
-    return this.getWrapper(tab).convert();
+  convert(nativeTab) {
+    return this.getWrapper(nativeTab).convert();
   }
 
   // The JSDoc validator does not support @returns tags in abstract functions or
   // star functions without return statements.
   /* eslint-disable valid-jsdoc */
   /**
    * Returns an iterator of TabBase objects which match the given query info.
    *
@@ -1676,25 +1676,25 @@ class TabManagerBase {
    */
   get(tabId) {
     throw new Error("Not implemented");
   }
 
   /**
    * Returns a new TabBase instance wrapping the given native tab.
    *
-   * @param {NativeTab} tab
+   * @param {NativeTab} nativeTab
    *        The native tab for which to return a wrapper.
    *
    * @returns {TabBase}
    * @protected
    * @abstract
    */
   /* eslint-enable valid-jsdoc */
-  wrapTab(tab) {
+  wrapTab(nativeTab) {
     throw new Error("Not implemented");
   }
 }
 
 /**
  * Manages native browser windows and their wrappers for a particular extension.
  *
  * @param {Extension} extension