static void colorful_tabs_app_add_browser_cb (MidoriApp* app, MidoriBrowser* browser, MidoriExtension* extension) { GtkWidget* statusbar; GtkWidget* bbox; GtkWidget* button; statusbar = katze_object_get_object (browser, "statusbar"); bbox = gtk_hbox_new (FALSE, 0); button = gtk_check_button_new_with_label (_("Tint tabs distinctly")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), midori_extension_get_boolean (extension, "tint")); gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2); gtk_widget_show (button); gtk_widget_show (bbox); gtk_box_pack_start (GTK_BOX (statusbar), bbox, FALSE, FALSE, 3); g_signal_connect (button, "toggled", G_CALLBACK (colorful_tabs_button_toggled_cb), extension); g_signal_connect (browser, "add-tab", G_CALLBACK (colorful_tabs_browser_add_tab_cb), extension); g_signal_connect (extension, "deactivate", G_CALLBACK (colorful_tabs_deactivate_cb), bbox); }
static void formhistory_app_add_browser_cb (MidoriApp* app, MidoriBrowser* browser, MidoriExtension* extension) { GtkAccelGroup* acg = gtk_accel_group_new (); GtkActionGroup* action_group = midori_browser_get_action_group (browser); GtkAction* action = gtk_action_new ("FormHistoryToggleState", _("Toggle form history state"), _("Activate or deactivate form history for the current tab."), NULL); gtk_window_add_accel_group (GTK_WINDOW (browser), acg); g_object_set_data (G_OBJECT (browser), "FormHistoryExtension", extension); g_signal_connect (action, "activate", G_CALLBACK (formhistory_toggle_state_cb), browser); gtk_action_group_add_action_with_accel (action_group, action, "<Ctrl><Shift>F"); gtk_action_set_accel_group (action, acg); gtk_action_connect_accelerator (action); if (midori_extension_get_boolean (extension, "always-load")) { GList* tabs = midori_browser_get_tabs (browser); for (; tabs; tabs = g_list_next (tabs)) formhistory_add_tab_cb (browser, tabs->data, extension); g_list_free (tabs); g_signal_connect (browser, "add-tab", G_CALLBACK (formhistory_add_tab_cb), extension); } g_signal_connect (extension, "deactivate", G_CALLBACK (formhistory_deactivate_cb), browser); }
static void colorful_tabs_button_toggled_cb (GtkWidget* button, MidoriExtension* extension) { MidoriBrowser* browser = MIDORI_BROWSER (gtk_widget_get_toplevel (button)); midori_extension_set_boolean (extension, "tint", !midori_extension_get_boolean (extension, "tint")); midori_browser_foreach (browser, (GtkCallback)colorful_tabs_browser_foreach_cb, extension); }
static void colorful_tabs_view_notify_uri_cb (MidoriView* view, GParamSpec* pspec, MidoriExtension* extension) { GtkWidget* label; SoupURI* uri; gchar* hash; gchar* colorstr; GdkColor color; label = midori_view_get_proxy_tab_label (view); if (!midori_extension_get_boolean (extension, "tint")) { gtk_widget_modify_bg (label, GTK_STATE_NORMAL, NULL); gtk_widget_modify_bg (label, GTK_STATE_ACTIVE, NULL); return; } /* Find a color that is unique to an address. We merely compute a hash value, pick the first 6 + 1 characters and turn the first into a hash sign, ie. #8b424b. In case a color is too dark, we lighten it up a litte. Finally we make the event box visible and modify its background. */ if ((uri = soup_uri_new (midori_view_get_display_uri (view))) && uri->host) { hash = g_compute_checksum_for_string (G_CHECKSUM_MD5, uri->host, -1); soup_uri_free (uri); colorstr = g_strndup (hash, 6 + 1); g_free (hash); colorstr[0] = '#'; gdk_color_parse (colorstr, &color); if (color.red < 35000) color.red += 25000 + (color.blue + 1) / 2; if (color.green < 35000) color.green += 25000 + (color.red + 1) / 2; if (color.blue < 35000) color.blue += 25000 + (color.green + 1) / 2; gtk_event_box_set_visible_window (GTK_EVENT_BOX (label), TRUE); gtk_widget_modify_bg (label, GTK_STATE_NORMAL, &color); gtk_widget_modify_bg (label, GTK_STATE_ACTIVE, &color); } else { gtk_widget_modify_bg (label, GTK_STATE_NORMAL, NULL); gtk_widget_modify_bg (label, GTK_STATE_ACTIVE, NULL); } }
static void formhistory_preferences_response_cb (GtkWidget* dialog, gint response_id, MidoriExtension* extension) { GtkWidget* checkbox; gboolean old_state; gboolean new_state; MidoriApp* app; KatzeArray* browsers; MidoriBrowser* browser; if (response_id == GTK_RESPONSE_APPLY) { checkbox = g_object_get_data (G_OBJECT (dialog), "always-load-checkbox"); new_state = !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbox)); old_state = midori_extension_get_boolean (extension, "always-load"); if (old_state != new_state) { midori_extension_set_boolean (extension, "always-load", new_state); app = midori_extension_get_app (extension); browsers = katze_object_get_object (app, "browsers"); KATZE_ARRAY_FOREACH_ITEM (browser, browsers) { GList* tabs = midori_browser_get_tabs (browser); for (; tabs; tabs = g_list_next (tabs)) formhistory_deactivate_tab (tabs->data, extension); g_signal_handlers_disconnect_by_func ( browser, formhistory_add_tab_cb, extension); if (new_state) { for (; tabs; tabs = g_list_next (tabs)) formhistory_add_tab_cb (browser, tabs->data, extension); g_signal_connect (browser, "add-tab", G_CALLBACK (formhistory_add_tab_cb), extension); } g_list_free (tabs); }
static gint _cookie_permission_manager_ask_for_policy(CookiePermissionManager *self, MidoriView *inView, SoupMessage *inMessage, GSList *inUnknownCookies) { /* 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)); modalInfo=g_new0(CookiePermissionManagerModalInfobar, 1); /* Create a copy of cookies and sort them */ sortedCookies=_cookie_permission_manager_get_number_domains_and_cookies(self, inUnknownCookies, &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 */ G_TYPE_STRING, /* PATH_COLUMN */ G_TYPE_STRING, /* NAME_COLUMN */ G_TYPE_STRING, /* VALUE_COLUMN */ G_TYPE_STRING /* EXPIRE_DATE_COLUMN */); for(cookies=sortedCookies; cookies; cookies=cookies->next) { SoupCookie *cookie=(SoupCookie*)cookies->data; SoupDate *cookieDate=soup_cookie_get_expires(cookie); 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, &listIter, DOMAIN_COLUMN, soup_cookie_get_domain(cookie), PATH_COLUMN, soup_cookie_get_path(cookie), NAME_COLUMN, soup_cookie_get_name(cookie), VALUE_COLUMN, soup_cookie_get_value(cookie), EXPIRE_DATE_COLUMN, text, -1); g_free(text); } #endif /* Create description text */ 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 text=g_strdup_printf(_("The website %s wants to store a cookie."), cookieDomain); } else { text=g_strdup_printf(_("Multiple websites want to store %d cookies in total."), numberCookies); } /* 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); /* 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_full(G_OBJECT(infobar), "cookie-permission-manager-infobar-data", modalInfo, (GDestroyNotify)g_free); /* FIXME: Find a way to add "details" widget */ #ifndef NO_INFOBAR_DETAILS /* Get content area of infobar */ contentArea=gtk_info_bar_get_content_area(GTK_INFO_BAR(infobar)); /* Create list and set up columns of list */ list=gtk_tree_view_new_with_model(GTK_TREE_MODEL(listStore)); #ifndef HAVE_GTK3 gtk_widget_set_size_request(list, -1, 100); #endif renderer=gtk_cell_renderer_text_new(); column=gtk_tree_view_column_new_with_attributes(_("Domain"), renderer, "text", DOMAIN_COLUMN, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(list), column); renderer=gtk_cell_renderer_text_new(); column=gtk_tree_view_column_new_with_attributes(_("Path"), renderer, "text", PATH_COLUMN, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(list), column); renderer=gtk_cell_renderer_text_new(); column=gtk_tree_view_column_new_with_attributes(_("Name"), renderer, "text", NAME_COLUMN, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(list), column); renderer=gtk_cell_renderer_text_new(); column=gtk_tree_view_column_new_with_attributes(_("Value"), renderer, "text", VALUE_COLUMN, NULL); g_object_set(G_OBJECT(renderer), "ellipsize", PANGO_ELLIPSIZE_END, "width-chars", 30, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(list), column); renderer=gtk_cell_renderer_text_new(); column=gtk_tree_view_column_new_with_attributes(_("Expire date"), renderer, "text", EXPIRE_DATE_COLUMN, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(list), column); scrolled=gtk_scrolled_window_new(NULL, NULL); #ifdef HAVE_GTK3 gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(scrolled), 100); #endif gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_container_add(GTK_CONTAINER(scrolled), list); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); gtk_container_add(GTK_CONTAINER(expander), scrolled); gtk_widget_show_all(vbox); gtk_container_add(GTK_CONTAINER(contentArea), vbox); /* Set state of expander based on config 'show-details-when-ask' */ 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 /* Show all widgets of info bar */ gtk_widget_show_all(infobar); /* 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); /* 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); 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(modalInfo->response!=COOKIE_PERMISSION_MANAGER_POLICY_UNDETERMINED) { const gchar *lastDomain=NULL; /* Iterate through cookies and store decision for each domain once */ for(cookies=sortedCookies; cookies; cookies=cookies->next) { SoupCookie *cookie=(SoupCookie*)cookies->data; const gchar *cookieDomain=soup_cookie_get_domain(cookie); if(*cookieDomain=='.') cookieDomain++; /* Store decision if new domain found while iterating through cookies */ if(!lastDomain || g_ascii_strcasecmp(lastDomain, cookieDomain)!=0) { gchar *sql; gchar *error=NULL; gint success; sql=sqlite3_mprintf("INSERT OR REPLACE INTO policies (domain, value) VALUES ('%q', %d);", cookieDomain, 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); sqlite3_free(sql); lastDomain=cookieDomain; } } } /* Free up allocated resources */ g_slist_free(sortedCookies); /* Return response */ return(modalInfo->response==COOKIE_PERMISSION_MANAGER_POLICY_UNDETERMINED ? COOKIE_PERMISSION_MANAGER_POLICY_BLOCK : modalInfo->response); }