X-Git-Url: http://git.maemo.org/git/?p=browser-switch;a=blobdiff_plain;f=launcher.c;h=6f25a28c0a783716c82c819cab279cfcf1e49b68;hp=b6c9ea432ec6c0afa93be76e3b9617da2ba34b4e;hb=0a8cbe98b0c4b2e8061abb6b1ce4593149024fb3;hpb=7d3b3e8a206bffae1e491f5887ab1aaaf69e4759 diff --git a/launcher.c b/launcher.c index b6c9ea4..6f25a28 100644 --- a/launcher.c +++ b/launcher.c @@ -32,12 +32,13 @@ #include "launcher.h" #include "dbus-server-bindings.h" +#define DEFAULT_BROWSER "/usr/bin/tear" #define LAUNCH_DEFAULT_BROWSER launch_tear -static void launch_tear(struct swb_context * ctx, char * uri) { +static void launch_tear(struct swb_context *ctx, char *uri) { int status; - static DBusGProxy * tear_proxy = NULL; - GError * error = NULL; + static DBusGProxy *tear_proxy = NULL; + GError *error = NULL; pid_t pid; if (!uri) @@ -45,18 +46,20 @@ static void launch_tear(struct swb_context * ctx, char * uri) { printf("launch_tear with uri '%s'\n", uri); + /* We should be able to just call the D-Bus service to open Tear ... + but if Tear's not open, that cuases D-Bus to star Tear and then pass + it the OpenAddress call, which results in two browser windows. + Properly fixing this probably requires Tear to provide a D-Bus + method that opens an address in an existing window, but for now work + around by just invoking Tear with exec() if it's not running. */ status = system("pidof tear > /dev/null"); - if (!WIFEXITED(status)) - exit(1); - if (!WEXITSTATUS(status)) { + if (WIFEXITED(status) && !WEXITSTATUS(status)) { if (!tear_proxy) tear_proxy = dbus_g_proxy_new_for_name(ctx->session_bus, "com.nokia.tear", "/com/nokia/tear", "com.nokia.Tear"); - dbus_g_proxy_call(tear_proxy, "OpenAddress", - &error, - G_TYPE_STRING, uri, - G_TYPE_INVALID); + dbus_g_proxy_call(tear_proxy, "OpenAddress", &error, + G_TYPE_STRING, uri, G_TYPE_INVALID); if (!ctx->continuous_mode) exit(0); } else { @@ -73,7 +76,7 @@ static void launch_tear(struct swb_context * ctx, char * uri) { } } -void launch_microb(struct swb_context * ctx, char * uri) { +void launch_microb(struct swb_context *ctx, char *uri) { int kill_browserd = 0; int status; pid_t pid; @@ -81,14 +84,16 @@ void launch_microb(struct swb_context * ctx, char * uri) { if (!uri) uri = "new_window"; + printf("launch_microb with uri '%s'\n", uri); + + /* Launch browserd if it's not running */ status = system("pidof /usr/sbin/browserd > /dev/null"); - if (!WIFEXITED(status)) - exit(1); - if (WEXITSTATUS(status)) { + if (WIFEXITED(status) && WEXITSTATUS(status)) { kill_browserd = 1; system("/usr/sbin/browserd -d"); } + /* Release the osso_browser D-Bus name so that MicroB can take it */ dbus_release_osso_browser_name(ctx); if ((pid = fork()) == -1) { @@ -100,15 +105,19 @@ void launch_microb(struct swb_context * ctx, char * uri) { waitpid(pid, &status, 0); } else { /* Child process */ + /* exec maemo-invoker directly instead of relying on the + /usr/bin/browser symlink, since /usr/bin/browser may have + been replaced with a shell script calling us via D-Bus */ if (!strcmp(uri, "new_window")) { execl("/usr/bin/maemo-invoker", - "browser", (char *)NULL); + "browser", (char *)NULL); } else { execl("/usr/bin/maemo-invoker", - "browser", "--url", uri, (char *)NULL); + "browser", "--url", uri, (char *)NULL); } } + /* Kill off browserd if we started it */ if (kill_browserd) system("kill `pidof /usr/sbin/browserd`"); @@ -118,38 +127,51 @@ void launch_microb(struct swb_context * ctx, char * uri) { dbus_request_osso_browser_name(ctx); } -static void launch_other_browser(struct swb_context * ctx, char * uri) { - char * command; - char * quoted_uri; +static void launch_other_browser(struct swb_context *ctx, char *uri) { + char *command; + char *quoted_uri, *quote; + size_t cmdlen, urilen; + size_t quoted_uri_size; + size_t offset; if (!uri || !strcmp(uri, "new_window")) uri = ""; - urilen = strlen(uri); - if (urilen > 0) { - char * quote; - /* Quote the URI */ + printf("launch_other_browser with uri '%s'\n", uri); + + if ((urilen = strlen(uri)) > 0) { + /* Quote the URI to prevent the shell from interpreting it */ /* urilen+3 = length of URI + 2x \' + \0 */ if (!(quoted_uri = calloc(urilen+3, sizeof(char)))) exit(1); - strncpy(quoted_uri+1, uri, urilen); - quoted_uri[0] = quoted_uri[urilen+1] = '\''; - /* calloc zeroes the memory, so string is automatically - null terminated */ + snprintf(quoted_uri, urilen+3, "'%s'", uri); /* If there are any 's in the original URI, URL-escape them (replace them with %27) */ + quoted_uri_size = urilen + 3; quote = quoted_uri + 1; while ((quote = strchr(quote, '\'')) && - (quote-quoted_uri) < strlen(quoted_uri)-1) { - /* 3 = strlen("%27")-strlen("'") + \0 */ + (offset = quote-quoted_uri) < strlen(quoted_uri)-1) { + /* Check to make sure we don't shrink the memory area + as a result of integer overflow */ + if (quoted_uri_size+2 <= quoted_uri_size) + exit(1); + + /* Grow the memory area; + 2 = strlen("%27")-strlen("'") */ if (!(quoted_uri = realloc(quoted_uri, - strlen(quoted_uri)+3))) + quoted_uri_size+2))) exit(1); + quoted_uri_size = quoted_uri_size + 2; + + /* Recalculate the location of the ' character -- + realloc() may have moved the string in memory */ + quote = quoted_uri + offset; + /* Move the string after the ', including the \0, over two chars */ - memmove(quote+3, quote+1, strlen(quote)+1); + memmove(quote+3, quote+1, strlen(quote)); memcpy(quote, "%27", 3); quote = quote + 3; } @@ -181,7 +203,11 @@ static void launch_other_browser(struct swb_context * ctx, char * uri) { execl("/bin/sh", "/bin/sh", "-c", command, (char *)NULL); } -static void use_other_browser_cmd(struct swb_context * ctx, char * cmd) { +/* Use launch_other_browser as the default browser launcher, with the string + passed in as the other_browser_cmd + Resulting other_browser_cmd is always safe to free(), even if a pointer + to a string constant is passed in */ +static void use_other_browser_cmd(struct swb_context *ctx, char *cmd) { size_t len = strlen(cmd); free(ctx->other_browser_cmd); @@ -191,18 +217,22 @@ static void use_other_browser_cmd(struct swb_context * ctx, char * cmd) { ctx->default_browser_launcher = LAUNCH_DEFAULT_BROWSER; } else { ctx->other_browser_cmd = strncpy(ctx->other_browser_cmd, - cmd, len); - ctx->other_browser_cmd[len] = '\0'; + cmd, len+1); ctx->default_browser_launcher = launch_other_browser; } } -void update_default_browser(struct swb_context * ctx, char * default_browser) { +void update_default_browser(struct swb_context *ctx, char *default_browser) { if (!ctx) return; if (!default_browser) { - ctx->default_browser_launcher = LAUNCH_DEFAULT_BROWSER; + /* No default_browser configured -- use DEFAULT_BROWSER if + installed, otherwise launch MicroB */ + if (!access(DEFAULT_BROWSER, X_OK)) + ctx->default_browser_launcher = LAUNCH_DEFAULT_BROWSER; + else + ctx->default_browser_launcher = launch_microb; return; } @@ -211,6 +241,8 @@ void update_default_browser(struct swb_context * ctx, char * default_browser) { else if (!strcmp(default_browser, "microb")) ctx->default_browser_launcher = launch_microb; else if (!strcmp(default_browser, "fennec")) + /* Cheat and reuse launch_other_browser, since we don't appear + to need to do anything special */ use_other_browser_cmd(ctx, "fennec %s"); else if (!strcmp(default_browser, "midori")) use_other_browser_cmd(ctx, "midori %s"); @@ -227,7 +259,7 @@ void update_default_browser(struct swb_context * ctx, char * default_browser) { } } -void launch_browser(struct swb_context * ctx, char * uri) { +void launch_browser(struct swb_context *ctx, char *uri) { if (ctx && ctx->default_browser_launcher) ctx->default_browser_launcher(ctx, uri); }