26 Components.utils.import(
"resource://gre/modules/XPCOMUtils.jsm");
27 Components.utils.import(
"resource://app/jsmodules/ArrayConverter.jsm");
30 NS_XLINK:
"http://www.w3.org/1999/xlink",
32 init:
function FeedHandler_init() {
34 getBrowser().addEventListener(
"DOMLinkAdded",
this,
false);
36 Ci.nsIWebProgress.NOTIFY_STATE_REQUEST |
37 Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
40 handleEvent:
function FeedHandler_handleEvent(aEvent) {
46 this.onLinkAdded(aEvent);
51 onLinkAdded:
function FeedHandler_onLinkAdded(aEvent) {
53 var link = aEvent.originalTarget;
54 var rel = link.rel && link.rel.toLowerCase();
55 if (!link || !link.ownerDocument || !rel || !link.href)
58 var iconAdded =
false;
59 var searchAdded =
false;
60 var relStrings = rel.split(/\s+/);
62 for (let
i = 0;
i < relStrings.length;
i++)
63 rels[relStrings[
i]] =
true;
65 for (let relVal in rels) {
69 if (!rels.feed && rels.alternate && rels.stylesheet)
73 link.ownerDocument.nodePrincipal,
76 this.detectedFeed(link, link.ownerDocument);
82 if (!
Application.prefs.getValue(
"browser.chrome.site_icons",
true))
85 var targetDoc = link.ownerDocument;
86 var
uri =
makeURI(link.href, targetDoc.characterSet);
88 if ((
"isFailedIcon" in gBrowser) && gBrowser.isFailedIcon(uri))
94 const aboutNeterr = /^about:neterror\?/;
95 const aboutBlocked = /^about:blocked\?/;
96 const aboutCert = /^about:certerror\?/;
97 if (!(aboutNeterr.test(targetDoc.documentURI) ||
98 aboutBlocked.test(targetDoc.documentURI) ||
99 aboutCert.test(targetDoc.documentURI)) ||
100 !uri.schemeIs(
"chrome")) {
101 var ssm =
Cc[
"@mozilla.org/scriptsecuritymanager;1"].
104 ssm.checkLoadURIWithPrincipal(targetDoc.nodePrincipal, uri,
105 Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
112 var contentPolicy =
Cc[
"@mozilla.org/layout/content-policy;1"].
119 if (contentPolicy.shouldLoad(
Ci.nsIContentPolicy.TYPE_IMAGE,
120 uri, targetDoc.documentURIObject,
121 link, link.type,
null)
122 !=
Ci.nsIContentPolicy.ACCEPT)
125 var browserIndex = gBrowser.getBrowserIndexForDocument(targetDoc);
127 if (browserIndex == -1)
130 var
tab = gBrowser.mTabContainer.childNodes[browserIndex];
131 gBrowser.setIcon(tab, link.href);
137 var type = link.type && link.type.toLowerCase();
138 type = type.replace(/^\s+|\s*(?:;.*)?$/g,
"");
140 if (type ==
"application/opensearchdescription+xml" && link.title &&
141 /^(?:https?|ftp):/
i.test(link.href)) {
142 var engine = { title: link.title,
href: link.href };
143 BrowserSearch.addEngine(engine, link.ownerDocument);
164 isValidFeed:
function FeedHandler_isValidFeed(aLink, aPrincipal, aIsFeed) {
166 if (!aLink || !aPrincipal)
169 var type = aLink.type.toLowerCase().replace(/^\s+|\s*(?:;.*)?$/g,
"");
171 aIsFeed = (type ==
"application/rss+xml" ||
172 type ==
"application/atom+xml");
177 urlSecurityCheck(aLink.href, aPrincipal,
178 Components.interfaces.nsIScriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL);
179 return type ||
"application/rss+xml";
188 detectedFeed:
function FeedHandler_detectedFeed(link, targetDoc) {
190 var browserForLink = gBrowser.getBrowserForDocument(targetDoc);
191 if (!browserForLink) {
196 var feed = {
href: link.href, title: link.title };
199 var
ios =
Cc[
"@mozilla.org/network/io-service;1"]
200 .getService(
Ci.nsIIOService);
203 var processor =
Cc[
"@mozilla.org/feed-processor;1"]
204 .createInstance(
Ci.nsIFeedProcessor);
205 processor.listener = {
207 handleResult:
function FeedHandler_handleFeedResult(aResult) {
208 if (aResult.doc.title) {
209 feed.title = aResult.doc.title.plainText();
211 feed.author = ArrayConverter.JSArray(aResult.doc.authors)
212 .map(
function(x) x.QueryInterface(
Ci.nsIFeedPerson).name)
214 feed.result = aResult;
215 this.
self.addFeed(feed, browserForLink);
220 processor.parseAsync(
null, uri);
222 var channel = ios.newChannelFromURI(uri);
223 channel.asyncOpen(processor,
null);
226 addFeed:
function FeedHandler_addFeed(feed, browserForLink) {
227 if (!browserForLink.feeds)
228 browserForLink.feeds = [];
230 const iTunesNS =
"http://www.itunes.com/dtds/podcast-1.0.dtd";
231 let feedElem = feed.result.doc.QueryInterface(
Ci.nsIFeed);
232 if (!feedElem.attributes) {
236 let hasItunesNS =
false;
237 for (let
i = 0;
i < feedElem.attributes.length; ++
i) {
238 if (feedElem.attributes.getURI(
i) !=
"http://www.w3.org/2000/xmlns/") {
242 if (feedElem.attributes.getValue(
i) == iTunesNS) {
252 browserForLink.feeds.push(feed);
254 if (browserForLink == gBrowser.mCurrentBrowser) {
255 var feedButton = document.getElementById(
"feed-button");
257 feedButton.collapsed =
false;
265 updateFeeds:
function() {
266 var feedButton = document.getElementById(
"feed-button");
267 if (!this._feedMenuitem)
268 this._feedMenuitem = document.getElementById(
"subscribeToPageMenuitem");
269 if (!this._feedMenupopup)
270 this._feedMenupopup = document.getElementById(
"subscribeToPageMenupopup");
272 var feeds = gBrowser.mCurrentBrowser.feeds;
273 if (!feeds || feeds.length == 0) {
275 feedButton.collapsed =
true;
276 feedButton.removeAttribute(
"feed");
285 feedButton.collapsed =
false;
287 if (feeds.length > 1) {
293 feedButton.removeAttribute(
"feed");
296 feedButton.setAttribute(
"feed", feeds[0].
href);
308 updateFeedPanel:
function FeedHandler_updateFeedPanel(aEvent) {
309 function getElem(s) {
return document.getElementById(
"feed-panel-" + s);}
311 if (aEvent.target != document.getElementById(
"feed-panel")) {
316 var feeds =
getBrowser().selectedBrowser.feeds || [];
318 getElem(
"listbox").removeAllItems();
319 for (let
i = 0;
i < feeds.length; ++
i) {
320 getElem(
"listbox").appendItem(feeds[
i].title,
i, feeds[
i].
href);
322 getElem(
"listbox").collapsed = (feeds.length <= 1);
325 let feedElem = feed.result.doc.QueryInterface(
Ci.nsIFeed);
326 getElem(
"title").value = feedElem.title.plainText();
327 getElem(
"author").value = feed.author;
328 var fields = feedElem.fields;
331 getElem(
"description").collapsed =
true;
332 for each (let
key in [
"media:description",
"itunes:summary",
"description"]) {
333 if (fields.hasKey(key)) {
334 getElem(
"description").collapsed =
false;
335 getElem(
"description").textContent = fields.getProperty(key);
339 var image = feedElem.image;
340 if ((image instanceof
Ci.nsIPropertyBag) && image.hasKey(
"url")) {
341 getElem(
"image").setAttributeNS(this.NS_XLINK,
343 image.getProperty(
"url"));
344 getElem(
"image").collapsed =
false;
346 getElem(
"image").collapsed =
true;
350 closeFeedPanel:
function FeedHandler_closeFeedPanel() {
351 document.getElementById(
"feed-panel").hidePopup();
355 onStateChange:
function FeedHandler_onStateChange(aWebProgress,
363 onProgressChange:
function FeedHanlder_onProgressChange(aWebProgress,
373 onLocationChange:
function FeedHandler_onLocationChange(aWebProgress,
380 onStatusChange:
function FeedHandler_onStatusChange(aWebProgress,
388 onSecurityChange:
function FeedHandler_onSecurityChange(aWebProgress,
396 Ci.nsIWebProgressListener])
sbOSDControlService prototype QueryInterface
function getBrowser() gBrowser
getService(Ci.sbIFaceplateManager)
function makeURI(aURLSpec, aCharset)
function isValidFeed(aLink, aPrincipal, aIsFeed)
ContinuingWebProgressListener prototype onStateChange
_getSelectedPageStyle s i