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	struct http_server *http;
69d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	struct in_addr addr;
70d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	struct browser_data data;
71fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	pid_t pid;
72d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
73d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_printf(MSG_INFO, "Launching wpadebug browser to %s", url);
74d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
75d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	os_memset(&data, 0, sizeof(data));
76d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
77d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (eloop_init() < 0) {
78d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_ERROR, "eloop_init failed");
79d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return -1;
80d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
81d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	addr.s_addr = htonl((127 << 24) | 1);
82d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	http = http_server_init(&addr, 12345, http_req, &data);
83d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	if (http == NULL) {
84d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_ERROR, "http_server_init failed");
85d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		eloop_destroy();
86d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return -1;
87d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
88d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
89fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	pid = fork();
90fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	if (pid < 0) {
91fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		wpa_printf(MSG_ERROR, "fork: %s", strerror(errno));
92d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		http_server_deinit(http);
93d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		eloop_destroy();
94d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		return -1;
95d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
96d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
97fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	if (pid == 0) {
98fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		/* run the external command in the child process */
99fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		char *argv[12];
100fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt
101fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		argv[0] = "browser-wpadebug";
102fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		argv[1] = "start";
103fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		argv[2] = "-a";
104fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		argv[3] = "android.action.MAIN";
105fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		argv[4] = "-c";
106fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		argv[5] = "android.intent.category.LAUNCHER";
107fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		argv[6] = "-n";
108fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		argv[7] = "w1.fi.wpadebug/.WpaWebViewActivity";
109fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		argv[8] = "-e";
110fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		argv[9] = "w1.fi.wpadebug.URL";
111fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		argv[10] = (void *) url;
112fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		argv[11] = NULL;
113fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt
114fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		execv("/system/bin/am", argv);
115fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		wpa_printf(MSG_ERROR, "execv: %s", strerror(errno));
116fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		exit(0);
117fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt		return -1;
118fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt	}
119fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt
120d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	eloop_register_timeout(300, 0, browser_timeout, &data, NULL);
121d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	eloop_run();
122d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	eloop_cancel_timeout(browser_timeout, &data, NULL);
123d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	http_server_deinit(http);
124d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	eloop_destroy();
125d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
126d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	wpa_printf(MSG_INFO, "Closing Android browser");
127a7b06faf528d1765cc2712cc9a31ad45d7c3110bDmitry Shmidt	if (os_exec("/system/bin/am",
128a7b06faf528d1765cc2712cc9a31ad45d7c3110bDmitry Shmidt		    "start -a android.action.MAIN "
129a7b06faf528d1765cc2712cc9a31ad45d7c3110bDmitry Shmidt		    "-c android.intent.category.LAUNCHER "
130a7b06faf528d1765cc2712cc9a31ad45d7c3110bDmitry Shmidt		    "-n w1.fi.wpadebug/.WpaWebViewActivity "
131a7b06faf528d1765cc2712cc9a31ad45d7c3110bDmitry Shmidt		    "-e w1.fi.wpadebug.URL FINISH", 1) != 0) {
132d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt		wpa_printf(MSG_INFO, "Failed to close wpadebug browser");
133d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	}
134d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt
135d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt	return data.success;
136d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt}
137