Backed out 2 changesets (bug 1500479) for failing bc at browser/components/extensions/test/browser/browser_ext_tabs_events.js on a CLOSED TREE
authorAndreea Pavel <apavel@mozilla.com>
Wed, 14 Nov 2018 21:09:19 +0200
changeset 502665 438b2437a3a7dbc542811c79f11144e8b6b62fbf
parent 502664 b750cfc5a0fc392225d6e0c3892d6dceaa97b0d8
child 502666 debe7b5d5bbc9d10205517f42d93a5a1d5e72bb2
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1500479
milestone65.0a1
backs out6f209bee42c5a07163c89d21beb7e7062e2c75b1
02ea631f55c3ad689fff3e24df75e810cbe042ad
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
Backed out 2 changesets (bug 1500479) for failing bc at browser/components/extensions/test/browser/browser_ext_tabs_events.js on a CLOSED TREE Backed out changeset 6f209bee42c5 (bug 1500479) Backed out changeset 02ea631f55c3 (bug 1500479)
browser/components/extensions/parent/ext-browser.js
browser/components/extensions/parent/ext-tabs.js
browser/components/extensions/schemas/tabs.json
browser/components/extensions/test/browser/browser-common.ini
browser/components/extensions/test/browser/browser_ext_tabs_events.js
browser/components/extensions/test/browser/browser_ext_tabs_successors.js
mobile/android/base/java/org/mozilla/gecko/Tabs.java
mobile/android/components/extensions/ext-tabs.js
mobile/android/components/extensions/ext-utils.js
mobile/android/components/extensions/schemas/tabs.json
mobile/android/components/extensions/test/mochitest/test_ext_tabs_events.html
toolkit/components/extensions/parent/ext-tabs-base.js
--- a/browser/components/extensions/parent/ext-browser.js
+++ b/browser/components/extensions/parent/ext-browser.js
@@ -483,17 +483,17 @@ class TabTracker extends TabTrackerBase 
       case "TabSelect":
         // Because we are delaying calling emitCreated above, we also need to
         // delay sending this event because it shouldn't fire before onCreated.
         Promise.resolve().then(() => {
           if (!nativeTab.parentNode) {
             // If the tab is already be destroyed, do nothing.
             return;
           }
-          this.emitActivated(nativeTab, event.detail.previousTab);
+          this.emitActivated(nativeTab);
         });
         break;
 
       case "TabMultiSelect":
         if (this.has("tabs-highlighted")) {
           // Because we are delaying calling emitCreated above, we also need to
           // delay sending this event because it shouldn't fire before onCreated.
           Promise.resolve().then(() => {
@@ -566,24 +566,21 @@ class TabTracker extends TabTrackerBase 
     }
   }
 
   /**
    * Emits a "tab-activated" event for the given tab element.
    *
    * @param {NativeTab} nativeTab
    *        The tab element which has been activated.
-   * @param {NativeTab} previousTab
-   *        The tab element which was previously activated.
    * @private
    */
-  emitActivated(nativeTab, previousTab = undefined) {
+  emitActivated(nativeTab) {
     this.emit("tab-activated", {
       tabId: this.getId(nativeTab),
-      previousTabId: previousTab && !previousTab.closing ? this.getId(previousTab) : undefined,
       windowId: windowTracker.getId(nativeTab.ownerGlobal)});
   }
 
   /**
    * Emits a "tabs-highlighted" event for the given tab element.
    *
    * @param {ChromeWindow} window
    *        The window in which the active tab or the set of multiselected tabs changed.
@@ -775,21 +772,16 @@ class Tab extends TabBase {
   get isArticle() {
     return this.nativeTab.linkedBrowser.isArticle;
   }
 
   get isInReaderMode() {
     return this.url && this.url.startsWith(READER_MODE_PREFIX);
   }
 
-  get successorTabId() {
-    const {successor} = this.nativeTab;
-    return successor ? tabTracker.getId(successor) : -1;
-  }
-
   /**
    * Converts session store data to an object compatible with the return value
    * of the convert() method, representing that data.
    *
    * @param {Extension} extension
    *        The extension for which to convert the data.
    * @param {Object} tabData
    *        Session store data for a closed tab, as returned by
--- a/browser/components/extensions/parent/ext-tabs.js
+++ b/browser/components/extensions/parent/ext-tabs.js
@@ -26,18 +26,16 @@ var {
 } = ExtensionUtils;
 
 const TABHIDE_PREFNAME = "extensions.webextensions.tabhide.enabled";
 const MULTISELECT_PREFNAME = "browser.tabs.multiselect";
 XPCOMUtils.defineLazyPreferenceGetter(this, "gMultiSelectEnabled", MULTISELECT_PREFNAME, false);
 
 const TAB_HIDE_CONFIRMED_TYPE = "tabHideNotification";
 
-const TAB_ID_NONE = -1;
-
 
 XPCOMUtils.defineLazyGetter(this, "tabHidePopup", () => {
   return new ExtensionControlledPopup({
     confirmedType: TAB_HIDE_CONFIRMED_TYPE,
     anchorId: "alltabs-button",
     popupnotificationId: "extension-tab-hide-notification",
     descriptionId: "extension-tab-hide-notification-description",
     descriptionMessageId: "tabHideControlled.message",
@@ -724,29 +722,16 @@ this.tabs = class extends ExtensionAPI {
           }
           if (updateProperties.openerTabId !== null) {
             let opener = tabTracker.getTab(updateProperties.openerTabId);
             if (opener.ownerDocument !== nativeTab.ownerDocument) {
               return Promise.reject({message: "Opener tab must be in the same window as the tab being updated"});
             }
             tabTracker.setOpener(nativeTab, opener);
           }
-          if (updateProperties.successorTabId !== null) {
-            let successor = null;
-            if (updateProperties.successorTabId !== TAB_ID_NONE) {
-              successor = tabTracker.getTab(updateProperties.successorTabId, null);
-              if (!successor) {
-                throw new ExtensionError("Invalid successorTabId");
-              }
-              if (successor.ownerDocument !== nativeTab.ownerDocument) {
-                throw new ExtensionError("Successor tab must be in the same window as the tab being updated");
-              }
-            }
-            tabbrowser.setSuccessor(nativeTab, successor);
-          }
 
           return tabManager.convert(nativeTab);
         },
 
         async reload(tabId, reloadProperties) {
           let nativeTab = getTabOrActive(tabId);
 
           let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
@@ -1250,67 +1235,16 @@ this.tabs = class extends ExtensionAPI {
           if (!tab.isInReaderMode && !tab.isArticle) {
             throw new ExtensionError("The specified tab cannot be placed into reader mode.");
           }
           tab = getTabOrActive(tabId);
 
           tab.linkedBrowser.messageManager.sendAsyncMessage("Reader:ToggleReaderMode");
         },
 
-        moveInSuccession(tabIds, tabId, options) {
-          const {insert, append} = options || {};
-          const tabIdSet = new Set(tabIds);
-          if (tabIdSet.size !== tabIds.length) {
-            throw new ExtensionError("IDs must not occur more than once in tabIds");
-          }
-          if ((append || insert) && tabIdSet.has(tabId)) {
-            throw new ExtensionError("Value of tabId must not occur in tabIds if append or insert is true");
-          }
-
-          const referenceTab = tabTracker.getTab(tabId, null);
-          let referenceWindow = referenceTab && referenceTab.ownerGlobal;
-          let previousTab, lastSuccessor;
-          if (append) {
-            previousTab = referenceTab;
-            lastSuccessor = (insert && referenceTab && referenceTab.successor) || null;
-          } else {
-            lastSuccessor = referenceTab;
-          }
-
-          let firstTab;
-          for (const tabId of tabIds) {
-            const tab = tabTracker.getTab(tabId, null);
-            if (tab === null) {
-              continue;
-            }
-            if (referenceWindow === null) {
-              referenceWindow = tab.ownerGlobal;
-            } else if (tab.ownerGlobal !== referenceWindow) {
-              continue;
-            }
-            referenceWindow.gBrowser.replaceInSuccession(tab, tab.successor);
-            if (append && tab === lastSuccessor) {
-              lastSuccessor = tab.successor;
-            }
-            if (previousTab) {
-              referenceWindow.gBrowser.setSuccessor(previousTab, tab);
-            } else {
-              firstTab = tab;
-            }
-            previousTab = tab;
-          }
-
-          if (previousTab) {
-            if (!append && insert && lastSuccessor !== null) {
-              referenceWindow.gBrowser.replaceInSuccession(lastSuccessor, firstTab);
-            }
-            referenceWindow.gBrowser.setSuccessor(previousTab, lastSuccessor);
-          }
-        },
-
         show(tabIds) {
           if (!Services.prefs.getBoolPref(TABHIDE_PREFNAME, false)) {
             throw new ExtensionError(`tabs.show is currently experimental and must be enabled with the ${TABHIDE_PREFNAME} preference.`);
           }
 
           if (!Array.isArray(tabIds)) {
             tabIds = [tabIds];
           }
--- a/browser/components/extensions/schemas/tabs.json
+++ b/browser/components/extensions/schemas/tabs.json
@@ -97,18 +97,17 @@
           "width": {"type": "integer", "optional": true, "description": "The width of the tab in pixels."},
           "height": {"type": "integer", "optional": true, "description": "The height of the tab in pixels."},
           "hidden": {"type": "boolean", "optional": true, "description": "True if the tab is hidden."},
           "sessionId": {"type": "string", "optional": true, "description": "The session ID used to uniquely identify a Tab obtained from the $(ref:sessions) API."},
           "cookieStoreId": {"type": "string", "optional": true, "description": "The CookieStoreId used for the tab."},
           "isArticle": {"type": "boolean", "optional": true, "description": "Whether the document in the tab can be rendered in reader mode."},
           "isInReaderMode": {"type": "boolean", "optional": true, "description": "Whether the document in the tab is being rendered in reader mode."},
           "sharingState": {"$ref": "SharingState", "optional": true, "description": "Current tab sharing state for screen, microphone and camera."},
-          "attention": {"type": "boolean", "optional": true, "description": "Whether the tab is drawing attention."},
-          "successorTabId": {"type": "integer", "optional": true, "minimum": -1, "description": "The ID of this tab's successor, if any; $(ref:tabs.TAB_ID_NONE) otherwise."}
+          "attention": {"type": "boolean", "optional": true, "description": "Whether the tab is drawing attention."}
         }
       },
       {
         "id": "ZoomSettingsMode",
         "type": "string",
         "description": "Defines how zoom changes are handled, i.e. which entity is responsible for the actual scaling of the page; defaults to <code>automatic</code>.",
         "enum": [
           {
@@ -884,22 +883,16 @@
                 "minimum": 0,
                 "optional": true,
                 "description": "The ID of the tab that opened this tab. If specified, the opener tab must be in the same window as this tab."
               },
               "loadReplace": {
                 "type": "boolean",
                 "optional": true,
                 "description": "Whether the load should replace the current history entry for the tab."
-              },
-              "successorTabId": {
-                "type": "integer",
-                "minimum": -1,
-                "optional": true,
-                "description": "The ID of this tab's successor. If specified, the successor tab must be in the same window as this tab."
               }
             }
           },
           {
             "type": "function",
             "name": "callback",
             "optional": true,
             "parameters": [
@@ -1398,58 +1391,16 @@
             "name": "tabIds",
             "description": "The TAB ID or list of TAB IDs to hide.",
             "choices": [
               {"type": "integer", "minimum": 0},
               {"type": "array", "items": {"type": "integer", "minimum": 0}}
             ]
           }
         ]
-      },
-      {
-        "name": "moveInSuccession",
-        "type": "function",
-        "async": true,
-        "description": "Removes an array of tabs from their lines of succession and prepends or appends them in a chain to another tab.",
-        "parameters": [
-          {
-            "name": "tabIds",
-            "type": "array",
-            "items": { "type": "integer", "minimum": 0 },
-            "minItems": 1,
-            "description": "An array of tab IDs to move in the line of succession. For each tab in the array, the tab's current predecessors will have their successor set to the tab's current successor, and each tab will then be set to be the successor of the previous tab in the array. Any tabs not in the same window as the tab indicated by the second argument (or the first tab in the array, if no second argument) will be skipped."
-          },
-          {
-            "name": "tabId",
-            "type": "integer",
-            "optional": true,
-            "default": -1,
-            "minimum": -1,
-            "description": "The ID of a tab to set as the successor of the last tab in the array, or $(ref:tabs.TAB_ID_NONE) to leave the last tab without a successor. If options.append is true, then this tab is made the predecessor of the first tab in the array instead."
-          },
-          {
-            "name": "options",
-            "type": "object",
-            "optional": true,
-            "properties": {
-              "append": {
-                "type": "boolean",
-                "optional": true,
-                "default": false,
-                "description": "Whether to move the tabs before (false) or after (true) tabId in the succession. Defaults to false."
-              },
-              "insert": {
-                "type": "boolean",
-                "optional": true,
-                "default": false,
-                "description": "Whether to link up the current predecessors or successor (depending on options.append) of tabId to the other side of the chain after it is prepended or appended. If true, one of the following happens: if options.append is false, the first tab in the array is set as the successor of any current predecessors of tabId; if options.append is true, the current successor of tabId is set as the successor of the last tab in the array. Defaults to false."
-              }
-            }
-          }
-        ]
       }
     ],
     "events": [
       {
         "name": "onCreated",
         "type": "function",
         "description": "Fired when a tab is created. Note that the tab's URL may not be set at the time this event fired, but you can listen to onUpdated events to be notified when a URL is set.",
         "parameters": [
@@ -1629,22 +1580,16 @@
             "type": "object",
             "name": "activeInfo",
             "properties": {
               "tabId": {
                 "type": "integer",
                 "minimum": 0,
                 "description": "The ID of the tab that has become active."
               },
-              "previousTabId": {
-                "type": "integer",
-                "minimum": 0,
-                "optional": true,
-                "description": "The ID of the tab that was previously active, if that tab is still open."
-              },
               "windowId": {
                 "type": "integer",
                 "minimum": 0,
                 "description": "The ID of the window the active tab changed inside of."
               }
             }
           }
         ]
--- a/browser/components/extensions/test/browser/browser-common.ini
+++ b/browser/components/extensions/test/browser/browser-common.ini
@@ -217,17 +217,16 @@ skip-if = (verify && !debug && (os == 'm
 [browser_ext_tabs_query.js]
 [browser_ext_tabs_readerMode.js]
 [browser_ext_tabs_reload.js]
 [browser_ext_tabs_reload_bypass_cache.js]
 [browser_ext_tabs_saveAsPDF.js]
 skip-if = os == 'mac' # Save as PDF not supported on Mac OS X
 [browser_ext_tabs_sendMessage.js]
 [browser_ext_tabs_sharingState.js]
-[browser_ext_tabs_successors.js]
 [browser_ext_tabs_cookieStoreId.js]
 [browser_ext_tabs_update.js]
 [browser_ext_tabs_update_highlighted.js]
 [browser_ext_tabs_update_url.js]
 [browser_ext_tabs_zoom.js]
 [browser_ext_themes_icons.js]
 [browser_ext_themes_validation.js]
 [browser_ext_url_overrides_newtab.js]
--- a/browser/components/extensions/test/browser/browser_ext_tabs_events.js
+++ b/browser/components/extensions/test/browser/browser_ext_tabs_events.js
@@ -405,86 +405,8 @@ add_task(async function testLastTabRemov
   BrowserTestUtils.removeTab(newWin.gBrowser.selectedTab);
 
   const actualDims = await extension.awaitMessage("tabCreated");
   is(actualDims, expectedDims, "created tab reports a size same to the removed last tab");
 
   await extension.unload();
   await BrowserTestUtils.closeWindow(newWin);
 });
-
-add_task(async function testTabActivationEvent() {
-  async function background() {
-    function makeExpectable() {
-      let expectation = null, resolver = null;
-      const expectable = param => {
-        if (expectation === null) {
-          browser.test.fail("unexpected call to expectable");
-        } else {
-          try {
-            resolver(expectation(param));
-          } catch (e) {
-            resolver(Promise.reject(e));
-          } finally {
-            expectation = null;
-          }
-        }
-      };
-      expectable.expect = e => {
-        expectation = e;
-        return new Promise(r => { resolver = r; });
-      };
-      return expectable;
-    }
-    try {
-      const listener = makeExpectable();
-      browser.tabs.onActivated.addListener(listener);
-
-      const [, {tabs: [tab1]}] = await Promise.all([
-        listener.expect(info => {
-          browser.test.assertEq(undefined, info.previousTabId, "previousTabId should not be defined when window is first opened");
-        }),
-        browser.windows.create({url: "about:blank"}),
-      ]);
-      const [, tab2] = await Promise.all([
-        listener.expect(info => {
-          browser.test.assertEq(tab1.id, info.previousTabId, "Got expected previousTabId");
-        }),
-        browser.tabs.create({url: "about:blank"}),
-      ]);
-
-      await Promise.all([
-        listener.expect(info => {
-          browser.test.assertEq(tab1.id, info.tabId, "Got expected tabId");
-          browser.test.assertEq(tab2.id, info.previousTabId, "Got expected previousTabId");
-        }),
-        browser.tabs.update(tab1.id, {active: true}),
-      ]);
-
-      await Promise.all([
-        listener.expect(info => {
-          browser.test.assertEq(tab2.id, info.tabId, "Got expected tabId");
-          browser.test.assertEq(undefined, info.previousTabId, "previousTabId should not be defined when previous tab was closed");
-        }),
-        browser.tabs.remove(tab1.id),
-      ]);
-
-      await browser.tabs.remove(tab2.id);
-
-      browser.test.notifyPass("tabs-events");
-    } catch (e) {
-      browser.test.fail(`${e} :: ${e.stack}`);
-      browser.test.notifyFail("tabs-events");
-    }
-  }
-
-  let extension = ExtensionTestUtils.loadExtension({
-    manifest: {
-      "permissions": ["tabs"],
-    },
-
-    background,
-  });
-
-  await extension.startup();
-  await extension.awaitFinish("tabs-events");
-  await extension.unload();
-});
deleted file mode 100644
--- a/browser/components/extensions/test/browser/browser_ext_tabs_successors.js
+++ /dev/null
@@ -1,212 +0,0 @@
-/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* vim: set sts=2 sw=2 et tw=80: */
-"use strict";
-
-async function background(tabCount, testFn) {
-  try {
-    const {TAB_ID_NONE} = browser.tabs;
-    const tabIds = await Promise.all(Array.from({length: tabCount}, () => browser.tabs.create({url: "about:blank"}).then(t => t.id)));
-
-    const toTabIds = i => tabIds[i];
-
-    const setSuccessors = mapping => Promise.all(mapping.map((succ, i) =>
-      browser.tabs.update(tabIds[i], {successorTabId: tabIds[succ]})));
-
-    const verifySuccessors = async function(mapping, name) {
-      const promises = [], expected = [];
-      for (let i = 0; i < mapping.length; i++) {
-        if (mapping[i] !== undefined) {
-          promises.push(browser.tabs.get(tabIds[i]).then(t => t.successorTabId));
-          expected.push(mapping[i] === TAB_ID_NONE ? TAB_ID_NONE : tabIds[mapping[i]]);
-        }
-      }
-      const results = await Promise.all(promises);
-      for (let i = 0; i < results.length; i++) {
-        browser.test.assertEq(expected[i], results[i], `${name}: successorTabId of tab ${i} in mapping should be ${expected[i]}`);
-      }
-    };
-
-    await testFn({TAB_ID_NONE, tabIds, toTabIds, setSuccessors, verifySuccessors});
-
-    browser.test.notifyPass("background-script");
-  } catch (e) {
-    browser.test.fail(`${e} :: ${e.stack}`);
-    browser.test.notifyFail("background-script");
-  }
-}
-
-async function runTabTest(tabCount, testFn) {
-  const extension = ExtensionTestUtils.loadExtension({
-    manifest: {
-      "permissions": ["tabs"],
-    },
-    background: `(${background})(${tabCount}, ${testFn});`,
-  });
-
-  await extension.startup();
-  await extension.awaitFinish("background-script");
-  await extension.unload();
-}
-
-add_task(function testTabSuccessors() {
-  return runTabTest(3, async function({TAB_ID_NONE, tabIds}) {
-    const anotherWindow = await browser.windows.create({url: "about:blank"});
-
-    browser.test.assertEq(TAB_ID_NONE, (await browser.tabs.get(tabIds[0])).successorTabId, "Tabs default to an undefined successor");
-
-    // Basic getting and setting
-
-    await browser.tabs.update(tabIds[0], {successorTabId: tabIds[1]});
-    browser.test.assertEq(tabIds[1], (await browser.tabs.get(tabIds[0])).successorTabId, "tabs.update assigned the correct successor");
-
-    await browser.tabs.update(tabIds[0], {successorTabId: browser.tabs.TAB_ID_NONE});
-    browser.test.assertEq(TAB_ID_NONE, (await browser.tabs.get(tabIds[0])).successorTabId, "tabs.update cleared successor");
-
-    await browser.tabs.update(tabIds[0], {successorTabId: tabIds[1]});
-    await browser.tabs.update(tabIds[0], {successorTabId: tabIds[0]});
-    browser.test.assertEq(TAB_ID_NONE, (await browser.tabs.get(tabIds[0])).successorTabId, "Setting a tab as its own successor clears the successor instead");
-
-    // Validation tests
-
-    await browser.test.assertRejects(
-      browser.tabs.update(tabIds[0], {successorTabId: 1e8}),
-      /Invalid successorTabId/,
-      "tabs.update should throw with an invalid successor tab ID");
-
-    await browser.test.assertRejects(
-      browser.tabs.update(tabIds[0], {successorTabId: anotherWindow.tabs[0].id}),
-      /Successor tab must be in the same window as the tab being updated/,
-      "tabs.update should throw with a successor tab ID from another window");
-
-    // Make sure the successor is truly being assigned
-
-    await browser.tabs.update(tabIds[0], {successorTabId: tabIds[2], active: true});
-    await browser.tabs.remove(tabIds[0]);
-    browser.test.assertEq(tabIds[2], (await browser.tabs.query({active: true}))[0].id);
-
-
-    return browser.tabs.remove([tabIds[1], tabIds[2], anotherWindow.tabs[0].id]);
-  });
-});
-
-add_task(function testMoveInSuccession_appendFalse() {
-  return runTabTest(8, async function({TAB_ID_NONE, tabIds, toTabIds, setSuccessors, verifySuccessors}) {
-    await browser.tabs.moveInSuccession([1, 0].map(toTabIds), tabIds[0]);
-    await verifySuccessors([TAB_ID_NONE, 0], "scenario 1");
-
-    await browser.tabs.moveInSuccession([0, 1, 2, 3].map(toTabIds), tabIds[0]);
-    await verifySuccessors([1, 2, 3, 0], "scenario 2");
-
-    await browser.tabs.moveInSuccession([1, 0].map(toTabIds), tabIds[0]);
-    await verifySuccessors([TAB_ID_NONE, 0], "scenario 1 after tab 0 has a successor");
-
-    await browser.tabs.update(tabIds[7], {successorTabId: tabIds[0]});
-    await browser.tabs.moveInSuccession([4, 5, 6, 7].map(toTabIds));
-    await verifySuccessors(new Array(4).concat([5, 6, 7, TAB_ID_NONE]), "scenario 4");
-
-    await setSuccessors([7, 2, 3, 4, 3, 6, 7, 5]);
-    await browser.tabs.moveInSuccession([4, 6, 3, 2].map(toTabIds), tabIds[7]);
-    await verifySuccessors([7, TAB_ID_NONE, 7, 2, 6, 7, 3, 5], "scenario 5");
-
-    await setSuccessors([7, 2, 3, 4, 3, 6, 7, 5]);
-    await browser.tabs.moveInSuccession([4, 6, 3, 2].map(toTabIds), tabIds[7], {insert: true});
-    await verifySuccessors([4, TAB_ID_NONE, 7, 2, 6, 4, 3, 5], "insert = true");
-
-    await setSuccessors([1, 2, 3, 4, 0]);
-    await browser.tabs.moveInSuccession([3, 1, 2].map(toTabIds), tabIds[0], {insert: true});
-    await verifySuccessors([4, 2, 0, 1, 3], "insert = true, part 2");
-
-    await browser.tabs.moveInSuccession([tabIds[0], tabIds[1], 1e8, tabIds[2]]);
-    await verifySuccessors([1, 2, TAB_ID_NONE], "unknown tab ID");
-
-    browser.test.assertTrue(await browser.tabs.moveInSuccession([1e8]).then(() => true, () => false), "When all tab IDs are unknown, tabs.moveInSuccession should not throw");
-
-    // Validation tests
-
-    await browser.test.assertRejects(
-      browser.tabs.moveInSuccession([tabIds[0], tabIds[1], tabIds[0]]),
-      /IDs must not occur more than once in tabIds/,
-      "tabs.moveInSuccession should throw when a tab is referenced more than once in tabIds");
-
-    await browser.test.assertRejects(
-      browser.tabs.moveInSuccession([tabIds[0], tabIds[1]], tabIds[0], {insert: true}),
-      /Value of tabId must not occur in tabIds if append or insert is true/,
-      "tabs.moveInSuccession should throw when tabId occurs in tabIds and insert is true");
-
-
-    return browser.tabs.remove(tabIds);
-  });
-});
-
-add_task(function testMoveInSuccession_appendTrue() {
-  return runTabTest(8, async function({TAB_ID_NONE, tabIds, toTabIds, setSuccessors, verifySuccessors}) {
-    await browser.tabs.moveInSuccession([1].map(toTabIds), tabIds[0], {append: true});
-    await verifySuccessors([1, TAB_ID_NONE], "scenario 1");
-
-    await browser.tabs.update(tabIds[3], {successorTabId: tabIds[4]});
-    await browser.tabs.moveInSuccession([1, 2, 3].map(toTabIds), tabIds[0], {append: true});
-    await verifySuccessors([1, 2, 3, TAB_ID_NONE], "scenario 2");
-
-    await browser.tabs.update(tabIds[0], {successorTabId: tabIds[1]});
-    await browser.tabs.moveInSuccession([1e8], tabIds[0], {append: true});
-    browser.test.assertEq(TAB_ID_NONE, (await browser.tabs.get(tabIds[0])).successorTabId, "If no tabs get appended after the reference tab, it should lose its successor");
-
-    await setSuccessors([7, 2, 3, 4, 3, 6, 7, 5]);
-    await browser.tabs.moveInSuccession([4, 6, 3, 2].map(toTabIds), tabIds[7], {append: true});
-    await verifySuccessors([7, TAB_ID_NONE, TAB_ID_NONE, 2, 6, 7, 3, 4], "scenario 3");
-
-    await setSuccessors([7, 2, 3, 4, 3, 6, 7, 5]);
-    await browser.tabs.moveInSuccession([4, 6, 3, 2].map(toTabIds), tabIds[7], {append: true, insert: true});
-    await verifySuccessors([7, TAB_ID_NONE, 5, 2, 6, 7, 3, 4], "insert = true");
-
-    await browser.tabs.moveInSuccession([0, 4].map(toTabIds), tabIds[7], {append: true, insert: true});
-    await verifySuccessors([4, undefined, undefined, undefined, 6, undefined, undefined, 0], "insert = true, part 2");
-
-    await setSuccessors([1, 2, 3, 4, 0]);
-    await browser.tabs.moveInSuccession([3, 1, 2].map(toTabIds), tabIds[0], {append: true, insert: true});
-    await verifySuccessors([3, 2, 4, 1, 0], "insert = true, part 3");
-
-    await browser.tabs.update(tabIds[0], {successorTabId: tabIds[1]});
-    await browser.tabs.moveInSuccession([1e8], tabIds[0], {append: true, insert: true});
-    browser.test.assertEq(tabIds[1], (await browser.tabs.get(tabIds[0])).successorTabId, "If no tabs get inserted after the reference tab, it should keep its successor");
-
-    // Validation tests
-
-    await browser.test.assertRejects(
-      browser.tabs.moveInSuccession([tabIds[0], tabIds[1]], tabIds[0], {append: true}),
-      /Value of tabId must not occur in tabIds if append or insert is true/,
-      "tabs.moveInSuccession should throw when tabId occurs in tabIds and insert is true");
-
-
-    return browser.tabs.remove(tabIds);
-  });
-});
-
-add_task(function testMoveInSuccession_ignoreTabsInOtherWindows() {
-  return runTabTest(2, async function({TAB_ID_NONE, tabIds, toTabIds, setSuccessors, verifySuccessors}) {
-    const anotherWindow = await browser.windows.create({url: Array.from({length: 3}, () => "about:blank")});
-    tabIds.push(...anotherWindow.tabs.map(t => t.id));
-
-    await setSuccessors([1, 0, 3, 4, 2]);
-    await browser.tabs.moveInSuccession([1, 3, 2].map(toTabIds), tabIds[4]);
-    await verifySuccessors([1, 0, 4, 2, TAB_ID_NONE], "first tab in another window");
-
-    await setSuccessors([1, 0, 3, 4, 2]);
-    await browser.tabs.moveInSuccession([3, 1, 2].map(toTabIds), tabIds[4]);
-    await verifySuccessors([1, 0, 4, 2, TAB_ID_NONE], "middle tab in another window");
-
-    await setSuccessors([1, 0, 3, 4, 2]);
-    await browser.tabs.moveInSuccession([3, 1, 2].map(toTabIds));
-    await verifySuccessors([1, 0, TAB_ID_NONE, 2, TAB_ID_NONE], "using the first tab to determine the window");
-
-    await setSuccessors([1, 0, 3, 4, 2]);
-    await browser.tabs.moveInSuccession([1, 3, 2].map(toTabIds), tabIds[4], {append: true});
-    await verifySuccessors([1, 0, TAB_ID_NONE, 2, 3], "first tab in another window, appending");
-
-    await setSuccessors([1, 0, 3, 4, 2]);
-    await browser.tabs.moveInSuccession([3, 1, 2].map(toTabIds), tabIds[4], {append: true});
-    await verifySuccessors([1, 0, TAB_ID_NONE, 2, 3], "middle tab in another window, appending");
-
-    return browser.tabs.remove(tabIds);
-  });
-});
--- a/mobile/android/base/java/org/mozilla/gecko/Tabs.java
+++ b/mobile/android/base/java/org/mozilla/gecko/Tabs.java
@@ -338,21 +338,18 @@ public class Tabs implements BundleEvent
         notifyListeners(tab, TabEvents.SELECTED);
 
         if (oldTab != null) {
             mPreviouslySelectedTabId = oldTab.getId();
             notifyListeners(oldTab, TabEvents.UNSELECTED);
         }
 
         // Pass a message to Gecko to update tab state in BrowserApp.
-        final GeckoBundle data = new GeckoBundle(2);
+        final GeckoBundle data = new GeckoBundle(1);
         data.putInt("id", tab.getId());
-        if (oldTab != null && mTabs.containsKey(oldTab.getId())) {
-            data.putInt("previousTabId", oldTab.getId());
-        }
         mEventDispatcher.dispatch("Tab:Selected", data);
         EventDispatcher.getInstance().dispatch("Tab:Selected", data);
         return tab;
     }
 
     public synchronized boolean selectLastTab() {
         if (mOrder.isEmpty()) {
             return false;
--- a/mobile/android/components/extensions/ext-tabs.js
+++ b/mobile/android/components/extensions/ext-tabs.js
@@ -91,21 +91,17 @@ this.tabs = class extends ExtensionAPI {
       return tab;
     }
 
     let self = {
       tabs: {
         onActivated: makeGlobalEvent(context, "tabs.onActivated", "Tab:Selected", (fire, data) => {
           let tab = tabManager.get(data.id);
 
-          fire.async({
-            tabId: tab.id,
-            previousTabId: data.previousTabId,
-            windowId: tab.windowId,
-          });
+          fire.async({tabId: tab.id, windowId: tab.windowId});
         }),
 
         onCreated: new EventManager({
           context,
           name: "tabs.onCreated",
           register: fire => {
             let listener = (eventName, event) => {
               fire.async(tabManager.convert(event.nativeTab));
@@ -331,17 +327,17 @@ this.tabs = class extends ExtensionAPI {
 
           if (updateProperties.active !== null) {
             if (updateProperties.active) {
               BrowserApp.selectTab(nativeTab);
             } else {
               // Not sure what to do here? Which tab should we select?
             }
           }
-          // FIXME: highlighted/selected, muted, pinned, openerTabId, successorTabId
+          // FIXME: highlighted/selected, muted, pinned, openerTabId
 
           return tabManager.convert(nativeTab);
         },
 
         async reload(tabId, reloadProperties) {
           let nativeTab = getTabOrActive(tabId);
 
           let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
--- a/mobile/android/components/extensions/ext-utils.js
+++ b/mobile/android/components/extensions/ext-utils.js
@@ -545,20 +545,16 @@ class Tab extends TabBase {
 
   get status() {
     if (this.browser.webProgress.isLoadingDocument) {
       return "loading";
     }
     return "complete";
   }
 
-  get successorTabId() {
-    return -1;
-  }
-
   get width() {
     return this.browser.clientWidth;
   }
 
   get window() {
     return this.browser.ownerGlobal;
   }
 
--- a/mobile/android/components/extensions/schemas/tabs.json
+++ b/mobile/android/components/extensions/schemas/tabs.json
@@ -1204,22 +1204,16 @@
             "type": "object",
             "name": "activeInfo",
             "properties": {
               "tabId": {
                 "type": "integer",
                 "minimum": 0,
                 "description": "The ID of the tab that has become active."
               },
-              "previousTabId": {
-                "type": "integer",
-                "minimum": 0,
-                "optional": true,
-                "description": "The ID of the tab that was previously active, if that tab is still open."
-              },
               "windowId": {
                 "type": "integer",
                 "minimum": 0,
                 "description": "The ID of the window the active tab changed inside of."
               }
             }
           }
         ]
--- a/mobile/android/components/extensions/test/mochitest/test_ext_tabs_events.html
+++ b/mobile/android/components/extensions/test/mochitest/test_ext_tabs_events.html
@@ -145,92 +145,12 @@ add_task(async function testTabRemovalEv
 
     background,
   });
 
   await extension.startup();
   await extension.awaitFinish("tabs-events");
   await extension.unload();
 });
-
-add_task(async function testTabActivationEvent() {
-  async function background() {
-    function makeExpectable() {
-      let expectation = null, resolver = null;
-      const expectable = param => {
-        if (expectation === null) {
-          browser.test.fail("unexpected call to expectable");
-        } else {
-          try {
-            resolver(expectation(param));
-          } catch (e) {
-            resolver(Promise.reject(e));
-          } finally {
-            expectation = null;
-          }
-        }
-      };
-      expectable.expect = e => {
-        expectation = e;
-        return new Promise(r => { resolver = r; });
-      };
-      return expectable;
-    }
-    try {
-      const listener = makeExpectable();
-      browser.tabs.onActivated.addListener(listener);
-
-      const [tab0] = await browser.tabs.query({active: true});
-      const [, tab1] = await Promise.all([
-        listener.expect(info => {
-          browser.test.assertEq(tab0.id, info.previousTabId, "Got expected previousTabId");
-        }),
-        browser.tabs.create({url: "about:blank"}),
-      ]);
-      const [, tab2] = await Promise.all([
-        listener.expect(info => {
-          browser.test.assertEq(tab1.id, info.previousTabId, "Got expected previousTabId");
-        }),
-        browser.tabs.create({url: "about:blank"}),
-      ]);
-
-      await Promise.all([
-        listener.expect(info => {
-          browser.test.assertEq(tab1.id, info.tabId, "Got expected tabId");
-          browser.test.assertEq(tab2.id, info.previousTabId, "Got expected previousTabId");
-        }),
-        browser.tabs.update(tab1.id, {active: true}),
-      ]);
-
-      await Promise.all([
-        listener.expect(info => {
-          browser.test.assertEq(tab2.id, info.tabId, "Got expected tabId");
-          browser.test.assertEq(undefined, info.previousTabId, "previousTabId should not be defined when previous tab was closed");
-        }),
-        browser.tabs.remove(tab1.id),
-      ]);
-
-      browser.tabs.onActivated.removeListener(listener);
-      await browser.tabs.remove(tab2.id);
-
-      browser.test.notifyPass("tabs-events");
-    } catch (e) {
-      browser.test.fail(`${e} :: ${e.stack}`);
-      browser.test.notifyFail("tabs-events");
-    }
-  }
-
-  let extension = ExtensionTestUtils.loadExtension({
-    manifest: {
-      "permissions": ["tabs"],
-    },
-
-    background,
-  });
-
-  await extension.startup();
-  await extension.awaitFinish("tabs-events");
-  await extension.unload();
-});
 </script>
 
 </body>
 </html>
--- a/toolkit/components/extensions/parent/ext-tabs-base.js
+++ b/toolkit/components/extensions/parent/ext-tabs-base.js
@@ -491,25 +491,16 @@ class TabBase {
    *        @readonly
    *        @abstract
    */
   get isInReaderMode() {
     throw new Error("Not implemented");
   }
 
   /**
-   * @property {integer} successorTabId
-   *        @readonly
-   *        @abstract
-   */
-  get successorTabId() {
-    throw new Error("Not implemented");
-  }
-
-  /**
    * Returns true if this tab matches the the given query info object. Omitted
    * or null have no effect on the match.
    *
    * @param {object} queryInfo
    *        The query info against which to match.
    * @param {boolean} [queryInfo.active]
    *        Matches against the exact value of the tab's `active` attribute.
    * @param {boolean} [queryInfo.audible]
@@ -613,17 +604,16 @@ class TabBase {
       width: this.width,
       height: this.height,
       lastAccessed: this.lastAccessed,
       audible: this.audible,
       mutedInfo: this.mutedInfo,
       isArticle: this.isArticle,
       isInReaderMode: this.isInReaderMode,
       sharingState: this.sharingState,
-      successorTabId: this.successorTabId,
     };
 
     // If the tab has not been fully layed-out yet, fallback to the geometry
     // from a different tab (usually the currently active tab).
     if (fallbackTabSize && (!result.width || !result.height)) {
       result.width = fallbackTabSize.width;
       result.height = fallbackTabSize.height;
     }