+void
+decidenavigation(WebKitPolicyDecision *d, Client *c)
+{
+ WebKitNavigationAction *a =
+ webkit_navigation_policy_decision_get_navigation_action(
+ WEBKIT_NAVIGATION_POLICY_DECISION(d));
+
+ switch (webkit_navigation_action_get_navigation_type(a)) {
+ case WEBKIT_NAVIGATION_TYPE_LINK_CLICKED: /* fallthrough */
+ case WEBKIT_NAVIGATION_TYPE_FORM_SUBMITTED: /* fallthrough */
+ case WEBKIT_NAVIGATION_TYPE_BACK_FORWARD: /* fallthrough */
+ case WEBKIT_NAVIGATION_TYPE_RELOAD: /* fallthrough */
+ case WEBKIT_NAVIGATION_TYPE_FORM_RESUBMITTED: /* fallthrough */
+ case WEBKIT_NAVIGATION_TYPE_OTHER: /* fallthrough */
+ default:
+ /* Do not navigate to links with a "_blank" target (popup) */
+ if (webkit_navigation_policy_decision_get_frame_name(
+ WEBKIT_NAVIGATION_POLICY_DECISION(d))) {
+ webkit_policy_decision_ignore(d);
+ } else {
+ /* Filter out navigation to different domain ? */
+ /* get action→urirequest, copy and load in new window+view
+ * on Ctrl+Click ? */
+ webkit_policy_decision_use(d);
+ }
+ break;
+ }
+}
+
+void
+decidenewwindow(WebKitPolicyDecision *d, Client *c)
+{
+ Arg arg;
+ WebKitNavigationAction *a =
+ webkit_navigation_policy_decision_get_navigation_action(
+ WEBKIT_NAVIGATION_POLICY_DECISION(d));
+
+
+ switch (webkit_navigation_action_get_navigation_type(a)) {
+ case WEBKIT_NAVIGATION_TYPE_LINK_CLICKED: /* fallthrough */
+ case WEBKIT_NAVIGATION_TYPE_FORM_SUBMITTED: /* fallthrough */
+ case WEBKIT_NAVIGATION_TYPE_BACK_FORWARD: /* fallthrough */
+ case WEBKIT_NAVIGATION_TYPE_RELOAD: /* fallthrough */
+ case WEBKIT_NAVIGATION_TYPE_FORM_RESUBMITTED:
+ /* Filter domains here */
+/* If the value of “mouse-button” is not 0, then the navigation was triggered by a mouse event.
+ * test for link clicked but no button ? */
+ arg.v = webkit_uri_request_get_uri(
+ webkit_navigation_action_get_request(a));
+ newwindow(c, &arg, 0);
+ break;
+ case WEBKIT_NAVIGATION_TYPE_OTHER: /* fallthrough */
+ default:
+ break;
+ }
+
+ webkit_policy_decision_ignore(d);
+}
+
+void
+decideresource(WebKitPolicyDecision *d, Client *c)
+{
+ int i, isascii = 1;
+ WebKitResponsePolicyDecision *r = WEBKIT_RESPONSE_POLICY_DECISION(d);
+ WebKitURIResponse *res =
+ webkit_response_policy_decision_get_response(r);
+ const gchar *uri = webkit_uri_response_get_uri(res);
+
+ if (g_str_has_suffix(uri, "/favicon.ico")) {
+ webkit_policy_decision_ignore(d);
+ return;
+ }
+
+ if (!g_str_has_prefix(uri, "http://")
+ && !g_str_has_prefix(uri, "https://")
+ && !g_str_has_prefix(uri, "about:")
+ && !g_str_has_prefix(uri, "file://")
+ && !g_str_has_prefix(uri, "data:")
+ && !g_str_has_prefix(uri, "blob:")
+ && strlen(uri) > 0) {
+ for (i = 0; i < strlen(uri); i++) {
+ if (!g_ascii_isprint(uri[i])) {
+ isascii = 0;
+ break;
+ }
+ }
+ if (isascii) {
+ handleplumb(c, uri);
+ webkit_policy_decision_ignore(d);
+ return;
+ }
+ }
+
+ if (webkit_response_policy_decision_is_mime_type_supported(r)) {
+ webkit_policy_decision_use(d);
+ } else {
+ webkit_policy_decision_ignore(d);
+ download(c, res);
+ }
+}
+
+void
+insecurecontent(WebKitWebView *v, WebKitInsecureContentEvent e, Client *c)
+{
+ c->insecure = 1;
+}
+
+void
+downloadstarted(WebKitWebContext *wc, WebKitDownload *d, Client *c)
+{
+ g_signal_connect(G_OBJECT(d), "notify::response",
+ G_CALLBACK(responsereceived), c);
+}
+
+void
+responsereceived(WebKitDownload *d, GParamSpec *ps, Client *c)
+{
+ download(c, webkit_download_get_response(d));
+ webkit_download_cancel(d);
+}
+
+void
+download(Client *c, WebKitURIResponse *r)
+{
+ Arg a = (Arg)DOWNLOAD(webkit_uri_response_get_uri(r), geturi(c));
+ spawn(c, &a);
+}
+
+void
+webprocessterminated(WebKitWebView *v, WebKitWebProcessTerminationReason r,
+ Client *c)
+{
+ fprintf(stderr, "web process terminated: %s\n",
+ r == WEBKIT_WEB_PROCESS_CRASHED ? "crashed" : "no memory");
+ closeview(v, c);
+}
+
+void
+closeview(WebKitWebView *v, Client *c)
+{
+ gtk_widget_destroy(c->win);
+}
+
+void
+destroywin(GtkWidget* w, Client *c)
+{
+ destroyclient(c);
+ if (!clients)
+ gtk_main_quit();
+}
+
+gchar *
+parseuri(const gchar *uri) {
+ guint i;
+
+ for (i = 0; i < LENGTH(searchengines); i++) {
+ if (searchengines[i].token == NULL || searchengines[i].uri == NULL ||
+ *(uri + strlen(searchengines[i].token)) != ' ')
+ continue;
+ if (g_str_has_prefix(uri, searchengines[i].token))
+ return g_strdup_printf(searchengines[i].uri,
+ uri + strlen(searchengines[i].token) + 1);
+ }
+
+ return g_strdup_printf("http://%s", uri);
+}
+
+void
+pasteuri(GtkClipboard *clipboard, const char *text, gpointer d)
+{
+ Arg a = {.v = text };
+ if (text)
+ loaduri((Client *) d, &a);
+}
+
+void
+reload(Client *c, const Arg *a)
+{
+ if (a->i)
+ webkit_web_view_reload_bypass_cache(c->view);
+ else
+ webkit_web_view_reload(c->view);
+}
+
+void
+print(Client *c, const Arg *a)
+{
+ webkit_print_operation_run_dialog(webkit_print_operation_new(c->view),
+ GTK_WINDOW(c->win));
+}
+
+void
+showcert(Client *c, const Arg *a)
+{
+ GTlsCertificate *cert = c->failedcert ? c->failedcert : c->cert;
+ GcrCertificate *gcrt;
+ GByteArray *crt;
+ GtkWidget *win;
+ GcrCertificateWidget *wcert;
+
+ if (!cert)
+ return;
+
+ g_object_get(cert, "certificate", &crt, NULL);
+ gcrt = gcr_simple_certificate_new(crt->data, crt->len);
+ g_byte_array_unref(crt);
+
+ win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ wcert = gcr_certificate_widget_new(gcrt);
+ g_object_unref(gcrt);
+
+ gtk_container_add(GTK_CONTAINER(win), GTK_WIDGET(wcert));
+ gtk_widget_show_all(win);
+}
+
+void
+clipboard(Client *c, const Arg *a)
+{
+ if (a->i) { /* load clipboard uri */
+ gtk_clipboard_request_text(gtk_clipboard_get(
+ GDK_SELECTION_PRIMARY),
+ pasteuri, c);
+ } else { /* copy uri */
+ gtk_clipboard_set_text(gtk_clipboard_get(
+ GDK_SELECTION_PRIMARY), c->targeturi
+ ? c->targeturi : geturi(c), -1);
+ }
+}
+
+void
+zoom(Client *c, const Arg *a)
+{
+ if (a->i > 0)
+ webkit_web_view_set_zoom_level(c->view,
+ curconfig[ZoomLevel].val.f + 0.1);
+ else if (a->i < 0)
+ webkit_web_view_set_zoom_level(c->view,
+ curconfig[ZoomLevel].val.f - 0.1);
+ else
+ webkit_web_view_set_zoom_level(c->view, 1.0);
+
+ curconfig[ZoomLevel].val.f = webkit_web_view_get_zoom_level(c->view);
+}
+
+static void
+msgext(Client *c, char type, const Arg *a)
+{
+ static char msg[MSGBUFSZ];
+ int ret;
+
+ if ((ret = snprintf(msg, sizeof(msg), "%c%c%c%c",
+ 4, c->pageid, type, a->i))
+ >= sizeof(msg)) {
+ fprintf(stderr, "surf: message too long: %d\n", ret);
+ return;
+ }
+
+ if (pipeout[1] && write(pipeout[1], msg, sizeof(msg)) < 0)
+ fprintf(stderr, "surf: error sending: %.*s\n", ret-2, msg+2);
+}
+
+void
+scrollv(Client *c, const Arg *a)
+{
+ msgext(c, 'v', a);
+}
+
+void
+scrollh(Client *c, const Arg *a)
+{
+ msgext(c, 'h', a);
+}
+
+void
+navigate(Client *c, const Arg *a)
+{
+ if (a->i < 0)
+ webkit_web_view_go_back(c->view);
+ else if (a->i > 0)
+ webkit_web_view_go_forward(c->view);
+}
+
+void
+stop(Client *c, const Arg *a)
+{
+ webkit_web_view_stop_loading(c->view);
+}
+
+void
+toggle(Client *c, const Arg *a)
+{
+ curconfig[a->i].val.i ^= 1;
+ setparameter(c, 1, (ParamName)a->i, &curconfig[a->i].val);
+}
+
+void
+togglefullscreen(Client *c, const Arg *a)
+{
+ /* toggling value is handled in winevent() */
+ if (c->fullscreen)
+ gtk_window_unfullscreen(GTK_WINDOW(c->win));
+ else
+ gtk_window_fullscreen(GTK_WINDOW(c->win));
+}
+
+void
+togglecookiepolicy(Client *c, const Arg *a)
+{
+ ++cookiepolicy;
+ cookiepolicy %= strlen(curconfig[CookiePolicies].val.v);
+
+ setparameter(c, 0, CookiePolicies, NULL);
+}
+
+void
+toggleinspector(Client *c, const Arg *a)
+{
+ if (webkit_web_inspector_is_attached(c->inspector))
+ webkit_web_inspector_close(c->inspector);
+ else if (curconfig[Inspector].val.i)
+ webkit_web_inspector_show(c->inspector);
+}
+
+void
+find(Client *c, const Arg *a)
+{
+ const char *s, *f;
+
+ if (a && a->i) {
+ if (a->i > 0)
+ webkit_find_controller_search_next(c->finder);
+ else
+ webkit_find_controller_search_previous(c->finder);
+ } else {
+ s = getatom(c, AtomFind);
+ f = webkit_find_controller_get_search_text(c->finder);
+
+ if (g_strcmp0(f, s) == 0) /* reset search */
+ webkit_find_controller_search(c->finder, "", findopts,
+ G_MAXUINT);
+
+ webkit_find_controller_search(c->finder, s, findopts,
+ G_MAXUINT);
+
+ if (strcmp(s, "") == 0)
+ webkit_find_controller_search_finish(c->finder);
+ }
+}
+
+void
+clicknavigate(Client *c, const Arg *a, WebKitHitTestResult *h)
+{
+ navigate(c, a);
+}
+
+void
+clicknewwindow(Client *c, const Arg *a, WebKitHitTestResult *h)
+{
+ Arg arg;
+
+ arg.v = webkit_hit_test_result_get_link_uri(h);
+ newwindow(c, &arg, a->i);
+}
+
+void
+clickexternplayer(Client *c, const Arg *a, WebKitHitTestResult *h)
+{
+ Arg arg;
+
+ arg = (Arg)VIDEOPLAY(webkit_hit_test_result_get_media_uri(h));
+ spawn(c, &arg);
+}
+
+int
+main(int argc, char *argv[])
+{
+ Arg arg;