[epiphany/wip/sync: 44/52] prefs-dialog: Use a helper function to parse WebChannelMessageToChrome



commit f9a39e83f057af1beaaa9a79923b0cc5ddc1b6e9
Author: Gabriel Ivascu <ivascu gabriel59 gmail com>
Date:   Tue Jun 13 17:20:41 2017 +0300

    prefs-dialog: Use a helper function to parse WebChannelMessageToChrome

 src/prefs-dialog.c |  260 ++++++++++++++++++++++++++++++++-------------------
 1 files changed, 163 insertions(+), 97 deletions(-)
---
diff --git a/src/prefs-dialog.c b/src/prefs-dialog.c
index d5f62af..63e8af5 100644
--- a/src/prefs-dialog.c
+++ b/src/prefs-dialog.c
@@ -345,7 +345,7 @@ sync_secrets_store_finished_cb (EphySyncService *service,
 
 static void
 sync_message_to_fxa_content (PrefsDialog *dialog,
-                             const char  *channel_id,
+                             const char  *web_channel_id,
                              const char  *command,
                              const char  *message_id,
                              JsonObject  *data)
@@ -357,12 +357,18 @@ sync_message_to_fxa_content (PrefsDialog *dialog,
   char *script;
   const char *type;
 
+  g_assert (EPHY_IS_PREFS_DIALOG (dialog));
+  g_assert (web_channel_id);
+  g_assert (command);
+  g_assert (message_id);
+  g_assert (data);
+
   message = json_object_new ();
   json_object_set_string_member (message, "command", command);
   json_object_set_string_member (message, "messageId", message_id);
   json_object_set_object_member (message, "data", json_object_ref (data));
   detail = json_object_new ();
-  json_object_set_string_member (detail, "id", channel_id);
+  json_object_set_string_member (detail, "id", web_channel_id);
   json_object_set_object_member (detail, "message", message);
   node = json_node_new (JSON_NODE_OBJECT);
   json_node_set_object (node, detail);
@@ -382,127 +388,187 @@ sync_message_to_fxa_content (PrefsDialog *dialog,
   json_node_unref (node);
 }
 
-static void
-sync_message_from_fxa_content_cb (WebKitUserContentManager *manager,
-                                  WebKitJavascriptResult   *result,
-                                  PrefsDialog              *dialog)
+static gboolean
+sync_parse_message_from_fxa_content (const char  *message,
+                                     char       **web_channel_id,
+                                     char       **message_id,
+                                     char       **command,
+                                     JsonObject **data,
+                                     char       **error_msg)
 {
-  JsonNode *node = NULL;
-  JsonObject *json = NULL;
-  JsonObject *detail = NULL;
-  JsonObject *message = NULL;
-  JsonObject *data = NULL;
-  GError *error = NULL;
-  char *json_string = NULL;
+  JsonNode *node;
+  JsonObject *object;
+  JsonObject *detail;
+  JsonObject *msg;
+  JsonObject *msg_data = NULL;
   const char *type;
-  const char *command;
-  const char *email;
-  const char *uid;
-  const char *session_token;
-  const char *key_fetch_token;
-  const char *unwrap_kb;
-
-  json_string = ephy_embed_utils_get_js_result_as_string (result);
-  if (!json_string) {
-    g_warning ("Failed to get JavaScript result as string");
+  const char *channel_id;
+  const char *cmd;
+  const char *error = NULL;
+  gboolean success = FALSE;
+
+  g_assert (message);
+  g_assert (web_channel_id);
+  g_assert (message_id);
+  g_assert (command);
+  g_assert (data);
+  g_assert (error_msg);
+
+  /* Expected message format is:
+   * {
+   *   type: "WebChannelMessageToChrome",
+   *   detail: {
+   *     id: <id> (string, the id of the WebChannel),
+   *     message: {
+   *       messageId: <messageId> (optional string, the message id),
+   *       command: <command> (string, the message command),
+   *       data: <data> (optional JSON object, the message data)
+   *     }
+   *   }
+   * }
+   */
+
+  node = json_from_string (message, NULL);
+  if (!node) {
+    error = "Message is not a valid JSON";
     goto out_error;
   }
-  node = json_from_string (json_string, &error);
-  if (error) {
-    g_warning ("Response is not a valid JSON: %s", error->message);
+  object = json_node_get_object (node);
+  if (!object) {
+    error = "Message is not a JSON object";
     goto out_error;
   }
-  json = json_node_get_object (node);
-  if (!json) {
-    g_warning ("JSON node does not hold a JSON object");
-    goto out_error;
-  }
-  type = json_object_get_string_member (json, "type");
+  type = json_object_get_string_member (object, "type");
   if (!type) {
-    g_warning ("JSON object has missing or invalid 'type' member");
+    error = "Message has missing or invalid 'type' member";
     goto out_error;
-  }
-  /* The only message type expected is WebChannelMessageToChrome. */
-  if (g_strcmp0 (type, "WebChannelMessageToChrome")) {
-    g_warning ("Unknown command type: %s", type);
+  } else if (strcmp (type, "WebChannelMessageToChrome")) {
+    error = "Message type is not WebChannelMessageToChrome";
     goto out_error;
   }
-  detail = json_object_get_object_member (json, "detail");
+  detail = json_object_get_object_member (object, "detail");
   if (!detail) {
-    g_warning ("JSON object has missing or invalid 'detail' member");
+    error = "Message has missing or invalid 'detail' member";
     goto out_error;
   }
-  message = json_object_get_object_member (detail, "message");
-  if (!message) {
-    g_warning ("JSON object has missing or invalid 'message' member");
+  channel_id = json_object_get_string_member (detail, "id");
+  if (!channel_id) {
+    error = "'Detail' object has missing or invalid 'id' member";
     goto out_error;
   }
-  command = json_object_get_string_member (message, "command");
-  if (!command) {
-    g_warning ("JSON object has missing or invalid 'command' member");
+  msg = json_object_get_object_member (detail, "message");
+  if (!msg) {
+    error = "'Detail' object has missing or invalid 'message' member";
     goto out_error;
   }
-
-  if (!g_strcmp0 (command, "fxaccounts:loaded")) {
-    LOG ("Firefox Accounts iframe loaded");
-    goto out_no_error;
-  }
-  if (!g_strcmp0 (command, "fxaccounts:can_link_account")) {
-    /* We need to confirm a relink. */
-    data = json_object_new ();
-    json_object_set_boolean_member (data, "ok", TRUE);
-    sync_message_to_fxa_content (dialog,
-                                 json_object_get_string_member (detail, "id"),
-                                 "fxaccounts:can_link_account",
-                                 json_object_get_string_member (message, "messageId"),
-                                 data);
-    json_object_unref (data);
-    goto out_no_error;
-  }
-  if (g_strcmp0 (command, "fxaccounts:login")) {
-    g_warning ("Unexepected command: %s", command);
+  cmd = json_object_get_string_member (msg, "command");
+  if (!cmd) {
+    error = "'Message' object has missing or invalid 'command' member";
     goto out_error;
   }
 
-  /* Login command. */
-  gtk_widget_set_visible (dialog->sync_firefox_iframe_label, FALSE);
+  *web_channel_id = g_strdup (channel_id);
+  *command = g_strdup (cmd);
+  *message_id = json_object_has_member (msg, "messageId") ?
+                g_strdup (json_object_get_string_member (msg, "messageId")) :
+                NULL;
+  if (json_object_has_member (msg, "data"))
+    msg_data = json_object_get_object_member (msg, "data");
+  *data = msg_data ? json_object_ref (msg_data) : NULL;
+
+  success = TRUE;
+  *error_msg = NULL;
+  goto out_no_error;
 
-  data = json_object_get_object_member (message, "data");
-  if (!data) {
-    g_warning ("JSON object has invalid 'data' member");
-    goto out_error;
+out_error:
+  *web_channel_id = NULL;
+  *command = NULL;
+  *message_id = NULL;
+  *error_msg = g_strdup (error);
+
+out_no_error:
+  json_node_unref (node);
+
+  return success;
+}
+
+static void
+sync_message_from_fxa_content_cb (WebKitUserContentManager *manager,
+                                  WebKitJavascriptResult   *result,
+                                  PrefsDialog              *dialog)
+{
+  JsonObject *data = NULL;
+  char *message = NULL;
+  char *web_channel_id = NULL;
+  char *message_id = NULL;
+  char *command = NULL;
+  char *error_msg = NULL;
+  gboolean is_error = FALSE;
+
+  message = ephy_embed_utils_get_js_result_as_string (result);
+  if (!message) {
+    g_warning ("Failed to get JavaScript result as string");
+    is_error = TRUE;
+    goto out;
   }
-  email = json_object_get_string_member (data, "email");
-  uid = json_object_get_string_member (data, "uid");
-  session_token = json_object_get_string_member (data, "sessionToken");
-  key_fetch_token = json_object_get_string_member (data, "keyFetchToken");
-  unwrap_kb = json_object_get_string_member (data, "unwrapBKey");
-  if (!email || !uid || !session_token || !key_fetch_token || !unwrap_kb) {
-    g_warning ("JSON object has missing or invalid members");
-    goto out_error;
+
+  if (!sync_parse_message_from_fxa_content (message, &web_channel_id,
+                                            &message_id, &command,
+                                            &data, &error_msg)) {
+    g_warning ("Failed to parse message from FxA Content Server: %s", error_msg);
+    is_error = TRUE;
+    goto out;
   }
-  if (!json_object_has_member (data, "verified") ||
-      !JSON_NODE_HOLDS_VALUE (json_object_get_member (data, "verified"))) {
-    g_warning ("JSON object has missing or invalid 'verified' member");
-    goto out_error;
+
+  LOG ("WebChannelMessageToChrome: received %s command", command);
+
+  if (!g_strcmp0 (command, "fxaccounts:can_link_account")) {
+    /* Confirm a relink. Respond with {ok: true}. */
+    JsonObject *response = json_object_new ();
+    json_object_set_boolean_member (response, "ok", TRUE);
+    sync_message_to_fxa_content (dialog, web_channel_id, command, message_id, response);
+    json_object_unref (response);
+  } else if (!g_strcmp0 (command, "fxaccounts:login")) {
+    /* Extract sync tokens and pass them to the sync service. */
+    const char *email = json_object_get_string_member (data, "email");
+    const char *uid = json_object_get_string_member (data, "uid");
+    const char *session_token = json_object_get_string_member (data, "sessionToken");
+    const char *key_fetch_token = json_object_get_string_member (data, "keyFetchToken");
+    const char *unwrap_kb = json_object_get_string_member (data, "unwrapBKey");
+
+    if (!email || !uid || !session_token || !key_fetch_token || !unwrap_kb) {
+      g_warning ("Message data has missing or invalid members");
+      is_error = TRUE;
+      goto out;
+    }
+    if (!json_object_has_member (data, "verified") ||
+        !JSON_NODE_HOLDS_VALUE (json_object_get_member (data, "verified"))) {
+      g_warning ("Message data has missing or invalid 'verified' member");
+      is_error = TRUE;
+      goto out;
+    }
+
+    if (!json_object_get_boolean_member (data, "verified"))
+      sync_sign_in_details_show (dialog, _("Please don’t leave this page until "
+                                           "you have completed the verification."));
+
+    ephy_sync_service_sign_in (dialog->sync_service, email, uid,
+                               session_token, key_fetch_token, unwrap_kb);
   }
 
-  if (!json_object_get_boolean_member (data, "verified"))
-    sync_sign_in_details_show (dialog, _("Please don’t leave this page until "
-                                         "you have completed the verification."));
-  ephy_sync_service_sign_in (dialog->sync_service, email, uid,
-                             session_token, key_fetch_token, unwrap_kb);
-  goto out_no_error;
+out:
+  if (data)
+    json_object_unref (data);
+  g_free (message);
+  g_free (web_channel_id);
+  g_free (message_id);
+  g_free (command);
+  g_free (error_msg);
 
-out_error:
-  sync_sign_in_details_show (dialog, _("Something went wrong, please try again."));
-  webkit_web_view_load_uri (dialog->fxa_web_view, FXA_IFRAME_URL);
-out_no_error:
-  if (node)
-    json_node_unref (node);
-  if (error)
-    g_error_free (error);
-  g_free (json_string);
+  if (is_error) {
+    sync_sign_in_details_show (dialog, _("Something went wrong, please try again later."));
+    webkit_web_view_load_uri (dialog->fxa_web_view, FXA_IFRAME_URL);
+  }
 }
 
 static void


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