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