1d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt/*
2d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt * Hotspot 2.0 client - Web browser using wpadebug on Android
3d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt * Copyright (c) 2013, Qualcomm Atheros, Inc.
4d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt *
5d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt * This software may be distributed under the terms of the BSD license.
6d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt * See README for more details.
7d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt */
8d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
9d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include "includes.h"
10d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
11d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include "common.h"
12d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include "utils/eloop.h"
13d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include "wps/http_server.h"
14d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt#include "browser.h"
15d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
16d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
17d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstruct browser_data {
18d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	int success;
19d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt};
20d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
21d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
22d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void browser_timeout(void *eloop_data, void *user_ctx)
23d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
24d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_printf(MSG_INFO, "Timeout on waiting browser interaction to "
25d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		   "complete");
26d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	eloop_terminate();
27d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
28d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
29d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
30d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtstatic void http_req(void *ctx, struct http_request *req)
31d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
32d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	struct browser_data *data = ctx;
33d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	struct wpabuf *resp;
34d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	const char *url;
35d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	int done = 0;
36d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
37d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	url = http_request_get_uri(req);
38d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_printf(MSG_INFO, "Browser response received: %s", url);
39d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
40d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (os_strcmp(url, "/") == 0) {
41d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		data->success = 1;
42d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		done = 1;
43d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	} else if (os_strncmp(url, "/osu/", 5) == 0) {
44d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		data->success = atoi(url + 5);
45d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		done = 1;
46d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
47d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
48d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	resp = wpabuf_alloc(100);
49d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (resp == NULL) {
50d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		http_request_deinit(req);
51d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		if (done)
52d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			eloop_terminate();
53d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return;
54d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
55d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpabuf_put_str(resp, "User input completed");
56d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
57d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (done) {
58d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		eloop_cancel_timeout(browser_timeout, NULL, NULL);
59d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		eloop_register_timeout(0, 500000, browser_timeout, &data, NULL);
60d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
61d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
62d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	http_request_send_and_deinit(req, resp);
63d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
64d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
65d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
66d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtint hs20_web_browser(const char *url)
67d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{
68d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	char cmd[2000];
69d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	int ret;
70d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	struct http_server *http;
71d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	struct in_addr addr;
72d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	struct browser_data data;
73d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
74d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_printf(MSG_INFO, "Launching wpadebug browser to %s", url);
75d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
76d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_memset(&data, 0, sizeof(data));
77d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
78d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	ret = os_snprintf(cmd, sizeof(cmd),
79a7b06faf528d1765cc2712cc9a31ad45d7c3110bDmitry Shmidt			  "start -a android.action.MAIN "
80d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			  "-c android.intent.category.LAUNCHER "
81d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			  "-n w1.fi.wpadebug/.WpaWebViewActivity "
82d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt			  "-e w1.fi.wpadebug.URL '%s'", url);
83d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (ret < 0 || (size_t) ret >= sizeof(cmd)) {
84d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_ERROR, "Too long URL");
85d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return -1;
86d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
87d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
88d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (eloop_init() < 0) {
89d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_ERROR, "eloop_init failed");
90d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return -1;
91d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
92d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	addr.s_addr = htonl((127 << 24) | 1);
93d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	http = http_server_init(&addr, 12345, http_req, &data);
94d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (http == NULL) {
95d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_ERROR, "http_server_init failed");
96d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		eloop_destroy();
97d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return -1;
98d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
99d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
100a7b06faf528d1765cc2712cc9a31ad45d7c3110bDmitry Shmidt	if (os_exec("/system/bin/am", cmd, 1) != 0) {
101d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_INFO, "Failed to launch wpadebug browser");
102d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		eloop_cancel_timeout(browser_timeout, NULL, NULL);
103d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		http_server_deinit(http);
104d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		eloop_destroy();
105d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return -1;
106d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
107d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
108d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	eloop_register_timeout(300, 0, browser_timeout, &data, NULL);
109d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	eloop_run();
110d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	eloop_cancel_timeout(browser_timeout, &data, NULL);
111d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	http_server_deinit(http);
112d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	eloop_destroy();
113d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
114d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_printf(MSG_INFO, "Closing Android browser");
115a7b06faf528d1765cc2712cc9a31ad45d7c3110bDmitry Shmidt	if (os_exec("/system/bin/am",
116a7b06faf528d1765cc2712cc9a31ad45d7c3110bDmitry Shmidt		    "start -a android.action.MAIN "
117a7b06faf528d1765cc2712cc9a31ad45d7c3110bDmitry Shmidt		    "-c android.intent.category.LAUNCHER "
118a7b06faf528d1765cc2712cc9a31ad45d7c3110bDmitry Shmidt		    "-n w1.fi.wpadebug/.WpaWebViewActivity "
119a7b06faf528d1765cc2712cc9a31ad45d7c3110bDmitry Shmidt		    "-e w1.fi.wpadebug.URL FINISH", 1) != 0) {
120d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_INFO, "Failed to close wpadebug browser");
121d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
122d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
123d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	return data.success;
124d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
125