1d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt/* 2d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt * Hotspot 2.0 client - Web browser using Android browser 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(1); 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 56d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (done) { 57d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt eloop_cancel_timeout(browser_timeout, NULL, NULL); 58d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt eloop_register_timeout(0, 500000, browser_timeout, &data, NULL); 59d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 60d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 61d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt http_request_send_and_deinit(req, resp); 62d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} 63d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 64d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 65d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidtint hs20_web_browser(const char *url) 66d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt{ 67d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt char cmd[2000]; 68d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt int ret; 69d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt struct http_server *http; 70d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt struct in_addr addr; 71d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt struct browser_data data; 72d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 73d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "Launching Android browser to %s", url); 74d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 75d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt os_memset(&data, 0, sizeof(data)); 76d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 77d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt ret = os_snprintf(cmd, sizeof(cmd), 78a7b06faf528d1765cc2712cc9a31ad45d7c3110bDmitry Shmidt "start -a android.intent.action.VIEW -d %s " 79d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt "-n com.android.browser/.BrowserActivity", url); 80d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (ret < 0 || (size_t) ret >= sizeof(cmd)) { 81d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_ERROR, "Too long URL"); 82d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return -1; 83d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 84d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 85d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (eloop_init() < 0) { 86d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_ERROR, "eloop_init failed"); 87d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return -1; 88d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 89d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt addr.s_addr = htonl((127 << 24) | 1); 90d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt http = http_server_init(&addr, 12345, http_req, &data); 91d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt if (http == NULL) { 92d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_ERROR, "http_server_init failed"); 93d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt eloop_destroy(); 94d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return -1; 95d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 96d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 97a7b06faf528d1765cc2712cc9a31ad45d7c3110bDmitry Shmidt if (os_exec("/system/bin/am", cmd, 1) != 0) { 98d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "Failed to launch Android browser"); 99d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt eloop_cancel_timeout(browser_timeout, NULL, NULL); 100d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt http_server_deinit(http); 101d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt eloop_destroy(); 102d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return -1; 103d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 104d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 105d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt eloop_register_timeout(30, 0, browser_timeout, &data, NULL); 106d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt eloop_run(); 107d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt eloop_cancel_timeout(browser_timeout, &data, NULL); 108d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt http_server_deinit(http); 109d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt eloop_destroy(); 110d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 111d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "Closing Android browser"); 112a7b06faf528d1765cc2712cc9a31ad45d7c3110bDmitry Shmidt if (os_exec("/system/bin/input", "keyevent 3", 1) != 0) { 113d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt wpa_printf(MSG_INFO, "Failed to inject keyevent"); 114d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt } 115d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt 116d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt return data.success; 117d5dc24eb5fbf0e0feff214c0260cae845721d5feDmitry Shmidt} 118