Commit e601bdc8 authored by Gabriel Ivașcu's avatar Gabriel Ivașcu Committed by Michael Catanzaro

sync-service: Notify the user to sign in with the new password

parent ef1f9043
......@@ -92,7 +92,7 @@ AM_CONDITIONAL([ENABLE_TESTS],[test "$enable_tests" = "yes"])
# Dependencies
# ************
LIBGD_INIT([_view-common static])
LIBGD_INIT([_view-common notification static])
LT_LIB_M
......
......@@ -40,8 +40,12 @@ libephyembed_la_SOURCES = \
ephy-file-monitor.h \
ephy-find-toolbar.c \
ephy-find-toolbar.h \
ephy-fx-password-notification.c \
ephy-fx-password-notification.h \
ephy-hosts-manager.c \
ephy-hosts-manager.h \
ephy-notification-manager.c \
ephy-notification-manager.h \
ephy-view-source-handler.c \
ephy-view-source-handler.h \
ephy-web-view.c \
......@@ -63,6 +67,7 @@ libephyembed_la_CPPFLAGS = \
-I$(top_srcdir)/lib/egg \
-I$(top_srcdir)/lib/history \
-I$(top_srcdir)/lib/widgets \
-I$(top_srcdir)/libgd \
-DPKGDATADIR=\"$(pkgdatadir)\" \
-DEPHY_WEB_EXTENSIONS_DIR=\"$(pkglibdir)/web-extensions\" \
$(GDK_CFLAGS) \
......
......@@ -28,6 +28,7 @@
#include "ephy-embed-shell.h"
#include "ephy-embed-utils.h"
#include "ephy-find-toolbar.h"
#include "ephy-notification-manager.h"
#include "ephy-prefs.h"
#include "ephy-settings.h"
#include "ephy-string.h"
......@@ -59,6 +60,7 @@ struct _EphyEmbed {
GtkPaned *paned;
WebKitWebView *web_view;
GSList *destroy_on_transition_list;
GtkWidget *overlay;
GtkWidget *floating_bar;
GtkWidget *progress;
GtkWidget *fullscreen_message_label;
......@@ -697,7 +699,6 @@ ephy_embed_constructed (GObject *object)
EphyEmbedShell *shell = ephy_embed_shell_get_default ();
GtkWidget *paned;
WebKitWebInspector *inspector;
GtkWidget *overlay;
g_signal_connect (shell, "window-restored",
G_CALLBACK (ephy_embed_restored_window_cb), embed);
......@@ -706,12 +707,12 @@ ephy_embed_constructed (GObject *object)
G_CALLBACK (ephy_embed_mapped_cb), NULL);
/* Skeleton */
overlay = gtk_overlay_new ();
embed->overlay = gtk_overlay_new ();
gtk_widget_add_events (overlay,
gtk_widget_add_events (embed->overlay,
GDK_ENTER_NOTIFY_MASK |
GDK_LEAVE_NOTIFY_MASK);
gtk_container_add (GTK_CONTAINER (overlay), GTK_WIDGET (embed->web_view));
gtk_container_add (GTK_CONTAINER (embed->overlay), GTK_WIDGET (embed->web_view));
/* Floating message popup for fullscreen mode. */
embed->fullscreen_message_label = gtk_label_new (NULL);
......@@ -719,7 +720,7 @@ ephy_embed_constructed (GObject *object)
gtk_widget_set_halign (embed->fullscreen_message_label, GTK_ALIGN_CENTER);
gtk_widget_set_valign (embed->fullscreen_message_label, GTK_ALIGN_CENTER);
gtk_widget_set_no_show_all (embed->fullscreen_message_label, TRUE);
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), embed->fullscreen_message_label);
gtk_overlay_add_overlay (GTK_OVERLAY (embed->overlay), embed->fullscreen_message_label);
ephy_embed_set_fullscreen_message (embed, FALSE);
/* statusbar is hidden by default */
......@@ -728,14 +729,14 @@ ephy_embed_constructed (GObject *object)
gtk_widget_set_valign (embed->floating_bar, GTK_ALIGN_END);
gtk_widget_set_no_show_all (embed->floating_bar, TRUE);
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), embed->floating_bar);
gtk_overlay_add_overlay (GTK_OVERLAY (embed->overlay), embed->floating_bar);
embed->progress = gtk_progress_bar_new ();
gtk_style_context_add_class (gtk_widget_get_style_context (embed->progress),
GTK_STYLE_CLASS_OSD);
gtk_widget_set_halign (embed->progress, GTK_ALIGN_FILL);
gtk_widget_set_valign (embed->progress, GTK_ALIGN_START);
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), embed->progress);
gtk_overlay_add_overlay (GTK_OVERLAY (embed->overlay), embed->progress);
embed->find_toolbar = ephy_find_toolbar_new (embed->web_view);
g_signal_connect (embed->find_toolbar, "close",
......@@ -750,7 +751,7 @@ ephy_embed_constructed (GObject *object)
embed->progress_update_handler_id = g_signal_connect (embed->web_view, "notify::estimated-load-progress",
G_CALLBACK (progress_update), object);
gtk_paned_pack1 (GTK_PANED (paned), GTK_WIDGET (overlay),
gtk_paned_pack1 (GTK_PANED (paned), GTK_WIDGET (embed->overlay),
TRUE, FALSE);
gtk_box_pack_start (GTK_BOX (embed),
......@@ -946,3 +947,28 @@ ephy_embed_inspector_is_loaded (EphyEmbed *embed)
return embed->inspector_loaded;
}
void
ephy_embed_attach_notification_manager (EphyEmbed *embed)
{
EphyNotificationManager *manager;
g_return_if_fail (EPHY_IS_EMBED (embed));
manager = ephy_notification_manager_dup_singleton ();
gtk_overlay_add_overlay (GTK_OVERLAY (embed->overlay), GTK_WIDGET (manager));
if (ephy_notification_manager_get_children_num (manager) == 0)
gtk_widget_hide (GTK_WIDGET (manager));
}
void
ephy_embed_detach_notification_manager (EphyEmbed *embed)
{
EphyNotificationManager *manager;
g_return_if_fail (EPHY_IS_EMBED (embed));
manager = ephy_notification_manager_dup_singleton ();
gtk_container_remove (GTK_CONTAINER (embed->overlay), GTK_WIDGET (manager));
}
......@@ -30,20 +30,22 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (EphyEmbed, ephy_embed, EPHY, EMBED, GtkBox)
EphyWebView* ephy_embed_get_web_view (EphyEmbed *embed);
EphyFindToolbar* ephy_embed_get_find_toolbar (EphyEmbed *embed);
void ephy_embed_add_top_widget (EphyEmbed *embed,
GtkWidget *widget,
gboolean destroy_on_transition);
void ephy_embed_remove_top_widget (EphyEmbed *embed,
GtkWidget *widget);
void ephy_embed_entering_fullscreen (EphyEmbed *embed);
void ephy_embed_leaving_fullscreen (EphyEmbed *embed);
void ephy_embed_set_delayed_load_request (EphyEmbed *embed,
WebKitURIRequest *request,
WebKitWebViewSessionState *state);
gboolean ephy_embed_has_load_pending (EphyEmbed *embed);
gboolean ephy_embed_inspector_is_loaded (EphyEmbed *embed);
const char *ephy_embed_get_title (EphyEmbed *embed);
EphyWebView* ephy_embed_get_web_view (EphyEmbed *embed);
EphyFindToolbar* ephy_embed_get_find_toolbar (EphyEmbed *embed);
void ephy_embed_add_top_widget (EphyEmbed *embed,
GtkWidget *widget,
gboolean destroy_on_transition);
void ephy_embed_remove_top_widget (EphyEmbed *embed,
GtkWidget *widget);
void ephy_embed_entering_fullscreen (EphyEmbed *embed);
void ephy_embed_leaving_fullscreen (EphyEmbed *embed);
void ephy_embed_set_delayed_load_request (EphyEmbed *embed,
WebKitURIRequest *request,
WebKitWebViewSessionState *state);
gboolean ephy_embed_has_load_pending (EphyEmbed *embed);
gboolean ephy_embed_inspector_is_loaded (EphyEmbed *embed);
const char *ephy_embed_get_title (EphyEmbed *embed);
void ephy_embed_attach_notification_manager (EphyEmbed *embed);
void ephy_embed_detach_notification_manager (EphyEmbed *embed);
G_END_DECLS
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* Copyright © 2016 Gabriel Ivascu <ivascu.gabriel59@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "ephy-fx-password-notification.h"
#include "ephy-notification-manager.h"
#include <glib/gi18n.h>
struct _EphyFxPasswordNotification {
GtkGrid parent_instance;
GtkWidget *note;
GtkWidget *suggestion;
const char *user;
};
struct _EphyFxPasswordNotificationClass {
GtkGridClass parent_class;
};
enum {
PROP_0,
PROP_USER
};
G_DEFINE_TYPE (EphyFxPasswordNotification, ephy_fx_password_notification, GTK_TYPE_GRID);
static void
ephy_fx_password_notification_constructed (GObject *object)
{
EphyFxPasswordNotification *self = EPHY_FX_PASSWORD_NOTIFICATION (object);
char *text;
text = g_strdup_printf (_("We noticed that the password of your Firefox "
"Account <b>%s</b> has been changed."),
self->user);
gtk_label_set_markup (GTK_LABEL (self->note), text);
gtk_label_set_text (GTK_LABEL (self->suggestion),
_("Please visit Preferences and sign in with the new "
"password to continue the sync process."));
g_free (text);
G_OBJECT_CLASS (ephy_fx_password_notification_parent_class)->constructed (object);
}
static void
ephy_fx_password_notification_dispose (GObject *object)
{
EphyFxPasswordNotification *self = EPHY_FX_PASSWORD_NOTIFICATION (object);
g_clear_pointer (&self->user, g_free);
G_OBJECT_CLASS (ephy_fx_password_notification_parent_class)->dispose (object);
}
static void
ephy_fx_password_notification_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
EphyFxPasswordNotification *self = EPHY_FX_PASSWORD_NOTIFICATION (object);
switch (prop_id) {
case PROP_USER:
self->user = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
ephy_fx_password_notification_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
EphyFxPasswordNotification *self = EPHY_FX_PASSWORD_NOTIFICATION (object);
switch (prop_id) {
case PROP_USER:
g_value_set_string (value, self->user);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
ephy_fx_password_notification_init (EphyFxPasswordNotification *self)
{
g_return_if_fail (EPHY_IS_FX_PASSWORD_NOTIFICATION (self));
self->note = gtk_label_new (NULL);
gtk_widget_set_halign (self->note, GTK_ALIGN_CENTER);
gtk_widget_set_hexpand (self->note, TRUE);
gtk_grid_attach (GTK_GRID (self), self->note, 0, 0, 1, 1);
self->suggestion = gtk_label_new (NULL);
gtk_widget_set_halign (self->suggestion, GTK_ALIGN_CENTER);
gtk_widget_set_hexpand (self->suggestion, TRUE);
gtk_grid_attach (GTK_GRID (self), self->suggestion, 0, 1, 1, 1);
}
static void
ephy_fx_password_notification_class_init (EphyFxPasswordNotificationClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructed = ephy_fx_password_notification_constructed;
object_class->dispose = ephy_fx_password_notification_dispose;
object_class->set_property = ephy_fx_password_notification_set_property;
object_class->get_property = ephy_fx_password_notification_get_property;
g_object_class_install_property (object_class,
PROP_USER,
g_param_spec_string ("user",
"User",
"The email of the signed in user",
"",
G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
}
EphyFxPasswordNotification *
ephy_fx_password_notification_new (const char *user)
{
return g_object_new (EPHY_TYPE_FX_PASSWORD_NOTIFICATION,
"column-spacing", 12,
"orientation", GTK_ORIENTATION_HORIZONTAL,
"user", user,
NULL);
}
void
ephy_fx_password_notification_show (EphyFxPasswordNotification *self)
{
g_return_if_fail (EPHY_IS_FX_PASSWORD_NOTIFICATION (self));
ephy_notification_manager_add_notification (ephy_notification_manager_dup_singleton (),
GTK_WIDGET (self));
}
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* Copyright © 2016 Gabriel Ivascu <ivascu.gabriel59@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EPHY_FX_PASSWORD_NOTIFICATION_H
#define EPHY_FX_PASSWORD_NOTIFICATION_H
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define EPHY_TYPE_FX_PASSWORD_NOTIFICATION (ephy_fx_password_notification_get_type ())
#define EPHY_FX_PASSWORD_NOTIFICATION(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
EPHY_TYPE_FX_PASSWORD_NOTIFICATION, EphyFxPasswordNotification))
#define EPHY_IS_FX_PASSWORD_NOTIFICATION(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
EPHY_TYPE_FX_PASSWORD_NOTIFICATION))
typedef struct _EphyFxPasswordNotification EphyFxPasswordNotification;
typedef struct _EphyFxPasswordNotificationClass EphyFxPasswordNotificationClass;
GType ephy_fx_password_notification_get_type (void) G_GNUC_CONST;
EphyFxPasswordNotification *ephy_fx_password_notification_new (const char *user);
void ephy_fx_password_notification_show (EphyFxPasswordNotification *self);
G_END_DECLS
#endif
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* Copyright © 2016 Gabriel Ivascu <ivascu.gabriel59@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "ephy-notification-manager.h"
struct _EphyNotificationManager {
GdNotification parent_instance;
GtkWidget *grid;
};
struct _EphyNotificationManagerClass {
GdNotificationClass parent_class;
};
G_DEFINE_TYPE (EphyNotificationManager, ephy_notification_manager, GD_TYPE_NOTIFICATION);
static GObject *
ephy_notification_manager_constructor (GType type,
guint n_construct_params,
GObjectConstructParam *construct_params)
{
static GObject *self = NULL;
if (self == NULL) {
self = G_OBJECT_CLASS (ephy_notification_manager_parent_class)->constructor (type,
n_construct_params,
construct_params);
g_object_add_weak_pointer (self, (gpointer) &self);
}
return g_object_ref_sink (self);
}
static void
ephy_notification_manager_dispose (GObject *object)
{
EphyNotificationManager *self = EPHY_NOTIFICATION_MANAGER (object);
if (ephy_notification_manager_get_children_num (self) > 0)
g_list_free (gtk_container_get_children (GTK_CONTAINER (self->grid)));
G_OBJECT_CLASS (ephy_notification_manager_parent_class)->dispose (object);
}
static void
ephy_notification_manager_init (EphyNotificationManager *self)
{
g_return_if_fail (EPHY_IS_NOTIFICATION_MANAGER (self));
gtk_widget_set_halign (GTK_WIDGET (self), GTK_ALIGN_CENTER);
gtk_widget_set_valign (GTK_WIDGET (self), GTK_ALIGN_START);
gtk_widget_set_visible (GTK_WIDGET (self), TRUE);
self->grid = gtk_grid_new ();
gtk_orientable_set_orientation (GTK_ORIENTABLE (self->grid), GTK_ORIENTATION_VERTICAL);
gtk_grid_set_row_spacing (GTK_GRID (self->grid), 6);
gtk_container_add (GTK_CONTAINER (self), self->grid);
}
static void
ephy_notification_manager_class_init (EphyNotificationManagerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructor = ephy_notification_manager_constructor;
object_class->dispose = ephy_notification_manager_dispose;
}
EphyNotificationManager *
ephy_notification_manager_dup_singleton (void)
{
return g_object_new (EPHY_TYPE_NOTIFICATION_MANAGER,
"show-close-button", TRUE,
"timeout", -1,
NULL);
}
void
ephy_notification_manager_add_notification (EphyNotificationManager *self,
GtkWidget *notification)
{
g_return_if_fail (EPHY_IS_NOTIFICATION_MANAGER (self));
g_return_if_fail (GTK_IS_WIDGET (notification));
gtk_container_add (GTK_CONTAINER (self->grid), notification);
gtk_widget_show_all (GTK_WIDGET (self));
}
guint
ephy_notification_manager_get_children_num (EphyNotificationManager *self)
{
g_return_val_if_fail (EPHY_IS_NOTIFICATION_MANAGER (self), 0);
return g_list_length (gtk_container_get_children (GTK_CONTAINER (self->grid)));
}
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* Copyright © 2016 Gabriel Ivascu <ivascu.gabriel59@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EPHY_NOTIFICATION_MANAGER_H
#define EPHY_NOTIFICATION_MANAGER_H
#include <libgd/gd.h>
G_BEGIN_DECLS
#define EPHY_TYPE_NOTIFICATION_MANAGER (ephy_notification_manager_get_type ())
#define EPHY_NOTIFICATION_MANAGER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
EPHY_TYPE_NOTIFICATION_MANAGER, EphyNotificationManager))
#define EPHY_IS_NOTIFICATION_MANAGER(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
EPHY_TYPE_NOTIFICATION_MANAGER))
typedef struct _EphyNotificationManager EphyNotificationManager;
typedef struct _EphyNotificationManagerClass EphyNotificationManagerClass;
GType ephy_notification_manager_get_type (void) G_GNUC_CONST;
EphyNotificationManager *ephy_notification_manager_dup_singleton (void);
void ephy_notification_manager_add_notification (EphyNotificationManager *self,
GtkWidget *notification);
guint ephy_notification_manager_get_children_num (EphyNotificationManager *self);
G_END_DECLS
#endif
......@@ -22,6 +22,7 @@
#include "ephy-bookmark.h"
#include "ephy-bookmarks-manager.h"
#include "ephy-debug.h"
#include "ephy-fx-password-notification.h"
#include "ephy-settings.h"
#include "ephy-shell.h"
#include "ephy-sync-crypto.h"
......@@ -363,12 +364,6 @@ obtain_storage_credentials_response_cb (SoupSession *session,
json_parser_load_from_data (parser, msg->response_body->data, -1, NULL);
json = json_node_get_object (json_parser_get_root (parser));
/* FIXME: Since a new Firefox Account password means a new kB, and a new kB
* means a new "X-Client-State" header, this will fail with a 401 error status
* code and an "invalid-client-state" status string if the user has changed his
* password since the last time he signed in. If this happens, the user needs
* to be asked to sign in again with the new password.
*/
if (msg->status_code == 200) {
service->storage_endpoint = g_strdup (json_object_get_string_member (json, "api_endpoint"));
service->storage_credentials_id = g_strdup (json_object_get_string_member (json, "id"));
......@@ -445,6 +440,7 @@ obtain_signed_certificate_response_cb (SoupSession *session,
{
StorageServerRequestAsyncData *data;
EphySyncService *service;
EphyFxPasswordNotification *notification;
JsonParser *parser;
JsonObject *json;
const char *certificate;
......@@ -456,6 +452,17 @@ obtain_signed_certificate_response_cb (SoupSession *session,
json_parser_load_from_data (parser, msg->response_body->data, -1, NULL);
json = json_node_get_object (json_parser_get_root (parser));
/* Since a new Firefox Account password implies new tokens, this will fail
* with an error code 110 (Invalid authentication token in request signature)
* if the user has changed his password since the last time he signed in.
* When this happens, notify the user to sign in with the new password. */
if (msg->status_code == 401 && json_object_get_int_member (json, "errno") == 110) {
notification = ephy_fx_password_notification_new (ephy_sync_service_get_user_email (service));
ephy_fx_password_notification_show (notification);
storage_server_request_async_data_free (data);
goto out;
}
if (msg->status_code != 200) {
g_warning ("FxA server errno: %ld, errmsg: %s",
json_object_get_int_member (json, "errno"),
......
......@@ -2078,6 +2078,8 @@ ephy_window_connect_active_embed (EphyWindow *window)
view = ephy_embed_get_web_view (embed);
web_view = EPHY_GET_WEBKIT_WEB_VIEW_FROM_EMBED (embed);
ephy_embed_attach_notification_manager (window->active_embed);
sync_tab_security (view, NULL, window);
sync_tab_document_type (view, NULL, window);
sync_tab_load_status (view, WEBKIT_LOAD_STARTED, window);
......@@ -2158,6 +2160,8 @@ ephy_window_disconnect_active_embed (EphyWindow *window)
web_view = EPHY_GET_WEBKIT_WEB_VIEW_FROM_EMBED (embed);
view = EPHY_WEB_VIEW (web_view);
ephy_embed_detach_notification_manager (window->active_embed);
g_signal_handlers_disconnect_by_func (web_view,
G_CALLBACK (sync_tab_zoom),
window);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment