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.
11 #include <webkit2/webkit2.h>
12 #else /* USE_WEBKIT2 */
13 #include <webkit/webkit.h>
14 #endif /* USE_WEBKIT2 */
20 struct browser_context
{
28 static void win_cb_destroy(GtkWidget
*win
, struct browser_context
*ctx
)
30 wpa_printf(MSG_DEBUG
, "BROWSER:%s", __func__
);
35 static void browser_update_title(struct browser_context
*ctx
)
39 if (ctx
->hover_link
) {
40 gtk_window_set_title(GTK_WINDOW(ctx
->win
), ctx
->hover_link
);
44 if (ctx
->progress
== 100) {
45 gtk_window_set_title(GTK_WINDOW(ctx
->win
),
46 ctx
->title
? ctx
->title
:
47 "Hotspot 2.0 client");
51 snprintf(buf
, sizeof(buf
), "[%d%%] %s", ctx
->progress
,
52 ctx
->title
? ctx
->title
: "Hotspot 2.0 client");
53 gtk_window_set_title(GTK_WINDOW(ctx
->win
), buf
);
57 static void view_cb_notify_progress(WebKitWebView
*view
, GParamSpec
*pspec
,
58 struct browser_context
*ctx
)
61 ctx
->progress
= 100 * webkit_web_view_get_estimated_load_progress(view
);
62 #else /* USE_WEBKIT2 */
63 ctx
->progress
= 100 * webkit_web_view_get_progress(view
);
64 #endif /* USE_WEBKIT2 */
65 wpa_printf(MSG_DEBUG
, "BROWSER:%s progress=%d", __func__
,
67 browser_update_title(ctx
);
71 static void view_cb_notify_load_status(WebKitWebView
*view
, GParamSpec
*pspec
,
72 struct browser_context
*ctx
)
75 int status
= webkit_web_view_get_estimated_load_progress(view
);
76 #else /* USE_WEBKIT2 */
77 int status
= webkit_web_view_get_load_status(view
);
78 #endif /* USE_WEBKIT2 */
79 wpa_printf(MSG_DEBUG
, "BROWSER:%s load-status=%d uri=%s",
80 __func__
, status
, webkit_web_view_get_uri(view
));
84 static void view_cb_resource_request_starting(WebKitWebView
*view
,
86 WebKitWebFrame
*frame
,
87 #endif /* USE_WEBKIT2 */
88 WebKitWebResource
*res
,
90 WebKitURIRequest
*req
,
91 #else /* USE_WEBKIT2 */
92 WebKitNetworkRequest
*req
,
93 WebKitNetworkResponse
*resp
,
94 #endif /* USE_WEBKIT2 */
95 struct browser_context
*ctx
)
98 const gchar
*uri
= webkit_uri_request_get_uri(req
);
99 #else /* USE_WEBKIT2 */
100 const gchar
*uri
= webkit_network_request_get_uri(req
);
101 #endif /* USE_WEBKIT2 */
102 wpa_printf(MSG_DEBUG
, "BROWSER:%s uri=%s", __func__
, uri
);
103 if (g_str_has_suffix(uri
, "/favicon.ico")) {
105 webkit_uri_request_set_uri(req
, "about:blank");
106 #else /* USE_WEBKIT2 */
107 webkit_network_request_set_uri(req
, "about:blank");
108 #endif /* USE_WEBKIT2 */
111 if (g_str_has_prefix(uri
, "osu://")) {
112 ctx
->success
= atoi(uri
+ 6);
115 if (g_str_has_prefix(uri
, "http://localhost:12345")) {
117 * This is used as a special trigger to indicate that the
118 * user exchange has been completed.
126 static gboolean
view_cb_mime_type_policy_decision(
129 WebKitWebFrame
*frame
, WebKitNetworkRequest
*req
,
130 gchar
*mime
, WebKitWebPolicyDecision
*policy
,
131 #else /* USE_WEBKIT2 */
132 WebKitPolicyDecision
*policy
,
133 WebKitPolicyDecisionType type
,
134 #endif /* USE_WEBKIT2 */
135 struct browser_context
*ctx
)
138 wpa_printf(MSG_DEBUG
, "BROWSER:%s type=%d", __func__
, type
);
140 case WEBKIT_POLICY_DECISION_TYPE_RESPONSE
: {
141 /* This function makes webkit send a download signal for all
142 * unknown mime types. */
143 WebKitResponsePolicyDecision
*response
;
145 response
= WEBKIT_RESPONSE_POLICY_DECISION(policy
);
146 if (!webkit_response_policy_decision_is_mime_type_supported(
148 webkit_policy_decision_download(policy
);
156 #else /* USE_WEBKIT2 */
157 wpa_printf(MSG_DEBUG
, "BROWSER:%s mime=%s", __func__
, mime
);
159 if (!webkit_web_view_can_show_mime_type(view
, mime
)) {
160 webkit_web_policy_decision_download(policy
);
163 #endif /* USE_WEBKIT2 */
170 static gboolean
view_cb_download_requested(WebKitWebView
*view
,
172 struct browser_context
*ctx
)
175 uri
= webkit_download_get_uri(dl
);
176 wpa_printf(MSG_DEBUG
, "BROWSER:%s uri=%s", __func__
, uri
);
179 #endif /* USE_WEBKIT2 */
182 static void view_cb_hovering_over_link(WebKitWebView
*view
, gchar
*title
,
183 gchar
*uri
, struct browser_context
*ctx
)
185 wpa_printf(MSG_DEBUG
, "BROWSER:%s title=%s uri=%s", __func__
, title
,
187 os_free(ctx
->hover_link
);
189 ctx
->hover_link
= os_strdup(uri
);
191 ctx
->hover_link
= NULL
;
193 browser_update_title(ctx
);
198 static void view_cb_title_changed(WebKitWebView
*view
, WebKitWebFrame
*frame
,
200 struct browser_context
*ctx
)
202 wpa_printf(MSG_DEBUG
, "BROWSER:%s title=%s", __func__
, title
);
204 ctx
->title
= os_strdup(title
);
205 browser_update_title(ctx
);
207 #endif /* USE_WEBKIT2 */
210 int hs20_web_browser(const char *url
)
215 WebKitSettings
*settings
;
216 #else /* USE_WEBKIT2 */
217 WebKitWebSettings
*settings
;
219 #endif /* USE_WEBKIT2 */
220 struct browser_context ctx
;
222 memset(&ctx
, 0, sizeof(ctx
));
223 if (!gtk_init_check(NULL
, NULL
))
227 s
= webkit_get_default_session();
228 g_object_set(G_OBJECT(s
), "ssl-ca-file",
229 "/etc/ssl/certs/ca-certificates.crt", NULL
);
230 g_object_set(G_OBJECT(s
), "ssl-strict", FALSE
, NULL
);
231 #endif /* USE_WEBKIT2 */
233 ctx
.win
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
234 gtk_window_set_role(GTK_WINDOW(ctx
.win
), "Hotspot 2.0 client");
235 gtk_window_set_default_size(GTK_WINDOW(ctx
.win
), 800, 600);
237 scroll
= gtk_scrolled_window_new(NULL
, NULL
);
238 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll
),
239 GTK_POLICY_NEVER
, GTK_POLICY_NEVER
);
241 g_signal_connect(G_OBJECT(ctx
.win
), "destroy",
242 G_CALLBACK(win_cb_destroy
), &ctx
);
244 view
= WEBKIT_WEB_VIEW(webkit_web_view_new());
245 g_signal_connect(G_OBJECT(view
), "notify::progress",
246 G_CALLBACK(view_cb_notify_progress
), &ctx
);
247 g_signal_connect(G_OBJECT(view
), "notify::load-status",
248 G_CALLBACK(view_cb_notify_load_status
), &ctx
);
250 g_signal_connect(G_OBJECT(view
), "resource-load-started",
251 G_CALLBACK(view_cb_resource_request_starting
), &ctx
);
252 g_signal_connect(G_OBJECT(view
), "decide-policy",
253 G_CALLBACK(view_cb_mime_type_policy_decision
), &ctx
);
254 /* TODO: Implement these?
255 g_signal_connect(G_OBJECT(view), "download-started",
256 G_CALLBACK(view_cb_download_requested), &ctx);
257 g_signal_connect(G_OBJECT(view), "notify::title",
258 G_CALLBACK(view_cb_title_changed), &ctx);
260 #else /* USE_WEBKIT2 */
261 g_signal_connect(G_OBJECT(view
), "resource-request-starting",
262 G_CALLBACK(view_cb_resource_request_starting
), &ctx
);
263 g_signal_connect(G_OBJECT(view
), "mime-type-policy-decision-requested",
264 G_CALLBACK(view_cb_mime_type_policy_decision
), &ctx
);
265 g_signal_connect(G_OBJECT(view
), "download-requested",
266 G_CALLBACK(view_cb_download_requested
), &ctx
);
267 g_signal_connect(G_OBJECT(view
), "title-changed",
268 G_CALLBACK(view_cb_title_changed
), &ctx
);
269 #endif /* USE_WEBKIT2 */
271 g_signal_connect(G_OBJECT(view
), "hovering-over-link",
272 G_CALLBACK(view_cb_hovering_over_link
), &ctx
);
274 gtk_container_add(GTK_CONTAINER(scroll
), GTK_WIDGET(view
));
275 gtk_container_add(GTK_CONTAINER(ctx
.win
), GTK_WIDGET(scroll
));
277 gtk_widget_grab_focus(GTK_WIDGET(view
));
278 gtk_widget_show_all(ctx
.win
);
280 settings
= webkit_web_view_get_settings(view
);
281 g_object_set(G_OBJECT(settings
), "user-agent",
282 "Mozilla/5.0 (X11; U; Unix; en-US) "
283 "AppleWebKit/537.15 (KHTML, like Gecko) "
284 "hs20-client/1.0", NULL
);
285 g_object_set(G_OBJECT(settings
), "auto-load-images", TRUE
, NULL
);
287 webkit_web_view_load_uri(view
, url
);
290 gtk_widget_destroy(ctx
.win
);
291 while (gtk_events_pending())
292 gtk_main_iteration();
294 free(ctx
.hover_link
);