diff --git a/core/cog-shell.c b/core/cog-shell.c index 8fb11609..6510dc5d 100644 --- a/core/cog-shell.c +++ b/core/cog-shell.c @@ -1,5 +1,6 @@ /* * cog-shell.c + * Copyright (C) 2019-2023 Igalia S.L. * Copyright (C) 2018 Adrian Perez * * SPDX-License-Identifier: MIT @@ -16,9 +17,6 @@ * A shell managed a [class@WebKit.WebView], the default URI that it will * load, the view configuration, and keeps track of a number of registered * [iface@Cog.RequestHandler] instances. - * - * Applications using a shell can handle the [signal@Cog.Shell::create-view] - * signal to customize the web view. */ typedef struct { @@ -30,7 +28,6 @@ typedef struct { WebKitSettings *web_settings; WebKitWebContext *web_context; - GPtrArray *viewports; #if !COG_USE_WPE2 WebKitWebsiteDataManager *web_data_manager; @@ -53,8 +50,6 @@ enum { PROP_NAME, PROP_WEB_SETTINGS, PROP_WEB_CONTEXT, - PROP_WEB_VIEW, - PROP_VIEWPORT, PROP_CONFIG_FILE, PROP_DEVICE_SCALE_FACTOR, PROP_AUTOMATED, @@ -69,23 +64,11 @@ enum { static GParamSpec *s_properties[N_PROPERTIES] = { NULL, }; enum { - CREATE_VIEW, - CREATE_VIEWPORT, STARTUP, SHUTDOWN, N_SIGNALS, }; -static int s_signals[N_SIGNALS] = { 0, }; - -static WebKitWebView* -cog_shell_create_view_base (CogShell *shell) -{ - CogShellPrivate *priv = PRIV(shell); - return g_object_new(cog_view_get_impl_type(), "settings", cog_shell_get_web_settings(shell), "web-context", - cog_shell_get_web_context(shell), "is-controlled-by-automation", priv->automated, NULL); -} - typedef struct { CogRequestHandler *handler; gboolean registered; @@ -137,23 +120,6 @@ request_handler_map_entry_register (const char *scheme, } } -static WebKitWebView * -cog_shell_create_web_view_for_automation(WebKitAutomationSession *session, CogShell *shell) -{ - /* FIXME: Actually create a fresh web view. */ - return cog_shell_get_web_view(shell); -} - -static void -cog_shell_automation_started_callback(WebKitWebContext *context, WebKitAutomationSession *session, CogShell *shell) -{ - g_autoptr(WebKitApplicationInfo) info = webkit_application_info_new(); - webkit_application_info_set_version(info, WEBKIT_MAJOR_VERSION, WEBKIT_MINOR_VERSION, WEBKIT_MICRO_VERSION); - webkit_automation_session_set_application_info(session, info); - - g_signal_connect(session, "create-web-view", G_CALLBACK(cog_shell_create_web_view_for_automation), shell); -} - static void cog_shell_startup_base(CogShell *shell) { @@ -165,24 +131,7 @@ cog_shell_startup_base(CogShell *shell) priv->web_context); } - g_autoptr(WebKitWebView) web_view = NULL; - g_signal_emit(shell, s_signals[CREATE_VIEW], 0, &web_view); - - g_assert(COG_IS_VIEW(web_view)); - - /* - * The web context and settings being used by the web view must be - * the same that were pre-created by shell. - */ - g_assert(webkit_web_view_get_settings(web_view) == priv->web_settings); - g_assert(webkit_web_view_get_context(web_view) == priv->web_context); - webkit_web_context_set_automation_allowed(priv->web_context, priv->automated); - g_signal_connect(priv->web_context, "automation-started", G_CALLBACK(cog_shell_automation_started_callback), shell); - CogViewport *viewport = cog_shell_get_viewport(shell); - g_assert(viewport); - - cog_viewport_add(viewport, COG_VIEW(web_view)); } static void @@ -207,12 +156,6 @@ cog_shell_get_property (GObject *object, case PROP_WEB_CONTEXT: g_value_set_object (value, cog_shell_get_web_context (shell)); break; - case PROP_WEB_VIEW: - g_value_set_object (value, cog_shell_get_web_view (shell)); - break; - case PROP_VIEWPORT: - g_value_set_object(value, cog_shell_get_viewport(shell)); - break; #if COG_HAVE_MEM_PRESSURE case PROP_WEB_MEMORY_SETTINGS: g_value_set_boxed(value, PRIV(shell)->web_mem_settings); @@ -279,17 +222,6 @@ cog_shell_set_property (GObject *object, } } -static void -cog_shell_viewport_visible_view_changed(CogViewport *viewport G_GNUC_UNUSED, - GParamSpec *pspec G_GNUC_UNUSED, - GObject *shell) -{ - g_assert(COG_IS_SHELL(shell)); - g_assert(COG_IS_VIEWPORT(viewport)); - - g_object_notify_by_pspec(shell, s_properties[PROP_WEB_VIEW]); -} - static void cog_shell_constructed(GObject *object) { @@ -323,8 +255,6 @@ cog_shell_constructed(GObject *object) "memory-pressure-settings", priv->web_mem_settings, #endif NULL); - - priv->viewports = g_ptr_array_new_full(3, g_object_unref); } static void @@ -332,8 +262,6 @@ cog_shell_dispose(GObject *object) { CogShellPrivate *priv = PRIV(object); - g_ptr_array_free(priv->viewports, TRUE); - g_clear_object(&priv->web_context); g_clear_object(&priv->web_settings); #if !COG_USE_WPE2 @@ -356,53 +284,9 @@ cog_shell_class_init(CogShellClass *klass) object_class->get_property = cog_shell_get_property; object_class->set_property = cog_shell_set_property; - klass->create_view = cog_shell_create_view_base; klass->startup = cog_shell_startup_base; klass->shutdown = cog_shell_shutdown_base; - /** - * CogShell::create-view: - * @self: The shell to create the view for. - * @user_data: User data. - * - * The `create-view` signal is emitted when the shell needs to create - * a [class@WebKit.WebView]. - * - * Handling this signal allows to customize how the web view is - * configured. Note that the web view returned by a signal handler - * **must** use the settings and context returned by - * [id@cog_shell_get_web_settings] and [id@cog_shell_get_web_context]. - * - * Returns: (transfer full) (nullable): A new web view that will be used - * by the shell. - */ - s_signals[CREATE_VIEW] = g_signal_new("create-view", - COG_TYPE_SHELL, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET(CogShellClass, create_view), - g_signal_accumulator_first_wins, - NULL, - NULL, - COG_TYPE_VIEW, - 0); - - /** - * CogShell::create-viewport: - * @self: The shell creating the new CogViewport. - * @viewport: The created new viewport. - * @user_data: User data. - * - * The `create-viewport` signal is emitted when the shell creates a new a - * new CogViewport. - * - * Handling this signal allows to customize the actions required to be - * done during the creation of a new viewport. - * - * Returns: (void). - */ - s_signals[CREATE_VIEWPORT] = g_signal_new("create-viewport", COG_TYPE_SHELL, G_SIGNAL_RUN_FIRST, 0, NULL, NULL, - NULL, G_TYPE_NONE, 1, COG_TYPE_VIEWPORT); - /** * CogShell:name: (attributes org.gtk.Property.get=cog_shell_get_name): * @@ -446,28 +330,6 @@ cog_shell_class_init(CogShellClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - /** - * CogShell:web-view: (attributes org.gtk.Property.get=cog_shell_get_web_view): - * - * The [class@WebKit.WebView] managed by this shell. - */ - s_properties[PROP_WEB_VIEW] = - g_param_spec_object("web-view", - "Web View", - "The WebKitWebView used by the shell", - WEBKIT_TYPE_WEB_VIEW, - G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); - - /** - * CogShell:viewport: (attributes org.gtk.Property.get=cog_shell_get_viewport) (getter get_viewport): - * - * The [class@Viewport] managed by this shell. - * - * Since: 0.20 - */ - s_properties[PROP_VIEWPORT] = - g_param_spec_object("viewport", NULL, NULL, COG_TYPE_VIEWPORT, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - /** * CogShell:config-file: (attributes org.gtk.Property.get=cog_shell_get_config_file): * @@ -594,21 +456,6 @@ cog_shell_get_web_settings (CogShell *shell) return PRIV (shell)->web_settings; } -/** - * cog_shell_get_web_view: - * - * Obtains the visible [class@WebKit.WebView] for this shell. - * - * Returns: (nullable): A web view. - */ -WebKitWebView * -cog_shell_get_web_view(CogShell *shell) -{ - g_return_val_if_fail(COG_IS_SHELL(shell), NULL); - CogViewport *viewport = cog_shell_get_viewport(shell); - return WEBKIT_WEB_VIEW(cog_viewport_get_visible_view(viewport)); -} - /** * cog_shell_get_name: * @@ -697,8 +544,7 @@ cog_shell_set_request_handler(CogShell *shell, const char *scheme, CogRequestHan * * Finish initializing the shell. * - * This takes care of registering custom URI scheme handlers and emitting - * [signal@Cog.Shell::create-view]. + * This takes care of registering custom URI scheme handlers. * * Subclasses which override this method **must** invoke the base * implementation. @@ -723,135 +569,3 @@ cog_shell_shutdown (CogShell *shell) CogShellClass *klass = COG_SHELL_GET_CLASS (shell); (*klass->shutdown) (shell); } - -/** - * cog_shell_get_viewport: - * - * Gets the default viewport managed by the shell. - * - * Returns: (transfer none): A viewport. - * - * Since: 0.20 - */ -CogViewport * -cog_shell_get_viewport(CogShell *shell) -{ - g_return_val_if_fail(COG_IS_SHELL(shell), NULL); - - gsize size = cog_shell_get_n_viewports(shell); - CogViewport *viewport; - - // Create and add the default viewport if this doesn't exist already - if (size == 0) { - viewport = cog_viewport_new(); - cog_shell_add_viewport(shell, viewport); - } else - viewport = cog_shell_get_nth_viewport(shell, COG_SHELL_DEFAULT_VIEWPORT_INDEX); - return viewport; -} - -GPtrArray * -cog_shell_get_viewports(CogShell *shell) -{ - g_return_val_if_fail(COG_IS_SHELL(shell), NULL); - return PRIV(shell)->viewports; -} - -/** - * cog_shell_add_viewport: - * @shell: Shell to add the viewport to. - * @viewport: The viewport to add. - * - * Adds a viewport to a shell. - * - * The next available index will be assigned to the viewport. - */ -void -cog_shell_add_viewport(CogShell *shell, CogViewport *viewport) -{ - g_return_if_fail(COG_IS_SHELL(shell)); - g_return_if_fail(COG_IS_VIEWPORT(viewport)); - - CogShellPrivate *priv = PRIV(shell); - g_return_if_fail(!g_ptr_array_find(priv->viewports, viewport, NULL)); - - g_ptr_array_add(priv->viewports, g_object_ref(viewport)); - - g_signal_connect_object(viewport, "notify::visible-view", G_CALLBACK(cog_shell_viewport_visible_view_changed), - shell, 0); - - g_signal_emit(shell, s_signals[CREATE_VIEWPORT], 0, viewport); -} - -/** - * cog_shell_remove_viewport: - * @shell: Shell to remove the viewport from. - * @viewport: The viewport to remove. - * - * Removes a viewport from the shell. - * - * Removing a viewport preserves the relative ordering of the rest of viewports in - * the shell. This also means that the index used to retrieve them may - * change after removal. - */ -void -cog_shell_remove_viewport(CogShell *shell, CogViewport *viewport) -{ - g_return_if_fail(COG_IS_VIEWPORT(shell)); - g_return_if_fail(COG_IS_VIEW(viewport)); - - CogShellPrivate *priv = PRIV(shell); - - unsigned index; - if (!g_ptr_array_find(priv->viewports, viewport, &index)) { - g_warning("Attempted to remove viewport %p, which was not in shell %p.", viewport, shell); - return; - } - - g_ptr_array_remove_index(priv->viewports, index); -} - -/** - * cog_shell_get_n_viewports: - * @shell: Shell. - * - * Gets the number of viewports in a shell. - * - * Returns: Number of viewports. - */ -gsize -cog_shell_get_n_viewports(CogShell *shell) -{ - g_return_val_if_fail(COG_IS_SHELL(shell), 0); - - return PRIV(shell)->viewports->len; -} - -/** - * cog_shell_get_nth_viewport: - * @shell: Shell. - * @index: Index of the viewport to get. - * - * Gets a viewport from the shell given its index. - * - * This is typically used along [method@CogShell.get_n_viewports] to iterate - * over the viewports: - * - * ```c - * CogShell *shell = get_shell(); - * for (gsize i = 0; i < cog_shell_get_n_viewports(shell); i++) - * handle_viewport(cog_shell_get_nth_viewport(shell, i)); - * ``` - * - * Returns: (transfer none): Viewport at the given @index. - */ -CogViewport * -cog_shell_get_nth_viewport(CogShell *shell, gsize index) -{ - g_return_val_if_fail(COG_IS_SHELL(shell), NULL); - - CogShellPrivate *priv = PRIV(shell); - g_return_val_if_fail(index < priv->viewports->len, NULL); - - return g_ptr_array_index(priv->viewports, index); -} diff --git a/core/cog-shell.h b/core/cog-shell.h index 679114b7..6a89464d 100644 --- a/core/cog-shell.h +++ b/core/cog-shell.h @@ -18,8 +18,7 @@ G_BEGIN_DECLS #define COG_SHELL_DEFAULT_VIEWPORT_INDEX 0 -typedef struct _CogViewport CogViewport; -typedef struct _WebKitWebView WebKitWebView; +typedef struct _CogView CogView; #define COG_TYPE_SHELL (cog_shell_get_type()) @@ -30,16 +29,14 @@ struct _CogShellClass { GObjectClass parent_class; /*< public >*/ - WebKitWebView* (*create_view) (CogShell*); - void (*startup) (CogShell*); - void (*shutdown) (CogShell*); + void (*startup)(CogShell *self); + void (*shutdown)(CogShell *self); }; COG_API CogShell *cog_shell_new(const char *name, gboolean automated); COG_API const char *cog_shell_get_name(CogShell *shell); COG_API WebKitWebContext *cog_shell_get_web_context(CogShell *shell); COG_API WebKitSettings *cog_shell_get_web_settings(CogShell *shell); -COG_API WebKitWebView *cog_shell_get_web_view(CogShell *shell); COG_API GKeyFile *cog_shell_get_config_file(CogShell *shell); COG_API gdouble cog_shell_get_device_scale_factor(CogShell *shell); COG_API gboolean cog_shell_is_automated(CogShell *shell); @@ -48,12 +45,4 @@ COG_API void cog_shell_set_request_handler(CogShell *shell, const char *scheme, COG_API void cog_shell_startup(CogShell *shell); COG_API void cog_shell_shutdown(CogShell *shell); -COG_API CogViewport *cog_shell_get_viewport(CogShell *shell); -COG_API GPtrArray *cog_shell_get_viewports(CogShell *shell); - -COG_API void cog_shell_add_viewport(CogShell *shell, CogViewport *viewport); -COG_API void cog_shell_remove_viewport(CogShell *shell, CogViewport *viewport); -COG_API gsize cog_shell_get_n_viewports(CogShell *shell); -COG_API CogViewport *cog_shell_get_nth_viewport(CogShell *shell, gsize index); - G_END_DECLS diff --git a/examples/viewport.c b/examples/viewport.c index 711cb82e..b3d0370c 100644 --- a/examples/viewport.c +++ b/examples/viewport.c @@ -43,10 +43,9 @@ main(int argc, char *argv[]) if (!cog_platform_setup(platform, shell, NULL, &error)) g_error("Cannot configure platform: %s", error->message); + g_autoptr(CogViewport) viewport = cog_viewport_new(); g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); - CogViewport *viewport = cog_shell_get_viewport(shell); - for (int i = 1; i < argc; i++) { g_autoptr(CogView) view = cog_view_new(NULL); cog_platform_init_web_view(platform, WEBKIT_WEB_VIEW(view)); diff --git a/examples/viewports.c b/examples/viewports.c index d21d2a96..d54c3e24 100644 --- a/examples/viewports.c +++ b/examples/viewports.c @@ -46,7 +46,6 @@ main(int argc, char *argv[]) g_autoptr(GMainLoop) loop = g_main_loop_new(NULL, FALSE); CogViewport *viewport0 = cog_viewport_new(); - cog_shell_add_viewport(shell, viewport0); for (int i = 1; i < argc; i++) { g_autoptr(CogView) view = cog_view_new(NULL); @@ -64,7 +63,6 @@ main(int argc, char *argv[]) on_timeout_tick(&data0); CogViewport *viewport1 = cog_viewport_new(); - cog_shell_add_viewport(shell, viewport1); for (int i = 1; i < argc; i++) { g_autoptr(CogView) view = cog_view_new(NULL); diff --git a/launcher/cog-launcher.c b/launcher/cog-launcher.c index ad490583..2055cafe 100644 --- a/launcher/cog-launcher.c +++ b/launcher/cog-launcher.c @@ -131,10 +131,19 @@ struct _CogLauncher { guint sigint_source; guint sigterm_source; + + CogViewport *viewport; }; G_DEFINE_TYPE(CogLauncher, cog_launcher, G_TYPE_APPLICATION) +static WebKitWebView * +cog_launcher_get_visible_view(CogLauncher *self) +{ + g_return_val_if_fail(COG_IS_LAUNCHER(self), NULL); + return (WebKitWebView *) cog_viewport_get_visible_view(self->viewport); +} + static void on_action_quit(G_GNUC_UNUSED GAction *action, G_GNUC_UNUSED GVariant *param, CogLauncher *launcher) { @@ -144,26 +153,26 @@ on_action_quit(G_GNUC_UNUSED GAction *action, G_GNUC_UNUSED GVariant *param, Cog static void on_action_prev(G_GNUC_UNUSED GAction *action, G_GNUC_UNUSED GVariant *param, CogLauncher *launcher) { - webkit_web_view_go_back(cog_shell_get_web_view(launcher->shell)); + webkit_web_view_go_back(cog_launcher_get_visible_view(launcher)); } static void on_action_next(G_GNUC_UNUSED GAction *action, G_GNUC_UNUSED GVariant *param, CogLauncher *launcher) { - webkit_web_view_go_forward(cog_shell_get_web_view(launcher->shell)); + webkit_web_view_go_forward(cog_launcher_get_visible_view(launcher)); } static void on_action_reload(G_GNUC_UNUSED GAction *action, G_GNUC_UNUSED GVariant *param, CogLauncher *launcher) { - webkit_web_view_reload(cog_shell_get_web_view(launcher->shell)); + webkit_web_view_reload(cog_launcher_get_visible_view(launcher)); } static void on_action_open(G_GNUC_UNUSED GAction *action, GVariant *param, CogLauncher *launcher) { g_return_if_fail(g_variant_is_of_type(param, G_VARIANT_TYPE_STRING)); - webkit_web_view_load_uri(cog_shell_get_web_view(launcher->shell), g_variant_get_string(param, NULL)); + webkit_web_view_load_uri(cog_launcher_get_visible_view(launcher), g_variant_get_string(param, NULL)); } static gboolean @@ -184,14 +193,6 @@ on_permission_request(G_GNUC_UNUSED WebKitWebView *web_view, WebKitPermissionReq return TRUE; } -static void -on_notify_web_view(CogShell *shell, GParamSpec *arg G_GNUC_UNUSED, CogLauncher *launcher) -{ - WebKitWebView *web_view = cog_shell_get_web_view(shell); - - g_signal_connect(web_view, "permission-request", G_CALLBACK(on_permission_request), launcher); -} - static void cog_launcher_add_action(CogLauncher *launcher, const char *name, @@ -216,7 +217,7 @@ cog_launcher_open(GApplication *application, GFile **files, int n_files, const c g_warning("Requested opening %i files, opening only the first one", n_files); g_autofree char *uri = g_file_get_uri(files[0]); - webkit_web_view_load_uri(cog_shell_get_web_view(COG_LAUNCHER(application)->shell), uri); + webkit_web_view_load_uri(cog_launcher_get_visible_view(COG_LAUNCHER(application)), uri); } static void * @@ -227,94 +228,33 @@ on_web_view_create(WebKitWebView *web_view, WebKitNavigationAction *action) } static WebKitWebView * -cog_launcher_create_view(CogLauncher *self, CogShell *shell) +on_automation_session_create_web_view(WebKitAutomationSession *session, CogLauncher *launcher) { - g_assert(shell == self->shell); - - WebKitWebContext *web_context = cog_shell_get_web_context(shell); - - if (s_options.doc_viewer) { - webkit_web_context_set_cache_model(web_context, WEBKIT_CACHE_MODEL_DOCUMENT_VIEWER); - } - - CogPlatform *platform = cog_platform_get(); - - g_autoptr(GError) error = NULL; - if (!cog_platform_setup(platform, shell, s_options.platform_params, &error)) - g_error("Cannot configure platform: %s", error->message); - #if HAVE_WEBKIT_AUTOPLAY - WebKitWebsitePolicies *website_policies = + g_autoptr(WebKitWebsitePolicies) website_policies = webkit_website_policies_new_with_policies("autoplay", s_options.autoplay_policy, NULL); -#endif +#endif /* HAVE_WEBKIT_AUTOPLAY */ - g_autoptr(WebKitWebView) web_view = - WEBKIT_WEB_VIEW(cog_view_new("settings", cog_shell_get_web_settings(shell), "web-context", web_context, - "zoom-level", s_options.scale_factor, "is-controlled-by-automation", - cog_shell_is_automated(shell), "use-key-bindings", !s_options.disable_key_bindings, + return (WebKitWebView *) cog_view_new("settings", cog_shell_get_web_settings(launcher->shell), "web-context", + cog_shell_get_web_context(launcher->shell), "is-controlled-by-automation", + TRUE, "zoom-level", s_options.scale_factor, "use-key-bindings", FALSE, #if COG_USE_WPE2 - "network-session", self->network_session, -#endif -#if HAVE_WEBKIT_AUTOPLAY - "website-policies", website_policies, -#endif - NULL)); - + "network-session", launcher->network_session, +#endif /* COG_USE_WPE2 */ #if HAVE_WEBKIT_AUTOPLAY - g_clear_object(&website_policies); -#endif - - if (s_options.filter) { - WebKitUserContentManager *manager = webkit_web_view_get_user_content_manager(web_view); - webkit_user_content_manager_add_filter(manager, s_options.filter); - g_clear_pointer(&s_options.filter, webkit_user_content_filter_unref); - } - - g_signal_connect(web_view, "create", G_CALLBACK(on_web_view_create), NULL); - - cog_platform_init_web_view(platform, web_view); - - if (s_options.background_color != NULL) { - WebKitColor color; - gboolean has_valid_color = webkit_color_parse(&color, s_options.background_color); - - if (has_valid_color) - webkit_web_view_set_background_color(web_view, &color); - else - g_error("'%s' doesn't represent a valid #RRGGBBAA or CSS color format.", s_options.background_color); - } - g_clear_pointer(&s_options.background_color, g_free); - - switch (s_options.on_failure.action_id) { - case WEBPROCESS_FAIL_ERROR_PAGE: - // Nothing else needed, the default error handler (connected - // below) already implements displaying an error page. - break; - - case WEBPROCESS_FAIL_EXIT: - cog_web_view_connect_web_process_terminated_exit_handler(web_view, EXIT_FAILURE); - break; - - case WEBPROCESS_FAIL_EXIT_OK: - cog_web_view_connect_web_process_terminated_exit_handler(web_view, EXIT_SUCCESS); - break; - - case WEBPROCESS_FAIL_RESTART: - // TODO: Un-hardcode the 5 retries per second. - cog_web_view_connect_web_process_terminated_restart_handler(web_view, 5, 1000); - break; - - default: - g_assert_not_reached(); - } - - cog_web_view_connect_default_progress_handlers(web_view); - cog_web_view_connect_default_error_handlers(web_view); + "website-policies", website_policies, +#endif /* HAVE_WEBKIT_AUTOPLAY */ + NULL); +} - webkit_web_view_load_uri(web_view, s_options.home_uri); - g_clear_pointer(&s_options.home_uri, g_free); +static void +on_automation_started(WebKitWebContext *context, WebKitAutomationSession *session, CogLauncher *launcher) +{ + g_autoptr(WebKitApplicationInfo) info = webkit_application_info_new(); + webkit_application_info_set_version(info, WEBKIT_MAJOR_VERSION, WEBKIT_MINOR_VERSION, WEBKIT_MICRO_VERSION); + webkit_automation_session_set_application_info(session, info); - return g_steal_pointer(&web_view); + g_signal_connect(session, "create-web-view", G_CALLBACK(on_automation_session_create_web_view), launcher); } static void @@ -340,18 +280,24 @@ cog_launcher_startup(GApplication *application) "web-memory-settings", self->web_mem_settings, "network-memory-settings", self->net_mem_settings, #endif /* COG_HAVE_MEM_PRESSURE */ NULL); - g_signal_connect_swapped(self->shell, "create-view", G_CALLBACK(cog_launcher_create_view), self); - g_signal_connect(self->shell, "notify::web-view", G_CALLBACK(on_notify_web_view), self); + + g_autoptr(GError) error = NULL; + if (!cog_platform_setup(cog_platform_get(), self->shell, s_options.platform_params, &error)) + g_error("Cannot configure platform: %s", error->message); + + WebKitWebContext *web_context = cog_shell_get_web_context(self->shell); + g_signal_connect(web_context, "automation-started", G_CALLBACK(on_automation_started), self); + + if (s_options.doc_viewer) + webkit_web_context_set_cache_model(web_context, WEBKIT_CACHE_MODEL_DOCUMENT_VIEWER); #if COG_USE_WPE2 if (s_options.web_extensions_dir) - webkit_web_context_set_web_process_extensions_directory(cog_shell_get_web_context(self->shell), - s_options.web_extensions_dir); + webkit_web_context_set_web_process_extensions_directory(web_context, s_options.web_extensions_dir); #else if (s_options.web_extensions_dir) - webkit_web_context_set_web_extensions_directory(cog_shell_get_web_context(self->shell), - s_options.web_extensions_dir); - webkit_web_context_set_sandbox_enabled(cog_shell_get_web_context(self->shell), s_options.enable_sandbox); + webkit_web_context_set_web_extensions_directory(web_context, s_options.web_extensions_dir); + webkit_web_context_set_sandbox_enabled(web_context, s_options.enable_sandbox); #endif g_clear_pointer(&s_options.web_extensions_dir, g_free); @@ -390,6 +336,76 @@ cog_launcher_startup(GApplication *application) s_options.ignore_tls_errors ? WEBKIT_TLS_ERRORS_POLICY_IGNORE : WEBKIT_TLS_ERRORS_POLICY_FAIL); #endif + +#if HAVE_WEBKIT_AUTOPLAY + g_autoptr(WebKitWebsitePolicies) website_policies = + webkit_website_policies_new_with_policies("autoplay", s_options.autoplay_policy, NULL); +#endif + + g_autoptr(CogView) view = cog_view_new("settings", cog_shell_get_web_settings(self->shell), "web-context", + cog_shell_get_web_context(self->shell), "zoom-level", s_options.scale_factor, + "use-key-bindings", !s_options.disable_key_bindings, +#if COG_USE_WPE2 + "network-session", self->network_session, +#endif +#if HAVE_WEBKIT_AUTOPLAY + "website-policies", website_policies, +#endif + NULL); + + cog_platform_init_web_view(cog_platform_get(), WEBKIT_WEB_VIEW(view)); + + g_signal_connect(view, "permission-request", G_CALLBACK(on_permission_request), self); + g_signal_connect(view, "create", G_CALLBACK(on_web_view_create), NULL); + + if (s_options.filter) { + WebKitUserContentManager *manager = webkit_web_view_get_user_content_manager(WEBKIT_WEB_VIEW(view)); + webkit_user_content_manager_add_filter(manager, s_options.filter); + g_clear_pointer(&s_options.filter, webkit_user_content_filter_unref); + } + + if (s_options.background_color != NULL) { + WebKitColor color; + gboolean has_valid_color = webkit_color_parse(&color, s_options.background_color); + + if (has_valid_color) + webkit_web_view_set_background_color(WEBKIT_WEB_VIEW(view), &color); + else + g_error("'%s' doesn't represent a valid #RRGGBBAA or CSS color format.", s_options.background_color); + } + g_clear_pointer(&s_options.background_color, g_free); + + switch (s_options.on_failure.action_id) { + case WEBPROCESS_FAIL_ERROR_PAGE: + // Nothing else needed, the default error handler (connected + // below) already implements displaying an error page. + break; + + case WEBPROCESS_FAIL_EXIT: + cog_web_view_connect_web_process_terminated_exit_handler(WEBKIT_WEB_VIEW(view), EXIT_FAILURE); + break; + + case WEBPROCESS_FAIL_EXIT_OK: + cog_web_view_connect_web_process_terminated_exit_handler(WEBKIT_WEB_VIEW(view), EXIT_SUCCESS); + break; + + case WEBPROCESS_FAIL_RESTART: + // TODO: Un-hardcode the 5 retries per second. + cog_web_view_connect_web_process_terminated_restart_handler(WEBKIT_WEB_VIEW(view), 5, 1000); + break; + + default: + g_assert_not_reached(); + } + + cog_web_view_connect_default_progress_handlers(WEBKIT_WEB_VIEW(view)); + cog_web_view_connect_default_error_handlers(WEBKIT_WEB_VIEW(view)); + + webkit_web_view_load_uri(WEBKIT_WEB_VIEW(view), s_options.home_uri); + g_clear_pointer(&s_options.home_uri, g_free); + + self->viewport = cog_viewport_new(); + cog_viewport_add(self->viewport, view); } static void @@ -413,11 +429,8 @@ cog_launcher_dispose(GObject *object) { CogLauncher *launcher = COG_LAUNCHER(object); - if (launcher->shell) { - g_signal_handlers_disconnect_by_func(launcher->shell, G_CALLBACK(on_notify_web_view), NULL); - g_signal_handlers_disconnect_by_func(launcher->shell, G_CALLBACK(cog_launcher_create_view), NULL); - g_clear_object(&launcher->shell); - } + g_clear_object(&launcher->shell); + g_clear_object(&launcher->viewport); g_clear_handle_id(&launcher->sigint_source, g_source_remove); g_clear_handle_id(&launcher->sigterm_source, g_source_remove);