[geary/wip/728002-webkit2: 94/96] Allow ClientWebView resources to be loaded via either cid or geary URLs.



commit a80ce0a3e8e20cdeff4205fda4069c4faf54d848
Author: Michael James Gratton <mike vee net>
Date:   Sat Jan 14 22:20:36 2017 +1100

    Allow ClientWebView resources to be loaded via either cid or geary URLs.
    
    * src/client/components/client-web-view.vala (ClientWebView): Rename
      members referring to inline resources to internal resources, update
      call sites.
      (ClientWebView::handle_cid_request,
       ClientWebView::handle_internal_request): Rework to use new common
       ::handle_internal_response method.
    
    * src/client/web-process/web-process-extension.vala: Permit by default
      any geary, cid, or data URI request.

 src/client/components/client-web-view.vala         |   54 +++++++++++++-------
 src/client/composer/composer-widget.vala           |   12 ++--
 .../conversation-viewer/conversation-email.vala    |    6 +-
 .../conversation-viewer/conversation-message.vala  |    2 +-
 src/client/web-process/web-process-extension.vala  |   13 ++---
 5 files changed, 49 insertions(+), 38 deletions(-)
---
diff --git a/src/client/components/client-web-view.vala b/src/client/components/client-web-view.vala
index 79e9179..08c7e5e 100644
--- a/src/client/components/client-web-view.vala
+++ b/src/client/components/client-web-view.vala
@@ -182,7 +182,7 @@ public class ClientWebView : WebKit.WebView {
 
     private weak string? body = null;
 
-    private Gee.Map<string,Geary.Memory.Buffer> cid_resources =
+    private Gee.Map<string,Geary.Memory.Buffer> internal_resources =
         new Gee.HashMap<string,Geary.Memory.Buffer>();
 
     private int preferred_height = 0;
@@ -194,8 +194,8 @@ public class ClientWebView : WebKit.WebView {
     /** Emitted when a user clicks a link in this web view. */
     public signal void link_activated(string uri);
 
-    /** Emitted when the web view has loaded an inline part. */
-    public signal void inline_resource_loaded(string cid);
+    /** Emitted when the view has loaded a resource added to it. */
+    public signal void internal_resource_loaded(string name);
 
     /** Emitted when a remote image load was disallowed. */
     public signal void remote_image_load_blocked();
@@ -294,17 +294,24 @@ public class ClientWebView : WebKit.WebView {
     }
 
     /**
-     * Adds an inline resource that may be accessed via a cid:id url.
+     * Adds an resource that may be accessed from the view via a URL.
+     *
+     * Internal resources may be access via both the internal `geary`
+     * scheme (for resources such as an image inserted via the
+     * composer) or via the `cid` scheme (for standard HTML email IMG
+     * elements).
      */
-    public void add_inline_resource(string id, Geary.Memory.Buffer buf) {
-        this.cid_resources[id] = buf;
+    public void add_internal_resource(string id, Geary.Memory.Buffer buf) {
+        this.internal_resources[id] = buf;
     }
 
     /**
-     * Adds a set of inline resource that may be accessed via a cid:id url.
+     * Adds a set of internal resources to the view.
+     *
+     * @see add_internal_resource
      */
-    public void add_inline_resources(Gee.Map<string,Geary.Memory.Buffer> res) {
-        this.cid_resources.set_all(res);
+    public void add_internal_resources(Gee.Map<string,Geary.Memory.Buffer> res) {
+        this.internal_resources.set_all(res);
     }
 
     /**
@@ -379,15 +386,8 @@ public class ClientWebView : WebKit.WebView {
     }
 
     private void handle_cid_request(WebKit.URISchemeRequest request) {
-        string cid = request.get_uri().substring(CID_URL_PREFIX.length);
-        Geary.Memory.Buffer? buf = this.cid_resources[cid];
-        if (buf != null) {
-            request.finish(buf.get_input_stream(), buf.size, null);
-            inline_resource_loaded(cid);
-        } else {
-            request.finish_error(
-                new FileError.NOENT("Unknown CID: %s".printf(cid))
-            );
+        if (!handle_internal_response(request)) {
+            request.finish_error(new FileError.NOENT("Unknown CID"));
         }
     }
 
@@ -395,11 +395,23 @@ public class ClientWebView : WebKit.WebView {
         if (request.get_uri() == INTERNAL_URL_BODY) {
             Geary.Memory.Buffer buf = new Geary.Memory.StringBuffer(this.body);
             request.finish(buf.get_input_stream(), buf.size, null);
-        } else {
+        } else if (!handle_internal_response(request)) {
             request.finish_error(new FileError.NOENT("Unknown internal URL"));
         }
     }
 
+    private bool handle_internal_response(WebKit.URISchemeRequest request) {
+        string name = soup_uri_decode(request.get_path());
+        Geary.Memory.Buffer? buf = this.internal_resources[name];
+        bool handled = false;
+        if (buf != null) {
+            request.finish(buf.get_input_stream(), buf.size, null);
+            internal_resource_loaded(name);
+            handled = true;
+        }
+        return handled;
+    }
+
     // Only allow string-based page loads, and notify but ignore if
     // the user attempts to click on a link. Deny everything else.
     private bool on_decide_policy(WebKit.WebView view,
@@ -454,3 +466,7 @@ public class ClientWebView : WebKit.WebView {
     }
 
 }
+
+// XXX this needs to be moved into the libsoup bindings
+extern string soup_uri_decode(string part);
+
diff --git a/src/client/composer/composer-widget.vala b/src/client/composer/composer-widget.vala
index 1da5624..7650e53 100644
--- a/src/client/composer/composer-widget.vala
+++ b/src/client/composer/composer-widget.vala
@@ -1435,8 +1435,9 @@ public class ComposerWidget : Gtk.EventBox {
         if (this.pending_attachments != null) {
             foreach(Geary.Attachment part in this.pending_attachments) {
                 try {
+                    string? content_id = part.content_id;
                     Geary.Mime.DispositionType? type =
-                    part.content_disposition.disposition_type;
+                        part.content_disposition.disposition_type;
                     File file = part.file;
                     if (type == Geary.Mime.DispositionType.INLINE) {
                         // We only care about the Content Ids of
@@ -1446,11 +1447,10 @@ public class ComposerWidget : Gtk.EventBox {
                         // possible to be referenced from an IMG SRC
                         // using a cid: URL anyway, so treat it as an
                         // attachment instead.
-                        if (part.content_id != null) {
-                            this.cid_files[part.content_id] = file;
-                            this.editor.add_inline_resource(
-                                part.content_id,
-                                new Geary.Memory.FileBuffer(file, true)
+                        if (content_id != null) {
+                            this.cid_files[content_id] = file;
+                            this.editor.add_internal_resource(
+                                content_id, new Geary.Memory.FileBuffer(file, true)
                             );
                         } else {
                             type = Geary.Mime.DispositionType.ATTACHMENT;
diff --git a/src/client/conversation-viewer/conversation-email.vala 
b/src/client/conversation-viewer/conversation-email.vala
index 4ea63f3..e24ff84 100644
--- a/src/client/conversation-viewer/conversation-email.vala
+++ b/src/client/conversation-viewer/conversation-email.vala
@@ -453,7 +453,7 @@ public class ConversationEmail : Gtk.Box {
         }
 
         this.primary_message = new ConversationMessage(message, config, load_images);
-        this.primary_message.web_view.add_inline_resources(cid_resources);
+        this.primary_message.web_view.add_internal_resources(cid_resources);
         connect_message_view_signals(this.primary_message);
 
         this.primary_message.summary.add(this.actions);
@@ -494,7 +494,7 @@ public class ConversationEmail : Gtk.Box {
             ConversationMessage attached_message =
                 new ConversationMessage(sub_message, config, false);
             connect_message_view_signals(attached_message);
-            attached_message.web_view.add_inline_resources(cid_resources);
+            attached_message.web_view.add_internal_resources(cid_resources);
             this.sub_messages.add(attached_message);
             this._attached_messages.add(attached_message);
         }
@@ -627,7 +627,7 @@ public class ConversationEmail : Gtk.Box {
     private void connect_message_view_signals(ConversationMessage view) {
         view.flag_remote_images.connect(on_flag_remote_images);
         view.remember_remote_images.connect(on_remember_remote_images);
-        view.web_view.inline_resource_loaded.connect((id) => {
+        view.web_view.internal_resource_loaded.connect((id) => {
                 this.inlined_content_ids.add(id);
             });
         view.web_view.notify["has-valid-height"].connect(() => {
diff --git a/src/client/conversation-viewer/conversation-message.vala 
b/src/client/conversation-viewer/conversation-message.vala
index 9758abf..86fb187 100644
--- a/src/client/conversation-viewer/conversation-message.vala
+++ b/src/client/conversation-viewer/conversation-message.vala
@@ -707,7 +707,7 @@ public class ConversationMessage : Gtk.Grid {
             id = REPLACED_CID_TEMPLATE.printf(this.next_replaced_buffer_number++);
         }
 
-        this.web_view.add_inline_resource(id, buffer);
+        this.web_view.add_internal_resource(id, buffer);
 
         return "<img alt=\"%s\" class=\"%s\" src=\"%s%s\" />".printf(
             Geary.HTML.escape_markup(filename),
diff --git a/src/client/web-process/web-process-extension.vala 
b/src/client/web-process/web-process-extension.vala
index ac7efc4..1b4980b 100644
--- a/src/client/web-process/web-process-extension.vala
+++ b/src/client/web-process/web-process-extension.vala
@@ -29,10 +29,7 @@ public void webkit_web_extension_initialize_with_user_data(WebKit.WebExtension e
 public class GearyWebExtension : Object {
 
 
-    private const string CID_URL_PREFIX = "cid:";
-    private const string DATA_URL_PREFIX = "data:";
-    private const string INTERNAL_URL_PREFIX = "geary:";
-    private const string INTERNAL_URL_BODY = INTERNAL_URL_PREFIX + "body";
+    private const string[] ALLOWED_SCHEMES = { "cid", "geary", "data" };
 
     private WebKit.WebExtension extension;
 
@@ -64,11 +61,9 @@ public class GearyWebExtension : Object {
                                  WebKit.URIRequest request,
                                  WebKit.URIResponse? response) {
         bool should_load = false;
-        string req_uri = request.get_uri();
-        if (req_uri.has_prefix(CID_URL_PREFIX) ||
-            req_uri.has_prefix(DATA_URL_PREFIX) ||
-            req_uri == INTERNAL_URL_BODY) {
-            // Always load images/resources with these prefixes
+        Soup.URI? uri = new Soup.URI(request.get_uri());
+        if (uri != null && uri.get_scheme() in ALLOWED_SCHEMES) {
+            // Always load internal resources
             should_load = true;
         } else {
             // Only load anything else if remote image loading is


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