Backed out 4 changesets (bug 1025548) for suspicion of causing Mozmill failures.

Backed out changeset 01b838f9a078 (bug 1025548)
Backed out changeset face6ed1726e (bug 1025548)
Backed out changeset 647a2915cf66 (bug 1025548)
Backed out changeset 60013aa5437b (bug 1025548)
This commit is contained in:
Ryan VanderMeulen 2014-07-14 11:43:37 -04:00
Родитель d5645369ea
Коммит 3ab7a83b44
10 изменённых файлов: 485 добавлений и 547 удалений

Просмотреть файл

@ -3415,6 +3415,241 @@ function OpenOrFocusWindow(args, windowType, chromeURL)
window.openDialog(chromeURL, "", "chrome,resizable,status,centerscreen,dialog=no", args);
}
// This global is for SeaMonkey compatibility in newsblogOverlay.js.
let gShowFeedSummary = true;
let FeedMessageHandler = {
gShowSummary: true,
gToggle: false,
kSelectOverrideWebPage: 0,
kSelectOverrideSummary: 1,
kSelectFeedDefault: 2,
kOpenWebPage: 0,
kOpenSummary: 1,
kOpenToggleInMessagePane: 2,
kOpenLoadInBrowser: 3,
/**
* How to load message on threadpane select.
*/
get onSelectPref() {
return Services.prefs.getIntPref("rss.show.summary");
},
set onSelectPref(val) {
Services.prefs.setIntPref("rss.show.summary", val);
ReloadMessage();
},
/**
* Load web page on threadpane select.
*/
get loadWebPageOnSelectPref() {
return Services.prefs.getIntPref("rss.message.loadWebPageOnSelect") ? true : false;
},
/**
* How to load message on open (enter/dbl click in threadpane, contextmenu).
*/
get onOpenPref() {
return Services.prefs.getIntPref("rss.show.content-base");
},
set onOpenPref(val) {
Services.prefs.setIntPref("rss.show.content-base", val);
},
/**
* Determine if a message is a feed message. Prior to Tb15, a message had to
* be in an rss acount type folder. In Tb15 and later, a flag is set on the
* message itself upon initial store; the message can be moved to any folder.
*
* @param nsIMsgDBHdr aMsgHdr - the message.
*
* @return true if message is a feed, false if not.
*/
isFeedMessage: function (aMsgHdr) {
return (aMsgHdr instanceof Components.interfaces.nsIMsgDBHdr) &&
((aMsgHdr.flags & Components.interfaces.nsMsgMessageFlags.FeedMsg) ||
(aMsgHdr.folder && aMsgHdr.folder.server.type == "rss"));
},
/**
* Determine whether to show a feed message summary or load a web page in the
* message pane.
*
* @param nsIMsgDBHdr aMsgHdr - the message.
* @param bool aToggle - true if in toggle mode, false otherwise.
*
* @return true if summary is to be displayed, false if web page.
*/
shouldShowSummary: function (aMsgHdr, aToggle) {
// Not a feed message, always show summary (the message).
if (!this.isFeedMessage(aMsgHdr))
return true;
// Notified of a summary reload when toggling, reset toggle and return.
if (!aToggle && this.gToggle)
return !(this.gToggle = false);
let showSummary = true;
this.gToggle = aToggle;
// Thunderbird 2 rss messages with 'Show article summary' not selected,
// ie message body constructed to show web page in an iframe, can't show
// a summary - notify user.
let contentDoc = getBrowser().contentDocument;
let rssIframe = contentDoc.getElementById("_mailrssiframe");
if (rssIframe) {
if (this.gToggle || this.onSelectPref == this.kSelectOverrideSummary)
this.gToggle = false;
return false;
}
if (aToggle)
// Toggle mode, flip value.
return gShowFeedSummary = this.gShowSummary = !this.gShowSummary;
let wintype = document.documentElement.getAttribute("windowtype");
let tabMail = document.getElementById("tabmail");
let messageTab = tabMail && tabMail.currentTabInfo.mode.type == "message";
let messageWindow = wintype == "mail:messageWindow";
switch (this.onSelectPref) {
case this.kSelectOverrideWebPage:
showSummary = false;
break;
case this.kSelectOverrideSummary:
showSummary = true
break;
case this.kSelectFeedDefault:
// Get quickmode per feed folder pref from feeds.rdf. If the feed
// message is not in a feed account folder (hence the folder is not in
// the feeds database), or FZ_QUICKMODE property is not found (possible
// in pre renovation urls), err on the side of showing the summary.
// For the former, toggle or global override is necessary; for the
// latter, a show summary checkbox toggle in Subscribe dialog will set
// one on the path to bliss.
let folder = aMsgHdr.folder, targetRes;
try {
targetRes = FeedUtils.getParentTargetForChildResource(
folder.URI, FeedUtils.FZ_QUICKMODE, folder.server);
}
catch (ex) {
// Not in a feed account folder or other error.
FeedUtils.log.info("FeedMessageHandler.shouldShowSummary: could not " +
"get summary pref for this folder");
}
showSummary = targetRes && targetRes.QueryInterface(Ci.nsIRDFLiteral).
Value == "false" ? false : true;
break;
}
gShowFeedSummary = this.gShowSummary = showSummary;
if (messageWindow || messageTab) {
// Message opened in either standalone window or tab, due to either
// message open pref (we are here only if the pref is 0 or 1) or
// contextmenu open.
switch (this.onOpenPref) {
case this.kOpenToggleInMessagePane:
// Opened by contextmenu, use the value derived above.
// XXX: allow a toggle via crtl?
break;
case this.kOpenWebPage:
showSummary = false;
break;
case this.kOpenSummary:
showSummary = true;
break;
}
}
// Auto load web page in browser on select, per pref; shouldShowSummary() is
// always called first to 1)test if feed, 2)get summary pref, so do it here.
if (this.loadWebPageOnSelectPref)
setTimeout(FeedMessageHandler.loadWebPage, 20, aMsgHdr, {browser:true});
return showSummary;
},
/**
* Load a web page for feed messages. Use MsgHdrToMimeMessage() to get
* the content-base url from the message headers. We cannot rely on
* currentHeaderData; it has not yet been streamed at our entry point in
* displayMessageChanged(), and in the case of a collapsed message pane it
* is not streamed.
*
* @param nsIMsgDBHdr aMessageHdr - the message.
* @param {obj} aWhere - name value=true pair, where name is in:
* 'messagepane', 'browser', 'tab', 'window'.
*/
loadWebPage: function (aMessageHdr, aWhere) {
MsgHdrToMimeMessage(aMessageHdr, null, function(aMsgHdr, aMimeMsg) {
if (aMimeMsg && aMimeMsg.headers["content-base"] &&
aMimeMsg.headers["content-base"][0]) {
let url = aMimeMsg.headers["content-base"], uri;
try {
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
.createInstance(Ci.nsIScriptableUnicodeConverter);
converter.charset = "UTF-8";
url = converter.ConvertToUnicode(url);
uri = Services.io.newURI(url, null, null);
url = uri.spec;
}
catch (ex) {
FeedUtils.log.info("FeedMessageHandler.loadWebPage: " +
"invalid Content-Base header url - " + url);
return;
}
if (aWhere.browser)
Components.classes["@mozilla.org/uriloader/external-protocol-service;1"]
.getService(Components.interfaces.nsIExternalProtocolService)
.loadURI(uri);
else if (aWhere.messagepane) {
let loadFlag = getBrowser().webNavigation.LOAD_FLAGS_NONE;
getBrowser().webNavigation.loadURI(url, loadFlag, null, null, null);
}
else if (aWhere.tab)
openContentTab(url, "tab", "^");
else if (aWhere.window)
openContentTab(url, "window", "^");
}
else
FeedUtils.log.info("FeedMessageHandler.loadWebPage: could not get " +
"Content-Base header url for this message");
});
},
/**
* Display summary or load web page for feed messages. Caller should already
* know if the message is a feed message.
*
* @param nsIMsgDBHdr aMsgHdr - the message.
* @param bool aShowSummary - true if summary is to be displayed, false if
* web page.
*/
setContent: function (aMsgHdr, aShowSummary) {
if (aShowSummary) {
// Only here if toggling to summary in 3pane.
if (this.gToggle && gDBView && GetNumSelectedMessages() == 1)
ReloadMessage();
}
else {
let browser = getBrowser();
if (browser && browser.contentDocument && browser.contentDocument.body)
browser.contentDocument.body.hidden = true;
// If in a non rss folder, hide possible remote content bar on a web
// page load, as it doesn't apply.
gMessageNotificationBar.clearMsgNotifications();
this.loadWebPage(aMsgHdr, {messagepane:true});
this.gToggle = false;
}
}
}
function initAppMenuPopup(aMenuPopup, aEvent)
{
file_init();

Просмотреть файл

@ -161,10 +161,8 @@ Feed.prototype =
// Only order what you're going to eat...
this.request.responseType = "document";
this.request.overrideMimeType("text/xml");
this.request.timeout = FeedUtils.REQUEST_TIMEOUT;
this.request.onload = this.onDownloaded;
this.request.onerror = this.onDownloadError;
this.request.ontimeout = this.onDownloadError;
FeedCache.putFeed(this);
this.request.send(null);
},
@ -305,6 +303,9 @@ Feed.prototype =
old_lastmodified, aLastModified);
else
ds.Assert(this.resource, FeedUtils.DC_LASTMODIFIED, aLastModified, true);
// Do we need to flush every time this property changes?
ds.Flush();
},
get quickMode ()
@ -395,9 +396,9 @@ Feed.prototype =
{
// Create a feed parser which will parse the feed.
let parser = new FeedParser();
this.itemsToStore = parser.parseFeed(this, this.request.responseXML);
delete parser;
this.itemsToStore = parser.parseFeed(this,
this.request.responseXML,
this.request.channel.URI);
if (this.mInvalidFeed)
{
this.request = null;
@ -551,7 +552,7 @@ Feed.prototype =
item.feed.folder.callFilterPlugins(null);
}
this.cleanupParsingState(this, FeedUtils.kNewsBlogSuccess);
this.cleanupParsingState(item.feed, FeedUtils.kNewsBlogSuccess);
}
},
@ -569,6 +570,9 @@ Feed.prototype =
ds.Flush();
FeedUtils.log.debug("Feed.cleanupParsingState: items stored - " + this.itemsStored);
if (aFeed.downloadCallback)
aFeed.downloadCallback.downloaded(aFeed, aCode);
// Force the xml http request to go away. This helps reduce some nasty
// assertions on shut down.
this.request = null;
@ -576,9 +580,6 @@ Feed.prototype =
this.itemsToStoreIndex = 0;
this.itemsStored = 0;
this.storeItemsTimer = null;
if (aFeed.downloadCallback)
aFeed.downloadCallback.downloaded(aFeed, aCode);
},
// nsITimerCallback

Просмотреть файл

@ -103,6 +103,8 @@ FeedItem.prototype =
store: function()
{
this.mUnicodeConverter.charset = this.characterSet;
// this.title and this.content contain HTML.
// this.mUrl and this.contentBase contain plain text.
@ -160,6 +162,16 @@ FeedItem.prototype =
let downloaded = ds.GetTarget(itemResource, FeedUtils.FZ_STORED, true);
// Backward compatibility: for current items with with no guid or not stored
// with id. All items are stored with a uri encoded id, post bug 264482.
// TODO: Remove this after a cycle as it does not help perf.
if (!downloaded)
{
let id = this.url || this.feed.url + "#" + (this.date || this.title);
itemResource = FeedUtils.rdf.GetResource(this.createURN(id));
downloaded = ds.GetTarget(itemResource, FeedUtils.FZ_STORED, true);
}
if (!downloaded ||
downloaded.QueryInterface(Ci.nsIRDFLiteral).Value == "false")
{
@ -245,6 +257,8 @@ FeedItem.prototype =
{
FeedUtils.log.trace("FeedItem.writeToFolder: " + this.identity +
" writing to message folder " + this.feed.name);
this.mUnicodeConverter.charset = this.characterSet;
// Convert the title to UTF-16 before performing our HTML entity
// replacement reg expressions.
let title = this.title;
@ -361,7 +375,6 @@ FeedItem.prototype =
msgFolder.gettingNewMessages = true;
// Source is a unicode string, we want to save a char * string in
// the original charset. So convert back.
this.mUnicodeConverter.charset = this.characterSet;
let msgDBHdr = folder.addMessage(this.mUnicodeConverter.ConvertFromUnicode(source));
msgDBHdr.OrFlags(Ci.nsMsgMessageFlags.FeedMsg);
msgFolder.gettingNewMessages = false;

Просмотреть файл

@ -73,9 +73,6 @@ var FeedUtils = {
ATOM_IETF_NS: "http://www.w3.org/2005/Atom",
ATOM_THREAD_NS: "http://purl.org/syndication/thread/1.0",
// Timeout for nonresponse to request, 30 seconds.
REQUEST_TIMEOUT: 30 * 1000,
// The approximate amount of time, specified in milliseconds, to leave an
// item in the RDF cache after the item has dissappeared from feeds.
// The delay is currently one day.
@ -187,204 +184,6 @@ var FeedUtils = {
return feeds.IndexOf(this.rdf.GetResource(aUrl)) != -1;
},
/**
* Download a feed url on biff or get new messages.
*
* @param nsIMsgFolder aFolder - folder
* @param nsIUrlListener aUrlListener - feed url
* @param bool aIsBiff - true if biff, false if manual get
* @param nsIDOMWindow aMsgWindow - window
*/
downloadFeed: function(aFolder, aUrlListener, aIsBiff, aMsgWindow) {
if (Services.io.offline)
return;
// We don't yet support the ability to check for new articles while we are
// in the middle of subscribing to a feed. For now, abort the check for
// new feeds.
if (FeedUtils.progressNotifier.mSubscribeMode)
{
FeedUtils.log.warn("downloadFeed: Aborting RSS New Mail Check. " +
"Feed subscription in progress\n");
return;
}
let allFolders = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
if (!aFolder.isServer) {
// Add the base folder; it does not get returned by ListDescendants. Do not
// add the account folder as it doesn't have the feedUrl property or even
// a msgDatabase necessarily.
allFolders.appendElement(aFolder, false);
}
aFolder.ListDescendants(allFolders);
function feeder() {
let folder;
let numFolders = allFolders.length;
for (let i = 0; i < numFolders; i++) {
folder = allFolders.queryElementAt(i, Ci.nsIMsgFolder);
FeedUtils.log.debug("downloadFeed: START x/# foldername:uri - " +
(i+1) + "/" + numFolders + " " +
folder.name + ":" + folder.URI);
// Ensure folder's msgDatabase is openable for new message processing.
// If not, reparse. After the async reparse the folder will be ready
// for the next cycle; don't bother with a listener. Continue with
// the next folder, as attempting to add a message to a folder with
// an unavailable msgDatabase will throw later.
if (!FeedUtils.isMsgDatabaseOpenable(folder, true))
continue;
let feedUrlArray = FeedUtils.getFeedUrlsInFolder(folder);
// Continue if there are no feedUrls for the folder in the feeds
// database. All folders in Trash are skipped.
if (!feedUrlArray)
continue;
FeedUtils.log.debug("downloadFeed: CONTINUE foldername:urlArray - " +
folder.name + ":" + feedUrlArray);
FeedUtils.progressNotifier.init(aMsgWindow, false);
// We need to kick off a download for each feed.
let id, feed;
for (let url of feedUrlArray)
{
id = FeedUtils.rdf.GetResource(url);
feed = new Feed(id, folder.server);
feed.folder = folder;
// Bump our pending feed download count.
FeedUtils.progressNotifier.mNumPendingFeedDownloads++;
feed.download(true, FeedUtils.progressNotifier);
FeedUtils.log.debug("downloadFeed: DOWNLOAD feed url - " + url);
Services.tm.mainThread.dispatch(function() {
try {
getFeed.next();
}
catch (ex) {
if (ex instanceof StopIteration)
{
// Finished with all feeds in base folder and its subfolders.
FeedUtils.log.debug("downloadFeed: Finished with folder - " +
aFolder.name);
delete folder;
delete allFolders;
}
else
{
FeedUtils.log.error("downloadFeed: error - " + ex);
FeedUtils.progressNotifier.downloaded({name: folder.name}, 0);
}
}
}, Ci.nsIThread.DISPATCH_NORMAL);
yield undefined;
}
}
}
let getFeed = feeder();
try {
getFeed.next();
}
catch (ex) {
if (ex instanceof StopIteration)
{
// Nothing to do.
FeedUtils.log.debug("downloadFeed: Nothing to do in folder - " +
aFolder.name);
delete folder;
delete allFolders;
}
else
{
FeedUtils.log.error("downloadFeed: error - " + ex);
FeedUtils.progressNotifier.downloaded({name: aFolder.name}, 0);
}
}
},
/**
* Subscribe a new feed url.
*
* @param string aUrl - feed url
* @param nsIMsgFolder aFolder - folder
* @param nsIDOMWindow aMsgWindow - window
*/
subscribeToFeed: function(aUrl, aFolder, aMsgWindow) {
// We don't support the ability to subscribe to several feeds at once yet.
// For now, abort the subscription if we are already in the middle of
// subscribing to a feed via drag and drop.
if (FeedUtils.progressNotifier.mNumPendingFeedDownloads)
{
FeedUtils.log.warn("subscribeToFeed: Aborting RSS subscription. " +
"Feed downloads already in progress\n");
return;
}
// If aFolder is null, then use the root folder for the first RSS account.
if (!aFolder)
aFolder = FeedUtils.getAllRssServerRootFolders()[0];
// If the user has no Feeds account yet, create one.
if (!aFolder)
aFolder = FeedUtils.createRssAccount().incomingServer.rootFolder;
if (!aMsgWindow)
{
let wlist = Services.wm.getEnumerator("mail:3pane");
if (wlist.hasMoreElements())
{
let win = wlist.getNext().QueryInterface(Ci.nsIDOMWindow);
win.focus();
aMsgWindow = win.msgWindow;
}
else
{
// If there are no open windows, open one, pass it the URL, and
// during opening it will subscribe to the feed.
let arg = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
arg.data = aUrl;
Services.ww.openWindow(null, "chrome://messenger/content/",
"_blank", "chrome,dialog=no,all", arg);
return;
}
}
// If aUrl is a feed url, then it is either of the form
// feed://example.org/feed.xml or feed:https://example.org/feed.xml.
// Replace feed:// with http:// per the spec, then strip off feed:
// for the second case.
aUrl = aUrl.replace(/^feed:\x2f\x2f/i, "http://");
aUrl = aUrl.replace(/^feed:/i, "");
// Make sure we aren't already subscribed to this feed before we attempt
// to subscribe to it.
if (FeedUtils.feedAlreadyExists(aUrl, aFolder.server))
{
aMsgWindow.statusFeedback.showStatusString(
FeedUtils.strings.GetStringFromName("subscribe-feedAlreadySubscribed"));
return;
}
let itemResource = FeedUtils.rdf.GetResource(aUrl);
let feed = new Feed(itemResource, aFolder.server);
feed.quickMode = feed.server.getBoolValue("quickMode");
feed.options = FeedUtils.getOptionsAcct(feed.server);
// If the root server, create a new folder for the feed. The user must
// want us to add this subscription url to an existing RSS folder.
if (!aFolder.isServer)
feed.folder = aFolder;
FeedUtils.progressNotifier.init(aMsgWindow, true);
FeedUtils.progressNotifier.mNumPendingFeedDownloads++;
feed.download(true, FeedUtils.progressNotifier);
},
/**
* Add a feed record to the feeds.rdf database and update the folder's feedUrl
* property.
@ -451,8 +250,6 @@ var FeedUtils = {
// Update folderpane.
this.setFolderPaneProperty(aParentFolder, "_favicon", null);
delete feed;
},
/**
@ -495,40 +292,6 @@ var FeedUtils = {
return feedUrlArray.length ? feedUrlArray : null;
},
/**
* Check if the folder's msgDatabase is openable, reparse if desired.
*
* @param nsIMsgFolder aFolder - the folder
* @param boolean aReparse - reparse if true
* @return boolean - true if msgDb is available, else false
*/
isMsgDatabaseOpenable: function(aFolder, aReparse) {
let msgDb;
try {
msgDb = Cc["@mozilla.org/msgDatabase/msgDBService;1"]
.getService(Ci.nsIMsgDBService).openFolderDB(aFolder, true);
}
catch (ex) {}
if (msgDb)
return true;
if (!aReparse)
return false;
// Force a reparse.
FeedUtils.log.debug("checkMsgDb: rebuild msgDatabase for " +
aFolder.name + " - " + aFolder.filePath.path);
try {
// Ignore error returns.
aFolder.QueryInterface(Ci.nsIMsgLocalMailFolder)
.getDatabaseWithReparse(null, null);
}
catch (ex) {}
return false;
},
/**
* Update a folderpane ftvItem property.
*
@ -783,7 +546,7 @@ var FeedUtils = {
while (enumerator.hasMoreElements())
{
let containerArc = enumerator.getNext();
let uri = containerArc.QueryInterface(Ci.nsIRDFResource).ValueUTF8;
let uri = containerArc.QueryInterface(Ci.nsIRDFResource).Value;
feedUrlArray.push(uri);
}
}
@ -1171,25 +934,16 @@ var FeedUtils = {
return validUri ? uri : null;
},
/**
* Returns if a uri/url is valid to subscribe.
*
* @param nsIURI aUri or string aUrl - the Uri/Url.
* @return boolean - true if a valid scheme, false if not.
*/
_validSchemes: ["http", "https"],
isValidScheme: function(aUri) {
if (!(aUri instanceof Ci.nsIURI)) {
try {
aUri = Services.io.newURI(aUri, null, null);
}
catch (ex) {
return false;
}
}
return (this._validSchemes.indexOf(aUri.scheme) != -1);
/**
* Returns if a uri is valid to subscribe.
*
* @param nsIURI aUri - the Uri.
* @return boolean - true if a valid scheme, false if not.
*/
isValidScheme: function(aUri) {
return (aUri instanceof Ci.nsIURI) &&
(aUri.schemeIs("http") || aUri.schemeIs("https"));
},
/**
@ -1386,10 +1140,8 @@ var FeedUtils = {
if (!--this.mNumPendingFeedDownloads)
{
FeedUtils.getSubscriptionsDS(feed.server).Flush();
this.mFeeds = {};
this.mSubscribeMode = false;
FeedUtils.log.debug("downloaded: all pending downloads finished");
// Should we do this on a timer so the text sticks around for a little
// while? It doesnt look like we do it on a timer for newsgroups so
@ -1398,8 +1150,6 @@ var FeedUtils = {
if (aErrorCode == FeedUtils.kNewsBlogSuccess && this.mStatusFeedback)
this.mStatusFeedback.showStatusString("");
}
delete feed;
},
// This gets called after the RSS parser finishes storing a feed item to

Просмотреть файл

@ -14,7 +14,7 @@ FeedParser.prototype =
// parseFeed() returns an array of parsed items ready for processing. It is
// currently a synchronous operation. If there is an error parsing the feed,
// parseFeed returns an empty feed in addition to calling aFeed.onParseError.
parseFeed: function (aFeed, aDOM)
parseFeed: function (aFeed, aDOM, aBaseURI)
{
if (!(aDOM instanceof Ci.nsIDOMXMLDocument))
{
@ -45,7 +45,7 @@ FeedParser.prototype =
// the XMLHttpRequest.responseBody property that IE has, which provides
// access to the unencoded response.
let xmlString = this.mSerializer.serializeToString(doc);
return this.parseAsRSS1(aFeed, xmlString, aFeed.request.channel.URI);
return this.parseAsRSS1(aFeed, xmlString, aBaseURI);
}
else if (doc.namespaceURI == FeedUtils.ATOM_03_NS)
{

Просмотреть файл

@ -13,8 +13,6 @@ Components.utils.import("resource://gre/modules/Services.jsm");
var {classes: Cc, interfaces: Ci} = Components;
var FeedSubscriptions = {
get mMainWin() { return Services.wm.getMostRecentWindow("mail:3pane"); },
get mTree() { return document.getElementById("rssSubscriptionsList"); },
mFeedContainers: [],
@ -50,11 +48,12 @@ var FeedSubscriptions = {
FeedUtils.CANCEL_REQUESTED = false;
if (this.mMainWin)
let win = Services.wm.getMostRecentWindow("mail:3pane");
if (win)
{
this.mMainWin.FeedFolderNotificationService = MailServices.mfn;
this.mMainWin.FeedFolderNotificationService
.addListener(this.FolderListener, this.FOLDER_ACTIONS);
win.FeedFolderNotificationService = MailServices.mfn;
win.FeedFolderNotificationService.addListener(this.FolderListener,
this.FOLDER_ACTIONS);
}
},
@ -79,12 +78,13 @@ var FeedSubscriptions = {
if (dismissDialog)
{
FeedUtils.CANCEL_REQUESTED = this.mActionMode == this.kSubscribeMode;
if (this.mMainWin)
{
this.mMainWin.FeedFolderNotificationService
.removeListener(this.FolderListener, this.FOLDER_ACTIONS);
delete this.mMainWin.FeedFolderNotificationService;
}
let win = Services.wm.getMostRecentWindow("mail:3pane");
if (win)
{
win.FeedFolderNotificationService.removeListener(this.FolderListener,
this.FOLDER_ACTIONS);
delete win.FeedFolderNotificationService;
}
}
return dismissDialog;
@ -1810,16 +1810,17 @@ var FeedSubscriptions = {
let validationSite = "http://validator.w3.org";
let validationQuery = "http://validator.w3.org/feed/check.cgi?url=";
if (this.mMainWin)
let win = Services.wm.getMostRecentWindow("mail:3pane");
if (win && win instanceof Ci.nsIDOMWindow)
{
let tabmail = this.mMainWin.document.getElementById("tabmail");
let tabmail = win.document.getElementById("tabmail");
if (tabmail)
{
let feedLocation = document.getElementById("locationValue").value;
let url = validationQuery + encodeURIComponent(feedLocation);
this.mMainWin.focus();
this.mMainWin.openContentTab(url, "tab", "^" + validationSite);
win.focus();
win.openContentTab(url, "tab", "^" + validationSite);
FeedUtils.log.debug("checkValidation: query url - " + url);
}
}

Просмотреть файл

@ -7,241 +7,6 @@ Components.utils.import("resource:///modules/gloda/mimemsg.js");
Components.utils.import("resource:///modules/mailServices.js");
Components.utils.import("resource://gre/modules/Services.jsm");
// This global is for SeaMonkey compatibility.
let gShowFeedSummary;
let FeedMessageHandler = {
gShowSummary: true,
gToggle: false,
kSelectOverrideWebPage: 0,
kSelectOverrideSummary: 1,
kSelectFeedDefault: 2,
kOpenWebPage: 0,
kOpenSummary: 1,
kOpenToggleInMessagePane: 2,
kOpenLoadInBrowser: 3,
/**
* How to load message on threadpane select.
*/
get onSelectPref() {
return Services.prefs.getIntPref("rss.show.summary");
},
set onSelectPref(val) {
Services.prefs.setIntPref("rss.show.summary", val);
ReloadMessage();
},
/**
* Load web page on threadpane select.
*/
get loadWebPageOnSelectPref() {
return Services.prefs.getIntPref("rss.message.loadWebPageOnSelect") ? true : false;
},
/**
* How to load message on open (enter/dbl click in threadpane, contextmenu).
*/
get onOpenPref() {
return Services.prefs.getIntPref("rss.show.content-base");
},
set onOpenPref(val) {
Services.prefs.setIntPref("rss.show.content-base", val);
},
/**
* Determine if a message is a feed message. Prior to Tb15, a message had to
* be in an rss acount type folder. In Tb15 and later, a flag is set on the
* message itself upon initial store; the message can be moved to any folder.
*
* @param nsIMsgDBHdr aMsgHdr - the message.
*
* @return true if message is a feed, false if not.
*/
isFeedMessage: function(aMsgHdr) {
return (aMsgHdr instanceof Components.interfaces.nsIMsgDBHdr) &&
((aMsgHdr.flags & Components.interfaces.nsMsgMessageFlags.FeedMsg) ||
(aMsgHdr.folder && aMsgHdr.folder.server.type == "rss"));
},
/**
* Determine whether to show a feed message summary or load a web page in the
* message pane.
*
* @param nsIMsgDBHdr aMsgHdr - the message.
* @param bool aToggle - true if in toggle mode, false otherwise.
*
* @return true if summary is to be displayed, false if web page.
*/
shouldShowSummary: function(aMsgHdr, aToggle) {
// Not a feed message, always show summary (the message).
if (!this.isFeedMessage(aMsgHdr))
return true;
// Notified of a summary reload when toggling, reset toggle and return.
if (!aToggle && this.gToggle)
return !(this.gToggle = false);
let showSummary = true;
this.gToggle = aToggle;
// Thunderbird 2 rss messages with 'Show article summary' not selected,
// ie message body constructed to show web page in an iframe, can't show
// a summary - notify user.
let contentDoc = getBrowser().contentDocument;
let rssIframe = contentDoc.getElementById("_mailrssiframe");
if (rssIframe) {
if (this.gToggle || this.onSelectPref == this.kSelectOverrideSummary)
this.gToggle = false;
return false;
}
if (aToggle)
// Toggle mode, flip value.
return gShowFeedSummary = this.gShowSummary = !this.gShowSummary;
let wintype = document.documentElement.getAttribute("windowtype");
let tabMail = document.getElementById("tabmail");
let messageTab = tabMail && tabMail.currentTabInfo.mode.type == "message";
let messageWindow = wintype == "mail:messageWindow";
switch (this.onSelectPref) {
case this.kSelectOverrideWebPage:
showSummary = false;
break;
case this.kSelectOverrideSummary:
showSummary = true
break;
case this.kSelectFeedDefault:
// Get quickmode per feed folder pref from feeds.rdf. If the feed
// message is not in a feed account folder (hence the folder is not in
// the feeds database), or FZ_QUICKMODE property is not found (possible
// in pre renovation urls), err on the side of showing the summary.
// For the former, toggle or global override is necessary; for the
// latter, a show summary checkbox toggle in Subscribe dialog will set
// one on the path to bliss.
let folder = aMsgHdr.folder, targetRes;
try {
targetRes = FeedUtils.getParentTargetForChildResource(
folder.URI, FeedUtils.FZ_QUICKMODE, folder.server);
}
catch (ex) {
// Not in a feed account folder or other error.
FeedUtils.log.info("FeedMessageHandler.shouldShowSummary: could not " +
"get summary pref for this folder");
}
showSummary = targetRes && targetRes.QueryInterface(Ci.nsIRDFLiteral).
Value == "false" ? false : true;
break;
}
gShowFeedSummary = this.gShowSummary = showSummary;
if (messageWindow || messageTab) {
// Message opened in either standalone window or tab, due to either
// message open pref (we are here only if the pref is 0 or 1) or
// contextmenu open.
switch (this.onOpenPref) {
case this.kOpenToggleInMessagePane:
// Opened by contextmenu, use the value derived above.
// XXX: allow a toggle via crtl?
break;
case this.kOpenWebPage:
showSummary = false;
break;
case this.kOpenSummary:
showSummary = true;
break;
}
}
// Auto load web page in browser on select, per pref; shouldShowSummary() is
// always called first to 1)test if feed, 2)get summary pref, so do it here.
if (this.loadWebPageOnSelectPref)
setTimeout(FeedMessageHandler.loadWebPage, 20, aMsgHdr, {browser:true});
return showSummary;
},
/**
* Load a web page for feed messages. Use MsgHdrToMimeMessage() to get
* the content-base url from the message headers. We cannot rely on
* currentHeaderData; it has not yet been streamed at our entry point in
* displayMessageChanged(), and in the case of a collapsed message pane it
* is not streamed.
*
* @param nsIMsgDBHdr aMessageHdr - the message.
* @param {obj} aWhere - name value=true pair, where name is in:
* 'messagepane', 'browser', 'tab', 'window'.
*/
loadWebPage: function(aMessageHdr, aWhere) {
MsgHdrToMimeMessage(aMessageHdr, null, function(aMsgHdr, aMimeMsg) {
if (aMimeMsg && aMimeMsg.headers["content-base"] &&
aMimeMsg.headers["content-base"][0]) {
let url = aMimeMsg.headers["content-base"], uri;
try {
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
.createInstance(Ci.nsIScriptableUnicodeConverter);
converter.charset = "UTF-8";
url = converter.ConvertToUnicode(url);
uri = Services.io.newURI(url, null, null);
url = uri.spec;
}
catch (ex) {
FeedUtils.log.info("FeedMessageHandler.loadWebPage: " +
"invalid Content-Base header url - " + url);
return;
}
if (aWhere.browser)
Components.classes["@mozilla.org/uriloader/external-protocol-service;1"]
.getService(Components.interfaces.nsIExternalProtocolService)
.loadURI(uri);
else if (aWhere.messagepane) {
let loadFlag = getBrowser().webNavigation.LOAD_FLAGS_NONE;
getBrowser().webNavigation.loadURI(url, loadFlag, null, null, null);
}
else if (aWhere.tab)
openContentTab(url, "tab", "^");
else if (aWhere.window)
openContentTab(url, "window", "^");
}
else
FeedUtils.log.info("FeedMessageHandler.loadWebPage: could not get " +
"Content-Base header url for this message");
});
},
/**
* Display summary or load web page for feed messages. Caller should already
* know if the message is a feed message.
*
* @param nsIMsgDBHdr aMsgHdr - the message.
* @param bool aShowSummary - true if summary is to be displayed, false if
* web page.
*/
setContent: function(aMsgHdr, aShowSummary) {
if (aShowSummary) {
// Only here if toggling to summary in 3pane.
if (this.gToggle && gDBView && GetNumSelectedMessages() == 1)
ReloadMessage();
}
else {
let browser = getBrowser();
if (browser && browser.contentDocument && browser.contentDocument.body)
browser.contentDocument.body.hidden = true;
// If in a non rss folder, hide possible remote content bar on a web
// page load, as it doesn't apply.
gMessageNotificationBar.clearMsgNotifications();
this.loadWebPage(aMsgHdr, {messagepane:true});
this.gToggle = false;
}
}
}
function openSubscriptionsDialog(aFolder)
{
// Check for an existing feed subscriptions window and focus it.
@ -267,7 +32,7 @@ function openSubscriptionsDialog(aFolder)
}
}
// Special case attempts to reply/forward/edit as new RSS articles. For
// Special case attempts to reply/forward/edit as new RSS articles. For
// messages stored prior to Tb15, we are here only if the message's folder's
// account server is rss and feed messages moved to other types will have their
// summaries loaded, as viewing web pages only happened in an rss account.
@ -302,11 +67,11 @@ function openComposeWindowForRSSArticle(aMsgComposeWindow, aMsgHdr, aMessageUri,
let fwdPrefix = Services.prefs.getCharPref("mail.forward_subject_prefix");
fwdPrefix = fwdPrefix ? fwdPrefix + ": " : "";
let params = Cc["@mozilla.org/messengercompose/composeparams;1"]
.createInstance(Ci.nsIMsgComposeParams);
let params = Cc["@mozilla.org/messengercompose/composeparams;1"].
createInstance(Ci.nsIMsgComposeParams);
let composeFields = Cc["@mozilla.org/messengercompose/composefields;1"]
.createInstance(Ci.nsIMsgCompFields);
let composeFields = Cc["@mozilla.org/messengercompose/composefields;1"].
createInstance(Ci.nsIMsgCompFields);
if (type == msgComposeType.Reply ||
type == msgComposeType.ReplyAll ||
@ -336,11 +101,7 @@ function openComposeWindowForRSSArticle(aMsgComposeWindow, aMsgHdr, aMessageUri,
if (aMimeMsg && aMimeMsg.headers["content-base"] &&
aMimeMsg.headers["content-base"][0])
{
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
.createInstance(Ci.nsIScriptableUnicodeConverter);
converter.charset = "UTF-8";
let url = converter.ConvertToUnicode(aMimeMsg.headers["content-base"]);
params.composeFields.body = url;
params.composeFields.body = aMimeMsg.headers["content-base"];
params.bodyIsLink = true;
MailServices.compose.OpenComposeWindowWithParams(null, params);
}

Просмотреть файл

@ -6,18 +6,201 @@
var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource:///modules/FeedUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
var nsNewsBlogFeedDownloader =
{
downloadFeed: function(aFolder, aUrlListener, aIsBiff, aMsgWindow)
downloadFeed: function(aFolder, aUrlListener, aMsgWindow)
{
FeedUtils.downloadFeed(aFolder, aUrlListener, aIsBiff, aMsgWindow);
if (Services.io.offline)
return;
// We don't yet support the ability to check for new articles while we are
// in the middle of subscribing to a feed. For now, abort the check for
// new feeds.
if (FeedUtils.progressNotifier.mSubscribeMode)
{
FeedUtils.log.warn("downloadFeed: Aborting RSS New Mail Check. " +
"Feed subscription in progress\n");
return;
}
let allFolders = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
if (!aFolder.isServer) {
// Add the base folder; it does not get returned by ListDescendants. Do not
// add the account folder as it doesn't have the feedUrl property or even
// a msgDatabase necessarily.
allFolders.appendElement(aFolder, false);
}
aFolder.ListDescendants(allFolders);
function feeder() {
let folder;
let numFolders = allFolders.length;
for (let i = 0; i < numFolders; i++) {
folder = allFolders.queryElementAt(i, Ci.nsIMsgFolder);
FeedUtils.log.debug("downloadFeed: START x/# foldername:uri - " +
(i+1) + "/" + numFolders + " " +
folder.name + ":" + folder.URI);
// Ensure msgDatabase for the folder is open for new message processing.
let msgDb;
try {
msgDb = folder.msgDatabase;
}
catch (ex) {}
if (!msgDb) {
// Force a reparse. After the async reparse the folder will be ready
// for the next cycle; don't bother with a listener. Continue with
// the next folder, as attempting to add a message to a folder with
// an unavailable msgDatabase will throw later.
FeedUtils.log.debug("downloadFeed: rebuild msgDatabase for " +
folder.name + " - " + folder.filePath.path);
try
{
// Ignore error returns.
folder.QueryInterface(Ci.nsIMsgLocalMailFolder).
getDatabaseWithReparse(null, null);
}
catch (ex) {}
continue;
}
let feedUrlArray = FeedUtils.getFeedUrlsInFolder(folder);
// Continue if there are no feedUrls for the folder in the feeds
// database. All folders in Trash are skipped.
if (!feedUrlArray)
continue;
FeedUtils.log.debug("downloadFeed: CONTINUE foldername:urlArray - " +
folder.name + ":" + feedUrlArray);
FeedUtils.progressNotifier.init(aMsgWindow, false);
// We need to kick off a download for each feed.
let id, feed;
for (let url of feedUrlArray)
{
id = FeedUtils.rdf.GetResource(url);
feed = new Feed(id, folder.server);
feed.folder = folder;
// Bump our pending feed download count.
FeedUtils.progressNotifier.mNumPendingFeedDownloads++;
feed.download(true, FeedUtils.progressNotifier);
FeedUtils.log.debug("downloadFeed: DOWNLOAD feed url - " + url);
Services.tm.mainThread.dispatch(function() {
try {
getFeed.next();
}
catch (ex) {
if (ex instanceof StopIteration)
// Finished with all feeds in base folder and its subfolders.
FeedUtils.log.debug("downloadFeed: Finished with folder - " +
aFolder.name);
else
{
FeedUtils.log.error("downloadFeed: error - " + ex);
FeedUtils.progressNotifier.downloaded({name: folder.name}, 0);
}
}
}, Ci.nsIThread.DISPATCH_NORMAL);
yield undefined;
}
}
}
let getFeed = feeder();
try {
getFeed.next();
}
catch (ex) {
if (ex instanceof StopIteration)
// Nothing to do.
FeedUtils.log.debug("downloadFeed: Nothing to do in folder - " +
aFolder.name);
else
{
FeedUtils.log.error("downloadFeed: error - " + ex);
FeedUtils.progressNotifier.downloaded({name: aFolder.name}, 0);
}
}
},
subscribeToFeed: function(aUrl, aFolder, aMsgWindow)
{
FeedUtils.subscribeToFeed(aUrl, aFolder, aMsgWindow);
// We don't support the ability to subscribe to several feeds at once yet.
// For now, abort the subscription if we are already in the middle of
// subscribing to a feed via drag and drop.
if (FeedUtils.progressNotifier.mNumPendingFeedDownloads)
{
FeedUtils.log.warn("subscribeToFeed: Aborting RSS subscription. " +
"Feed downloads already in progress\n");
return;
}
// If aFolder is null, then use the root folder for the first RSS account.
if (!aFolder)
aFolder = FeedUtils.getAllRssServerRootFolders()[0];
// If the user has no Feeds account yet, create one.
if (!aFolder)
aFolder = FeedUtils.createRssAccount().incomingServer.rootFolder;
if (!aMsgWindow)
{
let wlist = Services.wm.getEnumerator("mail:3pane");
if (wlist.hasMoreElements())
{
let win = wlist.getNext().QueryInterface(Ci.nsIDOMWindow);
win.focus();
aMsgWindow = win.msgWindow;
}
else
{
// If there are no open windows, open one, pass it the URL, and
// during opening it will subscribe to the feed.
let arg = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
arg.data = aUrl;
Services.ww.openWindow(null, "chrome://messenger/content/",
"_blank", "chrome,dialog=no,all", arg);
return;
}
}
// If aUrl is a feed url, then it is either of the form
// feed://example.org/feed.xml or feed:https://example.org/feed.xml.
// Replace feed:// with http:// per the spec, then strip off feed:
// for the second case.
aUrl = aUrl.replace(/^feed:\x2f\x2f/i, "http://");
aUrl = aUrl.replace(/^feed:/i, "");
// Make sure we aren't already subscribed to this feed before we attempt
// to subscribe to it.
if (FeedUtils.feedAlreadyExists(aUrl, aFolder.server))
{
aMsgWindow.statusFeedback.showStatusString(
FeedUtils.strings.GetStringFromName("subscribe-feedAlreadySubscribed"));
return;
}
let itemResource = FeedUtils.rdf.GetResource(aUrl);
let feed = new Feed(itemResource, aFolder.server);
feed.quickMode = feed.server.getBoolValue("quickMode");
feed.options = FeedUtils.getOptionsAcct(feed.server);
// If the root server, create a new folder for the feed. The user must
// want us to add this subscription url to an existing RSS folder.
if (!aFolder.isServer)
feed.folder = aFolder;
FeedUtils.progressNotifier.init(aMsgWindow, true);
FeedUtils.progressNotifier.mNumPendingFeedDownloads++;
feed.download(true, FeedUtils.progressNotifier);
},
updateSubscriptionsDS: function(aFolder, aOrigFolder, aAction)

Просмотреть файл

@ -8,12 +8,11 @@ interface nsIMsgFolder;
interface nsIUrlListener;
interface nsIMsgWindow;
[scriptable, uuid(86e5bd0e-c324-11e3-923a-00269e4fddc1)]
[scriptable, uuid(a74a60ce-7a4d-11e3-b4ca-00269e4fddc1)]
interface nsINewsBlogFeedDownloader : nsISupports
{
void downloadFeed(in nsIMsgFolder aFolder,
in nsIUrlListener aUrlListener,
in bool aIsBiff,
in nsIMsgWindow aMsgWindow);
/**

Просмотреть файл

@ -97,7 +97,8 @@ NS_IMETHODIMP nsRssIncomingServer::SetFlagsOnDefaultMailboxes()
nsresult rv = GetRootFolder(getter_AddRefs(rootFolder));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIMsgLocalMailFolder> localFolder = do_QueryInterface(rootFolder, &rv);
nsCOMPtr<nsIMsgLocalMailFolder> localFolder =
do_QueryInterface(rootFolder, &rv);
NS_ENSURE_SUCCESS(rv, rv);
localFolder->SetFlagsOnDefaultMailboxes(nsMsgFolderFlags::Trash);
@ -110,12 +111,7 @@ NS_IMETHODIMP nsRssIncomingServer::PerformBiff(nsIMsgWindow *aMsgWindow)
nsCOMPtr<nsIMsgFolder> rootRSSFolder;
GetRootMsgFolder(getter_AddRefs(rootRSSFolder));
nsCOMPtr<nsIUrlListener> urlListener = do_QueryInterface(rootRSSFolder);
nsresult rv;
bool isBiff = true;
nsCOMPtr<nsINewsBlogFeedDownloader> rssDownloader =
do_GetService("@mozilla.org/newsblog-feed-downloader;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
rssDownloader->DownloadFeed(rootRSSFolder, urlListener, isBiff, aMsgWindow);
GetNewMail(aMsgWindow, urlListener, rootRSSFolder, nullptr);
return NS_OK;
}
@ -127,11 +123,10 @@ NS_IMETHODIMP nsRssIncomingServer::GetNewMail(nsIMsgWindow *aMsgWindow,
// Pass the selected folder on to the downloader.
NS_ENSURE_ARG_POINTER(aFolder);
nsresult rv;
bool isBiff = false;
nsCOMPtr<nsINewsBlogFeedDownloader> rssDownloader =
do_GetService("@mozilla.org/newsblog-feed-downloader;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
rssDownloader->DownloadFeed(aFolder, aUrlListener, isBiff, aMsgWindow);
rssDownloader->DownloadFeed(aFolder, aUrlListener, aMsgWindow);
return NS_OK;
}