home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / lib / firefox / components / FeedWriter.js < prev    next >
Encoding:
Text File  |  2006-08-18  |  19.4 KB  |  589 lines

  1. //@line 37 "/build/buildd/firefox-1.99+2.0b1+dfsg/browser/components/feeds/src/FeedWriter.js"
  2.  
  3. const Cc = Components.classes;
  4. const Ci = Components.interfaces;
  5. const Cr = Components.results;
  6.  
  7. function LOG(str) {
  8.   dump("*** " + str + "\n");
  9. }
  10.  
  11. const HTML_NS = "http://www.w3.org/1999/xhtml";
  12. const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
  13. const URI_BUNDLE = "chrome://browser/locale/feeds/subscribe.properties";
  14.  
  15. const PREF_SELECTED_APP = "browser.feeds.handlers.application";
  16. const PREF_SELECTED_WEB = "browser.feeds.handlers.webservice";
  17. const PREF_SELECTED_HANDLER = "browser.feeds.handler";
  18. const PREF_SKIP_PREVIEW_PAGE = "browser.feeds.skip_preview_page";
  19.  
  20. const FW_CLASSID = Components.ID("{49bb6593-3aff-4eb3-a068-2712c28bd58e}");
  21. const FW_CLASSNAME = "Feed Writer";
  22. const FW_CONTRACTID = "@mozilla.org/browser/feeds/result-writer;1";
  23.  
  24. function FeedWriter() {
  25. }
  26. FeedWriter.prototype = {
  27.   _getPropertyAsBag: function FW__getPropertyAsBag(container, property) {
  28.     return container.fields.getProperty(property).
  29.                      QueryInterface(Ci.nsIPropertyBag2);
  30.   },
  31.   
  32.   _getPropertyAsString: function FW__getPropertyAsString(container, property) {
  33.     try {
  34.       return container.fields.getPropertyAsAString(property);
  35.     }
  36.     catch (e) {
  37.     }
  38.     return "";
  39.   },
  40.   
  41.   _setContentText: function FW__setContentText(id, text) {
  42.     var element = this._document.getElementById(id);
  43.     while (element.hasChildNodes())
  44.       element.removeChild(element.firstChild);
  45.     element.appendChild(this._document.createTextNode(text));
  46.   },
  47.   
  48.   /**
  49.    * Safely sets the href attribute on an anchor tag, providing the URI 
  50.    * specified can be loaded according to rules. 
  51.    * @param   element
  52.    *          The element to set a URI attribute on
  53.    * @param   attribute
  54.    *          The attribute of the element to set the URI to, e.g. href or src
  55.    * @param   uri
  56.    *          The URI spec to set as the href
  57.    */
  58.   _safeSetURIAttribute: 
  59.   function FW__safeSetURIAttribute(element, attribute, uri) {
  60.     var secman = 
  61.         Cc["@mozilla.org/scriptsecuritymanager;1"].
  62.         getService(Ci.nsIScriptSecurityManager);    
  63.     const flags = Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT_OR_DATA;
  64.     try {
  65.       secman.checkLoadURIStr(this._window.location.href, uri, flags);
  66.       // checkLoadURIStr will throw if the link URI should not be loaded per 
  67.       // the rules specified in |flags|, so we'll never "linkify" the link...
  68.       element.setAttribute(attribute, uri);
  69.     }
  70.     catch (e) {
  71.       // Not allowed to load this link because secman.checkLoadURIStr threw
  72.     }
  73.   },
  74.   
  75.   get _bundle() {
  76.     var sbs = 
  77.         Cc["@mozilla.org/intl/stringbundle;1"].
  78.         getService(Ci.nsIStringBundleService);
  79.     return sbs.createBundle(URI_BUNDLE);
  80.   },
  81.   
  82.   _getFormattedString: function FW__getFormattedString(key, params) {
  83.     return this._bundle.formatStringFromName(key, params, params.length);
  84.   },
  85.   
  86.   _getString: function FW__getString(key) {
  87.     return this._bundle.GetStringFromName(key);
  88.   },
  89.   
  90.   /**
  91.    * Writes the feed title into the preview document.
  92.    * @param   container
  93.    *          The feed container
  94.    */
  95.   _setTitleText: function FW__setTitleText(container) {
  96.     this._setContentText("feedTitleText", container.title);
  97.     this._setContentText("feedSubtitleText", 
  98.                          this._getPropertyAsString(container, "description"));
  99.     this._document.title = container.title;
  100.   },
  101.   
  102.   /**
  103.    * Writes the title image into the preview document if one is present.
  104.    * @param   container
  105.    *          The feed container
  106.    */
  107.   _setTitleImage: function FW__setTitleImage(container) {
  108.     try {
  109.       var parts = this._getPropertyAsBag(container, "image");
  110.       
  111.       // Set up the title image (supplied by the feed)
  112.       var feedTitleImage = this._document.getElementById("feedTitleImage");
  113.       this._safeSetURIAttribute(feedTitleImage, "src", 
  114.                                 parts.getPropertyAsAString("url"));
  115.       
  116.       // Set up the title image link
  117.       var feedTitleLink = this._document.getElementById("feedTitleLink");
  118.       
  119.       var titleText = 
  120.         this._getFormattedString("linkTitleTextFormat", 
  121.                                  [parts.getPropertyAsAString("title")]);
  122.       feedTitleLink.setAttribute("title", titleText);
  123.       this._safeSetURIAttribute(feedTitleLink, "href", 
  124.                                 parts.getPropertyAsAString("link"));
  125.  
  126.       // Fix the margin on the main title, so that the image doesn't run over
  127.       // the underline
  128.       var feedTitleText = this._document.getElementById("feedTitleText");
  129.       var titleImageWidth = parseInt(parts.getPropertyAsAString("width")) + 15;
  130.       feedTitleText.style.marginRight = titleImageWidth + "px";
  131.     }
  132.     catch (e) {
  133.       LOG("Failed to set Title Image (this is benign): " + e);
  134.     }
  135.   },
  136.   
  137.   /**
  138.    * Writes all entries contained in the feed.
  139.    * @param   container
  140.    *          The container of entries in the feed
  141.    */
  142.   _writeFeedContent: function FW__writeFeedContent(container) {
  143.     // XXXben - do something with this. parameterize?
  144.     const MAX_CHARS = 600;
  145.     
  146.     // Build the actual feed content
  147.     var feedContent = this._document.getElementById("feedContent");
  148.     var feed = container.QueryInterface(Ci.nsIFeed);
  149.     
  150.     for (var i = 0; i < feed.items.length; ++i) {
  151.       var entry = feed.items.queryElementAt(i, Ci.nsIFeedEntry);
  152.       entry.QueryInterface(Ci.nsIFeedContainer);
  153.       
  154.       var entryContainer = this._document.createElementNS(HTML_NS, "div");
  155.       entryContainer.className = "entry";
  156.       
  157.       var a = this._document.createElementNS(HTML_NS, "a");
  158.       a.appendChild(this._document.createTextNode(entry.title));
  159.       
  160.       // Entries are not required to have links, so entry.link can be null.
  161.       if (entry.link)
  162.         this._safeSetURIAttribute(a, "href", entry.link.spec);
  163.  
  164.       var title = this._document.createElementNS(HTML_NS, "h3");
  165.       title.appendChild(a);
  166.       entryContainer.appendChild(title);
  167.       
  168.       var body = this._document.createElementNS(HTML_NS, "p");
  169.       var summary = entry.summary(true)
  170.       if (summary && summary.length > MAX_CHARS)
  171.         summary = summary.substring(0, MAX_CHARS) + "...";
  172.       
  173.       // XXXben - Change to use innerHTML
  174.       body.appendChild(this._document.createTextNode(summary));
  175.       body.className = "feedEntryContent";
  176.       entryContainer.appendChild(body);
  177.       
  178.       feedContent.appendChild(entryContainer);
  179.     }
  180.   },
  181.   
  182.   /**
  183.    * Gets a valid nsIFeedContainer object from the parsed nsIFeedResult.
  184.    * Displays error information if there was one.
  185.    * @param   result
  186.    *          The parsed feed result
  187.    * @returns A valid nsIFeedContainer object containing the contents of
  188.    *          the feed.
  189.    */
  190.   _getContainer: function FW__getContainer(result) {
  191.     var feedService = 
  192.         Cc["@mozilla.org/browser/feeds/result-service;1"].
  193.         getService(Ci.nsIFeedResultService);
  194.         
  195.     var ios = 
  196.         Cc["@mozilla.org/network/io-service;1"].
  197.         getService(Ci.nsIIOService);
  198.     var feedURI = ios.newURI(this._window.location.href, null, null);
  199.     try {
  200.       var result = feedService.getFeedResult(feedURI);
  201.     }
  202.     catch (e) {
  203.       LOG("Subscribe Preview: feed not available?!");
  204.     }
  205.     
  206.     if (result.bozo) {
  207.       LOG("Subscribe Preview: feed result is bozo?!");
  208.     }
  209.  
  210.     try {
  211.       var container = result.doc;
  212.       container.title;
  213.     }
  214.     catch (e) {
  215.       LOG("Subscribe Preview: An error occurred in parsing! Fortunately, you can still subscribe...");
  216.       var feedError = this._document.getElementById("feedError");
  217.       feedError.removeAttribute("style");
  218.       var feedBody = this._document.getElementById("feedBody");
  219.       feedBody.setAttribute("style", "display:none;");
  220.       this._setContentText("errorCode", e);
  221.       return null;
  222.     }
  223.     return container;
  224.   },
  225.   
  226.   /**
  227.    * Get the human-readable display name of a file. This could be the 
  228.    * application name.
  229.    * @param   file
  230.    *          A nsIFile to look up the name of
  231.    * @returns The display name of the application represented by the file.
  232.    */
  233.   _getFileDisplayName: function FW__getFileDisplayName(file) {
  234. //@line 287 "/build/buildd/firefox-1.99+2.0b1+dfsg/browser/components/feeds/src/FeedWriter.js"
  235.     var ios = 
  236.         Cc["@mozilla.org/network/io-service;1"].
  237.         getService(Ci.nsIIOService);
  238.     var url = ios.newFileURI(file).QueryInterface(Ci.nsIURL);
  239.     return url.fileName;
  240.   },
  241.   
  242.   _initSelectedHandler: function FW__initSelectedHandler() {
  243.     var prefs =   
  244.         Cc["@mozilla.org/preferences-service;1"].
  245.         getService(Ci.nsIPrefBranch);
  246.     var chosen = 
  247.         this._document.getElementById("feedSubscribeLineHandlerChosen");
  248.     var unchosen = 
  249.         this._document.getElementById("feedSubscribeLineHandlerUnchosen");
  250.     var ios = 
  251.         Cc["@mozilla.org/network/io-service;1"].
  252.         getService(Ci.nsIIOService);
  253.     try {
  254.       var iconURI = "chrome://browser/skin/places/livemarkItem.png";
  255.       var handler = prefs.getCharPref(PREF_SELECTED_HANDLER);
  256.       switch (handler) {
  257.       case "client":
  258.         var selectedApp = 
  259.             prefs.getComplexValue(PREF_SELECTED_APP, Ci.nsILocalFile);      
  260.         var displayName = this._getFileDisplayName(selectedApp);
  261.         this._setContentText("feedSubscribeHandleText", displayName);
  262.         
  263.         var url = ios.newFileURI(selectedApp).QueryInterface(Ci.nsIURL);
  264.         iconURI = "moz-icon://" + url.spec;
  265.         break;
  266.       case "web":
  267.         var webURI = prefs.getCharPref(PREF_SELECTED_WEB);
  268.         var wccr = 
  269.             Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
  270.             getService(Ci.nsIWebContentConverterService);
  271.         var title ="Unknown";
  272.         var handler = 
  273.             wccr.getWebContentHandlerByURI(TYPE_MAYBE_FEED, webURI);
  274.         if (handler)
  275.           title = handler.name;
  276.         var uri = ios.newURI(webURI, null, null);
  277.         iconURI = uri.prePath + "/favicon.ico";
  278.         
  279.         this._setContentText("feedSubscribeHandleText", title);
  280.         break;
  281.       case "bookmarks":
  282.         this._setContentText("feedSubscribeHandleText", 
  283.                              this._getString("liveBookmarks"));
  284.         break;
  285.       }
  286.       unchosen.setAttribute("hidden", "true");
  287.       chosen.removeAttribute("hidden");
  288.       var button = this._document.getElementById("feedSubscribeLink");
  289.       button.focus();
  290.       
  291.       
  292.       var displayArea = 
  293.           this._document.getElementById("feedSubscribeHandleText");
  294.       displayArea.style.setProperty("background-image", 
  295.                                     "url(\"" + iconURI + "\")", "");
  296.     }
  297.     catch (e) {
  298.       LOG("Failed to set Handler: " + e);
  299.       // No selected handlers yet! Make the user choose...
  300.       chosen.setAttribute("hidden", "true");
  301.       unchosen.removeAttribute("hidden");
  302.       this._document.getElementById("feedHeader").setAttribute("firstrun", "true");
  303.       
  304.       var button = this._document.getElementById("feedChooseInitialReader");
  305.       button.focus();
  306.     }
  307.   },
  308.   
  309.   /**
  310.    * Ensures that this component is only ever invoked from the preview 
  311.    * document.
  312.    * @param   window
  313.    *          The window of the document invoking the BrowserFeedWriter
  314.    */
  315.   _isValidWindow: function FW__isValidWindow(window) {
  316.     var chan = 
  317.         window.QueryInterface(Ci.nsIInterfaceRequestor).
  318.         getInterface(Ci.nsIWebNavigation).
  319.         QueryInterface(Ci.nsIDocShell_MOZILLA_1_8_BRANCH).
  320.         currentDocumentChannel;
  321.     const kPrefix = "jar:file:";
  322.     return chan.URI.spec.substring(0, kPrefix.length) == kPrefix;
  323.   },
  324.   
  325.   _window: null,
  326.   _document: null,
  327.   
  328.   /**
  329.    * See nsIFeedWriter
  330.    */
  331.   write: function FW_write(window) {
  332.     if (!this._isValidWindow(window))
  333.       return;
  334.     
  335.     this._window = window;
  336.     this._document = window.document;
  337.       
  338.     LOG("Subscribe Preview: feed uri = " + this._window.location.href);
  339.  
  340.     // Set up the displayed handler
  341.     this._initSelectedHandler();
  342.     var prefs =   
  343.         Cc["@mozilla.org/preferences-service;1"].
  344.         getService(Ci.nsIPrefBranch2);
  345.     prefs.addObserver(PREF_SELECTED_HANDLER, this, false);
  346.     prefs.addObserver(PREF_SELECTED_APP, this, false);
  347.     
  348.     // Set up the feed content
  349.     var container = this._getContainer();
  350.     if (!container)
  351.       return;
  352.     
  353.     this._setTitleText(container);
  354.     
  355.     this._setTitleImage(container);
  356.     
  357.     this._writeFeedContent(container);
  358.   },
  359.   
  360.   /**
  361.    * See nsIFeedWriter
  362.    */
  363.   changeOptions: function FW_changeOptions() {
  364.     var paramBlock = 
  365.         Cc["@mozilla.org/embedcomp/dialogparam;1"].
  366.         createInstance(Ci.nsIDialogParamBlock);
  367.     // Used to tell the preview page that the user chose to subscribe with
  368.     // a particular reader, and so it should subscribe now.
  369.     const PARAM_USER_SUBSCRIBED = 0;
  370.     paramBlock.SetInt(PARAM_USER_SUBSCRIBED, 0);
  371.     this._window.openDialog("chrome://browser/content/feeds/options.xul", "", 
  372.                             "modal,centerscreen", "subscribe", paramBlock);
  373.     if (paramBlock.GetInt(PARAM_USER_SUBSCRIBED) == 1)
  374.       this.subscribe();
  375.   },
  376.   
  377.   /**
  378.    * See nsIFeedWriter
  379.    */
  380.   close: function FW_close() {
  381.     var prefs =   
  382.         Cc["@mozilla.org/preferences-service;1"].
  383.         getService(Ci.nsIPrefBranch2);
  384.     prefs.removeObserver(PREF_SELECTED_HANDLER, this);
  385.     prefs.removeObserver(PREF_SELECTED_APP, this);
  386.   },
  387.     
  388.   /**
  389.    * See nsIFeedWriter
  390.    */
  391.   subscribe: function FW_subscribe() {
  392.     var prefs =   
  393.         Cc["@mozilla.org/preferences-service;1"].
  394.         getService(Ci.nsIPrefBranch);
  395.     try {
  396.       var handler = prefs.getCharPref(PREF_SELECTED_HANDLER);
  397.     }
  398.     catch (e) {
  399.       // Something is bogus in our state. Prompt the user to fix it.
  400.       this.changeOptions();
  401.       return; 
  402.     }
  403.     if (handler == "web") {
  404.       var webURI = prefs.getCharPref(PREF_SELECTED_WEB);
  405.       var wccr = 
  406.           Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
  407.           getService(Ci.nsIWebContentConverterService);
  408.       var handler = 
  409.           wccr.getWebContentHandlerByURI(TYPE_MAYBE_FEED, webURI);
  410.       this._window.location.href = 
  411.         handler.getHandlerURI(this._window.location.href);
  412.     }
  413.     else {
  414.       var feedService = 
  415.           Cc["@mozilla.org/browser/feeds/result-service;1"].
  416.           getService(Ci.nsIFeedResultService);
  417.       feedService.addToClientReader(this._window.location.href);
  418.     }
  419.   },
  420.   
  421.   /**
  422.    * See nsIObserver
  423.    */
  424.   observe: function FW_observe(subject, topic, data) {
  425.     if (topic == "nsPref:changed")
  426.       this._initSelectedHandler();
  427.   },  
  428.   
  429.   /**
  430.    * See nsIClassInfo
  431.    */
  432.   getInterfaces: function WCCR_getInterfaces(countRef) {
  433.     var interfaces = 
  434.         [Ci.nsIFeedWriter, Ci.nsIClassInfo, Ci.nsISupports];
  435.     countRef.value = interfaces.length;
  436.     return interfaces;
  437.   },
  438.   getHelperForLanguage: function WCCR_getHelperForLanguage(language) {
  439.     return null;
  440.   },
  441.   contractID: FW_CONTRACTID,
  442.   classDescription: FW_CLASSNAME,
  443.   classID: FW_CLASSID,
  444.   implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT,
  445.   flags: Ci.nsIClassInfo.DOM_OBJECT,
  446.  
  447.   QueryInterface: function FW_QueryInterface(iid) {
  448.     if (iid.equals(Ci.nsIFeedWriter) ||
  449.         iid.equals(Ci.nsIClassInfo) ||
  450.         iid.equals(Ci.nsISupports))
  451.       return this;
  452.     throw Cr.NS_ERROR_NO_INTERFACE;
  453.   }
  454. };
  455.  
  456. var Module = {
  457.   QueryInterface: function M_QueryInterface(iid) {
  458.     if (iid.equals(Ci.nsIModule) ||
  459.         iid.equals(Ci.nsISupports))
  460.       return this;
  461.     throw Cr.NS_ERROR_NO_INTERFACE;
  462.   },
  463.   
  464.   getClassObject: function M_getClassObject(cm, cid, iid) {
  465.     if (!iid.equals(Ci.nsIFactory))
  466.       throw Cr.NS_ERROR_NOT_IMPLEMENTED;
  467.     
  468.     if (cid.equals(FW_CLASSID))
  469.       return new GenericComponentFactory(FeedWriter);
  470.       
  471.     throw Cr.NS_ERROR_NO_INTERFACE;
  472.   },
  473.   
  474.   registerSelf: function M_registerSelf(cm, file, location, type) {
  475.     var cr = cm.QueryInterface(Ci.nsIComponentRegistrar);
  476.     
  477.     cr.registerFactoryLocation(FW_CLASSID, FW_CLASSNAME, FW_CONTRACTID,
  478.                                file, location, type);
  479.     
  480.     var catman = 
  481.         Cc["@mozilla.org/categorymanager;1"].
  482.         getService(Ci.nsICategoryManager);
  483.     catman.addCategoryEntry("JavaScript global constructor",
  484.                             "BrowserFeedWriter", FW_CONTRACTID, true, true);
  485.   },
  486.   
  487.   unregisterSelf: function M_unregisterSelf(cm, location, type) {
  488.     var cr = cm.QueryInterface(Ci.nsIComponentRegistrar);
  489.     cr.unregisterFactoryLocation(FW_CLASSID, location);
  490.   },
  491.   
  492.   canUnload: function M_canUnload(cm) {
  493.     return true;
  494.   }
  495. };
  496.  
  497. function NSGetModule(cm, file) {
  498.   return Module;
  499. }
  500.  
  501. //@line 44 "/build/buildd/firefox-1.99+2.0b1+dfsg/browser/components/feeds/src/../../../../toolkit/content/debug.js"
  502.  
  503. const NS_ASSERT_ENVIRONMENT_VARIABLE_NAME = "XUL_ASSERT_PROMPT";
  504. var gTraceOnAssert = true;
  505.  
  506. /**
  507.  * This function provides a simple assertion function for JavaScript.
  508.  * If the condition is true, this function will do nothing.  If the
  509.  * condition is false, then the message will be printed to the console
  510.  * and an alert will appear showing a stack trace, so that the (alpha
  511.  * or nightly) user can file a bug containing it.  For future enhancements, 
  512.  * see bugs 330077 and 330078.
  513.  *
  514.  * To suppress the dialogs, you can run with the environment variable
  515.  * XUL_ASSERT_PROMPT set to 0 (if unset, this defaults to 1).
  516.  *
  517.  * @param condition represents the condition that we're asserting to be
  518.  *                  true when we call this function--should be
  519.  *                  something that can be evaluated as a boolean.
  520.  * @param message   a string to be displayed upon failure of the assertion
  521.  */
  522.  
  523. function NS_ASSERT(condition, message) {
  524.   if (condition)
  525.     return;
  526.  
  527.   var caller = arguments.callee.caller;
  528.   var assertionText = "ASSERT: " + message + "\n";
  529.   dump(assertionText);
  530.  
  531.   var stackText = "";
  532.   if (gTraceOnAssert) {
  533.     stackText = "Stack Trace: \n";
  534.     var count = 0;
  535.     while (caller) {
  536.       stackText += count++ + ":" + caller.name + "(";
  537.       for (var i = 0; i < caller.arguments.length; ++i) {
  538.         var arg = caller.arguments[i];
  539.         stackText += arg;
  540.         if (i < caller.arguments.length - 1)
  541.           stackText += ",";
  542.       }
  543.       stackText += ")\n";
  544.       caller = caller.arguments.callee.caller;
  545.     }
  546.   }
  547.  
  548.   var environment = Components.classes["@mozilla.org/process/environment;1"].
  549.                     getService(Components.interfaces.nsIEnvironment);
  550.   if (environment.exists(NS_ASSERT_ENVIRONMENT_VARIABLE_NAME) &&
  551.       !parseInt(environment.get(NS_ASSERT_ENVIRONMENT_VARIABLE_NAME)))
  552.     return;
  553.  
  554.   var source = null;
  555.   if (this.window)
  556.     source = window;
  557.   var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
  558.            getService(Components.interfaces.nsIPromptService);
  559.   ps.alert(source, "Assertion Failed", assertionText + stackText);
  560. }
  561. //@line 37 "/build/buildd/firefox-1.99+2.0b1+dfsg/browser/components/feeds/src/GenericFactory.js"
  562.  
  563. /**
  564.  * An object implementing nsIFactory that can construct other objects upon
  565.  * createInstance, passing a set of parameters to that object's constructor.
  566.  */
  567. function GenericComponentFactory(ctor, params) {
  568.   this._ctor = ctor;
  569.   this._params = params;
  570. }
  571. GenericComponentFactory.prototype = {
  572.   _ctor: null,
  573.   _params: null,
  574.   
  575.   createInstance: function GCF_createInstance(outer, iid) {
  576.     if (outer != null)
  577.       throw Cr.NS_ERROR_NO_AGGREGATION;
  578.     return (new this._ctor(this._params)).QueryInterface(iid);
  579.   },
  580.   
  581.   QueryInterface: function GCF_QueryInterface(iid) {
  582.     if (iid.equals(Ci.nsIFactory) ||
  583.         iid.equals(Ci.nsISupports)) 
  584.       return this;
  585.     throw Cr.NS_ERROR_NO_INTERFACE;
  586.   }
  587. };
  588.  
  589.