2 * (C) Copyright 2007,2010 John J. Foerch
3 * (C) Copyright 2007-2008 Jeremy Maitin-Shepard
5 * Use, modification, and distribution are subject to the terms specified in the
9 const Cc = Components.classes;
10 const Ci = Components.interfaces;
11 const Cr = Components.results;
12 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
14 function application () {
15 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm", this);
17 this.wrappedJSObject = this;
20 this.load_url = this.subscript_loader.loadSubScript;
21 this.loading_urls = [];
22 this.loading_paths = [];
23 this.loading_features = [];
25 this.load_paths = [this.module_uri_prefix,
26 this.module_uri_prefix+'extensions',
27 this.module_uri_prefix+'page-modes'];
28 this.after_load_functions = {};
29 this.pending_loads = [];
31 // clear the startup-cache so that modules and the user's rc are
32 // loaded from disk, not from a cache. this problem is a
33 // characteristic of using mozIJSSubScriptLoader.loadSubScript as our
34 // primary means of loading, since XULRunner 8.0.
35 var obs = Cc["@mozilla.org/observer-service;1"]
36 .getService(Ci.nsIObserverService);
37 obs.notifyObservers(null, "startupcache-invalidate", null);
40 this.require("conkeror.js");
42 this.dumpln("Error initializing.");
46 application.prototype = {
47 constructor: application,
51 /* Note: resource://app currently doesn't result in xpcnativewrappers=yes */
52 module_uri_prefix: "chrome://conkeror/content/",
53 subscript_loader: Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader),
54 preferences: Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService),
56 var formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"]
57 .getService(Ci.nsIURLFormatter);
58 return formatter.formatURL("%VERSION%");
60 dumpln: function (str) {
64 dump_error: function (e) {
65 if (e instanceof Error) {
66 this.dumpln(e.name + ": " + e.message);
67 this.dumpln(e.fileName + ":" + e.lineNumber);
69 } else if (e instanceof Ci.nsIException) {
70 this.dumpln(e.name + ": " + e.message);
71 var stack_frame = e.location;
73 this.dumpln(stack_frame.name + "()@" + stack_frame.filename + ":" + stack_frame.lineNumber);
74 stack_frame = stack_frame.caller;
77 this.dumpln("Error: " + e);
81 make_uri: function (uri, charset, base_uri) {
82 const io_service = Cc["@mozilla.org/network/io-service;1"]
83 .getService(Ci.nsIIOService2);
84 if (uri instanceof Ci.nsIURI)
86 if (uri instanceof Ci.nsIFile)
87 return io_service.newFileURI(uri);
88 return io_service.newURI(uri, charset, base_uri);
90 load: function (module) {
91 function load1 (url, path) {
93 this.loading_paths.unshift(path);
94 this.loading_urls.unshift(url);
95 this.loading_features.unshift({});
96 if (this.loading_urls.indexOf(url, 1) != -1)
97 throw new Error("Circular module dependency detected: "+
98 this.loading_urls.join(",\n"));
99 this.load_url(url, this);
101 // call-after-load callbacks
102 for (let f in this.loading_features[0]) {
103 this.features[f] = true;
104 this.run_after_load_functions(f);
107 this.loading_paths.shift();
108 this.loading_urls.shift();
109 this.loading_features.shift();
112 if (success && this.loading_urls[0] === undefined) {
113 let pending = this.pending_loads;
114 this.pending_loads = [];
115 for (let i = 0, m; m = pending[i]; ++i) {
120 if (module instanceof Ci.nsIURI)
121 var path = module.spec.substr(0, module.spec.lastIndexOf('/')+1);
122 else if (module instanceof Ci.nsIFile)
123 path = module.parent.path;
124 if (path !== undefined) {
125 var url = this.make_uri(module).spec;
126 load1.call(this, url, path);
128 // module name or relative path
129 var autoext = module.substr(-3) != '.js';
133 path = this.loading_paths[0];
134 if (path === undefined)
135 path = this.load_paths[++i];
136 while (path !== undefined) {
139 let sep = path.substr(-1) == '/' ? '' : '/';
140 url = path + sep + module + (suffix ? '.js' : '');
141 let si = module.lastIndexOf('/');
143 truepath += module.substr(0, si);
146 load1.call(this, url, truepath);
149 } catch (e if (typeof e == 'string' &&
150 {"ContentLength not available (not a local URL?)":true,
151 "Error creating channel (invalid URL scheme?)":true,
152 "Error opening input stream (invalid filename?)":true}
154 // null op. (suppress error, try next path)
159 path = this.load_paths[++i];
161 throw new Error("Module not found ("+module+")");
164 provide: function (symbol) {
166 throw new Error("Cannot provide null feature");
167 if (this.loading_urls[0] === undefined) {
168 this.features[symbol] = true;
169 this.run_after_load_functions(symbol);
171 this.loading_features[0][symbol] = true;
173 featurep: function (symbol) {
174 return this.features[symbol] || false;
176 call_after_load: function (feature, func) {
177 if (this.featurep(feature))
180 var funcs = this.after_load_functions[feature];
182 funcs = this.after_load_functions[feature] = [];
186 run_after_load_functions: function (symbol) {
187 var funcs = this.after_load_functions[symbol];
189 delete this.after_load_functions[symbol];
190 for (var i = 0; funcs[i]; ++i) {
199 require: function (module) {
200 if (module instanceof Ci.nsIURI)
201 var feature = module.spec.substr(module.spec.lastIndexOf('/')+1);
202 else if (module instanceof Ci.nsIFile)
203 feature = module.leafName;
205 feature = module.substr(module.lastIndexOf('/')+1);
206 var dot = feature.indexOf('.');
210 feature = feature.substr(0, dot);
211 feature = feature.replace('_', '-', 'g');
212 if (this.featurep(feature))
215 // ensure current path is not searched for 'require'
216 this.loading_paths.unshift(undefined);
219 this.loading_paths.shift();
223 require_later: function (module) {
224 this.pending_loads.push(module);
228 QueryInterface: XPCOMUtils.generateQI([]),
230 /* XPCOM registration */
231 classDescription: "Conkeror global object",
232 classID: Components.ID("{72a7eea7-a894-47ec-93a9-a7bc172cf1ac}"),
233 contractID: "@conkeror.mozdev.org/application;1"
236 if (XPCOMUtils.generateNSGetFactory)
237 var NSGetFactory = XPCOMUtils.generateNSGetFactory([application]); //XULRunner 2.0
239 var NSGetModule = XPCOMUtils.generateNSGetModule([application]);