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

  1. //@line 37 "/build/buildd/firefox-1.99+2.0b1+dfsg/browser/components/feeds/src/FeedConverter.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 FC_CLASSID = Components.ID("{229fa115-9412-4d32-baf3-2fc407f76fb1}");
  12. const FC_CLASSNAME = "Feed Stream Converter";
  13. const FS_CLASSID = Components.ID("{2376201c-bbc6-472f-9b62-7548040a61c6}");
  14. const FS_CLASSNAME = "Feed Result Service";
  15. const FS_CONTRACTID = "@mozilla.org/browser/feeds/result-service;1";
  16. const FPH_CONTRACTID = "@mozilla.org/network/protocol;1?name=feed";
  17. const FPH_CLASSID = Components.ID("{4f91ef2e-57ba-472e-ab7a-b4999e42d6c0}");
  18. const FPH_CLASSNAME = "Feed Protocol Handler";
  19. const PCPH_CONTRACTID = "@mozilla.org/network/protocol;1?name=pcast";
  20. const PCPH_CLASSID = Components.ID("{1c31ed79-accd-4b94-b517-06e0c81999d5}");
  21. const PCPH_CLASSNAME = "Podcast Protocol Handler";
  22. const FHS_CONTRACTID = "@mozilla.org/browser/feeds/handler-service;1";
  23. const FHS_CLASSID = Components.ID("{792a7e82-06a0-437c-af63-b2d12e808acc}");
  24. const FHS_CLASSNAME = "Feed Handler Service";
  25.  
  26. const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
  27. const TYPE_ANY = "*/*";
  28.  
  29. const FEEDHANDLER_URI = "about:feeds";
  30.  
  31. const PREF_SELECTED_APP = "browser.feeds.handlers.application";
  32. const PREF_SELECTED_WEB = "browser.feeds.handlers.webservice";
  33. const PREF_SELECTED_HANDLER = "browser.feeds.handler";
  34. const PREF_SKIP_PREVIEW_PAGE = "browser.feeds.skip_preview_page";
  35.  
  36. function safeGetBoolPref(pref, defaultValue) {
  37.   var prefs =   
  38.       Cc["@mozilla.org/preferences-service;1"].
  39.       getService(Ci.nsIPrefBranch);
  40.   try {
  41.     return prefs.getBoolPref(pref);
  42.   }
  43.   catch (e) {
  44.   }
  45.   return defaultValue;
  46. }
  47.  
  48. function safeGetCharPref(pref, defaultValue) {
  49.   var prefs =   
  50.       Cc["@mozilla.org/preferences-service;1"].
  51.       getService(Ci.nsIPrefBranch);
  52.   try {
  53.     return prefs.getCharPref(pref);
  54.   }
  55.   catch (e) {
  56.   }
  57.   return defaultValue;
  58. }
  59.  
  60. function FeedConverter() {
  61. }
  62. FeedConverter.prototype = {
  63.   /**
  64.    * This is the downloaded text data for the feed.
  65.    */
  66.   _data: null,
  67.   
  68.   /**
  69.    * This is the object listening to the conversion, which is ultimately the
  70.    * docshell for the load.
  71.    */
  72.   _listener: null,
  73.   
  74.   /**
  75.    * See nsIStreamConverter.idl
  76.    */
  77.   canConvert: function FC_canConvert(sourceType, destinationType) {
  78.     // We only support one conversion.
  79.     return destinationType == TYPE_ANY && sourceType == TYPE_MAYBE_FEED;
  80.   },
  81.   
  82.   /**
  83.    * See nsIStreamConverter.idl
  84.    */
  85.   convert: function FC_convert(sourceStream, sourceType, destinationType, 
  86.                                context) {
  87.     throw Cr.NS_ERROR_NOT_IMPLEMENTED;
  88.   },
  89.   
  90.   /**
  91.    * See nsIStreamConverter.idl
  92.    */
  93.   asyncConvertData: function FC_asyncConvertData(sourceType, destinationType,
  94.                                                  listener, context) {
  95.     this._listener = listener;
  96.   },
  97.   
  98.   /**
  99.    * Whether or not the preview page is being forced.
  100.    */
  101.   _forcePreviewPage: false,
  102.   
  103.   /**
  104.    * See nsIFeedResultListener.idl
  105.    */
  106.   handleResult: function FC_handleResult(result) {
  107.     // Feeds come in various content types, which our feed sniffer coerces to
  108.     // the maybe.feed type. However, feeds are used as a transport for 
  109.     // different data types, e.g. news/blogs (traditional feed), video/audio
  110.     // (podcasts) and photos (photocasts, photostreams). Each of these is 
  111.     // different in that there's a different class of application suitable for
  112.     // handling feeds of that type, but without a content-type differentiation
  113.     // it is difficult for us to disambiguate.
  114.     // 
  115.     // The other problem is that if the user specifies an auto-action handler
  116.     // for one feed application, the fact that the content type is shared means 
  117.     // that all other applications will auto-load with that handler too, 
  118.     // regardless of the content-type. 
  119.     //
  120.     // This means that content-type alone is not enough to determine whether
  121.     // or not a feed should be auto-handled. This means that for feeds we need
  122.     // to always use this stream converter, even when an auto-action is 
  123.     // specified, not the basic one provided by WebContentConverter. This 
  124.     // converter needs to consume all of the data and parse it, and based on
  125.     // that determination make a judgement about type. 
  126.     //
  127.     // Since there are no content types for this content, and I'm not going to
  128.     // invent any, the upshot is that while a user can set an auto-handler for
  129.     // generic feed content, the system will prevent them from setting an auto-
  130.     // handler for other stream types. In those cases, the user will always see
  131.     // the preview page and have to select a handler. We can guess and show 
  132.     // a client handler, but will not be able to show web handlers for those
  133.     // types.
  134.     //
  135.     // If this is just a feed, not some kind of specialized application, then
  136.     // auto-handlers can be set and we should obey them. 
  137.     var feedService = 
  138.         Cc["@mozilla.org/browser/feeds/result-service;1"].
  139.         getService(Ci.nsIFeedResultService);
  140.     if (!this._forcePreviewPage) {
  141.       var skipPreview = safeGetBoolPref(PREF_SKIP_PREVIEW_PAGE, false);
  142.       if (skipPreview) {
  143.         var handler = safeGetCharPref(PREF_SELECTED_HANDLER, "bookmarks");
  144.         if (handler == "web") {
  145.           var wccr = 
  146.               Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
  147.               getService(Ci.nsIWebContentConverterService);
  148.           var feed = result.doc.QueryInterface(Ci.nsIFeed);
  149.           if (feed.type == Ci.nsIFeed.TYPE_FEED &&
  150.               wccr.getAutoHandler(TYPE_MAYBE_FEED)) {
  151.             wccr.loadPreferredHandler(this._request);
  152.             return;
  153.           }
  154.         }
  155.         else {
  156.           feedService.addToClientReader(result.uri.spec);
  157.           return;
  158.         }
  159.       }
  160.     }
  161.         
  162.     // If there was no automatic handler, or this was a podcast, photostream or
  163.     // some other kind of application, we must always show the preview page...
  164.   
  165.     // Store the result in the result service so that the display page can 
  166.     // access it.
  167.     feedService.addFeedResult(result);
  168.  
  169.     // Now load the actual XUL document.
  170.     var ios = 
  171.         Cc["@mozilla.org/network/io-service;1"].
  172.         getService(Ci.nsIIOService);
  173.     var chromeURI = ios.newURI(FEEDHANDLER_URI, null, null);
  174.     var chromeChannel = ios.newChannelFromURI(chromeURI, null);
  175.     chromeChannel.originalURI = result.uri;
  176.     chromeChannel.asyncOpen(this._listener, null);
  177.   },
  178.   
  179.   /**
  180.    * See nsIStreamListener.idl
  181.    */
  182.   onDataAvailable: function FC_onDataAvailable(request, context, inputStream, 
  183.                                                sourceOffset, count) {
  184.     this._processor.onDataAvailable(request, context, inputStream,
  185.                                     sourceOffset, count);
  186.   },
  187.   
  188.   /**
  189.    * See nsIRequestObserver.idl
  190.    */
  191.   onStartRequest: function FC_onStartRequest(request, context) {
  192.     var channel = request.QueryInterface(Ci.nsIChannel);
  193.     this._request = request;
  194.     
  195.     // Save and reset the forced state bit early, in case there's some kind of
  196.     // error.
  197.     var feedService = 
  198.         Cc["@mozilla.org/browser/feeds/result-service;1"].
  199.         getService(Ci.nsIFeedResultService);
  200.     this._forcePreviewPage = feedService.forcePreviewPage;
  201.     feedService.forcePreviewPage = false;
  202.  
  203.  
  204.     // Parse feed data as it comes in
  205.     this._processor =
  206.         Cc["@mozilla.org/feed-processor;1"].
  207.         createInstance(Ci.nsIFeedProcessor);
  208.     this._processor.listener = this;
  209.     this._processor.parseAsync(null, channel.URI);
  210.     
  211.     this._processor.onStartRequest(request, context);
  212.   },
  213.   
  214.   /**
  215.    * See nsIRequestObserver.idl
  216.    */
  217.   onStopRequest: function FC_onStopReqeust(request, context, status) {
  218.     this._processor.onStopRequest(request, context, status);
  219.   },
  220.   
  221.   /**
  222.    * See nsISupports.idl
  223.    */
  224.   QueryInterface: function FC_QueryInterface(iid) {
  225.     if (iid.equals(Ci.nsIFeedResultListener) ||
  226.         iid.equals(Ci.nsIStreamConverter) ||
  227.         iid.equals(Ci.nsIStreamListener) ||
  228.         iid.equals(Ci.nsIRequestObserver)||
  229.         iid.equals(Ci.nsISupports))
  230.       return this;
  231.     throw Cr.NS_ERROR_NO_INTERFACE;
  232.   },
  233. };
  234.  
  235. var FeedConverterFactory = {
  236.   createInstance: function FS_createInstance(outer, iid) {
  237.     if (outer != null)
  238.       throw Cr.NS_ERROR_NO_AGGREGATION;
  239.     return new FeedConverter().QueryInterface(iid);
  240.   },
  241.  
  242.   QueryInterface: function FS_QueryInterface(iid) {
  243.     if (iid.equals(Ci.nsIFactory) ||
  244.         iid.equals(Ci.nsISupports))
  245.       return this;
  246.     throw Cr.NS_ERROR_NOT_IMPLEMENTED;
  247.   },
  248. };
  249.  
  250. /**
  251.  * Keeps parsed FeedResults around for use elsewhere in the UI after the stream
  252.  * converter completes. 
  253.  */
  254. var FeedResultService = {
  255.   
  256.   /**
  257.    * A URI spec -> nsIFeedResult hash
  258.    */
  259.   _results: { },
  260.   
  261.   /**
  262.    * See nsIFeedService.idl
  263.    */
  264.   forcePreviewPage: false,
  265.   
  266.   /**
  267.    * See nsIFeedService.idl
  268.    */
  269.   addToClientReader: function FRS_addToClientReader(spec) {
  270.     var prefs =   
  271.         Cc["@mozilla.org/preferences-service;1"].
  272.         getService(Ci.nsIPrefBranch);
  273.     var handler = safeGetCharPref(PREF_SELECTED_HANDLER, "bookmarks");
  274.     switch (handler) {
  275.     case "client":
  276.       try {
  277.         var clientApp = 
  278.             prefs.getComplexValue(PREF_SELECTED_APP, Ci.nsILocalFile);
  279.       }
  280.       catch (e) {
  281.         return;
  282.       }
  283. //@line 339 "/build/buildd/firefox-1.99+2.0b1+dfsg/browser/components/feeds/src/FeedConverter.js"
  284.       var ss = 
  285.           Cc["@mozilla.org/browser/shell-service;1"].
  286.           getService(Ci.nsIShellService_MOZILLA_1_8_BRANCH);
  287.       ss.openApplicationWithURI(clientApp, spec);
  288.       break;
  289.     case "bookmarks":
  290.       var wm = 
  291.           Cc["@mozilla.org/appshell/window-mediator;1"].
  292.           getService(Ci.nsIWindowMediator);
  293.       var topWindow = wm.getMostRecentWindow("navigator:browser");
  294. //@line 352 "/build/buildd/firefox-1.99+2.0b1+dfsg/browser/components/feeds/src/FeedConverter.js"
  295.       topWindow.FeedHandler.addLiveBookmark(spec);
  296. //@line 354 "/build/buildd/firefox-1.99+2.0b1+dfsg/browser/components/feeds/src/FeedConverter.js"
  297.       break;
  298.     }
  299.   },
  300.   
  301.   /**
  302.    * See nsIFeedService.idl
  303.    */
  304.   addFeedResult: function FRS_addFeedResult(feedResult) {
  305.     NS_ASSERT(feedResult.uri != null, "null URI!");
  306.     NS_ASSERT(feedResult.uri != null, "null feedResult!");
  307.     this._results[feedResult.uri.spec] = feedResult;
  308.   },
  309.   
  310.   /**
  311.    * See nsIFeedService.idl
  312.    */
  313.   getFeedResult: function RFS_getFeedResult(uri) {
  314.     NS_ASSERT(uri != null, "null URI!");
  315.     return this._results[uri.spec];
  316.   },
  317.   
  318.   /**
  319.    * See nsIFeedService.idl
  320.    */
  321.   removeFeedResult: function FRS_removeFeedResult(uri) {
  322.     NS_ASSERT(uri != null, "null URI!");
  323.     if (uri.spec in this._results)
  324.       delete this._results[uri.spec];
  325.   },
  326.  
  327.   createInstance: function FRS_createInstance(outer, iid) {
  328.     if (outer != null)
  329.       throw Cr.NS_ERROR_NO_AGGREGATION;
  330.     return this.QueryInterface(iid);
  331.   },
  332.   
  333.   QueryInterface: function FRS_QueryInterface(iid) {
  334.     if (iid.equals(Ci.nsIFeedResultService) ||
  335.         iid.equals(Ci.nsIFactory) ||
  336.         iid.equals(Ci.nsISupports))
  337.       return this;
  338.     throw Cr.NS_ERROR_NOT_IMPLEMENTED;
  339.   },
  340. };
  341.  
  342. /**
  343.  * A protocol handler that converts the URIs of Apple's various bogo protocol
  344.  * schemes into http, as they should be. Mostly, this object just forwards 
  345.  * things through to the HTTP protocol handler.
  346.  */
  347. function FeedProtocolHandler(scheme) {
  348.   this._scheme = scheme;
  349.   var ios = 
  350.       Cc["@mozilla.org/network/io-service;1"].
  351.       getService(Ci.nsIIOService);
  352.   this._http = ios.getProtocolHandler("http");
  353. }
  354. FeedProtocolHandler.prototype = {
  355.   _scheme: "",
  356.   get scheme() {
  357.     return this._scheme;
  358.   },
  359.   
  360.   get protocolFlags() {
  361.     return this._http.protocolFlags;
  362.   },
  363.   
  364.   get defaultPort() {
  365.     return this._http.defaultPort;
  366.   },
  367.   
  368.   allowPort: function FPH_allowPort(port, scheme) {
  369.     return this._http.allowPort(port, scheme);
  370.   },
  371.   
  372.   newURI: function FPH_newURI(spec, originalCharset, baseURI) {
  373.     var uri = 
  374.         Cc["@mozilla.org/network/standard-url;1"].
  375.         createInstance(Ci.nsIStandardURL);
  376.     uri.init(Ci.nsIStandardURL.URLTYPE_STANDARD, 80, spec, originalCharset,
  377.              baseURI);
  378.     return uri;
  379.   },
  380.   
  381.   newChannel: function FPH_newChannel(uri) {
  382.     var ios = 
  383.         Cc["@mozilla.org/network/io-service;1"].
  384.         getService(Ci.nsIIOService);
  385.     // feed: URIs either start feed://, in which case the real scheme is http:
  386.     // or feed:http(s)://, (which by now we've changed to feed://realscheme//)
  387.     const httpsChunk = "feed://https//";
  388.     const httpChunk = "feed://http//";
  389.     if (uri.spec.substr(0, httpsChunk.length) == httpsChunk)
  390.       uri.spec = "https://" + uri.spec.substr(httpsChunk.length);
  391.     else if (uri.spec.substr(0, httpChunk.length) == httpChunk)
  392.       uri.spec = "http://" + uri.spec.substr(httpChunk.length);
  393.     else
  394.       uri.scheme = "http";
  395.  
  396.     var channel = ios.newChannelFromURI(uri, null);
  397.     channel.originalURI = uri;
  398.     return channel;
  399.   },
  400.   
  401.   QueryInterface: function FPH_QueryInterface(iid) {
  402.     if (iid.equals(Ci.nsIProtocolHandler) ||
  403.         iid.equals(Ci.nsISupports))
  404.       return this;
  405.     throw Cr.NS_ERROR_NO_INTERFACE;
  406.   }  
  407. };
  408.  
  409. var Module = {
  410.   QueryInterface: function M_QueryInterface(iid) {
  411.     if (iid.equals(Ci.nsIModule) ||
  412.         iid.equals(Ci.nsISupports))
  413.       return this;
  414.     throw Cr.NS_ERROR_NO_INTERFACE;
  415.   },
  416.   
  417.   getClassObject: function M_getClassObject(cm, cid, iid) {
  418.     if (!iid.equals(Ci.nsIFactory))
  419.       throw Cr.NS_ERROR_NOT_IMPLEMENTED;
  420.     
  421.     if (cid.equals(FS_CLASSID))
  422.       return FeedResultService;
  423.     if (cid.equals(FPH_CLASSID))
  424.       return new GenericComponentFactory(FeedProtocolHandler, "feed");
  425.     if (cid.equals(PCPH_CLASSID))
  426.       return new GenericComponentFactory(FeedProtocolHandler, "pcast");
  427.     if (cid.equals(FC_CLASSID))
  428.       return new GenericComponentFactory(FeedConverter);
  429.       
  430.     throw Cr.NS_ERROR_NO_INTERFACE;
  431.   },
  432.   
  433.   registerSelf: function M_registerSelf(cm, file, location, type) {
  434.     var cr = cm.QueryInterface(Ci.nsIComponentRegistrar);
  435.     
  436.     cr.registerFactoryLocation(FS_CLASSID, FS_CLASSNAME, FS_CONTRACTID,
  437.                                file, location, type);
  438.     cr.registerFactoryLocation(FPH_CLASSID, FPH_CLASSNAME, FPH_CONTRACTID,
  439.                                file, location, type);
  440.     cr.registerFactoryLocation(PCPH_CLASSID, PCPH_CLASSNAME, PCPH_CONTRACTID,
  441.                                file, location, type);
  442.  
  443.     // The feed converter is always attached, since parsing must be done to 
  444.     // determine whether or not auto-handling can occur. 
  445.     const converterPrefix = "@mozilla.org/streamconv;1?from=";
  446.     var converterContractID = 
  447.         converterPrefix + TYPE_MAYBE_FEED + "&to=" + TYPE_ANY;
  448.     cr.registerFactoryLocation(FC_CLASSID, FC_CLASSNAME, converterContractID,
  449.                                file, location, type);
  450.   },
  451.   
  452.   unregisterSelf: function M_unregisterSelf(cm, location, type) {
  453.     var cr = cm.QueryInterface(Ci.nsIComponentRegistrar);
  454.     cr.unregisterFactoryLocation(FPH_CLASSID, location);
  455.     cr.unregisterFactoryLocation(PCPH_CLASSID, location);
  456.   },
  457.   
  458.   canUnload: function M_canUnload(cm) {
  459.     return true;
  460.   }
  461. };
  462.  
  463. function NSGetModule(cm, file) {
  464.   return Module;
  465. }
  466.  
  467. //@line 44 "/build/buildd/firefox-1.99+2.0b1+dfsg/browser/components/feeds/src/../../../../toolkit/content/debug.js"
  468.  
  469. const NS_ASSERT_ENVIRONMENT_VARIABLE_NAME = "XUL_ASSERT_PROMPT";
  470. var gTraceOnAssert = true;
  471.  
  472. /**
  473.  * This function provides a simple assertion function for JavaScript.
  474.  * If the condition is true, this function will do nothing.  If the
  475.  * condition is false, then the message will be printed to the console
  476.  * and an alert will appear showing a stack trace, so that the (alpha
  477.  * or nightly) user can file a bug containing it.  For future enhancements, 
  478.  * see bugs 330077 and 330078.
  479.  *
  480.  * To suppress the dialogs, you can run with the environment variable
  481.  * XUL_ASSERT_PROMPT set to 0 (if unset, this defaults to 1).
  482.  *
  483.  * @param condition represents the condition that we're asserting to be
  484.  *                  true when we call this function--should be
  485.  *                  something that can be evaluated as a boolean.
  486.  * @param message   a string to be displayed upon failure of the assertion
  487.  */
  488.  
  489. function NS_ASSERT(condition, message) {
  490.   if (condition)
  491.     return;
  492.  
  493.   var caller = arguments.callee.caller;
  494.   var assertionText = "ASSERT: " + message + "\n";
  495.   dump(assertionText);
  496.  
  497.   var stackText = "";
  498.   if (gTraceOnAssert) {
  499.     stackText = "Stack Trace: \n";
  500.     var count = 0;
  501.     while (caller) {
  502.       stackText += count++ + ":" + caller.name + "(";
  503.       for (var i = 0; i < caller.arguments.length; ++i) {
  504.         var arg = caller.arguments[i];
  505.         stackText += arg;
  506.         if (i < caller.arguments.length - 1)
  507.           stackText += ",";
  508.       }
  509.       stackText += ")\n";
  510.       caller = caller.arguments.callee.caller;
  511.     }
  512.   }
  513.  
  514.   var environment = Components.classes["@mozilla.org/process/environment;1"].
  515.                     getService(Components.interfaces.nsIEnvironment);
  516.   if (environment.exists(NS_ASSERT_ENVIRONMENT_VARIABLE_NAME) &&
  517.       !parseInt(environment.get(NS_ASSERT_ENVIRONMENT_VARIABLE_NAME)))
  518.     return;
  519.  
  520.   var source = null;
  521.   if (this.window)
  522.     source = window;
  523.   var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
  524.            getService(Components.interfaces.nsIPromptService);
  525.   ps.alert(source, "Assertion Failed", assertionText + stackText);
  526. }
  527. //@line 37 "/build/buildd/firefox-1.99+2.0b1+dfsg/browser/components/feeds/src/GenericFactory.js"
  528.  
  529. /**
  530.  * An object implementing nsIFactory that can construct other objects upon
  531.  * createInstance, passing a set of parameters to that object's constructor.
  532.  */
  533. function GenericComponentFactory(ctor, params) {
  534.   this._ctor = ctor;
  535.   this._params = params;
  536. }
  537. GenericComponentFactory.prototype = {
  538.   _ctor: null,
  539.   _params: null,
  540.   
  541.   createInstance: function GCF_createInstance(outer, iid) {
  542.     if (outer != null)
  543.       throw Cr.NS_ERROR_NO_AGGREGATION;
  544.     return (new this._ctor(this._params)).QueryInterface(iid);
  545.   },
  546.   
  547.   QueryInterface: function GCF_QueryInterface(iid) {
  548.     if (iid.equals(Ci.nsIFactory) ||
  549.         iid.equals(Ci.nsISupports)) 
  550.       return this;
  551.     throw Cr.NS_ERROR_NO_INTERFACE;
  552.   }
  553. };
  554.  
  555.