root/trunk/chrome/content/common/overlayFunctions.js

Revision 871, 20.3 kB (checked in by MaierMan, 2 years ago)

Simplify getProfileFile

Line 
1 /* ***** BEGIN LICENSE BLOCK *****
2  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Mozilla Public License Version
5  * 1.1 (the "License"); you may not use this file except in compliance with
6  * the License. You may obtain a copy of the License at
7  * http://www.mozilla.org/MPL/
8  *
9  * Software distributed under the License is distributed on an "AS IS" basis,
10  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11  * for the specific language governing rights and limitations under the
12  * License.
13  *
14  * The Original Code is DownThemAll.
15  *
16  * The Initial Developer of the Original Code is Nils Maier
17  * Portions created by the Initial Developer are Copyright (C) 2007
18  * the Initial Developer. All Rights Reserved.
19  *
20  * Contributor(s):
21  *   Nils Maier <MaierMan@web.de>
22  *   Federico Parodi <f.parodi@tiscali.it>
23  *   Stefano Verna <stefano.verna@gmail.com>
24  *
25  * Alternatively, the contents of this file may be used under the terms of
26  * either the GNU General Public License Version 2 or later (the "GPL"), or
27  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28  * in which case the provisions of the GPL or the LGPL are applicable instead
29  * of those above. If you wish to allow use of your version of this file only
30  * under the terms of either the GPL or the LGPL, and not to allow others to
31  * use your version of this file under the terms of the MPL, indicate your
32  * decision by deleting the provisions above and replace them with the notice
33  * and other provisions required by the GPL or the LGPL. If you do not delete
34  * the provisions above, a recipient may use your version of this file under
35  * the terms of any one of the MPL, the GPL or the LGPL.
36  *
37  * ***** END LICENSE BLOCK ***** */
38
39 /**
40  * include other chrome js files
41  * @param uri Relative URI to the dta content path
42  * @param many Optional. If set, then include that file more than once
43  */
44 var DTA_include = function() {
45   var _loaded = {};
46   return function(uri, many) {
47     if (!many && uri in _loaded) {
48       return true;
49     }
50     try {
51       Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
52         .getService(Components.interfaces.mozIJSSubScriptLoader)
53         .loadSubScript("chrome://dta/content/" + uri);     
54       _loaded[uri] = true;
55       return true;
56     }
57     catch (ex) {
58       Components.utils.reportError(ex);
59     }
60     return false;
61   }
62 }();
63
64 var DTA_FilterManager = Components.classes['@downthemall.net/filtermanager;2']
65   .getService(Components.interfaces.dtaIFilterManager);
66
67 function DTA_showPreferences() {
68   var instantApply = DTA_preferences.get("browser.preferences.instantApply", false);
69   window.openDialog(
70     'chrome://dta/content/preferences/prefs.xul',
71     'dtaPrefs',
72     'chrome,titlebar,toolbar,resizable,centerscreen'+ (instantApply ? ',dialog=no' : '')
73   );
74 }
75
76  // Preferences
77 var DTA_preferences = {
78   _pref: Components.classes['@mozilla.org/preferences-service;1']
79     .getService(Components.interfaces.nsIPrefBranch),
80   _conv: {
81     'boolean': 'BoolPref',
82     'string': 'CharPref',
83     'number': 'IntPref',
84     'undefined': 'CharPref'
85   },
86   get: function DP_get(key, def) {
87     if (!this._conv[typeof(def)]) {
88       def = def.toSource();
89     }
90     try {
91       return this._pref['get' + this._conv[typeof(def)]](key);
92     } catch (ex) {
93       //Components.utils.reportError('DTAP: key miss: ' + key + ' / set' + this._conv[typeof(def)]);
94       //this._pref['set' + this._conv[typeof(def)]](key, def);
95       return def;
96     }
97   },
98   getDTA: function DP_getDTA(key, def) {
99     return this.get('extensions.dta.' + key, def);
100   },
101   set: function(key, value) {
102     if (!this._conv[typeof(value)]) {
103       value = value.toSource();
104     }
105     this._pref['set' + this._conv[typeof(value)]](key, value);
106   },
107   setDTA: function DP_setDTA(key, value) {
108     return this.set('extensions.dta.' + key, value);
109   },
110   getMultiByte: function DP_getMultiByte(key, def) {
111     try {
112       var rv = this._pref.getComplexValue(
113         key,
114         Components.interfaces.nsISupportsString
115       );
116       return rv.data;
117     }
118     catch (ex) {
119       return def;
120     }
121   },
122   getMultiByteDTA: function DP_getMultiByteDTA(key, def) {
123     return this.getMultiByte('extensions.dta.' + key, def);
124   },
125   setMultiByte: function DP_setMultiByte(key, value) {
126     var str = Components.classes["@mozilla.org/supports-string;1"]
127       .createInstance(Components.interfaces.nsISupportsString);
128     str.data = value;
129     this._pref.setComplexValue(
130       key,
131       Components.interfaces.nsISupportsString,
132       str
133     );
134   },
135   setMultiByteDTA: function DP_setMultiByteDTA(key, value) {
136     this.setMultiByte('extensions.dta.' + key, value);
137   },
138   reset: function DP_reset(key) {
139     try {
140       return this._pref.clearUserPref(key);
141     } catch (ex) {
142       return false;
143     }
144   },
145   resetDTA: function DP_resetDTA(key) {
146     if (key.search(/^extensions\.dta\./) != 0) {
147       key = 'extensions.dta.' + key;
148     }
149     return this.reset(key);
150   },
151   resetBranch: function DP_resetBranch(key) {
152     // BEWARE: not yet implemented in XPCOM 1.8/trunk.
153     var branch = 'extensions.dta.' + key;
154     var c = {value: 0};
155     var prefs = this._pref.getChildList(branch, c);
156     for (var i = 0; i < c.value; ++i) {
157       this.resetDTA(prefs[i]);
158     }
159   },
160   resetAll: function DP_reset() {
161     this.resetBranch('');
162   },
163   addObserver: function DP_addObserver(branch, obj) {
164     this._pref
165       .QueryInterface(Components.interfaces.nsIPrefBranch2)
166       .addObserver(branch, obj, true);
167   },
168   removeObserver: function DP_removeObserver(branch, obj) {
169     this._pref
170       .QueryInterface(Components.interfaces.nsIPrefBranch2)
171       .removeObserver(branch, obj);
172   }
173 };
174
175 function DTA_getProfileFile(fileName) {
176   var _profile = Components.classes["@mozilla.org/file/directory_service;1"]
177     .getService(Components.interfaces.nsIProperties)
178     .get("ProfD", Components.interfaces.nsIFile);
179   DTA_getProfileFile = function(fileName) {
180     var file = _profile.clone();
181     file.append(fileName);
182     return file;
183   };
184   return DTA_getProfileFile(fileName);
185 }
186
187 var DTA_debug = Components.classes['@downthemall.net/debug-service;1']
188   .getService(Components.interfaces.dtaIDebugService);
189
190 var DTA_URLhelpers = {
191   textToSubURI : Components.classes["@mozilla.org/intl/texttosuburi;1"]
192     .getService(Components.interfaces.nsITextToSubURI),
193
194   decodeCharset: function(text, charset) {
195     var rv = text;
196     try {
197       if (!charset.length) {
198         throw 'no charset';
199       }
200       rv = this.textToSubURI.UnEscapeAndConvert(charset, text);
201     } catch (ex) {
202       try {
203         rv = decodeURIComponent(text);
204       }
205       catch (ex) {
206         DTA_debug.log("DTA_URLhelpers: failed to decode: " + text, ex);
207       }
208     }
209     return rv;
210   }
211 };
212
213 function DTA_URL(url, charset, usable, preference) {
214   this.charset = this.str(charset);
215   this.url = url;
216   if (usable) {
217     this.usable = this.str(usable);
218   }
219   this.preference = preference ? preference : 100;
220
221   this.decode();
222 };
223 DTA_URL.prototype = {
224   str: function(value) {
225     return value ? String(value) : '';
226   },
227   // only a getter here. :p
228   get url() {
229     return this._url;
230   },
231   set url(nv) {
232     delete this.hash;
233     this._url = this.str(nv);
234     var hash = DTA_getLinkPrintHash(this._url);
235     if (hash) {
236       this.hash = hash;
237     }
238     this._url = this._url.replace(/#.*$/, '');
239     this.usable = '';
240     this.decode();
241   },
242   decode: function DU_decode() {
243     if (!this.usable)
244     {
245       this.usable = DTA_URLhelpers.decodeCharset(this._url, this.charset);
246     }
247   },
248   save: function DU_save(element) {
249     element.setAttribute("url", this._url);
250     element.setAttribute("charset", this.charset);
251     element.setAttribute("usableURL", this.usable);
252   }
253 };
254
255 function DTA_DropProcessor(func) {
256   this.func = func;
257 };
258 DTA_DropProcessor.prototype = {
259   getSupportedFlavours: function() {
260     var flavours = new FlavourSet();
261     flavours.appendFlavour("text/x-moz-url");
262     return flavours;
263   },
264   onDragOver: function(evt,flavour,session) {},
265   onDrop: function (evt,dropdata,session) {
266     if (!dropdata) {
267       return;
268     }
269     try {
270       var url = transferUtils.retrieveURLFromData(dropdata.data, dropdata.flavour.contentType);
271     }
272     catch (ex) {
273       return;
274     }
275     var doc = document.commandDispatcher.focusedWindow.document;
276    
277     var ml = DTA_getLinkPrintMetalink(url);
278     url = new DTA_URL(ml ? ml : url, doc.characterSet);
279    
280     var ref = DTA_AddingFunctions.getRef(doc);
281     this.func(url, ref);
282   }
283 };
284
285 var DTA_DropTDTA = new DTA_DropProcessor(function(url, ref) { DTA_AddingFunctions.saveSingleLink(true, url, ref); });
286 var DTA_DropDTA = new DTA_DropProcessor(function(url, ref) { DTA_AddingFunctions.saveSingleLink(false, url, ref); });
287
288 var DTA_AddingFunctions = {
289   ios: Components.classes["@mozilla.org/network/io-service;1"]
290     .getService(Components.interfaces.nsIIOService),
291
292   isLinkOpenable : function(url) {
293     if (url instanceof DTA_URL) {
294       url = url.url;
295     }
296     try {
297       var scheme = this.ios.extractScheme(url);
298       return ['http', 'https', 'ftp'].indexOf(scheme) != -1;
299     }
300     catch (ex) {
301       // no op!
302     }
303     return false;
304   },
305  
306   composeURL: function UM_compose(doc, rel) {
307     // find <base href>
308     var base = doc.location.href;
309     var bases = doc.getElementsByTagName('base');
310     for (var i = 0; i < bases.length; ++i) {
311       if (bases[i].hasAttribute('href')) {
312         base = bases[i].getAttribute('href');
313         break;
314       }
315     }
316     return this.ios.newURI(rel, doc.characterSet, this.ios.newURI(base, doc.characterSet, null)).spec;
317   },
318  
319   getRef: function(doc) {
320     var ref = doc.URL;
321     if (!this.isLinkOpenable(ref)) {
322       var b = doc.getElementsByTagName('base');
323       for (var i = 0; i < b.length; ++i) {
324         if (!b[i].hasAttribute('href')) {
325           continue;
326         }
327         try {
328           ref = this.composeURL(doc, b[i].getAttribute('href'));
329         }
330         catch (ex) {
331           continue;
332         }
333         break;
334       }
335     }
336     return this.isLinkOpenable(ref) ? ref: '';
337   }, 
338
339   saveSingleLink : function(turbo, url, referrer, description) {
340     var item = {
341       'url': url,
342       'referrer': referrer,
343       'description': description
344     };
345
346     if (turbo) {
347       this.turboSendToDown([item]);
348       return;
349     }
350
351     // else open addurl.xul
352     var win = window.openDialog(
353       "chrome://dta/content/dta/addurl.xul",
354       "_blank",
355       "chrome, centerscreen, resizable=yes, dialog=no, all, modal=no, dependent=no",
356       item
357     );
358   },
359
360   getDropDownValue : function(name) {
361     var values = eval(DTA_preferences.getMultiByteDTA(name, '[]'));
362     return values.length ? values[0] : '';
363   },
364
365   turboSendToDown : function(urlsArray) {
366
367     var dir = this.getDropDownValue('directory');
368     var mask = this.getDropDownValue('renaming');
369
370     if (!mask || !dir) {
371       throw new Components.Exception("missing required information");
372     }
373
374     var num = DTA_preferences.getDTA("counter", 0);
375     if (++num > 999) {
376       num = 1;
377     }
378     DTA_preferences.setDTA("counter", num);
379
380     for (var i = 0; i < urlsArray.length; i++) {
381       urlsArray[i].mask = mask;
382       urlsArray[i].dirSave = dir;
383       urlsArray[i].numIstance = num;
384     }
385
386     this.sendToDown(!DTA_preferences.getDTA("lastqueued", false), urlsArray);
387   },
388
389   saveLinkArray : function(turbo, urls, images) {
390
391     if (urls.length == 0 && images.length == 0) {
392       throw new Components.Exception("no links");
393     }
394
395     if (turbo) {
396
397       DTA_debug.logString("saveLinkArray(): DtaOneClick filtering started");
398
399       var links;
400       var type;
401       if (DTA_preferences.getDTA("seltab", 0)) {
402         links = images;
403         type = 2;
404       }
405       else {
406         links = urls;
407         type = 1;
408       }
409
410       var fast = null;
411       try {
412         fast = DTA_FilterManager.getTmpFromString(this.getDropDownValue('filter'));
413       }
414       catch (ex) {
415         // fall-through
416       }
417       links = links.filter(
418         function(link) {
419           if (fast && (fast.match(link.url.usable) || fast.match(link.description))) {
420             return true;
421           }
422           return DTA_FilterManager.matchActive(link.url.usable, type);
423         }
424       );
425
426       DTA_debug.logString("saveLinkArray(): DtaOneClick has filtered " + links.length + " URLs");
427
428       if (links.length == 0) {
429           throw new Components.Exception('no links remaining');
430       }
431       this.turboSendToDown(links);
432       return;
433     }
434
435     window.openDialog(
436       "chrome://dta/content/dta/select.xul",
437       "_blank",
438       "chrome, centerscreen, resizable=yes, dialog=no, all, modal=no, dependent=no",
439       urls,
440       images
441     );
442   },
443
444   openManager : function (quite) {
445     try {
446       var win = DTA_Mediator.getByUrl("chrome://dta/content/dta/manager.xul");
447       if (win) {
448         if (!quite) {
449           win.focus();
450         }
451         return win;
452       }
453       window.openDialog(
454         "chrome://dta/content/dta/manager.xul",
455         "_blank",
456         "chrome, centerscreen, resizable=yes, dialog=no, all, modal=no, dependent=no"
457       );
458       return DTA_Mediator.getByUrl("chrome://dta/content/dta/manager.xul");
459     } catch(ex) {
460       DTA_debug.log("openManager():", ex);
461     }
462     return null;
463   },
464
465   sendToDown : function(start, links) {
466     var win = DTA_Mediator.getByUrl("chrome://dta/content/dta/manager.xul");
467     if (win) {
468       win.self.startDownloads(start, links);
469       return;
470     }
471     win = window.openDialog(
472       "chrome://dta/content/dta/manager.xul",
473       "_blank",
474       "chrome, centerscreen, resizable=yes, dialog=no, all, modal=no, dependent=no",
475       start,
476       links
477     );
478   }
479 }
480 var DTA_Mediator = {
481   _m: Components.classes["@mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator),
482
483   getMostRecent: function(name) {
484     var names = ['navigator:browser', 'mail:messageWindow', 'mail:3pane'];
485     if (name) {
486       names.unshift(name);
487     }
488     var rv = null;
489     names.some(
490       function(name) {
491         rv = this._m.getMostRecentWindow(name);
492         return rv;
493       },
494       this
495     );
496     return rv;
497   },
498   getByUrl: function(url) {
499     if (!url) {
500       return null;
501     }
502     if (url instanceof DTA_URL) {
503       url = url.url;
504     }
505     if (url instanceof Components.interfaces.nsIURI) {
506       url = url.spec;
507     }
508     var enumerator = this._m.getEnumerator(null);
509     while (enumerator.hasMoreElements()) {
510       var win = enumerator.getNext();
511       if (win.location == url) {
512         return win;
513       }
514     }
515     return null;
516   },
517   getAllByType: function(type) {
518     var rv = [];
519     var enumerator = this._m.getEnumerator(type);
520     while (enumerator.hasMoreElements()) {
521       rv.push(enumerator.getNext());
522     }
523     return rv;
524   },
525   openTab: function WM_openTab(url, ref) {
526     if (!url) {
527       return;
528     }
529     var win = this.getMostRecent();
530     if (!win) {
531       window.open();
532       win = this.getMostRecent();
533     }
534     if (url instanceof DTA_URL) {
535       url = url.url;
536     }
537     if (ref instanceof DTA_URL) {
538       ref = ref.url;
539     }
540     if (ref && !(ref instanceof Components.interfaces.nsIURI)) {
541       try {
542         ref = DTA_AddingFunctions.ios.newURI(ref, null, null);
543       } catch (ex) {
544         DTA_debug.log(ref, ex);
545         ref = null;
546       }
547     }
548     if ('delayedOpenTab' in win) {
549       win.delayedOpenTab(url, ref);
550     }
551     else {
552       win.getBrowser().addTab(url, ref);
553     }
554   },
555   removeTab: function WM_removeTab(url) {
556     function chk(browser, url) {
557       if (browser.currentURI.spec == url) {
558         return true;
559       }
560       var frames = browser.contentWindow.frames;
561       if (frames && frames.length) {
562         for (var i = 0; i < frames.length; i++) {
563           if (frames[i].location && frames[i].location == url) {
564             return true;
565           }
566         }
567       }
568       return false;
569     };   
570    
571     var enumerator = this._m.getEnumerator("navigator:browser");
572     while (enumerator.hasMoreElements()) {
573       var win = enumerator.getNext();
574       var browser = win.getBrowser();
575       for (var i = browser.browsers.length - 1; i >= 0; --i) {
576         if (chk(browser.getBrowserAtIndex(i), url)) {
577           browser.removeTab(browser.mTabContainer.childNodes[i]);
578           return;
579         }
580       }
581     }
582   }
583 };
584
585 /**
586  * Checks if a provided strip has the correct hash format
587  * Supported are: md5, sha1, sha256, sha384, sha512
588  * @param hash Hash to check
589  * @return hash type or null
590  */
591 const DTA_SUPPORTED_HASHES = {
592   'MD5': 32,
593   'SHA1': 40,
594   'SHA256': 64,
595   'SHA384': 96,
596   'SHA512':  128
597 };
598 function DTA_Hash(hash, type) {
599   if (typeof(hash) != 'string' && !(hash instanceof String)) {
600     throw new Components.Exception("hash is invalid");
601   }
602   if (typeof(type) != 'string' && (!type instanceof String)) {
603     throw new Components.Exception("hashtype is invalid");
604   }
605  
606   type = type.toUpperCase().replace(/[\s-]/g, '');
607   if (!(type in DTA_SUPPORTED_HASHES)) {
608     throw new Components.Exception("hashtype is invalid");
609   }
610   this.type = type;
611   this.sum = hash.toLowerCase().replace(/\s/g, '');
612   if (DTA_SUPPORTED_HASHES[this.type] != this.sum.length || isNaN(parseInt(this.sum, 16))) {
613     throw new Components.Exception("hash is invalid");
614   }
615 }
616 DTA_Hash.prototype = {
617   toString: function() {
618     return this.type + " [" + this.sum + "]";
619   }
620 };
621
622 /**
623  * Get a link-fingerprint hash from an url (or just the hash component)
624  * @param url. Either String or nsIURI
625  * @return Valid hash string or null
626  */
627 function DTA_getLinkPrintHash(url) {
628   if (url instanceof Components.interfaces.nsIURI) {
629     url = url.spec;
630   }
631   else if (typeof(url) != 'string' && !(url instanceof String)) {
632     return null;
633   }
634  
635   var lp = url.match(/#hash\((md5|sha(?:1|256|384|512)):([\da-f]+)\)$/i);
636   if (lp) {
637     try {
638       return new DTA_Hash(lp[2], lp[1]);
639     }
640     catch (ex) {
641       // pass down
642     }
643   }
644   return null;
645 }
646
647 /**
648  * Get a link-fingerprint metalink from an url (or just the hash component
649  * @param url. Either String or nsIURI
650  * @param charset. Optional. Charset of the orgin link and link to be created
651  * @return Valid hash string or null
652  */
653 function DTA_getLinkPrintMetalink(url, charset) {
654   if (url instanceof Components.interfaces.nsIURL) {
655     url = url.ref;
656   }
657   else if (url instanceof Components.interfaces.nsIURI) {
658     url = url.spec;
659   }
660   else if (typeof(url) != 'string' && !(url instanceof String)) {
661     return null;
662   }
663  
664   var lp = url.match(/#!metalink3!((?:https?|ftp):.+)$/);
665   if (lp) {
666     var rv = lp[1];
667     try {
668       return DTA_AddingFunctions.ios.newURI(rv, charset, null).spec;
669     }
670     catch (ex) {
671       // not a valid link, ignore it.
672     }
673   }
674   return null;
675 }
676
677 /**
678  * wrapper around confirmEx
679  * @param title. Dialog title
680  * @param text. Dialog text
681  * @param button0. Either null (omit), one of DTA_confirm.X or a string
682  * @param button1. s.a.
683  * @param button2. s.a.
684  * @param default. Index of the Default button
685  * @param check. either null, a boolean, or string specifying the prefs id.
686  * @param checkText. The text for the checkbox
687  * @return Either the button# or {button: #, checked: bool} if check was a boolean
688  * @author Nils
689  */
690 function DTA_confirm(aTitle, aText, aButton0, aButton1, aButton2, aDefault, aCheck, aCheckText) {
691   var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
692     .getService(Components.interfaces.nsIPromptService);
693   var flags = 0;
694   [aButton0, aButton1, aButton2].forEach(
695     function(button, idx) {
696       if (typeof(button) == "number") {
697         flags += prompts['BUTTON_POS_' + idx] * button;
698         button = null;
699       }
700       else if (typeof(button) == "string" || button instanceof String) {
701         flags |= prompts['BUTTON_POS_' + idx] * prompts.BUTTON_TITLE_IS_STRING;
702       }
703       else {
704         button = 0;
705       }
706     },
707     this
708   );
709   if (aDefault == 1) {
710     flags += prompts.BUTTON_POS_1_DEFAULT;
711   }
712   else if (aDefault == 2) {
713     flags += prompts.BUTTON_POS_2_DEFAULT;
714   }
715   var check = {};
716   if (aCheckText) {
717     if (typeof(aCheck) == 'boolean') {
718       var rv = {};
719       check.value = aCheck;
720     }
721     else if (typeof(aCheck) == 'string' || aCheck instanceof String) {
722       check.value = DTA_preferences.getDTA(aCheck, false);
723     }
724   }
725   var cr = prompts.confirmEx(
726     window,
727     aTitle,
728     aText,
729     flags,
730     aButton0,
731     aButton1,
732     aButton2,
733     aCheckText,
734     check
735   );
736   if (rv) {
737     rv.checked = check.value;
738     rv.button = cr;
739     return rv;
740   }
741   return cr;
742 }
743 DTA_confirm.init = function() {
744   for (x in Components.interfaces.nsIPromptService) {
745     var r = new String(x).match(/BUTTON_TITLE_(\w+)$/);
746     if (r) {
747       DTA_confirm[r[1]] = Components.interfaces.nsIPromptService[x];
748     }
749   }
750 }
751 DTA_confirm.init();
752 function DTA_confirmOC(title, text) {
753   return DTA_confirm(title, text, DTA_confirm.OK, DTA_confirm.CANCEL);
754 }
755 function DTA_confirmYN(title, text) {
756   return DTA_confirm(title, text, DTA_confirm.YES, DTA_confirm.NO);
757 }
758 function DTA_alert(aTitle, aText) {
759   Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
760     .getService(Components.interfaces.nsIPromptService)
761     .alert(window, aTitle, aText);
762 }
763
764 /**
765  * Tiny helper to "convert" given object into a weak observer. Object must still implement .observe()
766  * @author Nils
767  * @param obj Object to convert
768  */
769 function DTA_makeObserver(obj) {
770   // nsiSupports
771   obj.__QueryInterface = obj.QueryInterface;
772   obj.QueryInterface = function(iid) {
773     if (
774       iid.equals(Components.interfaces.nsISupports)
775       || iid.equals(Components.interfaces.nsISupportsWeakReference)
776       || iid.equals(Components.interfaces.nsIWeakReference)
777       || iid.equals(Components.interfaces.nsiObserver)
778     ) {
779       return this;
780     }
781     if (this.__QueryInterface) {
782       return this.__QueryInterface(iid);
783     }
784     throw Components.results.NS_ERROR_NO_INTERFACE;
785   };
786   // nsiWeakReference
787   obj.QueryReferent = function(iid) {
788     return this;
789   };
790   // nsiSupportsWeakReference
791   obj.GetWeakReference = function() {
792     return this;
793   }; 
794 }
Note: See TracBrowser for help on using the browser.