[geary/mjog/558-webkit-shared-process: 6/11] Re-use WebKitGTK WebProcesses between ConversationWebView



commit 5b04686dbbbd22fce61474be91e858251c0e13cc
Author: Michael Gratton <mike vee net>
Date:   Tue Nov 26 14:15:58 2019 +1100

    Re-use WebKitGTK WebProcesses between ConversationWebView
    
    Add a new ctor to Component.WebView and ConversationWebView to be able
    to use the WebKit.WebView::related-view property at construction time.
    Add new ConversationViewer::previous-web-view property to store
    the per-window last created web view. Use this when constructing new
    wen views in ConversationMessage to share the WebProcess.

 src/client/components/components-web-view.vala     | 111 +++++++++++++--------
 .../conversation-viewer/conversation-message.vala  |  17 +++-
 .../conversation-viewer/conversation-viewer.vala   |   8 ++
 .../conversation-viewer/conversation-web-view.vala |  35 ++++++-
 4 files changed, 121 insertions(+), 50 deletions(-)
---
diff --git a/src/client/components/components-web-view.vala b/src/client/components/components-web-view.vala
index 7d6cdcb1..c630505e 100644
--- a/src/client/components/components-web-view.vala
+++ b/src/client/components/components-web-view.vala
@@ -1,6 +1,6 @@
 /*
  * Copyright 2016 Software Freedom Conservancy Inc.
- * Copyright 2016 Michael Gratton <mike vee net>
+ * Copyright 2016-2019 Michael Gratton <mike vee net>
  *
  * This software is licensed under the GNU Lesser General Public License
  * (version 2.1 or later). See the COPYING file in this distribution.
@@ -294,7 +294,8 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
 
 
     protected WebView(Application.Configuration config,
-                            WebKit.UserContentManager? custom_manager = null) {
+                      WebKit.UserContentManager? custom_manager = null,
+                      WebView? related = null) {
         WebKit.Settings setts = new WebKit.Settings();
         setts.allow_modal_dialogs = false;
         setts.default_charset = "UTF-8";
@@ -321,53 +322,31 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
         }
 
         Object(
-            web_context: WebView.default_context,
+            settings: setts,
             user_content_manager: content_manager,
-            settings: setts
+            web_context: WebView.default_context
         );
         base_ref();
+        init(config);
+    }
 
-        // XXX get the allow prefix from the extension somehow
-
-        this.decide_policy.connect(on_decide_policy);
-        this.web_process_terminated.connect((reason) => {
-                warning("Web process crashed: %s", reason.to_string());
-            });
-
-        register_message_handler(
-            COMMAND_STACK_CHANGED, on_command_stack_changed
-        );
-        register_message_handler(
-            CONTENT_LOADED, on_content_loaded
-        );
-        register_message_handler(
-            DOCUMENT_MODIFIED, on_document_modified
-        );
-        register_message_handler(
-            PREFERRED_HEIGHT_CHANGED, on_preferred_height_changed
-        );
-        register_message_handler(
-            REMOTE_IMAGE_LOAD_BLOCKED, on_remote_image_load_blocked
-        );
-        register_message_handler(
-            SELECTION_CHANGED, on_selection_changed
+    /**
+     * Constructs a new web view with a new shared WebProcess.
+     *
+     * The new view will use the same WebProcess, settings and content
+     * manager as the given related view's.
+     *
+     * @see WebKit.WebView.with_related_view
+     */
+    protected WebView.with_related_view(Application.Configuration config,
+                                        WebView related) {
+        Object(
+            related_view: related,
+            settings: related.get_settings(),
+            user_content_manager: related.user_content_manager
         );
-
-        // Manage zoom level, ensure it's sane
-        config.bind(Application.Configuration.CONVERSATION_VIEWER_ZOOM_KEY, this, "zoom_level");
-        if (this.zoom_level < ZOOM_MIN) {
-            this.zoom_level = ZOOM_MIN;
-        } else if (this.zoom_level > ZOOM_MAX) {
-            this.zoom_level = ZOOM_MAX;
-        }
-        this.scroll_event.connect(on_scroll_event);
-
-        // Watch desktop font settings
-        Settings system_settings = config.gnome_interface;
-        system_settings.bind("document-font-name", this,
-                             "document-font", SettingsBindFlags.DEFAULT);
-        system_settings.bind("monospace-font-name", this,
-                             "monospace-font", SettingsBindFlags.DEFAULT);
+        base_ref();
+        init(config);
     }
 
     ~WebView() {
@@ -521,6 +500,50 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
         }
     }
 
+    private void init(Application.Configuration config) {
+        // XXX get the allow prefix from the extension somehow
+
+        this.decide_policy.connect(on_decide_policy);
+        this.web_process_terminated.connect((reason) => {
+                warning("Web process crashed: %s", reason.to_string());
+            });
+
+        register_message_handler(
+            COMMAND_STACK_CHANGED, on_command_stack_changed
+        );
+        register_message_handler(
+            CONTENT_LOADED, on_content_loaded
+        );
+        register_message_handler(
+            DOCUMENT_MODIFIED, on_document_modified
+        );
+        register_message_handler(
+            PREFERRED_HEIGHT_CHANGED, on_preferred_height_changed
+        );
+        register_message_handler(
+            REMOTE_IMAGE_LOAD_BLOCKED, on_remote_image_load_blocked
+        );
+        register_message_handler(
+            SELECTION_CHANGED, on_selection_changed
+        );
+
+        // Manage zoom level, ensure it's sane
+        config.bind(Application.Configuration.CONVERSATION_VIEWER_ZOOM_KEY, this, "zoom_level");
+        if (this.zoom_level < ZOOM_MIN) {
+            this.zoom_level = ZOOM_MIN;
+        } else if (this.zoom_level > ZOOM_MAX) {
+            this.zoom_level = ZOOM_MAX;
+        }
+        this.scroll_event.connect(on_scroll_event);
+
+        // Watch desktop font settings
+        Settings system_settings = config.gnome_interface;
+        system_settings.bind("document-font-name", this,
+                             "document-font", SettingsBindFlags.DEFAULT);
+        system_settings.bind("monospace-font-name", this,
+                             "monospace-font", SettingsBindFlags.DEFAULT);
+    }
+
     private void handle_cid_request(WebKit.URISchemeRequest request) {
         if (!handle_internal_response(request)) {
             request.finish_error(new FileError.NOENT("Unknown CID"));
diff --git a/src/client/conversation-viewer/conversation-message.vala 
b/src/client/conversation-viewer/conversation-message.vala
index f70c70c9..4e510ad8 100644
--- a/src/client/conversation-viewer/conversation-message.vala
+++ b/src/client/conversation-viewer/conversation-message.vala
@@ -510,7 +510,22 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
     }
 
     private void initialize_web_view() {
-        this.web_view = new ConversationWebView(config);
+        var viewer = get_ancestor(typeof(ConversationViewer)) as ConversationViewer;
+
+        // Ensure we share the same WebProcess with the last one
+        // constructed if possible.
+        if (viewer != null && viewer.previous_web_view != null) {
+            this.web_view = new ConversationWebView.with_related_view(
+                this.config,
+                viewer.previous_web_view
+            );
+        } else {
+            this.web_view = new ConversationWebView(this.config);
+        }
+        if (viewer != null) {
+            viewer.previous_web_view = this.web_view;
+        }
+
         this.web_view.context_menu.connect(on_context_menu);
         this.web_view.deceptive_link_clicked.connect(on_deceptive_link_clicked);
         this.web_view.link_activated.connect((link) => {
diff --git a/src/client/conversation-viewer/conversation-viewer.vala 
b/src/client/conversation-viewer/conversation-viewer.vala
index 3d2a0226..8157e140 100644
--- a/src/client/conversation-viewer/conversation-viewer.vala
+++ b/src/client/conversation-viewer/conversation-viewer.vala
@@ -24,6 +24,14 @@ public class ConversationViewer : Gtk.Stack, Geary.BaseInterface {
         get; private set; default = null;
     }
 
+    /**
+     * The most recent web view created in this viewer.
+     *
+     * Keep the last created web view around so others can share the
+     * same WebKitGTK WebProcess.
+     */
+    internal ConversationWebView? previous_web_view { get; set; default = null; }
+
     private Application.Configuration config;
 
     private Gee.Set<Geary.App.Conversation>? selection_while_composing = null;
diff --git a/src/client/conversation-viewer/conversation-web-view.vala 
b/src/client/conversation-viewer/conversation-web-view.vala
index 27a2cf34..a164c016 100644
--- a/src/client/conversation-viewer/conversation-web-view.vala
+++ b/src/client/conversation-viewer/conversation-web-view.vala
@@ -56,16 +56,33 @@ public class ConversationWebView : Components.WebView {
     );
 
 
+    /**
+     * Constructs a new web view for displaying an email message body.
+     *
+     * A new WebKitGTK WebProcess will be constructed for this view.
+     */
     public ConversationWebView(Application.Configuration config) {
         base(config);
+        init();
+
+        // These only need to be added when creating a new WebProcess,
+        // not when sharing one
         this.user_content_manager.add_script(ConversationWebView.app_script);
         this.user_content_manager.add_style_sheet(ConversationWebView.app_stylesheet);
+    }
 
-        register_message_handler(
-            DECEPTIVE_LINK_CLICKED, on_deceptive_link_clicked
-        );
-
-        this.notify["preferred-height"].connect(() => queue_resize());
+    /**
+     * Constructs a new web view for displaying an email message body.
+     *
+     * The WebKitGTK WebProcess will be shared with the related view's
+     * process.
+     */
+    internal ConversationWebView.with_related_view(
+        Application.Configuration config,
+        ConversationWebView related
+    ) {
+        base.with_related_view(config, related);
+        init();
     }
 
     /**
@@ -195,6 +212,14 @@ public class ConversationWebView : Components.WebView {
         minimum_height = natural_height = 0;
     }
 
+    private void init() {
+        register_message_handler(
+            DECEPTIVE_LINK_CLICKED, on_deceptive_link_clicked
+        );
+
+        this.notify["preferred-height"].connect(() => queue_resize());
+    }
+
     private void on_deceptive_link_clicked(WebKit.JavascriptResult result) {
         try {
             JSC.Value object = result.get_js_value();


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]