home *** CD-ROM | disk | FTP | other *** search
/ Mundo do CD-ROM 119 / cdrom119.iso / internet / gsync / google-browsersync.xpi / components / bootstrap.js next >
Encoding:
Text File  |  2006-06-07  |  8.8 KB  |  255 lines

  1. // Copyright 2005 and onwards, Google
  2. // Author: Aaron Boodman
  3. //
  4. // Clobber bootstrapper. All the files required by Clobber are loaded into this 
  5. // service's JS context and run here. This gives us a nice, stable, and clean 
  6. // area to play in which cannot be polluted by other extensions and which lasts 
  7. // the entire lifetime of Firefox.
  8. //
  9. // The file also registers several XPCOM components: 
  10. // * app-context: Used by clobber UI to get access to the code loaded here
  11. // * application: Used to hook the app-startup category
  12. // * sync-manager: The main external interface to Clobber from third-party code
  13. //
  14. //
  15. // Summary of the logic for loading necessary js files:
  16. //
  17. // There are two different ways that the bootstrap loader can load the js:
  18. // 1. Consult a manifest to determine which files to load, loading each
  19. //    one individually.  This is usually used during debugging, so that
  20. //    filenames and line numbers are preserved.
  21. // 2. Load a single, compiled js file.  This is how the extension should
  22. //    function in a release xpi.
  23. //
  24. // The default bootstrap loader behavior is to look for the single
  25. // compiled js file and load that.  If the compiled js file is
  26. // not in the lib directory (the location it will be packaged in a xpi),
  27. // you can specify a location via the CLB_COMPILED_JS environment variable.
  28. // You can override this default behavior by setting the CLB_MF_ENV_VAR
  29. // (see below for details.)  
  30. //
  31. // If you specify a manifest location via the CLB_MF_ENV_VAR environment
  32. // variable or if the compiled js cannot be found, the bootstrap loader will
  33. // look for the manifest to determine which files should be loaded.
  34. // If the manifest is not found in either the location specified by the
  35. // environment variable or the lib directory, then the bootstrap loader
  36. // will throw an error.
  37.  
  38. // Firefox and clobber scripts assume that these two are defined
  39. const Cc = Components.classes;
  40. const Ci = Components.interfaces;
  41.  
  42. // We load the manifest in debug mode to see which files need to be loaded
  43. const CLB_MANIFEST = "browserstate.MF";
  44. // Compiled js is only used in opt mode.
  45. const CLB_COMPILED_JS = "browserstate.js";
  46.  
  47. // Environment variable that specifies where to find the manifest
  48. const CLB_MF_ENV_VAR = "CLB_MANIFEST_DIR";
  49. // Environment variable that specifies where to fine the compiled js
  50. const CLB_COMPILED_ENV_VAR = "CLB_COMPILED_JS";
  51.  
  52. var envSvc = Cc["@mozilla.org/process/environment;1"]
  53.              .getService(Ci.nsIEnvironment);
  54.  
  55. // Load js files
  56. CLB_dump("Initializing Google Browser Sync...");
  57.  
  58. var compiledJsLoaded = false;
  59. if (!envSvc.exists(CLB_MF_ENV_VAR)) {
  60.   // In opt mode, we only need to load the compiled javascript.
  61.   try {
  62.     var compiledJsFile = findFile(CLB_COMPILED_JS, CLB_COMPILED_ENV_VAR);
  63.     var compiledJsUrl = Cc["@mozilla.org/network/protocol;1?name=file"]
  64.                         .getService(Ci.nsIFileProtocolHandler)
  65.                         .getURLSpecFromFile(compiledJsFile);
  66.     Cc["@mozilla.org/moz/jssubscript-loader;1"]
  67.       .getService(Ci.mozIJSSubScriptLoader)
  68.       .loadSubScript(compiledJsUrl);
  69.     compiledJsLoaded = true;
  70.   } catch (e) {
  71.     CLB_dump(e.toString());
  72.     CLB_dump("Warning.. could not load compiled js, falling back on manifest");
  73.   }
  74. }
  75.  
  76. if (envSvc.exists(CLB_MF_ENV_VAR) || !compiledJsLoaded) {
  77.   // In debug mode, we look for the manifest that lists the files we need.
  78.   // Then load each file listed there, in order
  79.   var manifest = findFile(CLB_MANIFEST, CLB_MF_ENV_VAR);
  80.  
  81.   // Now that we found the manifest, load it and populate an array with the
  82.   // files we want to load
  83.   var libs = readFile(manifest);
  84.  
  85.   // HACK ALERT: we need G_GDEBUG to be set according to whether we compiled
  86.   // in debug or optimized mode.  This is accomplished via the
  87.   // browserstate_debug genrule in browserstate/client/browserstate/lib/BUILD
  88.   // However, Since this is an output file, it's always placed at the end
  89.   // of the manifest.  Since we need to load it first, we bump it up to
  90.   // the front of the array.
  91.   if (libs[libs.length-1].match("browserstate_debug.js") == null) {
  92.     throw new Error("Could not find debug file in manifest.")
  93.   }
  94.   libs.unshift(libs.pop());
  95.  
  96.   // Now, load all the scripts into this context
  97.   for (var i = 0, libPath; libPath = libs[i]; i++) {
  98.     try {
  99.       Cc["@mozilla.org/moz/jssubscript-loader;1"]
  100.         .getService(Ci.mozIJSSubScriptLoader)
  101.         .loadSubScript(getLibUrl(libPath));
  102.     } catch (e) {
  103.       CLB_dump("Error loading library {%s}: %s", libPath, e);
  104.       throw e;
  105.     }
  106.   }
  107. }
  108.  
  109. // Register some XPCOM components.
  110. CLB_dump("Instanciating core objects...");
  111. var CLB_syncMan = new CLB_SyncManager();
  112. var CLB_app = new CLB_Application();
  113. var CLB_module = new G_JSModule();
  114.  
  115. CLB_dump("Registering with XPCOM...");
  116. // Allows our xul code to use the javascript loaded into this service
  117. CLB_module.registerObject("{3bb339f9-131b-465b-b52c-97ee10e61a05}",
  118.                           "@google.com/browserstate/app-context;1", 
  119.                           "CLB_AppContext",
  120.                           {wrappedJSObject:this});
  121.  
  122. // The main shell for the clobber client
  123. CLB_module.registerObject("{1ec74bff-2c43-4a0a-904f-821b0f624970}",
  124.                           "@google.com/browserstate/application;1", 
  125.                           "CLB_Application",
  126.                           CLB_app);
  127.  
  128. // The official external interface to CLB_SyncManager for other extensions
  129. CLB_module.registerObject("{2fffb7ba-c818-465c-8250-84e9bc4f350b}",
  130.                           "@google.com/browserstate/sync-manager;1", 
  131.                           "CLB_SyncManager",
  132.                           CLB_syncMan);
  133.  
  134. CLB_dump("Adding categories...");
  135. // Register CLB_app to be a command line handler with a very high priority, so
  136. // that it can execute before other command line handlers.
  137. // The priority is the 'a' part of the second argument. See: 
  138. // http://lxr.mozilla.org/mozilla/source/toolkit/components/commandlines/
  139. // public/nsICommandLineHandler.idl
  140. var catMgr = Cc["@mozilla.org/categorymanager;1"]
  141.                .getService(Ci.nsICategoryManager);
  142.  
  143. catMgr.addCategoryEntry("command-line-handler",
  144.                         "a-browserstate",
  145.                         "@google.com/browserstate/application;1",
  146.                         true, true);
  147.  
  148. CLB_dump("Google Browser Sync initialized succesfully!");
  149.  
  150. // TODO(aa): register CLB_SyncItem, but that requires constructor support in
  151. // G_JSModule.
  152.  
  153.  
  154. function NSGetModule() {
  155.   return CLB_module;
  156. }
  157.  
  158. /**
  159.  * Gets a nsIFile for the given physical path relative to the libs/ folder
  160.  */
  161. function getLibFile(path) {
  162.   var file = __LOCATION__.clone().parent.parent;
  163.   var parts = path.split("/");
  164.  
  165.   file.append("lib");
  166.  
  167.   for (var i = 0, part; part = parts[i]; i++) {
  168.     file.append(part);
  169.   }
  170.  
  171.   return file;
  172. }
  173.  
  174. /**
  175.  * Gets a file:// URL for the given physical path relative to the libs/ 
  176.  * folder. 
  177.  */
  178. function getLibUrl(path) {
  179.   var file = getLibFile(path);
  180.  
  181.   if (!file.exists()) {
  182.     throw new Error("Specified library {" + file.path + "} does not exist");
  183.   }
  184.  
  185.   return Cc["@mozilla.org/network/protocol;1?name=file"]
  186.     .getService(Ci.nsIFileProtocolHandler)
  187.     .getURLSpecFromFile(file);
  188. }
  189.  
  190. /**
  191.  * A utility to output to the console, even before G_Debug is loaded.
  192.  */
  193. function CLB_dump(msg) {
  194.   for (var i = 1; i < arguments.length; i++) {
  195.     msg = msg.replace(/\%s/, arguments[i]);
  196.   }
  197.  
  198.   dump("*** CLB *** " + msg + "\n");
  199. }
  200.  
  201. /**
  202.  * Find the given fileName.  First look where the environment variable
  203.  * points, if there is one.  Then fall back on looking in the lib directory.
  204.  * Returns nsILocalFile.
  205.  */
  206. function findFile(fileName, envVar) {
  207.   // First look for the file at the location specified by the env variable,
  208.   // if any
  209.   if (envSvc.exists(envVar)) {
  210.     var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
  211.     var filePath = envSvc.get(envVar) + fileName;
  212.     file.initWithPath(filePath);
  213.  
  214.     // Assume that if they specified an environment variable, they really
  215.     // wanted us to find it at this location, so die if we don't find it.
  216.     if (!file.exists()) {
  217.       throw new Error("File " + fileName + " could not be found at " +
  218.                       filePath);
  219.     }
  220.     return file;
  221.   }
  222.  
  223.   // Then fall back on the lib directory
  224.   var libFile = getLibFile(fileName);
  225.   if (!libFile.exists()) {
  226.     throw new Error("File " + fileName + " could not be found at " +
  227.                     filePath);
  228.   }
  229.  
  230.   return libFile;
  231. }
  232.  
  233. /**
  234.  * Returns all contents of the given file in an array, where each line
  235.  * of the file is a separate element in the array.
  236.  */
  237. function readFile(file) {
  238.   var fs = Cc["@mozilla.org/network/file-input-stream;1"]
  239.            .createInstance(Ci.nsIFileInputStream);
  240.   fs.init(file, 0x01, /* read only */ 0444, 0);
  241.  
  242.   fs.QueryInterface(Ci.nsILineInputStream);
  243.   var data = [];
  244.   do {
  245.     var line = {value : null};
  246.     var more = fs.readLine(line);
  247.     if (line.value != null) {
  248.       data[data.length] = line.value;
  249.     }
  250.   } while (more);
  251.   fs.close();
  252.  
  253.   return data;
  254. }
  255.