2 * (C) Copyright 2007,2010,2012 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 const Cu
= Components
.utils
;
13 Cu
.import("resource://gre/modules/XPCOMUtils.jsm");
15 function application () {
16 Cu
.import("resource://gre/modules/XPCOMUtils.jsm", this);
18 this.wrappedJSObject
= this;
21 this.load_url
= this.subscript_loader
.loadSubScript
;
22 this.loading_urls
= [];
23 this.loading_paths
= [];
24 this.loading_features
= [];
26 this.load_paths
= [this.module_uri_prefix
,
27 this.module_uri_prefix
+'extensions',
28 this.module_uri_prefix
+'page-modes'];
29 this.after_load_functions
= {};
30 this.pending_loads
= [];
32 // clear the startup-cache so that modules and the user's rc are
33 // loaded from disk, not from a cache. this problem is a
34 // characteristic of using mozIJSSubScriptLoader.loadSubScript as our
35 // primary means of loading, since XULRunner 8.0.
36 var obs
= Cc
["@mozilla.org/observer-service;1"]
37 .getService(Ci
.nsIObserverService
);
38 obs
.notifyObservers(null, "startupcache-invalidate", null);
41 this.require("conkeror.js");
43 this.dumpln("Error initializing.");
47 application
.prototype = {
48 constructor: application
,
52 /* Note: resource://app currently doesn't result in xpcnativewrappers=yes */
53 module_uri_prefix
: "chrome://conkeror/content/",
54 subscript_loader
: Cc
["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci
.mozIJSSubScriptLoader
),
55 preferences
: Cc
["@mozilla.org/preferences-service;1"].getService(Ci
.nsIPrefService
),
57 var formatter
= Cc
["@mozilla.org/toolkit/URLFormatterService;1"]
58 .getService(Ci
.nsIURLFormatter
);
59 return formatter
.formatURL("%VERSION%");
61 dumpln: function (str
) {
65 dump_error: function (e
) {
66 if (e
instanceof Error
) {
67 this.dumpln(e
.name
+ ": " + e
.message
);
68 this.dumpln(e
.fileName
+ ":" + e
.lineNumber
);
70 } else if (e
instanceof Ci
.nsIException
) {
71 this.dumpln(e
.name
+ ": " + e
.message
);
72 var stack_frame
= e
.location
;
74 this.dumpln(stack_frame
.name
+ "()@" + stack_frame
.filename
+ ":" + stack_frame
.lineNumber
);
75 stack_frame
= stack_frame
.caller
;
78 this.dumpln("Error: " + e
);
82 make_uri: function (uri
, charset
, base_uri
) {
83 const io_service
= Cc
["@mozilla.org/network/io-service;1"]
84 .getService(Ci
.nsIIOService2
);
85 if (uri
instanceof Ci
.nsIURI
)
87 if (uri
instanceof Ci
.nsIFile
)
88 return io_service
.newFileURI(uri
);
89 return io_service
.newURI(uri
, charset
, base_uri
);
91 load: function (module
) {
92 function load1 (url
, path
) {
94 this.loading_paths
.unshift(path
);
95 this.loading_urls
.unshift(url
);
96 this.loading_features
.unshift({});
97 if (this.loading_urls
.indexOf(url
, 1) != -1)
98 throw new Error("Circular module dependency detected: "+
99 this.loading_urls
.join(",\n"));
100 if (url
.substr(-4) == ".jsx") {
101 var scopename
= url
.substr(url
.lastIndexOf('/')+1)
103 var dot
= scopename
.indexOf(".");
105 scopename
= scopename
.substr(0, dot
);
106 var scope
= { __proto__
: this };
109 this.load_url(url
, scope
);
111 this[scopename
] = scope
;
113 // call-after-load callbacks
114 for (let f
in this.loading_features
[0]) {
115 this.features
[f
] = true;
116 this.run_after_load_functions(f
);
119 this.loading_paths
.shift();
120 this.loading_urls
.shift();
121 this.loading_features
.shift();
124 if (success
&& this.loading_urls
[0] === undefined) {
125 let pending
= this.pending_loads
;
126 this.pending_loads
= [];
127 for (let i
= 0, m
; m
= pending
[i
]; ++i
) {
132 if (module
instanceof Ci
.nsIURI
)
133 var path
= module
.spec
.substr(0, module
.spec
.lastIndexOf('/')+1);
134 else if (module
instanceof Ci
.nsIFile
)
135 path
= module
.parent
.path
;
136 if (path
!== undefined) {
137 var url
= this.make_uri(module
).spec
;
138 load1
.call(this.conkeror
, url
, path
);
140 // module name or relative path
141 var si
= module
.lastIndexOf('/');
142 var module_leaf
= module
.substr(si
+1);
143 var autoext
= module_leaf
.lastIndexOf(".") <= 0;
144 var exts
= { 0:"", 1:".js", 2:".jsx", len
:3 };
148 path
= this.loading_paths
[0];
149 if (path
=== undefined)
150 path
= this.load_paths
[++i
];
151 while (path
!== undefined) {
153 var sep
= path
.substr(-1) == '/' ? '' : '/';
154 var ext
= exts
[exti
];
156 url
= path
+ sep
+ module
+ ext
;
158 truepath
+= sep
+ module
.substr(0, si
);
161 load1
.call(this.conkeror
, url
, truepath
);
164 } catch (e
if (typeof e
== 'string' &&
165 (e
.startsWith("ContentLength not available (not a local URL?)") ||
166 e
.startsWith("Error creating channel (invalid URL scheme?)") ||
167 e
.startsWith("Error opening input stream (invalid filename?)")))) {
168 // null op. (suppress error, try next path)
171 exti
= (exti
+ 1) % exts
.len
;
173 path
= this.load_paths
[++i
];
175 throw new Error("Module not found ("+module
+")");
178 provide: function (symbol
) {
180 throw new Error("Cannot provide null feature");
181 if (this.loading_urls
[0] === undefined) {
182 this.features
[symbol
] = true;
183 this.run_after_load_functions(symbol
);
185 this.loading_features
[0][symbol
] = true;
187 featurep: function (symbol
) {
188 return this.features
[symbol
] || false;
190 call_after_load: function (feature
, func
) {
191 if (this.featurep(feature
))
194 var funcs
= this.after_load_functions
[feature
];
196 funcs
= this.after_load_functions
[feature
] = [];
200 run_after_load_functions: function (symbol
) {
201 var funcs
= this.after_load_functions
[symbol
];
203 delete this.after_load_functions
[symbol
];
204 for (var i
= 0, n
= funcs
.length
; i
< n
; ++i
) {
213 require: function (module
) {
214 if (module
instanceof Ci
.nsIURI
)
215 var feature
= module
.spec
.substr(module
.spec
.lastIndexOf('/')+1);
216 else if (module
instanceof Ci
.nsIFile
)
217 feature
= module
.leafName
;
219 feature
= module
.substr(module
.lastIndexOf('/')+1);
220 var dot
= feature
.indexOf('.');
224 feature
= feature
.substr(0, dot
);
225 feature
= feature
.replace(/_
/g
, '-');
226 if (this.featurep(feature
))
229 // ensure current path is not searched for 'require'
230 this.loading_paths
.unshift(undefined);
233 this.loading_paths
.shift();
237 require_later: function (module
) {
238 this.pending_loads
.push(module
);
242 QueryInterface
: XPCOMUtils
.generateQI([]),
244 /* XPCOM registration */
245 classDescription
: "Conkeror global object",
246 classID
: Components
.ID("{72a7eea7-a894-47ec-93a9-a7bc172cf1ac}"),
247 contractID
: "@conkeror.mozdev.org/application;1"
250 if (XPCOMUtils
.generateNSGetFactory
)
251 var NSGetFactory
= XPCOMUtils
.generateNSGetFactory([application
]); //XULRunner 2.0
253 var NSGetModule
= XPCOMUtils
.generateNSGetModule([application
]);