Updating branch refs/heads/master to 3de3a71f4fb26c3c77802d5dd25f241cc216245f (commit) from 7c49465bf169c21918658438d9456bdeef0fe259 (commit)
commit 3de3a71f4fb26c3c77802d5dd25f241cc216245f Author: Christian Dywan <christ...@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); } _______________________________________________ Xfce4-commits mailing list Xfce4-commits@xfce.org https://mail.xfce.org/mailman/listinfo/xfce4-commits