[epiphany/mwleeds/webapp-manifest-support] WIP: Copy Sonny's impl for manifest support




commit b29e56b86f1548c88fc51200a252d534b3625a80
Author: Phaedrus Leeds <mwleeds protonmail com>
Date:   Wed Mar 30 11:49:07 2022 -0700

    WIP: Copy Sonny's impl for manifest support

 embed/ephy-web-view.c                            |  53 +++++++++
 embed/ephy-web-view.h                            |   8 ++
 embed/web-process-extension/resources/js/ephy.js |   5 +
 src/window-commands.c                            | 130 +++++++++++++++++++++++
 4 files changed, 196 insertions(+)
---
diff --git a/embed/ephy-web-view.c b/embed/ephy-web-view.c
index d8521a012..8812f1ddd 100644
--- a/embed/ephy-web-view.c
+++ b/embed/ephy-web-view.c
@@ -3506,6 +3506,59 @@ ephy_web_view_get_web_app_title_finish (EphyWebView   *view,
   return g_task_propagate_pointer (G_TASK (result), error);
 }
 
+static void
+get_web_app_manifest_url_cb (WebKitWebView *view,
+                             GAsyncResult  *result,
+                             GTask         *task)
+{
+  WebKitJavascriptResult *js_result;
+  GError *error = NULL;
+
+  js_result = webkit_web_view_run_javascript_in_world_finish (view, result, &error);
+  if (js_result) {
+    JSCValue *js_value;
+    char *retval = NULL;
+
+    js_value = webkit_javascript_result_get_js_value (js_result);
+    if (!jsc_value_is_null (js_value) && !jsc_value_is_undefined (js_value))
+      retval = jsc_value_to_string (js_value);
+    g_task_return_pointer (task, retval, (GDestroyNotify)g_free);
+    webkit_javascript_result_unref (js_result);
+  } else
+    g_task_return_error (task, error);
+
+  g_object_unref (task);
+}
+
+void
+ephy_web_view_get_web_app_manifest_url (EphyWebView         *view,
+                                        GCancellable        *cancellable,
+                                        GAsyncReadyCallback  callback,
+                                        gpointer             user_data)
+{
+  GTask *task;
+
+  g_assert (EPHY_IS_WEB_VIEW (view));
+
+  task = g_task_new (view, cancellable, callback, user_data);
+  webkit_web_view_run_javascript_in_world (WEBKIT_WEB_VIEW (view),
+                                           "Ephy.getWebAppManifestURL();",
+                                           ephy_embed_shell_get_guid (ephy_embed_shell_get_default ()),
+                                           cancellable,
+                                           (GAsyncReadyCallback)get_web_app_manifest_url_cb,
+                                           task);
+}
+
+char *
+ephy_web_view_get_web_app_manifest_url_finish (EphyWebView   *view,
+                                               GAsyncResult  *result,
+                                               GError       **error)
+{
+  g_assert (g_task_is_valid (result, view));
+
+  return g_task_propagate_pointer (G_TASK (result), error);
+}
+
 static void
 get_web_app_mobile_capable_cb (WebKitWebView *view,
                                GAsyncResult  *result,
diff --git a/embed/ephy-web-view.h b/embed/ephy-web-view.h
index 5e45cb861..c4b2bf380 100644
--- a/embed/ephy-web-view.h
+++ b/embed/ephy-web-view.h
@@ -147,6 +147,14 @@ void                       ephy_web_view_get_web_app_title        (EphyWebView
 char                      *ephy_web_view_get_web_app_title_finish (EphyWebView               *view,
                                                                    GAsyncResult              *result,
                                                                    GError                   **error);
+
+void                       ephy_web_view_get_web_app_manifest_url (EphyWebView               *view,
+                                                                   GCancellable              *cancellable,
+                                                                   GAsyncReadyCallback        callback,
+                                                                   gpointer                   user_data);
+char                      *ephy_web_view_get_web_app_manifest_url_finish (EphyWebView               *view,
+                                                                   GAsyncResult              *result,
+                                                                   GError                   **error);
 void                       ephy_web_view_get_web_app_mobile_capable        (EphyWebView         *view,
                                                                             GCancellable        *cancellable,
                                                                             GAsyncReadyCallback  callback,
diff --git a/embed/web-process-extension/resources/js/ephy.js 
b/embed/web-process-extension/resources/js/ephy.js
index 38b806f7a..ea7da8b9e 100644
--- a/embed/web-process-extension/resources/js/ephy.js
+++ b/embed/web-process-extension/resources/js/ephy.js
@@ -18,6 +18,11 @@ Ephy.getAppleMobileWebAppCapable = function()
     return false;
 };
 
+Ephy.getWebAppManifestURL = function () {
+    const manifest = document.head.querySelector("link[rel=manifest]");
+    return manifest ? manifest.href : null;
+}
+
 Ephy.getWebAppTitle = function()
 {
     const metas = document.getElementsByTagName('meta');
diff --git a/src/window-commands.c b/src/window-commands.c
index 8a7e52b91..779aa8447 100644
--- a/src/window-commands.c
+++ b/src/window-commands.c
@@ -23,6 +23,7 @@
 
 #include "config.h"
 
+#include "ephy-web-view.h"
 #include "window-commands.h"
 
 #include "ephy-bookmarks-export.h"
@@ -1389,6 +1390,8 @@ typedef struct {
   EphyWebApplicationOptions webapp_options;
   gboolean webapp_options_set;
   WebKitDownload *download;
+  char *manifest_url;
+  WebKitDownload *download_manifest;
   EphyWindow *window;
 } EphyApplicationDialogData;
 
@@ -1450,6 +1453,13 @@ ephy_application_dialog_data_free (EphyApplicationDialogData *data)
     data->download = NULL;
   }
 
+  if (data->download_manifest) {
+    g_signal_handlers_disconnect_by_func (data->download_manifest, download_manifest_finished_cb, data);
+    g_signal_handlers_disconnect_by_func (data->download_manifest, download_manifest_failed_cb, data);
+
+    data->download = NULL;
+  }
+
   g_cancellable_cancel (data->cancellable);
   g_object_unref (data->cancellable);
   g_object_unref (data->window);
@@ -1458,6 +1468,7 @@ ephy_application_dialog_data_free (EphyApplicationDialogData *data)
   if (data->icon_v)
     g_variant_unref (data->icon_v);
   g_free (data->icon_href);
+  g_free (data->manifest_url);
   g_free (data->title);
   g_free (data->chosen_name);
   g_free (data->token);
@@ -1774,6 +1785,122 @@ fill_default_application_title_cb (GObject      *source,
     ephy_application_dialog_data_free (data);
 }
 
+
+static void
+download_manifest_finished_cb (WebKitDownload            *download,
+                      EphyApplicationDialogData *data)
+{
+  char *filename;
+  GError *error = NULL;
+  JsonParser *parser = json_parser_new();
+  JsonNode *root;
+  JsonObject *manifest_object;
+  char *name;
+  char *short_name;
+
+  filename = g_filename_from_uri (webkit_download_get_destination (download), NULL, NULL);
+  json_parser_load_from_file(parser, filename, &error);
+  g_free (filename);
+  if (error) {
+    g_warning ("Unable to parse manifest");
+    g_error_free (error);
+    g_object_unref (parser);
+    return;
+  }
+
+  root = json_parser_get_root (parser);
+  manifest_object = json_node_get_object(root);
+
+  name = json_object_get_string_member(manifest_object, "name");
+  short_name = json_object_get_string_member(manifest_object, "short_name");
+
+  if (short_name) {
+    g_message (short_name);
+    // data->name = short_name;
+  } else if (name) {
+    g_message (name);
+    // data->name = name;
+  }
+
+  g_free (name);
+  g_free (short_name);
+
+  g_object_unref (parser);
+}
+
+static void
+download_manifest_failed_cb (WebKitDownload            *download,
+                    GError                    *error,
+                    EphyApplicationDialogData *data)
+{
+  g_warning("failed");
+
+  g_signal_handlers_disconnect_by_func (download, download_manifest_finished_cb, data);
+
+  // TODO fallback to ephy.js stuff
+}
+
+static void
+download_and_use_manifest (EphyApplicationDialogData *data)
+{
+  char *destination, *destination_uri, *tmp_filename;
+  EphyEmbedShell *shell = ephy_embed_shell_get_default ();
+
+  data->download_manifest = webkit_web_context_download_uri (ephy_embed_shell_get_web_context (shell),
+                                                    data->manifest_url);
+  /* We do not want this download to show up in the UI, so let's
+   * set 'ephy-download-set' to make Epiphany think this is
+   * already there. */
+  /* FIXME: it's probably better to just do this in a clean way
+   * instead of using this workaround. */
+  g_object_set_data (G_OBJECT (data->download_manifest), "ephy-download-set", GINT_TO_POINTER (TRUE));
+  tmp_filename = ephy_file_tmp_filename (".ephy-download-XXXXXX", NULL);
+  destination = g_build_filename (ephy_file_tmp_dir (), tmp_filename, NULL);
+  destination_uri = g_filename_to_uri (destination, NULL, NULL);
+  g_message("%s", destination_uri);
+  webkit_download_set_destination (data->download_manifest, destination_uri);
+  g_free (destination);
+  g_free (destination_uri);
+  g_free (tmp_filename);
+
+  g_message("foobar!");
+
+
+  g_signal_connect (data->download_manifest, "finished",
+                    G_CALLBACK (download_manifest_finished_cb), data);
+  g_signal_connect (data->download_manifest, "failed",
+                    G_CALLBACK (download_manifest_failed_cb), data);
+}
+
+static void
+got_manifest_url_cb (GObject      *source,
+                     GAsyncResult *async_result,
+                     gpointer     user_data)
+{
+  EphyApplicationDialogData *data = user_data;
+  char *manifest_url;
+  GError *error = NULL;
+
+  manifest_url = ephy_web_view_get_web_app_manifest_url_finish (EPHY_WEB_VIEW (source), async_result, 
&error);
+  g_message("%s", manifest_url);
+
+  if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+    return;
+
+  data->manifest_url = manifest_url;
+  g_message("%s", manifest_url);
+  if (data->manifest_url != NULL)
+    download_and_use_manifest (data);
+
+  // TODO: fallback to ephy.js stuff
+}
+
+static void
+do_something_with_manifest (EphyApplicationDialogData *data)
+{
+  ephy_web_view_get_web_app_manifest_url (data->view, data->cancellable, got_manifest_url_cb, data);
+}
+
 static void
 fill_mobile_capable_cb (GObject      *source,
                         GAsyncResult *async_result,
@@ -1957,6 +2084,9 @@ window_cmd_save_as_application (GSimpleAction *action,
   ephy_web_view_get_best_web_app_icon (data->view, data->cancellable, fill_default_application_image_cb, 
data);
   ephy_web_view_get_web_app_title (data->view, data->cancellable, fill_default_application_title_cb, data);
   ephy_web_view_get_web_app_mobile_capable (data->view, data->cancellable, fill_mobile_capable_cb, data);
+  //TODO is this right
+  do_something_with_manifest (data);
+
 }
 
 static char *


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