/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* Copyright © 2000-2003 Marco Pesenti Gritti
* Copyright © 2011 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 .
*/
#include
#include "ephy-embed-shell.h"
#include "ephy-about-handler.h"
#include "ephy-debug.h"
#include "ephy-downloads-manager.h"
#include "ephy-embed-container.h"
#include "ephy-embed-prefs.h"
#include "ephy-embed-type-builtins.h"
#include "ephy-embed-utils.h"
#include "ephy-encodings.h"
#include "ephy-file-helpers.h"
#include "ephy-filters-manager.h"
#include "ephy-flatpak-utils.h"
#include "ephy-history-service.h"
#include "ephy-password-manager.h"
#include "ephy-pdf-handler.h"
#include "ephy-profile-utils.h"
#include "ephy-reader-handler.h"
#include "ephy-settings.h"
#include "ephy-snapshot-service.h"
#include "ephy-tabs-catalog.h"
#include "ephy-uri-helpers.h"
#include "ephy-view-source-handler.h"
#include "ephy-web-app-utils.h"
#include
#include
#include
#define PAGE_SETUP_FILENAME "page-setup-gtk.ini"
#define PRINT_SETTINGS_FILENAME "print-settings.ini"
typedef struct {
WebKitWebContext *web_context;
EphyHistoryService *global_history_service;
EphyGSBService *global_gsb_service;
EphyEncodings *encodings;
GtkPageSetup *page_setup;
GtkPrintSettings *print_settings;
EphyEmbedShellMode mode;
EphyDownloadsManager *downloads_manager;
EphyPermissionsManager *permissions_manager;
EphyPasswordManager *password_manager;
EphyAboutHandler *about_handler;
EphyViewSourceHandler *source_handler;
EphyReaderHandler *reader_handler;
EphyPDFHandler *pdf_handler;
char *guid;
EphyFiltersManager *filters_manager;
EphySearchEngineManager *search_engine_manager;
GCancellable *cancellable;
} EphyEmbedShellPrivate;
enum {
RESTORED_WINDOW,
WEB_VIEW_CREATED,
ALLOW_TLS_CERTIFICATE,
ALLOW_UNSAFE_BROWSING,
PASSWORD_FORM_FOCUSED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
enum {
PROP_0,
PROP_MODE,
N_PROPERTIES
};
static GParamSpec *object_properties[N_PROPERTIES] = { NULL, };
static EphyEmbedShell *embed_shell = NULL;
static void ephy_embed_shell_tabs_catalog_iface_init (EphyTabsCatalogInterface *iface);
G_DEFINE_TYPE_WITH_CODE (EphyEmbedShell, ephy_embed_shell, DZL_TYPE_APPLICATION,
G_ADD_PRIVATE (EphyEmbedShell)
G_IMPLEMENT_INTERFACE (EPHY_TYPE_TABS_CATALOG,
ephy_embed_shell_tabs_catalog_iface_init))
static EphyWebView *
ephy_embed_shell_get_view_for_page_id (EphyEmbedShell *self,
guint64 page_id,
const char *origin)
{
GList *windows = gtk_application_get_windows (GTK_APPLICATION (self));
for (GList *l = windows; l && l->data; l = l->next) {
g_autoptr (GList) tabs = ephy_embed_container_get_children (l->data);
for (GList *t = tabs; t && t->data; t = t->next) {
EphyWebView *ephy_view = ephy_embed_get_web_view (t->data);
WebKitWebView *web_view = WEBKIT_WEB_VIEW (ephy_view);
g_autofree char *real_origin = NULL;
if (webkit_web_view_get_page_id (web_view) != page_id)
continue;
real_origin = ephy_uri_to_security_origin (webkit_web_view_get_uri (web_view));
if (g_strcmp0 (real_origin, origin)) {
g_debug ("Extension's origin '%s' doesn't match real origin '%s'", origin, real_origin);
return NULL;
}
return ephy_view;
}
}
return NULL;
}
static GList *
tabs_catalog_get_tabs_info (EphyTabsCatalog *catalog)
{
WebKitFaviconDatabase *database;
GList *windows;
g_autoptr (GList) tabs = NULL;
GList *tabs_info = NULL;
const char *title;
const char *url;
g_autofree char *favicon = NULL;
g_assert ((gpointer)catalog == (gpointer)embed_shell);
windows = gtk_application_get_windows (GTK_APPLICATION (embed_shell));
database = webkit_web_context_get_favicon_database (ephy_embed_shell_get_web_context (embed_shell));
for (GList *l = windows; l && l->data; l = l->next) {
tabs = ephy_embed_container_get_children (l->data);
for (GList *t = tabs; t && t->data; t = t->next) {
title = ephy_embed_get_title (t->data);
if (!g_strcmp0 (title, _(BLANK_PAGE_TITLE)) || !g_strcmp0 (title, _(OVERVIEW_PAGE_TITLE)))
continue;
url = ephy_web_view_get_display_address (ephy_embed_get_web_view (t->data));
favicon = webkit_favicon_database_get_favicon_uri (database, url);
tabs_info = g_list_prepend (tabs_info,
ephy_tab_info_new (title, url, favicon));
}
}
return tabs_info;
}
static void
ephy_embed_shell_tabs_catalog_iface_init (EphyTabsCatalogInterface *iface)
{
iface->get_tabs_info = tabs_catalog_get_tabs_info;
}
static void
ephy_embed_shell_dispose (GObject *object)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (EPHY_EMBED_SHELL (object));
if (priv->cancellable) {
g_cancellable_cancel (priv->cancellable);
g_clear_object (&priv->cancellable);
}
g_clear_object (&priv->encodings);
g_clear_object (&priv->page_setup);
g_clear_object (&priv->print_settings);
g_clear_object (&priv->global_history_service);
g_clear_object (&priv->global_gsb_service);
g_clear_object (&priv->about_handler);
g_clear_object (&priv->reader_handler);
g_clear_object (&priv->source_handler);
g_clear_object (&priv->pdf_handler);
g_clear_object (&priv->downloads_manager);
g_clear_object (&priv->password_manager);
g_clear_object (&priv->permissions_manager);
g_clear_object (&priv->web_context);
g_clear_pointer (&priv->guid, g_free);
g_clear_object (&priv->filters_manager);
g_clear_object (&priv->search_engine_manager);
G_OBJECT_CLASS (ephy_embed_shell_parent_class)->dispose (object);
}
static void
web_process_extension_password_form_focused_message_received_cb (WebKitUserContentManager *manager,
WebKitJavascriptResult *message,
EphyEmbedShell *shell)
{
guint64 page_id;
gboolean insecure_form_action;
g_autoptr (GVariant) variant = NULL;
g_autofree char *message_str = NULL;
message_str = jsc_value_to_string (webkit_javascript_result_get_js_value (message));
variant = g_variant_parse (G_VARIANT_TYPE ("(tb)"), message_str, NULL, NULL, NULL);
g_variant_get (variant, "(tb)", &page_id, &insecure_form_action);
g_signal_emit (shell, signals[PASSWORD_FORM_FOCUSED], 0,
page_id, insecure_form_action);
}
static void
history_service_query_urls_cb (EphyHistoryService *service,
gboolean success,
GList *urls,
EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
GList *l;
GVariantBuilder builder;
if (!success)
return;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ss)"));
for (l = urls; l; l = g_list_next (l)) {
EphyHistoryURL *url = (EphyHistoryURL *)l->data;
g_variant_builder_add (&builder, "(ss)", url->url, url->title);
ephy_embed_shell_schedule_thumbnail_update (shell, (EphyHistoryURL *)l->data);
}
webkit_web_context_send_message_to_all_extensions (priv->web_context,
webkit_user_message_new ("History.SetURLs",
g_variant_builder_end (&builder)));
}
static void
ephy_embed_shell_update_overview_urls (EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
g_autoptr (EphyHistoryQuery) query = NULL;
query = ephy_history_query_new_for_overview ();
ephy_history_service_query_urls (priv->global_history_service, query, NULL,
(EphyHistoryJobCallback)history_service_query_urls_cb,
shell);
}
static void
history_service_urls_visited_cb (EphyHistoryService *history,
EphyEmbedShell *shell)
{
ephy_embed_shell_update_overview_urls (shell);
}
static void
history_set_url_hidden_cb (EphyHistoryService *service,
gboolean success,
gpointer result_data,
EphyEmbedShell *shell)
{
if (!success)
return;
ephy_embed_shell_update_overview_urls (shell);
}
static void
web_process_extension_overview_message_received_cb (WebKitUserContentManager *manager,
WebKitJavascriptResult *message,
EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
g_autofree char *url_to_remove = NULL;
url_to_remove = jsc_value_to_string (webkit_javascript_result_get_js_value (message));
ephy_history_service_set_url_hidden (priv->global_history_service,
url_to_remove, TRUE, NULL,
(EphyHistoryJobCallback)history_set_url_hidden_cb,
shell);
}
static void
web_process_extension_tls_error_page_message_received_cb (WebKitUserContentManager *manager,
WebKitJavascriptResult *message,
EphyEmbedShell *shell)
{
guint64 page_id;
page_id = jsc_value_to_double (webkit_javascript_result_get_js_value (message));
g_signal_emit (shell, signals[ALLOW_TLS_CERTIFICATE], 0, page_id);
}
static void
web_process_extension_unsafe_browsing_error_page_message_received_cb (WebKitUserContentManager *manager,
WebKitJavascriptResult *message,
EphyEmbedShell *shell)
{
guint64 page_id;
page_id = jsc_value_to_double (webkit_javascript_result_get_js_value (message));
g_signal_emit (shell, signals[ALLOW_UNSAFE_BROWSING], 0, page_id);
}
static void
web_process_extension_about_apps_message_received_cb (WebKitUserContentManager *manager,
WebKitJavascriptResult *message,
EphyEmbedShell *shell)
{
g_autofree char *app_id = NULL;
app_id = jsc_value_to_string (webkit_javascript_result_get_js_value (message));
ephy_web_application_delete (app_id);
}
static char *
property_to_string_or_null (JSCValue *value,
const char *name)
{
g_autoptr (JSCValue) prop = jsc_value_object_get_property (value, name);
if (jsc_value_is_null (prop) || jsc_value_is_undefined (prop))
return NULL;
return jsc_value_to_string (prop);
}
static int
property_to_uint64 (JSCValue *value,
const char *name)
{
g_autoptr (JSCValue) prop = jsc_value_object_get_property (value, name);
return (guint64)jsc_value_to_double (prop);
}
typedef struct {
EphyPasswordManager *password_manager;
EphyPermissionsManager *permissions_manager;
char *origin;
char *target_origin;
char *username;
char *password;
char *username_field;
char *password_field;
gboolean is_new;
} SaveAuthRequest;
static void
save_auth_request_free (SaveAuthRequest *request)
{
g_object_unref (request->password_manager);
g_object_unref (request->permissions_manager);
g_free (request->origin);
g_free (request->target_origin);
g_free (request->username);
g_free (request->password);
g_free (request->username_field);
g_free (request->password_field);
g_free (request);
}
static void
save_auth_request_response_cb (gint response_id,
SaveAuthRequest *data)
{
if (response_id == GTK_RESPONSE_REJECT) {
ephy_permissions_manager_set_permission (data->permissions_manager,
EPHY_PERMISSION_TYPE_SAVE_PASSWORD,
data->origin,
EPHY_PERMISSION_DENY);
} else if (response_id == GTK_RESPONSE_YES) {
ephy_password_manager_save (data->password_manager, data->origin, data->target_origin,
data->username, data->password, data->username_field,
data->password_field, data->is_new);
}
}
static void
web_process_extension_password_manager_save_real (EphyEmbedShell *shell,
JSCValue *value,
gboolean is_request)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
g_autofree char *origin = property_to_string_or_null (value, "origin");
g_autofree char *target_origin = property_to_string_or_null (value, "targetOrigin");
g_autofree char *username = property_to_string_or_null (value, "username");
g_autofree char *password = property_to_string_or_null (value, "password");
g_autofree char *username_field = property_to_string_or_null (value, "usernameField");
g_autofree char *password_field = property_to_string_or_null (value, "passwordField");
g_autoptr (JSCValue) is_new_prop = jsc_value_object_get_property (value, "isNew");
gboolean is_new = jsc_value_to_boolean (is_new_prop);
guint64 page_id = property_to_uint64 (value, "pageID");
EphyWebView *view;
SaveAuthRequest *request;
/* Both origin and target origin are required. */
if (!origin || !target_origin)
return;
/* Both password and password field are required. */
if (!password || !password_field)
return;
/* The username field is required if username is present. */
if (username && !username_field)
g_clear_pointer (&username, g_free);
/* The username is required if username field is present. */
if (!username && username_field)
g_clear_pointer (&username_field, g_free);
/* This also sanity checks that a page isn't saving websites for
* other origins. Remember the request comes from the untrusted web
* process and we have to make sure it's not being evil here. This
* could also happen even without malice if the origin of a subframe
* doesn't match the origin of the main frame (in which case we'll
* refuse to save the password).
*/
view = ephy_embed_shell_get_view_for_page_id (shell, page_id, origin);
if (!view)
return;
if (!is_request) {
ephy_password_manager_save (priv->password_manager, origin, target_origin, username,
password, username_field, password_field, is_new);
return;
}
request = g_new (SaveAuthRequest, 1);
request->password_manager = g_object_ref (priv->password_manager);
request->permissions_manager = g_object_ref (priv->permissions_manager);
request->origin = g_steal_pointer (&origin);
request->target_origin = g_steal_pointer (&target_origin);
request->username = g_steal_pointer (&username);
request->password = g_steal_pointer (&password);
request->username_field = g_steal_pointer (&username_field);
request->password_field = g_steal_pointer (&password_field);
request->is_new = is_new;
ephy_web_view_show_auth_form_save_request (view, request->origin, request->username,
(EphyPasswordSaveRequestCallback)save_auth_request_response_cb,
request, (GDestroyNotify)save_auth_request_free);
}
static void
web_process_extension_password_manager_save_received_cb (WebKitUserContentManager *manager,
WebKitJavascriptResult *message,
EphyEmbedShell *shell)
{
JSCValue *value = webkit_javascript_result_get_js_value (message);
web_process_extension_password_manager_save_real (shell, value, FALSE);
}
static void
web_process_extension_password_manager_request_save_received_cb (WebKitUserContentManager *manager,
WebKitJavascriptResult *message,
EphyEmbedShell *shell)
{
JSCValue *value = webkit_javascript_result_get_js_value (message);
web_process_extension_password_manager_save_real (shell, value, TRUE);
}
static void
history_service_url_title_changed_cb (EphyHistoryService *service,
const char *url,
const char *title,
EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
webkit_web_context_send_message_to_all_extensions (priv->web_context,
webkit_user_message_new ("History.SetURLTitle",
g_variant_new ("(ss)", url, title)));
}
static void
history_service_url_deleted_cb (EphyHistoryService *service,
EphyHistoryURL *url,
EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
webkit_web_context_send_message_to_all_extensions (priv->web_context,
webkit_user_message_new ("History.DeleteURL",
g_variant_new ("s", url->url)));
}
static void
history_service_host_deleted_cb (EphyHistoryService *service,
const char *deleted_url,
EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
g_autoptr (SoupURI) deleted_uri = NULL;
deleted_uri = soup_uri_new (deleted_url);
webkit_web_context_send_message_to_all_extensions (priv->web_context,
webkit_user_message_new ("History.DeleteHost",
g_variant_new ("s", soup_uri_get_host (deleted_uri))));
}
static void
history_service_cleared_cb (EphyHistoryService *service,
EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
webkit_web_context_send_message_to_all_extensions (priv->web_context,
webkit_user_message_new ("History.Clear",
NULL));
}
void
ephy_embed_shell_set_thumbnail_path (EphyEmbedShell *shell,
const char *url,
const char *path)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
webkit_web_context_send_message_to_all_extensions (priv->web_context,
webkit_user_message_new ("History.SetURLThumbnail",
g_variant_new ("(ss)", url, path)));
}
static void
got_snapshot_path_for_url_cb (EphySnapshotService *service,
GAsyncResult *result,
char *url)
{
g_autofree char *snapshot = NULL;
g_autoptr (GError) error = NULL;
snapshot = ephy_snapshot_service_get_snapshot_path_for_url_finish (service, result, &error);
if (snapshot) {
ephy_embed_shell_set_thumbnail_path (ephy_embed_shell_get_default (), url, snapshot);
} else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
/* Bad luck, not something to warn about. */
g_info ("Failed to get snapshot for URL %s: %s", url, error->message);
}
g_free (url);
}
void
ephy_embed_shell_schedule_thumbnail_update (EphyEmbedShell *shell,
EphyHistoryURL *url)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
EphySnapshotService *service;
const char *snapshot;
service = ephy_snapshot_service_get_default ();
snapshot = ephy_snapshot_service_lookup_cached_snapshot_path (service, url->url);
if (snapshot) {
ephy_embed_shell_set_thumbnail_path (shell, url->url, snapshot);
} else {
ephy_snapshot_service_get_snapshot_path_for_url_async (service,
url->url,
priv->cancellable,
(GAsyncReadyCallback)got_snapshot_path_for_url_cb,
g_strdup (url->url));
}
}
/**
* ephy_embed_shell_get_global_history_service:
* @shell: the #EphyEmbedShell
*
* Return value: (transfer none): the global #EphyHistoryService
**/
EphyHistoryService *
ephy_embed_shell_get_global_history_service (EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
g_assert (EPHY_IS_EMBED_SHELL (shell));
if (!priv->global_history_service) {
g_autofree char *filename = NULL;
EphySQLiteConnectionMode mode;
if (priv->mode == EPHY_EMBED_SHELL_MODE_INCOGNITO ||
priv->mode == EPHY_EMBED_SHELL_MODE_AUTOMATION ||
priv->mode == EPHY_EMBED_SHELL_MODE_SEARCH_PROVIDER)
mode = EPHY_SQLITE_CONNECTION_MODE_MEMORY;
else
mode = EPHY_SQLITE_CONNECTION_MODE_READWRITE;
filename = g_build_filename (ephy_profile_dir (), EPHY_HISTORY_FILE, NULL);
priv->global_history_service = ephy_history_service_new (filename, mode);
g_signal_connect_object (priv->global_history_service, "urls-visited",
G_CALLBACK (history_service_urls_visited_cb),
shell, 0);
g_signal_connect_object (priv->global_history_service, "url-title-changed",
G_CALLBACK (history_service_url_title_changed_cb),
shell, 0);
g_signal_connect_object (priv->global_history_service, "url-deleted",
G_CALLBACK (history_service_url_deleted_cb),
shell, 0);
g_signal_connect_object (priv->global_history_service, "host-deleted",
G_CALLBACK (history_service_host_deleted_cb),
shell, 0);
g_signal_connect_object (priv->global_history_service, "cleared",
G_CALLBACK (history_service_cleared_cb),
shell, 0);
}
return priv->global_history_service;
}
/**
* ephy_embed_shell_get_global_gsb_service:
* @shell: the #EphyEmbedShell
*
* Return value: (transfer none): the global #EphyGSBService
**/
EphyGSBService *
ephy_embed_shell_get_global_gsb_service (EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
g_assert (EPHY_IS_EMBED_SHELL (shell));
if (!priv->global_gsb_service) {
g_autofree char *db_path = NULL;
db_path = g_build_filename (ephy_default_cache_dir (), EPHY_GSB_FILE, NULL);
priv->global_gsb_service = ephy_gsb_service_new (GSB_API_KEY, db_path);
}
return priv->global_gsb_service;
}
/**
* ephy_embed_shell_get_encodings:
* @shell: the #EphyEmbedShell
*
* Return value: (transfer none):
**/
EphyEncodings *
ephy_embed_shell_get_encodings (EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
g_assert (EPHY_IS_EMBED_SHELL (shell));
if (!priv->encodings)
priv->encodings = ephy_encodings_new ();
return priv->encodings;
}
void
ephy_embed_shell_restored_window (EphyEmbedShell *shell)
{
g_signal_emit (shell, signals[RESTORED_WINDOW], 0);
}
static void
about_request_cb (WebKitURISchemeRequest *request,
EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
ephy_about_handler_handle_request (priv->about_handler, request);
}
static void
source_request_cb (WebKitURISchemeRequest *request,
EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
ephy_view_source_handler_handle_request (priv->source_handler, request);
}
static void
reader_request_cb (WebKitURISchemeRequest *request,
EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
ephy_reader_handler_handle_request (priv->reader_handler, request);
}
static void
pdf_request_cb (WebKitURISchemeRequest *request,
EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
ephy_pdf_handler_handle_request (priv->pdf_handler, request);
}
static void
ephy_resource_request_cb (WebKitURISchemeRequest *request)
{
const char *path;
gsize size;
g_autoptr (GInputStream) stream = NULL;
g_autoptr (GError) error = NULL;
path = webkit_uri_scheme_request_get_path (request);
if (!g_resources_get_info (path, 0, &size, NULL, &error)) {
webkit_uri_scheme_request_finish_error (request, error);
return;
}
stream = g_resources_open_stream (path, 0, &error);
if (stream)
webkit_uri_scheme_request_finish (request, stream, size, NULL);
else
webkit_uri_scheme_request_finish_error (request, error);
}
static void
initialize_web_process_extensions (WebKitWebContext *web_context,
EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
g_autoptr (GVariant) user_data = NULL;
gboolean private_profile;
#if DEVELOPER_MODE
webkit_web_context_set_web_extensions_directory (web_context, BUILD_ROOT "/embed/web-process-extension");
#else
webkit_web_context_set_web_extensions_directory (web_context, EPHY_WEB_PROCESS_EXTENSIONS_DIR);
#endif
private_profile = priv->mode == EPHY_EMBED_SHELL_MODE_PRIVATE || priv->mode == EPHY_EMBED_SHELL_MODE_INCOGNITO || priv->mode == EPHY_EMBED_SHELL_MODE_AUTOMATION;
user_data = g_variant_new ("(smsbb)",
priv->guid,
ephy_profile_dir_is_default () ? NULL : ephy_profile_dir (),
g_settings_get_boolean (EPHY_SETTINGS_WEB, EPHY_PREFS_WEB_REMEMBER_PASSWORDS),
private_profile);
webkit_web_context_set_web_extensions_initialization_user_data (web_context, g_steal_pointer (&user_data));
}
static void
initialize_notification_permissions (WebKitWebContext *web_context,
EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
GList *permitted_origins;
GList *denied_origins;
permitted_origins = ephy_permissions_manager_get_permitted_origins (priv->permissions_manager,
EPHY_PERMISSION_TYPE_SHOW_NOTIFICATIONS);
denied_origins = ephy_permissions_manager_get_denied_origins (priv->permissions_manager,
EPHY_PERMISSION_TYPE_SHOW_NOTIFICATIONS);
webkit_web_context_initialize_notification_permissions (web_context, permitted_origins, denied_origins);
}
static void
ephy_embed_shell_create_web_context (EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
g_autoptr (WebKitWebsiteDataManager) manager = NULL;
if (priv->mode == EPHY_EMBED_SHELL_MODE_INCOGNITO || priv->mode == EPHY_EMBED_SHELL_MODE_AUTOMATION) {
manager = webkit_website_data_manager_new_ephemeral ();
} else {
manager = webkit_website_data_manager_new ("base-data-directory", ephy_profile_dir (),
"base-cache-directory", ephy_cache_dir (),
NULL);
webkit_website_data_manager_set_persistent_credential_storage_enabled (manager, FALSE);
}
webkit_website_data_manager_set_itp_enabled (manager,
g_settings_get_boolean (EPHY_SETTINGS_WEB,
EPHY_PREFS_WEB_ENABLE_ITP));
priv->web_context = g_object_new (WEBKIT_TYPE_WEB_CONTEXT,
"website-data-manager", manager,
"process-swap-on-cross-site-navigation-enabled", TRUE,
NULL);
if (priv->mode == EPHY_EMBED_SHELL_MODE_AUTOMATION)
webkit_web_context_set_automation_allowed (priv->web_context, TRUE);
}
static void
download_started_cb (WebKitWebContext *web_context,
WebKitDownload *download,
EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
g_autoptr (EphyDownload) ephy_download = NULL;
gboolean ephy_download_set;
WebKitWebView *web_view;
/* Is download locked down? */
if (g_settings_get_boolean (EPHY_SETTINGS_LOCKDOWN,
EPHY_PREFS_LOCKDOWN_SAVE_TO_DISK)) {
webkit_download_cancel (download);
return;
}
/* Only create an EphyDownload for the WebKitDownload if it doesn't exist yet.
* This can happen when the download has been started automatically by WebKit,
* due to a context menu action or policy checker decision. Downloads started
* explicitly by Epiphany are marked with ephy-download-set GObject data.
*/
ephy_download_set = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (download), "ephy-download-set"));
if (ephy_download_set)
return;
ephy_download = ephy_download_new (download);
web_view = webkit_download_get_web_view (download);
if (EPHY_IS_WEB_VIEW (web_view)) {
if (ephy_web_view_get_document_type (EPHY_WEB_VIEW (web_view)) != EPHY_WEB_VIEW_DOCUMENT_PDF)
ephy_downloads_manager_add_download (priv->downloads_manager, ephy_download);
} else {
ephy_downloads_manager_add_download (priv->downloads_manager, ephy_download);
}
}
static void
remember_passwords_setting_changed_cb (GSettings *settings,
char *key,
EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
gboolean should_remember_passwords;
should_remember_passwords = g_settings_get_boolean (EPHY_SETTINGS_WEB, EPHY_PREFS_WEB_REMEMBER_PASSWORDS);
webkit_web_context_send_message_to_all_extensions (priv->web_context,
webkit_user_message_new ("PasswordManager.SetShouldRememberPasswords",
g_variant_new ("b", should_remember_passwords)));
}
static void
enable_itp_setting_changed_cb (GSettings *settings,
char *key,
EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
WebKitWebsiteDataManager *manager;
manager = webkit_web_context_get_website_data_manager (priv->web_context);
webkit_website_data_manager_set_itp_enabled (manager,
g_settings_get_boolean (EPHY_SETTINGS_WEB,
EPHY_PREFS_WEB_ENABLE_ITP));
}
static void
ephy_embed_shell_startup (GApplication *application)
{
EphyEmbedShell *shell = EPHY_EMBED_SHELL (application);
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
g_autofree char *favicon_db_path = NULL;
WebKitCookieManager *cookie_manager;
g_autofree char *filename = NULL;
G_APPLICATION_CLASS (ephy_embed_shell_parent_class)->startup (application);
webkit_web_context_set_process_model (priv->web_context, WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES);
webkit_web_context_set_sandbox_enabled (priv->web_context, TRUE);
webkit_web_context_add_path_to_sandbox (priv->web_context, ephy_profile_dir (), TRUE);
webkit_web_context_add_path_to_sandbox (priv->web_context, ephy_cache_dir (), TRUE);
webkit_web_context_add_path_to_sandbox (priv->web_context, ephy_config_dir (), TRUE);
#if DEVELOPER_MODE
webkit_web_context_add_path_to_sandbox (priv->web_context, BUILD_ROOT, TRUE);
#endif
g_signal_connect_object (priv->web_context, "initialize-web-extensions",
G_CALLBACK (initialize_web_process_extensions),
shell, 0);
g_signal_connect_object (priv->web_context, "initialize-notification-permissions",
G_CALLBACK (initialize_notification_permissions),
shell, 0);
priv->password_manager = ephy_password_manager_new ();
/* Do not cache favicons in automation mode. Don't change the TLS policy either, since that's
* handled by session capabilities in automation mode.
*/
if (priv->mode != EPHY_EMBED_SHELL_MODE_AUTOMATION) {
/* Favicon Database */
favicon_db_path = g_build_filename (ephy_cache_dir (), "icondatabase", NULL);
webkit_web_context_set_favicon_database_directory (priv->web_context, favicon_db_path);
}
/* about: URIs handler */
priv->about_handler = ephy_about_handler_new ();
webkit_web_context_register_uri_scheme (priv->web_context,
EPHY_ABOUT_SCHEME,
(WebKitURISchemeRequestCallback)about_request_cb,
shell, NULL);
/* Register about scheme as local so that it can contain file resources */
webkit_security_manager_register_uri_scheme_as_local (webkit_web_context_get_security_manager (priv->web_context),
EPHY_ABOUT_SCHEME);
/* view source handler */
priv->source_handler = ephy_view_source_handler_new ();
webkit_web_context_register_uri_scheme (priv->web_context, EPHY_VIEW_SOURCE_SCHEME,
(WebKitURISchemeRequestCallback)source_request_cb,
shell, NULL);
/* pdf handler */
priv->pdf_handler = ephy_pdf_handler_new ();
webkit_web_context_register_uri_scheme (priv->web_context, EPHY_PDF_SCHEME,
(WebKitURISchemeRequestCallback)pdf_request_cb,
shell, NULL);
/* reader mode handler */
priv->reader_handler = ephy_reader_handler_new ();
webkit_web_context_register_uri_scheme (priv->web_context, EPHY_READER_SCHEME,
(WebKitURISchemeRequestCallback)reader_request_cb,
shell, NULL);
/* ephy-resource handler */
webkit_web_context_register_uri_scheme (priv->web_context, "ephy-resource",
(WebKitURISchemeRequestCallback)ephy_resource_request_cb,
NULL, NULL);
webkit_security_manager_register_uri_scheme_as_secure (webkit_web_context_get_security_manager (priv->web_context),
"ephy-resource");
/* Store cookies in moz-compatible SQLite format */
cookie_manager = webkit_web_context_get_cookie_manager (priv->web_context);
if (!webkit_web_context_is_ephemeral (priv->web_context)) {
filename = g_build_filename (ephy_profile_dir (), "cookies.sqlite", NULL);
webkit_cookie_manager_set_persistent_storage (cookie_manager, filename,
WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE);
}
g_signal_connect_object (priv->web_context, "download-started",
G_CALLBACK (download_started_cb), shell, 0);
g_signal_connect_object (EPHY_SETTINGS_WEB, "changed::remember-passwords",
G_CALLBACK (remember_passwords_setting_changed_cb), shell, 0);
g_signal_connect_object (EPHY_SETTINGS_WEB, "changed::enable-itp",
G_CALLBACK (enable_itp_setting_changed_cb), shell, 0);
}
static void
ephy_embed_shell_shutdown (GApplication *application)
{
G_APPLICATION_CLASS (ephy_embed_shell_parent_class)->shutdown (application);
g_object_unref (ephy_embed_prefs_get_settings ());
ephy_embed_utils_shutdown ();
}
static void
ephy_embed_shell_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (EPHY_EMBED_SHELL (object));
switch (prop_id) {
case PROP_MODE:
priv->mode = g_value_get_enum (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
ephy_embed_shell_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (EPHY_EMBED_SHELL (object));
switch (prop_id) {
case PROP_MODE:
g_value_set_enum (value, priv->mode);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
ephy_embed_shell_constructed (GObject *object)
{
EphyEmbedShell *shell;
EphyEmbedShellPrivate *priv;
G_OBJECT_CLASS (ephy_embed_shell_parent_class)->constructed (object);
shell = EPHY_EMBED_SHELL (object);
priv = ephy_embed_shell_get_instance_private (shell);
priv->guid = g_dbus_generate_guid ();
ephy_embed_shell_create_web_context (shell);
priv->permissions_manager = ephy_permissions_manager_new ();
priv->filters_manager = ephy_filters_manager_new (NULL);
}
static void
ephy_embed_shell_init (EphyEmbedShell *shell)
{
/* globally accessible singleton */
g_assert (!embed_shell);
embed_shell = shell;
}
static void
ephy_embed_shell_class_init (EphyEmbedShellClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GApplicationClass *application_class = G_APPLICATION_CLASS (klass);
object_class->dispose = ephy_embed_shell_dispose;
object_class->set_property = ephy_embed_shell_set_property;
object_class->get_property = ephy_embed_shell_get_property;
object_class->constructed = ephy_embed_shell_constructed;
application_class->startup = ephy_embed_shell_startup;
application_class->shutdown = ephy_embed_shell_shutdown;
object_properties[PROP_MODE] =
g_param_spec_enum ("mode",
"Mode",
"The global mode for this instance.",
EPHY_TYPE_EMBED_SHELL_MODE,
EPHY_EMBED_SHELL_MODE_BROWSER,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class,
N_PROPERTIES,
object_properties);
/**
* EphyEmbedShell::finished-restoring-window:
* @shell: the #EphyEmbedShell
*
* The ::finished-restoring-window signal is emitted when the
* session finishes restoring a window.
**/
signals[RESTORED_WINDOW] =
g_signal_new ("window-restored",
EPHY_TYPE_EMBED_SHELL,
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (EphyEmbedShellClass, restored_window),
NULL, NULL, NULL,
G_TYPE_NONE,
0);
/**
* EphyEmbedShell::web-view-created:
* @shell: the #EphyEmbedShell
* @view: the newly created #EphyWebView
*
* The ::web-view-created signal will be emitted every time a new
* #EphyWebView is created.
*
**/
signals[WEB_VIEW_CREATED] =
g_signal_new ("web-view-created",
EPHY_TYPE_EMBED_SHELL,
G_SIGNAL_RUN_LAST,
0, NULL, NULL, NULL,
G_TYPE_NONE, 1,
EPHY_TYPE_WEB_VIEW);
/**
* EphyEmbedShell::allow-tls-certificate:
* @shell: the #EphyEmbedShell
* @page_id: the identifier of the web page
*
* Emitted when the web process extension requests an exception be
* permitted for the invalid TLS certificate on the given page
*/
signals[ALLOW_TLS_CERTIFICATE] =
g_signal_new ("allow-tls-certificate",
EPHY_TYPE_EMBED_SHELL,
G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL,
G_TYPE_NONE, 1,
G_TYPE_UINT64);
/**
* EphyEmbedShell::allow-unsafe-browsing:
* @shell: the #EphyEmbedShell
* @page_id: the identifier of the web page
*
* Emitted when the web process extension requests an exception be
* permitted for the unsafe browsing warning on the given page
*/
signals[ALLOW_UNSAFE_BROWSING] =
g_signal_new ("allow-unsafe-browsing",
EPHY_TYPE_EMBED_SHELL,
G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL,
G_TYPE_NONE, 1,
G_TYPE_UINT64);
/**
* EphyEmbedShell::password-form-focused
* @shell: the #EphyEmbedShell
* @page_id: the identifier of the web page
* @insecure_action: whether the target of the form is http://
*
* Emitted when a form in a web page gains focus.
*/
signals[PASSWORD_FORM_FOCUSED] =
g_signal_new ("password-form-focused",
EPHY_TYPE_EMBED_SHELL,
G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL,
G_TYPE_NONE, 2,
G_TYPE_UINT64,
G_TYPE_BOOLEAN);
}
/**
* ephy_embed_shell_get_default:
*
* Retrieves the default #EphyEmbedShell object
*
* Return value: (transfer none): the default #EphyEmbedShell
**/
EphyEmbedShell *
ephy_embed_shell_get_default (void)
{
return embed_shell;
}
void
ephy_embed_shell_set_page_setup (EphyEmbedShell *shell,
GtkPageSetup *page_setup)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
g_autofree char *path = NULL;
g_assert (EPHY_IS_EMBED_SHELL (shell));
if (page_setup)
g_object_ref (page_setup);
else
page_setup = gtk_page_setup_new ();
if (priv->page_setup)
g_object_unref (priv->page_setup);
priv->page_setup = page_setup;
path = g_build_filename (ephy_profile_dir (), PAGE_SETUP_FILENAME, NULL);
gtk_page_setup_to_file (page_setup, path, NULL);
}
/**
* ephy_embed_shell_get_page_setup:
*
* Return value: (transfer none):
**/
GtkPageSetup *
ephy_embed_shell_get_page_setup (EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
g_assert (EPHY_IS_EMBED_SHELL (shell));
if (!priv->page_setup) {
g_autofree char *path = NULL;
path = g_build_filename (ephy_profile_dir (), PAGE_SETUP_FILENAME, NULL);
priv->page_setup = gtk_page_setup_new_from_file (path, NULL);
/* If that still didn't work, create a new, empty one */
if (!priv->page_setup)
priv->page_setup = gtk_page_setup_new ();
}
return priv->page_setup;
}
/**
* ephy_embed_shell_set_print_settings:
* @shell: the #EphyEmbedShell
* @settings: the new #GtkPrintSettings object
*
* Sets the global #GtkPrintSettings object.
*
**/
void
ephy_embed_shell_set_print_settings (EphyEmbedShell *shell,
GtkPrintSettings *settings)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
g_autofree char *path = NULL;
g_assert (EPHY_IS_EMBED_SHELL (shell));
if (settings)
g_object_ref (settings);
if (priv->print_settings)
g_object_unref (priv->print_settings);
priv->print_settings = settings ? settings : gtk_print_settings_new ();
path = g_build_filename (ephy_profile_dir (), PRINT_SETTINGS_FILENAME, NULL);
gtk_print_settings_to_file (settings, path, NULL);
}
/**
* ephy_embed_shell_get_print_settings:
* @shell: the #EphyEmbedShell
*
* Gets the global #GtkPrintSettings object.
*
* Returns: (transfer none): a #GtkPrintSettings object
**/
GtkPrintSettings *
ephy_embed_shell_get_print_settings (EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
g_assert (EPHY_IS_EMBED_SHELL (shell));
if (!priv->print_settings) {
g_autofree char *path = NULL;
path = g_build_filename (ephy_profile_dir (), PRINT_SETTINGS_FILENAME, NULL);
priv->print_settings = gtk_print_settings_new_from_file (path, NULL);
/* Note: the gtk print settings file format is the same as our
* legacy one, so no need to migrate here.
*/
if (!priv->print_settings)
priv->print_settings = gtk_print_settings_new ();
}
return priv->print_settings;
}
/**
* ephy_embed_shell_get_mode:
* @shell: an #EphyEmbedShell
*
* Returns: the global mode of the @shell
**/
EphyEmbedShellMode
ephy_embed_shell_get_mode (EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
g_assert (EPHY_IS_EMBED_SHELL (shell));
return priv->mode;
}
/**
* ephy_embed_shell_clear_cache:
* @shell: an #EphyEmbedShell
*
* Clears the HTTP cache (temporarily saved web pages).
**/
void
ephy_embed_shell_clear_cache (EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
webkit_web_context_clear_cache (priv->web_context);
}
EphyFiltersManager *
ephy_embed_shell_get_filters_manager (EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
return priv->filters_manager;
}
const char *
ephy_embed_shell_get_guid (EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
return priv->guid;
}
WebKitWebContext *
ephy_embed_shell_get_web_context (EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
return priv->web_context;
}
EphyDownloadsManager *
ephy_embed_shell_get_downloads_manager (EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
if (!priv->downloads_manager)
priv->downloads_manager = EPHY_DOWNLOADS_MANAGER (g_object_new (EPHY_TYPE_DOWNLOADS_MANAGER, NULL));
return priv->downloads_manager;
}
EphyPermissionsManager *
ephy_embed_shell_get_permissions_manager (EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
return priv->permissions_manager;
}
EphySearchEngineManager *
ephy_embed_shell_get_search_engine_manager (EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
if (!priv->search_engine_manager)
priv->search_engine_manager = ephy_search_engine_manager_new ();
return priv->search_engine_manager;
}
EphyPasswordManager *
ephy_embed_shell_get_password_manager (EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
return priv->password_manager;
}
void
ephy_embed_shell_register_ucm_handler (EphyEmbedShell *shell,
WebKitUserContentManager *ucm)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
/* User content manager */
webkit_user_content_manager_register_script_message_handler_in_world (ucm,
"overview",
priv->guid);
g_signal_connect_object (ucm, "script-message-received::overview",
G_CALLBACK (web_process_extension_overview_message_received_cb),
shell, 0);
webkit_user_content_manager_register_script_message_handler (ucm,
"tlsErrorPage");
g_signal_connect_object (ucm, "script-message-received::tlsErrorPage",
G_CALLBACK (web_process_extension_tls_error_page_message_received_cb),
shell, 0);
webkit_user_content_manager_register_script_message_handler (ucm,
"unsafeBrowsingErrorPage");
g_signal_connect_object (ucm, "script-message-received::unsafeBrowsingErrorPage",
G_CALLBACK (web_process_extension_unsafe_browsing_error_page_message_received_cb),
shell, 0);
webkit_user_content_manager_register_script_message_handler_in_world (ucm,
"passwordFormFocused",
priv->guid);
g_signal_connect_object (ucm, "script-message-received::passwordFormFocused",
G_CALLBACK (web_process_extension_password_form_focused_message_received_cb),
shell, 0);
webkit_user_content_manager_register_script_message_handler (ucm,
"aboutApps");
g_signal_connect_object (ucm, "script-message-received::aboutApps",
G_CALLBACK (web_process_extension_about_apps_message_received_cb),
shell, 0);
webkit_user_content_manager_register_script_message_handler_in_world (ucm,
"passwordManagerSave",
priv->guid);
g_signal_connect_object (ucm, "script-message-received::passwordManagerSave",
G_CALLBACK (web_process_extension_password_manager_save_received_cb),
shell, 0);
webkit_user_content_manager_register_script_message_handler_in_world (ucm,
"passwordManagerRequestSave",
priv->guid);
g_signal_connect_object (ucm, "script-message-received::passwordManagerRequestSave",
G_CALLBACK (web_process_extension_password_manager_request_save_received_cb),
shell, 0);
/* Filter Manager */
g_signal_connect_object (priv->filters_manager, "filters-disabled",
G_CALLBACK (webkit_user_content_manager_remove_all_filters),
ucm,
G_CONNECT_SWAPPED);
g_signal_connect_object (priv->filters_manager, "filter-ready",
G_CALLBACK (webkit_user_content_manager_add_filter),
ucm,
G_CONNECT_SWAPPED);
g_signal_connect_object (priv->filters_manager, "filter-removed",
G_CALLBACK (webkit_user_content_manager_remove_filter_by_id),
ucm,
G_CONNECT_SWAPPED);
/* User Scripts */
ephy_embed_prefs_apply_user_style (ucm);
ephy_embed_prefs_apply_user_javascript (ucm);
}
void
ephy_embed_shell_unregister_ucm_handler (EphyEmbedShell *shell,
WebKitUserContentManager *ucm)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
webkit_user_content_manager_unregister_script_message_handler_in_world (ucm,
"overview",
priv->guid);
webkit_user_content_manager_unregister_script_message_handler (ucm,
"tlsErrorPage");
webkit_user_content_manager_unregister_script_message_handler (ucm,
"unsafeBrowsingErrorPage");
webkit_user_content_manager_unregister_script_message_handler_in_world (ucm,
"passwordManagerRequestSave",
priv->guid);
webkit_user_content_manager_unregister_script_message_handler_in_world (ucm,
"passwordFormFocused",
priv->guid);
webkit_user_content_manager_unregister_script_message_handler (ucm, "aboutApps");
webkit_user_content_manager_unregister_script_message_handler_in_world (ucm,
"passwordManagerSave",
priv->guid);
}
void
ephy_embed_shell_pdf_handler_stop (EphyEmbedShell *shell,
WebKitWebView *web_view)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
ephy_pdf_handler_stop (priv->pdf_handler, web_view);
}