diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java index 6e6d841bc30b..9babff7f3644 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java @@ -3152,6 +3152,9 @@ public class GeckoSession implements Parcelable { */ public final @Nullable String srcUri; + // TODO: Bug 1595822 make public + final List extensionMenus; + protected ContextElement( final @Nullable String baseUri, final @Nullable String linkUri, @@ -3165,6 +3168,7 @@ public class GeckoSession implements Parcelable { this.altText = altText; this.type = getType(typeStr); this.srcUri = srcUri; + this.extensionMenus = null; } private static int getType(final String name) { diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtension.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtension.java index 4ad02dbbb65c..c5aa8be537c1 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtension.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtension.java @@ -1864,4 +1864,259 @@ public class WebExtension { } } } + + // TODO: make public bug 1595822 + + @IntDef(flag = true, + value = {Context.NONE, Context.BOOKMARK, Context.BROWSER_ACTION, + Context.PAGE_ACTION, Context.TAB, Context.TOOLS_MENU}) + + /* package */ @interface ContextFlags {} + + /** + * Flags to determine which contexts a menu item should be shown in. + * See + * menus.ContextType. + **/ + static class Context { + /** + * Shows the menu item in no contexts. + */ + static final int NONE = 0; + + /** + * Shows the menu item when the user context-clicks an item on the bookmarks toolbar, bookmarks menu, + * bookmarks sidebar, or Library window. + */ + static final int BOOKMARK = 1 << 1; + + /** + * Shows the menu item when the user context-clicks the extension's browser action. + */ + static final int BROWSER_ACTION = 1 << 2; + + /** + * Shows the menu item when the user context-clicks on the extension's page action. + */ + static final int PAGE_ACTION = 1 << 3; + + /** + * Shows when the user context-clicks on a tab (such as the element on the tab bar.) + */ + static final int TAB = 1 << 4; + + /** + * Adds the item to the browser's tools menu. + */ + static final int TOOLS_MENU = 1 << 5; + + } + + // TODO: make public bug 1595822 + + /** + * Represents an addition to the context menu by an extension. + * + * In the menus + * API, all elements added by one extension should be collapsed under one header. This class represents + * all of one extension's menu items, as well as the icon that should be used with that header. + * + */ + static class Menu { + /** + * List of menu items that belong to this extension. + */ + final @NonNull List items; + + /** + * Icon for this extension. + */ + final @Nullable Icon icon; + + /** + * Title for the menu header. + */ + final @Nullable String title; + + /** + * The extension adding this Menu to the context menu. + */ + final @NonNull WebExtension extension; + + /* package */ Menu(final @NonNull WebExtension extension, final GeckoBundle bundle) { + this.extension = extension; + title = bundle.getString("title", ""); + GeckoBundle[] items = bundle.getBundleArray("items"); + this.items = new ArrayList<>(); + if (items != null) { + for (GeckoBundle item : items) { + this.items.add(new MenuItem(this.extension, item)); + } + } + + if (bundle.containsKey("icon")) { + icon = new Icon(bundle.getBundle("icon")); + } else { + icon = null; + } + } + + /** + * Notifies the extension that a user has opened the context menu. + */ + void show() { + final GeckoBundle bundle = new GeckoBundle(1); + bundle.putString("extensionId", extension.id); + + EventDispatcher.getInstance().dispatch( + "GeckoView:WebExtension:MenuShow", bundle); + } + + /** + * Notifies the extension that a user has hidden the context menu. + */ + void hide() { + final GeckoBundle bundle = new GeckoBundle(1); + bundle.putString("extensionId", extension.id); + + EventDispatcher.getInstance().dispatch( + "GeckoView:WebExtension:MenuHide", bundle); + } + } + + // TODO: make public bug 1595822 + /** + * Represents an item in the menu. + * + * If there is only one menu item in the list, the embedder should display that item as itself, + * not under a header. + */ + static class MenuItem { + + @IntDef(flag = false, + value = {MenuType.NORMAL, MenuType.CHECKBOX, MenuType.RADIO, MenuType.SEPARATOR}) + + /* package */ @interface Type {} + + /** + * A set of constants that represents the display type of this menu item. + */ + static class MenuType { + /** + * This represents a menu item that just displays a label. + *

+ * See + * menus.ItemType.normal + */ + static final int NORMAL = 0; + + /** + * This represents a menu item that can be selected and deselected. + *

+ * See + * menus.ItemType.checkbox + */ + static final int CHECKBOX = 1; + + /** + * This represents a menu item that is one of a group of choices. All menu items for an + * extension that are of type radio are part of one radio group. + *

+ * See + * menus.ItemType.radio + */ + static final int RADIO = 2; + + /** + * This represents a line separating elements. + *

+ * See + * menus.ItemType.separator + */ + static final int SEPARATOR = 3; + } + + + + /** + * Direct children for this menu item. These should be displayed as a sub-menu. + * + * See + * createProperties.parentId + */ + final @Nullable List children; + + /** + * One of the {@link Type} constants. Determines the type of the action. + */ + final @Type int type; + + /** The id of this menu item. See + * createProperties.id + */ + final @Nullable String id; + + /** + * Determines if the menu item should be currently displayed. + */ + final boolean visible; + + /** + * The title to be displayed for this menu item. + */ + final @Nullable String title; + + /** + * Whether or not the menu item is initially checked. Defaults to false. + */ + final boolean checked; + + /** + * Contexts that this menu item should be shown in. + */ + final @ContextFlags int contexts; + + /** + * Icon for this menu item. + */ + final @Nullable Icon icon; + + final WebExtension mExtension; + + /** + * Creates a new menu item using a bundle and a reference to the extension that + * this item belongs to. + * + * @param extension WebExtension object. + * @param bundle GeckoBundle containing the item information. + */ + /* package */ MenuItem(final WebExtension extension, final GeckoBundle bundle) { + title = bundle.getString("title"); + mExtension = extension; + checked = bundle.getBoolean("checked", false); + visible = bundle.getBoolean("visible", true); + id = bundle.getString("id"); + contexts = bundle.getInt("contexts"); + type = bundle.getInt("type"); + children = new ArrayList<>(); + + if (bundle.containsKey("icon")) { + icon = new Icon(bundle.getBundle("icon")); + } else { + icon = null; + } + } + + /** + * Notifies the extension that the user has clicked on this menu item. + */ + void click() { + final GeckoBundle bundle = new GeckoBundle(2); + bundle.putString("menuId", this.id); + bundle.putString("extensionId", mExtension.id); + + EventDispatcher.getInstance().dispatch( + "GeckoView:WebExtension:MenuClick", bundle); + } + } } diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtensionController.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtensionController.java index b9e5d9eebe98..67072919d19a 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtensionController.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtensionController.java @@ -901,7 +901,6 @@ public class WebExtensionController { openOptionsPage(message, extension); return; } - final String nativeApp = bundle.getString("nativeApp"); if (nativeApp == null) { if (BuildConfig.DEBUG) { @@ -1366,4 +1365,9 @@ public class WebExtensionController { delegate.onPageAction(extension, message.session, action); } } + + // TODO: implement bug 1595822 + /* package */ static GeckoResult> getMenu(final GeckoBundle menuArrayBundle) { + return null; + } } diff --git a/mobile/android/modules/geckoview/GeckoViewWebExtension.jsm b/mobile/android/modules/geckoview/GeckoViewWebExtension.jsm index 9e3e7d005b7f..5794a293cf0e 100644 --- a/mobile/android/modules/geckoview/GeckoViewWebExtension.jsm +++ b/mobile/android/modules/geckoview/GeckoViewWebExtension.jsm @@ -875,6 +875,19 @@ var GeckoViewWebExtension = { this.pageActionClick(aData.extensionId); break; } + case "GeckoView:WebExtension:MenuClick": { + aCallback.onError(`Not implemented`); + break; + } + case "GeckoView:WebExtension:MenuShow": { + aCallback.onError(`Not implemented`); + break; + } + case "GeckoView:WebExtension:MenuHide": { + aCallback.onError(`Not implemented`); + break; + } + // TODO: Remove deprecated Bug 1634504 case "GeckoView:RegisterWebExtension": { let uri;