336903 - feed view should not run with chrome privileges. Browser pieces: move privileged code from subscribe.js into FeedWriter javascript component, make an about:feeds redirector module in browser so that we don't need to touch the one in necko. r=mento

git-svn-id: svn://10.0.0.236/trunk@201020 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
beng%bengoodger.com
2006-06-27 19:53:48 +00:00
parent b8f7fcee72
commit fce8e93b7d
13 changed files with 943 additions and 429 deletions

View File

@@ -130,6 +130,9 @@
#define NS_FEEDSNIFFER_CONTRACTID \
"@mozilla.org/browser/feeds/sniffer;1"
#define NS_ABOUTFEEDS_CID \
{ 0x12ff56ec, 0x58be, 0x402c, { 0xb0, 0x57, 0x1, 0xf9, 0x61, 0xde, 0x96, 0x9b } }
#define NS_DOCNAVSTARTPROGRESSLISTENER_CID \
{ 0x7baf8179, 0xa4fd, 0x4bc0, { 0xbe, 0x43, 0xa9, 0xb1, 0x22, 0xc5, 0xde, 0xb6 } }

View File

@@ -79,6 +79,8 @@
#include "rdf.h"
#ifdef MOZ_FEEDS
#include "nsFeedSniffer.h"
#include "nsAboutFeeds.h"
#include "nsIAboutModule.h"
#endif
#ifdef MOZ_SAFE_BROWSING
#include "nsDocNavStartProgressListener.h"
@@ -226,6 +228,12 @@ static const nsModuleComponentInfo components[] =
NS_FEEDSNIFFER_CONTRACTID,
nsFeedSnifferConstructor,
nsFeedSniffer::Register },
{ "about:feeds Page",
NS_ABOUTFEEDS_CID,
NS_ABOUT_MODULE_CONTRACTID_PREFIX "feeds",
nsAboutFeeds::Create
},
#endif
#ifdef MOZ_SAFE_BROWSING

View File

@@ -79,6 +79,7 @@ var SubscriptionOptions = {
reader.value = handler != "bookmarks" ? "reader" : "bookmarks";
var readers = document.getElementById("readers");
readers.selectedIndex = 0;
if (handler == "web") {
try {
readers.value = prefs.getCharPref(PREF_SELECTED_WEB);
@@ -87,8 +88,6 @@ var SubscriptionOptions = {
readers.selectedIndex = 1;
}
}
else if (handler == "client")
readers.selectedIndex = 0;
if ("arguments" in window && window.arguments[0] == "subscribe") {
var strings = document.getElementById("bundle");
@@ -240,7 +239,7 @@ var SubscriptionOptions = {
getService(Ci.nsIWebContentConverterService);
if (autoHandle.checked) {
var handler =
wccr.getWebContentHandlerByURI(TYPE_MAYBE_FEED, webService.value);
wccr.getWebContentHandlerByURI(TYPE_MAYBE_FEED, readers.selectedItem.value);
if (handler)
wccr.setAutoHandler(TYPE_MAYBE_FEED, handler);
}

View File

@@ -35,344 +35,27 @@
*
* ***** END LICENSE BLOCK ***** */
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const HTML_NS = "http://www.w3.org/1999/xhtml";
const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
const URI_BUNDLE = "chrome://browser/locale/feeds/subscribe.properties";
const PREF_SELECTED_APP = "browser.feeds.handlers.application";
const PREF_SELECTED_WEB = "browser.feeds.handlers.webservice";
const PREF_SELECTED_HANDLER = "browser.feeds.handler";
const PREF_SKIP_PREVIEW_PAGE = "browser.feeds.skip_preview_page";
function LOG(str) {
dump("*** " + str + "\n");
}
var SubscribeHandler = {
_getPropertyAsBag: function FH__getPropertyAsBag(container, property) {
return container.fields.getProperty(property).
QueryInterface(Ci.nsIPropertyBag2);
},
_getPropertyAsString: function FH__getPropertyAsString(container, property) {
try {
return container.fields.getPropertyAsAString(property);
}
catch (e) {
}
return "";
},
_setContentText: function SH__setContentText(id, text) {
var element = document.getElementById(id);
while (element.hasChildNodes())
element.removeChild(element.firstChild);
element.appendChild(document.createTextNode(text));
},
/**
* Safely sets the href attribute on an anchor tag, providing the URI
* specified can be loaded according to rules.
* @param element
* The element to set a URI attribute on
* @param attribute
* The attribute of the element to set the URI to, e.g. href or src
* @param uri
* The URI spec to set as the href
* The nsIFeedWriter object that produces the UI
*/
_safeSetURIAttribute:
function SH__safeSetURIAttribute(element, attribute, uri) {
var secman =
Cc["@mozilla.org/scriptsecuritymanager;1"].
getService(Ci.nsIScriptSecurityManager);
const flags = Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT_OR_DATA;
try {
secman.checkLoadURIStr(document.documentURI, uri, flags);
// checkLoadURIStr will throw if the link URI should not be loaded per
// the rules specified in |flags|, so we'll never "linkify" the link...
element.setAttribute(attribute, uri);
}
catch (e) {
// Not allowed to load this link because secman.checkLoadURIStr threw
}
},
get _bundle() {
var sbs =
Cc["@mozilla.org/intl/stringbundle;1"].
getService(Ci.nsIStringBundleService);
return sbs.createBundle(URI_BUNDLE);
},
_getFormattedString: function SH__getFormattedString(key, params) {
return this._bundle.formatStringFromName(key, params, params.length);
},
_getString: function SH__getString(key) {
return this._bundle.GetStringFromName(key);
},
_feedWriter: null,
init: function SH_init() {
LOG("Subscribe Preview: feed uri = " + window.location.href);
var feedService =
Cc["@mozilla.org/browser/feeds/result-service;1"].
getService(Ci.nsIFeedResultService);
var ios =
Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
var feedURI = ios.newURI(window.location.href, null, null);
try {
var result = feedService.getFeedResult(feedURI);
}
catch (e) {
LOG("Subscribe Preview: feed not available?!");
}
if (result.bozo) {
LOG("Subscribe Preview: feed result is bozo?!");
}
// Set up the displayed handler
this._initSelectedHandler();
var prefs =
Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch2);
prefs.addObserver(PREF_SELECTED_HANDLER, this, false);
prefs.addObserver(PREF_SELECTED_APP, this, false);
try {
var container = result.doc;
container.title;
}
catch (e) {
LOG("Subscribe Preview: An error occurred in parsing! Fortunately, you can still subscribe...");
var feedError = document.getElementById("feedError");
feedError.removeAttribute("style");
var feedBody = document.getElementById("feedBody");
feedBody.setAttribute("style", "display:none;");
this._setContentText("errorCode", e);
return;
}
this._setContentText("feedTitleText", container.title);
this._setContentText("feedSubtitleText",
this._getPropertyAsString(container, "description"));
document.title = container.title;
try {
var parts = this._getPropertyAsBag(container, "image");
// Set up the title image (supplied by the feed)
var feedTitleImage = document.getElementById("feedTitleImage");
this._safeSetURIAttribute(feedTitleImage, "src",
parts.getPropertyAsAString("url"));
// Set up the title image link
var feedTitleLink = document.getElementById("feedTitleLink");
var titleText =
this._getFormattedString("linkTitleTextFormat",
[parts.getPropertyAsAString("title")]);
feedTitleLink.setAttribute("title", titleText);
this._safeSetURIAttribute(feedTitleLink, "href",
parts.getPropertyAsAString("link"));
// Fix the margin on the main title, so that the image doesn't run over
// the underline
var feedTitleText = document.getElementById("feedTitleText");
var titleImageWidth = parseInt(parts.getPropertyAsAString("width")) + 15;
feedTitleText.style.marginRight = titleImageWidth + "px";
}
catch (e) {
LOG("Failed to set Title Image (this is benign): " + e);
}
// XXXben - do something with this. parameterize?
const MAX_CHARS = 600;
// Build the actual feed content
var feedContent = document.getElementById("feedContent");
var feed = container.QueryInterface(Ci.nsIFeed);
for (var i = 0; i < feed.items.length; ++i) {
var entry = feed.items.queryElementAt(i, Ci.nsIFeedEntry);
entry.QueryInterface(Ci.nsIFeedContainer);
var entryContainer = document.createElementNS(HTML_NS, "div");
entryContainer.className = "entry";
var a = document.createElementNS(HTML_NS, "a");
a.appendChild(document.createTextNode(entry.title));
// Entries are not required to have links, so entry.link can be null.
if (entry.link)
this._safeSetURIAttribute(a, "href", entry.link.spec);
var title = document.createElementNS(HTML_NS, "h3");
title.appendChild(a);
entryContainer.appendChild(title);
var body = document.createElementNS(HTML_NS, "p");
var summary = entry.summary(true)
if (summary && summary.length > MAX_CHARS)
summary = summary.substring(0, MAX_CHARS) + "...";
// XXXben - Change to use innerHTML
body.appendChild(document.createTextNode(summary));
body.className = "feedEntryContent";
entryContainer.appendChild(body);
feedContent.appendChild(entryContainer);
}
this._feedWriter = new BrowserFeedWriter();
this._feedWriter.write(window);
},
uninit: function SH_uninit() {
var prefs =
Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch2);
prefs.removeObserver(PREF_SELECTED_HANDLER, this);
prefs.removeObserver(PREF_SELECTED_APP, this);
this._feedWriter.close();
},
_getFileDisplayName: function SH__getFileDisplayName(file) {
#ifdef XP_WIN
if (file instanceof Ci.nsILocalFileWin) {
try {
return file.getVersionInfoField("FileDescription");
}
catch (e) {
}
}
#endif
var ios =
Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
var url = ios.newFileURI(file).QueryInterface(Ci.nsIURL);
return url.fileName;
},
_initSelectedHandler: function SH__initSelectedHandler() {
var prefs =
Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch);
var chosen =
document.getElementById("feedSubscribeLineHandlerChosen");
var unchosen =
document.getElementById("feedSubscribeLineHandlerUnchosen");
var ios =
Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
try {
var iconURI = "chrome://browser/skin/places/livemarkItem.png";
var handler = prefs.getCharPref(PREF_SELECTED_HANDLER);
switch (handler) {
case "client":
var selectedApp =
prefs.getComplexValue(PREF_SELECTED_APP, Ci.nsILocalFile);
var displayName = this._getFileDisplayName(selectedApp);
LOG("displayName: "+ displayName);
this._setContentText("feedSubscribeHandleText", displayName);
var url = ios.newFileURI(selectedApp).QueryInterface(Ci.nsIURL);
iconURI = "moz-icon://" + url.spec;
break;
case "web":
var webURI = prefs.getCharPref(PREF_SELECTED_WEB);
var wccr =
Cc["@mozilla.org/web-content-handler-registrar;1"].
getService(Ci.nsIWebContentConverterService);
var title ="Unknown";
var handler =
wccr.getWebContentHandlerByURI(TYPE_MAYBE_FEED, webURI);
if (handler)
title = handler.name;
var uri = ios.newURI(webURI, null, null);
iconURI = uri.prePath + "/favicon.ico";
this._setContentText("feedSubscribeHandleText", title);
break;
case "bookmarks":
this._setContentText("feedSubscribeHandleText",
this._getString("liveBookmarks"));
break;
}
unchosen.setAttribute("hidden", "true");
chosen.removeAttribute("hidden");
var button = document.getElementById("feedSubscribeLink");
button.focus();
var displayArea =
document.getElementById("feedSubscribeHandleText");
displayArea.style.setProperty("background-image",
"url(\"" + iconURI + "\")", "");
}
catch (e) {
LOG("Failed to set Handler: " + e);
// No selected handlers yet! Make the user choose...
chosen.setAttribute("hidden", "true");
unchosen.removeAttribute("hidden");
document.getElementById("feedHeader").setAttribute("firstrun", "true");
var button = document.getElementById("feedChooseInitialReader");
button.focus();
}
},
observe: function SH_observe(subject, topic, data) {
if (topic == "nsPref:changed")
this._initSelectedHandler();
},
changeOptions: function SH_changeOptions() {
var paramBlock =
Cc["@mozilla.org/embedcomp/dialogparam;1"].
createInstance(Ci.nsIDialogParamBlock);
// Used to tell the preview page that the user chose to subscribe with
// a particular reader, and so it should subscribe now.
const PARAM_USER_SUBSCRIBED = 0;
paramBlock.SetInt(PARAM_USER_SUBSCRIBED, 0);
openDialog("chrome://browser/content/feeds/options.xul", "",
"modal,centerscreen", "subscribe", paramBlock);
if (paramBlock.GetInt(PARAM_USER_SUBSCRIBED) == 1)
this.subscribe();
this._feedWriter.changeOptions();
},
subscribe: function FH_subscribe() {
var prefs =
Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch);
try {
var handler = prefs.getCharPref(PREF_SELECTED_HANDLER);
}
catch (e) {
// Something is bogus in our state. Prompt the user to fix it.
this.changeOptions();
return;
}
if (handler == "web") {
var webURI = prefs.getCharPref(PREF_SELECTED_WEB);
var wccr =
Cc["@mozilla.org/web-content-handler-registrar;1"].
getService(Ci.nsIWebContentConverterService);
var handler =
wccr.getWebContentHandlerByURI(TYPE_MAYBE_FEED, webURI);
window.location.href = handler.getHandlerURI(window.location.href);
}
else {
var feedService =
Cc["@mozilla.org/browser/feeds/result-service;1"].
getService(Ci.nsIFeedResultService);
feedService.addToClientReader(window.location.href);
}
this._feedWriter.subscribe();
},
};
#include ../../../../toolkit/content/debug.js

View File

@@ -45,6 +45,6 @@ include $(DEPTH)/config/autoconf.mk
MODULE = browser-feeds
XPIDL_MODULE = browser-feeds
XPIDLSRCS = nsIFeedResultService.idl nsIWebContentConverterRegistrar.idl
XPIDLSRCS = nsIFeedResultService.idl nsIWebContentConverterRegistrar.idl nsIFeedWriter.idl
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,68 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Feed Writer.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <beng@google.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
interface nsIDOMWindow;
/**
* Instances of this component write UI into the display page. This component
* is trusted so can access preferences etc, but page content isn't and so
* cannot.
*/
[scriptable, uuid(25ad7625-a481-493d-90d5-4fa081a76dc5)]
interface nsIFeedWriter : nsISupports
{
/**
* Write feed UI for a particular preview DOMWindow
* @param window
* The DOMWindow of the preview page that has loaded.
* window.location.href == the URI of the feed.
*/
void write(in nsIDOMWindow window);
/**
* Show a UI for changing feed reader and options
*/
void changeOptions();
/**
* Subscribe to the current feed.
*/
void subscribe();
};

View File

@@ -1,39 +1,39 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Feed Stream Converter.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <beng@google.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
# -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the Feed Stream Converter.
#
# The Initial Developer of the Original Code is Google Inc.
# Portions created by the Initial Developer are Copyright (C) 2006
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Ben Goodger <beng@google.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK ***** */
const Cc = Components.classes;
const Ci = Components.interfaces;
@@ -61,7 +61,7 @@ const FHS_CLASSNAME = "Feed Handler Service";
const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
const TYPE_ANY = "*/*";
const FEEDHANDLER_URI = "chrome://browser/content/feeds/subscribe.xhtml";
const FEEDHANDLER_URI = "about:feeds";
const PREF_SELECTED_APP = "browser.feeds.handlers.application";
const PREF_SELECTED_WEB = "browser.feeds.handlers.webservice";
@@ -443,32 +443,6 @@ FeedProtocolHandler.prototype = {
}
};
/**
* An object implementing nsIFactory that can construct other objects upon
* createInstance, passing a set of parameters to that object's constructor.
*/
function GenericComponentFactory(ctor, params) {
this._ctor = ctor;
this._params = params;
}
GenericComponentFactory.prototype = {
_ctor: null,
_params: null,
createInstance: function GCF_createInstance(outer, iid) {
if (outer != null)
throw Cr.NS_ERROR_NO_AGGREGATION;
return (new this._ctor(this._params)).QueryInterface(iid);
},
QueryInterface: function GCF_QueryInterface(iid) {
if (iid.equals(Ci.nsIFactory) ||
iid.equals(Ci.nsISupports))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
}
};
var Module = {
QueryInterface: function M_QueryInterface(iid) {
if (iid.equals(Ci.nsIModule) ||
@@ -528,3 +502,4 @@ function NSGetModule(cm, file) {
}
#include ../../../../toolkit/content/debug.js
#include GenericFactory.js

View File

@@ -0,0 +1,554 @@
# -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the Feed Writer.
#
# The Initial Developer of the Original Code is Google Inc.
# Portions created by the Initial Developer are Copyright (C) 2006
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Ben Goodger <beng@google.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK ***** */
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
function LOG(str) {
dump("*** " + str + "\n");
}
const HTML_NS = "http://www.w3.org/1999/xhtml";
const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
const URI_BUNDLE = "chrome://browser/locale/feeds/subscribe.properties";
const PREF_SELECTED_APP = "browser.feeds.handlers.application";
const PREF_SELECTED_WEB = "browser.feeds.handlers.webservice";
const PREF_SELECTED_HANDLER = "browser.feeds.handler";
const PREF_SKIP_PREVIEW_PAGE = "browser.feeds.skip_preview_page";
const FW_CLASSID = Components.ID("{49bb6593-3aff-4eb3-a068-2712c28bd58e}");
const FW_CLASSNAME = "Feed Writer";
const FW_CONTRACTID = "@mozilla.org/browser/feeds/result-writer;1";
function FeedWriter() {
}
FeedWriter.prototype = {
_getPropertyAsBag: function FW__getPropertyAsBag(container, property) {
return container.fields.getProperty(property).
QueryInterface(Ci.nsIPropertyBag2);
},
_getPropertyAsString: function FW__getPropertyAsString(container, property) {
try {
return container.fields.getPropertyAsAString(property);
}
catch (e) {
}
return "";
},
_setContentText: function FW__setContentText(id, text) {
var element = this._document.getElementById(id);
while (element.hasChildNodes())
element.removeChild(element.firstChild);
element.appendChild(this._document.createTextNode(text));
},
/**
* Safely sets the href attribute on an anchor tag, providing the URI
* specified can be loaded according to rules.
* @param element
* The element to set a URI attribute on
* @param attribute
* The attribute of the element to set the URI to, e.g. href or src
* @param uri
* The URI spec to set as the href
*/
_safeSetURIAttribute:
function FW__safeSetURIAttribute(element, attribute, uri) {
var secman =
Cc["@mozilla.org/scriptsecuritymanager;1"].
getService(Ci.nsIScriptSecurityManager);
const flags = Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT_OR_DATA;
try {
secman.checkLoadURIStr(this._window.location.href, uri, flags);
// checkLoadURIStr will throw if the link URI should not be loaded per
// the rules specified in |flags|, so we'll never "linkify" the link...
element.setAttribute(attribute, uri);
}
catch (e) {
// Not allowed to load this link because secman.checkLoadURIStr threw
}
},
get _bundle() {
var sbs =
Cc["@mozilla.org/intl/stringbundle;1"].
getService(Ci.nsIStringBundleService);
return sbs.createBundle(URI_BUNDLE);
},
_getFormattedString: function FW__getFormattedString(key, params) {
return this._bundle.formatStringFromName(key, params, params.length);
},
_getString: function FW__getString(key) {
return this._bundle.GetStringFromName(key);
},
/**
* Writes the feed title into the preview document.
* @param container
* The feed container
*/
_setTitleText: function FW__setTitleText(container) {
this._setContentText("feedTitleText", container.title);
this._setContentText("feedSubtitleText",
this._getPropertyAsString(container, "description"));
this._document.title = container.title;
},
/**
* Writes the title image into the preview document if one is present.
* @param container
* The feed container
*/
_setTitleImage: function FW__setTitleImage(container) {
try {
var parts = this._getPropertyAsBag(container, "image");
// Set up the title image (supplied by the feed)
var feedTitleImage = this._document.getElementById("feedTitleImage");
this._safeSetURIAttribute(feedTitleImage, "src",
parts.getPropertyAsAString("url"));
// Set up the title image link
var feedTitleLink = this._document.getElementById("feedTitleLink");
var titleText =
this._getFormattedString("linkTitleTextFormat",
[parts.getPropertyAsAString("title")]);
feedTitleLink.setAttribute("title", titleText);
this._safeSetURIAttribute(feedTitleLink, "href",
parts.getPropertyAsAString("link"));
// Fix the margin on the main title, so that the image doesn't run over
// the underline
var feedTitleText = this._document.getElementById("feedTitleText");
var titleImageWidth = parseInt(parts.getPropertyAsAString("width")) + 15;
feedTitleText.style.marginRight = titleImageWidth + "px";
}
catch (e) {
LOG("Failed to set Title Image (this is benign): " + e);
}
},
/**
* Writes all entries contained in the feed.
* @param container
* The container of entries in the feed
*/
_writeFeedContent: function FW__writeFeedContent(container) {
// XXXben - do something with this. parameterize?
const MAX_CHARS = 600;
// Build the actual feed content
var feedContent = this._document.getElementById("feedContent");
var feed = container.QueryInterface(Ci.nsIFeed);
for (var i = 0; i < feed.items.length; ++i) {
var entry = feed.items.queryElementAt(i, Ci.nsIFeedEntry);
entry.QueryInterface(Ci.nsIFeedContainer);
var entryContainer = this._document.createElementNS(HTML_NS, "div");
entryContainer.className = "entry";
var a = this._document.createElementNS(HTML_NS, "a");
a.appendChild(this._document.createTextNode(entry.title));
// Entries are not required to have links, so entry.link can be null.
if (entry.link)
this._safeSetURIAttribute(a, "href", entry.link.spec);
var title = this._document.createElementNS(HTML_NS, "h3");
title.appendChild(a);
entryContainer.appendChild(title);
var body = this._document.createElementNS(HTML_NS, "p");
var summary = entry.summary(true)
if (summary && summary.length > MAX_CHARS)
summary = summary.substring(0, MAX_CHARS) + "...";
// XXXben - Change to use innerHTML
body.appendChild(this._document.createTextNode(summary));
body.className = "feedEntryContent";
entryContainer.appendChild(body);
feedContent.appendChild(entryContainer);
}
},
/**
* Gets a valid nsIFeedContainer object from the parsed nsIFeedResult.
* Displays error information if there was one.
* @param result
* The parsed feed result
* @returns A valid nsIFeedContainer object containing the contents of
* the feed.
*/
_getContainer: function FW__getContainer(result) {
var feedService =
Cc["@mozilla.org/browser/feeds/result-service;1"].
getService(Ci.nsIFeedResultService);
var ios =
Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
var feedURI = ios.newURI(this._window.location.href, null, null);
try {
var result = feedService.getFeedResult(feedURI);
}
catch (e) {
LOG("Subscribe Preview: feed not available?!");
}
if (result.bozo) {
LOG("Subscribe Preview: feed result is bozo?!");
}
try {
var container = result.doc;
container.title;
}
catch (e) {
LOG("Subscribe Preview: An error occurred in parsing! Fortunately, you can still subscribe...");
var feedError = this._document.getElementById("feedError");
feedError.removeAttribute("style");
var feedBody = this._document.getElementById("feedBody");
feedBody.setAttribute("style", "display:none;");
this._setContentText("errorCode", e);
return null;
}
return container;
},
/**
* Get the human-readable display name of a file. This could be the
* application name.
* @param file
* A nsIFile to look up the name of
* @returns The display name of the application represented by the file.
*/
_getFileDisplayName: function FW__getFileDisplayName(file) {
#ifdef XP_WIN
if (file instanceof Ci.nsILocalFileWin) {
try {
return file.getVersionInfoField("FileDescription");
}
catch (e) {
}
}
#endif
#ifdef XP_MACOSX
var lfm = file.QueryInterface(Components.interfaces.nsILocalFileMac);
try {
if (lfm.isPackage())
return lfm.bundleName;
}
catch (e) {
// fall through to the file name
}
#endif
var ios =
Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
var url = ios.newFileURI(file).QueryInterface(Ci.nsIURL);
return url.fileName;
},
_initSelectedHandler: function FW__initSelectedHandler() {
var prefs =
Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch);
var chosen =
this._document.getElementById("feedSubscribeLineHandlerChosen");
var unchosen =
this._document.getElementById("feedSubscribeLineHandlerUnchosen");
var ios =
Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
try {
var iconURI = "chrome://browser/skin/places/livemarkItem.png";
var handler = prefs.getCharPref(PREF_SELECTED_HANDLER);
switch (handler) {
case "client":
var selectedApp =
prefs.getComplexValue(PREF_SELECTED_APP, Ci.nsILocalFile);
var displayName = this._getFileDisplayName(selectedApp);
this._setContentText("feedSubscribeHandleText", displayName);
var url = ios.newFileURI(selectedApp).QueryInterface(Ci.nsIURL);
iconURI = "moz-icon://" + url.spec;
break;
case "web":
var webURI = prefs.getCharPref(PREF_SELECTED_WEB);
var wccr =
Cc["@mozilla.org/web-content-handler-registrar;1"].
getService(Ci.nsIWebContentConverterService);
var title ="Unknown";
var handler =
wccr.getWebContentHandlerByURI(TYPE_MAYBE_FEED, webURI);
if (handler)
title = handler.name;
var uri = ios.newURI(webURI, null, null);
iconURI = uri.prePath + "/favicon.ico";
this._setContentText("feedSubscribeHandleText", title);
break;
case "bookmarks":
this._setContentText("feedSubscribeHandleText",
this._getString("liveBookmarks"));
break;
}
unchosen.setAttribute("hidden", "true");
chosen.removeAttribute("hidden");
var button = this._document.getElementById("feedSubscribeLink");
button.focus();
var displayArea =
this._document.getElementById("feedSubscribeHandleText");
displayArea.style.setProperty("background-image",
"url(\"" + iconURI + "\")", "");
}
catch (e) {
LOG("Failed to set Handler: " + e);
// No selected handlers yet! Make the user choose...
chosen.setAttribute("hidden", "true");
unchosen.removeAttribute("hidden");
this._document.getElementById("feedHeader").setAttribute("firstrun", "true");
var button = this._document.getElementById("feedChooseInitialReader");
button.focus();
}
},
/**
* Ensures that this component is only ever invoked from the preview
* document.
* @param window
* The window of the document invoking the BrowserFeedWriter
*/
_isValidWindow: function FW__isValidWindow(window) {
var chan =
window.QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIWebNavigation).
QueryInterface(Ci.nsIDocShell).currentDocumentChannel;
const kPrefix = "jar:file:";
return chan.URI.spec.substring(0, kPrefix.length) == kPrefix;
},
_window: null,
_document: null,
/**
* See nsIFeedWriter
*/
write: function FW_write(window) {
if (!this._isValidWindow(window))
return;
this._window = window;
this._document = window.document;
LOG("Subscribe Preview: feed uri = " + this._window.location.href);
// Set up the displayed handler
this._initSelectedHandler();
var prefs =
Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch2);
prefs.addObserver(PREF_SELECTED_HANDLER, this, false);
prefs.addObserver(PREF_SELECTED_APP, this, false);
// Set up the feed content
var container = this._getContainer();
if (!container)
return;
this._setTitleText(container);
this._setTitleImage(container);
this._writeFeedContent(container);
},
/**
* See nsIFeedWriter
*/
changeOptions: function FW_changeOptions() {
var paramBlock =
Cc["@mozilla.org/embedcomp/dialogparam;1"].
createInstance(Ci.nsIDialogParamBlock);
// Used to tell the preview page that the user chose to subscribe with
// a particular reader, and so it should subscribe now.
const PARAM_USER_SUBSCRIBED = 0;
paramBlock.SetInt(PARAM_USER_SUBSCRIBED, 0);
this._window.openDialog("chrome://browser/content/feeds/options.xul", "",
"modal,centerscreen", "subscribe", paramBlock);
if (paramBlock.GetInt(PARAM_USER_SUBSCRIBED) == 1)
this.subscribe();
},
/**
* See nsIFeedWriter
*/
close: function FW_close() {
var prefs =
Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch2);
prefs.removeObserver(PREF_SELECTED_HANDLER, this);
prefs.removeObserver(PREF_SELECTED_APP, this);
},
/**
* See nsIFeedWriter
*/
subscribe: function FW_subscribe() {
var prefs =
Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch);
try {
var handler = prefs.getCharPref(PREF_SELECTED_HANDLER);
}
catch (e) {
// Something is bogus in our state. Prompt the user to fix it.
this.changeOptions();
return;
}
if (handler == "web") {
var webURI = prefs.getCharPref(PREF_SELECTED_WEB);
var wccr =
Cc["@mozilla.org/web-content-handler-registrar;1"].
getService(Ci.nsIWebContentConverterService);
var handler =
wccr.getWebContentHandlerByURI(TYPE_MAYBE_FEED, webURI);
this._window.location.href =
handler.getHandlerURI(this._window.location.href);
}
else {
var feedService =
Cc["@mozilla.org/browser/feeds/result-service;1"].
getService(Ci.nsIFeedResultService);
feedService.addToClientReader(this._window.location.href);
}
},
/**
* See nsIObserver
*/
observe: function FW_observe(subject, topic, data) {
if (topic == "nsPref:changed")
this._initSelectedHandler();
},
/**
* See nsIClassInfo
*/
getInterfaces: function WCCR_getInterfaces(countRef) {
var interfaces =
[Ci.nsIFeedWriter, Ci.nsIClassInfo, Ci.nsISupports];
countRef.value = interfaces.length;
return interfaces;
},
getHelperForLanguage: function WCCR_getHelperForLanguage(language) {
return null;
},
contractID: FW_CONTRACTID,
classDescription: FW_CLASSNAME,
classID: FW_CLASSID,
implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT,
flags: Ci.nsIClassInfo.DOM_OBJECT,
QueryInterface: function FW_QueryInterface(iid) {
if (iid.equals(Ci.nsIFeedWriter) ||
iid.equals(Ci.nsIClassInfo) ||
iid.equals(Ci.nsISupports))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
}
};
var Module = {
QueryInterface: function M_QueryInterface(iid) {
if (iid.equals(Ci.nsIModule) ||
iid.equals(Ci.nsISupports))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
},
getClassObject: function M_getClassObject(cm, cid, iid) {
if (!iid.equals(Ci.nsIFactory))
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
if (cid.equals(FW_CLASSID))
return new GenericComponentFactory(FeedWriter);
throw Cr.NS_ERROR_NO_INTERFACE;
},
registerSelf: function M_registerSelf(cm, file, location, type) {
var cr = cm.QueryInterface(Ci.nsIComponentRegistrar);
cr.registerFactoryLocation(FW_CLASSID, FW_CLASSNAME, FW_CONTRACTID,
file, location, type);
var catman =
Cc["@mozilla.org/categorymanager;1"].
getService(Ci.nsICategoryManager);
catman.addCategoryEntry("JavaScript global constructor",
"BrowserFeedWriter", FW_CONTRACTID, true, true);
},
unregisterSelf: function M_unregisterSelf(cm, location, type) {
var cr = cm.QueryInterface(Ci.nsIComponentRegistrar);
cr.unregisterFactoryLocation(FW_CLASSID, location);
},
canUnload: function M_canUnload(cm) {
return true;
}
};
function NSGetModule(cm, file) {
return Module;
}
#include ../../../../toolkit/content/debug.js
#include GenericFactory.js

View File

@@ -0,0 +1,63 @@
# -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the Generic Component Factory.
#
# The Initial Developer of the Original Code is Google Inc.
# Portions created by the Initial Developer are Copyright (C) 2006
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Ben Goodger <beng@google.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK ***** */
/**
* An object implementing nsIFactory that can construct other objects upon
* createInstance, passing a set of parameters to that object's constructor.
*/
function GenericComponentFactory(ctor, params) {
this._ctor = ctor;
this._params = params;
}
GenericComponentFactory.prototype = {
_ctor: null,
_params: null,
createInstance: function GCF_createInstance(outer, iid) {
if (outer != null)
throw Cr.NS_ERROR_NO_AGGREGATION;
return (new this._ctor(this._params)).QueryInterface(iid);
},
QueryInterface: function GCF_QueryInterface(iid) {
if (iid.equals(Ci.nsIFactory) ||
iid.equals(Ci.nsISupports))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
}
};

View File

@@ -46,12 +46,13 @@ LIBRARY_NAME = browser_feeds_s
EXTRA_PP_COMPONENTS = \
FeedConverter.js \
FeedWriter.js \
WebContentConverter.js \
$(NULL)
REQUIRES = xpcom string necko
REQUIRES = xpcom string necko caps js xpconnect
CPPSRCS = nsFeedSniffer.cpp
CPPSRCS = nsFeedSniffer.cpp nsAboutFeeds.cpp
LOCAL_INCLUDES = -I$(srcdir)/../../build

View File

@@ -1,39 +1,39 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Web Content Converter System.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <beng@google.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
# -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the Web Content Converter System.
#
# The Initial Developer of the Original Code is Google Inc.
# Portions created by the Initial Developer are Copyright (C) 2006
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Ben Goodger <beng@google.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK ***** */
const Cc = Components.classes;
const Ci = Components.interfaces;

View File

@@ -0,0 +1,100 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim:set ts=4 sw=4 sts=4 et cindent: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is The about:feeds Page.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <beng@google.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsAboutFeeds.h"
#include "nsNetUtil.h"
#include "nsIScriptSecurityManager.h"
NS_IMPL_ISUPPORTS1(nsAboutFeeds, nsIAboutModule)
#define FEEDS_PAGE_URI "chrome://browser/content/feeds/subscribe.xhtml"
NS_IMETHODIMP
nsAboutFeeds::NewChannel(nsIURI* uri, nsIChannel** result)
{
nsresult rv;
nsCOMPtr<nsIIOService> ios(do_GetIOService(&rv));
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIChannel> channel;
rv = ios->NewChannel(NS_LITERAL_CSTRING(FEEDS_PAGE_URI),
nsnull, nsnull, getter_AddRefs(channel));
if (NS_FAILED(rv))
return rv;
channel->SetOriginalURI(uri);
nsCOMPtr<nsIScriptSecurityManager> ssm =
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIPrincipal> principal;
rv = ssm->GetCodebasePrincipal(uri, getter_AddRefs(principal));
if (NS_FAILED(rv))
return rv;
rv = channel->SetOwner(principal);
if (NS_FAILED(rv))
return rv;
NS_ADDREF(*result = channel);
return NS_OK;
}
NS_IMETHODIMP
nsAboutFeeds::GetURIFlags(nsIURI* uri, PRUint32* uriFlags)
{
// Feeds page needs script, and is untrusted-content-safe
*uriFlags = URI_SAFE_FOR_UNTRUSTED_CONTENT | ALLOW_SCRIPT;
return NS_OK;
}
NS_METHOD
nsAboutFeeds::Create(nsISupports* outer, REFNSIID iid, void** result)
{
nsAboutFeeds* aboutFeeds = new nsAboutFeeds();
if (aboutFeeds == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(aboutFeeds);
nsresult rv = aboutFeeds->QueryInterface(iid, result);
NS_RELEASE(aboutFeeds);
return rv;
}

View File

@@ -0,0 +1,60 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim:set ts=4 sw=4 sts=4 et cindent: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is The about:feeds Page.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <beng@google.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsAboutFeeds_h__
#define nsAboutFeeds_h__
#include "nsIAboutModule.h"
class nsAboutFeeds : public nsIAboutModule
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIABOUTMODULE
nsAboutFeeds() { }
virtual ~nsAboutFeeds() { }
static NS_METHOD
Create(nsISupports* outer, REFNSIID iid, void** result);
protected:
};
#endif // nsAboutFeeds_h__