xref: /dflybsd-src/contrib/wpa_supplicant/src/utils/browser.c (revision 3a84a4273475ed07d0ab1c2dfeffdfedef35d9cd)
1*a1157835SDaniel Fojt /*
2*a1157835SDaniel Fojt  * Hotspot 2.0 client - Web browser using WebKit
3*a1157835SDaniel Fojt  * Copyright (c) 2013, Qualcomm Atheros, Inc.
4*a1157835SDaniel Fojt  *
5*a1157835SDaniel Fojt  * This software may be distributed under the terms of the BSD license.
6*a1157835SDaniel Fojt  * See README for more details.
7*a1157835SDaniel Fojt  */
8*a1157835SDaniel Fojt 
9*a1157835SDaniel Fojt #include "includes.h"
10*a1157835SDaniel Fojt #include <webkit/webkit.h>
11*a1157835SDaniel Fojt 
12*a1157835SDaniel Fojt #include "common.h"
13*a1157835SDaniel Fojt #include "browser.h"
14*a1157835SDaniel Fojt 
15*a1157835SDaniel Fojt 
16*a1157835SDaniel Fojt struct browser_context {
17*a1157835SDaniel Fojt 	GtkWidget *win;
18*a1157835SDaniel Fojt 	int success;
19*a1157835SDaniel Fojt 	int progress;
20*a1157835SDaniel Fojt 	char *hover_link;
21*a1157835SDaniel Fojt 	char *title;
22*a1157835SDaniel Fojt };
23*a1157835SDaniel Fojt 
win_cb_destroy(GtkWidget * win,struct browser_context * ctx)24*a1157835SDaniel Fojt static void win_cb_destroy(GtkWidget *win, struct browser_context *ctx)
25*a1157835SDaniel Fojt {
26*a1157835SDaniel Fojt 	wpa_printf(MSG_DEBUG, "BROWSER:%s", __func__);
27*a1157835SDaniel Fojt 	gtk_main_quit();
28*a1157835SDaniel Fojt }
29*a1157835SDaniel Fojt 
30*a1157835SDaniel Fojt 
browser_update_title(struct browser_context * ctx)31*a1157835SDaniel Fojt static void browser_update_title(struct browser_context *ctx)
32*a1157835SDaniel Fojt {
33*a1157835SDaniel Fojt 	char buf[100];
34*a1157835SDaniel Fojt 
35*a1157835SDaniel Fojt 	if (ctx->hover_link) {
36*a1157835SDaniel Fojt 		gtk_window_set_title(GTK_WINDOW(ctx->win), ctx->hover_link);
37*a1157835SDaniel Fojt 		return;
38*a1157835SDaniel Fojt 	}
39*a1157835SDaniel Fojt 
40*a1157835SDaniel Fojt 	if (ctx->progress == 100) {
41*a1157835SDaniel Fojt 		gtk_window_set_title(GTK_WINDOW(ctx->win),
42*a1157835SDaniel Fojt 				     ctx->title ? ctx->title :
43*a1157835SDaniel Fojt 				     "Hotspot 2.0 client");
44*a1157835SDaniel Fojt 		return;
45*a1157835SDaniel Fojt 	}
46*a1157835SDaniel Fojt 
47*a1157835SDaniel Fojt 	snprintf(buf, sizeof(buf), "[%d%%] %s", ctx->progress,
48*a1157835SDaniel Fojt 		 ctx->title ? ctx->title : "Hotspot 2.0 client");
49*a1157835SDaniel Fojt 	gtk_window_set_title(GTK_WINDOW(ctx->win), buf);
50*a1157835SDaniel Fojt }
51*a1157835SDaniel Fojt 
52*a1157835SDaniel Fojt 
view_cb_notify_progress(WebKitWebView * view,GParamSpec * pspec,struct browser_context * ctx)53*a1157835SDaniel Fojt static void view_cb_notify_progress(WebKitWebView *view, GParamSpec *pspec,
54*a1157835SDaniel Fojt 				    struct browser_context *ctx)
55*a1157835SDaniel Fojt {
56*a1157835SDaniel Fojt 	ctx->progress = 100 * webkit_web_view_get_progress(view);
57*a1157835SDaniel Fojt 	wpa_printf(MSG_DEBUG, "BROWSER:%s progress=%d", __func__,
58*a1157835SDaniel Fojt 		   ctx->progress);
59*a1157835SDaniel Fojt 	browser_update_title(ctx);
60*a1157835SDaniel Fojt }
61*a1157835SDaniel Fojt 
62*a1157835SDaniel Fojt 
view_cb_notify_load_status(WebKitWebView * view,GParamSpec * pspec,struct browser_context * ctx)63*a1157835SDaniel Fojt static void view_cb_notify_load_status(WebKitWebView *view, GParamSpec *pspec,
64*a1157835SDaniel Fojt 				       struct browser_context *ctx)
65*a1157835SDaniel Fojt {
66*a1157835SDaniel Fojt 	int status = webkit_web_view_get_load_status(view);
67*a1157835SDaniel Fojt 	wpa_printf(MSG_DEBUG, "BROWSER:%s load-status=%d uri=%s",
68*a1157835SDaniel Fojt 		   __func__, status, webkit_web_view_get_uri(view));
69*a1157835SDaniel Fojt }
70*a1157835SDaniel Fojt 
71*a1157835SDaniel Fojt 
view_cb_resource_request_starting(WebKitWebView * view,WebKitWebFrame * frame,WebKitWebResource * res,WebKitNetworkRequest * req,WebKitNetworkResponse * resp,struct browser_context * ctx)72*a1157835SDaniel Fojt static void view_cb_resource_request_starting(WebKitWebView *view,
73*a1157835SDaniel Fojt 					      WebKitWebFrame *frame,
74*a1157835SDaniel Fojt 					      WebKitWebResource *res,
75*a1157835SDaniel Fojt 					      WebKitNetworkRequest *req,
76*a1157835SDaniel Fojt 					      WebKitNetworkResponse *resp,
77*a1157835SDaniel Fojt 					      struct browser_context *ctx)
78*a1157835SDaniel Fojt {
79*a1157835SDaniel Fojt 	const gchar *uri = webkit_network_request_get_uri(req);
80*a1157835SDaniel Fojt 	wpa_printf(MSG_DEBUG, "BROWSER:%s uri=%s", __func__, uri);
81*a1157835SDaniel Fojt 	if (g_str_has_suffix(uri, "/favicon.ico"))
82*a1157835SDaniel Fojt 		webkit_network_request_set_uri(req, "about:blank");
83*a1157835SDaniel Fojt 	if (g_str_has_prefix(uri, "osu://")) {
84*a1157835SDaniel Fojt 		ctx->success = atoi(uri + 6);
85*a1157835SDaniel Fojt 		gtk_main_quit();
86*a1157835SDaniel Fojt 	}
87*a1157835SDaniel Fojt 	if (g_str_has_prefix(uri, "http://localhost:12345")) {
88*a1157835SDaniel Fojt 		/*
89*a1157835SDaniel Fojt 		 * This is used as a special trigger to indicate that the
90*a1157835SDaniel Fojt 		 * user exchange has been completed.
91*a1157835SDaniel Fojt 		 */
92*a1157835SDaniel Fojt 		ctx->success = 1;
93*a1157835SDaniel Fojt 		gtk_main_quit();
94*a1157835SDaniel Fojt 	}
95*a1157835SDaniel Fojt }
96*a1157835SDaniel Fojt 
97*a1157835SDaniel Fojt 
view_cb_mime_type_policy_decision(WebKitWebView * view,WebKitWebFrame * frame,WebKitNetworkRequest * req,gchar * mime,WebKitWebPolicyDecision * policy,struct browser_context * ctx)98*a1157835SDaniel Fojt static gboolean view_cb_mime_type_policy_decision(
99*a1157835SDaniel Fojt 	WebKitWebView *view, WebKitWebFrame *frame, WebKitNetworkRequest *req,
100*a1157835SDaniel Fojt 	gchar *mime, WebKitWebPolicyDecision *policy,
101*a1157835SDaniel Fojt 	struct browser_context *ctx)
102*a1157835SDaniel Fojt {
103*a1157835SDaniel Fojt 	wpa_printf(MSG_DEBUG, "BROWSER:%s mime=%s", __func__, mime);
104*a1157835SDaniel Fojt 
105*a1157835SDaniel Fojt 	if (!webkit_web_view_can_show_mime_type(view, mime)) {
106*a1157835SDaniel Fojt 		webkit_web_policy_decision_download(policy);
107*a1157835SDaniel Fojt 		return TRUE;
108*a1157835SDaniel Fojt 	}
109*a1157835SDaniel Fojt 
110*a1157835SDaniel Fojt 	return FALSE;
111*a1157835SDaniel Fojt }
112*a1157835SDaniel Fojt 
113*a1157835SDaniel Fojt 
view_cb_download_requested(WebKitWebView * view,WebKitDownload * dl,struct browser_context * ctx)114*a1157835SDaniel Fojt static gboolean view_cb_download_requested(WebKitWebView *view,
115*a1157835SDaniel Fojt 					   WebKitDownload *dl,
116*a1157835SDaniel Fojt 					   struct browser_context *ctx)
117*a1157835SDaniel Fojt {
118*a1157835SDaniel Fojt 	const gchar *uri;
119*a1157835SDaniel Fojt 	uri = webkit_download_get_uri(dl);
120*a1157835SDaniel Fojt 	wpa_printf(MSG_DEBUG, "BROWSER:%s uri=%s", __func__, uri);
121*a1157835SDaniel Fojt 	return FALSE;
122*a1157835SDaniel Fojt }
123*a1157835SDaniel Fojt 
124*a1157835SDaniel Fojt 
view_cb_hovering_over_link(WebKitWebView * view,gchar * title,gchar * uri,struct browser_context * ctx)125*a1157835SDaniel Fojt static void view_cb_hovering_over_link(WebKitWebView *view, gchar *title,
126*a1157835SDaniel Fojt 				       gchar *uri, struct browser_context *ctx)
127*a1157835SDaniel Fojt {
128*a1157835SDaniel Fojt 	wpa_printf(MSG_DEBUG, "BROWSER:%s title=%s uri=%s", __func__, title,
129*a1157835SDaniel Fojt 		   uri);
130*a1157835SDaniel Fojt 	os_free(ctx->hover_link);
131*a1157835SDaniel Fojt 	if (uri)
132*a1157835SDaniel Fojt 		ctx->hover_link = os_strdup(uri);
133*a1157835SDaniel Fojt 	else
134*a1157835SDaniel Fojt 		ctx->hover_link = NULL;
135*a1157835SDaniel Fojt 
136*a1157835SDaniel Fojt 	browser_update_title(ctx);
137*a1157835SDaniel Fojt }
138*a1157835SDaniel Fojt 
139*a1157835SDaniel Fojt 
view_cb_title_changed(WebKitWebView * view,WebKitWebFrame * frame,const char * title,struct browser_context * ctx)140*a1157835SDaniel Fojt static void view_cb_title_changed(WebKitWebView *view, WebKitWebFrame *frame,
141*a1157835SDaniel Fojt 				  const char *title,
142*a1157835SDaniel Fojt 				  struct browser_context *ctx)
143*a1157835SDaniel Fojt {
144*a1157835SDaniel Fojt 	wpa_printf(MSG_DEBUG, "BROWSER:%s title=%s", __func__, title);
145*a1157835SDaniel Fojt 	os_free(ctx->title);
146*a1157835SDaniel Fojt 	ctx->title = os_strdup(title);
147*a1157835SDaniel Fojt 	browser_update_title(ctx);
148*a1157835SDaniel Fojt }
149*a1157835SDaniel Fojt 
150*a1157835SDaniel Fojt 
hs20_web_browser(const char * url)151*a1157835SDaniel Fojt int hs20_web_browser(const char *url)
152*a1157835SDaniel Fojt {
153*a1157835SDaniel Fojt 	GtkWidget *scroll;
154*a1157835SDaniel Fojt 	SoupSession *s;
155*a1157835SDaniel Fojt 	WebKitWebView *view;
156*a1157835SDaniel Fojt 	WebKitWebSettings *settings;
157*a1157835SDaniel Fojt 	struct browser_context ctx;
158*a1157835SDaniel Fojt 
159*a1157835SDaniel Fojt 	memset(&ctx, 0, sizeof(ctx));
160*a1157835SDaniel Fojt 	if (!gtk_init_check(NULL, NULL))
161*a1157835SDaniel Fojt 		return -1;
162*a1157835SDaniel Fojt 
163*a1157835SDaniel Fojt 	s = webkit_get_default_session();
164*a1157835SDaniel Fojt 	g_object_set(G_OBJECT(s), "ssl-ca-file",
165*a1157835SDaniel Fojt 		     "/etc/ssl/certs/ca-certificates.crt", NULL);
166*a1157835SDaniel Fojt 	g_object_set(G_OBJECT(s), "ssl-strict", FALSE, NULL);
167*a1157835SDaniel Fojt 
168*a1157835SDaniel Fojt 	ctx.win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
169*a1157835SDaniel Fojt 	gtk_window_set_role(GTK_WINDOW(ctx.win), "Hotspot 2.0 client");
170*a1157835SDaniel Fojt 	gtk_window_set_default_size(GTK_WINDOW(ctx.win), 800, 600);
171*a1157835SDaniel Fojt 
172*a1157835SDaniel Fojt 	scroll = gtk_scrolled_window_new(NULL, NULL);
173*a1157835SDaniel Fojt 	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
174*a1157835SDaniel Fojt 				       GTK_POLICY_NEVER, GTK_POLICY_NEVER);
175*a1157835SDaniel Fojt 
176*a1157835SDaniel Fojt 	g_signal_connect(G_OBJECT(ctx.win), "destroy",
177*a1157835SDaniel Fojt 			 G_CALLBACK(win_cb_destroy), &ctx);
178*a1157835SDaniel Fojt 
179*a1157835SDaniel Fojt 	view = WEBKIT_WEB_VIEW(webkit_web_view_new());
180*a1157835SDaniel Fojt 	g_signal_connect(G_OBJECT(view), "notify::progress",
181*a1157835SDaniel Fojt 			 G_CALLBACK(view_cb_notify_progress), &ctx);
182*a1157835SDaniel Fojt 	g_signal_connect(G_OBJECT(view), "notify::load-status",
183*a1157835SDaniel Fojt 			 G_CALLBACK(view_cb_notify_load_status), &ctx);
184*a1157835SDaniel Fojt 	g_signal_connect(G_OBJECT(view), "resource-request-starting",
185*a1157835SDaniel Fojt 			 G_CALLBACK(view_cb_resource_request_starting), &ctx);
186*a1157835SDaniel Fojt 	g_signal_connect(G_OBJECT(view), "mime-type-policy-decision-requested",
187*a1157835SDaniel Fojt 			 G_CALLBACK(view_cb_mime_type_policy_decision), &ctx);
188*a1157835SDaniel Fojt 	g_signal_connect(G_OBJECT(view), "download-requested",
189*a1157835SDaniel Fojt 			 G_CALLBACK(view_cb_download_requested), &ctx);
190*a1157835SDaniel Fojt 	g_signal_connect(G_OBJECT(view), "hovering-over-link",
191*a1157835SDaniel Fojt 			 G_CALLBACK(view_cb_hovering_over_link), &ctx);
192*a1157835SDaniel Fojt 	g_signal_connect(G_OBJECT(view), "title-changed",
193*a1157835SDaniel Fojt 			 G_CALLBACK(view_cb_title_changed), &ctx);
194*a1157835SDaniel Fojt 
195*a1157835SDaniel Fojt 	gtk_container_add(GTK_CONTAINER(scroll), GTK_WIDGET(view));
196*a1157835SDaniel Fojt 	gtk_container_add(GTK_CONTAINER(ctx.win), GTK_WIDGET(scroll));
197*a1157835SDaniel Fojt 
198*a1157835SDaniel Fojt 	gtk_widget_grab_focus(GTK_WIDGET(view));
199*a1157835SDaniel Fojt 	gtk_widget_show_all(ctx.win);
200*a1157835SDaniel Fojt 
201*a1157835SDaniel Fojt 	settings = webkit_web_view_get_settings(view);
202*a1157835SDaniel Fojt 	g_object_set(G_OBJECT(settings), "user-agent",
203*a1157835SDaniel Fojt 		     "Mozilla/5.0 (X11; U; Unix; en-US) "
204*a1157835SDaniel Fojt 		     "AppleWebKit/537.15 (KHTML, like Gecko) "
205*a1157835SDaniel Fojt 		     "hs20-client/1.0", NULL);
206*a1157835SDaniel Fojt 	g_object_set(G_OBJECT(settings), "auto-load-images", TRUE, NULL);
207*a1157835SDaniel Fojt 
208*a1157835SDaniel Fojt 	webkit_web_view_load_uri(view, url);
209*a1157835SDaniel Fojt 
210*a1157835SDaniel Fojt 	gtk_main();
211*a1157835SDaniel Fojt 	gtk_widget_destroy(ctx.win);
212*a1157835SDaniel Fojt 	while (gtk_events_pending())
213*a1157835SDaniel Fojt 		gtk_main_iteration();
214*a1157835SDaniel Fojt 
215*a1157835SDaniel Fojt 	free(ctx.hover_link);
216*a1157835SDaniel Fojt 	free(ctx.title);
217*a1157835SDaniel Fojt 	return ctx.success;
218*a1157835SDaniel Fojt }
219