Merge commit 'v3.3b2' into diablo-package
authorSteven Luo <steven+maemo@steven676.net>
Sat, 28 Aug 2010 11:51:07 +0000 (04:51 -0700)
committerSteven Luo <steven+maemo@steven676.net>
Sat, 28 Aug 2010 11:51:07 +0000 (04:51 -0700)
19 files changed:
Changelog
Makefile
README
browser-switchboard.h
config-ui/Makefile
config-ui/browser-switchboard-config.c
config-ui/browser-switchboard-cp.c
config-ui/browser-switchboard-cp.desktop
config-ui/browsers.h [new file with mode: 0644]
config-ui/save-config.c
config-ui/save-config.h [new file with mode: 0644]
config.c
config.h
configfile.c
dbus-server-bindings.c
launcher.c
main.c
microb
xsession-post.sh [new file with mode: 0755]

index 120ab03..882cef9 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -1,11 +1,23 @@
 version 3.3:
 * add support for Opera Mobile
+* only offer installed browsers in the config GUI
+* make continuous mode operation the default; disable non-continuous-mode on
+  Fremantle (needed for correct operation on D-Bus system bus)
+* Fremantle: major overhaul of MicroB launching to improve robustness; should
+  result in speed and behavior indistinguishable from when Browser Switchboard
+  isn't installed when MicroB is configured as default browser
 * fall back to the built-in default if the user's configured default browser
   isn't installed
+* listen on D-Bus system bus as well as session bus, to accommodate some broken
+  applications that send their requests on the system bus
+* Fremantle: start browser-switchboard on X session startup, and also prestart
+  MicroB if it's the default browser or the user asks for it
+* Fremantle: prestart MicroB when the user changes to MicroB as the default
+  browser
 * introduce a command-line config utility; this is mainly intended to give
   browser vendors a way to set their browser as the default
-* provide a description for users who don't know what MicroB is; thanks
-  Emanuele Cassioli for pointing out the need
+* config UI: provide a description for users who don't know what MicroB is;
+  thanks Emanuele Cassioli for pointing out the need
 * major rewrite of configuration loading/saving code
 
 version 3.2:
index e6e1bb8..4e140ee 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -38,7 +38,11 @@ install: $(APP)
        install -c -m 0755 microb $(DESTDIR)$(PREFIX)/bin
        install -c -m 0644 microb.desktop $(DESTDIR)$(PREFIX)/share/applications/hildon
 
+install-xsession-script:
+       mkdir -p $(DESTDIR)/etc/X11/Xsession.post
+       install -c -m 0755 xsession-post.sh $(DESTDIR)/etc/X11/Xsession.post/35browser-switchboard
+
 clean:
        rm -f $(APP) $(obj) dbus-server-glue.h
 
-.PHONY: strip install diablo fremantle
+.PHONY: strip install install-xsession-script diablo fremantle
diff --git a/README b/README
index 2f36e77..774a77b 100644 (file)
--- a/README
+++ b/README
@@ -1,5 +1,5 @@
 BROWSER SWITCHBOARD
-version 3.3b1
+version 3.3b2
 
 Browser Switchboard is a program which allows you to choose which
 browser to use as the default browser. It supports MicroB, Tear,
@@ -15,9 +15,7 @@ page on garage.maemo.org: https://garage.maemo.org/frs/?group_id=1159
 Quick Start:
 1. Download the binary package: browser-switchboard_X.Y-Z_all.deb
 (where X.Y-Z is the version number, of course).
-2. If you're using a Maemo 5 device, make sure all your MicroB browser
-windows are closed.
-3. Install the package using the Application Manager (open the
+2. Install the package using the Application Manager (open the
 Application Manager, then select Application->Install from file in the
 menu).
 
@@ -52,9 +50,9 @@ $ cat > $HOME/.config/browser-switchboard <<EOF
 default_browser = "your_browser"
 EOF
 
-where your_browser can be one of "tear", "microb", "fennec", "midori",
-or "other" (see below for more on the "other" option).  You can of
-course also edit the $HOME/.config/browser-switchboard file with your
+where your_browser can be one of "tear", "microb", "fennec", "opera",
+"midori" or "other" (see below for more on the "other" option).  You can
+of course also edit the $HOME/.config/browser-switchboard file with your
 favorite text editor.
 
 To restore the default behavior, just delete the config file:
@@ -69,15 +67,22 @@ Here's a more complete sample configuration file:
 # BEGIN SAMPLE CONFIG FILE
 # This is a comment
 # continuous_mode: 0 -- close after handling a request; 1 -- run
-# continuously in the background
-continuous_mode = 0
-# default_browser: "tear", "microb", "fennec", "midori", or "other"
+# continuously in the background (default)
+# On Fremantle, this is forced to 1 regardless of config setting
+continuous_mode = 1
+# default_browser: "tear", "microb", "fennec", "midori", "opera" or
+# "other"
 default_browser = "tear"
 # other_browser_cmd: If default browser is "other", what program
 # to run (%s will be replaced by URI)
 #other_browser_cmd = "some_browser %s"
 # logging: Where log output should go: "stdout", "syslog", "none"
 #logging = "stdout"
+# autostart_microb: Fremantle only: whether MicroB should be
+# prestarted in the background: 0 -- never prestart MicroB; 1 -- always
+# prestart MicroB; -1 -- only prestart MicroB when MicroB is the default
+# browser (default behavior if unset)
+#autostart_microb = 0
 # END SAMPLE CONFIG FILE
 
 Lines beginning with # characters are comments and are ignored by the
@@ -87,15 +92,17 @@ in the configuration UI.]
 In continuous mode, Browser Switchboard keeps running in the background
 instead of closing after handling each request.  This saves a bit of
 startup time for each link (on my N800 running Diablo), but costs you
-about 100 KB extra memory.  Continuous mode is disabled by default; set
-continuous_mode to 1 to enable.  [This option corresponds to the
-"Optimize Browser Switchboard for" option group in the UI; "Lower memory
-usage" corresponds to continuous_mode off, while "Faster browser startup
-time" corresponds to continuous_mode on.]
-
-The "tear", "microb", "fennec", and "midori" options for default_browser
-should be self-explanatory.  [These correspond to the options in the
-"Default browser" combo box in the UI.]
+about 100 KB extra memory.  Continuous mode is enabled by default; set
+continuous_mode to 0 to enable.  On Fremantle, continuous mode is always
+enabled regardless of the value of this config setting, to provide
+better compatibility with MicroB's behavior.  [This option corresponds
+to the "Optimize Browser Switchboard for" option group in the UI; "Lower
+memory usage" corresponds to continuous_mode off, while "Faster browser
+startup time" corresponds to continuous_mode on.]
+
+The "tear", "microb", "fennec", "opera" and "midori" options for
+default_browser should be self-explanatory.  [These correspond to the
+options in the "Default browser" combo box in the UI.]
 
 If the default browser is "other", Browser Switchboard will run the
 program specified in other_browser_cmd as the default browser, with a
@@ -118,6 +125,51 @@ run Browser Switchboard from the shell.  "syslog" will send the output
 to the system log (assuming you have a syslogd set up on your device),
 and "none" disables debug logging entirely.
 
+On Fremantle only, autostart_microb controls whether MicroB is
+prestarted when the device boots and whether the MicroB browser process
+is left running when no browser windows are open.  By default, MicroB is
+prestarted (and the process left open when no browser windows are open)
+only when MicroB is set as the default browser; you can force MicroB to
+always prestart by setting autostart_microb = 1, while you can force it
+to never prestart by setting autostart_microb = 0.  [This option has no
+corresponding UI at the moment.]
+
+
+The browser-switchboard-config Command-Line Configuration Tool:
+
+A command-line configuration utility is provided to allow programs and
+scripts to query and set Browser Switchboard configuration variables.
+For example,
+
+$ browser-switchboard-config -b
+
+will display the default browser, and 
+
+$ browser-switchboard-config -s -b "opera"
+
+will set the default browser to Opera Mobile.  See the help output from
+running browser-switchboard-config with no arguments for more
+information.
+
+The primary purpose of this tool is to allow browser vendors to provide
+an option in their browsers to set themselves as the default browser,
+via something like this (shell-like pseudocode):
+
+if [ -x /usr/bin/browser-switchboard-config ]; then
+       if [ `browser-switchboard-config -b` = "mybrowser" ]; then
+               display "MyBrowser is the default browser."
+       else
+               button "Make MyBrowser the default browser"
+               action "browser-switchboard-config -s -b mybrowser"
+       fi
+else
+       display "Install Browser Switchboard to make MyBrowser the default browser"
+fi
+
+Browser vendors: setting yourself as the default browser without
+prompting the user first (via package maintainer scripts, for example)
+is strongly discouraged.
+
 
 Browser Switchboard and MicroB's browserd:
 
index 726a553..26f92d8 100644 (file)
@@ -27,8 +27,13 @@ struct swb_context {
        int continuous_mode;
        void (*default_browser_launcher)(struct swb_context *, char *);
        char *other_browser_cmd;
+#ifdef FREMANTLE
+       int autostart_microb;
+#endif
        DBusGConnection *session_bus;
        DBusGProxy *dbus_proxy;
+       DBusGConnection *system_bus;
+       DBusGProxy *dbus_system_proxy;
 };
 
 #endif /* _BROWSER_SWITCHBOARD_H */
index bb7ad98..4c843d9 100644 (file)
@@ -28,12 +28,15 @@ all:
        @echo '    make util -- build command-line configuration utility'
        @echo '    make diablo-hildon-app -- build standalone Diablo Hildon application'
        @echo '    make diablo-plugin -- build Diablo hildon-control-panel plugin'
+       @echo '    make fremantle-util -- build command-line configuration utility for Fremantle'
        @echo '    make fremantle-hildon-app -- build standalone Fremantle Hildon application'
        @echo '    make fremantle-plugin -- build Fremantle hildon-control-panel plugin'
 app: $(APP)
 util: $(UTIL)
 diablo-hildon-app: $(HILDON_APP)
 diablo-plugin: $(PLUGIN)
+fremantle-util:
+       @$(MAKE) EXTRA_CPPFLAGS='-DFREMANTLE $(EXTRA_CPPFLAGS)' $(UTIL)
 fremantle-hildon-app:
        @$(MAKE) EXTRA_CPPFLAGS='-DFREMANTLE $(EXTRA_CPPFLAGS)' $(HILDON_APP)
 fremantle-plugin:
@@ -58,7 +61,7 @@ $(HILDON_APP): $(happ_obj)
 $(PLUGIN): $(plugin_obj)
        $(CC) $(CFLAGS) $(CFLAGS_PLUGIN) -o $(PLUGIN) $(plugin_obj) \
                $(LDFLAGS) $(LDFLAGS_PLUGIN)
-               
+
 
 %.plugin.o: %.c
        $(CC) $(CFLAGS) $(CFLAGS_PLUGIN) $(CPPFLAGS) $(CPPFLAGS_PLUGIN) \
index ec1e509..c28b743 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * browser-switchboard-config.c -- command-line configuration utility for 
+ * browser-switchboard-config.c -- command-line configuration utility for
  * Browser Switchboard
- * 
+ *
  * Copyright (C) 2009-2010 Steven Luo
- * 
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2, or (at your option)
 #include <stddef.h>
 #include <string.h>
 #include <stdio.h>
+#include <unistd.h>
 #include <getopt.h>
 
 #include "config.h"
+#include "save-config.h"
+#include "browsers.h"
 
 extern struct swb_config_option swb_config_options[];
 
@@ -67,17 +70,52 @@ static int get_config_value(char *name) {
        return retval;
 }
 
-static int set_config_value(char *name, char *value) {
+static int get_default_browser(void) {
        struct swb_config cfg;
+       int i;
+
+       swb_config_init(&cfg);
+
+       if (!swb_config_load(&cfg))
+               return 1;
+
+       /* Check to see if the configured default browser is installed
+          If not, report the default default browser */
+       for (i = 0; browsers[i].config; ++i) {
+               if (strcmp(browsers[i].config, cfg.default_browser))
+                       continue;
+
+               if (browsers[i].binary && access(browsers[i].binary, X_OK))
+                       printf("%s\n", browsers[0].config);
+               else
+                       printf("%s\n", browsers[i].config);
+
+               break;
+       }
+
+       if (!browsers[i].config)
+               /* Unknown browser configured as default, report the default
+                  default browser */
+               printf("%s\n", browsers[0].config);
+
+       swb_config_free(&cfg);
+
+       return 0;
+}
+
+static int set_config_value(char *name, char *value) {
+       struct swb_config orig_cfg, cfg;
        struct swb_config_option *optinfo;
        ptrdiff_t i;
        int retval = 1;
 
-       swb_config_init(&cfg);
+       swb_config_init(&orig_cfg);
 
-       if (!swb_config_load(&cfg))
+       if (!swb_config_load(&orig_cfg))
                return 1;
 
+       swb_config_copy(&cfg, &orig_cfg);
+
        for (optinfo = swb_config_options; optinfo->name; ++optinfo) {
                if (strcmp(name, optinfo->name))
                        continue;
@@ -85,10 +123,6 @@ static int set_config_value(char *name, char *value) {
                i = optinfo - swb_config_options;
                switch (optinfo->type) {
                  case SWB_CONFIG_OPT_STRING:
-                       /* Free any existing string */
-                       if (cfg.flags & optinfo->set_mask)
-                               free(*(char **)cfg.entries[i]);
-
                        if (strlen(value) == 0) {
                                /* If the new value is empty, clear the config
                                   setting */
@@ -122,12 +156,15 @@ static int set_config_value(char *name, char *value) {
                if (!swb_config_save(&cfg))
                        retval = 1;
 
-       swb_config_free(&cfg);
+       /* Reconfigure a running browser-switchboard, if present */
+       swb_reconfig(&orig_cfg, &cfg);
 
-       /* Try to send SIGHUP to any running browser-switchboard process
-          This causes it to reread config files if in continuous_mode, or
-          die so that the config will be reloaded on next start otherwise */
-       system("kill -HUP `pidof browser-switchboard` > /dev/null 2>&1");
+       swb_config_free(&orig_cfg);
+       /* XXX can't free all of cfg, it contains pointers to memory we just
+          freed above
+       swb_config_free(&cfg); */
+       if (optinfo->name && optinfo->type == SWB_CONFIG_OPT_STRING)
+               free(*(char **)cfg.entries[i]);
 
        return retval;
 }
@@ -148,7 +185,7 @@ int main(int argc, char **argv) {
        int opt, done = 0;
        int set = 0;
        char *selected_opt = NULL;
-       
+
        while (!done && (opt = getopt(argc, argv, "hsbcmo:")) != -1) {
                switch (opt) {
                  case 'h':
@@ -194,6 +231,9 @@ int main(int argc, char **argv) {
                        exit(1);
                }
                return set_config_value(selected_opt, argv[optind]);
-       } else
+       } else if (!strcmp(selected_opt, "default_browser"))
+               /* Default browser value needs special handling */
+               return get_default_browser();
+       else
                return get_config_value(selected_opt);
 }
index 0c768e1..02a4a07 100644 (file)
@@ -1,14 +1,14 @@
 /*
  * browser-switchboard-cp.c -- a hildon-control-panel applet for
  * selecting the default browser for Browser Switchboard
- * 
+ *
  * Copyright (C) 2009-2010 Steven Luo
  * Copyright (C) 2009-2010 Faheem Pervez
- * 
+ *
  * Derived from services-cp.c from maemo-control-services
  * Copyright (c) 2008 Janne Kataja <janne.kataja@iki.fi>
  * Copyright (c) 2008 Nokia Corporation
- * 
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2, or (at your option)
@@ -52,6 +52,8 @@
 #endif /* HILDON */
 
 #include "config.h"
+#include "save-config.h"
+#include "browsers.h"
 
 #define CONTINUOUS_MODE_DEFAULT 0
 
 #define _HILDON_SIZE_DEFAULT (HILDON_SIZE_AUTO_WIDTH|HILDON_SIZE_FINGER_HEIGHT)
 #endif
 
-struct browser_entry {
-       char *config;
-       char *displayname;
-};
-struct browser_entry browsers[] = {
-       { "microb", "MicroB (stock browser)" }, /* First entry is the default! */
-       { "tear", "Tear" },
-       { "fennec", "Mobile Firefox (Fennec)" },
-       { "opera", "Opera Mobile" },
-       { "midori", "Midori" },
-       { "other", "Other" },
-       { NULL, NULL },
-};
-
 struct swb_config orig_cfg;
 
 struct config_widgets {
 #if defined(HILDON) && defined(FREMANTLE)
-       GtkWidget *continuous_mode_selector;
        GtkWidget *default_browser_selector;
 #else
        GtkWidget *continuous_mode_off_radio;
@@ -91,21 +78,29 @@ struct config_widgets cw;
 GtkWidget *dialog;
 
 
+struct browser_entry *installed_browsers;
+void init_installed_browsers(void) {
+       struct browser_entry *cur = browsers;
+       unsigned int count = 0;
+
+       installed_browsers = calloc(sizeof browsers, 1);
+       if (!installed_browsers)
+               exit(1);
+
+       count = 0;
+       for (; cur->config; ++cur)
+               if (!cur->binary || !access(cur->binary, X_OK))
+                       installed_browsers[count++] = *cur;
+}
+
 /**********************************************************************
  * Configuration routines
  **********************************************************************/
 
 #if defined(HILDON) && defined(FREMANTLE)
 
-static inline int get_continuous_mode(void) {
-       return hildon_touch_selector_get_active(HILDON_TOUCH_SELECTOR(cw.continuous_mode_selector), 0);
-}
-static inline void set_continuous_mode(int state) {
-       hildon_touch_selector_set_active(HILDON_TOUCH_SELECTOR(cw.continuous_mode_selector), 0, state);
-}
-
 static inline char *get_default_browser(void) {
-       return browsers[hildon_touch_selector_get_active(HILDON_TOUCH_SELECTOR(cw.default_browser_selector), 0)].config;
+       return installed_browsers[hildon_touch_selector_get_active(HILDON_TOUCH_SELECTOR(cw.default_browser_selector), 0)].config;
 }
 
 #else /* !defined(HILDON) || !defined(FREMANTLE) */
@@ -121,7 +116,7 @@ static inline void set_continuous_mode(int state) {
 }
 
 static inline char *get_default_browser(void) {
-       return browsers[gtk_combo_box_get_active(GTK_COMBO_BOX(cw.default_browser_combo))].config;
+       return installed_browsers[gtk_combo_box_get_active(GTK_COMBO_BOX(cw.default_browser_combo))].config;
 }
 
 #endif /* defined(HILDON) && defined(FREMANTLE) */
@@ -130,10 +125,11 @@ static void set_default_browser(char *browser) {
        gint i;
 
        /* Loop through browsers looking for a match */
-       for (i = 0; browsers[i].config && strcmp(browsers[i].config, browser);
-                       ++i);
+       for (i = 0;
+            installed_browsers[i].config && strcmp(installed_browsers[i].config, browser);
+            ++i);
 
-       if (!browsers[i].config)
+       if (!installed_browsers[i].config)
                /* No match found, set to the default browser */
                i = 0;
 
@@ -153,10 +149,12 @@ static inline void set_other_browser_cmd(char *cmd) {
 
 static void load_config(void) {
        swb_config_init(&orig_cfg);
-       
+
        swb_config_load(&orig_cfg);
 
+#ifndef FREMANTLE
        set_continuous_mode(orig_cfg.continuous_mode);
+#endif
        set_default_browser(orig_cfg.default_browser);
        if (orig_cfg.other_browser_cmd)
                set_other_browser_cmd(orig_cfg.other_browser_cmd);
@@ -167,10 +165,12 @@ static void save_config(void) {
 
        swb_config_copy(&new_cfg, &orig_cfg);
 
+#ifndef FREMANTLE
        if (get_continuous_mode() != orig_cfg.continuous_mode) {
                new_cfg.continuous_mode = get_continuous_mode();
                new_cfg.flags |= SWB_CONFIG_CONTINUOUS_MODE_SET;
        }
+#endif
        if (strcmp(get_default_browser(), orig_cfg.default_browser)) {
                new_cfg.default_browser = get_default_browser();
                new_cfg.flags |= SWB_CONFIG_DEFAULT_BROWSER_SET;
@@ -186,15 +186,9 @@ static void save_config(void) {
        }
 
        swb_config_save(&new_cfg);
-}
-
-static void do_reconfig(void) {
-       save_config();
 
-       /* Try to send SIGHUP to any running browser-switchboard process
-          This causes it to reread config files if in continuous_mode, or
-          die so that the config will be reloaded on next start otherwise */
-       system("kill -HUP `pidof browser-switchboard` > /dev/null 2>&1");
+       /* Reconfigure a running browser-switchboard, if present */
+       swb_reconfig(&orig_cfg, &new_cfg);
 }
 
 
@@ -232,7 +226,6 @@ static GtkDialog *swb_config_dialog(gpointer cp_window) {
        GtkWidget *dialog_vbox;
 
        GtkWidget *default_browser_selector_button;
-       GtkWidget *continuous_mode_selector_button;
        int i;
        HildonGtkInputMode input_mode;
 
@@ -249,9 +242,10 @@ static GtkDialog *swb_config_dialog(gpointer cp_window) {
        dialog_vbox = GTK_DIALOG(dialog)->vbox;
 
        /* Config options */
+       init_installed_browsers();
        cw.default_browser_selector = hildon_touch_selector_new_text();
-       for (i = 0; browsers[i].config; ++i)
-               hildon_touch_selector_append_text(HILDON_TOUCH_SELECTOR(cw.default_browser_selector), browsers[i].displayname);
+       for (i = 0; installed_browsers[i].config; ++i)
+               hildon_touch_selector_append_text(HILDON_TOUCH_SELECTOR(cw.default_browser_selector), installed_browsers[i].displayname);
        hildon_touch_selector_set_active(HILDON_TOUCH_SELECTOR(cw.default_browser_selector), 0, 0);
        default_browser_selector_button = hildon_picker_button_new(_HILDON_SIZE_DEFAULT, HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
        hildon_button_set_title(HILDON_BUTTON(default_browser_selector_button),
@@ -281,20 +275,6 @@ static GtkDialog *swb_config_dialog(gpointer cp_window) {
        gtk_box_pack_start(GTK_BOX(dialog_vbox),
                           cw.other_browser_cmd_entry_label, FALSE, FALSE, 0);
 
-       cw.continuous_mode_selector = hildon_touch_selector_new_text();
-       hildon_touch_selector_append_text(HILDON_TOUCH_SELECTOR(cw.continuous_mode_selector), "Lower memory usage");
-       hildon_touch_selector_append_text(HILDON_TOUCH_SELECTOR(cw.continuous_mode_selector), "Faster browser startup time");
-
-       continuous_mode_selector_button = hildon_picker_button_new(_HILDON_SIZE_DEFAULT, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
-       hildon_button_set_title(HILDON_BUTTON(continuous_mode_selector_button),
-                               "Optimize Browser Switchboard for:");
-       hildon_picker_button_set_selector(HILDON_PICKER_BUTTON(continuous_mode_selector_button), HILDON_TOUCH_SELECTOR(cw.continuous_mode_selector));
-       hildon_button_set_alignment(HILDON_BUTTON(continuous_mode_selector_button),
-                                   0, 0, 0, 0);
-       set_continuous_mode(CONTINUOUS_MODE_DEFAULT);
-       gtk_box_pack_start(GTK_BOX(dialog_vbox),
-                          continuous_mode_selector_button, FALSE, FALSE, 0);
-
        gtk_widget_show_all(dialog);
        return GTK_DIALOG(dialog);
 }
@@ -331,10 +311,11 @@ static GtkDialog *swb_config_dialog(gpointer cp_window) {
        gtk_table_set_row_spacings(GTK_TABLE(options_table), 5);
        gtk_box_pack_start(GTK_BOX(dialog_vbox), options_table, FALSE, FALSE, 0);
 
+       init_installed_browsers();
        cw.default_browser_combo = gtk_combo_box_new_text();
-       for (i = 0; browsers[i].config; ++i)
+       for (i = 0; installed_browsers[i].config; ++i)
                gtk_combo_box_append_text(GTK_COMBO_BOX(cw.default_browser_combo),
-                                         browsers[i].displayname);
+                                         installed_browsers[i].displayname);
        gtk_combo_box_set_active(GTK_COMBO_BOX(cw.default_browser_combo), 0);
        default_browser_combo_label = gtk_label_new("Default browser:");
        gtk_misc_set_alignment(GTK_MISC(default_browser_combo_label), 1, 0.5);
@@ -436,7 +417,7 @@ osso_return_t execute(osso_context_t *osso,
 
        response = gtk_dialog_run(dialog);
        if (response == GTK_RESPONSE_OK)
-               do_reconfig();
+               save_config();
 
        gtk_widget_destroy(GTK_WIDGET(dialog));
 
@@ -465,7 +446,7 @@ int main(int argc, char *argv[]) {
 
        response = gtk_dialog_run(dialog);
        if (response == GTK_RESPONSE_OK)
-               do_reconfig();
+               save_config();
 
        gtk_widget_destroy(GTK_WIDGET(dialog));
 
index 518160c..c913b67 100644 (file)
@@ -1,4 +1,4 @@
-[Desktop Entry] 
+[Desktop Entry]
 Encoding=UTF-8
 Version=1.0
 Name=Browser Switchboard
diff --git a/config-ui/browsers.h b/config-ui/browsers.h
new file mode 100644 (file)
index 0000000..7ac4988
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * browsers.h -- the list of known browsers
+ *
+ * Copyright (C) 2010 Steven Luo
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#ifndef _BROWSERS_H
+#define _BROWSERS_H 1
+
+struct browser_entry {
+       char *config;
+       char *displayname;
+       char *binary;
+};
+
+struct browser_entry browsers[] = {
+       { "microb", "MicroB (stock browser)", NULL }, /* First entry is the default! */
+       { "tear", "Tear", "/usr/bin/tear" },
+       { "fennec", "Firefox Mobile", "/usr/bin/fennec" },
+       { "opera", "Opera Mobile", "/usr/bin/opera" },
+       { "midori", "Midori", "/usr/bin/midori" },
+       { "other", "Other", NULL },
+       { NULL, NULL, NULL },
+};
+
+#endif /* _BROWSERS_H */
index 4415b99..1787f0e 100644 (file)
 #include <sys/types.h>
 #include <sys/stat.h>
 
+#ifdef FREMANTLE
+#include <sys/wait.h>
+#endif
+
 #include "configfile.h"
 #include "config.h"
 
@@ -38,7 +42,7 @@ static void swb_config_output_option(FILE *fp, unsigned int *oldcfg_seen,
                              struct swb_config *cfg, char *name) {
        struct swb_config_option *opt;
        ptrdiff_t i;
-       
+
        for (opt = swb_config_options; opt->name; ++opt) {
                if (strcmp(opt->name, name))
                        continue;
@@ -145,3 +149,48 @@ out:
                fclose(fp);
        return retval;
 }
+
+/* Reconfigure a running browser-switchboard process with new settings */
+void swb_reconfig(struct swb_config *old, struct swb_config *new) {
+#ifdef FREMANTLE
+       int microb_was_autostarted, microb_should_autostart;
+       pid_t pid;
+       int status;
+#endif
+
+       /* Try to send SIGHUP to any running browser-switchboard process
+          This causes it to reread config files if in continuous_mode, or
+          die so that the config will be reloaded on next start otherwise */
+       system("kill -HUP `pidof browser-switchboard` > /dev/null 2>&1");
+
+#ifdef FREMANTLE
+       if (!old || !new)
+               return;
+
+       microb_was_autostarted = (old->autostart_microb == 1) ||
+                                (!strcmp(old->default_browser, "microb") &&
+                                 old->autostart_microb);
+       microb_should_autostart = (new->autostart_microb == 1) ||
+                                 (!strcmp(new->default_browser, "microb") &&
+                                  new->autostart_microb);
+       if (!microb_was_autostarted && microb_should_autostart) {
+               /* MicroB should be started if it's not running */
+               status = system("pidof browser > /dev/null");
+               if (WIFEXITED(status) && WEXITSTATUS(status)) {
+                       if ((pid = fork()) == -1)
+                               return;
+
+                       if (!pid) {
+                               /* Child process, start MicroB */
+                               execl("/usr/bin/maemo-invoker", "browser",
+                                     (char *)NULL);
+                       }
+               }
+       }
+       /* XXX: We'd like to stop MicroB if (microb_was_autostarted &&
+          !microb_should_autostart), but we don't know if the open MicroB
+          process has open windows. */
+#endif /* FREMANTLE */
+
+       return;
+}
diff --git a/config-ui/save-config.h b/config-ui/save-config.h
new file mode 100644 (file)
index 0000000..e25d783
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * save-config.h -- definitions for saving Browser Switchboard configuration
+ *
+ * Copyright (C) 2009-2010 Steven Luo
+ * Derived from a Python implementation by Jason Simpson and Steven Luo
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#ifndef _SAVE_CONFIG_H
+#define _SAVE_CONFIG_H
+
+#include "config.h"
+
+int swb_config_save(struct swb_config *cfg);
+void swb_reconfig(struct swb_config *old, struct swb_config *new);
+
+#endif /* _SAVE_CONFIG_H */
index 8928a3d..2dcbfae 100644 (file)
--- a/config.c
+++ b/config.c
@@ -33,16 +33,18 @@ struct swb_config_option swb_config_options[] = {
        { "default_browser", SWB_CONFIG_OPT_STRING, SWB_CONFIG_DEFAULT_BROWSER_SET },
        { "other_browser_cmd", SWB_CONFIG_OPT_STRING, SWB_CONFIG_OTHER_BROWSER_CMD_SET },
        { "logging", SWB_CONFIG_OPT_STRING, SWB_CONFIG_LOGGING_SET },
+       { "autostart_microb", SWB_CONFIG_OPT_INT, SWB_CONFIG_AUTOSTART_MICROB_SET },
        { NULL, 0, 0 },
 };
 
 /* Browser Switchboard configuration defaults */
 static struct swb_config swb_config_defaults = {
        .flags = SWB_CONFIG_INITIALIZED,
-       .continuous_mode = 0,
+       .continuous_mode = 1,
        .default_browser = "microb",
        .other_browser_cmd = NULL,
        .logging = "stdout",
+       .autostart_microb = -1,
 };
 
 
@@ -56,6 +58,7 @@ void swb_config_copy(struct swb_config *dst, struct swb_config *src) {
        dst->entries[1] = &(dst->default_browser);
        dst->entries[2] = &(dst->other_browser_cmd);
        dst->entries[3] = &(dst->logging);
+       dst->entries[4] = &(dst->autostart_microb);
 
        dst->flags = src->flags;
 
@@ -63,6 +66,7 @@ void swb_config_copy(struct swb_config *dst, struct swb_config *src) {
        dst->default_browser = src->default_browser;
        dst->other_browser_cmd = src->other_browser_cmd;
        dst->logging = src->logging;
+       dst->autostart_microb = src->autostart_microb;
 }
 
 /* Initialize a swb_config struct with configuration defaults */
@@ -101,8 +105,8 @@ static int swb_config_load_option(struct swb_config *cfg,
                                  char *name, char *value) {
        struct swb_config_option *opt;
        ptrdiff_t i;
-       int retval = 0;
 
+       /* Search through list of recognized config options for a match */
        for (opt = swb_config_options; opt->name; ++opt) {
                if (strcmp(name, opt->name))
                        continue;
@@ -119,15 +123,17 @@ static int swb_config_load_option(struct swb_config *cfg,
                                break;
                        }
                        cfg->flags |= opt->set_mask;
+               } else {
+                       /* Option was repeated in the config file
+                          We want the first value, so ignore this one */
+                       free(value);
                }
-               retval = 1;
-               break;
+               return 1;
        }
 
-       if (!retval)
-               free(value);
-
-       return retval;
+       /* Unrecognized config option */
+       free(value);
+       return 0;
 }
 
 /* Read the config file and load settings into the provided swb_config struct
index 858aec5..31149f6 100644 (file)
--- a/config.h
+++ b/config.h
 #define SWB_CONFIG_DEFAULT_BROWSER_SET         0x04
 #define SWB_CONFIG_OTHER_BROWSER_CMD_SET       0x08
 #define SWB_CONFIG_LOGGING_SET                 0x10
+#define SWB_CONFIG_AUTOSTART_MICROB_SET                0x20
 
 struct swb_config {
        unsigned int flags;
        /* Array of pointers to the elements of the struct, in the order given
           in swb_config_options[] */
-       void *entries[4];
+       void *entries[5];
 
        int continuous_mode;
        char *default_browser;
        char *other_browser_cmd;
        char *logging;
+       int autostart_microb;
 };
 
 struct swb_config_option {
@@ -56,6 +58,4 @@ void swb_config_free(struct swb_config *cfg);
 
 int swb_config_load(struct swb_config *cfg);
 
-int swb_config_save(struct swb_config *cfg);
-
 #endif /* _CONFIG_H */
index 5ed02d6..0a522aa 100644 (file)
@@ -169,7 +169,7 @@ int parse_config_file_line(FILE *fp, struct swb_config_line *line) {
        /* calloc() zeroes the memory, so string is automatically
           null terminated */
 
-       /* make key point to a null-terminated string holding the 
+       /* make key point to a null-terminated string holding the
           config key */
        len = substrs[1].rm_eo - substrs[1].rm_so;
        memmove(line->key, line->key+substrs[1].rm_so, len);
index f20a690..748f557 100644 (file)
@@ -147,9 +147,10 @@ void dbus_request_osso_browser_name(struct swb_context *ctx) {
        GError *error = NULL;
        guint result;
 
-       if (!ctx || !ctx->dbus_proxy)
+       if (!ctx || !ctx->dbus_proxy || !ctx->dbus_system_proxy)
                return;
 
+       /* Acquire the com.nokia.osso_browser name on the session bus */
        if (!dbus_g_proxy_call(ctx->dbus_proxy, "RequestName", &error,
                               G_TYPE_STRING, "com.nokia.osso_browser",
                               G_TYPE_UINT, DBUS_NAME_FLAG_REPLACE_EXISTING|DBUS_NAME_FLAG_DO_NOT_QUEUE,
@@ -159,10 +160,26 @@ void dbus_request_osso_browser_name(struct swb_context *ctx) {
                log_msg("Couldn't acquire name com.nokia.osso_browser\n");
                exit(1);
        }
-       if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {  
+       if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
                log_msg("Couldn't acquire name com.nokia.osso_browser\n");
                exit(1);
        }
+
+       /* Try to acquire the com.nokia.osso_browser name on the system bus
+          Treat a failure as non-fatal, which makes testing on desktop systems
+          easier */
+       if (!dbus_g_proxy_call(ctx->dbus_system_proxy, "RequestName", &error,
+                              G_TYPE_STRING, "com.nokia.osso_browser",
+                              G_TYPE_UINT, DBUS_NAME_FLAG_REPLACE_EXISTING|DBUS_NAME_FLAG_DO_NOT_QUEUE,
+                              G_TYPE_INVALID,
+                              G_TYPE_UINT, &result,
+                              G_TYPE_INVALID)) {
+               log_msg("Couldn't acquire name com.nokia.osso_browser on system bus\n");
+               g_error_free(error);
+       }
+       if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+               log_msg("Couldn't acquire name com.nokia.osso_browser on system bus\n");
+       }
 }
 
 /* Release the name com.nokia.osso_browser on the D-Bus session bus */
@@ -170,7 +187,7 @@ void dbus_release_osso_browser_name(struct swb_context *ctx) {
        GError *error = NULL;
        guint result;
 
-       if (!ctx || !ctx->dbus_proxy)
+       if (!ctx || !ctx->dbus_proxy || !ctx->dbus_system_proxy)
                return;
 
        dbus_g_proxy_call(ctx->dbus_proxy, "ReleaseName", &error,
@@ -178,4 +195,9 @@ void dbus_release_osso_browser_name(struct swb_context *ctx) {
                          G_TYPE_INVALID,
                          G_TYPE_UINT, &result,
                          G_TYPE_INVALID);
+       dbus_g_proxy_call(ctx->dbus_system_proxy, "ReleaseName", &error,
+                         G_TYPE_STRING, "com.nokia.osso_browser",
+                         G_TYPE_INVALID,
+                         G_TYPE_UINT, &result,
+                         G_TYPE_INVALID);
 }
index fe57eb9..f42e999 100644 (file)
@@ -56,53 +56,9 @@ struct browser_launcher {
 
 #ifdef FREMANTLE
 static int microb_started = 0;
-
-/* Check to see whether MicroB is ready to handle D-Bus requests yet
-   See the comments in launch_microb to understand how this works. */
-static DBusHandlerResult check_microb_started(DBusConnection *connection,
-                                    DBusMessage *message,
-                                    void *user_data) {
-       DBusError error;
-       char *name, *old, *new;
-
-       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)) {
-               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) {
-               log_msg("MicroB ready\n");
-               microb_started = 1;
-       }
-
-       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
-/* Get a browserd PID from the corresponding Mozilla profile lockfile */
-static pid_t get_browserd_pid(const char *lockfile) {
-       char buf[256], *tmp;
-
-       /* The lockfile is a symlink pointing to "[ipaddr]:+[pid]", so read in
-          the target of the symlink and parse it that way */
-       memset(buf, '\0', 256);
-       if (readlink(lockfile, buf, 255) == -1)
-               return -errno;
-       if (!(tmp = strstr(buf, ":+")))
-               return 0;
-       tmp += 2; /* Skip over the ":+" */
-
-       return atoi(tmp);
-}
 #endif
 
+
 /* Close stdin/stdout/stderr and replace with /dev/null */
 static int close_stdio(void) {
        int fd;
@@ -117,6 +73,7 @@ static int close_stdio(void) {
        return 0;
 }
 
+
 static void launch_tear(struct swb_context *ctx, char *uri) {
        int status;
        static DBusGProxy *tear_proxy = NULL;
@@ -170,47 +127,229 @@ static void launch_tear(struct swb_context *ctx, char *uri) {
        }
 }
 
-void launch_microb(struct swb_context *ctx, char *uri) {
-       int kill_browserd = 0;
+
+#ifdef FREMANTLE
+/* Get a browserd PID from the corresponding Mozilla profile lockfile */
+static pid_t get_browserd_pid(const char *lockfile) {
+       char buf[256], *tmp;
+
+       /* The lockfile is a symlink pointing to "[ipaddr]:+[pid]", so read in
+          the target of the symlink and parse it that way */
+       memset(buf, '\0', 256);
+       if (readlink(lockfile, buf, 255) == -1)
+               return -errno;
+       if (!(tmp = strstr(buf, ":+")))
+               return 0;
+       tmp += 2; /* Skip over the ":+" */
+
+       return atoi(tmp);
+}
+
+/* Check to see whether MicroB is ready to handle D-Bus requests yet
+   See the comments in microb_start_dbus_watch_* to understand how this
+   works. */
+static DBusHandlerResult check_microb_started(DBusConnection *connection,
+                                    DBusMessage *message,
+                                    void *user_data) {
+       DBusError error;
+       char *name, *old, *new;
+
+       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)) {
+               log_msg("%s\n", error.message);
+               dbus_error_free(&error);
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+       }
+       /* If new is not an empty string, then the name has been acquired, and
+          MicroB should be ready to handle our request */
+       if (strlen(new) > 0) {
+               log_msg("MicroB ready\n");
+               microb_started = 1;
+       }
+
+       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+/* Set up the D-Bus eavesdropping we'll use to watch for MicroB acquiring the
+   com.nokia.osso_browser D-Bus name.
+
+   Ideas for how to do this monitoring derived from the dbus-monitor code
+   (tools/dbus-monitor.c in the D-Bus codebase). */
+DBusConnection *microb_start_dbus_watch_init(void) {
+       DBusConnection *conn;
+       DBusError dbus_error;
+       DBusHandleMessageFunction filter_func = check_microb_started;
+
+       dbus_error_init(&dbus_error);
+
+       conn = dbus_bus_get_private(DBUS_BUS_SESSION, &dbus_error);
+       if (!conn) {
+               log_msg("Failed to open connection to session bus: %s\n",
+                       dbus_error.message);
+               dbus_error_free(&dbus_error);
+               return NULL;
+       }
+
+       dbus_bus_add_match(conn,
+                          "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged',arg0='com.nokia.osso_browser'",
+                          &dbus_error);
+       if (dbus_error_is_set(&dbus_error)) {
+               log_msg("Failed to set up watch for browser UI start: %s\n",
+                       dbus_error.message);
+               dbus_error_free(&dbus_error);
+               return NULL;
+       }
+       if (!dbus_connection_add_filter(conn, filter_func, NULL, NULL)) {
+               log_msg("Failed to set up watch filter!\n");
+               return NULL;
+       }
+
+       return conn;
+}
+
+/* Wait for MicroB to acquire the com.nokia.osso_browser D-Bus name
+   Blocks until name is acquired, then returns */
+void microb_start_dbus_watch_wait(DBusConnection *conn) {
+       microb_started = 0;
+       log_msg("Waiting for MicroB to start\n");
+       while (!microb_started &&
+              dbus_connection_read_write_dispatch(conn, -1));
+}
+
+/* Tear down the D-Bus watch for acquiring com.nokia.osso-browser */
+void microb_start_dbus_watch_remove(DBusConnection *conn) {
+       DBusError dbus_error;
+       DBusHandleMessageFunction filter_func = check_microb_started;
+
+       dbus_error_init(&dbus_error);
+
+       dbus_connection_remove_filter(conn, filter_func, NULL);
+       dbus_bus_remove_match(conn,
+                             "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged',arg0='com.nokia.osso_browser'",
+                             &dbus_error);
+       if (dbus_error_is_set(&dbus_error))
+               /* Don't really care -- about to disconnect from the
+                  bus anyhow */
+               dbus_error_free(&dbus_error);
+       dbus_connection_close(conn);
+       dbus_connection_unref(conn);
+}
+
+/* Start a new MicroB browser process if one isn't already running */
+pid_t launch_microb_start_browser_process(DBusConnection *conn, int fd) {
+       pid_t pid;
+       int status;
+
+       status = system("pidof browser > /dev/null");
+       if (WIFEXITED(status) && !WEXITSTATUS(status)) {
+               /* MicroB browser already running */
+               return 0;
+       }
+
+       if ((pid = fork()) == -1) {
+               log_perror(errno, "fork");
+               return -1;
+       }
+
+       if (!pid) {
+               /* Child process */
+               dbus_connection_close(conn);
+               dbus_connection_unref(conn);
+               if (fd != -1)
+                       close(fd);
+               close_stdio();
+
+               /* 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 */
+               /* Launch the browser in the background -- our parent will
+                  wait for it to claim the D-Bus name and then display the
+                  window using D-Bus */
+               execl("/usr/bin/maemo-invoker", "browser", (char *)NULL);
+
+               /* If we get here, exec() failed */
+               exit(1);
+       }
+
+       return pid;
+}
+
+/* Open a MicroB window using the D-Bus interface
+   It's assumed that we have already released the D-Bus name and that it's been
+   ensured that MicroB has acquired com.nokia.osso_browser (otherwise this will
+   cause D-Bus to try forever to launch another browser-switchboard) */
+
+#define LAUNCH_MICROB_BOOKMARK_WIN_OK 0x1
+
+int launch_microb_open_window(struct swb_context *ctx, char *uri,
+                             int flags) {
+       DBusGProxy *g_proxy;
+       GError *gerror = NULL;
+
+       g_proxy = dbus_g_proxy_new_for_name(ctx->session_bus,
+                       "com.nokia.osso_browser",
+                       "/com/nokia/osso_browser/request",
+                       "com.nokia.osso_browser");
+       if (!g_proxy) {
+               log_msg("Couldn't get a com.nokia.osso_browser proxy\n");
+               return 0;
+       }
+
+       if (!strcmp(uri, "new_window")) {
+               if (flags & LAUNCH_MICROB_BOOKMARK_WIN_OK) {
+                       if (!dbus_g_proxy_call(g_proxy, "top_application",
+                                              &gerror, G_TYPE_INVALID,
+                                              G_TYPE_INVALID)) {
+                               log_msg("Opening window failed: %s\n",
+                                       gerror->message);
+                               g_error_free(gerror);
+                               return 0;
+                       }
+
+                       return 1;
+               } else {
+                       /* Since we can't detect when the bookmark window
+                          closes, we'd have a corner case where, if the user
+                          just closes the bookmark window without opening any
+                          browser windows, we don't kill off MicroB or resume
+                          handling com.nokia.osso_browser */
+                       uri = "about:blank";
+               }
+       }
+       if (!dbus_g_proxy_call(g_proxy, "load_url",
+                              &gerror,
+                              G_TYPE_STRING, uri,
+                              G_TYPE_INVALID,
+                              G_TYPE_INVALID)) {
+               log_msg("Opening window failed: %s\n", gerror->message);
+               g_error_free(gerror);
+               return 0;
+       }
+
+       g_object_unref(g_proxy);
+       return 1;
+}
+
+/* Launch Fremantle MicroB and kill it when the session is finished */
+void launch_microb_fremantle_with_kill(struct swb_context *ctx, char *uri) {
        int status;
        pid_t pid;
-#ifdef FREMANTLE
        char *homedir, *microb_profile_dir, *microb_lockfile;
        size_t len;
        int fd, inot_wd;
        DBusConnection *raw_connection;
-       DBusError dbus_error;
-       DBusHandleMessageFunction filter_func;
-       DBusGProxy *g_proxy;
-       GError *gerror = NULL;
        int bytes_read;
        char buf[256], *pos;
        struct inotify_event *event;
        pid_t browserd_pid, waited_pid;
        struct sigaction act, oldact;
        int ignore_sigstop;
-#endif
-
-       if (!uri)
-               uri = "new_window";
 
-       log_msg("launch_microb with uri '%s'\n", uri);
-
-       /* Launch browserd if it's not running */
-       status = system("pidof browserd > /dev/null");
-       if (WIFEXITED(status) && WEXITSTATUS(status)) {
-               kill_browserd = 1;
-#ifdef FREMANTLE
-               system("/usr/sbin/browserd -d -b > /dev/null 2>&1");
-#else
-               system("/usr/sbin/browserd -d > /dev/null 2>&1");
-#endif
-       }
-
-       /* Release the osso_browser D-Bus name so that MicroB can take it */
-       dbus_release_osso_browser_name(ctx);
-
-#ifdef FREMANTLE
        /* Put together the path to the MicroB browserd lockfile */
        if (!(homedir = getenv("HOME")))
                homedir = DEFAULT_HOMEDIR;
@@ -248,122 +387,51 @@ void launch_microb(struct swb_context *ctx, char *uri) {
        /* Set up the D-Bus eavesdropping we'll use to watch for MicroB
           acquiring the com.nokia.osso_browser D-Bus name.  Again, this needs
           to happen before the browser is launched, so that there's no race
-          between establishing the watch and browser startup.
-
-          Ideas for how to do this monitoring derived from the dbus-monitor
-          code (tools/dbus-monitor.c in the D-Bus codebase). */
-       dbus_error_init(&dbus_error);
-
-       raw_connection = dbus_bus_get_private(DBUS_BUS_SESSION, &dbus_error);
-       if (!raw_connection) {
-               log_msg("Failed to open connection to session bus: %s\n",
-                       dbus_error.message);
-               dbus_error_free(&dbus_error);
+          between establishing the watch and browser startup. */
+       if (!(raw_connection = microb_start_dbus_watch_init())) {
                exit(1);
        }
 
-       dbus_bus_add_match(raw_connection,
-                          "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged',arg0='com.nokia.osso_browser'",
-                          &dbus_error);
-       if (dbus_error_is_set(&dbus_error)) {
-               log_msg("Failed to set up watch for browser UI start: %s\n",
-                       dbus_error.message);
-               dbus_error_free(&dbus_error);
+       /* Launch a MicroB browser process if it's not already running */
+       if ((pid = launch_microb_start_browser_process(raw_connection, fd)) < 0)
                exit(1);
-       }
-       filter_func = check_microb_started;
-       if (!dbus_connection_add_filter(raw_connection,
-                                       filter_func, NULL, NULL)) {
-               log_msg("Failed to set up watch filter!\n");
-               exit(1);
-       }
 
-       if ((pid = fork()) == -1) {
-               log_perror(errno, "fork");
+       /* Release the osso_browser D-Bus name so that MicroB can take it */
+       dbus_release_osso_browser_name(ctx);
+
+       /* Wait for our child to start the browser UI process and
+          for it to acquire the com.nokia.osso_browser D-Bus name,
+          then make the appropriate method call to open the browser
+          window. */
+       microb_start_dbus_watch_wait(raw_connection);
+       microb_start_dbus_watch_remove(raw_connection);
+       if (!launch_microb_open_window(ctx, uri, 0)) {
                exit(1);
        }
 
-       if (pid > 0) {
-               /* Parent process */
-               /* Wait for our child to start the browser UI process and
-                  for it to acquire the com.nokia.osso_browser D-Bus name,
-                  then make the appropriate method call to open the browser
-                  window. */
-               microb_started = 0;
-               log_msg("Waiting for MicroB to start\n");
-               while (!microb_started &&
-                      dbus_connection_read_write_dispatch(raw_connection,
-                                                          -1));
-               dbus_connection_remove_filter(raw_connection,
-                                             filter_func, NULL);
-               dbus_bus_remove_match(raw_connection,
-                                     "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged',arg0='com.nokia.osso_browser'",
-                                     &dbus_error);
-               if (dbus_error_is_set(&dbus_error))
-                       /* Don't really care -- about to disconnect from the
-                          bus anyhow */
-                       dbus_error_free(&dbus_error);
-               dbus_connection_close(raw_connection);
-               dbus_connection_unref(raw_connection);
-
-               /* Browser UI's started, send it the request for a new window
-                  via D-Bus */
-               g_proxy = dbus_g_proxy_new_for_name(ctx->session_bus,
-                               "com.nokia.osso_browser",
-                               "/com/nokia/osso_browser/request",
-                               "com.nokia.osso_browser");
-               if (!g_proxy) {
-                       log_msg("Couldn't get a com.nokia.osso_browser proxy\n");
-                       exit(1);
-               }
-               if (!strcmp(uri, "new_window")) {
-#if 0 /* Since we can't detect when the bookmark window closes, we'd have a
-        corner case where, if the user just closes the bookmark window
-        without opening any browser windows, we don't kill off MicroB or
-        resume handling com.nokia.osso_browser */
-                       if (!dbus_g_proxy_call(g_proxy, "top_application",
-                                              &gerror, G_TYPE_INVALID,
-                                              G_TYPE_INVALID)) {
-                               log_msg("Opening window failed: %s\n",
-                                       gerror->message);
-                               exit(1);
-                       }
-#endif
-                       if (!dbus_g_proxy_call(g_proxy, "load_url",
-                                              &gerror,
-                                              G_TYPE_STRING, "about:blank",
-                                              G_TYPE_INVALID,
-                                              G_TYPE_INVALID)) {
-                               log_msg("Opening window failed: %s\n",
-                                       gerror->message);
-                               exit(1);
-                       }
-               } else {
-                       if (!dbus_g_proxy_call(g_proxy, "load_url",
-                                              &gerror,
-                                              G_TYPE_STRING, uri,
-                                              G_TYPE_INVALID,
-                                              G_TYPE_INVALID)) {
-                               log_msg("Opening window failed: %s\n",
-                                       gerror->message);
-                               exit(1);
-                       }
-               }
-               g_object_unref(g_proxy);
-
-               /* Workaround: the browser process we started is going to want
-                  to hang around forever, hogging the com.nokia.osso_browser
-                  D-Bus interface while at it.  To fix this, we notice that
-                  when the last browser window closes, the browser UI restarts
-                  its attached browserd process.  Get the browserd process's
-                  PID and use ptrace() to watch for process termination.
-
-                  This has the problem of not being able to detect whether
-                  the bookmark window is open and/or in use, but it's the best
-                  that I can think of.  Better suggestions would be greatly
-                  appreciated. */
-
-               /* Wait for the MicroB browserd lockfile to be created */
+       /* Workaround: the browser process we started is going to want
+          to hang around forever, hogging the com.nokia.osso_browser
+          D-Bus interface while at it.  To fix this, we notice that
+          when the last browser window closes, the browser UI restarts
+          its attached browserd process.  Get the browserd process's
+          PID and use ptrace() to watch for process termination.
+
+          This has the problem of not being able to detect whether
+          the bookmark window is open and/or in use, but it's the best
+          that I can think of.  Better suggestions would be greatly
+          appreciated. */
+
+       if (!pid)
+               /* If we didn't start the MicroB browser process ourselves, try
+                  to get the PID of the browserd from the lockfile */
+               browserd_pid = get_browserd_pid(microb_lockfile);
+       else
+               browserd_pid = 0;
+
+       /* If getting the lockfile PID failed, or the lockfile PID doesn't
+          exist, assume that we have a stale lockfile and wait for the new
+          browserd lockfile to be created */
+       if (browserd_pid <= 0 || kill(browserd_pid, 0) == ESRCH) {
                log_msg("Waiting for browserd lockfile to be created\n");
                memset(buf, '\0', 256);
                /* read() blocks until there are events to be read */
@@ -373,10 +441,8 @@ void launch_microb(struct swb_context *ctx, char *uri) {
                           or until all the events are processed */
                        while (pos && (pos-buf) < bytes_read) {
                                event = (struct inotify_event *)pos;
-                               len = sizeof(struct inotify_event)
-                                     + event->len;
-                               if (!strcmp(MICROB_LOCKFILE,
-                                           event->name)) {
+                               len = sizeof(struct inotify_event) + event->len;
+                               if (!strcmp(MICROB_LOCKFILE, event->name)) {
                                        /* Lockfile created */
                                        pos = NULL;
                                        break;
@@ -392,10 +458,7 @@ void launch_microb(struct swb_context *ctx, char *uri) {
                                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)
                                log_msg("Profile lockfile link lacks PID\n");
@@ -404,90 +467,157 @@ void launch_microb(struct swb_context *ctx, char *uri) {
                                           "readlink() on lockfile failed");
                        exit(1);
                }
-               free(microb_lockfile);
-
-               /* Wait for the browserd to close */
-               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) {
-                       log_perror(errno, "clearing SIGCHLD handler failed");
-                       exit(1);
-               }
+       }
+       inotify_rm_watch(fd, inot_wd);
+       close(fd);
+       free(microb_lockfile);
+
+       /* Wait for the browserd to close */
+       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) {
+               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) {
-                       log_perror(errno, "PTRACE_ATTACH");
-                       exit(1);
-               }
-               ptrace(PTRACE_CONT, browserd_pid, NULL, NULL);
-               while ((waited_pid = wait(&status)) > 0) {
-                       if (waited_pid != browserd_pid)
-                               /* Not interested in other processes */
+       /* Trace the browserd to get a close notification */
+       ignore_sigstop = 1;
+       if (ptrace(PTRACE_ATTACH, browserd_pid, NULL, NULL) == -1) {
+               log_perror(errno, "PTRACE_ATTACH");
+               exit(1);
+       }
+       ptrace(PTRACE_CONT, browserd_pid, NULL, NULL);
+       while ((waited_pid = wait(&status)) > 0) {
+               if (waited_pid != browserd_pid)
+                       /* Not interested in other processes */
+                       continue;
+               if (WIFEXITED(status) || WIFSIGNALED(status))
+                       /* browserd exited */
+                       break;
+               else if (WIFSTOPPED(status)) {
+                       /* browserd was sent a signal
+                          We're responsible for making sure this signal gets
+                          delivered */
+                       if (ignore_sigstop && WSTOPSIG(status) == SIGSTOP) {
+                               /* Ignore the first SIGSTOP received
+                                  This is raised for some reason immediately
+                                  after we start tracing the process, and
+                                  won't be followed by a SIGCONT at any point
+                                */
+                               log_msg("Ignoring first SIGSTOP\n");
+                               ptrace(PTRACE_CONT, browserd_pid, NULL, NULL);
+                               ignore_sigstop = 0;
                                continue;
-                       if (WIFEXITED(status) || WIFSIGNALED(status))
-                               /* browserd exited */
-                               break;
-                       else if (WIFSTOPPED(status)) {
-                               /* browserd was sent a signal
-                                  We're responsible for making sure this
-                                  signal gets delivered */
-                               if (ignore_sigstop &&
-                                   WSTOPSIG(status) == SIGSTOP) {
-                                       /* Ignore the first SIGSTOP received
-                                          This is raised for some reason
-                                          immediately after we start tracing
-                                          the process, and won't be followed
-                                          by a SIGCONT at any point */
-                                       log_msg("Ignoring first SIGSTOP\n");
-                                       ptrace(PTRACE_CONT, browserd_pid,
-                                              NULL, NULL);
-                                       ignore_sigstop = 0;
-                                       continue;
-                               }
-                               log_msg("Forwarding signal %d to browserd\n",
-                                       WSTOPSIG(status));
-                               ptrace(PTRACE_CONT, browserd_pid,
-                                      NULL, WSTOPSIG(status));
                        }
+                       log_msg("Forwarding signal %d to browserd\n",
+                               WSTOPSIG(status));
+                       ptrace(PTRACE_CONT, browserd_pid, NULL,
+                              WSTOPSIG(status));
                }
+       }
 
-               /* Kill off browser UI
-                  XXX: There is a race here with the restarting of the closed
-                  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! */
-               log_msg("Killing MicroB\n");
+       /* Kill off browser UI
+          XXX: There is a race here with the restarting of the closed
+          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! */
+       log_msg("Killing MicroB\n");
+       if (pid > 0) {
                kill(pid, SIGTERM);
                waitpid(pid, &status, 0);
-
-               /* Restore old SIGCHLD handler */
-               if (sigaction(SIGCHLD, &oldact, NULL) == -1) {
-                       log_perror(errno,
-                                  "restoring old SIGCHLD handler failed");
-                       exit(1);
-               }
        } else {
-               /* Child process */
-               dbus_connection_close(raw_connection);
-               dbus_connection_unref(raw_connection);
-               close(fd);
-               close_stdio();
+               system("kill `pidof browser` > /dev/null 2>&1");
+       }
 
-               /* 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 */
-               /* Launch the browser in the background -- our parent will
-                  wait for it to claim the D-Bus name and then display the
-                  window using D-Bus */
-               execl("/usr/bin/maemo-invoker", "browser", (char *)NULL);
+       /* Restore old SIGCHLD handler */
+       if (sigaction(SIGCHLD, &oldact, NULL) == -1) {
+               log_perror(errno, "restoring old SIGCHLD handler failed");
+               exit(1);
+       }
+
+       dbus_request_osso_browser_name(ctx);
+}
+
+/* Launch a new window in Fremantle MicroB; don't kill the MicroB process
+   when the session is finished
+   This is designed to work with a prestarted MicroB process that runs
+   continuously in the background */
+void launch_microb_fremantle(struct swb_context *ctx, char *uri) {
+       DBusConnection *raw_connection;
+
+       /* Set up the D-Bus eavesdropping we'll use to watch for MicroB
+          acquiring the com.nokia.osso_browser D-Bus name */
+       if (!(raw_connection = microb_start_dbus_watch_init())) {
+               exit(1);
+       }
+
+       /* Launch a MicroB browser process if it's not already running */
+       if (launch_microb_start_browser_process(raw_connection, -1) < 0)
+               exit(1);
+
+       /* Release the osso_browser D-Bus name so that MicroB can take it */
+       dbus_release_osso_browser_name(ctx);
+
+       /* Wait for MicroB to acquire com.nokia.osso_browser, then make the
+          appropriate method call to open the browser window. */
+       microb_start_dbus_watch_wait(raw_connection);
+       microb_start_dbus_watch_remove(raw_connection);
+       if (!launch_microb_open_window(ctx, uri,
+                                      LAUNCH_MICROB_BOOKMARK_WIN_OK)) {
+               exit(1);
+       }
+
+       /* Take back the osso_browser D-Bus name from MicroB */
+       dbus_request_osso_browser_name(ctx);
+}
+#endif /* FREMANTLE */
+
+void launch_microb(struct swb_context *ctx, char *uri) {
+       int kill_browserd = 0;
+       int status;
+#ifndef FREMANTLE
+       pid_t pid;
+#endif
+
+       if (!uri)
+               uri = "new_window";
+
+       log_msg("launch_microb with uri '%s'\n", uri);
+
+       /* Launch browserd if it's not running */
+       status = system("pidof browserd > /dev/null");
+       if (WIFEXITED(status) && WEXITSTATUS(status)) {
+               kill_browserd = 1;
+#ifdef FREMANTLE
+               system("/usr/sbin/browserd -d -b > /dev/null 2>&1");
+#else
+               system("/usr/sbin/browserd -d > /dev/null 2>&1");
+#endif
+       }
+
+#ifdef FREMANTLE
+       /* Do the insanity to launch Fremantle MicroB */
+       if ((ctx->default_browser_launcher == launch_microb &&
+            ctx->autostart_microb) || ctx->autostart_microb == 1) {
+
+               /* If MicroB is set as the default browser, or if the user has
+                  configured MicroB to always be running, just send the
+                  running MicroB the request */
+               launch_microb_fremantle(ctx, uri);
+       } else {
+               /* Otherwise, launch MicroB and kill it when the user's
+                  MicroB session is done */
+               launch_microb_fremantle_with_kill(ctx, uri);
        }
 #else /* !FREMANTLE */
+       /* Release the osso_browser D-Bus name so that MicroB can take it */
+       dbus_release_osso_browser_name(ctx);
+
        if ((pid = fork()) == -1) {
                log_perror(errno, "fork");
                exit(1);
@@ -511,16 +641,16 @@ void launch_microb(struct swb_context *ctx, char *uri) {
                              "browser", "--url", uri, (char *)NULL);
                }
        }
+
+       dbus_request_osso_browser_name(ctx);
 #endif /* FREMANTLE */
 
        /* Kill off browserd if we started it */
        if (kill_browserd)
                system("kill `pidof browserd`");
 
-       if (!ctx || !ctx->continuous_mode) 
+       if (!ctx || !ctx->continuous_mode)
                exit(0);
-
-       dbus_request_osso_browser_name(ctx);
 }
 
 static void launch_other_browser(struct swb_context *ctx, char *uri) {
@@ -590,7 +720,7 @@ static void launch_other_browser(struct swb_context *ctx, char *uri) {
                        /* Parent process or error in fork() */
                        if (urilen > 0)
                                free(quoted_uri);
-                       free(command);  
+                       free(command);
                        return;
                }
                /* Child process */
diff --git a/main.c b/main.c
index 40823e3..2e19b84 100644 (file)
--- a/main.c
+++ b/main.c
@@ -49,7 +49,14 @@ static void read_config(int signalnum) {
        swb_config_load(&cfg);
 
        log_config(cfg.logging);
+#ifdef FREMANTLE
+       /* continuous mode is required on Fremantle */
+       ctx.continuous_mode = 1;
+       if (!cfg.continuous_mode)
+               log_msg("continuous_mode = 0 operation no longer supported, ignoring config setting\n");
+#else
        ctx.continuous_mode = cfg.continuous_mode;
+#endif
        free(ctx.other_browser_cmd);
        if (cfg.other_browser_cmd) {
                if (!(ctx.other_browser_cmd = strdup(cfg.other_browser_cmd))) {
@@ -59,6 +66,9 @@ static void read_config(int signalnum) {
        } else
                ctx.other_browser_cmd = NULL;
        update_default_browser(&ctx, cfg.default_browser);
+#ifdef FREMANTLE
+       ctx.autostart_microb = cfg.autostart_microb;
+#endif
 
        log_msg("continuous_mode: %d\n", cfg.continuous_mode);
        log_msg("default_browser: '%s'\n", cfg.default_browser);
@@ -72,6 +82,7 @@ static void read_config(int signalnum) {
 
 int main() {
        OssoBrowser *obj_osso_browser, *obj_osso_browser_req;
+       OssoBrowser *obj_osso_browser_sys, *obj_osso_browser_sys_req;
        GMainLoop *mainloop;
        GError *error = NULL;
        int reqname_result;
@@ -134,21 +145,43 @@ int main() {
                        error->message);
                return 1;
        }
-       if (reqname_result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {  
+       if (reqname_result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
                log_msg("Another browser-switchboard already running\n");
                return 1;
        }
 
+       /* Get a connection to the D-Bus system bus */
+       ctx.system_bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
+       if (!ctx.system_bus) {
+               log_msg("Couldn't get a D-Bus system bus connection\n");
+               return 1;
+       }
+       ctx.dbus_system_proxy = dbus_g_proxy_new_for_name(ctx.system_bus,
+                       "org.freedesktop.DBus", "/org/freedesktop/DBus",
+                       "org.freedesktop.DBus");
+       if (!ctx.dbus_system_proxy) {
+               log_msg("Couldn't get an org.freedesktop.DBus proxy\n");
+               return 1;
+       }
+
        dbus_request_osso_browser_name(&ctx);
 
        /* Register ourselves to handle the osso_browser D-Bus methods */
        obj_osso_browser = g_object_new(OSSO_BROWSER_TYPE, NULL);
        obj_osso_browser_req = g_object_new(OSSO_BROWSER_TYPE, NULL);
+       obj_osso_browser_sys = g_object_new(OSSO_BROWSER_TYPE, NULL);
+       obj_osso_browser_sys_req = g_object_new(OSSO_BROWSER_TYPE, NULL);
        dbus_g_connection_register_g_object(ctx.session_bus,
                        "/com/nokia/osso_browser", G_OBJECT(obj_osso_browser));
        dbus_g_connection_register_g_object(ctx.session_bus,
                        "/com/nokia/osso_browser/request",
                        G_OBJECT(obj_osso_browser_req));
+       dbus_g_connection_register_g_object(ctx.system_bus,
+                       "/com/nokia/osso_browser",
+                       G_OBJECT(obj_osso_browser_sys));
+       dbus_g_connection_register_g_object(ctx.system_bus,
+                       "/com/nokia/osso_browser/request",
+                       G_OBJECT(obj_osso_browser_sys_req));
 
        mainloop = g_main_loop_new(NULL, FALSE);
        log_msg("Starting main loop\n");
diff --git a/microb b/microb
index 334523f..ed7c006 100755 (executable)
--- a/microb
+++ b/microb
@@ -1,5 +1,15 @@
 #!/bin/sh
 
+get_name_owner() {
+       output=$(dbus-send --session --type=method_call --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.GetNameOwner string:"$1" 2>/dev/null)
+       RETVAL=$?
+       if [ $RETVAL -ne 0 ]; then
+               return $RETVAL
+       fi
+       echo "$output" | tail -1
+       return 0
+}
+
 case "$1" in
        --url=* )
                url="${1#--url=}"
@@ -9,10 +19,24 @@ case "$1" in
                ;;
 esac
 
-if pidof browser > /dev/null 2>&1; then
-       method=open_new_window
-else
+# Check whether Browser Switchboard owns the com.nokia.osso_browser name or not
+osso_browser_owner=$(get_name_owner com.nokia.osso_browser)
+if [ $? -ne 0 ]; then
+       # No one owns com.nokia.osso_browser -- let D-Bus start
+       # browser-switchboard to handle this request
        method=switchboard_launch_microb
+else
+       # If com.nokia.osso_browser is owned by the owner of
+       # org.maemo.garage.browser-switchboard, then Browser Switchboard must
+       # be the owner
+       browser_switchboard_owner=$(get_name_owner org.maemo.garage.browser-switchboard)
+       if [ "$osso_browser_owner" = "$browser_switchboard_owner" ]; then
+               # Browser Switchboard owns com.nokia.osso_browser
+               method=switchboard_launch_microb
+       else
+               # Assume MicroB owns com.nokia.osso_browser
+               method=open_new_window
+       fi
 fi
 
 dbus-send --session --type=method_call --print-reply --dest="com.nokia.osso_browser" /com/nokia/osso_browser/request com.nokia.osso_browser.$method string:${url:-"new_window"} > /dev/null 2>&1
diff --git a/xsession-post.sh b/xsession-post.sh
new file mode 100755 (executable)
index 0000000..237a9cd
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# start Browser Switchboard, then start MicroB if appropriate
+/usr/bin/browser-switchboard > /dev/null 2>&1 &
+
+if ! /bin/pidof browser > /dev/null 2>&1; then
+       DEFAULT_BROWSER=`/usr/bin/browser-switchboard-config -b`
+       AUTOSTART_MICROB=`/usr/bin/browser-switchboard-config -o autostart_microb`
+       if [ "$AUTOSTART_MICROB" -eq 1 ] || [ "$DEFAULT_BROWSER" = "microb" -a "$AUTOSTART_MICROB" -ne 0 ]; then
+               /usr/bin/maemo-invoker /usr/bin/browser.launch > /dev/null 2>&1 &
+       fi
+fi