Bug 1530402 - Remove Fennec's {Browser,Page} Action implementation. r=snorp
☠☠ backed out by 8f3cbd66bbc3 ☠ ☠
authorAgi Sferro <agi@sferro.dev>
Wed, 13 Nov 2019 20:28:58 +0000
changeset 501838 cf16e02e62cda5c70aca83c51bb446e5e4556c0e
parent 501837 3638fcff5bed7cbfff4762b8a8529a64b762ef3b
child 501839 126af041394bc375d4bf0f8b89ffa033164b2d81
push id114172
push userdluca@mozilla.com
push dateTue, 19 Nov 2019 11:31:10 +0000
treeherdermozilla-inbound@b5c5ba07d3db [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp
bugs1530402
milestone72.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 1530402 - Remove Fennec's {Browser,Page} Action implementation. r=snorp We're going to replace this implementation from scratch so we remove it here to avoid a confusing diff. Differential Revision: https://phabricator.services.mozilla.com/D51917
mobile/android/components/extensions/ext-android.js
mobile/android/components/extensions/ext-browserAction.js
mobile/android/components/extensions/ext-pageAction.js
mobile/android/components/extensions/schemas/browser_action.json
mobile/android/components/extensions/schemas/jar.mn
mobile/android/components/extensions/schemas/page_action.json
mobile/android/modules/BrowserActions.jsm
mobile/android/modules/PageActions.jsm
mobile/android/modules/moz.build
--- a/mobile/android/components/extensions/ext-android.js
+++ b/mobile/android/components/extensions/ext-android.js
@@ -1,16 +1,10 @@
 "use strict";
 
-ChromeUtils.defineModuleGetter(
-  this,
-  "Services",
-  "resource://gre/modules/Services.jsm"
-);
-
 // This function is pretty tightly tied to Extension.jsm.
 // Its job is to fill in the |tab| property of the sender.
 const getSender = (extension, target, sender) => {
   let tabId = -1;
   if ("tabId" in sender) {
     // The message came from a privileged extension page running in a tab. In
     // that case, it should include a tabId property (which is filled in by the
     // page-open listener below).
@@ -67,44 +61,25 @@ global.openOptionsPage = extension => {
   } else {
     BrowserApp.openAddonManager({ addonId: extension.id });
   }
 
   return Promise.resolve();
 };
 
 extensions.registerModules({
-  browserAction: {
-    url: "chrome://geckoview/content/ext-browserAction.js",
-    schema: "chrome://geckoview/content/schemas/browser_action.json",
-    scopes: ["addon_parent"],
-    manifest: ["browser_action"],
-    paths: [["browserAction"]],
-  },
   browsingData: {
     url: "chrome://geckoview/content/ext-browsingData.js",
     schema: "chrome://geckoview/content/schemas/browsing_data.json",
     scopes: ["addon_parent"],
     manifest: ["browsing_data"],
     paths: [["browsingData"]],
   },
-  pageAction: {
-    url: "chrome://geckoview/content/ext-pageAction.js",
-    schema: "chrome://geckoview/content/schemas/page_action.json",
-    scopes: ["addon_parent"],
-    manifest: ["page_action"],
-    paths: [["pageAction"]],
-  },
   tabs: {
     url: "chrome://geckoview/content/ext-tabs.js",
     schema: "chrome://geckoview/content/schemas/tabs.json",
     scopes: ["addon_parent"],
     paths: [["tabs"]],
   },
+  geckoViewAddons: {
+    schema: "chrome://geckoview/content/schemas/gecko_view_addons.json",
+  },
 });
-
-if (!Services.androidBridge.isFennec) {
-  extensions.registerModules({
-    geckoViewAddons: {
-      schema: "chrome://geckoview/content/schemas/gecko_view_addons.json",
-    },
-  });
-}
deleted file mode 100644
--- a/mobile/android/components/extensions/ext-browserAction.js
+++ /dev/null
@@ -1,203 +0,0 @@
-/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* vim: set sts=2 sw=2 et tw=80: */
-"use strict";
-
-// The ext-* files are imported into the same scopes.
-/* import-globals-from ext-utils.js */
-
-// Import the android BrowserActions module.
-ChromeUtils.defineModuleGetter(
-  this,
-  "BrowserActions",
-  "resource://gre/modules/BrowserActions.jsm"
-);
-
-// WeakMap[Extension -> BrowserAction]
-let browserActionMap = new WeakMap();
-
-class BrowserAction extends EventEmitter {
-  constructor(options, extension) {
-    super();
-
-    this.uuid = `{${extension.uuid}}`;
-
-    this.defaults = {
-      name: options.default_title || extension.name,
-      popup: options.default_popup,
-    };
-
-    this.tabContext = new TabContext(tabId => this.defaults);
-
-    this.tabManager = extension.tabManager;
-
-    // eslint-disable-next-line mozilla/balanced-listeners
-    this.tabContext.on("tab-selected", (evt, tabId) => {
-      this.onTabSelected(tabId);
-    });
-    // eslint-disable-next-line mozilla/balanced-listeners
-    this.tabContext.on("tab-closed", (evt, tabId) => {
-      this.onTabClosed(tabId);
-    });
-
-    BrowserActions.register(this);
-  }
-
-  /**
-   * Required by the BrowserActions module. This event will get
-   * called whenever the browser action is clicked on.
-   */
-  onClicked() {
-    const tab = tabTracker.activeTab;
-
-    this.tabManager.addActiveTabPermission(tab);
-
-    let popup = this.tabContext.get(tab.id).popup || this.defaults.popup;
-    if (popup) {
-      tabTracker.openExtensionPopupTab(popup);
-    } else {
-      this.emit("click", tab);
-    }
-  }
-
-  /**
-   * Updates the browser action whenever a tab is selected.
-   * @param {string} tabId The tab id to update.
-   */
-  onTabSelected(tabId) {
-    let name = this.tabContext.get(tabId).name || this.defaults.name;
-    BrowserActions.update(this.uuid, { name });
-  }
-
-  /**
-   * Removes the tab from the property map now that it is closed.
-   * @param {string} tabId The tab id of the closed tab.
-   */
-  onTabClosed(tabId) {
-    this.tabContext.clear(tabId);
-  }
-
-  /**
-   * Sets a property for the browser action for the specified tab. If the property is set
-   * for the active tab, the browser action is also updated.
-   *
-   * @param {Object} tab The tab to set. If null, the browser action's default value is set.
-   * @param {string} prop The property to update. Currently only "name" is supported.
-   * @param {string} value The value to set the property to.
-   */
-  setProperty(tab, prop, value) {
-    if (tab == null) {
-      if (value) {
-        this.defaults[prop] = value;
-      }
-    } else {
-      let properties = this.tabContext.get(tab.id);
-      if (value) {
-        properties[prop] = value;
-      } else {
-        delete properties[prop];
-      }
-    }
-
-    if (!tab || tab.getActive()) {
-      BrowserActions.update(this.uuid, { [prop]: value });
-    }
-  }
-
-  /**
-   * Retreives a property of the browser action for the specified tab.
-   *
-   * @param {Object} tab The tab to retrieve the property from. If null, the default value is returned.
-   * @param {string} prop The property to retreive. Currently only "name" is supported.
-   * @returns {string} the value stored for the specified property. If the value is undefined, then the
-   *    default value is returned.
-   */
-  getProperty(tab, prop) {
-    if (tab == null) {
-      return this.defaults[prop];
-    }
-
-    return this.tabContext.get(tab.id)[prop] || this.defaults[prop];
-  }
-
-  /**
-   * Unregister the browser action from the BrowserActions module.
-   */
-  shutdown() {
-    this.tabContext.shutdown();
-    BrowserActions.unregister(this.uuid);
-  }
-}
-
-this.browserAction = class extends ExtensionAPI {
-  onManifestEntry(entryName) {
-    let { extension } = this;
-    let { manifest } = extension;
-
-    let browserAction = new BrowserAction(manifest.browser_action, extension);
-    browserActionMap.set(extension, browserAction);
-  }
-
-  onShutdown() {
-    let { extension } = this;
-
-    if (browserActionMap.has(extension)) {
-      browserActionMap.get(extension).shutdown();
-      browserActionMap.delete(extension);
-    }
-  }
-
-  getAPI(context) {
-    const { extension } = context;
-    const { tabManager } = extension;
-
-    function getTab(tabId) {
-      if (tabId !== null) {
-        return tabTracker.getTab(tabId);
-      }
-      return null;
-    }
-
-    return {
-      browserAction: {
-        onClicked: new EventManager({
-          context,
-          name: "browserAction.onClicked",
-          register: fire => {
-            let listener = (event, tab) => {
-              fire.async(tabManager.convert(tab));
-            };
-            browserActionMap.get(extension).on("click", listener);
-            return () => {
-              browserActionMap.get(extension).off("click", listener);
-            };
-          },
-        }).api(),
-
-        setTitle: function(details) {
-          let { tabId, title } = details;
-          let tab = getTab(tabId);
-          browserActionMap.get(extension).setProperty(tab, "name", title);
-        },
-
-        getTitle: function(details) {
-          let { tabId } = details;
-          let tab = getTab(tabId);
-          let title = browserActionMap.get(extension).getProperty(tab, "name");
-          return Promise.resolve(title);
-        },
-
-        setPopup(details) {
-          let tab = getTab(details.tabId);
-          let url = details.popup && context.uri.resolve(details.popup);
-          browserActionMap.get(extension).setProperty(tab, "popup", url);
-        },
-
-        getPopup(details) {
-          let tab = getTab(details.tabId);
-          let popup = browserActionMap.get(extension).getProperty(tab, "popup");
-          return Promise.resolve(popup);
-        },
-      },
-    };
-  }
-};
deleted file mode 100644
--- a/mobile/android/components/extensions/ext-pageAction.js
+++ /dev/null
@@ -1,292 +0,0 @@
-/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* vim: set sts=2 sw=2 et tw=80: */
-
-"use strict";
-
-// The ext-* files are imported into the same scopes.
-/* import-globals-from ext-utils.js */
-
-ChromeUtils.defineModuleGetter(
-  this,
-  "Services",
-  "resource://gre/modules/Services.jsm"
-);
-
-// Import the android PageActions module.
-ChromeUtils.defineModuleGetter(
-  this,
-  "PageActions",
-  "resource://gre/modules/PageActions.jsm"
-);
-
-var { ExtensionParent } = ChromeUtils.import(
-  "resource://gre/modules/ExtensionParent.jsm"
-);
-
-var { IconDetails } = ExtensionParent;
-
-// WeakMap[Extension -> PageAction]
-let pageActionMap = new WeakMap();
-
-class PageAction extends EventEmitter {
-  constructor(manifest, extension) {
-    super();
-
-    this.id = null;
-
-    this.extension = extension;
-
-    this.defaults = {
-      icons: IconDetails.normalize({ path: manifest.default_icon }, extension),
-      popup: manifest.default_popup,
-    };
-
-    this.tabManager = extension.tabManager;
-    this.context = null;
-
-    this.tabContext = new TabContext(tabId => this.defaults);
-
-    this.options = {
-      title: manifest.default_title || extension.name,
-      id: `{${extension.uuid}}`,
-      clickCallback: () => {
-        let tab = tabTracker.activeTab;
-
-        this.tabManager.addActiveTabPermission(tab);
-
-        let popup = this.tabContext.get(tab.id).popup || this.defaults.popup;
-        if (popup) {
-          tabTracker.openExtensionPopupTab(popup);
-        } else {
-          this.emit("click", tab);
-        }
-      },
-    };
-
-    this.shouldShow = false;
-
-    // eslint-disable-next-line mozilla/balanced-listeners
-    this.tabContext.on("tab-selected", (evt, tabId) => {
-      this.onTabSelected(tabId);
-    });
-    // eslint-disable-next-line mozilla/balanced-listeners
-    this.tabContext.on("tab-closed", (evt, tabId) => {
-      this.onTabClosed(tabId);
-    });
-  }
-
-  /**
-   * Updates the page action whenever a tab is selected.
-   * @param {Integer} tabId The ID of the selected tab.
-   */
-  onTabSelected(tabId) {
-    if (this.options.icon) {
-      this.hide();
-      let shouldShow = this.tabContext.get(tabId).show;
-      if (shouldShow) {
-        this.show();
-      }
-    }
-  }
-
-  /**
-   * Removes the tab from the property map now that it is closed.
-   * @param {Integer} tabId The ID of the closed tab.
-   */
-  onTabClosed(tabId) {
-    this.tabContext.clear(tabId);
-  }
-
-  /**
-   * Sets the context for the page action.
-   * @param {Object} context The extension context.
-   */
-  setContext(context) {
-    this.context = context;
-  }
-
-  /**
-   * Sets a property for the page action for the specified tab. If the property is set
-   * for the active tab, the page action is also updated.
-   *
-   * @param {Object} tab The tab to set.
-   * @param {string} prop The property to update - either "show" or "popup".
-   * @param {string} value The value to set the property to. If falsy, the property is deleted.
-   * @returns {Object} Promise which resolves when the property is set and the page action is
-   *    shown if necessary.
-   */
-  setProperty(tab, prop, value) {
-    if (tab == null) {
-      throw new Error("Tab must not be null");
-    }
-
-    let properties = this.tabContext.get(tab.id);
-    if (value) {
-      properties[prop] = value;
-    } else {
-      delete properties[prop];
-    }
-
-    if (prop === "show" && tab.id == tabTracker.activeTab.id) {
-      if (this.id && !value) {
-        return this.hide();
-      } else if (!this.id && value) {
-        return this.show();
-      }
-    }
-  }
-
-  /**
-   * Retreives a property of the page action for the specified tab.
-   *
-   * @param {Object} tab The tab to retrieve the property from. If null, the default value is returned.
-   * @param {string} prop The property to retreive - currently only "popup" is supported.
-   * @returns {string} the value stored for the specified property. If the value for the tab is undefined, then the
-   *    default value is returned.
-   */
-  getProperty(tab, prop) {
-    if (tab == null) {
-      return this.defaults[prop];
-    }
-
-    return this.tabContext.get(tab.id)[prop] || this.defaults[prop];
-  }
-
-  /**
-   * Show the page action for the active tab.
-   * @returns {Promise} resolves when the page action is shown.
-   */
-  show() {
-    // The PageAction icon has been created or it is being converted.
-    if (this.id || this.shouldShow) {
-      return Promise.resolve();
-    }
-
-    if (this.options.icon) {
-      this.id = PageActions.add(this.options);
-      return Promise.resolve();
-    }
-
-    this.shouldShow = true;
-
-    // Bug 1372782: Remove dependency on contentWindow from this file. It should
-    // be put in a separate file called ext-c-pageAction.js.
-    // Note: Fennec is not going to be multi-process for the foreseaable future,
-    // so this layering violation has no immediate impact. However, it is should
-    // be done at some point.
-    let { contentWindow } = this.context.xulBrowser;
-
-    // Bug 1372783: Why is this contentWindow.devicePixelRatio, while
-    // convertImageURLToDataURL uses browserWindow.devicePixelRatio?
-    let { icon } = IconDetails.getPreferredIcon(
-      this.defaults.icons,
-      this.extension,
-      16 * contentWindow.devicePixelRatio
-    );
-
-    let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
-    return IconDetails.convertImageURLToDataURL(
-      icon,
-      contentWindow,
-      browserWindow
-    )
-      .then(dataURI => {
-        if (this.shouldShow) {
-          this.options.icon = dataURI;
-          this.id = PageActions.add(this.options);
-        }
-      })
-      .catch(() => {
-        // The "icon conversion" promise has been rejected, set `this.shouldShow` to `false`
-        // so that we will try again on the next `pageAction.show` call.
-        this.shouldShow = false;
-
-        return Promise.reject({
-          message: "Failed to load PageAction icon",
-        });
-      });
-  }
-
-  /**
-   * Hides the page action for the active tab.
-   */
-  hide() {
-    this.shouldShow = false;
-
-    if (this.id) {
-      PageActions.remove(this.id);
-      this.id = null;
-    }
-  }
-
-  shutdown() {
-    this.tabContext.shutdown();
-    this.hide();
-  }
-}
-
-this.pageAction = class extends ExtensionAPI {
-  onManifestEntry(entryName) {
-    let { extension } = this;
-    let { manifest } = extension;
-
-    let pageAction = new PageAction(manifest.page_action, extension);
-    pageActionMap.set(extension, pageAction);
-  }
-
-  onShutdown() {
-    let { extension } = this;
-
-    if (pageActionMap.has(extension)) {
-      pageActionMap.get(extension).shutdown();
-      pageActionMap.delete(extension);
-    }
-  }
-
-  getAPI(context) {
-    const { extension } = context;
-    const { tabManager } = extension;
-
-    pageActionMap.get(extension).setContext(context);
-
-    return {
-      pageAction: {
-        onClicked: new EventManager({
-          context,
-          name: "pageAction.onClicked",
-          register: fire => {
-            let listener = (event, tab) => {
-              fire.async(tabManager.convert(tab));
-            };
-            pageActionMap.get(extension).on("click", listener);
-            return () => {
-              pageActionMap.get(extension).off("click", listener);
-            };
-          },
-        }).api(),
-
-        show(tabId) {
-          let tab = tabTracker.getTab(tabId);
-          return pageActionMap.get(extension).setProperty(tab, "show", true);
-        },
-
-        hide(tabId) {
-          let tab = tabTracker.getTab(tabId);
-          pageActionMap.get(extension).setProperty(tab, "show", false);
-        },
-
-        setPopup(details) {
-          let tab = tabTracker.getTab(details.tabId);
-          let url = details.popup && context.uri.resolve(details.popup);
-          pageActionMap.get(extension).setProperty(tab, "popup", url);
-        },
-
-        getPopup(details) {
-          let tab = tabTracker.getTab(details.tabId);
-          let popup = pageActionMap.get(extension).getProperty(tab, "popup");
-          return Promise.resolve(popup);
-        },
-      },
-    };
-  }
-};
deleted file mode 100644
--- a/mobile/android/components/extensions/schemas/browser_action.json
+++ /dev/null
@@ -1,448 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-[
-  {
-    "namespace": "manifest",
-    "types": [
-      {
-        "$extend": "WebExtensionManifest",
-        "properties": {
-          "browser_action": {
-            "type": "object",
-            "additionalProperties": { "$ref": "UnrecognizedProperty" },
-            "properties": {
-              "default_title": {
-                "type": "string",
-                "optional": true,
-                "preprocess": "localize"
-              },
-              "default_icon": {
-                "$ref": "IconPath",
-                "deprecated": "Unsupported on Android.",
-                "optional": true
-              },
-              "default_popup": {
-                "type": "string",
-                "format": "relativeUrl",
-                "optional": true,
-                "preprocess": "localize"
-              },
-              "browser_style": {
-                "type": "boolean",
-                "deprecated": "Unsupported on Android.",
-                "optional": true,
-                "default": false
-              },
-              "default_area": {
-                "description": "Defines the location the browserAction will appear by default.  The default location is navbar.",
-                "type": "string",
-                "enum": ["navbar", "menupanel", "tabstrip", "personaltoolbar"],
-                "deprecated": "Unsupported on Android.",
-                "optional": true
-              }
-            },
-            "optional": true
-          }
-        }
-      }
-    ]
-  },
-  {
-    "namespace": "browserAction",
-    "description": "Use browser actions to put icons in the main browser toolbar, to the right of the address bar. In addition to its icon, a browser action can also have a tooltip, a badge, and a popup.",
-    "permissions": ["manifest:browser_action"],
-    "types": [
-      {
-        "id": "ColorArray",
-        "type": "array",
-        "items": {
-          "type": "integer",
-          "minimum": 0,
-          "maximum": 255
-        },
-        "minItems": 4,
-        "maxItems": 4
-      },
-      {
-        "id": "ImageDataType",
-        "type": "object",
-        "isInstanceOf": "ImageData",
-        "additionalProperties": { "type": "any" },
-        "postprocess": "convertImageDataToURL",
-        "description": "Pixel data for an image. Must be an ImageData object (for example, from a <code>canvas</code> element)."
-      }
-    ],
-    "functions": [
-      {
-        "name": "setTitle",
-        "type": "function",
-        "description": "Sets the title of the browser action. This shows up in the tooltip.",
-        "async": "callback",
-        "parameters": [
-          {
-            "name": "details",
-            "type": "object",
-            "properties": {
-              "title": {
-                "type": "string",
-                "description": "The string the browser action should display when moused over."
-              },
-              "tabId": {
-                "type": "integer",
-                "optional": true,
-                "description": "Limits the change to when a particular tab is selected. Automatically resets when the tab is closed."
-              }
-            }
-          },
-          {
-            "type": "function",
-            "name": "callback",
-            "optional": true,
-            "parameters": []
-          }
-        ]
-      },
-      {
-        "name": "getTitle",
-        "type": "function",
-        "description": "Gets the title of the browser action.",
-        "async": "callback",
-        "parameters": [
-          {
-            "name": "details",
-            "type": "object",
-            "properties": {
-              "tabId": {
-                "type": "integer",
-                "optional": true,
-                "description": "Specify the tab to get the title from. If no tab is specified, the non-tab-specific title is returned."
-              }
-            }
-          },
-          {
-            "type": "function",
-            "name": "callback",
-            "parameters": [
-              {
-                "name": "result",
-                "type": "string"
-              }
-            ]
-          }
-        ]
-      },
-      {
-        "name": "setIcon",
-        "unsupported": true,
-        "type": "function",
-        "description": "Sets the icon for the browser action. The icon can be specified either as the path to an image file or as the pixel data from a canvas element, or as dictionary of either one of those. Either the <b>path</b> or the <b>imageData</b> property must be specified.",
-        "async": "callback",
-        "parameters": [
-          {
-            "name": "details",
-            "type": "object",
-            "properties": {
-              "imageData": {
-                "choices": [
-                  { "$ref": "ImageDataType" },
-                  {
-                    "type": "object",
-                    "additionalProperties": {"$ref": "ImageDataType"}
-                  }
-                ],
-                "optional": true,
-                "description": "Either an ImageData object or a dictionary {size -> ImageData} representing icon to be set. If the icon is specified as a dictionary, the actual image to be used is chosen depending on screen's pixel density. If the number of image pixels that fit into one screen space unit equals <code>scale</code>, then image with size <code>scale</code> * 19 will be selected. Initially only scales 1 and 2 will be supported. At least one image must be specified. Note that 'details.imageData = foo' is equivalent to 'details.imageData = {'19': foo}'"
-              },
-              "path": {
-                "choices": [
-                  { "type": "string" },
-                  {
-                    "type": "object",
-                    "additionalProperties": {"type": "string"}
-                  }
-                ],
-                "optional": true,
-                "description": "Either a relative image path or a dictionary {size -> relative image path} pointing to icon to be set. If the icon is specified as a dictionary, the actual image to be used is chosen depending on screen's pixel density. If the number of image pixels that fit into one screen space unit equals <code>scale</code>, then image with size <code>scale</code> * 19 will be selected. Initially only scales 1 and 2 will be supported. At least one image must be specified. Note that 'details.path = foo' is equivalent to 'details.imageData = {'19': foo}'"
-              },
-              "tabId": {
-                "type": "integer",
-                "optional": true,
-                "description": "Limits the change to when a particular tab is selected. Automatically resets when the tab is closed."
-              }
-            }
-          },
-          {
-            "type": "function",
-            "name": "callback",
-            "optional": true,
-            "parameters": []
-          }
-        ]
-      },
-      {
-        "name": "setPopup",
-        "type": "function",
-        "description": "Sets the html document to be opened as a popup when the user clicks on the browser action's icon.",
-        "async": "callback",
-        "parameters": [
-          {
-            "name": "details",
-            "type": "object",
-            "properties": {
-              "tabId": {
-                "type": "integer",
-                "optional": true,
-                "minimum": 0,
-                "description": "Limits the change to when a particular tab is selected. Automatically resets when the tab is closed."
-              },
-              "popup": {
-                "type": "string",
-                "description": "The html file to show in a popup.  If set to the empty string (''), no popup is shown."
-              }
-            }
-          },
-          {
-            "type": "function",
-            "name": "callback",
-            "optional": true,
-            "parameters": []
-          }
-        ]
-      },
-      {
-        "name": "getPopup",
-        "type": "function",
-        "description": "Gets the html document set as the popup for this browser action.",
-        "async": "callback",
-        "parameters": [
-          {
-            "name": "details",
-            "type": "object",
-            "properties": {
-              "tabId": {
-                "type": "integer",
-                "optional": true,
-                "minimum": 0,
-                "description": "Specify the tab to get the popup from. If no tab is specified, the non-tab-specific popup is returned."
-              }
-            }
-          },
-          {
-            "type": "function",
-            "name": "callback",
-            "parameters": [
-              {
-                "name": "result",
-                "type": "string"
-              }
-            ]
-          }
-        ]
-      },
-      {
-        "name": "setBadgeText",
-        "unsupported": true,
-        "type": "function",
-        "description": "Sets the badge text for the browser action. The badge is displayed on top of the icon.",
-        "async": "callback",
-        "parameters": [
-          {
-            "name": "details",
-            "type": "object",
-            "properties": {
-              "text": {
-                "type": "string",
-                "description": "Any number of characters can be passed, but only about four can fit in the space."
-              },
-              "tabId": {
-                "type": "integer",
-                "optional": true,
-                "description": "Limits the change to when a particular tab is selected. Automatically resets when the tab is closed."
-              }
-            }
-          },
-          {
-            "type": "function",
-            "name": "callback",
-            "optional": true,
-            "parameters": []
-          }
-        ]
-      },
-      {
-        "name": "getBadgeText",
-        "unsupported": true,
-        "type": "function",
-        "description": "Gets the badge text of the browser action. If no tab is specified, the non-tab-specific badge text is returned.",
-        "async": "callback",
-        "parameters": [
-          {
-            "name": "details",
-            "type": "object",
-            "properties": {
-              "tabId": {
-                "type": "integer",
-                "optional": true,
-                "description": "Specify the tab to get the badge text from. If no tab is specified, the non-tab-specific badge text is returned."
-              }
-            }
-          },
-          {
-            "type": "function",
-            "name": "callback",
-            "parameters": [
-              {
-                "name": "result",
-                "type": "string"
-              }
-            ]
-          }
-        ]
-      },
-      {
-        "name": "setBadgeBackgroundColor",
-        "unsupported": true,
-        "type": "function",
-        "description": "Sets the background color for the badge.",
-        "async": "callback",
-        "parameters": [
-          {
-            "name": "details",
-            "type": "object",
-            "properties": {
-              "color": {
-                "description": "An array of four integers in the range [0,255] that make up the RGBA color of the badge. For example, opaque red is <code>[255, 0, 0, 255]</code>. Can also be a string with a CSS value, with opaque red being <code>#FF0000</code> or <code>#F00</code>.",
-                "choices": [
-                  {"type": "string"},
-                  {"$ref": "ColorArray"}
-                ]
-              },
-              "tabId": {
-                "type": "integer",
-                "optional": true,
-                "description": "Limits the change to when a particular tab is selected. Automatically resets when the tab is closed."
-              }
-            }
-          },
-          {
-            "type": "function",
-            "name": "callback",
-            "optional": true,
-            "parameters": []
-          }
-        ]
-      },
-      {
-        "name": "getBadgeBackgroundColor",
-        "unsupported": true,
-        "type": "function",
-        "description": "Gets the background color of the browser action.",
-        "async": "callback",
-        "parameters": [
-          {
-            "name": "details",
-            "type": "object",
-            "properties": {
-              "tabId": {
-                "type": "integer",
-                "optional": true,
-                "description": "Specify the tab to get the badge background color from. If no tab is specified, the non-tab-specific badge background color is returned."
-              }
-            }
-          },
-          {
-            "type": "function",
-            "name": "callback",
-            "parameters": [
-              {
-                "name": "result",
-                "$ref": "ColorArray"
-              }
-            ]
-          }
-        ]
-      },
-      {
-        "name": "enable",
-        "unsupported": true,
-        "type": "function",
-        "description": "Enables the browser action for a tab. By default, browser actions are enabled.",
-        "async": "callback",
-        "parameters": [
-          {
-            "type": "integer",
-            "optional": true,
-            "name": "tabId",
-            "minimum": 0,
-            "description": "The id of the tab for which you want to modify the browser action."
-          },
-          {
-            "type": "function",
-            "name": "callback",
-            "optional": true,
-            "parameters": []
-          }
-        ]
-      },
-      {
-        "name": "disable",
-        "unsupported": true,
-        "type": "function",
-        "description": "Disables the browser action for a tab.",
-        "async": "callback",
-        "parameters": [
-          {
-            "type": "integer",
-            "optional": true,
-            "name": "tabId",
-            "minimum": 0,
-            "description": "The id of the tab for which you want to modify the browser action."
-          },
-          {
-            "type": "function",
-            "name": "callback",
-            "optional": true,
-            "parameters": []
-          }
-        ]
-      },
-      {
-        "name": "openPopup",
-        "unsupported": true,
-        "type": "function",
-        "description": "Opens the extension popup window in the active window but does not grant tab permissions.",
-        "async": "callback",
-        "parameters": [
-          {
-            "type": "function",
-            "name": "callback",
-            "parameters": [
-              {
-                "name": "popupView",
-                "type": "object",
-                "optional": true,
-                "description": "JavaScript 'window' object for the popup window if it was succesfully opened.",
-                "additionalProperties": { "type": "any" }
-              }
-            ]
-          }
-        ]
-      }
-    ],
-    "events": [
-      {
-        "name": "onClicked",
-        "type": "function",
-        "description": "Fired when a browser action icon is clicked.  This event will not fire if the browser action has a popup.",
-        "parameters": [
-          {
-            "name": "tab",
-            "$ref": "tabs.Tab"
-          }
-        ]
-      }
-    ]
-  }
-]
--- a/mobile/android/components/extensions/schemas/jar.mn
+++ b/mobile/android/components/extensions/schemas/jar.mn
@@ -1,10 +1,8 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 geckoview.jar:
-    content/schemas/browser_action.json
     content/schemas/browsing_data.json
     content/schemas/gecko_view_addons.json
-    content/schemas/page_action.json
     content/schemas/tabs.json
deleted file mode 100644
--- a/mobile/android/components/extensions/schemas/page_action.json
+++ /dev/null
@@ -1,240 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-[
-  {
-    "namespace": "manifest",
-    "types": [
-      {
-        "$extend": "WebExtensionManifest",
-        "properties": {
-          "page_action": {
-            "type": "object",
-            "additionalProperties": { "$ref": "UnrecognizedProperty" },
-            "properties": {
-              "default_title": {
-                "type": "string",
-                "optional": true,
-                "preprocess": "localize"
-              },
-              "default_icon": {
-                "$ref": "IconPath",
-                "optional": true
-              },
-              "default_popup": {
-                "type": "string",
-                "format": "relativeUrl",
-                "optional": true,
-                "preprocess": "localize"
-              },
-              "browser_style": {
-                "type": "boolean",
-                "optional": true,
-                "default": false
-              }
-            },
-            "optional": true
-          }
-        }
-      }
-    ]
-  },
-  {
-    "namespace": "pageAction",
-    "description": "Use the <code>browser.pageAction</code> API to put icons inside the address bar. Page actions represent actions that can be taken on the current page, but that aren't applicable to all pages.",
-    "permissions": ["manifest:page_action"],
-    "types": [
-      {
-        "id": "ImageDataType",
-        "type": "object",
-        "isInstanceOf": "ImageData",
-        "additionalProperties": { "type": "any" },
-        "description": "Pixel data for an image. Must be an ImageData object (for example, from a <code>canvas</code> element)."
-      }
-    ],
-    "functions": [
-      {
-        "name": "show",
-        "type": "function",
-        "description": "Shows the page action. The page action is shown whenever the tab is selected.",
-        "async": "callback",
-        "parameters": [
-          {"type": "integer", "name": "tabId", "minimum": 0, "description": "The id of the tab for which you want to modify the page action."},
-          {
-            "type": "function",
-            "name": "callback",
-            "optional": true,
-            "parameters": []
-          }
-        ]
-      },
-      {
-        "name": "hide",
-        "type": "function",
-        "description": "Hides the page action.",
-        "async": "callback",
-        "parameters": [
-          {"type": "integer", "name": "tabId", "minimum": 0, "description": "The id of the tab for which you want to modify the page action."},
-          {
-            "type": "function",
-            "name": "callback",
-            "optional": true,
-            "parameters": []
-          }
-        ]
-      },
-      {
-        "name": "setTitle",
-        "unsupported": true,
-        "type": "function",
-        "description": "Sets the title of the page action. This is displayed in a tooltip over the page action.",
-        "parameters": [
-          {
-            "name": "details",
-            "type": "object",
-            "properties": {
-              "tabId": {"type": "integer", "minimum": 0, "description": "The id of the tab for which you want to modify the page action."},
-              "title": {"type": "string", "description": "The tooltip string."}
-            }
-          }
-        ]
-      },
-      {
-        "name": "getTitle",
-        "unsupported": true,
-        "type": "function",
-        "description": "Gets the title of the page action.",
-        "async": "callback",
-        "parameters": [
-          {
-            "name": "details",
-            "type": "object",
-            "properties": {
-              "tabId": {
-                "type": "integer",
-                "description": "Specify the tab to get the title from."
-              }
-            }
-          },
-          {
-            "type": "function",
-            "name": "callback",
-            "parameters": [
-              {
-                "name": "result",
-                "type": "string"
-              }
-            ]
-          }
-        ]
-      },
-      {
-        "name": "setIcon",
-        "unsupported": true,
-        "type": "function",
-        "description": "Sets the icon for the page action. The icon can be specified either as the path to an image file or as the pixel data from a canvas element, or as dictionary of either one of those. Either the <b>path</b> or the <b>imageData</b> property must be specified.",
-        "async": "callback",
-        "parameters": [
-          {
-            "name": "details",
-            "type": "object",
-            "properties": {
-              "tabId": {"type": "integer", "minimum": 0, "description": "The id of the tab for which you want to modify the page action."},
-              "imageData": {
-                "choices": [
-                  { "$ref": "ImageDataType" },
-                  {
-                    "type": "object",
-                    "additionalProperties": {"$ref": "ImageDataType"}
-                  }
-                ],
-                "optional": true,
-                "description": "Either an ImageData object or a dictionary {size -> ImageData} representing icon to be set. If the icon is specified as a dictionary, the actual image to be used is chosen depending on screen's pixel density. If the number of image pixels that fit into one screen space unit equals <code>scale</code>, then image with size <code>scale</code> * 19 will be selected. Initially only scales 1 and 2 will be supported. At least one image must be specified. Note that 'details.imageData = foo' is equivalent to 'details.imageData = {'19': foo}'"
-              },
-              "path": {
-                "choices": [
-                  { "type": "string" },
-                  {
-                    "type": "object",
-                    "additionalProperties": {"type": "string"}
-                  }
-                ],
-                "optional": true,
-                "description": "Either a relative image path or a dictionary {size -> relative image path} pointing to icon to be set. If the icon is specified as a dictionary, the actual image to be used is chosen depending on screen's pixel density. If the number of image pixels that fit into one screen space unit equals <code>scale</code>, then image with size <code>scale</code> * 19 will be selected. Initially only scales 1 and 2 will be supported. At least one image must be specified. Note that 'details.path = foo' is equivalent to 'details.imageData = {'19': foo}'"
-              }
-            }
-          },
-          {
-            "type": "function",
-            "name": "callback",
-            "optional": true,
-            "parameters": []
-          }
-        ]
-      },
-      {
-        "name": "setPopup",
-        "type": "function",
-        "async": "callback",
-        "description": "Sets the html document to be opened as a popup when the user clicks on the page action's icon.",
-        "parameters": [
-          {
-            "name": "details",
-            "type": "object",
-            "properties": {
-              "tabId": {"type": "integer", "minimum": 0, "description": "The id of the tab for which you want to modify the page action."},
-              "popup": {
-                "type": "string",
-                "description": "The html file to show in a popup.  If set to the empty string (''), no popup is shown."
-              }
-            }
-          },
-          {
-            "type": "function",
-            "name": "callback",
-            "optional": true,
-            "parameters": []
-          }
-        ]
-      },
-      {
-        "name": "getPopup",
-        "type": "function",
-        "description": "Gets the html document set as the popup for this page action.",
-        "async": "callback",
-        "parameters": [
-          {
-            "name": "details",
-            "type": "object",
-            "properties": {
-              "tabId": {
-                "type": "integer",
-                "description": "Specify the tab to get the popup from."
-              }
-            }
-          },
-          {
-            "type": "function",
-            "name": "callback",
-            "optional": true,
-            "parameters": []
-          }
-        ]
-      }
-    ],
-    "events": [
-      {
-        "name": "onClicked",
-        "type": "function",
-        "description": "Fired when a page action icon is clicked.  This event will not fire if the page action has a popup.",
-        "parameters": [
-          {
-            "name": "tab",
-            "$ref": "tabs.Tab"
-          }
-        ]
-      }
-    ]
-  }
-]
deleted file mode 100644
--- a/mobile/android/modules/BrowserActions.jsm
+++ /dev/null
@@ -1,146 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const { EventDispatcher } = ChromeUtils.import(
-  "resource://gre/modules/Messaging.jsm"
-);
-
-var EXPORTED_SYMBOLS = ["BrowserActions"];
-
-var BrowserActions = {
-  _browserActions: {},
-  _browserActionTitles: {},
-
-  _initialized: false,
-
-  /**
-   * Registers the listeners only if they have not been initialized
-   * already and there is at least one browser action.
-   */
-  _maybeRegisterListeners() {
-    if (!this._initialized && Object.keys(this._browserActions).length) {
-      this._initialized = true;
-      EventDispatcher.instance.registerListener(this, "Menu:Clicked");
-    }
-  },
-
-  /**
-   * Unregisters the listeners if they are already initizliaed and
-   * all of the browser actions have been removed.
-   */
-  _maybeUnregisterListeners() {
-    if (this._initialized && !Object.keys(this._browserActions).length) {
-      this._initialized = false;
-      EventDispatcher.instance.unregisterListener(this, "Menu:Clicked");
-    }
-  },
-
-  /**
-   * Called when a browser action is clicked on.
-   * @param {string} event The name of the event, which should always
-   *    be "Menu:Clicked".
-   * @param {Object} data An object containing information about the
-   *    browser action, which in this case should contain an `item`
-   *    property which is browser action's UUID.
-   */
-  onEvent(event, data) {
-    if (event !== "Menu:Clicked") {
-      throw new Error(
-        `Expected "Menu:Clicked" event - received "${event}" instead`
-      );
-    }
-
-    let browserAction = this._browserActions[data.item];
-    if (!browserAction) {
-      // This was probably meant for the NativeWindow menu handler.
-      return;
-    }
-    browserAction.onClicked();
-  },
-
-  /**
-   * Registers a new browser action.
-   * @param {Object} browserAction The browser action to add.
-   */
-  register(browserAction) {
-    EventDispatcher.instance.sendRequest({
-      type: "Menu:Add",
-      uuid: browserAction.uuid,
-      name: browserAction.defaults.name,
-    });
-
-    this._browserActions[browserAction.uuid] = browserAction;
-    this._browserActionTitles[browserAction.uuid] = browserAction.defaults.name;
-
-    this._maybeRegisterListeners();
-  },
-
-  /**
-   * Updates the browser action with the specified UUID.
-   * @param {string} uuid The UUID of the browser action.
-   * @param {Object} options The properties to update.
-   */
-  update(uuid, options) {
-    if (options.name) {
-      EventDispatcher.instance.sendRequest({
-        type: "Menu:Update",
-        uuid,
-        options,
-      });
-
-      this._browserActionTitles[uuid] = options.name;
-    }
-  },
-
-  /**
-   * Retrieves the name currently used for the browser action with the
-   * specified UUID. Used for testing only.
-   * @param {string} uuid The UUID of the browser action.
-   * @returns {string} the name currently used for the browser action.
-   */
-  getNameForActiveTab(uuid) {
-    return this._browserActionTitles[uuid];
-  },
-
-  /**
-   * Checks to see if the browser action is shown. Used for testing only.
-   * @param {string} uuid The UUID of the browser action.
-   * @returns {boolean} true if the browser action is shown; false otherwise.
-   */
-  isShown(uuid) {
-    return !!this._browserActions[uuid];
-  },
-
-  /**
-   * Synthesizes a click on the browser action. Used for testing only.
-   * @param {string} uuid The UUID of the browser action.
-   */
-  synthesizeClick(uuid) {
-    let browserAction = this._browserActions[uuid];
-    if (!browserAction) {
-      throw new Error(`No BrowserAction with UUID ${uuid} was found`);
-    }
-    browserAction.onClicked();
-  },
-
-  /**
-   * Unregisters the browser action with the specified UUID.
-   * @param {string} uuid The UUID of the browser action.
-   */
-  unregister(uuid) {
-    let browserAction = this._browserActions[uuid];
-    if (!browserAction) {
-      throw new Error(`No BrowserAction with UUID ${uuid} was found`);
-    }
-    EventDispatcher.instance.sendRequest({
-      type: "Menu:Remove",
-      uuid,
-    });
-    delete this._browserActions[uuid];
-    delete this._browserActionTitles[uuid];
-    this._maybeUnregisterListeners();
-  },
-};
deleted file mode 100644
--- a/mobile/android/modules/PageActions.jsm
+++ /dev/null
@@ -1,129 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const { XPCOMUtils } = ChromeUtils.import(
-  "resource://gre/modules/XPCOMUtils.jsm"
-);
-const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
-const { EventDispatcher } = ChromeUtils.import(
-  "resource://gre/modules/Messaging.jsm"
-);
-
-XPCOMUtils.defineLazyServiceGetter(
-  this,
-  "uuidgen",
-  "@mozilla.org/uuid-generator;1",
-  "nsIUUIDGenerator"
-);
-
-var EXPORTED_SYMBOLS = ["PageActions"];
-
-// Copied from browser.js
-// TODO: We should move this method to a common importable location
-function resolveGeckoURI(aURI) {
-  if (!aURI) {
-    throw new Error("Can't resolve an empty uri");
-  }
-
-  if (aURI.startsWith("chrome://")) {
-    let registry = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(
-      Ci.nsIChromeRegistry
-    );
-    return registry.convertChromeURL(Services.io.newURI(aURI)).spec;
-  } else if (aURI.startsWith("resource://")) {
-    let handler = Services.io
-      .getProtocolHandler("resource")
-      .QueryInterface(Ci.nsIResProtocolHandler);
-    return handler.resolveURI(Services.io.newURI(aURI));
-  }
-  return aURI;
-}
-
-var PageActions = {
-  _items: {},
-
-  _initialized: false,
-
-  _maybeInitialize: function() {
-    if (!this._initialized && Object.keys(this._items).length) {
-      this._initialized = true;
-      EventDispatcher.instance.registerListener(this, [
-        "PageActions:Clicked",
-        "PageActions:LongClicked",
-      ]);
-    }
-  },
-
-  _maybeUninitialize: function() {
-    if (this._initialized && !Object.keys(this._items).length) {
-      this._initialized = false;
-      EventDispatcher.instance.unregisterListener(this, [
-        "PageActions:Clicked",
-        "PageActions:LongClicked",
-      ]);
-    }
-  },
-
-  onEvent: function(event, data, callback) {
-    let item = this._items[data.id];
-    if (event == "PageActions:Clicked") {
-      if (item.clickCallback) {
-        item.clickCallback();
-      }
-    } else if (event == "PageActions:LongClicked") {
-      if (item.longClickCallback) {
-        item.longClickCallback();
-      }
-    }
-  },
-
-  isShown: function(id) {
-    return !!this._items[id];
-  },
-
-  synthesizeClick: function(id) {
-    let item = this._items[id];
-    if (item && item.clickCallback) {
-      item.clickCallback();
-    }
-  },
-
-  add: function(aOptions) {
-    let id = aOptions.id || uuidgen.generateUUID().toString();
-
-    EventDispatcher.instance.sendRequest({
-      type: "PageActions:Add",
-      id: id,
-      title: aOptions.title,
-      icon: resolveGeckoURI(aOptions.icon),
-      important: "important" in aOptions ? aOptions.important : false,
-      useTint: "useTint" in aOptions ? aOptions.useTint : false,
-    });
-
-    this._items[id] = {};
-
-    if (aOptions.clickCallback) {
-      this._items[id].clickCallback = aOptions.clickCallback;
-    }
-
-    if (aOptions.longClickCallback) {
-      this._items[id].longClickCallback = aOptions.longClickCallback;
-    }
-
-    this._maybeInitialize();
-    return id;
-  },
-
-  remove: function(id) {
-    EventDispatcher.instance.sendRequest({
-      type: "PageActions:Remove",
-      id: id,
-    });
-
-    delete this._items[id];
-    this._maybeUninitialize();
-  },
-};
--- a/mobile/android/modules/moz.build
+++ b/mobile/android/modules/moz.build
@@ -17,30 +17,28 @@ with Files('HomeProvider.jsm'):
 with Files('geckoview/**'):
     BUG_COMPONENT = ('GeckoView', 'General')
 
 DIRS += ['geckoview']
 
 EXTRA_JS_MODULES += [
     'Accounts.jsm',
     'ActionBarHandler.jsm',
-    'BrowserActions.jsm',
     'dbg-browser-actors.js',
     'DownloadNotifications.jsm',
     'FormAssistant.jsm',
     'FxAccountsWebChannel.jsm',
     'HelperApps.jsm',
     'Home.jsm',
     'HomeProvider.jsm',
     'InputWidgetHelper.jsm',
     'LightweightThemeConsumer.jsm',
     'MediaPlayerApp.jsm',
     'NetErrorHelper.jsm',
     'Notifications.jsm',
-    'PageActions.jsm',
     'Prompt.jsm',
     'RuntimePermissions.jsm',
     'Sanitizer.jsm',
     'SelectHelper.jsm',
     'SharedPreferences.jsm',
     'Snackbars.jsm',
     'WebrtcUI.jsm',
     'WebsiteMetadata.jsm'