[epiphany] Use EphyDownload for pdf.js support



commit 316966bb7a8501149322c14b3371e7548006adda
Author: Jan-Michael Brummer <jan brummer tabos org>
Date:   Sun Jan 19 13:59:42 2020 +0100

    Use EphyDownload for pdf.js support
    
    Fixes: https://gitlab.gnome.org/GNOME/epiphany/issues/1059

 embed/ephy-embed-shell.c |  15 +++++-
 embed/ephy-embed.c       | 134 +++++++++++++++++++++++++++++++++++++++++++++++
 embed/ephy-embed.h       |   2 +
 embed/ephy-web-view.c    |  67 ------------------------
 4 files changed, 150 insertions(+), 68 deletions(-)
---
diff --git a/embed/ephy-embed-shell.c b/embed/ephy-embed-shell.c
index 213411e54..9b4c1f712 100644
--- a/embed/ephy-embed-shell.c
+++ b/embed/ephy-embed-shell.c
@@ -776,6 +776,7 @@ download_started_cb (WebKitWebContext *web_context,
   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,
@@ -794,7 +795,19 @@ download_started_cb (WebKitWebContext *web_context,
     return;
 
   ephy_download = ephy_download_new (download);
-  ephy_downloads_manager_add_download (priv->downloads_manager, ephy_download);
+
+  web_view = webkit_download_get_web_view (download);
+  if (EPHY_IS_WEB_VIEW (web_view)) {
+    EphyEmbed *embed;
+
+    embed = EPHY_GET_EMBED_FROM_EPHY_WEB_VIEW (web_view);
+    ephy_embed_download_started (embed, ephy_download);
+
+    if (!ephy_web_view_in_pdf_viewer (EPHY_WEB_VIEW (web_view)))
+      ephy_downloads_manager_add_download (priv->downloads_manager, ephy_download);
+  } else {
+    ephy_downloads_manager_add_download (priv->downloads_manager, ephy_download);
+  }
 }
 
 static void
diff --git a/embed/ephy-embed.c b/embed/ephy-embed.c
index aaaa5e159..208730764 100644
--- a/embed/ephy-embed.c
+++ b/embed/ephy-embed.c
@@ -996,3 +996,137 @@ ephy_embed_detach_notification_container (EphyEmbed *embed)
     gtk_container_remove (GTK_CONTAINER (embed->overlay), g_object_ref (GTK_WIDGET (container)));
   }
 }
+
+typedef struct {
+  char *document_uri;
+  char *remote_uri;
+  WebKitDownload *download;
+  EphyWebView *web_view;
+} PdfAsyncData;
+
+static PdfAsyncData *
+pdf_async_data_new (const char  *document_uri,
+                    const char  *remote_uri,
+                    EphyWebView *web_view)
+{
+  PdfAsyncData *data;
+
+  data = g_new0 (PdfAsyncData, 1);
+  data->document_uri = g_strdup (document_uri);
+  data->remote_uri = g_strdup (remote_uri);
+  data->web_view = web_view;
+
+  if (web_view)
+    g_object_add_weak_pointer (G_OBJECT (web_view), (gpointer *)&data->web_view);
+
+  return data;
+}
+
+static void
+pdf_async_data_free (PdfAsyncData *data)
+{
+  if (data->web_view)
+    g_object_remove_weak_pointer (G_OBJECT (data->web_view), (gpointer *)&data->web_view);
+
+  g_free (data->document_uri);
+  g_free (data->remote_uri);
+  g_free (data);
+}
+
+static void
+pdf_file_deleted (GObject      *source,
+                  GAsyncResult *res,
+                  gpointer      user_data)
+{
+  g_autoptr (GError) error = NULL;
+  if (!g_file_delete_finish (G_FILE (source), res, &error))
+    g_warning ("Could not delete temporary PDF file: %s", error->message);
+}
+
+static void
+pdf_file_loaded (GObject      *source,
+                 GAsyncResult *res,
+                 gpointer      user_data)
+{
+  PdfAsyncData *data = user_data;
+  WebKitWebView *web_view = WEBKIT_WEB_VIEW (data->web_view);
+  GBytes *html_file;
+  g_autoptr (GError) error = NULL;
+  g_autoptr (GString) html = NULL;
+  g_autofree gchar *b64 = NULL;
+  g_autofree gchar *requested_uri = NULL;
+  g_autofree char *file_data = NULL;
+  gsize len = 0;
+
+  if (!g_file_load_contents_finish (G_FILE (source), res, &file_data, &len, NULL, &error)) {
+    g_warning ("Could not read PDF file content: %s", error->message);
+    pdf_async_data_free (data);
+    return;
+  }
+
+  html_file = g_resources_lookup_data ("/org/gnome/epiphany/pdfjs/web/viewer.html", 0, NULL);
+
+  b64 = g_base64_encode ((const guchar *)file_data, len);
+  g_file_delete_async (G_FILE (source), G_PRIORITY_DEFAULT, NULL, pdf_file_deleted, NULL);
+
+  html = g_string_new ("");
+  g_string_printf (html, g_bytes_get_data (html_file, NULL), b64, g_path_get_basename (data->remote_uri));
+
+  webkit_web_view_load_alternate_html (web_view, html->str, data->remote_uri, 
"ephy-resource:///org/gnome/epiphany/pdfjs/web/");
+
+  /* FIXME: Necessary WebKit API to access security level (TLS certificate) of a download is not
+   * available. Please fix this line once available.
+   */
+  ephy_web_view_set_security_level (data->web_view, EPHY_SECURITY_LEVEL_LOCAL_PAGE);
+
+  pdf_async_data_free (data);
+}
+
+static void
+pdf_download_finished_cb (WebKitDownload *download,
+                          EphyEmbed      *embed)
+{
+  EphyWebView *view = ephy_embed_get_web_view (embed);
+  WebKitURIRequest *request = webkit_download_get_request (download);
+  g_autoptr (GFile) file = NULL;
+  PdfAsyncData *pdf_data;
+  const char *document_uri = webkit_download_get_destination (download);
+  const char *remote_uri = webkit_uri_request_get_uri (request);
+
+  file = g_file_new_for_uri (document_uri);
+
+  pdf_data = pdf_async_data_new (document_uri, remote_uri, view);
+  g_file_load_contents_async (file, NULL, pdf_file_loaded, pdf_data);
+}
+
+static gboolean
+pdf_download_decide_destination_cb (WebKitDownload *wk_download,
+                                    gchar          *suggested_filename,
+                                    gpointer        user_data)
+{
+  EphyWebView *web_view = ephy_embed_get_web_view (EPHY_EMBED (user_data));
+
+  if (ephy_web_view_in_pdf_viewer (web_view)) {
+    g_autofree gchar *tmp_file = g_strdup_printf ("%s/%s", g_get_tmp_dir (), suggested_filename);
+    g_autofree gchar *file_uri = g_filename_to_uri (tmp_file, NULL, NULL);
+
+    webkit_download_set_allow_overwrite (wk_download, TRUE);
+    webkit_download_set_destination (wk_download, file_uri);
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+void
+ephy_embed_download_started (EphyEmbed    *embed,
+                             EphyDownload *ephy_download)
+{
+  EphyWebView *web_view = ephy_embed_get_web_view (embed);
+  WebKitDownload *download = ephy_download_get_webkit_download (ephy_download);
+
+  if (ephy_web_view_in_pdf_viewer (web_view)) {
+    g_signal_connect_object (download, "finished", G_CALLBACK (pdf_download_finished_cb), embed, 0);
+    g_signal_connect_object (download, "decide-destination", G_CALLBACK 
(pdf_download_decide_destination_cb), embed, 0);
+  }
+}
diff --git a/embed/ephy-embed.h b/embed/ephy-embed.h
index 919a6d366..5004bffcd 100644
--- a/embed/ephy-embed.h
+++ b/embed/ephy-embed.h
@@ -54,5 +54,7 @@ gboolean         ephy_embed_inspector_is_loaded           (EphyEmbed *embed);
 const char      *ephy_embed_get_title                     (EphyEmbed *embed);
 void             ephy_embed_attach_notification_container (EphyEmbed *embed);
 void             ephy_embed_detach_notification_container (EphyEmbed *embed);
+void             ephy_embed_download_started              (EphyEmbed    *embed,
+                                                           EphyDownload *ephy_download);
 
 G_END_DECLS
diff --git a/embed/ephy-web-view.c b/embed/ephy-web-view.c
index ebe28e15a..49f59f9b7 100644
--- a/embed/ephy-web-view.c
+++ b/embed/ephy-web-view.c
@@ -858,68 +858,6 @@ ephy_web_view_style_updated (GtkWidget *web_view)
   webkit_web_view_set_background_color (WEBKIT_WEB_VIEW (web_view), &color);
 }
 
-/**
- * TODO: Please note that we are currently making use of soup function to download
- * the requested pdf file. This is due to an issue with EphyDownload emitting download
- * finished signal before the file really exists in 50% of the cases. That
- * would lead to a very bad pdf experience therefore we are using soup.
- * Please switch to EphyDownload as soon as the issue is fixed.
- */
-static void
-pdf_loaded (SoupSession *session,
-            SoupMessage *msg,
-            gpointer     user_data)
-{
-  WebKitWebView *web_view = WEBKIT_WEB_VIEW (user_data);
-  EphyWebView *view = EPHY_WEB_VIEW (web_view);
-  GBytes *html_file;
-  g_autoptr (GString) html = NULL;
-  g_autofree gchar *b64 = NULL;
-  SoupURI *uri = NULL;
-  g_autofree gchar *requested_uri = NULL;
-
-  if (msg->status_code != 200) {
-    g_warning ("PDF file could not be loaded, got status code %d\n", msg->status_code);
-    return;
-  }
-
-  html_file = g_resources_lookup_data ("/org/gnome/epiphany/pdfjs/web/viewer.html", 0, NULL);
-  b64 = g_base64_encode ((const guchar *)msg->response_body->data, msg->response_body->length);
-
-  uri = soup_message_get_uri (msg);
-
-  html = g_string_new ("");
-  g_string_printf (html, g_bytes_get_data (html_file, NULL), b64, g_path_get_basename (uri->path));
-  requested_uri = soup_uri_to_string (uri, FALSE);
-
-  /* FIXME: Remove this, and remove the hack from update_security_status_for_committed_load(),
-   * when we switch from SoupSession to EphyDownload.
-   *
-   * We are using SoupSession directly, bypassing WebKit's functionality for ignoring
-   * TLS certificate errors, so we should be guaranteed there are no security issues
-   */
-  if (!strcmp (SOUP_URI_SCHEME_HTTPS, soup_uri_get_scheme (uri)))
-    ephy_web_view_set_security_level (view, EPHY_SECURITY_LEVEL_STRONG_SECURITY);
-  else
-    ephy_web_view_set_security_level (view, EPHY_SECURITY_LEVEL_TO_BE_DETERMINED);
-
-  webkit_web_view_load_alternate_html (web_view, html->str, requested_uri, 
"ephy-resource:///org/gnome/epiphany/pdfjs/web/");
-
-  g_object_unref (session);
-}
-
-static void
-load_pdf (WebKitWebView *web_view,
-          const gchar   *request_uri)
-{
-  SoupSession *session = soup_session_new ();
-  SoupMessage *msg;
-
-  msg = soup_message_new ("GET", request_uri);
-
-  soup_session_queue_message (session, g_steal_pointer (&msg), pdf_loaded, web_view);
-}
-
 static gboolean
 ephy_web_view_decide_policy (WebKitWebView            *web_view,
                              WebKitPolicyDecision     *decision,
@@ -946,11 +884,6 @@ ephy_web_view_decide_policy (WebKitWebView            *web_view,
     EphyWebView *view = EPHY_WEB_VIEW (web_view);
 
     view->in_pdf_viewer = TRUE;
-    webkit_policy_decision_ignore (decision);
-
-    load_pdf (web_view, request_uri);
-
-    return FALSE;
   }
 
   /* If WebKit can't handle the mime type start the download


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