hostenv_ff_ext.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. // a host environment specifically built for Mozilla extensions, but derived
  7. // from the browser host environment
  8. if(typeof window != 'undefined'){
  9. dojo.isBrowser = true;
  10. dojo._name = "browser";
  11. // FIXME: PORTME
  12. // http://developer.mozilla.org/en/mozIJSSubScriptLoader
  13. // attempt to figure out the path to dojo if it isn't set in the config
  14. (function(){
  15. var d = dojo;
  16. // this is a scope protection closure. We set browser versions and grab
  17. // the URL we were loaded from here.
  18. // FIXME: need to probably use a different reference to "document" to get the hosting XUL environment
  19. d.baseUrl = d.config.baseUrl;
  20. // fill in the rendering support information in dojo.render.*
  21. var n = navigator;
  22. var dua = n.userAgent;
  23. var dav = n.appVersion;
  24. var tv = parseFloat(dav);
  25. d.isMozilla = d.isMoz = tv;
  26. if(d.isMoz){
  27. d.isFF = parseFloat(dua.split("Firefox/")[1]) || undefined;
  28. }
  29. // FIXME
  30. d.isQuirks = document.compatMode == "BackCompat";
  31. // FIXME
  32. // TODO: is the HTML LANG attribute relevant?
  33. d.locale = dojo.config.locale || n.language.toLowerCase();
  34. d._xhrObj = function(){
  35. return new XMLHttpRequest();
  36. }
  37. // monkey-patch _loadUri to handle file://, chrome://, and resource:// url's
  38. var oldLoadUri = d._loadUri;
  39. d._loadUri = function(uri, cb){
  40. var handleLocal = ["file:", "chrome:", "resource:"].some(function(prefix){
  41. return String(uri).indexOf(prefix) == 0;
  42. });
  43. if(handleLocal){
  44. // see:
  45. // http://developer.mozilla.org/en/mozIJSSubScriptLoader
  46. var l = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
  47. .getService(Components.interfaces.mozIJSSubScriptLoader);
  48. var value = l.loadSubScript(uri, d.global)
  49. if(cb){ cb(value); }
  50. return true;
  51. }else{
  52. // otherwise, call the pre-existing version
  53. return oldLoadUri.apply(d, arguments);
  54. }
  55. }
  56. // FIXME: PORTME
  57. d._isDocumentOk = function(http){
  58. var stat = http.status || 0;
  59. return (stat >= 200 && stat < 300) || // Boolean
  60. stat == 304 || // allow any 2XX response code
  61. stat == 1223 || // get it out of the cache
  62. (!stat && (location.protocol=="file:" || location.protocol=="chrome:") );
  63. }
  64. // FIXME: PORTME
  65. // var owloc = window.location+"";
  66. // var base = document.getElementsByTagName("base");
  67. // var hasBase = (base && base.length > 0);
  68. var hasBase = false;
  69. d._getText = function(/*URI*/ uri, /*Boolean*/ fail_ok){
  70. // summary: Read the contents of the specified uri and return those contents.
  71. // uri:
  72. // A relative or absolute uri. If absolute, it still must be in
  73. // the same "domain" as we are.
  74. // fail_ok:
  75. // Default false. If fail_ok and loading fails, return null
  76. // instead of throwing.
  77. // returns: The response text. null is returned when there is a
  78. // failure and failure is okay (an exception otherwise)
  79. // alert("_getText: " + uri);
  80. // NOTE: must be declared before scope switches ie. this._xhrObj()
  81. var http = d._xhrObj();
  82. if(!hasBase && dojo._Url){
  83. uri = (new dojo._Url(uri)).toString();
  84. }
  85. if(d.config.cacheBust){
  86. //Make sure we have a string before string methods are used on uri
  87. uri += "";
  88. uri += (uri.indexOf("?") == -1 ? "?" : "&") + String(d.config.cacheBust).replace(/\W+/g,"");
  89. }
  90. var handleLocal = ["file:", "chrome:", "resource:"].some(function(prefix){
  91. return String(uri).indexOf(prefix) == 0;
  92. });
  93. if(handleLocal){
  94. // see:
  95. // http://forums.mozillazine.org/viewtopic.php?p=921150#921150
  96. var ioService = Components.classes["@mozilla.org/network/io-service;1"]
  97. .getService(Components.interfaces.nsIIOService);
  98. var scriptableStream=Components
  99. .classes["@mozilla.org/scriptableinputstream;1"]
  100. .getService(Components.interfaces.nsIScriptableInputStream);
  101. var channel = ioService.newChannel(uri, null, null);
  102. var input = channel.open();
  103. scriptableStream.init(input);
  104. var str = scriptableStream.read(input.available());
  105. scriptableStream.close();
  106. input.close();
  107. return str;
  108. }else{
  109. http.open('GET', uri, false);
  110. try{
  111. http.send(null);
  112. // alert(http);
  113. if(!d._isDocumentOk(http)){
  114. var err = Error("Unable to load "+uri+" status:"+ http.status);
  115. err.status = http.status;
  116. err.responseText = http.responseText;
  117. throw err;
  118. }
  119. }catch(e){
  120. if(fail_ok){ return null; } // null
  121. // rethrow the exception
  122. throw e;
  123. }
  124. return http.responseText; // String
  125. }
  126. }
  127. d._windowUnloaders = [];
  128. // FIXME: PORTME
  129. d.windowUnloaded = function(){
  130. // summary:
  131. // signal fired by impending window destruction. You may use
  132. // dojo.addOnWIndowUnload() or dojo.connect() to this method to perform
  133. // page/application cleanup methods. See dojo.addOnWindowUnload for more info.
  134. var mll = d._windowUnloaders;
  135. while(mll.length){
  136. (mll.pop())();
  137. }
  138. }
  139. // FIXME: PORTME
  140. d.addOnWindowUnload = function(/*Object?*/obj, /*String|Function?*/functionName){
  141. // summary:
  142. // registers a function to be triggered when window.onunload fires.
  143. // Be careful trying to modify the DOM or access JavaScript properties
  144. // during this phase of page unloading: they may not always be available.
  145. // Consider dojo.addOnUnload() if you need to modify the DOM or do heavy
  146. // JavaScript work.
  147. // example:
  148. // | dojo.addOnWindowUnload(functionPointer)
  149. // | dojo.addOnWindowUnload(object, "functionName")
  150. // | dojo.addOnWindowUnload(object, function(){ /* ... */});
  151. d._onto(d._windowUnloaders, obj, functionName);
  152. }
  153. // XUL specific APIs
  154. var contexts = [];
  155. var current = null;
  156. dojo._defaultContext = [ window, document ];
  157. dojo.pushContext = function(/*Object|String?*/g, /*MDocumentElement?*/d){
  158. // summary:
  159. // causes subsequent calls to Dojo methods to assume the
  160. // passed object and, optionally, document as the default
  161. // scopes to use. A 2-element array of the previous global and
  162. // document are returned.
  163. // description:
  164. // dojo.pushContext treats contexts as a stack. The
  165. // auto-detected contexts which are initially provided using
  166. // dojo.setContext() require authors to keep state in order to
  167. // "return" to a previous context, whereas the
  168. // dojo.pushContext and dojo.popContext methods provide a more
  169. // natural way to augment blocks of code to ensure that they
  170. // execute in a different window or frame without issue. If
  171. // called without any arguments, the default context (the
  172. // context when Dojo is first loaded) is instead pushed into
  173. // the stack. If only a single string is passed, a node in the
  174. // intitial context's document is looked up and its
  175. // contextWindow and contextDocument properties are used as
  176. // the context to push. This means that iframes can be given
  177. // an ID and code can be executed in the scope of the iframe's
  178. // document in subsequent calls easily.
  179. // g:
  180. // The global context. If a string, the id of the frame to
  181. // search for a context and document.
  182. // d:
  183. // The document element to execute subsequent code with.
  184. var old = [dojo.global, dojo.doc];
  185. contexts.push(old);
  186. var n;
  187. if(!g && !d){
  188. n = dojo._defaultContext;
  189. }else{
  190. n = [ g, d ];
  191. if(!d && dojo.isString(g)){
  192. var t = document.getElementById(g);
  193. if(t.contentDocument){
  194. n = [t.contentWindow, t.contentDocument];
  195. }
  196. }
  197. }
  198. current = n;
  199. dojo.setContext.apply(dojo, n);
  200. return old; // Array
  201. };
  202. dojo.popContext = function(){
  203. // summary:
  204. // If the context stack contains elements, ensure that
  205. // subsequent code executes in the *previous* context to the
  206. // current context. The current context set ([global,
  207. // document]) is returned.
  208. var oc = current;
  209. if(!contexts.length){
  210. return oc;
  211. }
  212. dojo.setContext.apply(dojo, contexts.pop());
  213. return oc;
  214. };
  215. // FIXME:
  216. // don't really like the current arguments and order to
  217. // _inContext, so don't make it public until it's right!
  218. dojo._inContext = function(g, d, f){
  219. var a = dojo._toArray(arguments);
  220. f = a.pop();
  221. if(a.length == 1){
  222. d = null;
  223. }
  224. dojo.pushContext(g, d);
  225. var r = f();
  226. dojo.popContext();
  227. return r;
  228. };
  229. })();
  230. dojo._initFired = false;
  231. // BEGIN DOMContentLoaded, from Dean Edwards (http://dean.edwards.name/weblog/2006/06/again/)
  232. dojo._loadInit = function(e){
  233. dojo._initFired = true;
  234. // allow multiple calls, only first one will take effect
  235. // A bug in khtml calls events callbacks for document for event which isnt supported
  236. // for example a created contextmenu event calls DOMContentLoaded, workaround
  237. var type = (e && e.type) ? e.type.toLowerCase() : "load";
  238. if(arguments.callee.initialized || (type != "domcontentloaded" && type != "load")){ return; }
  239. arguments.callee.initialized = true;
  240. if(dojo._inFlightCount == 0){
  241. dojo._modulesLoaded();
  242. }
  243. }
  244. /*
  245. (function(){
  246. var _w = window;
  247. var _handleNodeEvent = function(evtName, fp){
  248. // summary:
  249. // non-destructively adds the specified function to the node's
  250. // evtName handler.
  251. // evtName: should be in the form "onclick" for "onclick" handlers.
  252. // Make sure you pass in the "on" part.
  253. var oldHandler = _w[evtName] || function(){};
  254. _w[evtName] = function(){
  255. fp.apply(_w, arguments);
  256. oldHandler.apply(_w, arguments);
  257. };
  258. };
  259. // FIXME: PORT
  260. // FIXME: dojo.unloaded requires dojo scope, so using anon function wrapper.
  261. _handleNodeEvent("onbeforeunload", function() { dojo.unloaded(); });
  262. _handleNodeEvent("onunload", function() { dojo.windowUnloaded(); });
  263. })();
  264. */
  265. // FIXME: PORTME
  266. // this event fires a lot, namely for all plugin XUL overlays and for
  267. // all iframes (in addition to window navigations). We only want
  268. // Dojo's to fire once..but we might care if pages navigate. We'll
  269. // probably need an extension-specific API
  270. if(!dojo.config.afterOnLoad){
  271. window.addEventListener("DOMContentLoaded",function(e){
  272. dojo._loadInit(e);
  273. // console.log("DOM content loaded", e);
  274. }, false);
  275. }
  276. } //if (typeof window != 'undefined')
  277. //Register any module paths set up in djConfig. Need to do this
  278. //in the hostenvs since hostenv_browser can read djConfig from a
  279. //script tag's attribute.
  280. (function(){
  281. var mp = dojo.config["modulePaths"];
  282. if(mp){
  283. for(var param in mp){
  284. dojo.registerModulePath(param, mp[param]);
  285. }
  286. }
  287. })();
  288. //Load debug code if necessary.
  289. if(dojo.config.isDebug){
  290. // logging stub for extension logging
  291. console.log = function(m){
  292. var s = Components.classes["@mozilla.org/consoleservice;1"].getService(
  293. Components.interfaces.nsIConsoleService
  294. );
  295. s.logStringMessage(m);
  296. }
  297. console.debug = function(){
  298. console.log(dojo._toArray(arguments).join(" "));
  299. }
  300. // FIXME: what about the rest of the console.* methods? And is there any way to reach into firebug and log into it directly?
  301. }