mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 03:45:46 +00:00
Merge mozilla-central to mozilla-inbound
This commit is contained in:
commit
fc2b61e583
@ -236,7 +236,7 @@ public class BrowserApp extends GeckoApp
|
||||
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;
|
||||
@ -258,9 +258,8 @@ public class BrowserApp extends GeckoApp
|
||||
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;
|
||||
@ -295,9 +294,6 @@ public class BrowserApp extends GeckoApp
|
||||
// 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;
|
||||
@ -736,7 +732,7 @@ public class BrowserApp extends GeckoApp
|
||||
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",
|
||||
@ -1799,7 +1795,8 @@ public class BrowserApp extends GeckoApp
|
||||
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":
|
||||
@ -1809,8 +1806,7 @@ public class BrowserApp extends GeckoApp
|
||||
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);
|
||||
@ -1818,11 +1814,10 @@ public class BrowserApp extends GeckoApp
|
||||
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":
|
||||
@ -3093,13 +3088,13 @@ public class BrowserApp extends GeckoApp
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@ -3129,38 +3124,30 @@ public class BrowserApp extends GeckoApp
|
||||
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);
|
||||
@ -3172,11 +3159,11 @@ public class BrowserApp extends GeckoApp
|
||||
}
|
||||
}
|
||||
|
||||
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()));
|
||||
@ -4024,7 +4011,7 @@ public class BrowserApp extends GeckoApp
|
||||
|
||||
@Override
|
||||
public View getDoorhangerOverlay() {
|
||||
return mDoorhangerOverlay;
|
||||
return doorhangerOverlay;
|
||||
}
|
||||
|
||||
public SearchEngineManager getSearchEngineManager() {
|
||||
|
@ -2262,6 +2262,7 @@ var NativeWindow = {
|
||||
|
||||
menu: {
|
||||
_callbacks: [],
|
||||
_menuId: 1,
|
||||
toolsMenuID: -1,
|
||||
add: function() {
|
||||
let options;
|
||||
@ -2278,26 +2279,25 @@ var NativeWindow = {
|
||||
}
|
||||
|
||||
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
|
||||
});
|
||||
}
|
||||
|
@ -47,15 +47,6 @@ extensions.on("page-shutdown", (type, context) => {
|
||||
|
||||
|
||||
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",
|
||||
|
@ -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(),
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
@ -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
|
||||
|
@ -6,7 +6,6 @@ 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
|
||||
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
@ -3,6 +3,5 @@
|
||||
# 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
|
||||
|
@ -4,6 +4,5 @@ support-files =
|
||||
../../../../../../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]
|
||||
|
@ -1,8 +1,9 @@
|
||||
"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(
|
||||
@ -21,3 +22,11 @@ var {AppConstants} = SpecialPowers.Cu.import("resource://gre/modules/AppConstant
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function isPageActionShown(uuid) {
|
||||
return PageActions.isShown(uuid);
|
||||
}
|
||||
|
||||
function clickPageAction(uuid) {
|
||||
PageActions.synthesizeClick(uuid);
|
||||
}
|
||||
|
@ -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>
|
@ -13,8 +13,6 @@
|
||||
<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);
|
||||
@ -42,7 +40,13 @@ async function background() {
|
||||
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() {
|
||||
@ -68,28 +72,27 @@ add_task(function* test_pageAction() {
|
||||
});
|
||||
|
||||
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>
|
||||
|
||||
|
@ -17,14 +17,12 @@ 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;
|
||||
@ -58,7 +56,12 @@ add_task(function* test_pageAction_withPopup() {
|
||||
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() {
|
||||
@ -128,7 +131,7 @@ add_task(function* test_pageAction_withPopup() {
|
||||
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");
|
||||
@ -136,7 +139,7 @@ add_task(function* test_pageAction_withPopup() {
|
||||
} 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.");
|
||||
|
||||
@ -148,12 +151,11 @@ add_task(function* test_pageAction_withPopup() {
|
||||
}
|
||||
|
||||
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);
|
||||
@ -161,7 +163,7 @@ add_task(function* test_pageAction_withPopup() {
|
||||
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>
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -34,11 +34,11 @@ function resolveGeckoURI(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",
|
||||
@ -46,9 +46,9 @@ var PageActions = {
|
||||
}
|
||||
},
|
||||
|
||||
_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",
|
||||
@ -101,7 +101,7 @@ var PageActions = {
|
||||
this._items[id].longClickCallback = aOptions.longClickCallback;
|
||||
}
|
||||
|
||||
this._maybeInitialize();
|
||||
this._maybeInit();
|
||||
return id;
|
||||
},
|
||||
|
||||
@ -112,6 +112,6 @@ var PageActions = {
|
||||
});
|
||||
|
||||
delete this._items[id];
|
||||
this._maybeUninitialize();
|
||||
this._maybeUninit();
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ DIRS += ['geckoview']
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'Accounts.jsm',
|
||||
'BrowserActions.jsm',
|
||||
'dbg-browser-actors.js',
|
||||
'DelayedInit.jsm',
|
||||
'DownloadNotifications.jsm',
|
||||
|
@ -570,7 +570,7 @@ SpecialPowersObserverAPI.prototype = {
|
||||
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
|
||||
|
@ -2001,7 +2001,6 @@ SpecialPowersAPI.prototype = {
|
||||
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");
|
||||
|
@ -188,7 +188,6 @@ class ExtensionWrapper {
|
||||
|
||||
if (extension) {
|
||||
this.id = extension.id;
|
||||
this.uuid = extension.uuid;
|
||||
this.attachExtension(extension);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user