Bug #250247 --> Framework work for News & Blog account settings for Thunderbird.

newsblog.js is now an account manager extension so it can overlay custom panels into the account manager.

Implement "download new articles at startup". Implement Check for new articles every n minutes.

Add a property on nsIMsgIncomingServer that allows the incoming server
to specify the main account manager xul file that is loaded for that server
instead of hard coding am-main.xul in the account manager data source.
This commit is contained in:
scott%scott-macgregor.org 2004-07-10 22:52:48 +00:00
Родитель 765d4043a5
Коммит 5b738a1db5
19 изменённых файлов: 300 добавлений и 140 удалений

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

@ -0,0 +1,35 @@
# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
# ***** 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 News and Blogs Account Settings.
#
# Contributor(s):
# Scott MacGregor <mscott@mozilla.org>
#
# Alternatively, the contents of this file may be used under the terms of
# either of 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 *****
function onInit()
{
// nothing to do here yet...
}

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

@ -0,0 +1,65 @@
<?xml version="1.0"?>
# ***** 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 News and Blogs Account Settings.
#
# Contributor(s):
# Scott MacGregor <mscott@mozilla.org>
#
# Alternatively, the contents of this file may be used under the terms of
# either of 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 *****
<?xml-stylesheet href="chrome://messenger/skin/accountManage.css" type="text/css"?>
<!DOCTYPE page SYSTEM "chrome://messenger-newsblog/locale/am-newsblog.dtd">
<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
class="color-dialog"
onload="parent.onPanelLoaded('am-newsblog.xul');"
orient="vertical">
<script type="application/x-javascript" src="chrome://messenger/content/AccountManager.js"/>
<script type="application/x-javascript" src="chrome://messenger-newsblog/content/am-newsblog.js"/>
<dialogheader title="&newsblogTitle.label;"/>
<vbox align="start">
<hbox align="center">
<checkbox wsm_persist="true" id="server.doBiff" label="&biffStart.label;"
accesskey="&biffStart.accesskey;"
prefattribute="value"
prefstring="mail.server.%serverkey%.check_new_mail"/>
<textbox wsm_persist="true" id="server.biffMinutes" size="3"
preftype="int"
prefstring="mail.server.%serverkey%.check_time"/>
<label id="biffEnd" control="server.biffMinutes" value="&biffEnd.label;"/>
</hbox>
<checkbox wsm_persist="true"
id="server.loginAtStartUp" hidefor="nntp"
label="&loginAtStartup.label;"
accesskey="&loginAtStartup.accesskey;"
prefattribute="value"
prefstring="mail.server.%serverkey%.login_at_startup"/>
</vbox>
</page>

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

@ -24,88 +24,10 @@ var gFzPrefs =
.getService(Components.interfaces.nsIPrefService)
.getBranch("forumzilla.");
var gFzStartupDelay;
try { gFzStartupDelay = gFzPrefs.getIntPref("startup.delay") }
catch(e) { gFzStartupDelay = 2; }
// Record when we started up so we can give up trying certain things
// repetitively after some time.
var gFzStartupTime = new Date();
// Load and cache the subscriptions data source so it's available when we need it.
getSubscriptionsDS();
getItemsDS();
function onLoad() {
// XXX Code to make the News & Blogs toolbar button show up automatically.
// Commented out because it isn't working quite right.
//var toolbar = document.getElementById('mail-bar');
//var currentset = toolbar.getAttribute('currentset');
//if (!currentset.search("button-newsandblogs") == -1)
// toolbar.insertItem('button-newsandblogs', 'button-stop', null, true);
// currentset = currentset.replace(/spring/, "button-newsandblogs,spring");
//if (!currentset.search("button-newsandblogs") == -1)
// currentset += ",button-newsandblogs";
//toolbar.setAttribute('currentset', currentset);
// Make sure the subscriptions and items data source is loaded, since we'll
// need them for everything we do.
var itemsDS =
getItemsDS()
.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
if (!itemsDS.loaded) {
if (new Date() - gFzStartupTime < 30 * 1000) {
window.setTimeout(onLoad, 1000);
return;
}
else
throw("couldn't load the items datasource within thirty seconds");
}
// Make sure the subscriptions data source is loaded, since we'll need it
// for everything we do. If it's not loaded, recheck it every second until
// it's been ten seconds since we started up, then give up.
var ds = getSubscriptionsDS();
var remote = ds.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
if (!remote.loaded) {
if (new Date() - gFzStartupTime < 10 * 1000)
window.setTimeout(onLoad, 1000);
else
throw("couldn't load the subscriptions datasource within ten seconds");
return;
}
var subs = getSubscriptionsFile();
var oldSubs = getOldSubscriptionsFile();
if (oldSubs.exists())
migrateSubscriptions(oldSubs);
getAccount();
ensureDatabasesAreReady();
downloadFeeds();
}
// Wait a few seconds before starting Forumzilla so we don't grab the UI thread
// before the host application has a chance to display itself. Also, starting
// on load used to crash the host app, although that's not a problem anymore.
//addEventListener("load", onLoad, false);
window.setTimeout(onLoad, gFzStartupDelay * 1000);
function downloadFeeds() {
var ds = getSubscriptionsDS();
var feeds = getSubscriptionsList().GetElements();
var feed;
while(feeds.hasMoreElements())
downloadFeed(feeds.getNext());
}
function downloadFeed(feed) {
var ds = getSubscriptionsDS();
new Feed(feed).download();
}
function migrateSubscriptions(oldFile) {
var oldFile2 = new LocalFile(oldFile, MODE_RDONLY | MODE_CREATE);
var subscriptions = oldFile2.read();

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

@ -43,16 +43,12 @@ function doAdd() {
debug("feedProperties.result empty\n");
return;
}
if (!feedProperties.feedLocation)
{
debug("feedProperties.feedLocation empty\n");
return;
}
const DEFAULT_FEED_TITLE = "feed title";
const DEFAULT_FEED_URL = "feed location";
if (!feedProperties.feedName)
feedProperties.feedName = DEFAULT_FEED_TITLE;
var itemResource = rdf.GetResource(feedProperties.feedLocation);
feed = new Feed(itemResource);

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

@ -203,7 +203,7 @@ function getItemsDS() {
var file = getItemsFile();
var url = fileHandler.getURLSpecFromFile(file);
gFzItemsDS = rdf.GetDataSource(url);
gFzItemsDS = rdf.GetDataSourceBlocking(url);
if (!gFzItemsDS)
throw("can't get subscriptions data source");

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

@ -11,10 +11,14 @@ newsblog.jar:
* content/messenger-newsblog/subscriptions.js (content/subscriptions.js)
* content/messenger-newsblog/utils.js (content/utils.js)
* content/messenger-newsblog/feed-properties.xul (content/feed-properties.xul)
* content/messenger-newsblog/feed-properties.js (content/feed-properties.js)
* content/messenger-newsblog/feed-properties.js (content/feed-properties.js)
* content/messenger-newsblog/am-newsblog.xul (content/am-newsblog.xul)
* content/messenger-newsblog/am-newsblog.js (content/am-newsblog.js)
* content/messenger-newsblog/contents.rdf (content/contents.rdf)
newsblog.jar:
locale/en-US/messenger-newsblog/newsblog.dtd (locale/newsblog.dtd)
locale/en-US/messenger-newsblog/feed-properties.dtd (locale/feed-properties.dtd)
locale/en-US/messenger-newsblog/am-newsblog.properties (locale/am-newsblog.properties)
locale/en-US/messenger-newsblog/am-newsblog.dtd (locale/am-newsblog.dtd)
* locale/en-US/messenger-newsblog/contents.rdf (locale/contents.rdf)

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

@ -62,69 +62,121 @@ var nsNewsBlogFeedDownloader =
}
}
var nsNewsBlogAcctMgrExtension =
{
name: "newsblog",
chromePackageName: "messenger-newsblog",
showPanel: function (server)
{
return server.type == "rss";
},
QueryInterface: function(aIID)
{
if (aIID.equals(Components.interfaces.nsIMsgAccountManagerExtension) ||
aIID.equals(Components.interfaces.nsISupports))
return this;
Components.returnCode = Components.results.NS_ERROR_NO_INTERFACE;
return null;
}
}
var nsNewsBlogFeedDownloaderModule =
{
mClassName: "News+Blog Feed Downloader",
mContractID: "@mozilla.org/newsblog-feed-downloader;1",
mClassID: Components.ID("5c124537-adca-4456-b2b5-641ab687d1f6"),
getClassObject: function(aCompMgr, aCID, aIID)
{
if (!aCID.equals(this.mClassID))
throw Components.results.NS_ERROR_NO_INTERFACE;
if (!aIID.equals(Components.interfaces.nsIFactory))
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
return this.mFactory;
for (var key in this.mObjects)
if (aCID.equals(this.mObjects[key].CID))
return this.mObjects[key].factory;
throw Components.results.NS_ERROR_NO_INTERFACE;
},
mObjects:
{
feedDownloader:
{
CID: Components.ID("{5c124537-adca-4456-b2b5-641ab687d1f6}"),
contractID: "@mozilla.org/newsblog-feed-downloader;1",
className: "News+Blog Feed Downloader",
factory:
{
createInstance: function (aOuter, aIID)
{
if (aOuter != null)
throw Components.results.NS_ERROR_NO_AGGREGATION;
if (!aIID.equals(Components.interfaces.nsINewsBlogFeedDownloader) &&
!aIID.equals(Components.interfaces.nsISupports))
throw Components.results.NS_ERROR_INVALID_ARG;
// return the singleton
return nsNewsBlogFeedDownloader.QueryInterface(aIID);
}
} // factory
}, // feed downloader
nsNewsBlogAcctMgrExtension:
{
CID: Components.ID("{E109C05F-D304-4ca5-8C44-6DE1BFAF1F74}"),
contractID: "@mozilla.org/accountmanager/extension;1?name=newsblog",
className: "News+Blog Account Manager Extension",
factory:
{
createInstance: function (aOuter, aIID)
{
if (aOuter != null)
throw Components.results.NS_ERROR_NO_AGGREGATION;
if (!aIID.equals(Components.interfaces.nsIMsgAccountManagerExtension) &&
!aIID.equals(Components.interfaces.nsISupports))
throw Components.results.NS_ERROR_INVALID_ARG;
// return the singleton
return nsNewsBlogAcctMgrExtension.QueryInterface(aIID);
}
} // factory
} // account manager extension
},
registerSelf: function(aCompMgr, aFileSpec, aLocation, aType)
{
{
if (kDebug)
dump("*** Registering nsNewsBlogFeedDownloaderModule (a JavaScript Module)\n");
aCompMgr = aCompMgr.QueryInterface(
Components.interfaces.nsIComponentRegistrar);
aCompMgr.registerFactoryLocation(this.mClassID, this.mClassName,
this.mContractID, aFileSpec, aLocation, aType);
aCompMgr = aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
for (var key in this.mObjects)
{
var obj = this.mObjects[key];
aCompMgr.registerFactoryLocation(obj.CID, obj.className, obj.contractID, aFileSpec, aLocation, aType);
}
// we also need to do special account extension registration
var catman = Components.classes["@mozilla.org/categorymanager;1"].getService(Components.interfaces.nsICategoryManager);
catman.addCategoryEntry("mailnews-accountmanager-extensions",
"newsblog account manager extension",
"@mozilla.org/accountmanager/extension;1?name=newsblog", true, true);
},
unregisterSelf: function(aCompMgr, aFileSpec, aLocation)
{
aCompMgr = aCompMgr.QueryInterface(
Components.interfaces.nsIComponentRegistrar);
aCompMgr.unregisterFactoryLocation(this.mClassID, aFileSpec);
aCompMgr = aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
for (var key in this.mObjects)
{
var obj = this.mObjects[key];
aCompMgr.unregisterFactoryLocation(obj.CID, aFileSpec);
}
// unregister the account manager extension
catman = Components.classes["@mozilla.org/categorymanager;1"].getService(Components.interfaces.nsICategoryManager);
catman.deleteCategoryEntry("mailnews-accountmanager-extensions",
"@mozilla.org/accountmanager/extension;1?name=newsblog", true);
},
canUnload: function(aCompMgr)
{
return true;
},
//////////////////////////////////////////////////////////////////////
//
// mFactory : nsIFactory
//
//////////////////////////////////////////////////////////////////////
mFactory:
{
createInstance: function(aOuter, aIID)
{
if (aOuter != null)
throw Components.results.NS_ERROR_NO_AGGREGATION;
if (!aIID.equals(Components.interfaces.nsINewsBlogFeedDownloader) &&
!aIID.equals(Components.interfaces.nsISupports))
throw Components.results.NS_ERROR_INVALID_ARG;
// return the singleton
return nsNewsBlogFeedDownloader.QueryInterface(aIID);
},
lockFactory: function(aLock)
{
}
}
};

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

@ -0,0 +1,8 @@
<!ENTITY newsblogTitle.label "News &amp; Blog Settings">
<!ENTITY biffStart.label "Check for new articles every ">
<!ENTITY biffStart.accesskey "k">
<!ENTITY biffEnd.label "minutes">
<!ENTITY loginAtStartup.label "Check for new articles at startup">
<!ENTITY loginAtStartup.accesskey "C">

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

@ -0,0 +1,2 @@
## Strings used in the Account Manager
prefPanel-newsblog=Feed Settings

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

@ -105,6 +105,8 @@ interface nsIMsgIncomingServer : nsISupports {
*/
attribute string type;
readonly attribute AString accountManagerChrome;
/**
* the schema for the local mail store, such
* as "mailbox", "imap", or "news"

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

@ -447,19 +447,10 @@ nsMsgAccountManagerDataSource::GetTarget(nsIRDFResource *source,
/* if this is a server, with no identities, then we show a special panel */
nsCOMPtr<nsIMsgIncomingServer> server;
rv = getServerForFolderNode(source, getter_AddRefs(server));
if (server) {
PRBool hasIdentities;
rv = serverHasIdentities(server, &hasIdentities);
if (NS_SUCCEEDED(rv) && !hasIdentities) {
str.AssignLiteral("am-serverwithnoidentities.xul");
}
else {
str.AssignLiteral("am-main.xul");
}
}
else {
if (server)
server->GetAccountManagerChrome(str);
else
str.AssignLiteral("am-main.xul");
}
}
else {
// allow for the accountmanager to be dynamically extended
@ -858,7 +849,6 @@ nsMsgAccountManagerDataSource::serverHasIdentities(nsIMsgIncomingServer* aServer
if (count >0)
*aResult = PR_TRUE;
return NS_OK;
}

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

@ -1085,6 +1085,13 @@ nsMsgIncomingServer::GetLocalStoreType(char **aResult)
return NS_ERROR_UNEXPECTED;
}
NS_IMETHODIMP
nsMsgIncomingServer::GetAccountManagerChrome(nsAString& aResult)
{
aResult = ToNewUnicode(NS_LITERAL_STRING("am-main.xul"));
return NS_OK;
}
NS_IMETHODIMP
nsMsgIncomingServer::Equals(nsIMsgIncomingServer *server, PRBool *_retval)
{

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

@ -44,7 +44,7 @@ interface nsIMsgWindow;
interface nsINewsBlogFeedDownloader : nsISupports
{
void downloadFeed(in string aUrl, in nsIMsgFolder aFolder,
in boolean aQuickMode, in string aTitle,
in boolean aQuickMode, in wstring aTitle,
in nsIUrlListener aUrlListener, in nsIMsgWindow aMsgWindow);
};

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

@ -190,3 +190,10 @@ nsMovemailIncomingServer::GetCanSearchMessages(PRBool *canSearchMessages)
*canSearchMessages = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP
nsMovemailIncomingServer::GetAccountManagerChrome(AString& aResult)
{
aResult = ToNewUnicodeString("am-serverwithnoidentities.xul");
return NS_OK;
}

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

@ -61,6 +61,7 @@ public:
NS_IMETHOD GetIsSecureServer(PRBool *aIsSecureServer);
NS_IMETHOD GetLocalStoreType(char * *type);
NS_IMETHOD GetCanSearchMessages(PRBool *canSearchMessages);
NS_IMETHOD GetAccountManagerChrome(nsAString& aResult);
};

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

@ -77,6 +77,13 @@ nsNoIncomingServer::GetLocalStoreType(char **type)
return NS_OK;
}
NS_IMETHODIMP
nsNoIncomingServer::GetAccountManagerChrome(nsAString& aResult)
{
aResult = ToNewUnicode(NS_LITERAL_STRING("am-serverwithnoidentities.xul"));
return NS_OK;
}
NS_IMETHODIMP
nsNoIncomingServer::SetFlagsOnDefaultMailboxes()
{

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

@ -61,6 +61,7 @@ public:
NS_IMETHOD GetLocalStoreType(char * *type);
NS_IMETHOD GetCanSearchMessages(PRBool *canSearchMessages);
NS_IMETHOD GetServerRequiresPasswordForBiff(PRBool *aServerRequiresPasswordForBiff);
NS_IMETHOD GetAccountManagerChrome(nsAString& aResult);
};

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

@ -19,6 +19,7 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* David Bienvenu <bienvenu@nventure.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
@ -92,6 +93,39 @@ NS_IMETHODIMP nsRssIncomingServer::SetFlagsOnDefaultMailboxes()
return NS_OK;
}
NS_IMETHODIMP nsRssIncomingServer::PerformBiff(nsIMsgWindow *aMsgWindow)
{
// do we need to do anything here besides download articles
// for each feed? I don't think we have a way to check a feed for new articles without actually
// getting the articles. Do we need to SetPerformingBiff to true for this server?
nsresult rv;
nsCOMPtr<nsIMsgFolder> rootRSSFolder;
GetRootMsgFolder(getter_AddRefs(rootRSSFolder));
// enumerate over the RSS folders and ping each one
nsCOMPtr<nsIEnumerator> folderEnumerator;
rv = rootRSSFolder->GetSubFolders(getter_AddRefs(folderEnumerator));
NS_ENSURE_SUCCESS(rv, rv);
nsresult more = folderEnumerator->First();
nsCOMPtr<nsISupports> supports;
nsCOMPtr<nsIUrlListener> urlListener;
while (NS_SUCCEEDED(more))
{
rv = folderEnumerator->CurrentItem(getter_AddRefs(supports));
nsCOMPtr<nsIMsgFolder> rssFolder = do_QueryInterface(supports);
if (rssFolder)
{
urlListener = do_QueryInterface(rssFolder);
GetNewMail(aMsgWindow, urlListener, rssFolder, nsnull);
}
more = folderEnumerator->Next();
}
return NS_OK;
}
NS_IMETHODIMP nsRssIncomingServer::GetNewMail(nsIMsgWindow *aMsgWindow, nsIUrlListener *aUrlListener, nsIMsgFolder *aFolder, nsIURI **_retval)
{
NS_ENSURE_ARG_POINTER(aFolder);
@ -113,10 +147,13 @@ NS_IMETHODIMP nsRssIncomingServer::GetNewMail(nsIMsgWindow *aMsgWindow, nsIUrlLi
if (folderInfo)
{
nsXPIDLCString url;
nsXPIDLString folderName;
aFolder->GetName(getter_Copies(folderName));
folderInfo->GetCharPtrProperty("feedUrl", getter_Copies(url));
rv = rssDownloader->DownloadFeed(url.get(),
aFolder, PR_FALSE, "Slashdot", aUrlListener, aMsgWindow);
if (!url.IsEmpty())
rv = rssDownloader->DownloadFeed(url.get(),
aFolder, PR_FALSE, folderName.get(), aUrlListener, aMsgWindow);
}
}
}
@ -129,3 +166,23 @@ NS_IMETHODIMP nsRssIncomingServer::GetLocalStoreType(char **type)
*type = strdup("mailbox");
return NS_OK;
}
NS_IMETHODIMP nsRssIncomingServer::GetAccountManagerChrome(nsAString& aResult)
{
aResult = ToNewUnicode(NS_LITERAL_STRING("am-newsblog.xul"));
return NS_OK;
}
NS_IMETHODIMP nsRssIncomingServer::GetOfflineSupportLevel(PRInt32 *aSupportLevel)
{
NS_ENSURE_ARG_POINTER(aSupportLevel);
*aSupportLevel = OFFLINE_SUPPORT_LEVEL_NONE;
return NS_OK;
}
NS_IMETHODIMP nsRssIncomingServer::GetSupportsDiskSpace(PRBool *aSupportsDiskSpace)
{
NS_ENSURE_ARG_POINTER(aSupportsDiskSpace);
*aSupportsDiskSpace = PR_FALSE;
return NS_OK;
}

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

@ -53,6 +53,10 @@ public:
NS_DECL_NSILOCALMAILINCOMINGSERVER
NS_IMETHOD GetLocalStoreType(char **);
NS_IMETHOD GetOfflineSupportLevel(PRInt32 *aSupportLevel);
NS_IMETHOD GetSupportsDiskSpace(PRBool *aSupportsDiskSpace);
NS_IMETHOD GetAccountManagerChrome(nsAString& aResult);
NS_IMETHOD PerformBiff(nsIMsgWindow *aMsgWindow);
nsRssIncomingServer();
virtual ~nsRssIncomingServer();