home *** CD-ROM | disk | FTP | other *** search
- // Copyright 2005 and onwards, Google
- // Author: Aaron Boodman
- //
- // Clobber bootstrapper. All the files required by Clobber are loaded into this
- // service's JS context and run here. This gives us a nice, stable, and clean
- // area to play in which cannot be polluted by other extensions and which lasts
- // the entire lifetime of Firefox.
- //
- // The file also registers several XPCOM components:
- // * app-context: Used by clobber UI to get access to the code loaded here
- // * application: Used to hook the app-startup category
- // * sync-manager: The main external interface to Clobber from third-party code
- //
- //
- // Summary of the logic for loading necessary js files:
- //
- // There are two different ways that the bootstrap loader can load the js:
- // 1. Consult a manifest to determine which files to load, loading each
- // one individually. This is usually used during debugging, so that
- // filenames and line numbers are preserved.
- // 2. Load a single, compiled js file. This is how the extension should
- // function in a release xpi.
- //
- // The default bootstrap loader behavior is to look for the single
- // compiled js file and load that. If the compiled js file is
- // not in the lib directory (the location it will be packaged in a xpi),
- // you can specify a location via the CLB_COMPILED_JS environment variable.
- // You can override this default behavior by setting the CLB_MF_ENV_VAR
- // (see below for details.)
- //
- // If you specify a manifest location via the CLB_MF_ENV_VAR environment
- // variable or if the compiled js cannot be found, the bootstrap loader will
- // look for the manifest to determine which files should be loaded.
- // If the manifest is not found in either the location specified by the
- // environment variable or the lib directory, then the bootstrap loader
- // will throw an error.
-
- // Firefox and clobber scripts assume that these two are defined
- const Cc = Components.classes;
- const Ci = Components.interfaces;
-
- // We load the manifest in debug mode to see which files need to be loaded
- const CLB_MANIFEST = "browserstate.MF";
- // Compiled js is only used in opt mode.
- const CLB_COMPILED_JS = "browserstate.js";
-
- // Environment variable that specifies where to find the manifest
- const CLB_MF_ENV_VAR = "CLB_MANIFEST_DIR";
- // Environment variable that specifies where to fine the compiled js
- const CLB_COMPILED_ENV_VAR = "CLB_COMPILED_JS";
-
- var envSvc = Cc["@mozilla.org/process/environment;1"]
- .getService(Ci.nsIEnvironment);
-
- // Load js files
- CLB_dump("Initializing Google Browser Sync...");
-
- var compiledJsLoaded = false;
- if (!envSvc.exists(CLB_MF_ENV_VAR)) {
- // In opt mode, we only need to load the compiled javascript.
- try {
- var compiledJsFile = findFile(CLB_COMPILED_JS, CLB_COMPILED_ENV_VAR);
- var compiledJsUrl = Cc["@mozilla.org/network/protocol;1?name=file"]
- .getService(Ci.nsIFileProtocolHandler)
- .getURLSpecFromFile(compiledJsFile);
- Cc["@mozilla.org/moz/jssubscript-loader;1"]
- .getService(Ci.mozIJSSubScriptLoader)
- .loadSubScript(compiledJsUrl);
- compiledJsLoaded = true;
- } catch (e) {
- CLB_dump(e.toString());
- CLB_dump("Warning.. could not load compiled js, falling back on manifest");
- }
- }
-
- if (envSvc.exists(CLB_MF_ENV_VAR) || !compiledJsLoaded) {
- // In debug mode, we look for the manifest that lists the files we need.
- // Then load each file listed there, in order
- var manifest = findFile(CLB_MANIFEST, CLB_MF_ENV_VAR);
-
- // Now that we found the manifest, load it and populate an array with the
- // files we want to load
- var libs = readFile(manifest);
-
- // HACK ALERT: we need G_GDEBUG to be set according to whether we compiled
- // in debug or optimized mode. This is accomplished via the
- // browserstate_debug genrule in browserstate/client/browserstate/lib/BUILD
- // However, Since this is an output file, it's always placed at the end
- // of the manifest. Since we need to load it first, we bump it up to
- // the front of the array.
- if (libs[libs.length-1].match("browserstate_debug.js") == null) {
- throw new Error("Could not find debug file in manifest.")
- }
- libs.unshift(libs.pop());
-
- // Now, load all the scripts into this context
- for (var i = 0, libPath; libPath = libs[i]; i++) {
- try {
- Cc["@mozilla.org/moz/jssubscript-loader;1"]
- .getService(Ci.mozIJSSubScriptLoader)
- .loadSubScript(getLibUrl(libPath));
- } catch (e) {
- CLB_dump("Error loading library {%s}: %s", libPath, e);
- throw e;
- }
- }
- }
-
- // Register some XPCOM components.
- CLB_dump("Instanciating core objects...");
- var CLB_syncMan = new CLB_SyncManager();
- var CLB_app = new CLB_Application();
- var CLB_module = new G_JSModule();
-
- CLB_dump("Registering with XPCOM...");
- // Allows our xul code to use the javascript loaded into this service
- CLB_module.registerObject("{3bb339f9-131b-465b-b52c-97ee10e61a05}",
- "@google.com/browserstate/app-context;1",
- "CLB_AppContext",
- {wrappedJSObject:this});
-
- // The main shell for the clobber client
- CLB_module.registerObject("{1ec74bff-2c43-4a0a-904f-821b0f624970}",
- "@google.com/browserstate/application;1",
- "CLB_Application",
- CLB_app);
-
- // The official external interface to CLB_SyncManager for other extensions
- CLB_module.registerObject("{2fffb7ba-c818-465c-8250-84e9bc4f350b}",
- "@google.com/browserstate/sync-manager;1",
- "CLB_SyncManager",
- CLB_syncMan);
-
- CLB_dump("Adding categories...");
- // Register CLB_app to be a command line handler with a very high priority, so
- // that it can execute before other command line handlers.
- // The priority is the 'a' part of the second argument. See:
- // http://lxr.mozilla.org/mozilla/source/toolkit/components/commandlines/
- // public/nsICommandLineHandler.idl
- var catMgr = Cc["@mozilla.org/categorymanager;1"]
- .getService(Ci.nsICategoryManager);
-
- catMgr.addCategoryEntry("command-line-handler",
- "a-browserstate",
- "@google.com/browserstate/application;1",
- true, true);
-
- CLB_dump("Google Browser Sync initialized succesfully!");
-
- // TODO(aa): register CLB_SyncItem, but that requires constructor support in
- // G_JSModule.
-
-
- function NSGetModule() {
- return CLB_module;
- }
-
- /**
- * Gets a nsIFile for the given physical path relative to the libs/ folder
- */
- function getLibFile(path) {
- var file = __LOCATION__.clone().parent.parent;
- var parts = path.split("/");
-
- file.append("lib");
-
- for (var i = 0, part; part = parts[i]; i++) {
- file.append(part);
- }
-
- return file;
- }
-
- /**
- * Gets a file:// URL for the given physical path relative to the libs/
- * folder.
- */
- function getLibUrl(path) {
- var file = getLibFile(path);
-
- if (!file.exists()) {
- throw new Error("Specified library {" + file.path + "} does not exist");
- }
-
- return Cc["@mozilla.org/network/protocol;1?name=file"]
- .getService(Ci.nsIFileProtocolHandler)
- .getURLSpecFromFile(file);
- }
-
- /**
- * A utility to output to the console, even before G_Debug is loaded.
- */
- function CLB_dump(msg) {
- for (var i = 1; i < arguments.length; i++) {
- msg = msg.replace(/\%s/, arguments[i]);
- }
-
- dump("*** CLB *** " + msg + "\n");
- }
-
- /**
- * Find the given fileName. First look where the environment variable
- * points, if there is one. Then fall back on looking in the lib directory.
- * Returns nsILocalFile.
- */
- function findFile(fileName, envVar) {
- // First look for the file at the location specified by the env variable,
- // if any
- if (envSvc.exists(envVar)) {
- var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
- var filePath = envSvc.get(envVar) + fileName;
- file.initWithPath(filePath);
-
- // Assume that if they specified an environment variable, they really
- // wanted us to find it at this location, so die if we don't find it.
- if (!file.exists()) {
- throw new Error("File " + fileName + " could not be found at " +
- filePath);
- }
- return file;
- }
-
- // Then fall back on the lib directory
- var libFile = getLibFile(fileName);
- if (!libFile.exists()) {
- throw new Error("File " + fileName + " could not be found at " +
- filePath);
- }
-
- return libFile;
- }
-
- /**
- * Returns all contents of the given file in an array, where each line
- * of the file is a separate element in the array.
- */
- function readFile(file) {
- var fs = Cc["@mozilla.org/network/file-input-stream;1"]
- .createInstance(Ci.nsIFileInputStream);
- fs.init(file, 0x01, /* read only */ 0444, 0);
-
- fs.QueryInterface(Ci.nsILineInputStream);
- var data = [];
- do {
- var line = {value : null};
- var more = fs.readLine(line);
- if (line.value != null) {
- data[data.length] = line.value;
- }
- } while (more);
- fs.close();
-
- return data;
- }
-