X-Git-Url: http://git.maemo.org/git/?p=browser-switch;a=blobdiff_plain;f=launcher.c;h=e042f7896fef91383a888d1d758876f6e824d767;hp=9d2953be0dccd0f15514076138077bbabba92f39;hb=8e8375e7af5af21d1741dce1fc5ebc39a2aa270b;hpb=13c579741f0f3186a7b4fe5609607d7ac1aa984f diff --git a/launcher.c b/launcher.c index 9d2953b..e042f78 100644 --- a/launcher.c +++ b/launcher.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -32,7 +33,6 @@ #ifdef FREMANTLE #include -#include #include #include #include @@ -45,8 +45,13 @@ #include "browser-switchboard.h" #include "launcher.h" #include "dbus-server-bindings.h" +#include "log.h" -#define LAUNCH_DEFAULT_BROWSER launch_microb +struct browser_launcher { + char *name; + void (*launcher)(struct swb_context *, char *); + char *other_browser_cmd; +}; #ifdef FREMANTLE static int microb_started = 0; @@ -59,21 +64,21 @@ static DBusHandlerResult check_microb_started(DBusConnection *connection, DBusError error; char *name, *old, *new; - printf("Checking to see if MicroB is ready\n"); + log_msg("Checking to see if MicroB is ready\n"); dbus_error_init(&error); if (!dbus_message_get_args(message, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old, DBUS_TYPE_STRING, &new, DBUS_TYPE_INVALID)) { - printf("%s\n", error.message); + log_msg("%s\n", error.message); dbus_error_free(&error); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } /* If old is an empty string, then the name has been acquired, and MicroB should be ready to handle our request */ if (strlen(old) == 0) { - printf("MicroB ready\n"); + log_msg("MicroB ready\n"); microb_started = 1; } @@ -120,7 +125,7 @@ static void launch_tear(struct swb_context *ctx, char *uri) { if (!uri) uri = "new_window"; - printf("launch_tear with uri '%s'\n", uri); + log_msg("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 start Tear and then @@ -133,10 +138,10 @@ static void launch_tear(struct swb_context *ctx, char *uri) { if (!tear_proxy) { if (!(tear_proxy = dbus_g_proxy_new_for_name( ctx->session_bus, - "com.nokia.tear", + "com.nokia.tear", "/com/nokia/tear", "com.nokia.Tear"))) { - printf("Failed to create proxy for com.nokia.Tear D-Bus interface\n"); + log_msg("Failed to create proxy for com.nokia.Tear D-Bus interface\n"); exit(1); } } @@ -144,7 +149,7 @@ static void launch_tear(struct swb_context *ctx, char *uri) { if (!dbus_g_proxy_call(tear_proxy, "OpenAddress", &error, G_TYPE_STRING, uri, G_TYPE_INVALID, G_TYPE_INVALID)) { - printf("Opening window failed: %s\n", error->message); + log_msg("Opening window failed: %s\n", error->message); exit(1); } if (!ctx->continuous_mode) @@ -153,7 +158,7 @@ static void launch_tear(struct swb_context *ctx, char *uri) { if (ctx->continuous_mode) { if ((pid = fork()) != 0) { /* Parent process or error in fork() */ - printf("child: %d\n", (int)pid); + log_msg("child: %d\n", (int)pid); return; } /* Child process */ @@ -188,7 +193,7 @@ void launch_microb(struct swb_context *ctx, char *uri) { if (!uri) uri = "new_window"; - printf("launch_microb with uri '%s'\n", uri); + log_msg("launch_microb with uri '%s'\n", uri); /* Launch browserd if it's not running */ status = system("pidof browserd > /dev/null"); @@ -210,7 +215,7 @@ void launch_microb(struct swb_context *ctx, char *uri) { homedir = DEFAULT_HOMEDIR; len = strlen(homedir) + strlen(MICROB_PROFILE_DIR) + 1; if (!(microb_profile_dir = calloc(len, sizeof(char)))) { - printf("calloc() failed\n"); + log_msg("calloc() failed\n"); exit(1); } snprintf(microb_profile_dir, len, "%s%s", @@ -218,7 +223,7 @@ void launch_microb(struct swb_context *ctx, char *uri) { len = strlen(homedir) + strlen(MICROB_PROFILE_DIR) + strlen("/") + strlen(MICROB_LOCKFILE) + 1; if (!(microb_lockfile = calloc(len, sizeof(char)))) { - printf("calloc() failed\n"); + log_msg("calloc() failed\n"); exit(1); } snprintf(microb_lockfile, len, "%s%s/%s", @@ -229,12 +234,12 @@ void launch_microb(struct swb_context *ctx, char *uri) { is launched, to make sure there's no race between browserd starting and us creating the watch */ if ((fd = inotify_init()) == -1) { - perror("inotify_init"); + log_perror(errno, "inotify_init"); exit(1); } if ((inot_wd = inotify_add_watch(fd, microb_profile_dir, IN_CREATE)) == -1) { - perror("inotify_add_watch"); + log_perror(errno, "inotify_add_watch"); exit(1); } free(microb_profile_dir); @@ -250,8 +255,7 @@ void launch_microb(struct swb_context *ctx, char *uri) { raw_connection = dbus_bus_get_private(DBUS_BUS_SESSION, &dbus_error); if (!raw_connection) { - fprintf(stderr, - "Failed to open connection to session bus: %s\n", + log_msg("Failed to open connection to session bus: %s\n", dbus_error.message); dbus_error_free(&dbus_error); exit(1); @@ -261,8 +265,7 @@ void launch_microb(struct swb_context *ctx, char *uri) { "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged',arg0='com.nokia.osso_browser'", &dbus_error); if (dbus_error_is_set(&dbus_error)) { - fprintf(stderr, - "Failed to set up watch for browser UI start: %s\n", + log_msg("Failed to set up watch for browser UI start: %s\n", dbus_error.message); dbus_error_free(&dbus_error); exit(1); @@ -270,12 +273,12 @@ void launch_microb(struct swb_context *ctx, char *uri) { filter_func = check_microb_started; if (!dbus_connection_add_filter(raw_connection, filter_func, NULL, NULL)) { - fprintf(stderr, "Failed to set up watch filter!\n"); + log_msg("Failed to set up watch filter!\n"); exit(1); } if ((pid = fork()) == -1) { - perror("fork"); + log_perror(errno, "fork"); exit(1); } @@ -286,7 +289,7 @@ void launch_microb(struct swb_context *ctx, char *uri) { then make the appropriate method call to open the browser window. */ microb_started = 0; - printf("Waiting for MicroB to start\n"); + log_msg("Waiting for MicroB to start\n"); while (!microb_started && dbus_connection_read_write_dispatch(raw_connection, -1)); @@ -309,7 +312,7 @@ void launch_microb(struct swb_context *ctx, char *uri) { "/com/nokia/osso_browser/request", "com.nokia.osso_browser"); if (!g_proxy) { - printf("Couldn't get a com.nokia.osso_browser proxy\n"); + log_msg("Couldn't get a com.nokia.osso_browser proxy\n"); exit(1); } if (!strcmp(uri, "new_window")) { @@ -320,8 +323,8 @@ void launch_microb(struct swb_context *ctx, char *uri) { if (!dbus_g_proxy_call(g_proxy, "top_application", &gerror, G_TYPE_INVALID, G_TYPE_INVALID)) { - printf("Opening window failed: %s\n", - gerror->message); + log_msg("Opening window failed: %s\n", + gerror->message); exit(1); } #endif @@ -330,8 +333,8 @@ void launch_microb(struct swb_context *ctx, char *uri) { G_TYPE_STRING, "about:blank", G_TYPE_INVALID, G_TYPE_INVALID)) { - printf("Opening window failed: %s\n", - gerror->message); + log_msg("Opening window failed: %s\n", + gerror->message); exit(1); } } else { @@ -340,8 +343,8 @@ void launch_microb(struct swb_context *ctx, char *uri) { G_TYPE_STRING, uri, G_TYPE_INVALID, G_TYPE_INVALID)) { - printf("Opening window failed: %s\n", - gerror->message); + log_msg("Opening window failed: %s\n", + gerror->message); exit(1); } } @@ -360,7 +363,7 @@ void launch_microb(struct swb_context *ctx, char *uri) { appreciated. */ /* Wait for the MicroB browserd lockfile to be created */ - printf("Waiting for browserd lockfile to be created\n"); + log_msg("Waiting for browserd lockfile to be created\n"); memset(buf, '\0', 256); /* read() blocks until there are events to be read */ while ((bytes_read = read(fd, buf, 255)) > 0) { @@ -387,38 +390,38 @@ void launch_microb(struct swb_context *ctx, char *uri) { /* Event found, stop looking */ break; memset(buf, '\0', 256); - } + } inotify_rm_watch(fd, inot_wd); close(fd); /* Get the PID of the browserd from the lockfile */ if ((browserd_pid = get_browserd_pid(microb_lockfile)) <= 0) { if (browserd_pid == 0) - printf("Profile lockfile link lacks PID\n"); + log_msg("Profile lockfile link lacks PID\n"); else - printf("readlink() on lockfile failed: %s\n", - strerror(-browserd_pid)); + log_perror(-browserd_pid, + "readlink() on lockfile failed"); exit(1); } free(microb_lockfile); /* Wait for the browserd to close */ - printf("Waiting for MicroB (browserd pid %d) to finish\n", - browserd_pid); + log_msg("Waiting for MicroB (browserd pid %d) to finish\n", + browserd_pid); /* Clear any existing SIGCHLD handler to prevent interference with our wait() */ act.sa_handler = SIG_DFL; act.sa_flags = 0; sigemptyset(&(act.sa_mask)); if (sigaction(SIGCHLD, &act, &oldact) == -1) { - perror("clearing SIGCHLD handler failed"); + log_perror(errno, "clearing SIGCHLD handler failed"); exit(1); } /* Trace the browserd to get a close notification */ ignore_sigstop = 1; if (ptrace(PTRACE_ATTACH, browserd_pid, NULL, NULL) == -1) { - perror("PTRACE_ATTACH"); + log_perror(errno, "PTRACE_ATTACH"); exit(1); } ptrace(PTRACE_CONT, browserd_pid, NULL, NULL); @@ -440,14 +443,14 @@ void launch_microb(struct swb_context *ctx, char *uri) { immediately after we start tracing the process, and won't be followed by a SIGCONT at any point */ - printf("Ignoring first SIGSTOP\n"); + log_msg("Ignoring first SIGSTOP\n"); ptrace(PTRACE_CONT, browserd_pid, NULL, NULL); ignore_sigstop = 0; continue; } - printf("Forwarding signal %d to browserd\n", - WSTOPSIG(status)); + log_msg("Forwarding signal %d to browserd\n", + WSTOPSIG(status)); ptrace(PTRACE_CONT, browserd_pid, NULL, WSTOPSIG(status)); } @@ -458,13 +461,14 @@ void launch_microb(struct swb_context *ctx, char *uri) { browserd; if that happens before we kill the browser UI, the newly started browserd may not close with the UI XXX: Hope we don't cause data loss here! */ - printf("Killing MicroB\n"); + log_msg("Killing MicroB\n"); kill(pid, SIGTERM); waitpid(pid, &status, 0); /* Restore old SIGCHLD handler */ if (sigaction(SIGCHLD, &oldact, NULL) == -1) { - perror("restoring old SIGCHLD handler failed"); + log_perror(errno, + "restoring old SIGCHLD handler failed"); exit(1); } } else { @@ -484,7 +488,7 @@ void launch_microb(struct swb_context *ctx, char *uri) { } #else /* !FREMANTLE */ if ((pid = fork()) == -1) { - perror("fork"); + log_perror(errno, "fork"); exit(1); } @@ -529,7 +533,7 @@ static void launch_other_browser(struct swb_context *ctx, char *uri) { if (!uri || !strcmp(uri, "new_window")) uri = ""; - printf("launch_other_browser with uri '%s'\n", uri); + log_msg("launch_other_browser with uri '%s'\n", uri); if ((urilen = strlen(uri)) > 0) { /* Quote the URI to prevent the shell from interpreting it */ @@ -578,7 +582,7 @@ static void launch_other_browser(struct swb_context *ctx, char *uri) { if (!(command = calloc(cmdlen+urilen+1, sizeof(char)))) exit(1); snprintf(command, cmdlen+urilen+1, ctx->other_browser_cmd, quoted_uri); - printf("command: '%s'\n", command); + log_msg("command: '%s'\n", command); if (ctx->continuous_mode) { if (fork() != 0) { @@ -595,56 +599,76 @@ static void launch_other_browser(struct swb_context *ctx, char *uri) { execl("/bin/sh", "/bin/sh", "-c", command, (char *)NULL); } -/* 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); - ctx->other_browser_cmd = calloc(len+1, sizeof(char)); - if (!ctx->other_browser_cmd) { - printf("malloc failed!\n"); - ctx->default_browser_launcher = LAUNCH_DEFAULT_BROWSER; - } else { - ctx->other_browser_cmd = strncpy(ctx->other_browser_cmd, - cmd, len+1); - ctx->default_browser_launcher = launch_other_browser; + +/* The list of known browsers and how to launch them */ +static struct browser_launcher browser_launchers[] = { + { "microb", launch_microb, NULL }, /* First entry is the default! */ + { "tear", launch_tear, NULL }, + { "fennec", NULL, "fennec %s" }, + { "opera", NULL, "opera %s" }, + { "midori", NULL, "midori %s" }, + { NULL, NULL, NULL }, +}; + +static void use_launcher_as_default(struct swb_context *ctx, + struct browser_launcher *browser) { + if (!ctx || !browser) + return; + + if (browser->launcher) + ctx->default_browser_launcher = browser->launcher; + else if (browser->other_browser_cmd) { + free(ctx->other_browser_cmd); + + /* Make a copy of the string constant so that + ctx->other_browser_cmd is safe to free() */ + ctx->other_browser_cmd = strdup(browser->other_browser_cmd); + if (!ctx->other_browser_cmd) { + log_msg("malloc failed!\n"); + /* Ideally, we'd configure the built-in default here -- + but it's possible we could be called in that path */ + exit(1); + } else + ctx->default_browser_launcher = launch_other_browser; } + + return; } void update_default_browser(struct swb_context *ctx, char *default_browser) { + struct browser_launcher *browser; + if (!ctx) return; - if (!default_browser) { + /* Configure the built-in default to start -- that way, we can + handle errors by just returning */ + use_launcher_as_default(ctx, &browser_launchers[0]); + + if (!default_browser) /* No default_browser configured -- use built-in default */ - ctx->default_browser_launcher = LAUNCH_DEFAULT_BROWSER; return; - } - if (!strcmp(default_browser, "tear")) - ctx->default_browser_launcher = launch_tear; - 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"); - else if (!strcmp(default_browser, "other")) { + /* Go through the list of known browser launchers and use one if + it matches */ + for (browser = browser_launchers; browser->name; ++browser) + if (!strcmp(default_browser, browser->name)) { + use_launcher_as_default(ctx, browser); + return; + } + + /* Deal with default_browser = "other" */ + if (!strcmp(default_browser, "other")) { if (ctx->other_browser_cmd) ctx->default_browser_launcher = launch_other_browser; - else { - printf("default_browser is 'other', but no other_browser_cmd set -- using default\n"); - ctx->default_browser_launcher = LAUNCH_DEFAULT_BROWSER; - } - } else { - printf("Unknown default_browser %s, using default", default_browser); - ctx->default_browser_launcher = LAUNCH_DEFAULT_BROWSER; + else + log_msg("default_browser is 'other', but no other_browser_cmd set -- using default\n"); + return; } + + /* Unknown value of default_browser */ + log_msg("Unknown default_browser %s, using default\n", default_browser); + return; } void launch_browser(struct swb_context *ctx, char *uri) {