summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharlie Turner <cturner@igalia.com>2020-06-29 15:33:39 +0100
committerCharlie Turner <cturner@igalia.com>2020-06-29 16:59:46 +0100
commitd048aafb8be90b5e8a9622aa5c2c42bd8a76d7b2 (patch)
tree696b1eaea0ac404d2b77d06cfa3123ed4de9a2e5
parentf87996ef2cf973a091424bd72897ec0826760ff8 (diff)
downloadepiphany-d048aafb8be90b5e8a9622aa5c2c42bd8a76d7b2.tar.gz
Allow per-site autoplay policies.
Denying autoplay can break websites that use it for stylistic effects. On the other hand, it can be increadibly annoying to be spammed with videos autoplaying. By default, videos can autoplay so long as they have no audio (or the audio is muted). Alternatively, users can allow all videos to autoplay even with audio, or to deny all attempts to autoplay video. Users can make these decisions using the security pop-over on a per security-origin basis.
-rw-r--r--data/org.gnome.epiphany.gschema.xml5
-rw-r--r--embed/ephy-web-view.c66
-rw-r--r--lib/ephy-permissions-manager.c2
-rw-r--r--lib/ephy-permissions-manager.h1
-rw-r--r--lib/widgets/ephy-security-popover.c36
5 files changed, 94 insertions, 16 deletions
diff --git a/data/org.gnome.epiphany.gschema.xml b/data/org.gnome.epiphany.gschema.xml
index aff5400ca..f5e0c256f 100644
--- a/data/org.gnome.epiphany.gschema.xml
+++ b/data/org.gnome.epiphany.gschema.xml
@@ -429,5 +429,10 @@
<summary>Decision to apply when advertisement permission is requested for this host</summary>
<description>This option is used to save whether a given host has been given permission to allow advertisements. The “undecided” default means the browser global setting is used, while “allow” and “deny” tell it to automatically make the decision upon request.</description>
</key>
+ <key name="autoplay-permission" enum="org.gnome.Epiphany.Permission">
+ <default>'undecided'</default>
+ <summary>Decision to apply when an autoplay policy is requested for this host</summary>
+ <description>This option is used to save whether a given host has been given permission to autoplay. The “undecided” default means to allow autoplay of muted media, while “allow” and “deny” tell it to allow / deny all requests to autoplay media respectively.</description>
+ </key>
</schema>
</schemalist>
diff --git a/embed/ephy-web-view.c b/embed/ephy-web-view.c
index e0b4eebe7..a0bf84d7d 100644
--- a/embed/ephy-web-view.c
+++ b/embed/ephy-web-view.c
@@ -812,10 +812,46 @@ process_terminated_cb (EphyWebView *web_view,
}
static gboolean
-decide_policy_cb (WebKitWebView *web_view,
- WebKitPolicyDecision *decision,
- WebKitPolicyDecisionType decision_type,
- gpointer user_data)
+decide_navigation (WebKitWebView *web_view,
+ WebKitPolicyDecision *decision,
+ gpointer user_data)
+{
+ EphyEmbedShell *shell = ephy_embed_shell_get_default ();
+ WebKitWebsitePolicies *website_policies = NULL;
+ g_autofree gchar *origin = NULL;
+ WebKitNavigationPolicyDecision *navigation_policy_decision = WEBKIT_NAVIGATION_POLICY_DECISION (decision);
+ WebKitNavigationAction *navigation_action = webkit_navigation_policy_decision_get_navigation_action (navigation_policy_decision);
+ WebKitURIRequest *request = webkit_navigation_action_get_request (navigation_action);
+ const gchar *navigation_uri = webkit_uri_request_get_uri (request);
+ EphyPermission permission = EPHY_PERMISSION_UNDECIDED;
+
+ origin = ephy_uri_to_security_origin (navigation_uri);
+ if (origin)
+ permission = ephy_permissions_manager_get_permission (ephy_embed_shell_get_permissions_manager (shell),
+ EPHY_PERMISSION_TYPE_AUTOPLAY_POLICY,
+ origin);
+
+ switch (permission) {
+ case EPHY_PERMISSION_UNDECIDED:
+ website_policies = webkit_website_policies_new_with_policies ("autoplay", WEBKIT_AUTOPLAY_ALLOW_WITHOUT_SOUND, NULL);
+ break;
+ case EPHY_PERMISSION_PERMIT:
+ website_policies = webkit_website_policies_new_with_policies ("autoplay", WEBKIT_AUTOPLAY_ALLOW, NULL);
+ break;
+ case EPHY_PERMISSION_DENY:
+ website_policies = webkit_website_policies_new_with_policies ("autoplay", WEBKIT_AUTOPLAY_DENY, NULL);
+ break;
+ }
+
+ webkit_policy_decision_use_with_policies (decision, website_policies);
+ g_object_unref (website_policies);
+ return TRUE;
+}
+
+static gboolean
+decide_resource (WebKitWebView *web_view,
+ WebKitPolicyDecision *decision,
+ gpointer user_data)
{
WebKitResponsePolicyDecision *response_decision;
WebKitURIResponse *response;
@@ -826,9 +862,6 @@ decide_policy_cb (WebKitWebView *web_view,
const char *request_uri;
gboolean is_main_resource;
- if (decision_type != WEBKIT_POLICY_DECISION_TYPE_RESPONSE)
- return FALSE;
-
/* If WebKit can handle the MIME type, let it.
* Otherwise, we'll start a download.
*/
@@ -881,6 +914,25 @@ decide_policy_cb (WebKitWebView *web_view,
return TRUE;
}
+static gboolean
+decide_policy_cb (WebKitWebView *web_view,
+ WebKitPolicyDecision *decision,
+ WebKitPolicyDecisionType decision_type,
+ gpointer user_data)
+{
+ switch (decision_type) {
+ case WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION:
+ return decide_navigation (web_view, decision, user_data);
+ case WEBKIT_POLICY_DECISION_TYPE_RESPONSE:
+ return decide_resource (web_view, decision, user_data);
+ case WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION:
+ /* not handled */
+ break;
+ }
+
+ return TRUE;
+}
+
typedef struct {
EphyWebView *web_view;
WebKitPermissionRequest *request;
diff --git a/lib/ephy-permissions-manager.c b/lib/ephy-permissions-manager.c
index 45395c5ff..4079c759e 100644
--- a/lib/ephy-permissions-manager.c
+++ b/lib/ephy-permissions-manager.c
@@ -167,6 +167,8 @@ permission_type_to_string (EphyPermissionType type)
return "video-device-permission";
case EPHY_PERMISSION_TYPE_SHOW_ADS:
return "advertisement-permission";
+ case EPHY_PERMISSION_TYPE_AUTOPLAY_POLICY:
+ return "autoplay-permission";
default:
g_assert_not_reached ();
}
diff --git a/lib/ephy-permissions-manager.h b/lib/ephy-permissions-manager.h
index caba693cc..aab47c17c 100644
--- a/lib/ephy-permissions-manager.h
+++ b/lib/ephy-permissions-manager.h
@@ -43,6 +43,7 @@ typedef enum {
EPHY_PERMISSION_TYPE_ACCESS_MICROPHONE,
EPHY_PERMISSION_TYPE_ACCESS_WEBCAM,
EPHY_PERMISSION_TYPE_SHOW_ADS,
+ EPHY_PERMISSION_TYPE_AUTOPLAY_POLICY,
} EphyPermissionType;
EphyPermissionsManager *ephy_permissions_manager_new (void);
diff --git a/lib/widgets/ephy-security-popover.c b/lib/widgets/ephy-security-popover.c
index 7f32102ff..68a8be9c5 100644
--- a/lib/widgets/ephy-security-popover.c
+++ b/lib/widgets/ephy-security-popover.c
@@ -65,6 +65,7 @@ struct _EphySecurityPopover {
GtkWidget *access_location_combobox;
GtkWidget *access_microphone_combobox;
GtkWidget *access_webcam_combobox;
+ GtkWidget *autoplay_combobox;
GtkWidget *grid;
GTlsCertificate *certificate;
GTlsCertificateFlags tls_errors;
@@ -155,6 +156,7 @@ ephy_security_popover_set_address (EphySecurityPopover *popover,
set_permission_combobox_state (permissions_manager, EPHY_PERMISSION_TYPE_ACCESS_LOCATION, origin, popover->access_location_combobox);
set_permission_combobox_state (permissions_manager, EPHY_PERMISSION_TYPE_ACCESS_MICROPHONE, origin, popover->access_microphone_combobox);
set_permission_combobox_state (permissions_manager, EPHY_PERMISSION_TYPE_ACCESS_WEBCAM, origin, popover->access_webcam_combobox);
+ set_permission_combobox_state (permissions_manager, EPHY_PERMISSION_TYPE_AUTOPLAY_POLICY, origin, popover->autoplay_combobox);
}
static void
@@ -482,11 +484,20 @@ on_access_webcam_combobox_changed (GtkComboBox *box,
handle_permission_combobox_changed (popover, gtk_combo_box_get_active (box), EPHY_PERMISSION_TYPE_ACCESS_WEBCAM);
}
+static void
+on_autoplay_policy_combobox_changed (GtkComboBox *box,
+ EphySecurityPopover *popover)
+{
+ handle_permission_combobox_changed (popover, gtk_combo_box_get_active (box), EPHY_PERMISSION_TYPE_AUTOPLAY_POLICY);
+}
+
static GtkWidget *
add_permission_combobox (EphySecurityPopover *popover,
const gchar *name,
gpointer callback,
- gboolean no_ask)
+ GtkSizeGroup *size_group,
+ gboolean no_ask,
+ const gchar *third_option_name)
{
GtkWidget *widget;
GtkWidget *hbox;
@@ -503,11 +514,14 @@ add_permission_combobox (EphySecurityPopover *popover,
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), _("Allow"));
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), _("Deny"));
- if (!no_ask)
- gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), _("Ask"));
+ if (!no_ask) {
+ const gchar *name = third_option_name == NULL ? _("Ask") : third_option_name;
+ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), _(name));
+ }
gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 6);
g_signal_connect (widget, "changed", G_CALLBACK (callback), popover);
+ gtk_size_group_add_widget (size_group, widget);
return widget;
}
@@ -517,6 +531,7 @@ ephy_security_popover_init (EphySecurityPopover *popover)
{
GtkWidget *permissions;
GtkWidget *box;
+ g_autoptr (GtkSizeGroup) combo_box_size_group = NULL;
g_autofree char *label = g_strdup_printf ("<b>%s</b>", _("Permissions"));
popover->grid = gtk_grid_new ();
@@ -553,12 +568,15 @@ ephy_security_popover_init (EphySecurityPopover *popover)
gtk_grid_attach (GTK_GRID (popover->grid), permissions, 0, 4, 2, 1);
popover->permission_pos = 5;
- popover->ad_combobox = add_permission_combobox (popover, _("Advertisements"), on_ad_combobox_changed, TRUE);
- popover->notification_combobox = add_permission_combobox (popover, _("Notifications"), on_notification_combobox_changed, FALSE);
- popover->save_password_combobox = add_permission_combobox (popover, _("Password saving"), on_save_password_combobox_changed, FALSE);
- popover->access_location_combobox = add_permission_combobox (popover, _("Location access"), on_access_location_combobox_changed, FALSE);
- popover->access_microphone_combobox = add_permission_combobox (popover, _("Microphone access"), on_access_microphone_combobox_changed, FALSE);
- popover->access_webcam_combobox = add_permission_combobox (popover, _("Webcam access"), on_access_webcam_combobox_changed, FALSE);
+ combo_box_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
+ popover->ad_combobox = add_permission_combobox (popover, _("Advertisements"), on_ad_combobox_changed, combo_box_size_group, TRUE, NULL);
+ popover->notification_combobox = add_permission_combobox (popover, _("Notifications"), on_notification_combobox_changed, combo_box_size_group, FALSE, NULL);
+ popover->save_password_combobox = add_permission_combobox (popover, _("Password saving"), on_save_password_combobox_changed, combo_box_size_group, FALSE, NULL);
+ popover->access_location_combobox = add_permission_combobox (popover, _("Location access"), on_access_location_combobox_changed, combo_box_size_group, FALSE, NULL);
+ popover->access_microphone_combobox = add_permission_combobox (popover, _("Microphone access"), on_access_microphone_combobox_changed, combo_box_size_group, FALSE, NULL);
+ popover->access_webcam_combobox = add_permission_combobox (popover, _("Webcam access"), on_access_webcam_combobox_changed, combo_box_size_group, FALSE, NULL);
+ popover->autoplay_combobox = add_permission_combobox (popover, _("Media autoplay"), on_autoplay_policy_combobox_changed, combo_box_size_group, FALSE, "Without Sound");
gtk_container_add (GTK_CONTAINER (popover), popover->grid);
gtk_widget_show_all (popover->grid);