2 * Hotspot 2.0 client - Web browser using WebKit
3 * Copyright (c) 2013, Qualcomm Atheros, Inc.
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
10 #include <webkit/webkit.h>
16 struct browser_context {
24 static void win_cb_destroy(GtkWidget *win, struct browser_context *ctx)
26 wpa_printf(MSG_DEBUG, "BROWSER:%s", __func__);
31 static void browser_update_title(struct browser_context *ctx)
35 if (ctx->hover_link) {
36 gtk_window_set_title(GTK_WINDOW(ctx->win), ctx->hover_link);
40 if (ctx->progress == 100) {
41 gtk_window_set_title(GTK_WINDOW(ctx->win),
42 ctx->title ? ctx->title :
43 "Hotspot 2.0 client");
47 snprintf(buf, sizeof(buf), "[%d%%] %s", ctx->progress,
48 ctx->title ? ctx->title : "Hotspot 2.0 client");
49 gtk_window_set_title(GTK_WINDOW(ctx->win), buf);
53 static void view_cb_notify_progress(WebKitWebView *view, GParamSpec *pspec,
54 struct browser_context *ctx)
56 ctx->progress = 100 * webkit_web_view_get_progress(view);
57 wpa_printf(MSG_DEBUG, "BROWSER:%s progress=%d", __func__,
59 browser_update_title(ctx);
63 static void view_cb_notify_load_status(WebKitWebView *view, GParamSpec *pspec,
64 struct browser_context *ctx)
66 int status = webkit_web_view_get_load_status(view);
67 wpa_printf(MSG_DEBUG, "BROWSER:%s load-status=%d uri=%s",
68 __func__, status, webkit_web_view_get_uri(view));
72 static void view_cb_resource_request_starting(WebKitWebView *view,
73 WebKitWebFrame *frame,
74 WebKitWebResource *res,
75 WebKitNetworkRequest *req,
76 WebKitNetworkResponse *resp,
77 struct browser_context *ctx)
79 const gchar *uri = webkit_network_request_get_uri(req);
80 wpa_printf(MSG_DEBUG, "BROWSER:%s uri=%s", __func__, uri);
81 if (g_str_has_suffix(uri, "/favicon.ico"))
82 webkit_network_request_set_uri(req, "about:blank");
83 if (g_str_has_prefix(uri, "osu://")) {
84 ctx->success = atoi(uri + 6);
87 if (g_str_has_prefix(uri, "http://localhost:12345")) {
89 * This is used as a special trigger to indicate that the
90 * user exchange has been completed.
98 static gboolean view_cb_mime_type_policy_decision(
99 WebKitWebView *view, WebKitWebFrame *frame, WebKitNetworkRequest *req,
100 gchar *mime, WebKitWebPolicyDecision *policy,
101 struct browser_context *ctx)
103 wpa_printf(MSG_DEBUG, "BROWSER:%s mime=%s", __func__, mime);
105 if (!webkit_web_view_can_show_mime_type(view, mime)) {
106 webkit_web_policy_decision_download(policy);
114 static gboolean view_cb_download_requested(WebKitWebView *view,
116 struct browser_context *ctx)
119 uri = webkit_download_get_uri(dl);
120 wpa_printf(MSG_DEBUG, "BROWSER:%s uri=%s", __func__, uri);
125 static void view_cb_hovering_over_link(WebKitWebView *view, gchar *title,
126 gchar *uri, struct browser_context *ctx)
128 wpa_printf(MSG_DEBUG, "BROWSER:%s title=%s uri=%s", __func__, title,
130 os_free(ctx->hover_link);
132 ctx->hover_link = os_strdup(uri);
134 ctx->hover_link = NULL;
136 browser_update_title(ctx);
140 static void view_cb_title_changed(WebKitWebView *view, WebKitWebFrame *frame,
142 struct browser_context *ctx)
144 wpa_printf(MSG_DEBUG, "BROWSER:%s title=%s", __func__, title);
146 ctx->title = os_strdup(title);
147 browser_update_title(ctx);
151 int hs20_web_browser(const char *url)
156 WebKitWebSettings *settings;
157 struct browser_context ctx;
159 memset(&ctx, 0, sizeof(ctx));
160 if (!gtk_init_check(NULL, NULL))
163 s = webkit_get_default_session();
164 g_object_set(G_OBJECT(s), "ssl-ca-file",
165 "/etc/ssl/certs/ca-certificates.crt", NULL);
166 g_object_set(G_OBJECT(s), "ssl-strict", FALSE, NULL);
168 ctx.win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
169 gtk_window_set_wmclass(GTK_WINDOW(ctx.win), "Hotspot 2.0 client",
170 "Hotspot 2.0 client");
171 gtk_window_set_default_size(GTK_WINDOW(ctx.win), 800, 600);
173 scroll = gtk_scrolled_window_new(NULL, NULL);
174 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
175 GTK_POLICY_NEVER, GTK_POLICY_NEVER);
177 g_signal_connect(G_OBJECT(ctx.win), "destroy",
178 G_CALLBACK(win_cb_destroy), &ctx);
180 view = WEBKIT_WEB_VIEW(webkit_web_view_new());
181 g_signal_connect(G_OBJECT(view), "notify::progress",
182 G_CALLBACK(view_cb_notify_progress), &ctx);
183 g_signal_connect(G_OBJECT(view), "notify::load-status",
184 G_CALLBACK(view_cb_notify_load_status), &ctx);
185 g_signal_connect(G_OBJECT(view), "resource-request-starting",
186 G_CALLBACK(view_cb_resource_request_starting), &ctx);
187 g_signal_connect(G_OBJECT(view), "mime-type-policy-decision-requested",
188 G_CALLBACK(view_cb_mime_type_policy_decision), &ctx);
189 g_signal_connect(G_OBJECT(view), "download-requested",
190 G_CALLBACK(view_cb_download_requested), &ctx);
191 g_signal_connect(G_OBJECT(view), "hovering-over-link",
192 G_CALLBACK(view_cb_hovering_over_link), &ctx);
193 g_signal_connect(G_OBJECT(view), "title-changed",
194 G_CALLBACK(view_cb_title_changed), &ctx);
196 gtk_container_add(GTK_CONTAINER(scroll), GTK_WIDGET(view));
197 gtk_container_add(GTK_CONTAINER(ctx.win), GTK_WIDGET(scroll));
199 gtk_widget_grab_focus(GTK_WIDGET(view));
200 gtk_widget_show_all(ctx.win);
202 settings = webkit_web_view_get_settings(view);
203 g_object_set(G_OBJECT(settings), "user-agent",
204 "Mozilla/5.0 (X11; U; Unix; en-US) "
205 "AppleWebKit/537.15 (KHTML, like Gecko) "
206 "hs20-client/1.0", NULL);
207 g_object_set(G_OBJECT(settings), "auto-load-images", TRUE, NULL);
209 webkit_web_view_load_uri(view, url);
212 gtk_widget_destroy(ctx.win);
213 while (gtk_events_pending())
214 gtk_main_iteration();
216 free(ctx.hover_link);