2 * launcher.c -- functions for launching web browsers for browser-switchboard
4 * Copyright (C) 2009 Steven Luo
5 * Derived from a Python implementation by Jason Simpson and Steven Luo
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
27 #include <sys/types.h>
29 #include <dbus/dbus-glib.h>
31 #include "browser-switchboard.h"
33 #include "dbus-server-bindings.h"
35 #define DEFAULT_BROWSER "/usr/bin/tear"
36 #define LAUNCH_DEFAULT_BROWSER launch_tear
38 static void launch_tear(struct swb_context *ctx, char *uri) {
40 static DBusGProxy *tear_proxy = NULL;
47 printf("launch_tear with uri '%s'\n", uri);
49 /* We should be able to just call the D-Bus service to open Tear ...
50 but if Tear's not open, that cuases D-Bus to star Tear and then pass
51 it the OpenAddress call, which results in two browser windows.
52 Properly fixing this probably requires Tear to provide a D-Bus
53 method that opens an address in an existing window, but for now work
54 around by just invoking Tear with exec() if it's not running. */
55 status = system("pidof tear > /dev/null");
56 if (WIFEXITED(status) && !WEXITSTATUS(status)) {
58 tear_proxy = dbus_g_proxy_new_for_name(ctx->session_bus,
59 "com.nokia.tear", "/com/nokia/tear",
61 dbus_g_proxy_call(tear_proxy, "OpenAddress", &error,
62 G_TYPE_STRING, uri, G_TYPE_INVALID);
63 if (!ctx->continuous_mode)
66 if (ctx->continuous_mode) {
67 if ((pid = fork()) != 0) {
68 /* Parent process or error in fork() */
69 printf("child: %d\n", (int)pid);
75 execl("/usr/bin/tear", "/usr/bin/tear", uri, (char *)NULL);
79 void launch_microb(struct swb_context *ctx, char *uri) {
80 int kill_browserd = 0;
87 printf("launch_microb with uri '%s'\n", uri);
89 /* Launch browserd if it's not running */
90 status = system("pidof /usr/sbin/browserd > /dev/null");
91 if (WIFEXITED(status) && WEXITSTATUS(status)) {
93 system("/usr/sbin/browserd -d");
96 /* Release the osso_browser D-Bus name so that MicroB can take it */
97 dbus_release_osso_browser_name(ctx);
99 if ((pid = fork()) == -1) {
105 waitpid(pid, &status, 0);
108 /* exec maemo-invoker directly instead of relying on the
109 /usr/bin/browser symlink, since /usr/bin/browser may have
110 been replaced with a shell script calling us via D-Bus */
111 if (!strcmp(uri, "new_window")) {
112 execl("/usr/bin/maemo-invoker",
113 "browser", (char *)NULL);
115 execl("/usr/bin/maemo-invoker",
116 "browser", "--url", uri, (char *)NULL);
120 /* Kill off browserd if we started it */
122 system("kill `pidof /usr/sbin/browserd`");
124 if (!ctx || !ctx->continuous_mode)
127 dbus_request_osso_browser_name(ctx);
130 static void launch_other_browser(struct swb_context *ctx, char *uri) {
132 char *quoted_uri, *quote;
134 size_t cmdlen, urilen;
135 size_t quoted_uri_size;
138 if (!uri || !strcmp(uri, "new_window"))
141 printf("launch_other_browser with uri '%s'\n", uri);
143 if ((urilen = strlen(uri)) > 0) {
144 /* Quote the URI to prevent the shell from interpreting it */
145 /* urilen+3 = length of URI + 2x \' + \0 */
146 if (!(quoted_uri = calloc(urilen+3, sizeof(char))))
148 snprintf(quoted_uri, urilen+3, "'%s'", uri);
150 /* If there are any 's in the original URI, URL-escape them
151 (replace them with %27) */
152 quoted_uri_size = urilen + 3;
153 quote = quoted_uri + 1;
154 while ((quote = strchr(quote, '\'')) &&
155 (offset = quote-quoted_uri) < strlen(quoted_uri)-1) {
156 /* Check to make sure we don't shrink the memory area
157 as a result of integer overflow */
158 if (quoted_uri_size+2 <= quoted_uri_size)
161 /* Grow the memory area;
162 2 = strlen("%27")-strlen("'") */
163 if (!(quoted_uri = realloc(quoted_uri,
166 quoted_uri_size = quoted_uri_size + 2;
168 /* Recalculate the location of the ' character --
169 realloc() may have moved the string in memory */
170 quote = quoted_uri + offset;
172 /* Move the string after the ', including the \0,
174 memmove(quote+3, quote+1, strlen(quote));
175 memcpy(quote, "%27", 3);
178 urilen = strlen(quoted_uri);
182 cmdlen = strlen(ctx->other_browser_cmd);
184 /* cmdlen+urilen+1 is normally two bytes longer than we need (uri will
185 replace "%s"), but is needed in the case other_browser_cmd has no %s
187 if (!(command = calloc(cmdlen+urilen+1, sizeof(char))))
189 snprintf(command, cmdlen+urilen+1, ctx->other_browser_cmd, quoted_uri);
190 printf("command: '%s'\n", command);
192 if (ctx->continuous_mode) {
194 /* Parent process or error in fork() */
203 execl("/bin/sh", "/bin/sh", "-c", command, (char *)NULL);
206 /* Use launch_other_browser as the default browser launcher, with the string
207 passed in as the other_browser_cmd
208 Resulting other_browser_cmd is always safe to free(), even if a pointer
209 to a string constant is passed in */
210 static void use_other_browser_cmd(struct swb_context *ctx, char *cmd) {
211 size_t len = strlen(cmd);
213 free(ctx->other_browser_cmd);
214 ctx->other_browser_cmd = calloc(len+1, sizeof(char));
215 if (!ctx->other_browser_cmd) {
216 printf("malloc failed!\n");
217 ctx->default_browser_launcher = LAUNCH_DEFAULT_BROWSER;
219 ctx->other_browser_cmd = strncpy(ctx->other_browser_cmd,
221 ctx->default_browser_launcher = launch_other_browser;
225 void update_default_browser(struct swb_context *ctx, char *default_browser) {
229 if (!default_browser) {
230 /* No default_browser configured -- use DEFAULT_BROWSER if
231 installed, otherwise launch MicroB */
232 if (!access(DEFAULT_BROWSER, X_OK))
233 ctx->default_browser_launcher = LAUNCH_DEFAULT_BROWSER;
235 ctx->default_browser_launcher = launch_microb;
239 if (!strcmp(default_browser, "tear"))
240 ctx->default_browser_launcher = launch_tear;
241 else if (!strcmp(default_browser, "microb"))
242 ctx->default_browser_launcher = launch_microb;
243 else if (!strcmp(default_browser, "fennec"))
244 /* Cheat and reuse launch_other_browser, since we don't appear
245 to need to do anything special */
246 use_other_browser_cmd(ctx, "fennec %s");
247 else if (!strcmp(default_browser, "midori"))
248 use_other_browser_cmd(ctx, "midori %s");
249 else if (!strcmp(default_browser, "other")) {
250 if (ctx->other_browser_cmd)
251 ctx->default_browser_launcher = launch_other_browser;
253 printf("default_browser is 'other', but no other_browser_cmd set -- using default\n");
254 ctx->default_browser_launcher = LAUNCH_DEFAULT_BROWSER;
257 printf("Unknown default_browser %s, using default", default_browser);
258 ctx->default_browser_launcher = LAUNCH_DEFAULT_BROWSER;
262 void launch_browser(struct swb_context *ctx, char *uri) {
263 if (ctx && ctx->default_browser_launcher)
264 ctx->default_browser_launcher(ctx, uri);