Merge mozilla-central to mozilla-inbound
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Mon, 24 Apr 2017 13:13:02 +0200
changeset 354640 44e3d204f259dee6727107e099ac35544dde94b0
parent 354639 ccdbdd6e79e3114d88f972953f462555fc3083d1 (current diff)
parent 354495 e17cbb839dd225a2da7e5d5bec43cf94e11749d8 (diff)
child 354641 297b5b4a46caaa71f55d5f1e0daf16f0bebfdc03
push id31707
push userkwierso@gmail.com
push dateMon, 24 Apr 2017 22:53:41 +0000
treeherdermozilla-central@abdcc8dfc283 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone55.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
Merge mozilla-central to mozilla-inbound
mobile/android/components/extensions/ext-browserAction.js
mobile/android/components/extensions/schemas/browser_action.json
mobile/android/components/extensions/test/mochitest/test_ext_browserAction_onClicked.html
mobile/android/modules/BrowserActions.jsm
--- a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
@@ -231,17 +231,17 @@ public class BrowserApp extends GeckoApp
     private BrowserSearch mBrowserSearch;
     private View mBrowserSearchContainer;
 
     public ViewGroup mBrowserChrome;
     public ViewFlipper mActionBarFlipper;
     public ActionModeCompatView mActionBar;
     private VideoPlayer mVideoPlayer;
     private BrowserToolbar mBrowserToolbar;
-    private View mDoorhangerOverlay;
+    private View doorhangerOverlay;
     // We can't name the TabStrip class because it's not included on API 9.
     private TabStripInterface mTabStrip;
     private ToolbarProgressView mProgressView;
     private FirstrunAnimationContainer mFirstrunAnimationContainer;
     private HomeScreen mHomeScreen;
     private TabsPanel mTabsPanel;
     /**
      * Container for the home screen implementation. This will be populated with any valid
@@ -253,19 +253,18 @@ public class BrowserApp extends GeckoApp
     private ActionModeCompat mActionMode;
     private TabHistoryController tabHistoryController;
 
     private static final int GECKO_TOOLS_MENU = -1;
     private static final int ADDON_MENU_OFFSET = 1000;
     public static final String TAB_HISTORY_FRAGMENT_TAG = "tabHistoryFragment";
 
     private static class MenuItemInfo {
-        public String id;
+        public int id;
         public String label;
-        public int position;
         public boolean checkable;
         public boolean checked;
         public boolean enabled = true;
         public boolean visible = true;
         public int parent;
         public boolean added;   // So we can re-add after a locale change.
     }
 
@@ -290,19 +289,16 @@ public class BrowserApp extends GeckoApp
     private MediaCastingBar mMediaCastingBar;
 
     // We'll ask for feedback after the user launches the app this many times.
     private static final int FEEDBACK_LAUNCH_COUNT = 15;
 
     // Stored value of the toolbar height, so we know when it's changed.
     private int mToolbarHeight;
 
-    // The ID to use for the next addon menu item.
-    private int mNextAddonMenuId = 0;
-
     private SharedPreferencesHelper mSharedPreferencesHelper;
 
     private ReadingListHelper mReadingListHelper;
 
     private AccountsHelper mAccountsHelper;
 
     // The tab to be selected on editing mode exit.
     private Integer mTargetTabForEditingMode;
@@ -731,17 +727,17 @@ public class BrowserApp extends GeckoApp
             mBrowserSearch.setUserVisibleHint(false);
         }
 
         setBrowserToolbarListeners();
 
         mFindInPageBar = (FindInPageBar) findViewById(R.id.find_in_page);
         mMediaCastingBar = (MediaCastingBar) findViewById(R.id.media_casting);
 
-        mDoorhangerOverlay = findViewById(R.id.doorhanger_overlay);
+        doorhangerOverlay = findViewById(R.id.doorhanger_overlay);
 
         EventDispatcher.getInstance().registerGeckoThreadListener(this,
             "Search:Keyword",
             null);
 
         EventDispatcher.getInstance().registerUiThreadListener(this,
             "Menu:Open",
             "Menu:Update",
@@ -1794,40 +1790,39 @@ public class BrowserApp extends GeckoApp
             case "Menu:Open":
                 if (mBrowserToolbar.isEditing()) {
                     mBrowserToolbar.cancelEdit();
                 }
                 openOptionsMenu();
                 break;
 
             case "Menu:Update":
-                updateAddonMenuItem(message.getString("id"), message.getBundle("options"));
+                updateAddonMenuItem(message.getInt("id") + ADDON_MENU_OFFSET,
+                                    message.getBundle("options"));
                 break;
 
             case "Menu:Add":
                 final MenuItemInfo info = new MenuItemInfo();
                 info.label = message.getString("name");
                 if (info.label == null) {
                     Log.e(LOGTAG, "Invalid menu item name");
                     return;
                 }
-                info.id = message.getString("id");
-                info.position = ADDON_MENU_OFFSET + mNextAddonMenuId;
+                info.id = message.getInt("id") + ADDON_MENU_OFFSET;
                 info.checked = message.getBoolean("checked", false);
                 info.enabled = message.getBoolean("enabled", true);
                 info.visible = message.getBoolean("visible", true);
                 info.checkable = message.getBoolean("checkable", false);
                 final int parent = message.getInt("parent", 0);
                 info.parent = parent <= 0 ? parent : parent + ADDON_MENU_OFFSET;
                 addAddonMenuItem(info);
-                mNextAddonMenuId++;
                 break;
 
             case "Menu:Remove":
-                removeAddonMenuItem(message.getString("id"));
+                removeAddonMenuItem(message.getInt("id") + ADDON_MENU_OFFSET);
                 break;
 
             case "LightweightTheme:Update":
                 mDynamicToolbar.setVisible(true, VisibilityTransition.ANIMATE);
                 break;
 
             case "Search:Keyword":
                 storeSearchQuery(message.getString("query"));
@@ -3088,23 +3083,23 @@ public class BrowserApp extends GeckoApp
                 if (parent.getIcon() != null) {
                     ((SubMenu) destination).getItem().setIcon(parent.getIcon());
                 }
             } else {
                 destination = parent.getSubMenu();
             }
         }
 
-        final MenuItem item = destination.add(Menu.NONE, info.position, Menu.NONE, info.label);
+        final MenuItem item = destination.add(Menu.NONE, info.id, Menu.NONE, info.label);
 
         item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
             @Override
             public boolean onMenuItemClick(MenuItem item) {
                 final GeckoBundle data = new GeckoBundle(1);
-                data.putString("item", info.id);
+                data.putInt("item", info.id - ADDON_MENU_OFFSET);
                 EventDispatcher.getInstance().dispatch("Menu:Clicked", data);
                 return true;
             }
         });
 
         item.setCheckable(info.checkable);
         item.setChecked(info.checked);
         item.setEnabled(info.enabled);
@@ -3124,64 +3119,56 @@ public class BrowserApp extends GeckoApp
 
         if (mMenu == null) {
             return;
         }
 
         addAddonMenuItemToMenu(mMenu, info);
     }
 
-    private void removeAddonMenuItem(String id) {
-        int position = -1;
-
+    private void removeAddonMenuItem(int id) {
         // Remove add-on menu item from cache, if available.
         if (mAddonMenuItemsCache != null && !mAddonMenuItemsCache.isEmpty()) {
             for (MenuItemInfo item : mAddonMenuItemsCache) {
-                if (item.id.equals(id)) {
-                    position = item.position;
-                    mAddonMenuItemsCache.remove(item);
-                    break;
-                }
+                 if (item.id == id) {
+                     mAddonMenuItemsCache.remove(item);
+                     break;
+                 }
             }
         }
 
-        if (mMenu == null || position == -1)
+        if (mMenu == null)
             return;
 
-        final MenuItem menuItem = mMenu.findItem(position);
-        if (menuItem != null) {
-            mNextAddonMenuId--;
-            mMenu.removeItem(position);
-        }
+        final MenuItem menuItem = mMenu.findItem(id);
+        if (menuItem != null)
+            mMenu.removeItem(id);
     }
 
-    private void updateAddonMenuItem(String id, final GeckoBundle options) {
-        int position = -1;
-
+    private void updateAddonMenuItem(int id, final GeckoBundle options) {
         // Set attribute for the menu item in cache, if available
         if (mAddonMenuItemsCache != null && !mAddonMenuItemsCache.isEmpty()) {
             for (MenuItemInfo item : mAddonMenuItemsCache) {
                 if (item.id == id) {
-                    position = item.position;
                     item.label = options.getString("name", item.label);
                     item.checkable = options.getBoolean("checkable", item.checkable);
                     item.checked = options.getBoolean("checked", item.checked);
                     item.enabled = options.getBoolean("enabled", item.enabled);
                     item.visible = options.getBoolean("visible", item.visible);
                     item.added = (mMenu != null);
                     break;
                 }
             }
         }
 
-        if (mMenu == null || position == -1) {
+        if (mMenu == null) {
             return;
         }
 
-        final MenuItem menuItem = mMenu.findItem(position);
+        final MenuItem menuItem = mMenu.findItem(id);
         if (menuItem != null) {
             menuItem.setTitle(options.getString("name", menuItem.getTitle().toString()));
             menuItem.setCheckable(options.getBoolean("checkable", menuItem.isCheckable()));
             menuItem.setChecked(options.getBoolean("checked", menuItem.isChecked()));
             menuItem.setEnabled(options.getBoolean("enabled", menuItem.isEnabled()));
             menuItem.setVisible(options.getBoolean("visible", menuItem.isVisible()));
         }
     }
@@ -4019,17 +4006,17 @@ public class BrowserApp extends GeckoApp
         mBrowserToolbar.onEditSuggestion(suggestion);
     }
 
     @Override
     public int getLayout() { return R.layout.gecko_app; }
 
     @Override
     public View getDoorhangerOverlay() {
-        return mDoorhangerOverlay;
+        return doorhangerOverlay;
     }
 
     public SearchEngineManager getSearchEngineManager() {
         return mSearchEngineManager;
     }
 
     // For use from tests only.
     @RobocopTarget
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -2257,52 +2257,52 @@ var NativeWindow = {
     GlobalEventDispatcher.sendRequest({
       type: "Dex:Unload",
       zipfile: zipFile
     });
   },
 
   menu: {
     _callbacks: [],
+    _menuId: 1,
     toolsMenuID: -1,
     add: function() {
       let options;
       if (arguments.length == 1) {
         options = arguments[0];
       } else if (arguments.length == 3) {
           Log.w("Browser", "This menu addon API has been deprecated. Instead, use the options object API.");
           options = {
             name: arguments[0],
             callback: arguments[2]
           };
       } else {
          throw "Incorrect number of parameters";
       }
 
       options.type = "Menu:Add";
-
-      let uuid = uuidgen.generateUUID().toString();
-      options.id = uuid;
+      options.id = this._menuId;
 
       GlobalEventDispatcher.sendRequest(options);
-      this._callbacks[uuid] = options.callback;
-      return uuid;
+      this._callbacks[this._menuId] = options.callback;
+      this._menuId++;
+      return this._menuId - 1;
     },
 
-    remove: function(uuid) {
-      GlobalEventDispatcher.sendRequest({ type: "Menu:Remove", id: uuid });
+    remove: function(aId) {
+      GlobalEventDispatcher.sendRequest({ type: "Menu:Remove", id: aId });
     },
 
-    update: function(uuid, aOptions) {
+    update: function(aId, aOptions) {
       if (!aOptions)
         return;
 
       GlobalEventDispatcher.sendRequest({
         type: "Menu:Update",
-        id: uuid,
+        id: aId,
         options: aOptions
       });
     }
   },
 
   doorhanger: {
     _callbacks: {},
     _callbacksId: 0,
--- a/mobile/android/components/extensions/ext-android.js
+++ b/mobile/android/components/extensions/ext-android.js
@@ -42,25 +42,16 @@ extensions.on("page-shutdown", (type, co
       }
     }
   }
 });
 /* eslint-enable mozilla/balanced-listeners */
 
 
 extensions.registerModules({
-  browserAction: {
-    url: "chrome://browser/content/ext-browserAction.js",
-    schema: "chrome://browser/content/schemas/browser_action.json",
-    scopes: ["addon_parent"],
-    manifest: ["browser_action"],
-    paths: [
-      ["browserAction"],
-    ],
-  },
   pageAction: {
     url: "chrome://browser/content/ext-pageAction.js",
     schema: "chrome://browser/content/schemas/page_action.json",
     scopes: ["addon_parent"],
     manifest: ["page_action"],
     paths: [
       ["pageAction"],
     ],
deleted file mode 100644
--- a/mobile/android/components/extensions/ext-browserAction.js
+++ /dev/null
@@ -1,78 +0,0 @@
-/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* vim: set sts=2 sw=2 et tw=80: */
-"use strict";
-
-XPCOMUtils.defineLazyModuleGetter(this, "EventEmitter",
-                                  "resource://devtools/shared/event-emitter.js");
-
-XPCOMUtils.defineLazyModuleGetter(this, "Services",
-                                  "resource://gre/modules/Services.jsm");
-
-// Import the android BrowserActions module.
-XPCOMUtils.defineLazyModuleGetter(this, "BrowserActions",
-                                  "resource://gre/modules/BrowserActions.jsm");
-
-// WeakMap[Extension -> BrowserAction]
-var browserActionMap = new WeakMap();
-
-class BrowserAction {
-  constructor(options, extension) {
-    this.id = `{${extension.uuid}}`;
-    this.name = options.default_title || extension.name;
-    BrowserActions.register(this);
-    EventEmitter.decorate(this);
-  }
-
-  /**
-   * Required by the BrowserActions module. This event will get
-   * called whenever the browser action is clicked on.
-   */
-  onClicked() {
-    this.emit("click", tabTracker.activeTab);
-  }
-
-  /**
-   * Unregister the browser action from the BrowserActions module.
-   */
-  shutdown() {
-    BrowserActions.unregister(this.id);
-  }
-}
-
-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(reason) {
-    let {extension} = this;
-
-    if (browserActionMap.has(extension)) {
-      browserActionMap.get(extension).shutdown();
-      browserActionMap.delete(extension);
-    }
-  }
-
-  getAPI(context) {
-    const {extension} = context;
-    const {tabManager} = extension;
-
-    return {
-      browserAction: {
-        onClicked: new SingletonEventManager(context, "browserAction.onClicked", fire => {
-          let listener = (event, tab) => {
-            fire.async(tabManager.convert(tab));
-          };
-          browserActionMap.get(extension).on("click", listener);
-          return () => {
-            browserActionMap.get(extension).off("click", listener);
-          };
-        }).api(),
-      },
-    };
-  }
-};
--- a/mobile/android/components/extensions/extensions-mobile.manifest
+++ b/mobile/android/components/extensions/extensions-mobile.manifest
@@ -1,4 +1,4 @@
-# modules
+# scripts
 category webextension-scripts android chrome://browser/content/ext-android.js
 category webextension-scripts utils chrome://browser/content/ext-utils.js
 category webextension-scripts-addon android chrome://browser/content/ext-c-android.js
--- a/mobile/android/components/extensions/jar.mn
+++ b/mobile/android/components/extensions/jar.mn
@@ -1,12 +1,11 @@
 # 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/.
 
 chrome.jar:
     content/ext-android.js
     content/ext-c-android.js
     content/ext-c-tabs.js
-    content/ext-browserAction.js
     content/ext-pageAction.js
     content/ext-tabs.js
     content/ext-utils.js
deleted file mode 100644
--- a/mobile/android/components/extensions/schemas/browser_action.json
+++ /dev/null
@@ -1,451 +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",
-                "unsupported": true,
-                "optional": true
-              },
-              "default_popup": {
-                "type": "string",
-                "format": "relativeUrl",
-                "unsupported": true,
-                "optional": true,
-                "preprocess": "localize"
-              },
-              "browser_style": {
-                "type": "boolean",
-                "unsupported": true,
-                "optional": true
-              },
-              "default_area": {
-                "description": "Defines the location the browserAction will appear by default.  The default location is navbar.",
-                "type": "string",
-                "enum": ["navbar", "menupanel", "tabstrip", "personaltoolbar"],
-                "unsupported": true,
-                "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",
-        "unsupported": true,
-        "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",
-        "unsupported": true,
-        "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",
-        "unsupported": true,
-        "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",
-        "unsupported": true,
-        "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,
-                "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,8 +1,7 @@
 # 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/.
 
 chrome.jar:
-    content/schemas/browser_action.json
     content/schemas/page_action.json
     content/schemas/tabs.json
--- a/mobile/android/components/extensions/test/mochitest/chrome.ini
+++ b/mobile/android/components/extensions/test/mochitest/chrome.ini
@@ -1,9 +1,8 @@
 [DEFAULT]
 support-files =
   head.js
   ../../../../../../toolkit/components/extensions/test/mochitest/chrome_cleanup_script.js
 tags = webextensions
 
-[test_ext_browserAction_onClicked.html]
 [test_ext_pageAction.html]
 [test_ext_pageAction_popup.html]
--- a/mobile/android/components/extensions/test/mochitest/head.js
+++ b/mobile/android/components/extensions/test/mochitest/head.js
@@ -1,13 +1,14 @@
 "use strict";
 
-/* exported AppConstants */
+/* exported isPageActionShown clickPageAction, AppConstants */
 
 var {AppConstants} = SpecialPowers.Cu.import("resource://gre/modules/AppConstants.jsm", {});
+var {PageActions} = SpecialPowers.Cu.import("resource://gre/modules/PageActions.jsm", {});
 
 {
   let chromeScript = SpecialPowers.loadChromeScript(
     SimpleTest.getTestFileURL("chrome_cleanup_script.js"));
 
   SimpleTest.registerCleanupFunction(async () => {
     await new Promise(resolve => setTimeout(resolve, 0));
 
@@ -16,8 +17,16 @@ var {AppConstants} = SpecialPowers.Cu.im
     let results = await chromeScript.promiseOneMessage("cleanup-results");
     chromeScript.destroy();
 
     if (results.extraWindows.length || results.extraTabs.length) {
       ok(false, `Test left extra windows or tabs: ${JSON.stringify(results)}\n`);
     }
   });
 }
+
+function isPageActionShown(uuid) {
+  return PageActions.isShown(uuid);
+}
+
+function clickPageAction(uuid) {
+  PageActions.synthesizeClick(uuid);
+}
deleted file mode 100644
--- a/mobile/android/components/extensions/test/mochitest/test_ext_browserAction_onClicked.html
+++ /dev/null
@@ -1,94 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <title>BrowserAction Test</title>
-  <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <script src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
-  <script src="chrome://mochikit/content/tests/SimpleTest/ExtensionTestUtils.js"></script>
-  <script type="text/javascript" src="head.js"></script>
-  <link rel="stylesheet" href="chrome://mochikit/contents/tests/SimpleTest/test.css"/>
-</head>
-<body>
-
-<script type="text/javascript">
-"use strict";
-
-var {BrowserActions} = SpecialPowers.Cu.import("resource://gre/modules/BrowserActions.jsm", {});
-
-async function background() {
-  browser.test.assertTrue("browserAction" in browser, "Namespace 'browserAction' exists in browser");
-  browser.test.assertTrue("onClicked" in browser.browserAction, "API method 'onClicked' exists in browser.browserAction");
-
-  const tabs = await browser.tabs.query({active: true, currentWindow: true});
-
-  browser.browserAction.onClicked.addListener(tab => {
-    browser.test.sendMessage("browser-action-clicked", tab);
-  });
-
-  browser.test.sendMessage("ready", tabs[0]);
-}
-
-function createExtension(name) {
-  return ExtensionTestUtils.loadExtension({
-    background,
-    manifest: {
-      "name": name,
-      "browser_action": {
-        "default_title": "Browser Action",
-      },
-    },
-  });
-}
-
-function* checkBrowserAction(extension, id, tab) {
-  ok(BrowserActions.isShown(id), "The BrowerAction should be shown");
-  BrowserActions.synthesizeClick(id);
-  const clickedTab = yield extension.awaitMessage("browser-action-clicked");
-  is(clickedTab.id, tab.id, "Got the expected tab id in the browserAction.onClicked event");
-}
-
-add_task(function* test_browserAction() {
-  const extension = createExtension("BrowserAction Extension");
-  yield extension.startup();
-  const tab = yield extension.awaitMessage("ready");
-  let id = `{${extension.uuid}}`;
-  yield checkBrowserAction(extension, id, tab);
-  yield extension.unload();
-
-  ok(!BrowserActions.isShown(id), "The BrowserAction should be removed after the extension unloads");
-});
-
-add_task(function* test_multiple_browserActions() {
-  const ext1 = createExtension("BrowserAction Extension 1");
-  const ext2 = createExtension("BrowserAction Extension 2");
-
-  // Start the first extension and test its browser action.
-  yield ext1.startup();
-  const tab1 = yield ext1.awaitMessage("ready");
-  let id1 = `{${ext1.uuid}}`;
-  yield checkBrowserAction(ext1, id1, tab1);
-
-  // Start the second extension and test its browser action.
-  yield ext2.startup();
-  const tab2 = yield ext2.awaitMessage("ready");
-  let id2 = `{${ext2.uuid}}`;
-  yield checkBrowserAction(ext2, id2, tab2);
-
-  // Verify that the first browser action is still active.
-  yield checkBrowserAction(ext1, id1, tab1);
-
-  // Unload the first extension and verify that the browser action is removed.
-  yield ext1.unload();
-  ok(!BrowserActions.isShown(id1), "The first BrowserAction should be removed after ext1 unloads");
-
-  // Verify that the second browser action is still active.
-  yield checkBrowserAction(ext2, id2, tab2);
-
-  // Unload the second extension and verify that the browser action is removed.
-  yield ext2.unload();
-  ok(!BrowserActions.isShown(id2), "The second BrowserAction should be removed after ext2 unloads");
-});
-</script>
-
-</body>
-</html>
--- a/mobile/android/components/extensions/test/mochitest/test_ext_pageAction.html
+++ b/mobile/android/components/extensions/test/mochitest/test_ext_pageAction.html
@@ -8,18 +8,16 @@
   <script type="text/javascript" src="head.js"></script>
   <link rel="stylesheet" href="chrome://mochikit/contents/tests/SimpleTest/test.css"/>
 </head>
 <body>
 
 <script type="text/javascript">
 "use strict";
 
-var {PageActions} = SpecialPowers.Cu.import("resource://gre/modules/PageActions.jsm", {});
-
 let dataURI = "iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAC4klEQVRYhdWXLWzbQBSADQtDAwsHC1tUhUxqfL67lk2tdn+OJg0ODU0rLByqgqINBY6tmlbn7LMTJ5FaFVVBk1G0oUGjG2jT2Y7jxmmcbU/6iJ+f36fz+e5sGP9riCGm9hB37RG+scd4Yo/wsDXCZyIE2xuXsce4bY+wXkAsQtzYmExrfFgvkJkRbkzo1ehoxx5iXcgI/9iYUGt8WH9MqDXEcmNChmEYrRCf2SHWeYgQx3x0tLNRIeKQLTtEFyJEep4NTuhk8BC+yMrwEE3+iozo42d8gK7FAOkMsRiiN8QhW2ttSK5QTfRRV4QoymVeJMvPvDp7gCZigD613MN6yRFA3SWarow9QB9LCfG+NeF9qCtjAKOSQjCqVKhfVsiHEQ+grgx/lRGqUihAc1uL8EFD+KCRO+GrF4J61phcoRoPoEzkYhZYpykh5sMb7kOdIeY+jHKur4QI4Feh4AFX1nVeLxrAvQchGsBz5ls6wa2QdwcvIcE2863bTH79KOvsz/uUYJsp+J0pSzNlDckVqqVGUAF+n6uS7txcOl6wot4JVy70ufDLy4pWLUQVPE81pRI0mGe9oxLMHSeohHvMs/STUNaUK6vDPCvOyxMFDx4achehRDJmHnydnkPww5OFfLxrGIZBFDyYl4LpMzlTQFIP6AQx86w2UeYBccFpJrcKv5L9eGDtUAU6RIELqsB74uynjy/UBRF1gS5BTFxwQT1wTiXoUg9MH7m/3NZRRoi5IJytUbMgzv4Wc832+oQkiKgEehmyMkkpKsFkQV11QsRJL5rJYBLItQgRaUZEmnoZXsomz3vGiWw+I9KMF9SVFOqZEemZekli1jN3U/UOqhHHvC6oWWGElhfSpGdOk6+O9prdwvtLj5BjRsQxdRnot+Zeifpy/2/0stktKTRNLmbk0mwXyl8253fyojj+8rxOHNAhjjm5n0/5OOCGOKBzkrMO0Z75lvSAzKlrF32Z/3z8BqLAn+yMV7VhAAAAAElFTkSuQmCC";
 
 let image = atob(dataURI);
 const IMAGE_ARRAYBUFFER = Uint8Array.from(image, byte => byte.charCodeAt(0)).buffer;
 
 async function background() {
   browser.test.assertTrue("pageAction" in browser, "Namespace 'pageAction' exists in browser");
   browser.test.assertTrue("show" in browser.pageAction, "API method 'show' exists in browser.pageAction");
@@ -37,17 +35,23 @@ async function background() {
       });
     }
   });
 
   browser.pageAction.onClicked.addListener(tab => {
     browser.test.sendMessage("page-action-clicked", tab);
   });
 
-  browser.test.sendMessage("ready", tabs[0]);
+  const extensionInfo = {
+    // Extract the assigned uuid from the background page url.
+    uuid: `{${window.location.hostname}}`,
+    tab: tabs[0],
+  };
+
+  browser.test.sendMessage("ready", extensionInfo);
 }
 
 add_task(function* test_pageAction() {
   const extension = ExtensionTestUtils.loadExtension({
     background,
     manifest: {
       "name": "PageAction Extension",
       "page_action": {
@@ -63,35 +67,34 @@ add_task(function* test_pageAction() {
       },
     },
     files: {
       "extension.png": IMAGE_ARRAYBUFFER,
     },
   });
 
   yield extension.startup();
-  const tab = yield extension.awaitMessage("ready");
-  const uuid = `{${extension.uuid}}`;
+  const {uuid, tab} = yield extension.awaitMessage("ready");
 
   extension.sendMessage("pageAction-show");
   yield extension.awaitMessage("page-action-shown");
-  ok(PageActions.isShown(uuid), "The PageAction should be shown");
+  ok(isPageActionShown(uuid), "The PageAction should be shown");
 
   extension.sendMessage("pageAction-hide");
   yield extension.awaitMessage("page-action-hidden");
-  ok(!PageActions.isShown(uuid), "The PageAction should be hidden");
+  ok(!isPageActionShown(uuid), "The PageAction should be hidden");
 
   extension.sendMessage("pageAction-show");
   yield extension.awaitMessage("page-action-shown");
-  ok(PageActions.isShown(uuid), "The PageAction should be shown");
+  ok(isPageActionShown(uuid), "The PageAction should be shown");
 
-  PageActions.synthesizeClick(uuid);
+  clickPageAction(uuid);
   const clickedTab = yield extension.awaitMessage("page-action-clicked");
-  ok(PageActions.isShown(uuid), "The PageAction should still be shown after being clicked");
+  ok(isPageActionShown(uuid), "The PageAction should still be shown after being clicked");
   is(clickedTab.id, tab.id, "Got the expected tab id in the pageAction.onClicked event");
 
   yield extension.unload();
-  ok(!PageActions.isShown(uuid), "The PageAction should be removed after unload");
+  ok(!isPageActionShown(uuid), "The PageAction should be removed after unload");
 });
 </script>
 
 </body>
 </html>
--- a/mobile/android/components/extensions/test/mochitest/test_ext_pageAction_popup.html
+++ b/mobile/android/components/extensions/test/mochitest/test_ext_pageAction_popup.html
@@ -12,24 +12,22 @@
 
 <script type="text/javascript">
 "use strict";
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
 Cu.import("resource://gre/modules/Services.jsm");
 
-var {PageActions} = Cu.import("resource://gre/modules/PageActions.jsm", {});
-
 let dataURI = "iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAC4klEQVRYhdWXLWzbQBSADQtDAwsHC1tUhUxqfL67lk2tdn+OJg0ODU0rLByqgqINBY6tmlbn7LMTJ5FaFVVBk1G0oUGjG2jT2Y7jxmmcbU/6iJ+f36fz+e5sGP9riCGm9hB37RG+scd4Yo/wsDXCZyIE2xuXsce4bY+wXkAsQtzYmExrfFgvkJkRbkzo1ehoxx5iXcgI/9iYUGt8WH9MqDXEcmNChmEYrRCf2SHWeYgQx3x0tLNRIeKQLTtEFyJEep4NTuhk8BC+yMrwEE3+iozo42d8gK7FAOkMsRiiN8QhW2ttSK5QTfRRV4QoymVeJMvPvDp7gCZigD613MN6yRFA3SWarow9QB9LCfG+NeF9qCtjAKOSQjCqVKhfVsiHEQ+grgx/lRGqUihAc1uL8EFD+KCRO+GrF4J61phcoRoPoEzkYhZYpykh5sMb7kOdIeY+jHKur4QI4Feh4AFX1nVeLxrAvQchGsBz5ls6wa2QdwcvIcE2863bTH79KOvsz/uUYJsp+J0pSzNlDckVqqVGUAF+n6uS7txcOl6wot4JVy70ufDLy4pWLUQVPE81pRI0mGe9oxLMHSeohHvMs/STUNaUK6vDPCvOyxMFDx4achehRDJmHnydnkPww5OFfLxrGIZBFDyYl4LpMzlTQFIP6AQx86w2UeYBccFpJrcKv5L9eGDtUAU6RIELqsB74uynjy/UBRF1gS5BTFxwQT1wTiXoUg9MH7m/3NZRRoi5IJytUbMgzv4Wc832+oQkiKgEehmyMkkpKsFkQV11QsRJL5rJYBLItQgRaUZEmnoZXsomz3vGiWw+I9KMF9SVFOqZEemZekli1jN3U/UOqhHHvC6oWWGElhfSpGdOk6+O9prdwvtLj5BjRsQxdRnot+Zeifpy/2/0stktKTRNLmbk0mwXyl8253fyojj+8rxOHNAhjjm5n0/5OOCGOKBzkrMO0Z75lvSAzKlrF32Z/3z8BqLAn+yMV7VhAAAAAElFTkSuQmCC";
 
 let image = atob(dataURI);
 const IMAGE_ARRAYBUFFER = Uint8Array.from(image, byte => byte.charCodeAt(0)).buffer;
 
-add_task(function* test_pageAction_withPopup() {
+add_task(function* test_contentscript() {
   function background() {
     // TODO: Use the Tabs API to obtain the tab ids for showing pageActions.
     let tabId = 1;
     let onClickedListenerEnabled = false;
 
     browser.test.onMessage.addListener((msg, details) => {
       if (msg === "page-action-show") {
         // TODO: switch to using .show(tabId).then(...) once bug 1270742 lands.
@@ -53,17 +51,22 @@ add_task(function* test_pageAction_withP
       }
     });
 
     browser.pageAction.onClicked.addListener(tab => {
       browser.test.assertTrue(onClickedListenerEnabled, "The onClicked listener should only fire when it is enabled.");
       browser.test.sendMessage("page-action-onClicked-fired");
     });
 
-    browser.test.sendMessage("ready");
+    let extensionInfo = {
+      // Extract the assigned uuid from the background page url.
+      uuid: `{${window.location.hostname}}`,
+    };
+
+    browser.test.sendMessage("ready", extensionInfo);
   }
 
   function popupScript() {
     window.onload = () => {
       browser.test.sendMessage("page-action-from-popup", location.href);
     };
     browser.test.onMessage.addListener((msg, details) => {
       if (msg == "page-action-close-popup") {
@@ -123,47 +126,46 @@ add_task(function* test_pageAction_withP
 
     if (name == "") {
       ok(url == name, "Calling pageAction.getPopup should return an empty string when the popup is not set.");
 
       // The onClicked listener should get called when the popup is set to an empty string.
       extension.sendMessage("page-action-enable-onClicked-listener");
       yield extension.awaitMessage("page-action-onClicked-listener-enabled");
 
-      PageActions.synthesizeClick(uuid);
+      clickPageAction(uuid);
       yield extension.awaitMessage("page-action-onClicked-fired");
 
       extension.sendMessage("page-action-disable-onClicked-listener");
       yield extension.awaitMessage("page-action-onClicked-listener-disabled");
     } else {
       ok(url.includes(name), "Calling pageAction.getPopup should return the correct popup URL when the popup is set.");
 
-      PageActions.synthesizeClick(uuid);
+      clickPageAction(uuid);
       let location = yield extension.awaitMessage("page-action-from-popup");
       ok(location.includes(name), "The popup with the correct URL should be shown.");
 
       extension.sendMessage("page-action-close-popup", {location});
 
       url = yield tabClosedPromise();
       ok(url.includes(name), "The tab for the popup should be closed.");
     }
   }
 
   yield extension.startup();
-  yield extension.awaitMessage("ready");
-  const uuid = `{${extension.uuid}}`;
+  let {uuid} = yield extension.awaitMessage("ready");
 
   extension.sendMessage("page-action-show");
   yield extension.awaitMessage("page-action-shown");
-  ok(PageActions.isShown(uuid), "The PageAction should be shown.");
+  ok(isPageActionShown(uuid), "The PageAction should be shown.");
 
   yield testPopup("default.html", uuid);
   yield testPopup("a.html", uuid);
   yield testPopup("", uuid);
   yield testPopup("b.html", uuid);
 
   yield extension.unload();
-  ok(!PageActions.isShown(uuid), "The PageAction should be removed after unload.");
+  ok(!isPageActionShown(uuid), "The PageAction should be removed after unload.");
 });
 </script>
 
 </body>
 </html>
deleted file mode 100644
--- a/mobile/android/modules/BrowserActions.jsm
+++ /dev/null
@@ -1,113 +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 { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Messaging.jsm");
-
-this.EXPORTED_SYMBOLS = ["BrowserActions"];
-
-var BrowserActions = {
-  _browserActions: {},
-
-  _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: function() {
-    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 ID.
-   */
-  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) {
-      throw new Error(`No browser action found with id ${data.item}`);
-    }
-    browserAction.onClicked();
-  },
-
-  /**
-   * Registers a new browser action.
-   * @param {Object} browserAction The browser action to add.
-   */
-  register(browserAction) {
-    EventDispatcher.instance.sendRequest({
-      type: "Menu:Add",
-      id: browserAction.id,
-      name: browserAction.name,
-    });
-
-    this._browserActions[browserAction.id] = browserAction;
-    this._maybeRegisterListeners();
-  },
-
-  /**
-   * Checks to see if the browser action is shown. Used for testing only.
-   * @param {string} id The ID of the browser action.
-   * @returns True if the browser action is shown; false otherwise.
-   */
-  isShown: function(id) {
-    return !!this._browserActions[id];
-  },
-
-  /**
-   * Synthesizes a click on the browser action. Used for testing only.
-   * @param {string} id The ID of the browser action.
-   */
-  synthesizeClick: function(id) {
-    let browserAction = this._browserActions[id];
-    if (!browserAction) {
-      throw new Error(`No browser action found with id ${id}`);
-    }
-    browserAction.onClicked();
-  },
-
-  /**
-   * Unregisters the browser action with the specified ID.
-   * @param {string} id The browser action ID.
-   */
-  unregister(id) {
-    let browserAction = this._browserActions[id];
-    if (!browserAction) {
-      throw new Error(`No BrowserAction with ID ${id} was found`);
-    }
-    EventDispatcher.instance.sendRequest({
-      type: "Menu:Remove",
-      id,
-    });
-    delete this._browserActions[id];
-    this._maybeUnregisterListeners();
-  }
-}
\ No newline at end of file
--- a/mobile/android/modules/PageActions.jsm
+++ b/mobile/android/modules/PageActions.jsm
@@ -29,31 +29,31 @@ function resolveGeckoURI(aURI) {
     return handler.resolveURI(Services.io.newURI(aURI));
   }
   return aURI;
 }
 
 var PageActions = {
   _items: { },
 
-  _initialized: false,
+  _inited: false,
 
-  _maybeInitialize: function() {
-    if (!this._initialized && Object.keys(this._items).length) {
-      this._initialized = true;
+  _maybeInit: function() {
+    if (!this._inited && Object.keys(this._items).length > 0) {
+      this._inited = true;
       EventDispatcher.instance.registerListener(this, [
         "PageActions:Clicked",
         "PageActions:LongClicked",
       ]);
     }
   },
 
-  _maybeUninitialize: function() {
-    if (this._initialized && !Object.keys(this._items).length) {
-      this._initialized = false;
+  _maybeUninit: function() {
+    if (this._inited && Object.keys(this._items).length == 0) {
+      this._inited = false;
       EventDispatcher.instance.unregisterListener(this, [
         "PageActions:Clicked",
         "PageActions:LongClicked",
       ]);
     }
   },
 
   onEvent: function(event, data, callback) {
@@ -96,22 +96,22 @@ var PageActions = {
     if (aOptions.clickCallback) {
       this._items[id].clickCallback = aOptions.clickCallback;
     }
 
     if (aOptions.longClickCallback) {
       this._items[id].longClickCallback = aOptions.longClickCallback;
     }
 
-    this._maybeInitialize();
+    this._maybeInit();
     return id;
   },
 
   remove: function(id) {
     EventDispatcher.instance.sendRequest({
       type: "PageActions:Remove",
       id: id
     });
 
     delete this._items[id];
-    this._maybeUninitialize();
+    this._maybeUninit();
   }
 }
--- a/mobile/android/modules/moz.build
+++ b/mobile/android/modules/moz.build
@@ -16,17 +16,16 @@ with Files('HomeProvider.jsm'):
 
 with Files('geckoview/**'):
     BUG_COMPONENT = ('Firefox for Android', 'GeckoView')
 
 DIRS += ['geckoview']
 
 EXTRA_JS_MODULES += [
     'Accounts.jsm',
-    'BrowserActions.jsm',
     'dbg-browser-actors.js',
     'DelayedInit.jsm',
     'DownloadNotifications.jsm',
     'FxAccountsWebChannel.jsm',
     'HelperApps.jsm',
     'Home.jsm',
     'HomeProvider.jsm',
     'JavaAddonManager.jsm',
--- a/testing/specialpowers/content/SpecialPowersObserverAPI.js
+++ b/testing/specialpowers/content/SpecialPowersObserverAPI.js
@@ -565,17 +565,17 @@ SpecialPowersObserverAPI.prototype = {
       }
 
       case "SPStartupExtension": {
         let {ExtensionData} = Components.utils.import("resource://gre/modules/Extension.jsm", {});
 
         let id = aMessage.data.id;
         let extension = this._extensions.get(id);
         extension.on("startup", () => {
-          this._sendReply(aMessage, "SPExtensionMessage", {id, type: "extensionSetId", args: [extension.id, extension.uuid]});
+          this._sendReply(aMessage, "SPExtensionMessage", {id, type: "extensionSetId", args: [extension.id]});
         });
 
         // Make sure the extension passes the packaging checks when
         // they're run on a bare archive rather than a running instance,
         // as the add-on manager runs them.
         let extensionData = new ExtensionData(extension.rootURI);
         extensionData.loadManifest().then(
           () => {
--- a/testing/specialpowers/content/specialpowersAPI.js
+++ b/testing/specialpowers/content/specialpowersAPI.js
@@ -1996,17 +1996,16 @@ SpecialPowersAPI.prototype = {
 
     let listener = (msg) => {
       if (msg.data.id == id) {
         if (msg.data.type == "extensionStarted") {
           state = "running";
           resolveStartup();
         } else if (msg.data.type == "extensionSetId") {
           extension.id = msg.data.args[0];
-          extension.uuid = msg.data.args[1];
         } else if (msg.data.type == "extensionFailed") {
           state = "failed";
           rejectStartup("startup failed");
         } else if (msg.data.type == "extensionUnloaded") {
           this._extensionListeners.delete(listener);
           state = "unloaded";
           resolveUnload();
         } else if (msg.data.type in handler) {
--- a/toolkit/components/extensions/ExtensionXPCShellUtils.jsm
+++ b/toolkit/components/extensions/ExtensionXPCShellUtils.jsm
@@ -183,17 +183,16 @@ class ExtensionWrapper {
       } else if (this.state == "unloading") {
         this.testScope.equal(this.state, "unloaded", "Extension not fully unloaded at test shutdown");
       }
       this.destroy();
     });
 
     if (extension) {
       this.id = extension.id;
-      this.uuid = extension.uuid;
       this.attachExtension(extension);
     }
   }
 
   destroy() {
     // This method should be implemented in subclasses which need to
     // perform cleanup when destroyed.
   }