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