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