Browse Source

HS 2.0R2: Add wrapper functions for WebKit

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
Jouni Malinen 12 years ago
parent
commit
d0b79d74b6
2 changed files with 240 additions and 0 deletions
  1. 219 0
      src/utils/browser.c
  2. 21 0
      src/utils/browser.h

+ 219 - 0
src/utils/browser.c

@@ -0,0 +1,219 @@
+/*
+ * Hotspot 2.0 client - Web browser using WebKit
+ * Copyright (c) 2013, Qualcomm Atheros, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+#include <webkit/webkit.h>
+
+#include "common.h"
+#include "browser.h"
+
+
+struct browser_context {
+	GtkWidget *win;
+	int success;
+	int progress;
+	char *hover_link;
+	char *title;
+};
+
+static void win_cb_destroy(GtkWidget *win, struct browser_context *ctx)
+{
+	wpa_printf(MSG_DEBUG, "BROWSER:%s", __func__);
+	gtk_main_quit();
+}
+
+
+static void browser_update_title(struct browser_context *ctx)
+{
+	char buf[100];
+
+	if (ctx->hover_link) {
+		gtk_window_set_title(GTK_WINDOW(ctx->win), ctx->hover_link);
+		return;
+	}
+
+	if (ctx->progress == 100) {
+		gtk_window_set_title(GTK_WINDOW(ctx->win),
+				     ctx->title ? ctx->title :
+				     "Hotspot 2.0 client");
+		return;
+	}
+
+	snprintf(buf, sizeof(buf), "[%d%%] %s", ctx->progress,
+		 ctx->title ? ctx->title : "Hotspot 2.0 client");
+	gtk_window_set_title(GTK_WINDOW(ctx->win), buf);
+}
+
+
+static void view_cb_notify_progress(WebKitWebView *view, GParamSpec *pspec,
+				    struct browser_context *ctx)
+{
+	ctx->progress = 100 * webkit_web_view_get_progress(view);
+	wpa_printf(MSG_DEBUG, "BROWSER:%s progress=%d", __func__,
+		   ctx->progress);
+	browser_update_title(ctx);
+}
+
+
+static void view_cb_notify_load_status(WebKitWebView *view, GParamSpec *pspec,
+				       struct browser_context *ctx)
+{
+	int status = webkit_web_view_get_load_status(view);
+	wpa_printf(MSG_DEBUG, "BROWSER:%s load-status=%d uri=%s",
+		   __func__, status, webkit_web_view_get_uri(view));
+}
+
+
+static void view_cb_resource_request_starting(WebKitWebView *view,
+					      WebKitWebFrame *frame,
+					      WebKitWebResource *res,
+					      WebKitNetworkRequest *req,
+					      WebKitNetworkResponse *resp,
+					      struct browser_context *ctx)
+{
+	const gchar *uri = webkit_network_request_get_uri(req);
+	wpa_printf(MSG_DEBUG, "BROWSER:%s uri=%s", __func__, uri);
+	if (g_str_has_suffix(uri, "/favicon.ico"))
+		webkit_network_request_set_uri(req, "about:blank");
+	if (g_str_has_prefix(uri, "osu://")) {
+		ctx->success = atoi(uri + 6);
+		gtk_main_quit();
+	}
+	if (g_str_has_prefix(uri, "http://localhost:12345")) {
+		/*
+		 * This is used as a special trigger to indicate that the
+		 * user exchange has been completed.
+		 */
+		ctx->success = 1;
+		gtk_main_quit();
+	}
+}
+
+
+static gboolean view_cb_mime_type_policy_decision(
+	WebKitWebView *view, WebKitWebFrame *frame, WebKitNetworkRequest *req,
+	gchar *mime, WebKitWebPolicyDecision *policy,
+	struct browser_context *ctx)
+{
+	wpa_printf(MSG_DEBUG, "BROWSER:%s mime=%s", __func__, mime);
+
+	if (!webkit_web_view_can_show_mime_type(view, mime)) {
+		webkit_web_policy_decision_download(policy);
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+
+static gboolean view_cb_download_requested(WebKitWebView *view,
+					   WebKitDownload *dl,
+					   struct browser_context *ctx)
+{
+	const gchar *uri;
+	uri = webkit_download_get_uri(dl);
+	wpa_printf(MSG_DEBUG, "BROWSER:%s uri=%s", __func__, uri);
+	return FALSE;
+}
+
+
+static void view_cb_hovering_over_link(WebKitWebView *view, gchar *title,
+				       gchar *uri, struct browser_context *ctx)
+{
+	wpa_printf(MSG_DEBUG, "BROWSER:%s title=%s uri=%s", __func__, title,
+		   uri);
+	os_free(ctx->hover_link);
+	if (uri)
+		ctx->hover_link = os_strdup(uri);
+	else
+		ctx->hover_link = NULL;
+
+	browser_update_title(ctx);
+}
+
+
+static void view_cb_title_changed(WebKitWebView *view, WebKitWebFrame *frame,
+				  const char *title,
+				  struct browser_context *ctx)
+{
+	wpa_printf(MSG_DEBUG, "BROWSER:%s title=%s", __func__, title);
+	os_free(ctx->title);
+	ctx->title = os_strdup(title);
+	browser_update_title(ctx);
+}
+
+
+int hs20_web_browser(const char *url)
+{
+	GtkWidget *scroll;
+	SoupSession *s;
+	WebKitWebView *view;
+	WebKitWebSettings *settings;
+	struct browser_context ctx;
+
+	memset(&ctx, 0, sizeof(ctx));
+	if (!gtk_init_check(NULL, NULL))
+		return -1;
+
+	s = webkit_get_default_session();
+	g_object_set(G_OBJECT(s), "ssl-ca-file",
+		     "/etc/ssl/certs/ca-certificates.crt", NULL);
+	g_object_set(G_OBJECT(s), "ssl-strict", FALSE, NULL);
+
+	ctx.win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+	gtk_window_set_wmclass(GTK_WINDOW(ctx.win), "Hotspot 2.0 client",
+			       "Hotspot 2.0 client");
+	gtk_window_set_default_size(GTK_WINDOW(ctx.win), 800, 600);
+
+	scroll = gtk_scrolled_window_new(NULL, NULL);
+	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
+				       GTK_POLICY_NEVER, GTK_POLICY_NEVER);
+
+	g_signal_connect(G_OBJECT(ctx.win), "destroy",
+			 G_CALLBACK(win_cb_destroy), &ctx);
+
+	view = WEBKIT_WEB_VIEW(webkit_web_view_new());
+	g_signal_connect(G_OBJECT(view), "notify::progress",
+			 G_CALLBACK(view_cb_notify_progress), &ctx);
+	g_signal_connect(G_OBJECT(view), "notify::load-status",
+			 G_CALLBACK(view_cb_notify_load_status), &ctx);
+	g_signal_connect(G_OBJECT(view), "resource-request-starting",
+			 G_CALLBACK(view_cb_resource_request_starting), &ctx);
+	g_signal_connect(G_OBJECT(view), "mime-type-policy-decision-requested",
+			 G_CALLBACK(view_cb_mime_type_policy_decision), &ctx);
+	g_signal_connect(G_OBJECT(view), "download-requested",
+			 G_CALLBACK(view_cb_download_requested), &ctx);
+	g_signal_connect(G_OBJECT(view), "hovering-over-link",
+			 G_CALLBACK(view_cb_hovering_over_link), &ctx);
+	g_signal_connect(G_OBJECT(view), "title-changed",
+			 G_CALLBACK(view_cb_title_changed), &ctx);
+
+	gtk_container_add(GTK_CONTAINER(scroll), GTK_WIDGET(view));
+	gtk_container_add(GTK_CONTAINER(ctx.win), GTK_WIDGET(scroll));
+
+	gtk_widget_grab_focus(GTK_WIDGET(view));
+	gtk_widget_show_all(ctx.win);
+
+	settings = webkit_web_view_get_settings(view);
+	g_object_set(G_OBJECT(settings), "user-agent",
+		     "Mozilla/5.0 (X11; U; Unix; en-US) "
+		     "AppleWebKit/537.15 (KHTML, like Gecko) "
+		     "hs20-client/1.0", NULL);
+	g_object_set(G_OBJECT(settings), "auto-load-images", TRUE, NULL);
+
+	webkit_web_view_load_uri(view, url);
+
+	gtk_main();
+	gtk_widget_destroy(ctx.win);
+	while (gtk_events_pending())
+		gtk_main_iteration();
+
+	free(ctx.hover_link);
+	free(ctx.title);
+	return ctx.success;
+}

+ 21 - 0
src/utils/browser.h

@@ -0,0 +1,21 @@
+/*
+ * Hotspot 2.0 client - Web browser
+ * Copyright (c) 2013, Qualcomm Atheros, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef BROWSER_H
+#define BROWSER_H
+
+#ifdef CONFIG_NO_BROWSER
+static inline int hs20_web_browser(const char *url)
+{
+	return -1;
+}
+#else /* CONFIG_NO_BROWSER */
+int hs20_web_browser(const char *url);
+#endif /* CONFIG_NO_BROWSER */
+
+#endif /* BROWSER_H */