Mozilla Cross-Reference mozilla-central
mozilla/ browser/ base/ content/ browser-feeds.js
Hg Log
Hg Blame
Diff file
Raw file
view using tree:
1 # -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
2 # This Source Code Form is subject to the terms of the Mozilla Public
3 # License, v. 2.0. If a copy of the MPL was not distributed with this
4 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 
6 /**
7  * The Feed Handler object manages discovery of RSS/ATOM feeds in web pages
8  * and shows UI when they are discovered.
9  */
10 var FeedHandler = {
11   /** Called when the user clicks on the Subscribe to This Page... menu item,
12    * or when the user clicks the feed button when the page contains multiple
13    * feeds.
14    * Builds a menu of unique feeds associated with the page, and if there
15    * is only one, shows the feed inline in the browser window.
16    * @param   container
17    *          The feed list container (menupopup or subview) to be populated.
18    * @param   isSubview
19    *          Whether we're creating a subview (true) or menu (false/undefined)
20    * @returns true if the menu/subview should be shown, false if there was only
21    *          one feed and the feed should be shown inline in the browser
22    *          window (do not show the menupopup/subview).
23    */
24   buildFeedList: function(container, isSubview) {
25     var feeds = gBrowser.selectedBrowser.feeds;
26     if (!isSubview && feeds == null) {
27       // XXX hack -- menu opening depends on setting of an "open"
28       // attribute, and the menu refuses to open if that attribute is
29       // set (because it thinks it's already open).  onpopupshowing gets
30       // called after the attribute is unset, and it doesn't get unset
31       // if we return false.  so we unset it here; otherwise, the menu
32       // refuses to work past this point.
33       container.parentNode.removeAttribute("open");
34       return false;
35     }
36 
37     for (let i = container.childNodes.length - 1; i >= 0; --i) {
38       let node = container.childNodes[i];
39       if (isSubview && node.localName == "label")
40         continue;
41       container.removeChild(node);
42     }
43 
44     if (!feeds || feeds.length <= 1)
45       return false;
46 
47     // Build the menu showing the available feed choices for viewing.
48     var itemNodeType = isSubview ? "toolbarbutton" : "menuitem";
49     for (let feedInfo of feeds) {
50       var item = document.createElement(itemNodeType);
51       var baseTitle = feedInfo.title || feedInfo.href;
52       var labelStr = gNavigatorBundle.getFormattedString("feedShowFeedNew", [baseTitle]);
53       item.setAttribute("label", labelStr);
54       item.setAttribute("feed", feedInfo.href);
55       item.setAttribute("tooltiptext", feedInfo.href);
56       item.setAttribute("crop", "center");
57       let className = "feed-" + itemNodeType;
58       if (isSubview) {
59         className += " subviewbutton";
60       }
61       item.setAttribute("class", className);
62       container.appendChild(item);
63     }
64     return true;
65   },
66 
67   /**
68    * Subscribe to a given feed.  Called when
69    *   1. Page has a single feed and user clicks feed icon in location bar
70    *   2. Page has a single feed and user selects Subscribe menu item
71    *   3. Page has multiple feeds and user selects from feed icon popup (or subview)
72    *   4. Page has multiple feeds and user selects from Subscribe submenu
73    * @param   href
74    *          The feed to subscribe to. May be null, in which case the
75    *          event target's feed attribute is examined.
76    * @param   event
77    *          The event this method is handling. Used to decide where
78    *          to open the preview UI. (Optional, unless href is null)
79    */
80   subscribeToFeed: function(href, event) {
81     // Just load the feed in the content area to either subscribe or show the
82     // preview UI
83     if (!href)
84       href = event.target.getAttribute("feed");
85     urlSecurityCheck(href, gBrowser.contentPrincipal,
86                      Ci.nsIScriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL);
87     var feedURI = makeURI(href, document.characterSet);
88     // Use the feed scheme so X-Moz-Is-Feed will be set
89     // The value doesn't matter
90     if (/^https?$/.test(feedURI.scheme))
91       href = "feed:" + href;
92     this.loadFeed(href, event);
93   },
94 
95   loadFeed: function(href, event) {
96     var feeds = gBrowser.selectedBrowser.feeds;
97     try {
98       openUILink(href, event, { ignoreAlt: true });
99     }
100     finally {
101       // We might default to a livebookmarks modal dialog,
102       // so reset that if the user happens to click it again
103       gBrowser.selectedBrowser.feeds = feeds;
104     }
105   },
106 
107   get _feedMenuitem() {
108     delete this._feedMenuitem;
109     return this._feedMenuitem = document.getElementById("singleFeedMenuitemState");
110   },
111 
112   get _feedMenupopup() {
113     delete this._feedMenupopup;
114     return this._feedMenupopup = document.getElementById("multipleFeedsMenuState");
115   },
116 
117   /**
118    * Update the browser UI to show whether or not feeds are available when
119    * a page is loaded or the user switches tabs to a page that has feeds.
120    */
121   updateFeeds: function() {
122     if (this._updateFeedTimeout)
123       clearTimeout(this._updateFeedTimeout);
124 
125     var feeds = gBrowser.selectedBrowser.feeds;
126     var haveFeeds = feeds && feeds.length > 0;
127 
128     var feedButton = document.getElementById("feed-button");
129     if (feedButton) {
130       if (haveFeeds) {
131         feedButton.removeAttribute("disabled");
132       } else {
133         feedButton.setAttribute("disabled", "true");
134       }
135     }
136 
137     if (!haveFeeds) {
138       this._feedMenuitem.setAttribute("disabled", "true");
139       this._feedMenuitem.removeAttribute("hidden");
140       this._feedMenupopup.setAttribute("hidden", "true");
141       return;
142     }
143 
144     if (feeds.length > 1) {
145       this._feedMenuitem.setAttribute("hidden", "true");
146       this._feedMenupopup.removeAttribute("hidden");
147     } else {
148       this._feedMenuitem.setAttribute("feed", feeds[0].href);
149       this._feedMenuitem.removeAttribute("disabled");
150       this._feedMenuitem.removeAttribute("hidden");
151       this._feedMenupopup.setAttribute("hidden", "true");
152     }
153   },
154 
155   addFeed: function(link, browserForLink) {
156     if (!browserForLink.feeds)
157       browserForLink.feeds = [];
158 
159     browserForLink.feeds.push({ href: link.href, title: link.title });
160 
161     // If this addition was for the current browser, update the UI. For
162     // background browsers, we'll update on tab switch.
163     if (browserForLink == gBrowser.selectedBrowser) {
164       // Batch updates to avoid updating the UI for multiple onLinkAdded events
165       // fired within 100ms of each other.
166       if (this._updateFeedTimeout)
167         clearTimeout(this._updateFeedTimeout);
168       this._updateFeedTimeout = setTimeout(this.updateFeeds.bind(this), 100);
169     }
170   }
171 };
172 
view http://hg.mozilla.org/mozilla-central/rev/ /browser/base/content/browser-feeds.js