[Xfce4-commits] <midori:master> Merged cookie permissions as of 2013-03-08

Christian Dywan noreply at xfce.org
Sat Mar 23 12:38:01 CET 2013


Updating branch refs/heads/master
         to 3de3a71f4fb26c3c77802d5dd25f241cc216245f (commit)
       from 7c49465bf169c21918658438d9456bdeef0fe259 (commit)

commit 3de3a71f4fb26c3c77802d5dd25f241cc216245f
Author: Christian Dywan <christian at twotoasts.de>
Date:   Sat Mar 23 12:29:55 2013 +0100

    Merged cookie permissions as of 2013-03-08
    
    Fixes: https://bugs.launchpad.net/midori/+bug/1139496
    Fixes: https://bugs.launchpad.net/midori/+bug/1145197

 .../cookie-permission-manager-preferences-window.c |   69 +++-
 .../cookie-permissions/cookie-permission-manager.c |  399 +++++++++++++-------
 2 files changed, 321 insertions(+), 147 deletions(-)

diff --git a/extensions/cookie-permissions/cookie-permission-manager-preferences-window.c b/extensions/cookie-permissions/cookie-permission-manager-preferences-window.c
index c7ccc5b..33fb2d6 100644
--- a/extensions/cookie-permissions/cookie-permission-manager-preferences-window.c
+++ b/extensions/cookie-permissions/cookie-permission-manager-preferences-window.c
@@ -189,7 +189,7 @@ static void _cookie_permission_manager_preferences_on_add_domain_entry_changed(C
 		checkAsciiDomain++;
 	}
 
-	/* If we have not reached the trimmed end of string something must have gone wrong
+	/* If we have not reached the trimmed end of string something must have gone wrong 
 	 * and domain entered is invalid. If domain name entered excluding dots is longer
 	 * than 255 character it is also invalid.
 	 */
@@ -282,21 +282,19 @@ static void _cookie_permission_manager_preferences_window_manager_database_chang
 {
 	CookiePermissionManagerPreferencesWindowPrivate	*priv=self->priv;
 	CookiePermissionManager							*manager=COOKIE_PERMISSION_MANAGER(inUserData);
-	sqlite3											*database;
+	const gchar										*databaseFilename;
 
 	/* Close connection to any open database */
 	if(priv->database) sqlite3_close(priv->database);
 	priv->database=NULL;
 
 	/* Get pointer to new database and open database */
-	g_object_get(manager, "database", &database, NULL);
-	if(database)
+	g_object_get(manager, "database-filename", &databaseFilename, NULL);
+	if(databaseFilename)
 	{
-		const gchar									*databaseFile;
 		gint										success;
 
-		databaseFile=sqlite3_db_filename(database, NULL);
-		success=sqlite3_open(databaseFile, &priv->database);
+		success=sqlite3_open(databaseFilename, &priv->database);
 		if(success!=SQLITE_OK)
 		{
 			g_warning(_("Could not open database of extenstion: %s"), sqlite3_errmsg(priv->database));
@@ -465,6 +463,27 @@ void _cookie_permission_manager_preferences_on_delete_all(CookiePermissionManage
 	_cookie_permission_manager_preferences_window_fill(self);
 }
 
+/* Sorting callbacks */
+static gint _cookie_permission_manager_preferences_sort_string_callback(GtkTreeModel *inModel,
+																		GtkTreeIter *inLeft,
+																		GtkTreeIter *inRight,
+																		gpointer inUserData)
+{
+	gchar		*left, *right;
+	gint		column=GPOINTER_TO_INT(inUserData);
+	gint		result;
+
+	gtk_tree_model_get(inModel, inLeft, column, &left, -1);
+	gtk_tree_model_get(inModel, inRight, column, &right, -1);
+
+	result=g_strcmp0(left, right);
+
+	g_free(left);
+	g_free(right);
+
+	return(result);
+}
+
 /* IMPLEMENTATION: GObject */
 
 /* Finalize this object */
@@ -527,16 +546,18 @@ static void cookie_permission_manager_preferences_window_set_property(GObject *i
 			{
 				priv->manager=g_object_ref(manager);
 
-				priv->signalManagerChangedDatabaseID=g_signal_connect_swapped(priv->manager,
-																					"notify::database",
-																					G_CALLBACK(_cookie_permission_manager_preferences_window_manager_database_changed),
-																					self);
-				priv->signalManagerAskForUnknownPolicyID=g_signal_connect_swapped(priv->manager,
-																					"notify::ask-for-unknown-policy",
-																					G_CALLBACK(_cookie_permission_manager_preferences_window_manager_ask_for_unknown_policy_changed),
-																					self);
-
+				priv->signalManagerChangedDatabaseID=
+					g_signal_connect_swapped(priv->manager,
+												"notify::database-filename",
+												G_CALLBACK(_cookie_permission_manager_preferences_window_manager_database_changed),
+												self);
 				_cookie_permission_manager_preferences_window_manager_database_changed(self, NULL, priv->manager);
+
+				priv->signalManagerAskForUnknownPolicyID=
+					g_signal_connect_swapped(priv->manager,
+												"notify::ask-for-unknown-policy",
+												G_CALLBACK(_cookie_permission_manager_preferences_window_manager_ask_for_unknown_policy_changed),
+												self);
 				_cookie_permission_manager_preferences_window_manager_ask_for_unknown_policy_changed(self, NULL, priv->manager);
 			}
 			break;
@@ -598,6 +619,7 @@ static void cookie_permission_manager_preferences_window_class_init(CookiePermis
 static void cookie_permission_manager_preferences_window_init(CookiePermissionManagerPreferencesWindow *self)
 {
 	CookiePermissionManagerPreferencesWindowPrivate		*priv;
+	GtkTreeSortable										*sortableList;
 	GtkCellRenderer										*renderer;
 	GtkTreeViewColumn									*column;
 	GtkWidget											*widget;
@@ -654,6 +676,19 @@ static void cookie_permission_manager_preferences_window_init(CookiePermissionMa
 										G_TYPE_STRING,	/* DOMAIN_COLUMN */
 										G_TYPE_STRING	/* POLICY_COLUMN */);
 
+	sortableList=GTK_TREE_SORTABLE(priv->listStore);
+	gtk_tree_sortable_set_sort_func(sortableList,
+										DOMAIN_COLUMN,
+										(GtkTreeIterCompareFunc)_cookie_permission_manager_preferences_sort_string_callback,
+										GINT_TO_POINTER(DOMAIN_COLUMN),
+										NULL);
+	gtk_tree_sortable_set_sort_func(sortableList,
+										POLICY_COLUMN,
+										(GtkTreeIterCompareFunc)_cookie_permission_manager_preferences_sort_string_callback,
+										GINT_TO_POINTER(POLICY_COLUMN),
+										NULL);
+	gtk_tree_sortable_set_sort_column_id(sortableList, DOMAIN_COLUMN, GTK_SORT_ASCENDING);
+
 	/* Set up domain addition widgets */
 #ifdef HAVE_GTK3
 	hbox=gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
@@ -706,6 +741,7 @@ static void cookie_permission_manager_preferences_window_init(CookiePermissionMa
 													renderer,
 													"text", DOMAIN_COLUMN,
 													NULL);
+	gtk_tree_view_column_set_sort_column_id(column, DOMAIN_COLUMN);
 	gtk_tree_view_append_column(GTK_TREE_VIEW(priv->list), column);
 
 	renderer=gtk_cell_renderer_text_new();
@@ -713,6 +749,7 @@ static void cookie_permission_manager_preferences_window_init(CookiePermissionMa
 													renderer,
 													"text", POLICY_COLUMN,
 													NULL);
+	gtk_tree_view_column_set_sort_column_id(column, POLICY_COLUMN);
 	gtk_tree_view_append_column(GTK_TREE_VIEW(priv->list), column);
 
 	scrolled=gtk_scrolled_window_new(NULL, NULL);
diff --git a/extensions/cookie-permissions/cookie-permission-manager.c b/extensions/cookie-permissions/cookie-permission-manager.c
index 84f99af..2fca15c 100644
--- a/extensions/cookie-permissions/cookie-permission-manager.c
+++ b/extensions/cookie-permissions/cookie-permission-manager.c
@@ -13,6 +13,9 @@
 
 #include <errno.h>
 
+/* Remove next line if we found a way to show details in infobar */
+#define NO_INFOBAR_DETAILS
+
 /* Define this class in GObject system */
 G_DEFINE_TYPE(CookiePermissionManager,
 				cookie_permission_manager,
@@ -27,9 +30,9 @@ enum
 	PROP_APPLICATION,
 
 	PROP_DATABASE,
+	PROP_DATABASE_FILENAME,
 	PROP_ASK_FOR_UNKNOWN_POLICY,
 
-
 	PROP_LAST
 };
 
@@ -45,12 +48,9 @@ struct _CookiePermissionManagerPrivate
 	MidoriExtension					*extension;
 	MidoriApp						*application;
 	sqlite3							*database;
+	gchar							*databaseFilename;
 	gboolean						askForUnknownPolicy;
 
-	/* Session related */
-	void(*oldRequestQueued)(SoupSessionFeature *inFeature, SoupSession *inSession, SoupMessage *inMessage);
-	void(*oldRequestUnqueued)(SoupSessionFeature *inFeature, SoupSession *inSession, SoupMessage *inMessage);
-
 	/* Cookie jar related */
 	SoupSession						*session;
 	SoupCookieJar					*cookieJar;
@@ -68,6 +68,14 @@ enum
 	N_COLUMN
 };
 
+struct _CookiePermissionManagerModalInfobar
+{
+	GMainLoop						*mainLoop;
+	gint							response;
+};
+
+typedef struct _CookiePermissionManagerModalInfobar		CookiePermissionManagerModalInfobar;
+
 /* IMPLEMENTATION: Private variables and methods */
 
 /* Show common error dialog */
@@ -105,7 +113,6 @@ static void _cookie_permission_manager_open_database(CookiePermissionManager *se
 {
 	CookiePermissionManagerPrivate	*priv=self->priv;
 	const gchar						*configDir;
-	gchar							*databaseFile;
 	gchar							*error=NULL;
 	gint							success;
 	sqlite3_stmt					*statement=NULL;
@@ -113,9 +120,14 @@ static void _cookie_permission_manager_open_database(CookiePermissionManager *se
 	/* Close any open database */
 	if(priv->database)
 	{
+		g_free(priv->databaseFilename);
+		priv->databaseFilename=NULL;
+
 		sqlite3_close(priv->database);
 		priv->database=NULL;
+
 		g_object_notify_by_pspec(G_OBJECT(self), CookiePermissionManagerProperties[PROP_DATABASE]);
+		g_object_notify_by_pspec(G_OBJECT(self), CookiePermissionManagerProperties[PROP_DATABASE_FILENAME]);
 	}
 
 	/* Build path to database file */
@@ -127,7 +139,7 @@ static void _cookie_permission_manager_open_database(CookiePermissionManager *se
 		_cookie_permission_manager_error(self, _("Could not get path to configuration of extension."));
 		return;
 	}
-
+	
 	if(katze_mkdir_with_parents(configDir, 0700))
 	{
 		g_warning(_("Could not create configuration folder for extension: %s"), g_strerror(errno));
@@ -137,13 +149,15 @@ static void _cookie_permission_manager_open_database(CookiePermissionManager *se
 	}
 
 	/* Open database */
-	databaseFile=g_build_filename(configDir, COOKIE_PERMISSION_DATABASE, NULL);
-	success=sqlite3_open(databaseFile, &priv->database);
-	g_free(databaseFile);
+	priv->databaseFilename=g_build_filename(configDir, COOKIE_PERMISSION_DATABASE, NULL);
+	success=sqlite3_open(priv->databaseFilename, &priv->database);
 	if(success!=SQLITE_OK)
 	{
 		g_warning(_("Could not open database of extenstion: %s"), sqlite3_errmsg(priv->database));
 
+		g_free(priv->databaseFilename);
+		priv->databaseFilename=NULL;
+
 		if(priv->database) sqlite3_close(priv->database);
 		priv->database=NULL;
 
@@ -188,6 +202,9 @@ static void _cookie_permission_manager_open_database(CookiePermissionManager *se
 			sqlite3_free(error);
 		}
 
+		g_free(priv->databaseFilename);
+		priv->databaseFilename=NULL;
+
 		sqlite3_close(priv->database);
 		priv->database=NULL;
 		return;
@@ -237,6 +254,7 @@ static void _cookie_permission_manager_open_database(CookiePermissionManager *se
 	sqlite3_finalize(statement);
 
 	g_object_notify_by_pspec(G_OBJECT(self), CookiePermissionManagerProperties[PROP_DATABASE]);
+	g_object_notify_by_pspec(G_OBJECT(self), CookiePermissionManagerProperties[PROP_DATABASE_FILENAME]);
 }
 
 /* Get policy for cookies from domain */
@@ -361,6 +379,8 @@ static GSList* _cookie_permission_manager_get_number_domains_and_cookies(CookieP
 	return(sortedList);
 }
 
+/* FIXME: Find a way to add "details" widget */
+#ifndef NO_INFOBAR_DETAILS
 static void _cookie_permission_manager_when_ask_expander_changed(CookiePermissionManager *self,
 																	GParamSpec *inSpec,
 																	gpointer inUserData)
@@ -369,26 +389,84 @@ static void _cookie_permission_manager_when_ask_expander_changed(CookiePermissio
 
 	midori_extension_set_boolean(self->priv->extension, "show-details-when-ask", gtk_expander_get_expanded(expander));
 }
+#endif
+
+static gboolean _cookie_permission_manager_on_infobar_webview_navigate(WebKitWebView *inView,
+																		WebKitWebFrame *inFrame,
+																		WebKitNetworkRequest *inRequest,
+																		WebKitWebNavigationAction *inAction,
+																		WebKitWebPolicyDecision *inDecision,
+																		gpointer inUserData)
+{
+	/* Destroy info bar - that calls another callback which quits main loop */
+	GtkWidget		*infobar=GTK_WIDGET(inUserData);
+
+	gtk_widget_destroy(infobar);
+
+	/* Let the default handler decide */
+	return(FALSE);
+}
+
+static void _cookie_permission_manager_on_infobar_destroy(GtkWidget* inInfobar,
+															gpointer inUserData)
+{
+	CookiePermissionManagerModalInfobar		*modalInfo=(CookiePermissionManagerModalInfobar*)inUserData;
+
+	/* Quit main loop */
+	if(g_main_loop_is_running(modalInfo->mainLoop)) g_main_loop_quit(modalInfo->mainLoop);
+}
+
+static void _cookie_permission_manager_on_infobar_policy_decision(GtkWidget* inInfobar,
+																	gint inResponse,
+																	gpointer inUserData)
+{
+	CookiePermissionManagerModalInfobar		*modalInfo;
+
+	/* Get modal info struct */
+	modalInfo=(CookiePermissionManagerModalInfobar*)g_object_get_data(G_OBJECT(inInfobar), "cookie-permission-manager-infobar-data");
+
+	/* Store response */
+	modalInfo->response=inResponse;
+
+	/* Quit main loop */
+	if(g_main_loop_is_running(modalInfo->mainLoop)) g_main_loop_quit(modalInfo->mainLoop);
+}
 
 static gint _cookie_permission_manager_ask_for_policy(CookiePermissionManager *self,
+														MidoriView *inView,
+														SoupMessage *inMessage,
 														GSList *inUnknownCookies)
 {
-	CookiePermissionManagerPrivate	*priv=self->priv;
-	GtkWidget						*dialog;
-	GtkWidget						*widget;
-	GtkWidget						*contentArea;
-	GtkWidget						*vbox, *hbox;
-	GtkWidget						*expander;
-	GtkListStore					*listStore;
-	GtkTreeIter						listIter;
-	GtkWidget						*scrolled;
-	GtkWidget						*list;
-	GtkCellRenderer					*renderer;
-	GtkTreeViewColumn				*column;
-	gchar							*text;
-	gint							numberDomains, numberCookies;
-	gint							response;
-	GSList							*sortedCookies, *cookies;
+	/* Ask user for policy of unkndown domains in an undistracting way.
+	 * The idea is to put the message not in a modal window but into midori's info bar.
+	 * Then we'll set up our own GMainLoop to simulate a modal info bar. We need to
+	 * connect to all possible signals of info bar, web view and so on to handle user's
+	 * decision and to get out of our own GMainLoop. After that webkit resumes processing
+	 * data.
+	 */
+	CookiePermissionManagerPrivate			*priv=self->priv;
+	GtkWidget								*infobar;
+/* FIXME: Find a way to add "details" widget */
+#ifndef NO_INFOBAR_DETAILS
+	GtkWidget								*widget;
+	GtkWidget								*contentArea;
+	GtkWidget								*vbox, *hbox;
+	GtkWidget								*expander;
+	GtkListStore							*listStore;
+	GtkTreeIter								listIter;
+	GtkWidget								*scrolled;
+	GtkWidget								*list;
+	GtkCellRenderer							*renderer;
+	GtkTreeViewColumn						*column;
+#endif
+	gchar									*text;
+	gint									numberDomains, numberCookies;
+	GSList									*sortedCookies, *cookies;
+	WebKitWebView							*webkitView;
+	CookiePermissionManagerModalInfobar		modalInfo;
+
+	/* Get webkit view of midori view */
+	webkitView=WEBKIT_WEB_VIEW(midori_view_get_web_view(inView));
 
 	/* Create a copy of cookies and sort them */
 	sortedCookies=_cookie_permission_manager_get_number_domains_and_cookies(self,
@@ -396,6 +474,8 @@ static gint _cookie_permission_manager_ask_for_policy(CookiePermissionManager *s
 																			&numberDomains,
 																			&numberCookies);
 
+/* FIXME: Find a way to add "details" widget */
+#ifndef NO_INFOBAR_DETAILS
 	/* Create list model and fill in data */
 	listStore=gtk_list_store_new(N_COLUMN,
 									G_TYPE_STRING,	/* DOMAIN_COLUMN */
@@ -409,7 +489,8 @@ static gint _cookie_permission_manager_ask_for_policy(CookiePermissionManager *s
 		SoupCookie				*cookie=(SoupCookie*)cookies->data;
 		SoupDate				*cookieDate=soup_cookie_get_expires(cookie);
 
-		text=soup_date_to_string(cookieDate, SOUP_DATE_HTTP);
+		if(cookieDate) text=soup_date_to_string(cookieDate, SOUP_DATE_HTTP);
+			else text=g_strdup(_("Till session end"));
 
 		gtk_list_store_append(listStore, &listIter);
 		gtk_list_store_set(listStore,
@@ -423,40 +504,15 @@ static gint _cookie_permission_manager_ask_for_policy(CookiePermissionManager *s
 
 		g_free(text);
 	}
-
-	/* Create dialog with text, icon, title and so on */
-	dialog=gtk_dialog_new();
-
-	gtk_window_set_title(GTK_WINDOW(dialog), _("Confirm storing cookie"));
-	gtk_window_set_icon_name(GTK_WINDOW (dialog), "midori");
-
-	/* Get content area and layout widgets */
-	contentArea=gtk_dialog_get_content_area(GTK_DIALOG(dialog));
-
-#ifdef HAVE_GTK3
-	vbox=gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
-	gtk_box_set_homogeneous(GTK_BOX(vbox), FALSE);
-#else
-	vbox=gtk_vbox_new(FALSE, 0);
 #endif
 
 	/* Create description text */
-#ifdef HAVE_GTK3
-	hbox=gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
-	gtk_box_set_homogeneous(GTK_BOX(hbox), FALSE);
-#else
-	hbox=gtk_hbox_new(FALSE, 0);
-#endif
-
-	widget=gtk_image_new_from_stock(GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG);
-	gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, FALSE, 4);
-
 	if(numberDomains==1)
 	{
 		const gchar					*cookieDomain=soup_cookie_get_domain((SoupCookie*)sortedCookies->data);
 
 		if(*cookieDomain=='.') cookieDomain++;
-
+		
 		if(numberCookies>1)
 			text=g_strdup_printf(_("The website %s wants to store %d cookies."), cookieDomain, numberCookies);
 		else
@@ -467,17 +523,33 @@ static gint _cookie_permission_manager_ask_for_policy(CookiePermissionManager *s
 			text=g_strdup_printf(_("Multiple websites want to store %d cookies in total."), numberCookies);
 		}
 
-	widget=gtk_label_new(NULL);
-	gtk_label_set_markup(GTK_LABEL(widget), text);
-	gtk_label_set_line_wrap(GTK_LABEL(widget), TRUE);
-	gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, FALSE, 4);
+	/* Create info bar message and buttons */
+	infobar=midori_view_add_info_bar(inView,
+										GTK_MESSAGE_QUESTION,
+										text,
+										G_CALLBACK(_cookie_permission_manager_on_infobar_policy_decision),
+										NULL,
+										_("_Accept"), COOKIE_PERMISSION_MANAGER_POLICY_ACCEPT,
+										_("Accept for this _session"), COOKIE_PERMISSION_MANAGER_POLICY_ACCEPT_FOR_SESSION,
+										_("De_ny"), COOKIE_PERMISSION_MANAGER_POLICY_BLOCK,
+										_("Deny _this time"), COOKIE_PERMISSION_MANAGER_POLICY_UNDETERMINED,
+										NULL);
 	g_free(text);
 
-	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 4);
+	/* midori_view_add_info_bar() in version 0.4.8 expects a GObject as user data
+	 * but I don't want to create an GObject just for a simple struct. So set object
+	 * data by our own
+	 */
+	g_object_set_data(G_OBJECT(infobar), "cookie-permission-manager-infobar-data", &modalInfo);
 
-	/* Create expander for details */
-	expander=gtk_expander_new_with_mnemonic(_("_Details"));
-	gtk_box_pack_start(GTK_BOX(vbox), expander, TRUE, TRUE, 5);
+/* FIXME: Find a way to add "details" widget */
+#ifndef NO_INFOBAR_DETAILS
+	/* Get content area of infobar */
+#if HAVE_GTK_INFO_BAR
+	contentArea=gtk_info_bar_get_content_area(GTK_INFO_BAR(infobar));
+#else
+	contentArea=infobar;
+#endif
 
 	/* Create list and set up columns of list */
 	list=gtk_tree_view_new_with_model(GTK_TREE_MODEL(listStore));
@@ -540,25 +612,36 @@ static gint _cookie_permission_manager_ask_for_policy(CookiePermissionManager *s
 	gtk_expander_set_expanded(GTK_EXPANDER(expander),
 								midori_extension_get_boolean(priv->extension, "show-details-when-ask"));
 	g_signal_connect_swapped(expander, "notify::expanded", G_CALLBACK(_cookie_permission_manager_when_ask_expander_changed), self);
+#endif
 
-	/* Create buttons for dialog */
-	widget=gtk_dialog_add_button(GTK_DIALOG(dialog), _("_Accept"), COOKIE_PERMISSION_MANAGER_POLICY_ACCEPT);
-	gtk_button_set_image(GTK_BUTTON(widget), gtk_image_new_from_stock(GTK_STOCK_APPLY, GTK_ICON_SIZE_BUTTON));
+	/* Show all widgets of info bar */
+	gtk_widget_show_all(infobar);
 
-	gtk_dialog_add_button(GTK_DIALOG(dialog), _("Accept for this _session"), COOKIE_PERMISSION_MANAGER_POLICY_ACCEPT_FOR_SESSION);
+	/* Connect signals to quit main loop */
+	g_signal_connect(webkitView, "navigation-policy-decision-requested", G_CALLBACK(_cookie_permission_manager_on_infobar_webview_navigate), infobar);
+	g_signal_connect(infobar, "destroy", G_CALLBACK(_cookie_permission_manager_on_infobar_destroy), &modalInfo);
 
-	widget=gtk_dialog_add_button(GTK_DIALOG(dialog), _("De_ny"), COOKIE_PERMISSION_MANAGER_POLICY_BLOCK);
-	gtk_button_set_image(GTK_BUTTON(widget), gtk_image_new_from_stock(GTK_STOCK_CANCEL, GTK_ICON_SIZE_BUTTON));
+	/* Let info bar be modal and set response to default */
+	modalInfo.response=COOKIE_PERMISSION_MANAGER_POLICY_UNDETERMINED;
+	modalInfo.mainLoop=g_main_loop_new(NULL, FALSE);
 
-	/* Show confirmation dialog and wait for response of user */
-	response=gtk_dialog_run(GTK_DIALOG(dialog));
+	GDK_THREADS_LEAVE();
+	g_main_loop_run(modalInfo.mainLoop);
+	GDK_THREADS_ENTER();
+
+	g_main_loop_unref(modalInfo.mainLoop);
+
+	modalInfo.mainLoop=NULL;
+
+	/* Disconnect signal handler to webkit's web view  */
+	g_signal_handlers_disconnect_by_func(webkitView, G_CALLBACK(_cookie_permission_manager_on_infobar_webview_navigate), infobar);
 
 	/* Store user's decision in database if it is not a temporary block.
 	 * We use the already sorted list of cookies to prevent multiple
 	 * updates of database for the same domain. This sorted list is a copy
 	 * to avoid a reorder of cookies
 	 */
-	if(response>=0)
+	if(modalInfo.response!=COOKIE_PERMISSION_MANAGER_POLICY_UNDETERMINED)
 	{
 		const gchar					*lastDomain=NULL;
 
@@ -579,7 +662,7 @@ static gint _cookie_permission_manager_ask_for_policy(CookiePermissionManager *s
 
 				sql=sqlite3_mprintf("INSERT OR REPLACE INTO policies (domain, value) VALUES ('%q', %d);",
 										cookieDomain,
-										response);
+										modalInfo.response);
 				success=sqlite3_exec(priv->database, sql, NULL, NULL, &error);
 				if(success!=SQLITE_OK) g_warning(_("SQL fails: %s"), error);
 				if(error) sqlite3_free(error);
@@ -592,10 +675,10 @@ static gint _cookie_permission_manager_ask_for_policy(CookiePermissionManager *s
 
 	/* Free up allocated resources */
 	g_slist_free(sortedCookies);
-	gtk_widget_destroy(dialog);
 
-	/* Return user's selection */
-	return(response>=0 ? response : COOKIE_PERMISSION_MANAGER_POLICY_BLOCK);
+	/* Return response */
+	return(modalInfo.response==COOKIE_PERMISSION_MANAGER_POLICY_UNDETERMINED ?
+			COOKIE_PERMISSION_MANAGER_POLICY_BLOCK : modalInfo.response);
 }
 
 /* A cookie was changed outside a request (e.g. Javascript) */
@@ -604,9 +687,6 @@ static void _cookie_permission_manager_on_cookie_changed(CookiePermissionManager
 															SoupCookie *inNewCookie,
 															SoupCookieJar *inCookieJar)
 {
-	GSList			*newCookies;
-	gint			newCookiePolicy;
-
 	/* Do not check changed cookies because they must have been allowed before.
 	 * Also do not check removed cookies because they are removed ;)
 	 */
@@ -615,33 +695,30 @@ static void _cookie_permission_manager_on_cookie_changed(CookiePermissionManager
 	/* New cookie is a new cookie so check */
 	switch(_cookie_permission_manager_get_policy(self, inNewCookie))
 	{
-		case COOKIE_PERMISSION_MANAGER_POLICY_BLOCK:
-			soup_cookie_jar_delete_cookie(inCookieJar, inNewCookie);
+		case COOKIE_PERMISSION_MANAGER_POLICY_ACCEPT:
+		case COOKIE_PERMISSION_MANAGER_POLICY_ACCEPT_FOR_SESSION:
 			break;
 
 		case COOKIE_PERMISSION_MANAGER_POLICY_UNDETERMINED:
-			newCookies=g_slist_prepend(NULL, inNewCookie);
-			newCookiePolicy=_cookie_permission_manager_ask_for_policy(self, newCookies);
-			if(newCookiePolicy==COOKIE_PERMISSION_MANAGER_POLICY_BLOCK)
-			{
-				/* Free cookie because it should be blocked */
-				soup_cookie_jar_delete_cookie(inCookieJar, inNewCookie);
-			}
-				else
-				{
-					/* Cookie was accept so do nothing (it is already added) */
-				}
-			g_slist_free(newCookies);
-			break;
+			/* Fallthrough!
+			 * The problem here is that we don't know the view to ask user
+			 * for policy to follow for this cookie domain. Therefore we
+			 * delete the cookie from jar and assume that we will be asked
+			 * again in _cookie_permission_manager_on_response_received().
+			 */
 
-		case COOKIE_PERMISSION_MANAGER_POLICY_ACCEPT:
-		case COOKIE_PERMISSION_MANAGER_POLICY_ACCEPT_FOR_SESSION:
+		default:
+			soup_cookie_jar_delete_cookie(inCookieJar, inNewCookie);
 			break;
 	}
 }
 
 /* We received the HTTP headers of the request and it contains cookie-managing headers */
-static void _cookie_permission_manager_process_set_cookie_header(SoupMessage *inMessage, gpointer inUserData)
+static void _cookie_permission_manager_on_response_received(WebKitWebView *inView,
+															WebKitWebFrame *inFrame,
+															WebKitWebResource *inResource,
+															WebKitNetworkResponse *inResponse,
+															gpointer inUserData)
 {
 	g_return_if_fail(IS_COOKIE_PERMISSION_MANAGER(inUserData));
 
@@ -652,18 +729,23 @@ static void _cookie_permission_manager_process_set_cookie_header(SoupMessage *in
 	SoupURI							*firstParty;
 	SoupCookieJarAcceptPolicy		cookiePolicy;
 	gint							unknownCookiesPolicy;
+	SoupMessage						*message;
 
 	/* If policy is to deny all cookies return immediately */
 	cookiePolicy=soup_cookie_jar_get_accept_policy(priv->cookieJar);
 	if(cookiePolicy==SOUP_COOKIE_JAR_ACCEPT_NEVER) return;
 
+	/* Get SoupMessage */
+	message=webkit_network_response_get_message(inResponse);
+	if(!message || !SOUP_IS_MESSAGE(message)) return;
+
 	/* Iterate through cookies in response and check if they should be
 	 * blocked (remove from cookies list) or accepted (added to cookie jar).
 	 * If we could not determine what to do collect these cookies and
 	 * ask user
 	 */
-	newCookies=soup_cookies_from_response(inMessage);
-	firstParty=soup_message_get_first_party(inMessage);
+	newCookies=soup_cookies_from_response(message);
+	firstParty=soup_message_get_first_party(message);
 	for(cookie=newCookies; cookie; cookie=cookie->next)
 	{
 		switch(_cookie_permission_manager_get_policy(self, cookie->data))
@@ -712,7 +794,13 @@ static void _cookie_permission_manager_process_set_cookie_header(SoupMessage *in
 	 */
 	if(g_slist_length(unknownCookies)>0)
 	{
-		unknownCookiesPolicy=_cookie_permission_manager_ask_for_policy(self, unknownCookies);
+		/* Get view */
+		MidoriView					*view;
+
+		view=MIDORI_VIEW(g_object_get_data(G_OBJECT(inView), "midori-view"));
+
+		/* Ask for user's decision */
+		unknownCookiesPolicy=_cookie_permission_manager_ask_for_policy(self, view, message, unknownCookies);
 		if(unknownCookiesPolicy==COOKIE_PERMISSION_MANAGER_POLICY_ACCEPT ||
 			unknownCookiesPolicy==COOKIE_PERMISSION_MANAGER_POLICY_ACCEPT_FOR_SESSION)
 		{
@@ -744,33 +832,51 @@ static void _cookie_permission_manager_process_set_cookie_header(SoupMessage *in
 	g_slist_free(newCookies);
 }
 
-/* A request was started and is in queue now */
-static void _cookie_permission_manager_request_queued(SoupSessionFeature *inFeature, SoupSession *inSession, SoupMessage *inMessage)
+/* A tab to a browser was added */
+static void _cookie_permission_manager_on_add_tab(CookiePermissionManager *self, MidoriView *inView, gpointer inUserData)
 {
-	/* Get class instance */
-	CookiePermissionManager		*manager=g_object_get_data(G_OBJECT(inFeature), "cookie-permission-manager");
+	/* Listen to starting network requests */
+	WebKitWebView	*webkitView=WEBKIT_WEB_VIEW(midori_view_get_web_view(inView));
 
-	/* Listen to "got-headers" signals and register handlers for
-	 * checking cookie-managing headers in HTTP stream
-	 */
-	soup_message_add_header_handler(inMessage,
-										"got-headers",
-										"Set-Cookie",
-										G_CALLBACK(_cookie_permission_manager_process_set_cookie_header),
-										manager);
-
-	soup_message_add_header_handler(inMessage,
-										"got-headers",
-										"Set-Cookie2",
-										G_CALLBACK(_cookie_permission_manager_process_set_cookie_header),
-										manager);
+	g_object_set_data(G_OBJECT(webkitView), "midori-view", inView);
+	g_signal_connect(webkitView, "resource-response-received", G_CALLBACK(_cookie_permission_manager_on_response_received), self);
 }
 
-/* Request has loaded and was unqueued */
-static void _cookie_permission_manager_request_unqueued(SoupSessionFeature *inFeature, SoupSession *inSession, SoupMessage *inMessage)
+/* A browser window was added */
+static void _cookie_permission_manager_on_add_browser(CookiePermissionManager *self,
+														MidoriBrowser *inBrowser,
+														gpointer inUserData)
 {
-	/* Stop listening to HTTP stream */
-	g_signal_handlers_disconnect_by_func(inMessage, _cookie_permission_manager_process_set_cookie_header, inFeature);
+	GList	*tabs, *iter;
+
+	/* Set up all current available tabs in browser */
+	tabs=midori_browser_get_tabs(inBrowser);
+	for(iter=tabs; iter; iter=g_list_next(iter))
+	{
+		_cookie_permission_manager_on_add_tab(self, iter->data, inBrowser);
+	}
+	g_list_free(tabs);
+
+	/* Listen to new tabs opened in browser and existing ones closed */
+	g_signal_connect_swapped(inBrowser, "add-tab", G_CALLBACK(_cookie_permission_manager_on_add_tab), self);
+}
+
+/* Application property has changed */
+static void _cookie_permission_manager_on_application_changed(CookiePermissionManager *self)
+{
+	CookiePermissionManagerPrivate		*priv=COOKIE_PERMISSION_MANAGER(self)->priv;
+	GList								*browsers, *iter;
+
+	/* Set up all current open browser windows */
+	browsers=midori_app_get_browsers(priv->application);
+	for(iter=browsers; iter; iter=g_list_next(iter))
+	{
+		_cookie_permission_manager_on_add_browser(self, MIDORI_BROWSER(iter->data), priv->application);
+	}
+	g_list_free(browsers);
+
+	/* Listen to new browser windows opened and existing ones closed */
+	g_signal_connect_swapped(priv->application, "add-browser", G_CALLBACK(_cookie_permission_manager_on_add_browser), self);
 }
 
 /* IMPLEMENTATION: GObject */
@@ -778,9 +884,20 @@ static void _cookie_permission_manager_request_unqueued(SoupSessionFeature *inFe
 /* Finalize this object */
 static void cookie_permission_manager_finalize(GObject *inObject)
 {
-	CookiePermissionManagerPrivate	*priv=COOKIE_PERMISSION_MANAGER(inObject)->priv;
+	CookiePermissionManager			*self=COOKIE_PERMISSION_MANAGER(inObject);
+	CookiePermissionManagerPrivate	*priv=self->priv;
+	GList							*browsers, *browser;
+	GList							*tabs, *tab;
+	WebKitWebView					*webkitView;
 
 	/* Dispose allocated resources */
+	if(priv->databaseFilename)
+	{
+		g_free(priv->databaseFilename);
+		priv->databaseFilename=NULL;
+		g_object_notify_by_pspec(inObject, CookiePermissionManagerProperties[PROP_DATABASE_FILENAME]);
+	}
+
 	if(priv->database)
 	{
 		sqlite3_close(priv->database);
@@ -789,11 +906,24 @@ static void cookie_permission_manager_finalize(GObject *inObject)
 	}
 
 	g_signal_handler_disconnect(priv->cookieJar, priv->cookieJarChangedID);
+	g_object_steal_data(G_OBJECT(priv->cookieJar), "cookie-permission-manager");
 
-	priv->featureIface->request_queued=priv->oldRequestQueued;
-	priv->featureIface->request_unqueued=priv->oldRequestUnqueued;
+	g_signal_handlers_disconnect_by_data(priv->application, self);
 
-	g_object_steal_data(G_OBJECT(priv->cookieJar), "cookie-permission-manager");
+	browsers=midori_app_get_browsers(priv->application);
+	for(browser=browsers; browser; browser=g_list_next(browser))
+	{
+		g_signal_handlers_disconnect_by_data(browser->data, self);
+
+		tabs=midori_browser_get_tabs(MIDORI_BROWSER(browser->data));
+		for(tab=tabs; tab; tab=g_list_next(tab))
+		{
+			webkitView=WEBKIT_WEB_VIEW(midori_view_get_web_view(MIDORI_VIEW(tab->data)));
+			g_signal_handlers_disconnect_by_data(webkitView, self);
+		}
+		g_list_free(tabs);
+	}
+	g_list_free(browsers);
 
 	/* Call parent's class finalize method */
 	G_OBJECT_CLASS(cookie_permission_manager_parent_class)->finalize(inObject);
@@ -806,7 +936,7 @@ static void cookie_permission_manager_set_property(GObject *inObject,
 													GParamSpec *inSpec)
 {
 	CookiePermissionManager		*self=COOKIE_PERMISSION_MANAGER(inObject);
-
+	
 	switch(inPropID)
 	{
 		/* Construct-only properties */
@@ -817,6 +947,7 @@ static void cookie_permission_manager_set_property(GObject *inObject,
 
 		case PROP_APPLICATION:
 			self->priv->application=g_value_get_object(inValue);
+			_cookie_permission_manager_on_application_changed(self);
 			break;
 
 		case PROP_ASK_FOR_UNKNOWN_POLICY:
@@ -850,6 +981,10 @@ static void cookie_permission_manager_get_property(GObject *inObject,
 			g_value_set_pointer(outValue, self->priv->database);
 			break;
 
+		case PROP_DATABASE_FILENAME:
+			g_value_set_string(outValue, self->priv->databaseFilename);
+			break;
+
 		case PROP_ASK_FOR_UNKNOWN_POLICY:
 			g_value_set_boolean(outValue, self->priv->askForUnknownPolicy);
 			break;
@@ -896,6 +1031,13 @@ static void cookie_permission_manager_class_init(CookiePermissionManagerClass *k
 								_("Pointer to sqlite database instance used by this extension"),
 								G_PARAM_READABLE);
 
+	CookiePermissionManagerProperties[PROP_DATABASE_FILENAME]=
+		g_param_spec_string("database-filename",
+								_("Database path"),
+								_("Path to sqlite database instance used by this extension"),
+								NULL,
+								G_PARAM_READABLE);
+
 	CookiePermissionManagerProperties[PROP_ASK_FOR_UNKNOWN_POLICY]=
 		g_param_spec_boolean("ask-for-unknown-policy",
 								_("Ask for unknown policy"),
@@ -918,6 +1060,7 @@ static void cookie_permission_manager_init(CookiePermissionManager *self)
 
 	/* Set up default values */
 	priv->database=NULL;
+	priv->databaseFilename=NULL;
 	priv->askForUnknownPolicy=TRUE;
 
 	/* Hijack session's cookie jar to handle cookies requests on our own in HTTP streams
@@ -928,12 +1071,6 @@ static void cookie_permission_manager_init(CookiePermissionManager *self)
 	priv->featureIface=SOUP_SESSION_FEATURE_GET_CLASS(priv->cookieJar);
 	g_object_set_data(G_OBJECT(priv->cookieJar), "cookie-permission-manager", self);
 
-	priv->oldRequestQueued=priv->featureIface->request_queued;
-	priv->oldRequestUnqueued=priv->featureIface->request_unqueued;
-
-	priv->featureIface->request_queued=_cookie_permission_manager_request_queued;
-	priv->featureIface->request_unqueued=_cookie_permission_manager_request_unqueued;
-
 	/* Listen to changed cookies set or changed by other sources like javascript */
 	priv->cookieJarChangedID=g_signal_connect_swapped(priv->cookieJar, "changed", G_CALLBACK(_cookie_permission_manager_on_cookie_changed), self);
 }


More information about the Xfce4-commits mailing list