[epiphany/pgriffis/browser-action-abstraction: 5/5] WebExtensions: Redesign Browser Actions to have a flexible presentation
- From: Marge Bot <marge-bot src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [epiphany/pgriffis/browser-action-abstraction: 5/5] WebExtensions: Redesign Browser Actions to have a flexible presentation
- Date: Thu, 13 Oct 2022 14:44:05 +0000 (UTC)
commit 9496817d20251e3c00dfba37279de04a717c7b21
Author: Patrick Griffis <pgriffis igalia com>
Date: Mon Oct 10 20:01:00 2022 -0500
WebExtensions: Redesign Browser Actions to have a flexible presentation
Previously the WebExtensionManager would directly poke around inserting
widgets into the HeaderBar. This falls apart with adaptive views so
switching to mobile would lose access to extensions.
This changes the design where WebExtensionsManager exposes a list of
EphyBrowserAction objects and the UI tracks this list and decides
how to show them in any mode or in multiple windows.
As well as this change the UI was changed so now all browser actions
are shown in a popover and the popover doubles as the browser actions
popup UI when clicked. This matches Firefox's UI (but is even smoother!).
The ability to show all actions as a dedicated button in the headerbar
was lost for now. I think this is ok for now but ideally we implement
a solution similar to other browsers where the user can select which
ones to be dedicated buttons and which ones to go into the dropdown.
Part-of: <https://gitlab.gnome.org/GNOME/epiphany/-/merge_requests/1199>
meson.build | 6 +-
src/ephy-action-bar-end.c | 182 ++++++++++++++++++++++--
src/ephy-action-bar-end.h | 5 +-
src/ephy-header-bar.c | 7 -
src/ephy-header-bar.h | 3 -
src/resources/epiphany.gresource.xml | 1 +
src/resources/gtk/action-bar-end.ui | 92 ++++++++++++-
src/resources/gtk/browser-action-row.ui | 32 +++++
src/resources/themes/_shared-base.scss | 4 +
src/webextension/api/commands.c | 3 +-
src/webextension/api/menus.c | 4 +-
src/webextension/ephy-browser-action-row.c | 147 ++++++++++++++++++++
src/webextension/ephy-browser-action-row.h | 37 +++++
src/webextension/ephy-browser-action.c | 150 ++++++++++++++++++++
src/webextension/ephy-browser-action.h | 39 ++++++
src/webextension/ephy-web-extension-manager.c | 191 +++++++++++---------------
src/webextension/ephy-web-extension-manager.h | 14 +-
src/webextension/meson.build | 2 +
18 files changed, 767 insertions(+), 152 deletions(-)
---
diff --git a/meson.build b/meson.build
index 0270ed4fd..30fb154c4 100644
--- a/meson.build
+++ b/meson.build
@@ -73,13 +73,13 @@ gsb_api_key = get_option('gsb_api_key')
conf.set_quoted('GSB_API_KEY', gsb_api_key)
conf.set10('ENABLE_GSB', gsb_api_key != '')
-glib_requirement = '>= 2.67.4'
+glib_requirement = '>= 2.70.0'
gtk_requirement = '>= 3.24.0'
nettle_requirement = '>= 3.4'
webkitgtk_requirement = '>= 2.37.90'
-conf.set('GLIB_VERSION_MIN_REQUIRED', 'GLIB_VERSION_2_68')
-conf.set('GLIB_VERSION_MAX_ALLOWED', 'GLIB_VERSION_2_68')
+conf.set('GLIB_VERSION_MIN_REQUIRED', 'GLIB_VERSION_2_70')
+conf.set('GLIB_VERSION_MAX_ALLOWED', 'GLIB_VERSION_2_70')
cairo_dep = dependency('cairo', version: '>= 1.2')
gcr_dep = dependency('gcr-3', version: '>= 3.5.5')
diff --git a/src/ephy-action-bar-end.c b/src/ephy-action-bar-end.c
index c6e0cd154..c93c3d78a 100644
--- a/src/ephy-action-bar-end.c
+++ b/src/ephy-action-bar-end.c
@@ -21,10 +21,13 @@
#include "ephy-action-bar-end.h"
#include "ephy-add-bookmark-popover.h"
+#include "ephy-browser-action.h"
+#include "ephy-browser-action-row.h"
#include "ephy-desktop-utils.h"
#include "ephy-downloads-popover.h"
#include "ephy-location-entry.h"
#include "ephy-shell.h"
+#include "ephy-web-extension-manager.h"
#include "ephy-window.h"
#define NEEDS_ATTENTION_ANIMATION_TIMEOUT 2000 /*ms */
@@ -42,7 +45,13 @@ struct _EphyActionBarEnd {
GtkWidget *downloads_popover;
GtkWidget *downloads_icon;
GtkWidget *downloads_progress;
- GtkWidget *browser_action_box;
+ GtkWidget *browser_actions_button;
+ GtkWidget *browser_actions_popover;
+ GtkWidget *browser_actions_scrolled_window;
+ GtkWidget *browser_actions_listbox;
+ GtkWidget *browser_actions_stack;
+ GtkWidget *browser_actions_popup_view_box;
+ GtkWidget *browser_actions_popup_view_label;
guint downloads_button_attention_timeout_id;
};
@@ -50,6 +59,8 @@ struct _EphyActionBarEnd {
G_DEFINE_TYPE (EphyActionBarEnd, ephy_action_bar_end, GTK_TYPE_BOX)
static void begin_complete_theatrics (EphyActionBarEnd *self);
+static void set_browser_actions (EphyActionBarEnd *action_bar_end,
+ GListStore *browser_actions);
static void
remove_downloads_button_attention_style (EphyActionBarEnd *self)
@@ -223,6 +234,93 @@ show_downloads_cb (EphyDownloadsManager *manager,
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (action_bar_end->downloads_button), TRUE);
}
+static void
+remove_popup_webview (EphyActionBarEnd *action_bar_end)
+{
+ GList *children = gtk_container_get_children (GTK_CONTAINER
(action_bar_end->browser_actions_popup_view_box));
+ GtkWidget *last_child = GTK_WIDGET (g_list_last (children)->data);
+
+ if (WEBKIT_IS_WEB_VIEW (last_child))
+ gtk_widget_destroy (last_child);
+
+ g_list_free (children);
+}
+
+static void
+show_browser_action_popup (EphyActionBarEnd *action_bar_end,
+ EphyBrowserAction *action)
+{
+ EphyWebExtensionManager *manager = ephy_web_extension_manager_get_default ();
+ EphyWebExtension *web_extension = ephy_browser_action_get_web_extension (action);
+ GtkWidget *popup_view = ephy_web_extension_manager_create_browser_popup (manager, web_extension);
+
+ gtk_container_add (GTK_CONTAINER (action_bar_end->browser_actions_popup_view_box), popup_view);
+
+ gtk_label_set_text (GTK_LABEL (action_bar_end->browser_actions_popup_view_label),
+ ephy_browser_action_get_title (action));
+
+ gtk_stack_set_visible_child (GTK_STACK (action_bar_end->browser_actions_stack),
+ action_bar_end->browser_actions_popup_view_box);
+}
+
+static void
+browser_actions_popup_view_back_clicked_cb (GtkButton *button,
+ EphyActionBarEnd *action_bar_end)
+{
+ gtk_stack_set_visible_child (GTK_STACK (action_bar_end->browser_actions_stack),
+ action_bar_end->browser_actions_scrolled_window);
+ remove_popup_webview (action_bar_end);
+}
+
+static void
+show_browser_action_cb (EphyWebExtensionManager *manager,
+ EphyBrowserAction *action,
+ EphyActionBarEnd *action_bar_end)
+{
+ GtkWindow *parent_window = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (action_bar_end)));
+ GtkWindow *active_window = gtk_application_get_active_window (GTK_APPLICATION (g_application_get_default
()));
+
+ /* There may be multiple action bars that exist. We only want to show the popup in the visible bar the
active window. */
+ if (parent_window != active_window)
+ return;
+ if (!gtk_widget_is_visible (action_bar_end->browser_actions_button))
+ return;
+
+ remove_popup_webview (action_bar_end);
+ gtk_popover_popup (GTK_POPOVER (action_bar_end->browser_actions_popover));
+ show_browser_action_popup (action_bar_end, action);
+}
+
+static void
+browser_actions_row_activated_cb (GtkListBox *listbox,
+ EphyBrowserActionRow *row,
+ EphyActionBarEnd *action_bar_end)
+{
+ EphyBrowserAction *action = ephy_browser_action_row_get_browser_action (row);
+
+ /* If it was handled we are done, otherwise we have to show a popup. */
+ if (ephy_browser_action_activate (action)) {
+ gtk_popover_popdown (GTK_POPOVER (action_bar_end->browser_actions_popover));
+ return;
+ }
+
+ show_browser_action_popup (action_bar_end, action);
+}
+
+static void
+browser_action_popover_visible_changed_cb (GtkWidget *popover,
+ GParamSpec *pspec,
+ EphyActionBarEnd *action_bar_end)
+{
+ if (!gtk_widget_get_visible (popover)) {
+ GtkStack *stack = GTK_STACK (action_bar_end->browser_actions_stack);
+
+ /* Reset to default state and destroy any open webview. */
+ gtk_stack_set_visible_child (stack, action_bar_end->browser_actions_scrolled_window);
+ remove_popup_webview (action_bar_end);
+ }
+}
+
static void
ephy_action_bar_end_class_init (EphyActionBarEndClass *klass)
{
@@ -254,7 +352,30 @@ ephy_action_bar_end_class_init (EphyActionBarEndClass *klass)
downloads_progress);
gtk_widget_class_bind_template_child (widget_class,
EphyActionBarEnd,
- browser_action_box);
+ browser_actions_button);
+ gtk_widget_class_bind_template_child (widget_class,
+ EphyActionBarEnd,
+ browser_actions_popover);
+ gtk_widget_class_bind_template_child (widget_class,
+ EphyActionBarEnd,
+ browser_actions_scrolled_window);
+ gtk_widget_class_bind_template_child (widget_class,
+ EphyActionBarEnd,
+ browser_actions_listbox);
+ gtk_widget_class_bind_template_child (widget_class,
+ EphyActionBarEnd,
+ browser_actions_stack);
+ gtk_widget_class_bind_template_child (widget_class,
+ EphyActionBarEnd,
+ browser_actions_popup_view_box);
+ gtk_widget_class_bind_template_child (widget_class,
+ EphyActionBarEnd,
+ browser_actions_popup_view_label);
+
+ gtk_widget_class_bind_template_callback (widget_class,
+ browser_actions_popup_view_back_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class,
+ browser_actions_row_activated_cb);
}
static void
@@ -263,6 +384,7 @@ ephy_action_bar_end_init (EphyActionBarEnd *action_bar_end)
GObject *object = G_OBJECT (action_bar_end);
EphyDownloadsManager *downloads_manager;
GtkWidget *popover;
+ EphyWebExtensionManager *extension_manager;
gtk_widget_init_template (GTK_WIDGET (action_bar_end));
@@ -307,6 +429,17 @@ ephy_action_bar_end_init (EphyActionBarEnd *action_bar_end)
popover = ephy_add_bookmark_popover_new ();
gtk_menu_button_set_popover (GTK_MENU_BUTTON (action_bar_end->bookmark_button), popover);
+
+ extension_manager = ephy_web_extension_manager_get_default ();
+ g_signal_connect_object (extension_manager, "show-browser-action",
+ G_CALLBACK (show_browser_action_cb),
+ object, 0);
+
+ set_browser_actions (action_bar_end, ephy_web_extension_manager_get_browser_actions (extension_manager));
+
+ g_signal_connect (action_bar_end->browser_actions_popover, "notify::visible",
+ G_CALLBACK (browser_action_popover_visible_changed_cb),
+ action_bar_end);
}
EphyActionBarEnd *
@@ -349,13 +482,6 @@ ephy_action_bar_end_get_downloads_revealer (EphyActionBarEnd *action_bar_end)
return action_bar_end->downloads_revealer;
}
-void
-ephy_action_bar_end_add_browser_action (EphyActionBarEnd *action_bar_end,
- GtkWidget *action)
-{
- gtk_container_add (GTK_CONTAINER (action_bar_end->browser_action_box), action);
-}
-
void
ephy_action_bar_end_set_show_bookmark_button (EphyActionBarEnd *action_bar_end,
gboolean show)
@@ -390,3 +516,41 @@ ephy_action_bar_end_set_bookmark_icon_state (EphyActionBarEnd *action_bar_e
g_assert_not_reached ();
}
}
+
+GtkWidget *
+create_browser_action_item_widget (EphyBrowserAction *action,
+ gpointer user_data)
+{
+ return ephy_browser_action_row_new (action);
+}
+
+static void
+browser_actions_items_changed_cb (GListModel *list,
+ guint position,
+ guint removed,
+ guint added,
+ EphyActionBarEnd *action_bar_end)
+{
+ gtk_widget_set_visible (action_bar_end->browser_actions_button, g_list_model_get_n_items (list) != 0);
+
+ /* This handles an edge-case where if an extension is disabled while its popover is open the webview
should be destroyed.
+ * However in normal usage this shouldn't happen and with the GTK4 port the extension dialog is also modal.
+ * So we just always manually close it instead of trying to track which extension popup is open. */
+ if (removed)
+ gtk_popover_popdown (GTK_POPOVER (action_bar_end->browser_actions_popover));
+}
+
+static void
+set_browser_actions (EphyActionBarEnd *action_bar_end,
+ GListStore *browser_actions)
+{
+ gtk_list_box_bind_model (GTK_LIST_BOX (action_bar_end->browser_actions_listbox),
+ G_LIST_MODEL (browser_actions),
+ (GtkListBoxCreateWidgetFunc)create_browser_action_item_widget,
+ NULL, NULL);
+
+ g_signal_connect_object (browser_actions, "items-changed", G_CALLBACK (browser_actions_items_changed_cb),
+ action_bar_end, 0);
+
+ browser_actions_items_changed_cb (G_LIST_MODEL (browser_actions), 0, 0, 0, action_bar_end);
+}
diff --git a/src/ephy-action-bar-end.h b/src/ephy-action-bar-end.h
index ffecf9596..3872aed46 100644
--- a/src/ephy-action-bar-end.h
+++ b/src/ephy-action-bar-end.h
@@ -38,13 +38,12 @@ void ephy_action_bar_end_show_downloads (EphyActionBarEn
void ephy_action_bar_end_show_bookmarks (EphyActionBarEnd *action_bar_end);
GtkWidget *ephy_action_bar_end_get_downloads_revealer (EphyActionBarEnd *action_bar_end);
-void ephy_action_bar_end_add_browser_action (EphyActionBarEnd *action_bar_end,
- GtkWidget *action);
+void ephy_action_bar_end_set_browser_actions (EphyActionBarEnd *action_bar_end,
+ GListStore *browser_actions);
void ephy_action_bar_end_set_show_bookmark_button (EphyActionBarEnd *action_bar_end,
gboolean show);
void ephy_action_bar_end_set_bookmark_icon_state (EphyActionBarEnd *action_bar_end,
EphyBookmarkIconState state);
-
G_END_DECLS
diff --git a/src/ephy-header-bar.c b/src/ephy-header-bar.c
index d6132ba8b..8a08d3fa1 100644
--- a/src/ephy-header-bar.c
+++ b/src/ephy-header-bar.c
@@ -468,10 +468,3 @@ ephy_header_bar_set_zoom_level (EphyHeaderBar *header_bar,
gtk_label_set_label (GTK_LABEL (header_bar->zoom_level_label), zoom_level);
}
-
-void
-ephy_header_bar_add_browser_action (EphyHeaderBar *header_bar,
- GtkWidget *action)
-{
- ephy_action_bar_end_add_browser_action (header_bar->action_bar_end, action);
-}
diff --git a/src/ephy-header-bar.h b/src/ephy-header-bar.h
index f066de16d..56fde0d3d 100644
--- a/src/ephy-header-bar.h
+++ b/src/ephy-header-bar.h
@@ -49,7 +49,4 @@ void ephy_header_bar_start_change_combined_stop_reload_state (Eph
void ephy_header_bar_set_zoom_level (EphyHeaderBar *header_bar,
gdouble zoom);
-void ephy_header_bar_add_browser_action (EphyHeaderBar *header_bar,
- GtkWidget *action);
-
G_END_DECLS
diff --git a/src/resources/epiphany.gresource.xml b/src/resources/epiphany.gresource.xml
index d962bccd1..d9491d6cf 100644
--- a/src/resources/epiphany.gresource.xml
+++ b/src/resources/epiphany.gresource.xml
@@ -8,6 +8,7 @@
<file preprocess="xml-stripblanks" compressed="true">gtk/bookmark-properties.ui</file>
<file preprocess="xml-stripblanks" compressed="true">gtk/bookmark-row.ui</file>
<file preprocess="xml-stripblanks" compressed="true">gtk/bookmarks-popover.ui</file>
+ <file preprocess="xml-stripblanks" compressed="true">gtk/browser-action-row.ui</file>
<file preprocess="xml-stripblanks" compressed="true">gtk/clear-data-view.ui</file>
<file preprocess="xml-stripblanks" compressed="true">gtk/data-view.ui</file>
<file preprocess="xml-stripblanks" compressed="true">gtk/encoding-dialog.ui</file>
diff --git a/src/resources/gtk/action-bar-end.ui b/src/resources/gtk/action-bar-end.ui
index fc86d7b69..a2401ef7e 100644
--- a/src/resources/gtk/action-bar-end.ui
+++ b/src/resources/gtk/action-bar-end.ui
@@ -2,12 +2,6 @@
<interface>
<template class="EphyActionBarEnd" parent="GtkBox">
<property name="spacing">6</property>
- <child>
- <object class="GtkBox" id="browser_action_box">
- <property name="visible">True</property>
- <property name="spacing">6</property>
- </object>
- </child>
<child>
<object class="GtkRevealer" id="downloads_revealer">
<property name="visible">True</property>
@@ -49,6 +43,21 @@
</child>
</object>
</child>
+ <child>
+ <object class="GtkMenuButton" id="browser_actions_button">
+ <!-- Translators: tooltip for the webextension actions button -->
+ <property name="tooltip_text" translatable="yes">View extension actions</property>
+ <property name="visible">False</property>
+ <property name="receives_default">True</property>
+ <property name="popover">browser_actions_popover</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="icon-name">application-x-addon-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
<child>
<object class="GtkMenuButton" id="bookmark_button">
<property name="visible">True</property>
@@ -88,4 +97,75 @@
<object class="EphyBookmarksPopover" id="bookmarks_popover">
<property name="visible">True</property>
</object>
+ <object class="GtkPopover" id="browser_actions_popover">
+ <property name="width-request">250</property>
+ <child>
+ <object class="GtkStack" id="browser_actions_stack">
+ <property name="visible">True</property>
+ <property name="transition-type">slide-left-right</property>
+ <property name="interpolate-size">True</property>
+ <property name="margin-start">6</property>
+ <property name="margin-end">6</property>
+ <property name="margin-top">6</property>
+ <property name="margin-bottom">6</property>
+ <child>
+ <object class="GtkScrolledWindow" id="browser_actions_scrolled_window">
+ <property name="visible">True</property>
+ <property name="hscrollbar-policy">never</property>
+ <property name="max-content-height">360</property>
+ <property name="propagate-natural-height">True</property>
+ <child>
+ <object class="GtkListBox" id="browser_actions_listbox">
+ <property name="visible">True</property>
+ <property name="selection-mode">none</property>
+ <signal name="row-activated" handler="browser_actions_row_activated_cb"/>
+ <style>
+ <class name="browser-actions-listbox"/>\
+ <class name="background"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="browser_actions_popup_view_box">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="orientation">horizontal</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkButton">
+ <property name="visible">True</property>
+ <signal name="clicked" handler="browser_actions_popup_view_back_clicked_cb"/>
+ <style>
+ <class name="flat"/>
+ </style>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="icon-name">go-previous-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="browser_actions_popup_view_label">
+ <property name="visible">True</property>
+ <property name="hexpand">True</property>
+ <style>
+ <class name="heading"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
</interface>
diff --git a/src/resources/gtk/browser-action-row.ui b/src/resources/gtk/browser-action-row.ui
new file mode 100644
index 000000000..0ba4b0d01
--- /dev/null
+++ b/src/resources/gtk/browser-action-row.ui
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.18"/>
+ <template class="EphyBrowserActionRow" parent="GtkListBoxRow">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <property name="margin-start">6</property>
+ <property name="margin-end">6</property>
+ <property name="margin-top">6</property>
+ <property name="margin-bottom">6</property>
+ <child>
+ <object class="GtkImage" id="browser_action_image">
+ <property name="visible">True</property>
+ <property name="pixel-size">16</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="title_label">
+ <property name="visible">True</property>
+ <property name="hexpand">True</property>
+ <property name="ellipsize">end</property>
+ <property name="max_width_chars">40</property>
+ <property name="xalign">0</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/src/resources/themes/_shared-base.scss b/src/resources/themes/_shared-base.scss
index d1628d4e1..7c0a6bc71 100644
--- a/src/resources/themes/_shared-base.scss
+++ b/src/resources/themes/_shared-base.scss
@@ -253,3 +253,7 @@ fullscreenbox > flap {
background: linear-gradient(to bottom, gtkalpha(black, .1), gtkalpha(black, .0));
}
}
+
+.browser-actions-listbox {
+ padding: 6px;
+}
\ No newline at end of file
diff --git a/src/webextension/api/commands.c b/src/webextension/api/commands.c
index 31e3c4a2e..8f4c3218b 100644
--- a/src/webextension/api/commands.c
+++ b/src/webextension/api/commands.c
@@ -33,12 +33,11 @@ on_command_activated (GAction *action,
EphyWebExtensionManager *manager = ephy_web_extension_manager_get_default ();
EphyShell *shell = ephy_shell_get_default ();
EphyWebView *view = EPHY_WEB_VIEW (ephy_shell_get_active_web_view (shell));
- EphyWindow *window = EPHY_WINDOW (gtk_application_get_active_window (GTK_APPLICATION (shell)));
GtkWidget *button;
const char *command_name = g_object_get_data (G_OBJECT (action), "command-name-json");
if (strcmp (command_name, "\"_execute_browser_action\"") == 0) {
- ephy_web_extension_manager_activate_browser_action (manager, self, window);
+ ephy_web_extension_manager_show_browser_action (manager, self);
return;
} else if (strcmp (command_name, "\"_execute_page_action\"") == 0) {
button = ephy_web_extension_manager_get_page_action (manager, self, view);
diff --git a/src/webextension/api/menus.c b/src/webextension/api/menus.c
index 674f39a75..1cc6f0cfb 100644
--- a/src/webextension/api/menus.c
+++ b/src/webextension/api/menus.c
@@ -558,10 +558,8 @@ menu_activate_browser_action (gpointer user_data)
{
EphyWebExtension *web_extension = user_data;
EphyWebExtensionManager *manager = ephy_web_extension_manager_get_default ();
- EphyShell *shell = ephy_shell_get_default ();
- EphyWindow *window = EPHY_WINDOW (gtk_application_get_active_window (GTK_APPLICATION (shell)));
- ephy_web_extension_manager_activate_browser_action (manager, web_extension, window);
+ ephy_web_extension_manager_show_browser_action (manager, web_extension);
return G_SOURCE_REMOVE;
}
diff --git a/src/webextension/ephy-browser-action-row.c b/src/webextension/ephy-browser-action-row.c
new file mode 100644
index 000000000..164645902
--- /dev/null
+++ b/src/webextension/ephy-browser-action-row.c
@@ -0,0 +1,147 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2016 Iulian-Gabriel Radu <iulian radu67 gmail com>
+ * Copyright 2022 Igalia S.L.
+ *
+ * This file is part of Epiphany.
+ *
+ * Epiphany is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Epiphany is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Epiphany. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "ephy-browser-action-row.h"
+
+struct _EphyBrowserActionRow {
+ GtkListBoxRow parent_instance;
+
+ EphyBrowserAction *browser_action;
+
+ GtkWidget *browser_action_image;
+ GtkWidget *title_label;
+};
+
+G_DEFINE_FINAL_TYPE (EphyBrowserActionRow, ephy_browser_action_row, GTK_TYPE_LIST_BOX_ROW)
+
+enum {
+ PROP_0,
+ PROP_BROWSER_ACTION,
+ LAST_PROP
+};
+
+static GParamSpec *obj_properties[LAST_PROP];
+
+static void
+ephy_browser_action_row_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EphyBrowserActionRow *self = EPHY_BROWSER_ACTION_ROW (object);
+
+ switch (prop_id) {
+ case PROP_BROWSER_ACTION:
+ self->browser_action = g_value_dup_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ephy_browser_action_row_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EphyBrowserActionRow *self = EPHY_BROWSER_ACTION_ROW (object);
+
+ switch (prop_id) {
+ case PROP_BROWSER_ACTION:
+ g_value_set_object (value, ephy_browser_action_row_get_browser_action (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ephy_browser_action_row_constructed (GObject *object)
+{
+ EphyBrowserActionRow *self = EPHY_BROWSER_ACTION_ROW (object);
+
+ gtk_label_set_label (GTK_LABEL (self->title_label),
+ ephy_browser_action_get_title (self->browser_action));
+ gtk_image_set_from_pixbuf (GTK_IMAGE (self->browser_action_image),
+ ephy_browser_action_get_pixbuf (self->browser_action, 16));
+
+ G_OBJECT_CLASS (ephy_browser_action_row_parent_class)->constructed (object);
+}
+
+static void
+ephy_browser_action_row_dispose (GObject *object)
+{
+ EphyBrowserActionRow *self = EPHY_BROWSER_ACTION_ROW (object);
+
+ g_clear_object (&self->browser_action);
+
+ G_OBJECT_CLASS (ephy_browser_action_row_parent_class)->dispose (object);
+}
+
+static void
+ephy_browser_action_row_class_init (EphyBrowserActionRowClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->set_property = ephy_browser_action_row_set_property;
+ object_class->get_property = ephy_browser_action_row_get_property;
+ object_class->dispose = ephy_browser_action_row_dispose;
+ object_class->constructed = ephy_browser_action_row_constructed;
+
+ obj_properties[PROP_BROWSER_ACTION] =
+ g_param_spec_object ("browser-action",
+ "",
+ "",
+ EPHY_TYPE_BROWSER_ACTION,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, LAST_PROP, obj_properties);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/epiphany/gtk/browser-action-row.ui");
+ gtk_widget_class_bind_template_child (widget_class, EphyBrowserActionRow, browser_action_image);
+ gtk_widget_class_bind_template_child (widget_class, EphyBrowserActionRow, title_label);
+}
+
+static void
+ephy_browser_action_row_init (EphyBrowserActionRow *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+GtkWidget *
+ephy_browser_action_row_new (EphyBrowserAction *browser_action)
+{
+ return g_object_new (EPHY_TYPE_BROWSER_ACTION_ROW,
+ "browser-action", browser_action,
+ NULL);
+}
+
+EphyBrowserAction *
+ephy_browser_action_row_get_browser_action (EphyBrowserActionRow *self)
+{
+ g_assert (EPHY_IS_BROWSER_ACTION_ROW (self));
+
+ return self->browser_action;
+}
diff --git a/src/webextension/ephy-browser-action-row.h b/src/webextension/ephy-browser-action-row.h
new file mode 100644
index 000000000..b309940be
--- /dev/null
+++ b/src/webextension/ephy-browser-action-row.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright 2022 Igalia S.L.
+ *
+ * This file is part of Epiphany.
+ *
+ * Epiphany is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Epiphany is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Epiphany. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "ephy-browser-action.h"
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_BROWSER_ACTION_ROW (ephy_browser_action_row_get_type ())
+
+G_DECLARE_FINAL_TYPE (EphyBrowserActionRow, ephy_browser_action_row, EPHY, BROWSER_ACTION_ROW, GtkListBoxRow)
+
+GtkWidget *ephy_browser_action_row_new (EphyBrowserAction *browser_action);
+
+EphyBrowserAction *ephy_browser_action_row_get_browser_action (EphyBrowserActionRow *self);
+
+G_END_DECLS
diff --git a/src/webextension/ephy-browser-action.c b/src/webextension/ephy-browser-action.c
new file mode 100644
index 000000000..e55b3e670
--- /dev/null
+++ b/src/webextension/ephy-browser-action.c
@@ -0,0 +1,150 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2022 Igalia S.L.
+ *
+ * This file is part of Epiphany.
+ *
+ * Epiphany is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Epiphany is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Epiphany. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "ephy-browser-action.h"
+#include "ephy-web-extension-manager.h"
+
+struct _EphyBrowserAction {
+ GObject parent_instance;
+ EphyWebExtension *web_extension;
+};
+
+G_DEFINE_FINAL_TYPE (EphyBrowserAction, ephy_browser_action, G_TYPE_OBJECT)
+
+enum {
+ PROP_0,
+ PROP_WEB_EXTENSION,
+ N_PROPS
+};
+
+static GParamSpec *properties[N_PROPS];
+
+EphyBrowserAction *
+ephy_browser_action_new (EphyWebExtension *web_extension)
+{
+ return g_object_new (EPHY_TYPE_BROWSER_ACTION,
+ "web-extension", web_extension,
+ NULL);
+}
+
+const char *
+ephy_browser_action_get_title (EphyBrowserAction *self)
+{
+ const char *short_name = ephy_web_extension_get_short_name (self->web_extension);
+
+ return short_name && *short_name ? short_name : ephy_web_extension_get_name (self->web_extension);
+}
+
+GdkPixbuf *
+ephy_browser_action_get_pixbuf (EphyBrowserAction *self,
+ gint64 size)
+{
+ return ephy_web_extension_get_icon (self->web_extension, size);
+}
+
+EphyWebExtension *
+ephy_browser_action_get_web_extension (EphyBrowserAction *self)
+{
+ return self->web_extension;
+}
+
+gboolean
+ephy_browser_action_activate (EphyBrowserAction *self)
+{
+ EphyWebExtensionManager *manager = ephy_web_extension_manager_get_default ();
+
+ /* If it has no popup clicking just emits this event and is handled already. */
+ if (ephy_web_extension_get_browser_popup (self->web_extension) == NULL) {
+ ephy_web_extension_manager_emit_in_background_view (manager, self->web_extension,
"browserAction.onClicked", "");
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+ephy_browser_action_finalize (GObject *object)
+{
+ EphyBrowserAction *self = (EphyBrowserAction *)object;
+
+ g_clear_object (&self->web_extension);
+
+ G_OBJECT_CLASS (ephy_browser_action_parent_class)->finalize (object);
+}
+
+static void
+ephy_browser_action_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EphyBrowserAction *self = EPHY_BROWSER_ACTION (object);
+
+ switch (prop_id) {
+ case PROP_WEB_EXTENSION:
+ g_value_set_object (value, self->web_extension);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ephy_browser_action_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EphyBrowserAction *self = EPHY_BROWSER_ACTION (object);
+
+ switch (prop_id) {
+ case PROP_WEB_EXTENSION:
+ g_set_object (&self->web_extension, g_value_dup_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ephy_browser_action_class_init (EphyBrowserActionClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = ephy_browser_action_finalize;
+ object_class->get_property = ephy_browser_action_get_property;
+ object_class->set_property = ephy_browser_action_set_property;
+
+ properties[PROP_WEB_EXTENSION] =
+ g_param_spec_object ("web-extension",
+ "",
+ "",
+ EPHY_TYPE_WEB_EXTENSION,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+ephy_browser_action_init (EphyBrowserAction *self)
+{
+}
diff --git a/src/webextension/ephy-browser-action.h b/src/webextension/ephy-browser-action.h
new file mode 100644
index 000000000..96d2fbd27
--- /dev/null
+++ b/src/webextension/ephy-browser-action.h
@@ -0,0 +1,39 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2022 Igalia S.L.
+ *
+ * This file is part of Epiphany.
+ *
+ * Epiphany is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Epiphany is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Epiphany. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gio/gio.h>
+
+#include "ephy-web-extension.h"
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_BROWSER_ACTION (ephy_browser_action_get_type())
+
+G_DECLARE_FINAL_TYPE (EphyBrowserAction, ephy_browser_action, EPHY, BROWSER_ACTION, GObject)
+
+EphyBrowserAction *ephy_browser_action_new (EphyWebExtension *web_extension);
+const char *ephy_browser_action_get_title (EphyBrowserAction *self);
+GdkPixbuf *ephy_browser_action_get_pixbuf (EphyBrowserAction *self, gint64 size);
+EphyWebExtension *ephy_browser_action_get_web_extension (EphyBrowserAction *self);
+gboolean ephy_browser_action_activate (EphyBrowserAction *self);
+
+G_END_DECLS
diff --git a/src/webextension/ephy-web-extension-manager.c b/src/webextension/ephy-web-extension-manager.c
index 2cb6b9340..2adaab326 100644
--- a/src/webextension/ephy-web-extension-manager.c
+++ b/src/webextension/ephy-web-extension-manager.c
@@ -20,6 +20,7 @@
#include "config.h"
+#include "ephy-browser-action.h"
#include "ephy-debug.h"
#include "ephy-embed-shell.h"
#include "ephy-embed-prefs.h"
@@ -58,7 +59,9 @@ struct _EphyWebExtensionManager {
GCancellable *cancellable;
GPtrArray *web_extensions;
GHashTable *page_action_map;
+
GHashTable *browser_action_map;
+ GListStore *browser_actions;
GHashTable *user_agent_overrides;
@@ -87,6 +90,7 @@ EphyWebExtensionApiHandler api_handlers[] = {
enum {
CHANGED,
+ SHOW_BROWSER_ACTION,
LAST_SIGNAL
};
@@ -206,12 +210,6 @@ ephy_web_extension_manager_scan_directory_async (EphyWebExtensionManager *self,
self);
}
-static void
-destroy_widget_list (GSList *widget_list)
-{
- g_slist_free_full (widget_list, (GDestroyNotify)gtk_widget_destroy);
-}
-
static void
ephy_webextension_scheme_cb (WebKitURISchemeRequest *request,
gpointer user_data)
@@ -269,7 +267,8 @@ ephy_web_extension_manager_constructed (GObject *object)
self->background_web_views = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
(GDestroyNotify)gtk_widget_destroy);
self->popup_web_views = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
(GDestroyNotify)g_ptr_array_free);
self->page_action_map = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_hash_table_destroy);
- self->browser_action_map = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)destroy_widget_list);
+ self->browser_action_map = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_object_unref);
+ self->browser_actions = g_list_store_new (EPHY_TYPE_BROWSER_ACTION);
self->pending_messages = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
(GDestroyNotify)g_hash_table_destroy);
self->web_extensions = g_ptr_array_new_full (0, g_object_unref);
self->user_agent_overrides = create_user_agent_overrides ();
@@ -284,8 +283,12 @@ ephy_web_extension_manager_dispose (GObject *object)
ephy_web_extension_api_downloads_dispose (self);
+ g_list_store_remove_all (self->browser_actions);
+
g_clear_pointer (&self->background_web_views, g_hash_table_destroy);
g_clear_pointer (&self->popup_web_views, g_hash_table_destroy);
+ g_clear_object (&self->browser_actions);
+ g_clear_pointer (&self->browser_action_map, g_hash_table_destroy);
g_clear_pointer (&self->page_action_map, g_hash_table_destroy);
g_clear_pointer (&self->pending_messages, g_hash_table_destroy);
g_clear_pointer (&self->web_extensions, g_ptr_array_unref);
@@ -306,6 +309,14 @@ ephy_web_extension_manager_class_init (EphyWebExtensionManagerClass *klass)
G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
0, NULL, NULL, NULL,
G_TYPE_NONE, 0);
+
+ signals[SHOW_BROWSER_ACTION] =
+ g_signal_new ("show-browser-action",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 1, EPHY_TYPE_BROWSER_ACTION);
}
static void
@@ -1066,17 +1077,20 @@ ephy_web_extension_manager_register_popup_view (EphyWebExtensionManager *manager
g_signal_connect (web_view, "destroy", G_CALLBACK (on_popup_view_destroyed), web_extension);
}
-static GtkWidget *
-create_browser_popup (EphyWebExtension *web_extension)
+GtkWidget *
+ephy_web_extension_manager_create_browser_popup (EphyWebExtensionManager *self,
+ EphyWebExtension *web_extension)
{
- EphyWebExtensionManager *manager = ephy_web_extension_manager_get_default ();
GtkWidget *web_view;
g_autofree char *popup_uri = NULL;
const char *popup;
web_view = ephy_web_extensions_manager_create_web_extensions_webview (web_extension);
+ gtk_widget_set_hexpand (web_view, TRUE);
+ gtk_widget_set_vexpand (web_view, TRUE);
gtk_widget_hide (web_view); /* Shown in on_popup_load_changed. */
- ephy_web_extension_manager_register_popup_view (manager, web_extension, web_view);
+
+ ephy_web_extension_manager_register_popup_view (self, web_extension, web_view);
popup = ephy_web_extension_get_browser_popup (web_extension);
popup_uri = g_strdup_printf ("ephy-webextension://%s/%s", ephy_web_extension_get_guid (web_extension),
popup);
@@ -1086,75 +1100,6 @@ create_browser_popup (EphyWebExtension *web_extension)
return web_view;
}
-static gboolean
-on_browser_action_clicked (GtkWidget *event_box,
- gpointer user_data)
-{
- EphyWebExtension *web_extension = EPHY_WEB_EXTENSION (user_data);
- EphyWebExtensionManager *self = ephy_web_extension_manager_get_default ();
- g_autofree char *script = NULL;
- WebKitWebView *web_view = ephy_web_extension_manager_get_background_web_view (self, web_extension);
-
- script = g_strdup_printf ("window.browser.browserAction.onClicked._emit();");
-
- webkit_web_view_run_javascript (web_view,
- script,
- NULL,
- NULL,
- NULL);
-
- return GDK_EVENT_STOP;
-}
-
-static void
-on_browser_action_visible_changed (GtkWidget *popover,
- GParamSpec *pspec,
- gpointer user_data)
-{
- EphyWebExtension *web_extension = EPHY_WEB_EXTENSION (user_data);
- GtkWidget *child;
-
- if (gtk_widget_get_visible (popover)) {
- child = create_browser_popup (web_extension);
- gtk_container_add (GTK_CONTAINER (popover), child);
- } else {
- child = gtk_bin_get_child (GTK_BIN (popover));
- gtk_container_remove (GTK_CONTAINER (popover), child);
- }
-}
-
-GtkWidget *
-create_browser_action (EphyWebExtension *web_extension,
- EphyWindow *window)
-{
- GtkWidget *button;
- GtkWidget *image;
- GtkWidget *popover;
- GdkPixbuf *pixbuf;
-
- pixbuf = ephy_web_extension_browser_action_get_icon (web_extension, 16);
- if (pixbuf)
- image = gtk_image_new_from_pixbuf (pixbuf);
- else
- image = gtk_image_new_from_icon_name ("application-x-addon-symbolic", GTK_ICON_SIZE_BUTTON);
-
- if (ephy_web_extension_get_browser_popup (web_extension)) {
- button = gtk_menu_button_new ();
- popover = gtk_popover_new (NULL);
- g_signal_connect (popover, "notify::visible", G_CALLBACK (on_browser_action_visible_changed),
web_extension);
- gtk_menu_button_set_popover (GTK_MENU_BUTTON (button), popover);
- gtk_button_set_image (GTK_BUTTON (button), image);
- } else {
- button = gtk_button_new ();
- g_signal_connect_object (button, "clicked", G_CALLBACK (on_browser_action_clicked), web_extension, 0);
- gtk_button_set_image (GTK_BUTTON (button), image);
- }
-
- gtk_widget_set_visible (button, TRUE);
-
- return button;
-}
-
void
ephy_web_extension_manager_add_web_extension_to_window (EphyWebExtensionManager *self,
EphyWebExtension *web_extension,
@@ -1174,16 +1119,6 @@ ephy_web_extension_manager_add_web_extension_to_window (EphyWebExtensionManager
ephy_web_extension_manager_add_web_extension_to_webview (self, web_extension, window, web_view);
}
- if (ephy_web_extension_has_browser_action (web_extension)) {
- GtkWidget *browser_action_widget = create_browser_action (web_extension, window);
- GSList *widget_list = g_hash_table_lookup (self->browser_action_map, web_extension);
-
- ephy_header_bar_add_browser_action (EPHY_HEADER_BAR (ephy_window_get_header_bar (window)),
browser_action_widget);
-
- g_hash_table_steal (self->browser_action_map, web_extension); /* Avoid freeing list. */
- g_hash_table_insert (self->browser_action_map, web_extension, g_slist_append (widget_list,
browser_action_widget));
- }
-
ephy_web_extension_manager_update_location_entry (self, window);
g_signal_connect_object (view, "page-attached", G_CALLBACK (page_attached_cb), web_extension, 0);
}
@@ -1356,6 +1291,23 @@ application_window_removed_cb (EphyShell *shell,
ephy_web_extension_manager_emit_in_extension_views (manager, web_extension, "windows.onRemoved",
window_json);
}
+static void
+remove_browser_action (EphyWebExtensionManager *self,
+ EphyWebExtension *web_extension)
+{
+ EphyBrowserAction *action;
+ guint position;
+
+ action = g_hash_table_lookup (self->browser_action_map, web_extension);
+ if (!action)
+ return;
+
+ g_assert (g_list_store_find (self->browser_actions, action, &position));
+ g_list_store_remove (self->browser_actions, position);
+
+ g_hash_table_remove (self->browser_action_map, web_extension);
+}
+
void
ephy_web_extension_manager_set_active (EphyWebExtensionManager *self,
EphyWebExtension *web_extension,
@@ -1401,42 +1353,33 @@ ephy_web_extension_manager_set_active (EphyWebExtensionManager *self,
if (ephy_web_extension_has_background_web_view (web_extension))
run_background_script (self, web_extension);
+ if (ephy_web_extension_has_browser_action (web_extension)) {
+ EphyBrowserAction *action = ephy_browser_action_new (web_extension);
+ g_list_store_append (self->browser_actions, action);
+ g_hash_table_insert (self->browser_action_map, web_extension, g_steal_pointer (&action));
+ }
+
ephy_web_extension_api_commands_init (web_extension);
} else {
g_signal_handlers_disconnect_by_data (shell, web_extension);
- g_hash_table_remove (self->browser_action_map, web_extension);
+ remove_browser_action (self, web_extension);
g_hash_table_remove (self->background_web_views, web_extension);
g_object_set_data (G_OBJECT (web_extension), "alarms", NULL); /* Set in alarms.c */
ephy_web_extension_api_commands_dispose (web_extension);
}
}
-gint
-get_browser_action_for_window (GtkWidget *widget,
- GtkWidget *window)
-{
- return gtk_widget_get_toplevel (widget) != window;
-}
-
-
void
-ephy_web_extension_manager_activate_browser_action (EphyWebExtensionManager *self,
- EphyWebExtension *web_extension,
- EphyWindow *window)
+ephy_web_extension_manager_show_browser_action (EphyWebExtensionManager *self,
+ EphyWebExtension *web_extension)
{
- GSList *table, *l;
- GtkWidget *button;
+ EphyBrowserAction *action = EPHY_BROWSER_ACTION (g_hash_table_lookup (self->browser_action_map,
web_extension));
- table = g_hash_table_lookup (self->browser_action_map, web_extension);
- if (table) {
- l = g_slist_find_custom (table, window, (GCompareFunc)get_browser_action_for_window);
-
- g_assert (l && l->data);
+ if (!action || ephy_browser_action_activate (action))
+ return;
- button = l->data;
- gtk_widget_mnemonic_activate (button, FALSE);
- }
+ g_signal_emit (self, signals[SHOW_BROWSER_ACTION], 0, action);
}
GtkWidget *
@@ -1454,6 +1397,12 @@ ephy_web_extension_manager_get_page_action (EphyWebExtensionManager *self,
return ret;
}
+GListStore *
+ephy_web_extension_manager_get_browser_actions (EphyWebExtensionManager *self)
+{
+ return self->browser_actions;
+}
+
void
ephy_web_extension_manager_handle_notifications_action (EphyWebExtensionManager *self,
GVariant *params)
@@ -1653,6 +1602,24 @@ on_extension_emit_ready (GObject *source,
g_warning ("Emitting in view errored: %s", error->message);
}
+void
+ephy_web_extension_manager_emit_in_background_view (EphyWebExtensionManager *self,
+ EphyWebExtension *web_extension,
+ const char *name,
+ const char *json)
+{
+ g_autofree char *script = NULL;
+ WebKitWebView *web_view = ephy_web_extension_manager_get_background_web_view (self, web_extension);
+
+ script = g_strdup_printf ("window.browser.%s._emit(%s);", name, json);
+
+ webkit_web_view_run_javascript (web_view,
+ script,
+ NULL,
+ NULL,
+ NULL);
+}
+
static void
ephy_web_extension_manager_emit_in_extension_views_internal (EphyWebExtensionManager *self,
EphyWebExtension *web_extension,
diff --git a/src/webextension/ephy-web-extension-manager.h b/src/webextension/ephy-web-extension-manager.h
index 13f68b22d..89901bd75 100644
--- a/src/webextension/ephy-web-extension-manager.h
+++ b/src/webextension/ephy-web-extension-manager.h
@@ -64,17 +64,19 @@ void ephy_web_extension_manager_set_active
EphyWebExtension
*web_extension,
gboolean
active);
-void ephy_web_extension_manager_activate_browser_action (EphyWebExtensionManager
*self,
- EphyWebExtension
*web_extension,
- EphyWindow
*window);
+void ephy_web_extension_manager_show_browser_action (EphyWebExtensionManager
*self,
+ EphyWebExtension
*web_extension);
GtkWidget *ephy_web_extension_manager_get_page_action (EphyWebExtensionManager
*self,
EphyWebExtension
*web_extension,
EphyWebView
*web_view);
+GListStore *ephy_web_extension_manager_get_browser_actions (EphyWebExtensionManager
*self);
+
WebKitWebView *ephy_web_extension_manager_get_background_web_view (EphyWebExtensionManager
*self,
EphyWebExtension
*web_extension);
-
+GtkWidget *ephy_web_extension_manager_create_browser_popup (EphyWebExtensionManager
*self,
+ EphyWebExtension
*web_extension);
void ephy_web_extension_manager_handle_notifications_action (EphyWebExtensionManager
*self,
GVariant
*params);
@@ -101,6 +103,10 @@ void ephy_web_extension_manager_emit_in_tab_with_reply
WebKitWebView
*target_web_view,
const char
*sender_json,
GTask
*reply_task);
+void ephy_web_extension_manager_emit_in_background_view (EphyWebExtensionManager
*self,
+ EphyWebExtension
*web_extension,
+ const char
*name,
+ const char
*json);
GtkWidget *ephy_web_extensions_manager_create_web_extensions_webview (EphyWebExtension
*web_extension);
diff --git a/src/webextension/meson.build b/src/webextension/meson.build
index c4ad72c50..32a76c5af 100644
--- a/src/webextension/meson.build
+++ b/src/webextension/meson.build
@@ -10,6 +10,8 @@ ephywebextension_src = [
'webextension/api/storage.c',
'webextension/api/tabs.c',
'webextension/api/windows.c',
+ 'webextension/ephy-browser-action.c',
+ 'webextension/ephy-browser-action-row.c',
'webextension/ephy-json-utils.c',
'webextension/ephy-web-extension-manager.c',
'webextension/ephy-web-extension.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]