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