browser-android: Use execv() directly instead of os_exec()

This allows the URL to be passed as a single argument to the program
instead of getting split into multiple by os_exec(). This makes the
operation more robust for cases where the URL could have been received
from an external source and could potentially add extra arguments to the
command line.

In addition, fix the /system/bin/input execution by using system() for
it instead of execv() through os_exec(). /system/bin/input is a script
that execv() won't be able to run. Since the full command line is
specified, system() can be used for this. The keycode is also changed
from 3 to KEYCODE_HOME to make this work with current Android version.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2014-10-21 14:16:06 +03:00 committed by Jouni Malinen
parent c94382259d
commit ccf79ab256

View file

@ -64,24 +64,15 @@ static void http_req(void *ctx, struct http_request *req)
int hs20_web_browser(const char *url) int hs20_web_browser(const char *url)
{ {
char cmd[2000];
int ret;
struct http_server *http; struct http_server *http;
struct in_addr addr; struct in_addr addr;
struct browser_data data; struct browser_data data;
pid_t pid;
wpa_printf(MSG_INFO, "Launching Android browser to %s", url); wpa_printf(MSG_INFO, "Launching Android browser to %s", url);
os_memset(&data, 0, sizeof(data)); os_memset(&data, 0, sizeof(data));
ret = os_snprintf(cmd, sizeof(cmd),
"start -a android.intent.action.VIEW -d %s "
"-n com.android.browser/.BrowserActivity", url);
if (ret < 0 || (size_t) ret >= sizeof(cmd)) {
wpa_printf(MSG_ERROR, "Too long URL");
return -1;
}
if (eloop_init() < 0) { if (eloop_init() < 0) {
wpa_printf(MSG_ERROR, "eloop_init failed"); wpa_printf(MSG_ERROR, "eloop_init failed");
return -1; return -1;
@ -94,14 +85,34 @@ int hs20_web_browser(const char *url)
return -1; return -1;
} }
if (os_exec("/system/bin/am", cmd, 1) != 0) { pid = fork();
wpa_printf(MSG_INFO, "Failed to launch Android browser"); if (pid < 0) {
eloop_cancel_timeout(browser_timeout, NULL, NULL); perror("fork");
http_server_deinit(http); http_server_deinit(http);
eloop_destroy(); eloop_destroy();
return -1; return -1;
} }
if (pid == 0) {
/* run the external command in the child process */
char *argv[9];
argv[0] = "browser-android";
argv[1] = "start";
argv[2] = "-a";
argv[3] = "android.intent.action.VIEW";
argv[4] = "-d";
argv[5] = (void *) url;
argv[6] = "-n";
argv[7] = "com.android.browser/.BrowserActivity";
argv[8] = NULL;
execv("/system/bin/am", argv);
perror("execv");
exit(0);
return -1;
}
eloop_register_timeout(30, 0, browser_timeout, &data, NULL); eloop_register_timeout(30, 0, browser_timeout, &data, NULL);
eloop_run(); eloop_run();
eloop_cancel_timeout(browser_timeout, &data, NULL); eloop_cancel_timeout(browser_timeout, &data, NULL);
@ -109,7 +120,7 @@ int hs20_web_browser(const char *url)
eloop_destroy(); eloop_destroy();
wpa_printf(MSG_INFO, "Closing Android browser"); wpa_printf(MSG_INFO, "Closing Android browser");
if (os_exec("/system/bin/input", "keyevent 3", 1) != 0) { if (system("/system/bin/input keyevent KEYCODE_HOME") != 0) {
wpa_printf(MSG_INFO, "Failed to inject keyevent"); wpa_printf(MSG_INFO, "Failed to inject keyevent");
} }