Compare commits
107 Commits
alecf_fast
...
CacheInteg
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
22c40d96b2 | ||
|
|
06a79b2069 | ||
|
|
ebc4face0d | ||
|
|
150696bb86 | ||
|
|
683045595b | ||
|
|
7f09538b93 | ||
|
|
bb364ef512 | ||
|
|
7c96c92a19 | ||
|
|
a6defdef4c | ||
|
|
76159a2caf | ||
|
|
1988cb05b5 | ||
|
|
dd8c6b3bed | ||
|
|
bc64749366 | ||
|
|
2e9287bd58 | ||
|
|
0f2274a140 | ||
|
|
957fa10cac | ||
|
|
e603146886 | ||
|
|
cb698a0df1 | ||
|
|
1b918d9ef0 | ||
|
|
6407144c9f | ||
|
|
2ed563a178 | ||
|
|
4becc0b508 | ||
|
|
7d5427ea31 | ||
|
|
99904bcc48 | ||
|
|
bcb56c9593 | ||
|
|
f18bc8e6cd | ||
|
|
7d14c5669a | ||
|
|
c0dd3df02e | ||
|
|
e5cc84978f | ||
|
|
5694537330 | ||
|
|
297c5ceba3 | ||
|
|
e0311312f7 | ||
|
|
cf3dc77b02 | ||
|
|
dd2506a737 | ||
|
|
b1bee1f21c | ||
|
|
48ecc5625b | ||
|
|
1b791685e6 | ||
|
|
dc94d1d6e2 | ||
|
|
f5b437ade3 | ||
|
|
8c0b4b3e4a | ||
|
|
fb640ab144 | ||
|
|
106e263b33 | ||
|
|
85045a8552 | ||
|
|
a2279be132 | ||
|
|
0ce702d402 | ||
|
|
f14d03cd67 | ||
|
|
b91343fdf6 | ||
|
|
2c517489b5 | ||
|
|
ae57da58eb | ||
|
|
8d4586dd65 | ||
|
|
9b473ad9be | ||
|
|
2ad227a994 | ||
|
|
94d8da33c1 | ||
|
|
81c05809fd | ||
|
|
e30547b2b2 | ||
|
|
257f9cfaaa | ||
|
|
96e2654e43 | ||
|
|
3b023433be | ||
|
|
1b89716afe | ||
|
|
ad02058877 | ||
|
|
fa8a3196e7 | ||
|
|
5c2c543e58 | ||
|
|
c588721cc0 | ||
|
|
0b049b17ba | ||
|
|
854ef4631d | ||
|
|
051c558653 | ||
|
|
37a04adb09 | ||
|
|
c823c04b45 | ||
|
|
03cbd000eb | ||
|
|
a91e91a1c7 | ||
|
|
be7a5a48b6 | ||
|
|
b2bc7468e8 | ||
|
|
9692dfd994 | ||
|
|
f3edd4cfb5 | ||
|
|
33403345c1 | ||
|
|
20c850de23 | ||
|
|
e8b619cd02 | ||
|
|
eed396bb92 | ||
|
|
41d44c070b | ||
|
|
698ba42268 | ||
|
|
1a0fd23991 | ||
|
|
67dded330b | ||
|
|
936ff4777a | ||
|
|
96c55e42f7 | ||
|
|
82fa0cf06a | ||
|
|
98c8285334 | ||
|
|
bad4b683f4 | ||
|
|
cb5269a28a | ||
|
|
74712f3635 | ||
|
|
9f8ea739db | ||
|
|
97a10dd7c6 | ||
|
|
85a132fac0 | ||
|
|
e594eee877 | ||
|
|
9148eee3d6 | ||
|
|
b5989a8382 | ||
|
|
2b861f60d9 | ||
|
|
87db050b37 | ||
|
|
ffe483cf95 | ||
|
|
52aa17a1c3 | ||
|
|
5fdb3aa69e | ||
|
|
8cae473bc0 | ||
|
|
0719303755 | ||
|
|
90d3e40858 | ||
|
|
c792b2d35c | ||
|
|
7a4377d840 | ||
|
|
a5fa416010 | ||
|
|
49d00db5e2 |
@@ -1,298 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "msgCore.h" // for pre-compiled headers
|
||||
//#include "nsIMsgIdentity.h"
|
||||
#include "nsIMsgAccountManager.h"
|
||||
//#include "nsIPop3IncomingServer.h"
|
||||
#include "nsMsgMailSession.h"
|
||||
#include "nsMsgLocalCID.h"
|
||||
#include "nsMsgBaseCID.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsMsgFolderCache.h"
|
||||
#include "nsIFileLocator.h"
|
||||
#include "nsFileLocations.h"
|
||||
#include "nsIMsgStatusFeedback.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsMsgMailSession, nsCOMTypeInfo<nsIMsgMailSession>::GetIID());
|
||||
|
||||
static NS_DEFINE_CID(kMsgAccountManagerCID, NS_MSGACCOUNTMANAGER_CID);
|
||||
static NS_DEFINE_CID(kMsgFolderCacheCID, NS_MSGFOLDERCACHE_CID);
|
||||
static NS_DEFINE_IID(kIFileLocatorIID, NS_IFILELOCATOR_IID);
|
||||
static NS_DEFINE_CID(kFileLocatorCID, NS_FILELOCATOR_CID);
|
||||
|
||||
//static NS_DEFINE_CID(kMsgIdentityCID, NS_MSGIDENTITY_CID);
|
||||
//static NS_DEFINE_CID(kPop3IncomingServerCID, NS_POP3INCOMINGSERVER_CID);
|
||||
//static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
|
||||
|
||||
|
||||
nsMsgMailSession::nsMsgMailSession():
|
||||
mRefCnt(0),
|
||||
m_accountManager(0),
|
||||
m_msgFolderCache(0)
|
||||
{
|
||||
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
|
||||
nsMsgMailSession::~nsMsgMailSession()
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
nsresult nsMsgMailSession::Init()
|
||||
{
|
||||
nsresult rv = NS_NewISupportsArray(getter_AddRefs(mListeners));
|
||||
|
||||
return rv;
|
||||
|
||||
}
|
||||
|
||||
nsresult nsMsgMailSession::Shutdown()
|
||||
{
|
||||
if(m_accountManager)
|
||||
{
|
||||
if (m_msgFolderCache)
|
||||
m_accountManager->WriteToFolderCache(m_msgFolderCache);
|
||||
m_accountManager->CloseCachedConnections();
|
||||
m_accountManager->UnloadAccounts();
|
||||
}
|
||||
|
||||
NS_IF_RELEASE(m_accountManager);
|
||||
|
||||
NS_IF_RELEASE(m_msgFolderCache);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIMsgMailSession
|
||||
nsresult nsMsgMailSession::GetCurrentIdentity(nsIMsgIdentity ** aIdentity)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIMsgAccountManager> accountManager;
|
||||
rv = GetAccountManager(getter_AddRefs(accountManager));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIMsgAccount> defaultAccount;
|
||||
rv = accountManager->GetDefaultAccount(getter_AddRefs(defaultAccount));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = defaultAccount->GetDefaultIdentity(aIdentity);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
NS_ADDREF(*aIdentity);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMsgMailSession::GetCurrentServer(nsIMsgIncomingServer ** aServer)
|
||||
{
|
||||
nsresult rv=NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIMsgAccountManager> accountManager;
|
||||
rv = GetAccountManager(getter_AddRefs(accountManager));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIMsgAccount> defaultAccount;
|
||||
rv = accountManager->GetDefaultAccount(getter_AddRefs(defaultAccount));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
//if successful aServer will be addref'd by GetIncomingServer
|
||||
rv = defaultAccount->GetIncomingServer(aServer);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMsgMailSession::GetAccountManager(nsIMsgAccountManager* *aAM)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aAM);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
NS_WITH_SERVICE(nsIMsgAccountManager, accountManager, kMsgAccountManagerCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
accountManager->LoadAccounts();
|
||||
|
||||
*aAM = accountManager;
|
||||
NS_IF_ADDREF(*aAM);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsMsgMailSession::GetFolderCache(nsIMsgFolderCache* *aFolderCache)
|
||||
{
|
||||
if (!aFolderCache) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (!m_msgFolderCache)
|
||||
{
|
||||
rv = nsComponentManager::CreateInstance(kMsgFolderCacheCID,
|
||||
NULL,
|
||||
nsCOMTypeInfo<nsIMsgFolderCache>::GetIID(),
|
||||
(void **)&m_msgFolderCache);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr <nsIFileSpec> cacheFile;
|
||||
NS_WITH_SERVICE(nsIFileLocator, locator, kFileLocatorCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = locator->GetFileLocation(nsSpecialFileSpec::App_MessengerFolderCache50, getter_AddRefs(cacheFile));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
m_msgFolderCache->Init(cacheFile);
|
||||
|
||||
}
|
||||
|
||||
*aFolderCache = m_msgFolderCache;
|
||||
NS_IF_ADDREF(*aFolderCache);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMsgMailSession::GetTemporaryMsgStatusFeedback(nsIMsgStatusFeedback* *aMsgStatusFeedback)
|
||||
{
|
||||
if (!aMsgStatusFeedback) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*aMsgStatusFeedback = m_temporaryMsgStatusFeedback;
|
||||
NS_IF_ADDREF(*aMsgStatusFeedback);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsMsgMailSession::SetTemporaryMsgStatusFeedback(nsIMsgStatusFeedback* aMsgStatusFeedback)
|
||||
{
|
||||
m_temporaryMsgStatusFeedback = do_QueryInterface(aMsgStatusFeedback);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMsgMailSession::AddFolderListener(nsIFolderListener * listener)
|
||||
{
|
||||
mListeners->AppendElement(listener);
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailSession::RemoveFolderListener(nsIFolderListener * listener)
|
||||
{
|
||||
mListeners->RemoveElement(listener);
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgMailSession::NotifyFolderItemPropertyChanged(nsISupports *item,
|
||||
const char *property,
|
||||
const char* oldValue,
|
||||
const char* newValue)
|
||||
{
|
||||
nsresult rv;
|
||||
PRUint32 count;
|
||||
rv = mListeners->Count(&count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
|
||||
for(PRUint32 i = 0; i < count; i++)
|
||||
{
|
||||
nsCOMPtr<nsIFolderListener> listener = getter_AddRefs((nsIFolderListener*)mListeners->ElementAt(i));
|
||||
listener->OnItemPropertyChanged(item, property, oldValue, newValue);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgMailSession::NotifyFolderItemPropertyFlagChanged(nsISupports *item,
|
||||
const char *property,
|
||||
PRUint32 oldValue,
|
||||
PRUint32 newValue)
|
||||
{
|
||||
nsresult rv;
|
||||
PRUint32 count;
|
||||
rv = mListeners->Count(&count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
|
||||
for(PRUint32 i = 0; i < count; i++)
|
||||
{
|
||||
nsCOMPtr<nsIFolderListener> listener = getter_AddRefs((nsIFolderListener*)mListeners->ElementAt(i));
|
||||
listener->OnItemPropertyFlagChanged(item, property, oldValue, newValue);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailSession::NotifyFolderItemAdded(nsIFolder *folder, nsISupports *item)
|
||||
{
|
||||
nsresult rv;
|
||||
PRUint32 count;
|
||||
rv = mListeners->Count(&count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
|
||||
for(PRUint32 i = 0; i < count; i++)
|
||||
{
|
||||
nsCOMPtr<nsIFolderListener> listener = getter_AddRefs((nsIFolderListener*)mListeners->ElementAt(i));
|
||||
listener->OnItemAdded(folder, item);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailSession::NotifyFolderItemDeleted(nsIFolder *folder, nsISupports *item)
|
||||
{
|
||||
nsresult rv;
|
||||
PRUint32 count;
|
||||
rv = mListeners->Count(&count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
|
||||
for(PRUint32 i = 0; i < count; i++)
|
||||
{
|
||||
nsCOMPtr<nsIFolderListener> listener = getter_AddRefs((nsIFolderListener*)mListeners->ElementAt(i));
|
||||
listener->OnItemRemoved(folder, item);
|
||||
}
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailSession::NotifyFolderLoaded(nsIFolder *folder)
|
||||
{
|
||||
|
||||
nsresult rv;
|
||||
PRUint32 count;
|
||||
rv = mListeners->Count(&count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
|
||||
for(PRUint32 i = 0; i < count; i++)
|
||||
{
|
||||
nsCOMPtr<nsIFolderListener> listener = getter_AddRefs((nsIFolderListener*)mListeners->ElementAt(i));
|
||||
listener->OnFolderLoaded(folder);
|
||||
}
|
||||
return NS_OK;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
@@ -1,21 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "MacPrefix.h"
|
||||
@@ -1,21 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "MacPrefix_debug.h"
|
||||
@@ -1,87 +0,0 @@
|
||||
#!nmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH=..\..\..
|
||||
MODULE= msgbsutl
|
||||
|
||||
include <$(DEPTH)\config\config.mak>
|
||||
|
||||
################################################################################
|
||||
## exports
|
||||
|
||||
EXPORTS= \
|
||||
nsMsgLineBuffer.h \
|
||||
nsMsgGroupRecord.h \
|
||||
nsUInt32Array.h \
|
||||
nsMsgKeySet.h \
|
||||
nsMsgFolder.h \
|
||||
nsMsgDBFolder.h \
|
||||
nsLocalFolderSummarySpec.h \
|
||||
nsMsgIdentity.h \
|
||||
nsMsgIncomingServer.h \
|
||||
nsNewsSummarySpec.h \
|
||||
nsMsgUtils.h \
|
||||
nsMessage.h \
|
||||
nsMsgProtocol.h \
|
||||
nsMsgMailNewsUrl.h \
|
||||
nsMsgTxn.h \
|
||||
nsMsgI18N.h \
|
||||
$(NULL)
|
||||
|
||||
################################################################################
|
||||
## library
|
||||
|
||||
LIBNAME = .\$(OBJDIR)\msgbsutl
|
||||
DLL = $(LIBNAME).dll
|
||||
|
||||
DEFINES=-D_IMPL_NS_MSG_BASE
|
||||
|
||||
LCFLAGS = \
|
||||
$(LCFLAGS) \
|
||||
$(DEFINES) \
|
||||
$(NULL)
|
||||
|
||||
CPP_OBJS= \
|
||||
.\$(OBJDIR)\nsMsgGroupRecord.obj \
|
||||
.\$(OBJDIR)\nsMsgLineBuffer.obj \
|
||||
.\$(OBJDIR)\nsUInt32Array.obj \
|
||||
.\$(OBJDIR)\nsMsgKeySet.obj \
|
||||
.\$(OBJDIR)\nsMsgFolder.obj \
|
||||
.\$(OBJDIR)\nsMsgDBFolder.obj \
|
||||
.\$(OBJDIR)\nsLocalFolderSummarySpec.obj \
|
||||
.\$(OBJDIR)\nsMsgIdentity.obj \
|
||||
.\$(OBJDIR)\nsMsgIncomingServer.obj \
|
||||
.\$(OBJDIR)\nsNewsSummarySpec.obj \
|
||||
.\$(OBJDIR)\nsMsgUtils.obj \
|
||||
.\$(OBJDIR)\nsMessage.obj \
|
||||
.\$(OBJDIR)\nsMsgProtocol.obj \
|
||||
.\$(OBJDIR)\nsMsgMailNewsUrl.obj \
|
||||
.\$(OBJDIR)\nsMsgTxn.obj \
|
||||
.\$(OBJDIR)\nsMsgI18N.obj \
|
||||
$(NULL)
|
||||
|
||||
LLIBS= \
|
||||
$(DIST)\lib\xpcom.lib \
|
||||
$(DIST)\lib\rdfutil_s.lib \
|
||||
$(LIBNSPR) \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)/config/rules.mak>
|
||||
|
||||
libs:: $(DLL)
|
||||
$(MAKE_INSTALL) $(LIBNAME).$(DLL_SUFFIX) $(DIST)\bin
|
||||
$(MAKE_INSTALL) $(LIBNAME).$(LIB_SUFFIX) $(DIST)\lib
|
||||
@@ -1,76 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsLocalFolderSummarySpec.h"
|
||||
#include "plstr.h"
|
||||
#include "nsString.h"
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsLocalFolderSummarySpec);
|
||||
|
||||
nsLocalFolderSummarySpec::~nsLocalFolderSummarySpec()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsLocalFolderSummarySpec);
|
||||
|
||||
}
|
||||
|
||||
nsLocalFolderSummarySpec::nsLocalFolderSummarySpec()
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsLocalFolderSummarySpec);
|
||||
}
|
||||
|
||||
nsLocalFolderSummarySpec::nsLocalFolderSummarySpec(const char *folderPath, PRBool create)
|
||||
: nsFileSpec(folderPath, create)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsLocalFolderSummarySpec);
|
||||
CreateSummaryFileName();
|
||||
}
|
||||
|
||||
nsLocalFolderSummarySpec::nsLocalFolderSummarySpec(const nsFileSpec& inFolderPath)
|
||||
: nsFileSpec(inFolderPath)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsLocalFolderSummarySpec);
|
||||
CreateSummaryFileName();
|
||||
}
|
||||
|
||||
nsLocalFolderSummarySpec::nsLocalFolderSummarySpec(const nsFilePath &inFolderPath, PRBool create) : nsFileSpec(inFolderPath, create)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsLocalFolderSummarySpec);
|
||||
CreateSummaryFileName();
|
||||
}
|
||||
|
||||
void nsLocalFolderSummarySpec::SetFolderName(const char *folderPath)
|
||||
{
|
||||
*this = folderPath;
|
||||
}
|
||||
|
||||
void nsLocalFolderSummarySpec:: CreateSummaryFileName()
|
||||
{
|
||||
char *leafName = GetLeafName();
|
||||
|
||||
nsString fullLeafName(leafName);
|
||||
|
||||
// Append .msf (msg summary file) this is what windows will want.
|
||||
// Mac and Unix can decide for themselves.
|
||||
|
||||
fullLeafName += ".msf"; // message summary file
|
||||
char *cLeafName = fullLeafName.ToNewCString();
|
||||
SetLeafName(cLeafName);
|
||||
nsAllocator::Free(cLeafName);
|
||||
PL_strfree(leafName);
|
||||
}
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _nsLocalFolderSummarySpec_H
|
||||
#define _nsLocalFolderSummarySpec_H
|
||||
|
||||
#include "msgCore.h"
|
||||
#include "nsFileSpec.h"
|
||||
|
||||
// Class to name a summary file for a local mail folder,
|
||||
// given a full folder file spec. For windows, this just means tacking .msf on the end.
|
||||
// For Unix, it might mean something like putting a '.' on the front and .msgsummary on the end.
|
||||
// Note this class expects the invoking code to fully specify the folder path.
|
||||
// This class does NOT prepend the local folder directory, or put .sbd on the containing
|
||||
// directory names.
|
||||
class NS_MSG_BASE nsLocalFolderSummarySpec : public nsFileSpec
|
||||
{
|
||||
public:
|
||||
virtual ~nsLocalFolderSummarySpec();
|
||||
nsLocalFolderSummarySpec();
|
||||
nsLocalFolderSummarySpec(const char *folderPath, PRBool create = PR_FALSE);
|
||||
nsLocalFolderSummarySpec(const nsFileSpec& inFolderPath);
|
||||
nsLocalFolderSummarySpec(const nsFilePath &inFolderPath, PRBool create = PR_FALSE);
|
||||
void SetFolderName(const char *folderPath);
|
||||
|
||||
protected:
|
||||
void CreateSummaryFileName();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,509 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "msgCore.h" // precompiled header...
|
||||
#include "nsMessage.h"
|
||||
#include "nsIMsgFolder.h"
|
||||
|
||||
|
||||
nsMessage::nsMessage(void)
|
||||
: nsRDFResource(), mFolder(nsnull)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
nsMessage::~nsMessage(void)
|
||||
{
|
||||
//Member variables are either nsCOMPtr's or ptrs we don't want to own.
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsMessage, nsRDFResource)
|
||||
NS_IMPL_RELEASE_INHERITED(nsMessage, nsRDFResource)
|
||||
|
||||
NS_IMETHODIMP nsMessage::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
||||
{
|
||||
if (!aInstancePtr) return NS_ERROR_NULL_POINTER;
|
||||
*aInstancePtr = nsnull;
|
||||
if (aIID.Equals(nsCOMTypeInfo<nsIMessage>::GetIID()) || aIID.Equals(nsCOMTypeInfo<nsIDBMessage>::GetIID()))
|
||||
{
|
||||
*aInstancePtr = NS_STATIC_CAST(nsIDBMessage*, this);
|
||||
}
|
||||
if(*aInstancePtr)
|
||||
{
|
||||
AddRef();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return nsRDFResource::QueryInterface(aIID, aInstancePtr);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMessage::Init(const char* aURI)
|
||||
{
|
||||
|
||||
return nsRDFResource::Init(aURI);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetProperty(const char *propertyName, nsString &resultProperty)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetProperty(propertyName, resultProperty);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetProperty(const char *propertyName, nsString &propertyStr)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetProperty(propertyName, propertyStr);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetUint32Property(const char *propertyName, PRUint32 *pResult)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetUint32Property(propertyName, pResult);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetUint32Property(const char *propertyName, PRUint32 propertyVal)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetUint32Property(propertyName, propertyVal);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetNumReferences(PRUint16 *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetNumReferences(result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetStringReference(PRInt32 refNum, nsCString &resultReference)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetStringReference(refNum, resultReference);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetDate(PRTime *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetDate(result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetDate(PRTime date)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetDate(date);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetMessageId(const char *messageId)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetMessageId(messageId);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetReferences(const char *references)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetReferences(references);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetCCList(const char *ccList)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetCCList(ccList);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetRecipients(const char *recipients, PRBool recipientsIsNewsgroup)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetRecipients(recipients, recipientsIsNewsgroup);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetRecipientsArray(const char *names, const char *addresses, PRUint32 numAddresses)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetRecipientsArray(names, addresses, numAddresses);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetCCListArray(const char *names, const char *addresses, PRUint32 numAddresses)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetCCListArray(names, addresses, numAddresses);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetAuthor(const char *author)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetAuthor(author);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetSubject(const char *subject)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetSubject(subject);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetStatusOffset(PRUint32 statusOffset)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetStatusOffset(statusOffset);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetAuthor(nsString *resultAuthor)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetAuthor(resultAuthor);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetSubject(nsString *resultSubject)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetSubject(resultSubject);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetRecipients(nsString *resultRecipients)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetRecipients(resultRecipients);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetCCList(nsString *ccList)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetCCList(ccList);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetMessageId(nsCString *resultMessageId)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetMessageId(resultMessageId);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetMime2DecodedAuthor(nsString *resultAuthor)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetMime2DecodedAuthor(resultAuthor);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetMime2DecodedSubject(nsString *resultSubject)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetMime2DecodedSubject(resultSubject);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetMime2DecodedRecipients(nsString *resultRecipients)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetMime2DecodedRecipients(resultRecipients);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetAuthorCollationKey(nsString *resultAuthor)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetAuthorCollationKey(resultAuthor);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetSubjectCollationKey(nsString *resultSubject)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetSubjectCollationKey(resultSubject);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetRecipientsCollationKey(nsString *resultRecipients)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetRecipientsCollationKey(resultRecipients);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetFlags(PRUint32 *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetFlags(result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetFlags(PRUint32 flags)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetFlags(flags);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::OrFlags(PRUint32 flags, PRUint32 *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->OrFlags(flags, result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::AndFlags(PRUint32 flags, PRUint32 *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->AndFlags(flags, result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::MarkRead(PRBool bRead)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->MarkRead(bRead);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::MarkFlagged(PRBool bFlagged)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->MarkFlagged(bFlagged);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetMessageKey(nsMsgKey *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetMessageKey(result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetThreadId(nsMsgKey *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetThreadId(result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetThreadId(nsMsgKey inKey)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetThreadId(inKey);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetMessageKey(nsMsgKey inKey)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetMessageKey(inKey);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetMessageSize(PRUint32 *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetMessageSize(result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetLineCount(PRUint32 *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetLineCount(result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetMessageSize(PRUint32 messageSize)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetMessageSize(messageSize);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetLineCount(PRUint32 lineCount)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetLineCount(lineCount);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetPriority(nsMsgPriority priority)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetPriority(priority);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetPriority(const char *priority)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetPriority(priority);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetPriority(nsMsgPriority *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetPriority(result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetMessageOffset(PRUint32 *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetMessageOffset(result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetStatusOffset(PRUint32 *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetStatusOffset(result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetCharSet(nsString *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetCharSet(result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetThreadParent(nsMsgKey *result)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->GetThreadParent(result);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetThreadParent(nsMsgKey inKey)
|
||||
{
|
||||
if(mMsgHdr)
|
||||
return mMsgHdr->SetThreadParent(inKey);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetMsgFolder(nsIMsgFolder **folder)
|
||||
{
|
||||
if(!folder)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
*folder = mFolder;
|
||||
if(mFolder)
|
||||
{
|
||||
NS_ADDREF(mFolder);
|
||||
return NS_OK;
|
||||
}
|
||||
else
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetMsgFolder(nsIMsgFolder *folder)
|
||||
{
|
||||
mFolder = folder;
|
||||
//We don't want to own folder, so don't AddRef
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMessage::SetMsgDBHdr(nsIMsgDBHdr *hdr)
|
||||
{
|
||||
mMsgHdr = dont_QueryInterface(hdr);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessage::GetMsgDBHdr(nsIMsgDBHdr **hdr)
|
||||
{
|
||||
*hdr = mMsgHdr;
|
||||
if(*hdr)
|
||||
{
|
||||
NS_ADDREF(*hdr);
|
||||
return NS_OK;
|
||||
}
|
||||
else
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/********************************************************************************************************
|
||||
|
||||
Interface for representing Messenger folders.
|
||||
|
||||
*********************************************************************************************************/
|
||||
|
||||
#ifndef nsMessage_h__
|
||||
#define nsMessage_h__
|
||||
|
||||
#include "msgCore.h"
|
||||
#include "nsIMessage.h" /* include the interface we are going to support */
|
||||
#include "nsRDFResource.h"
|
||||
#include "nsIMsgHdr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
|
||||
class NS_MSG_BASE nsMessage: public nsRDFResource, public nsIDBMessage
|
||||
{
|
||||
public:
|
||||
nsMessage(void);
|
||||
virtual ~nsMessage(void);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIMESSAGE
|
||||
NS_DECL_NSIDBMESSAGE
|
||||
|
||||
NS_IMETHOD Init(const char *aURI);
|
||||
//nsIMsgHdr
|
||||
NS_IMETHOD GetProperty(const char *propertyName, nsString &resultProperty);
|
||||
NS_IMETHOD SetProperty(const char *propertyName, nsString &propertyStr);
|
||||
NS_IMETHOD GetUint32Property(const char *propertyName, PRUint32 *pResult);
|
||||
NS_IMETHOD SetUint32Property(const char *propertyName, PRUint32 propertyVal);
|
||||
NS_IMETHOD GetNumReferences(PRUint16 *result);
|
||||
NS_IMETHOD GetStringReference(PRInt32 refNum, nsCString &resultReference);
|
||||
NS_IMETHOD GetDate(PRTime *result);
|
||||
NS_IMETHOD SetDate(PRTime date);
|
||||
NS_IMETHOD SetMessageId(const char *messageId);
|
||||
NS_IMETHOD SetReferences(const char *references);
|
||||
NS_IMETHOD SetCCList(const char *ccList);
|
||||
NS_IMETHOD SetRecipients(const char *recipients, PRBool recipientsIsNewsgroup);
|
||||
NS_IMETHOD SetRecipientsArray(const char *names, const char *addresses, PRUint32 numAddresses);
|
||||
NS_IMETHOD SetCCListArray(const char *names, const char *addresses, PRUint32 numAddresses);
|
||||
NS_IMETHOD SetAuthor(const char *author);
|
||||
NS_IMETHOD SetSubject(const char *subject);
|
||||
NS_IMETHOD SetStatusOffset(PRUint32 statusOffset);
|
||||
|
||||
NS_IMETHOD GetAuthor(nsString *resultAuthor);
|
||||
NS_IMETHOD GetSubject(nsString *resultSubject);
|
||||
NS_IMETHOD GetRecipients(nsString *resultRecipients);
|
||||
NS_IMETHOD GetCCList(nsString *ccList);
|
||||
NS_IMETHOD GetMessageId(nsCString *resultMessageId);
|
||||
|
||||
NS_IMETHOD GetMime2DecodedAuthor(nsString *resultAuthor);
|
||||
NS_IMETHOD GetMime2DecodedSubject(nsString *resultSubject);
|
||||
NS_IMETHOD GetMime2DecodedRecipients(nsString *resultRecipients);
|
||||
|
||||
NS_IMETHOD GetAuthorCollationKey(nsString *resultAuthor);
|
||||
NS_IMETHOD GetSubjectCollationKey(nsString *resultSubject);
|
||||
NS_IMETHOD GetRecipientsCollationKey(nsString *resultRecipients);
|
||||
|
||||
// flag handling routines
|
||||
NS_IMETHOD GetFlags(PRUint32 *result);
|
||||
NS_IMETHOD SetFlags(PRUint32 flags);
|
||||
NS_IMETHOD OrFlags(PRUint32 flags, PRUint32 *result);
|
||||
NS_IMETHOD AndFlags(PRUint32 flags, PRUint32 *result);
|
||||
|
||||
// Mark message routines
|
||||
NS_IMETHOD MarkRead(PRBool bRead);
|
||||
NS_IMETHOD MarkFlagged(PRBool bFlagged);
|
||||
|
||||
NS_IMETHOD GetMessageKey(nsMsgKey *result);
|
||||
NS_IMETHOD GetThreadId(nsMsgKey *result);
|
||||
NS_IMETHOD SetThreadId(nsMsgKey inKey);
|
||||
NS_IMETHOD SetMessageKey(nsMsgKey inKey);
|
||||
NS_IMETHOD GetMessageSize(PRUint32 *result);
|
||||
NS_IMETHOD SetMessageSize(PRUint32 messageSize);
|
||||
NS_IMETHOD GetLineCount(PRUint32 *result);
|
||||
NS_IMETHOD SetLineCount(PRUint32 lineCount);
|
||||
NS_IMETHOD SetPriority(nsMsgPriority priority);
|
||||
NS_IMETHOD SetPriority(const char *priority);
|
||||
NS_IMETHOD GetMessageOffset(PRUint32 *result);
|
||||
NS_IMETHOD GetStatusOffset(PRUint32 *result);
|
||||
NS_IMETHOD GetCharSet(nsString *result);
|
||||
NS_IMETHOD GetPriority(nsMsgPriority *result);
|
||||
NS_IMETHOD GetThreadParent(nsMsgKey *result);
|
||||
NS_IMETHOD SetThreadParent(nsMsgKey inKey);
|
||||
|
||||
protected:
|
||||
nsIMsgFolder *mFolder;
|
||||
nsCOMPtr<nsIMsgDBHdr> mMsgHdr;
|
||||
|
||||
};
|
||||
|
||||
#endif //nsMessage_h__
|
||||
|
||||
@@ -1,530 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "msgCore.h"
|
||||
#include "nsIMessage.h"
|
||||
#include "nsMsgDBFolder.h"
|
||||
#include "nsMsgFolderFlags.h"
|
||||
#include "nsIPref.h"
|
||||
#include "nsIMsgFolderCache.h"
|
||||
#include "nsIMsgFolderCacheElement.h"
|
||||
#include "nsIMsgMailSession.h"
|
||||
#include "nsMsgBaseCID.h"
|
||||
#include "nsIMsgMailNewsUrl.h"
|
||||
|
||||
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
|
||||
static NS_DEFINE_CID(kMsgMailSessionCID, NS_MSGMAILSESSION_CID);
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsMsgDBFolder, nsMsgFolder)
|
||||
NS_IMPL_RELEASE_INHERITED(nsMsgDBFolder, nsMsgFolder)
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
||||
{
|
||||
if (!aInstancePtr) return NS_ERROR_NULL_POINTER;
|
||||
*aInstancePtr = nsnull;
|
||||
if (aIID.Equals(nsCOMTypeInfo<nsIDBChangeListener>::GetIID()))
|
||||
{
|
||||
*aInstancePtr = NS_STATIC_CAST(nsIDBChangeListener*, this);
|
||||
}
|
||||
else if (aIID.Equals(nsCOMTypeInfo<nsIUrlListener>::GetIID()))
|
||||
{
|
||||
*aInstancePtr = NS_STATIC_CAST(nsIUrlListener*, this);
|
||||
}
|
||||
|
||||
if(*aInstancePtr)
|
||||
{
|
||||
AddRef();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return nsRDFResource::QueryInterface(aIID, aInstancePtr);
|
||||
}
|
||||
|
||||
nsMsgDBFolder::nsMsgDBFolder(void)
|
||||
: mCharset(""), mAddListener(PR_TRUE)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
nsMsgDBFolder::~nsMsgDBFolder(void)
|
||||
{
|
||||
if(mDatabase)
|
||||
{
|
||||
mDatabase->RemoveListener(this);
|
||||
mDatabase->Close(PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::StartFolderLoading(void)
|
||||
{
|
||||
if(mDatabase)
|
||||
mDatabase->RemoveListener(this);
|
||||
mAddListener = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::EndFolderLoading(void)
|
||||
{
|
||||
if(mDatabase)
|
||||
mDatabase->AddListener(this);
|
||||
mAddListener = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::GetThreads(nsISimpleEnumerator** threadEnumerator)
|
||||
{
|
||||
nsresult rv = GetDatabase();
|
||||
|
||||
if(NS_SUCCEEDED(rv))
|
||||
return mDatabase->EnumerateThreads(threadEnumerator);
|
||||
else
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgDBFolder::GetThreadForMessage(nsIMessage *message, nsIMsgThread **thread)
|
||||
{
|
||||
nsresult rv = GetDatabase();
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsCOMPtr<nsIMsgDBHdr> msgDBHdr;
|
||||
nsCOMPtr<nsIDBMessage> dbMessage(do_QueryInterface(message, &rv));
|
||||
if(NS_SUCCEEDED(rv))
|
||||
rv = dbMessage->GetMsgDBHdr(getter_AddRefs(msgDBHdr));
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = mDatabase->GetThreadContainingMsgHdr(msgDBHdr, thread);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgDBFolder::HasMessage(nsIMessage *message, PRBool *hasMessage)
|
||||
{
|
||||
if(!hasMessage)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult rv = GetDatabase();
|
||||
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsCOMPtr<nsIMsgDBHdr> msgDBHdr, msgDBHdrForKey;
|
||||
nsCOMPtr<nsIDBMessage> dbMessage(do_QueryInterface(message, &rv));
|
||||
nsMsgKey key;
|
||||
if(NS_SUCCEEDED(rv))
|
||||
rv = dbMessage->GetMsgDBHdr(getter_AddRefs(msgDBHdr));
|
||||
if(NS_SUCCEEDED(rv))
|
||||
rv = msgDBHdr->GetMessageKey(&key);
|
||||
if(NS_SUCCEEDED(rv))
|
||||
rv = mDatabase->ContainsKey(key, hasMessage);
|
||||
|
||||
}
|
||||
return rv;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::GetCharset(PRUnichar * *aCharset)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
if(!aCharset)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if(mCharset == "")
|
||||
{
|
||||
NS_WITH_SERVICE(nsIPref, prefs, kPrefServiceCID, &rv);
|
||||
|
||||
char *prefCharset = nsnull;
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = prefs->CopyCharPref("intl.character_set_name", &prefCharset);
|
||||
}
|
||||
|
||||
nsString prefCharsetStr;
|
||||
if(prefCharset)
|
||||
{
|
||||
prefCharsetStr = prefCharset;
|
||||
PR_Free(prefCharset);
|
||||
}
|
||||
else
|
||||
{
|
||||
prefCharsetStr = "us-ascii";
|
||||
}
|
||||
*aCharset = prefCharsetStr.ToNewUnicode();
|
||||
}
|
||||
else
|
||||
{
|
||||
*aCharset = mCharset.ToNewUnicode();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::SetCharset(const PRUnichar * aCharset)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIDBFolderInfo> folderInfo;
|
||||
nsCOMPtr<nsIMsgDatabase> db;
|
||||
rv = GetDBFolderInfoAndDB(getter_AddRefs(folderInfo), getter_AddRefs(db));
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsString charset(aCharset);
|
||||
rv = folderInfo->SetCharacterSet(&charset);
|
||||
db->Commit(nsMsgDBCommitType::kLargeCommit);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMsgDBFolder::ReadDBFolderInfo(PRBool force)
|
||||
{
|
||||
// Since it turns out to be pretty expensive to open and close
|
||||
// the DBs all the time, if we have to open it once, get everything
|
||||
// we might need while we're here
|
||||
|
||||
nsresult result;
|
||||
|
||||
nsCOMPtr <nsIMsgFolderCache> folderCache;
|
||||
|
||||
NS_WITH_SERVICE(nsIMsgMailSession, mailSession, kMsgMailSessionCID, &result);
|
||||
if(NS_SUCCEEDED(result))
|
||||
{
|
||||
result = mailSession->GetFolderCache(getter_AddRefs(folderCache));
|
||||
if (NS_SUCCEEDED(result) && folderCache)
|
||||
{
|
||||
char *uri;
|
||||
|
||||
result = GetURI(&uri);
|
||||
if (NS_SUCCEEDED(result) && uri)
|
||||
{
|
||||
nsCOMPtr <nsIMsgFolderCacheElement> cacheElement;
|
||||
result = folderCache->GetCacheElement(uri, PR_FALSE, getter_AddRefs(cacheElement));
|
||||
if (NS_SUCCEEDED(result) && cacheElement)
|
||||
{
|
||||
result = ReadFromFolderCache(cacheElement);
|
||||
}
|
||||
PR_Free(uri);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
// if (m_master->InitFolderFromCache (this))
|
||||
// return err;
|
||||
|
||||
if (force || !(mPrefFlags & MSG_FOLDER_PREF_CACHED))
|
||||
{
|
||||
nsCOMPtr<nsIDBFolderInfo> folderInfo;
|
||||
nsCOMPtr<nsIMsgDatabase> db;
|
||||
result = GetDBFolderInfoAndDB(getter_AddRefs(folderInfo), getter_AddRefs(db));
|
||||
if(NS_SUCCEEDED(result))
|
||||
{
|
||||
mIsCachable = PR_TRUE;
|
||||
if (folderInfo)
|
||||
{
|
||||
|
||||
folderInfo->GetFlags(&mPrefFlags);
|
||||
mPrefFlags |= MSG_FOLDER_PREF_CACHED;
|
||||
folderInfo->SetFlags(mPrefFlags);
|
||||
|
||||
folderInfo->GetNumMessages(&mNumTotalMessages);
|
||||
folderInfo->GetNumNewMessages(&mNumUnreadMessages);
|
||||
|
||||
//These should be put in IMAP folder only.
|
||||
//folderInfo->GetImapTotalPendingMessages(&mNumPendingTotalMessages);
|
||||
//folderInfo->GetImapUnreadPendingMessages(&mNumPendingUnreadMessages);
|
||||
|
||||
folderInfo->GetCharacterSet(&mCharset);
|
||||
|
||||
if (db) {
|
||||
PRBool hasnew;
|
||||
nsresult rv;
|
||||
rv = db->HasNew(&hasnew);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!hasnew && mNumPendingUnreadMessages <= 0) {
|
||||
ClearFlag(MSG_FOLDER_FLAG_GOT_NEW);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (db)
|
||||
db->Close(PR_FALSE);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
nsresult nsMsgDBFolder::SendFlagNotifications(nsISupports *item, PRUint32 oldFlags, PRUint32 newFlags)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
PRUint32 changedFlags = oldFlags ^ newFlags;
|
||||
if((changedFlags & MSG_FLAG_READ) || (changedFlags & MSG_FLAG_REPLIED)
|
||||
|| (changedFlags & MSG_FLAG_FORWARDED)|| (changedFlags & MSG_FLAG_NEW))
|
||||
{
|
||||
rv = NotifyPropertyFlagChanged(item, "Status", oldFlags, newFlags);
|
||||
}
|
||||
else if((changedFlags & MSG_FLAG_MARKED))
|
||||
{
|
||||
rv = NotifyPropertyFlagChanged(item, "Flagged", oldFlags, newFlags);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgDBFolder::GetMsgDatabase(nsIMsgDatabase** aMsgDatabase)
|
||||
{
|
||||
if (!aMsgDatabase || !mDatabase)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
*aMsgDatabase = mDatabase;
|
||||
NS_ADDREF(*aMsgDatabase);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::OnKeyChange(nsMsgKey aKeyChanged, PRUint32 aOldFlags, PRUint32 aNewFlags,
|
||||
nsIDBChangeListener * aInstigator)
|
||||
{
|
||||
nsCOMPtr<nsIMsgDBHdr> pMsgDBHdr;
|
||||
nsresult rv = mDatabase->GetMsgHdrForKey(aKeyChanged, getter_AddRefs(pMsgDBHdr));
|
||||
if(NS_SUCCEEDED(rv) && pMsgDBHdr)
|
||||
{
|
||||
nsCOMPtr<nsIMessage> message;
|
||||
rv = CreateMessageFromMsgDBHdr(pMsgDBHdr, getter_AddRefs(message));
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsCOMPtr<nsISupports> msgSupports(do_QueryInterface(message, &rv));
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
SendFlagNotifications(msgSupports, aOldFlags, aNewFlags);
|
||||
}
|
||||
UpdateSummaryTotals(PR_TRUE);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::OnKeyDeleted(nsMsgKey aKeyChanged, nsMsgKey aParentKey, PRInt32 aFlags,
|
||||
nsIDBChangeListener * aInstigator)
|
||||
{
|
||||
nsCOMPtr<nsIMsgDBHdr> pMsgDBHdr;
|
||||
nsresult rv = mDatabase->GetMsgHdrForKey(aKeyChanged, getter_AddRefs(pMsgDBHdr));
|
||||
if(NS_SUCCEEDED(rv) && pMsgDBHdr)
|
||||
{
|
||||
nsCOMPtr<nsIMessage> message;
|
||||
rv = CreateMessageFromMsgDBHdr(pMsgDBHdr, getter_AddRefs(message));
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsCOMPtr<nsISupports> msgSupports(do_QueryInterface(message, &rv));
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
NotifyItemDeleted(msgSupports);
|
||||
}
|
||||
UpdateSummaryTotals(PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::OnKeyAdded(nsMsgKey aKeyChanged, nsMsgKey aParentKey , PRInt32 aFlags,
|
||||
nsIDBChangeListener * aInstigator)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIMsgDBHdr> msgDBHdr;
|
||||
rv = mDatabase->GetMsgHdrForKey(aKeyChanged, getter_AddRefs(msgDBHdr));
|
||||
if(NS_SUCCEEDED(rv) && msgDBHdr)
|
||||
{
|
||||
nsCOMPtr<nsIMessage> message;
|
||||
rv = CreateMessageFromMsgDBHdr(msgDBHdr, getter_AddRefs(message));
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsCOMPtr<nsISupports> msgSupports(do_QueryInterface(message));
|
||||
if(msgSupports)
|
||||
{
|
||||
NotifyItemAdded(msgSupports);
|
||||
}
|
||||
UpdateSummaryTotals(PR_TRUE);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::OnParentChanged(nsMsgKey aKeyChanged, nsMsgKey oldParent, nsMsgKey newParent,
|
||||
nsIDBChangeListener * aInstigator)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::OnAnnouncerGoingAway(nsIDBChangeAnnouncer *
|
||||
instigator)
|
||||
{
|
||||
if (mDatabase)
|
||||
{
|
||||
mDatabase->RemoveListener(this);
|
||||
mDatabase = null_nsCOMPtr();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::ManyHeadersToDownload(PRBool *retval)
|
||||
{
|
||||
PRInt32 numTotalMessages;
|
||||
|
||||
if (!retval)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
if (!mDatabase)
|
||||
*retval = PR_TRUE;
|
||||
else if (NS_SUCCEEDED(GetTotalMessages(PR_FALSE, &numTotalMessages)) && numTotalMessages <= 0)
|
||||
*retval = PR_TRUE;
|
||||
else
|
||||
*retval = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsMsgDBFolder::ReadFromFolderCache(nsIMsgFolderCacheElement *element)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
char *charset;
|
||||
|
||||
element->GetInt32Property("flags", &mPrefFlags);
|
||||
element->GetInt32Property("totalMsgs", &mNumTotalMessages);
|
||||
element->GetInt32Property("totalUnreadMsgs", &mNumUnreadMessages);
|
||||
|
||||
element->GetStringProperty("charset", &charset);
|
||||
|
||||
#ifdef DEBUG_bienvenu1
|
||||
char *uri;
|
||||
|
||||
GetURI(&uri);
|
||||
printf("read total %ld for %s\n", mNumTotalMessages, uri);
|
||||
PR_Free(uri);
|
||||
#endif
|
||||
mCharset = charset;
|
||||
PR_FREEIF(charset);
|
||||
|
||||
mPrefFlags |= MSG_FOLDER_PREF_CACHED;
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::WriteToFolderCache(nsIMsgFolderCache *folderCache)
|
||||
{
|
||||
nsCOMPtr <nsIEnumerator> aEnumerator;
|
||||
|
||||
nsresult rv = GetSubFolders(getter_AddRefs(aEnumerator));
|
||||
if(NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
char *uri = nsnull;
|
||||
rv = GetURI(&uri);
|
||||
|
||||
if (folderCache)
|
||||
{
|
||||
nsCOMPtr <nsIMsgFolderCacheElement> cacheElement;
|
||||
rv = folderCache->GetCacheElement(uri, PR_TRUE, getter_AddRefs(cacheElement));
|
||||
if (NS_SUCCEEDED(rv) && cacheElement)
|
||||
rv = WriteToFolderCacheElem(cacheElement);
|
||||
}
|
||||
PR_FREEIF(uri);
|
||||
|
||||
|
||||
nsCOMPtr<nsISupports> aItem;
|
||||
|
||||
rv = aEnumerator->First();
|
||||
if (!NS_SUCCEEDED(rv))
|
||||
return NS_OK; // it's OK, there are no sub-folders.
|
||||
|
||||
while(NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = aEnumerator->CurrentItem(getter_AddRefs(aItem));
|
||||
if (NS_FAILED(rv)) break;
|
||||
nsCOMPtr<nsIMsgFolder> aMsgFolder(do_QueryInterface(aItem, &rv));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
if (folderCache)
|
||||
{
|
||||
rv = aMsgFolder->WriteToFolderCache(folderCache);
|
||||
if (!NS_SUCCEEDED(rv))
|
||||
break;
|
||||
}
|
||||
}
|
||||
rv = aEnumerator->Next();
|
||||
if (!NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = NS_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::WriteToFolderCacheElem(nsIMsgFolderCacheElement *element)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
element->SetInt32Property("flags", mPrefFlags);
|
||||
element->SetInt32Property("totalMsgs", mNumTotalMessages);
|
||||
element->SetInt32Property("totalUnreadMsgs", mNumUnreadMessages);
|
||||
|
||||
element->SetStringProperty("charset", (const char *) nsCAutoString(mCharset));
|
||||
|
||||
#ifdef DEBUG_bienvenu1
|
||||
char *uri;
|
||||
|
||||
GetURI(&uri);
|
||||
printf("writing total %ld for %s\n", mNumTotalMessages, uri);
|
||||
PR_Free(uri);
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgDBFolder::MarkAllMessagesRead(void)
|
||||
{
|
||||
nsresult rv = GetDatabase();
|
||||
|
||||
if(NS_SUCCEEDED(rv))
|
||||
return mDatabase->MarkAllRead(nsnull);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgDBFolder::OnStartRunningUrl(nsIURI *aUrl)
|
||||
{
|
||||
NS_PRECONDITION(aUrl, "just a sanity check");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgDBFolder::OnStopRunningUrl(nsIURI *aUrl, nsresult aExitCode)
|
||||
{
|
||||
NS_PRECONDITION(aUrl, "just a sanity check");
|
||||
nsCOMPtr<nsIMsgMailNewsUrl> mailUrl = do_QueryInterface(aUrl);
|
||||
if (mailUrl)
|
||||
{
|
||||
PRBool updatingFolder = PR_FALSE;
|
||||
if (NS_SUCCEEDED(mailUrl->GetUpdatingFolder(&updatingFolder)) && updatingFolder)
|
||||
{
|
||||
NotifyFolderLoaded();
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef nsMsgDBFolder_h__
|
||||
#define nsMsgDBFolder_h__
|
||||
|
||||
#include "msgCore.h"
|
||||
#include "nsMsgFolder.h"
|
||||
#include "nsIDBFolderInfo.h"
|
||||
#include "nsIMsgDatabase.h"
|
||||
#include "nsIMessage.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDBChangeListener.h"
|
||||
#include "nsIUrlListener.h"
|
||||
|
||||
class nsIMsgFolderCacheElement;
|
||||
/*
|
||||
* nsMsgDBFolder
|
||||
* class derived from nsMsgFolder for those folders that use an nsIMsgDatabase
|
||||
*/
|
||||
|
||||
class NS_MSG_BASE nsMsgDBFolder: public nsMsgFolder,
|
||||
public nsIDBChangeListener,
|
||||
public nsIUrlListener
|
||||
{
|
||||
public:
|
||||
nsMsgDBFolder(void);
|
||||
virtual ~nsMsgDBFolder(void);
|
||||
NS_DECL_NSIDBCHANGELISTENER
|
||||
|
||||
NS_IMETHOD StartFolderLoading(void);
|
||||
NS_IMETHOD EndFolderLoading(void);
|
||||
NS_IMETHOD GetThreads(nsISimpleEnumerator** threadEnumerator);
|
||||
NS_IMETHOD GetThreadForMessage(nsIMessage *message, nsIMsgThread **thread);
|
||||
NS_IMETHOD HasMessage(nsIMessage *message, PRBool *hasMessage);
|
||||
NS_IMETHOD GetCharset(PRUnichar * *aCharset);
|
||||
NS_IMETHOD SetCharset(const PRUnichar * aCharset);
|
||||
|
||||
NS_IMETHOD GetMsgDatabase(nsIMsgDatabase** aMsgDatabase);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
NS_DECL_NSIURLLISTENER
|
||||
|
||||
NS_IMETHOD WriteToFolderCache(nsIMsgFolderCache *folderCache);
|
||||
NS_IMETHOD WriteToFolderCacheElem(nsIMsgFolderCacheElement *element);
|
||||
NS_IMETHOD ManyHeadersToDownload(PRBool *_retval);
|
||||
|
||||
NS_IMETHOD MarkAllMessagesRead(void);
|
||||
|
||||
protected:
|
||||
virtual nsresult ReadDBFolderInfo(PRBool force);
|
||||
virtual nsresult GetDatabase() = 0;
|
||||
virtual nsresult SendFlagNotifications(nsISupports *item, PRUint32 oldFlags, PRUint32 newFlags);
|
||||
nsresult ReadFromFolderCache(nsIMsgFolderCacheElement *element);
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIMsgDatabase> mDatabase;
|
||||
nsString mCharset;
|
||||
PRBool mAddListener;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,268 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
/********************************************************************************************************
|
||||
|
||||
Interface for representing Messenger folders.
|
||||
|
||||
*********************************************************************************************************/
|
||||
|
||||
#ifndef nsMsgFolder_h__
|
||||
#define nsMsgFolder_h__
|
||||
|
||||
#include "msgCore.h"
|
||||
#include "nsIMsgFolder.h" /* include the interface we are going to support */
|
||||
#include "nsRDFResource.h"
|
||||
#include "nsIDBFolderInfo.h"
|
||||
#include "nsIMsgDatabase.h"
|
||||
#include "nsIMsgIncomingServer.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIURL.h"
|
||||
/*
|
||||
* MsgFolder
|
||||
*/
|
||||
|
||||
class NS_MSG_BASE nsMsgFolder: public nsRDFResource, public nsIMsgFolder
|
||||
{
|
||||
public:
|
||||
nsMsgFolder(void);
|
||||
virtual ~nsMsgFolder(void);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
NS_DECL_NSICOLLECTION
|
||||
NS_DECL_NSIFOLDER
|
||||
// eventually this will be an instantiable class, and we should
|
||||
// use this macro:
|
||||
// NS_DECL_NSIMSGFOLDER
|
||||
|
||||
// right now a few of these methods are left abstract, and
|
||||
// are commented out below
|
||||
|
||||
// begin NS_DECL_NSIMSGFOLDER
|
||||
NS_IMETHOD AddUnique(nsISupports *element);
|
||||
NS_IMETHOD ReplaceElement(nsISupports *element, nsISupports *newElement);
|
||||
NS_IMETHOD GetMessages(nsISimpleEnumerator **_retval);
|
||||
NS_IMETHOD GetThreads(nsISimpleEnumerator **_retval);
|
||||
NS_IMETHOD StartFolderLoading(void);
|
||||
NS_IMETHOD EndFolderLoading(void);
|
||||
NS_IMETHOD UpdateFolder(void);
|
||||
NS_IMETHOD GetThreadForMessage(nsIMessage *message, nsIMsgThread **_retval);
|
||||
NS_IMETHOD HasMessage(nsIMessage *message, PRBool *_retval);
|
||||
NS_IMETHOD GetVisibleSubFolders(nsIEnumerator **_retval);
|
||||
NS_IMETHOD GetPrettiestName(PRUnichar * *aPrettiestName);
|
||||
NS_IMETHOD GetFolderURL(char * *aFolderURL);
|
||||
NS_IMETHOD GetDeleteIsMoveToTrash(PRBool *aDeleteIsMoveToTrash);
|
||||
NS_IMETHOD GetShowDeletedMessages(PRBool *aShowDeletedMessages);
|
||||
NS_IMETHOD GetServer(nsIMsgIncomingServer * *aServer);
|
||||
NS_IMETHOD GetIsServer(PRBool *aIsServer);
|
||||
NS_IMETHOD OnCloseFolder(void);
|
||||
NS_IMETHOD Delete(void);
|
||||
NS_IMETHOD DeleteSubFolders(nsISupportsArray *folders);
|
||||
NS_IMETHOD PropagateDelete(nsIMsgFolder *folder, PRBool deleteStorage);
|
||||
NS_IMETHOD RecursiveDelete(PRBool deleteStorage);
|
||||
NS_IMETHOD CreateSubfolder(const char *folderName);
|
||||
NS_IMETHOD Compact(void);
|
||||
NS_IMETHOD EmptyTrash(void);
|
||||
NS_IMETHOD Rename(const char *name);
|
||||
NS_IMETHOD Adopt(nsIMsgFolder *srcFolder, PRUint32 *outPos);
|
||||
NS_IMETHOD ContainsChildNamed(const char *name, PRBool *_retval);
|
||||
NS_IMETHOD IsAncestorOf(nsIMsgFolder *folder, PRBool *_retval);
|
||||
NS_IMETHOD GenerateUniqueSubfolderName(const char *prefix, nsIMsgFolder *otherFolder, char **_retval);
|
||||
NS_IMETHOD UpdateSummaryTotals(PRBool force);
|
||||
NS_IMETHOD SummaryChanged(void);
|
||||
NS_IMETHOD GetNumUnread(PRBool deep, PRInt32 *_retval);
|
||||
NS_IMETHOD GetTotalMessages(PRBool deep, PRInt32 *_retval);
|
||||
NS_IMETHOD GetExpungedBytesCount(PRUint32 *aExpungedBytesCount);
|
||||
NS_IMETHOD GetDeletable(PRBool *aDeletable);
|
||||
NS_IMETHOD GetCanCreateChildren(PRBool *aCanCreateChildren);
|
||||
NS_IMETHOD GetCanBeRenamed(PRBool *aCanBeRenamed);
|
||||
NS_IMETHOD GetRequiresCleanup(PRBool *aRequiresCleanup);
|
||||
NS_IMETHOD ClearRequiresCleanup(void);
|
||||
NS_IMETHOD ManyHeadersToDownload(PRBool *_retval);
|
||||
NS_IMETHOD GetKnowsSearchNntpExtension(PRBool *aKnowsSearchNntpExtension);
|
||||
NS_IMETHOD GetAllowsPosting(PRBool *aAllowsPosting);
|
||||
NS_IMETHOD GetDisplayRecipients(PRBool *aDisplayRecipients);
|
||||
NS_IMETHOD GetRelativePathName(char * *aRelativePathName);
|
||||
NS_IMETHOD GetSizeOnDisk(PRUint32 *aSizeOnDisk);
|
||||
NS_IMETHOD RememberPassword(const char *password);
|
||||
NS_IMETHOD GetRememberedPassword(char * *aRememberedPassword);
|
||||
NS_IMETHOD UserNeedsToAuthenticateForFolder(PRBool displayOnly, PRBool *_retval);
|
||||
NS_IMETHOD GetUsername(char * *aUsername);
|
||||
NS_IMETHOD GetHostname(char * *aHostname);
|
||||
NS_IMETHOD SetFlag(PRUint32 flag);
|
||||
NS_IMETHOD ClearFlag(PRUint32 flag);
|
||||
NS_IMETHOD GetFlag(PRUint32 flag, PRBool *_retval);
|
||||
NS_IMETHOD ToggleFlag(PRUint32 flag);
|
||||
NS_IMETHOD OnFlagChange(PRUint32 flag);
|
||||
NS_IMETHOD GetFlags(PRUint32 *aFlags);
|
||||
NS_IMETHOD GetFoldersWithFlag(PRUint32 flags, nsIMsgFolder **result, PRUint32 resultsize, PRUint32 *numFolders);
|
||||
NS_IMETHOD GetExpansionArray(nsISupportsArray *expansionArray);
|
||||
// NS_IMETHOD DeleteMessages(nsISupportsArray *message, nsITransactionManager *txnMgr, PRBool deleteStorage);
|
||||
NS_IMETHOD CopyMessages(nsIMsgFolder *srcFolder, nsISupportsArray *messages, PRBool isMove, nsITransactionManager *txnMgr, nsIMsgCopyServiceListener *listener);
|
||||
NS_IMETHOD CopyFileMessage(nsIFileSpec *fileSpec, nsIMessage *msgToReplace, PRBool isDraft, nsITransactionManager *txnMgr, nsIMsgCopyServiceListener *listener);
|
||||
NS_IMETHOD AcquireSemaphore(nsISupports *semHolder);
|
||||
NS_IMETHOD ReleaseSemaphore(nsISupports *semHolder);
|
||||
NS_IMETHOD TestSemaphore(nsISupports *semHolder, PRBool *_retval);
|
||||
NS_IMETHOD GetLocked(PRBool *aLocked);
|
||||
// NS_IMETHOD CreateMessageFromMsgDBHdr(nsIMsgDBHdr *msgDBHdr, nsIMessage **_retval);
|
||||
NS_IMETHOD GetNewMessages(void);
|
||||
// NS_IMETHOD WriteToFolderCache(nsIMsgFolderCache *folderCache);
|
||||
// NS_IMETHOD GetCharset(PRUnichar * *aCharset);
|
||||
// NS_IMETHOD SetCharset(const PRUnichar * aCharset);
|
||||
NS_IMETHOD GetBiffState(PRUint32 *aBiffState);
|
||||
NS_IMETHOD SetBiffState(PRUint32 aBiffState);
|
||||
NS_IMETHOD GetNumNewMessages(PRInt32 *aNumNewMessages);
|
||||
NS_IMETHOD SetNumNewMessages(PRInt32 aNumNewMessages);
|
||||
NS_IMETHOD GetNewMessagesNotificationDescription(PRUnichar * *aNewMessagesNotificationDescription);
|
||||
NS_IMETHOD GetRootFolder(nsIMsgFolder * *aRootFolder);
|
||||
NS_IMETHOD GetMsgDatabase(nsIMsgDatabase * *aMsgDatabase);
|
||||
NS_IMETHOD GetPath(nsIFileSpec * *aPath);
|
||||
NS_IMETHOD MarkMessagesRead(nsISupportsArray *messages, PRBool markRead);
|
||||
NS_IMETHOD MarkAllMessagesRead(void);
|
||||
NS_IMETHOD MarkMessagesFlagged(nsISupportsArray *messages, PRBool markFlagged);
|
||||
NS_IMETHOD GetChildWithURI(const char *uri, PRBool deep, nsIMsgFolder **_retval);
|
||||
|
||||
// end NS_DECL_NSIMSGFOLDER
|
||||
|
||||
// nsRDFResource overrides
|
||||
NS_IMETHOD Init(const char* aURI);
|
||||
|
||||
#if 0
|
||||
static nsresult GetRoot(nsIMsgFolder* *result);
|
||||
#endif
|
||||
// Gets the URL that represents the given message. Returns a newly
|
||||
// created string that must be free'd using XP_FREE().
|
||||
// If the db is NULL, then returns a URL that represents the entire
|
||||
// folder as a whole.
|
||||
#ifdef HAVE_DB
|
||||
NS_IMETHOD BuildUrl(nsMsgDatabase *db, nsMsgKey key, char ** url);
|
||||
|
||||
// updates num messages and num unread - should be pure virtual
|
||||
// when I get around to implementing in all subclasses?
|
||||
NS_IMETHOD GetTotalMessagesInDB(PRUint32 *totalMessages) const; // How many messages in database.
|
||||
// These functions are used for tricking the front end into thinking that we have more
|
||||
// messages than are really in the DB. This is usually after and IMAP message copy where
|
||||
// we don't want to do an expensive select until the user actually opens that folder
|
||||
// These functions are called when MSG_Master::GetFolderLineById is populating a MSG_FolderLine
|
||||
// struct used by the FE
|
||||
int32 GetNumPendingUnread(PRBool deep = PR_FALSE);
|
||||
int32 GetNumPendingTotalMessages(PRBool deep = PR_FALSE);
|
||||
|
||||
void ChangeNumPendingUnread(int32 delta);
|
||||
void ChangeNumPendingTotalMessages(int32 delta);
|
||||
|
||||
|
||||
NS_IMETHOD SetFolderPrefFlags(PRUint32 flags);
|
||||
NS_IMETHOD GetFolderPrefFlags(PRUint32 *flags);
|
||||
|
||||
|
||||
NS_IMETHOD SetLastMessageLoaded(nsMsgKey lastMessageLoaded);
|
||||
NS_IMETHOD GetLastMessageLoaded();
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_ADMINURL
|
||||
NS_IMETHOD GetAdminUrl(MWContext *context, MSG_AdminURLType type);
|
||||
NS_IMETHOD HaveAdminUrl(MSG_AdminURLType type, PRBool *hadAdminUrl);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_PANE
|
||||
NS_IMETHOD MarkAllRead(MSG_Pane *pane, PRBool deep);
|
||||
NS_IMETHOD SetFlagInAllFolderPanes(PRUint32 which);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NET
|
||||
NS_IMETHOD EscapeMessageId(const char *messageId, const char **escapeMessageID);
|
||||
NS_IMETHOD ShouldPerformOperationOffline(PRBool *performOffline);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CACHE
|
||||
virtual nsresult WriteToCache(XP_File);
|
||||
virtual nsresult ReadFromCache(char *);
|
||||
virtual PRBool IsCachable();
|
||||
void SkipCacheTokens(char **ppBuf, int numTokens);
|
||||
#endif
|
||||
|
||||
#ifdef DOES_FOLDEROPERATIONS
|
||||
int DownloadToTempFileAndUpload(MessageCopyInfo *copyInfo, nsMsgKeyArray &keysToSave, MSG_FolderInfo *dstFolder, nsMsgDatabase *sourceDB);
|
||||
void UpdateMoveCopyStatus(MWContext *context, PRBool isMove, int32 curMsgCount, int32 totMessages);
|
||||
#endif
|
||||
|
||||
virtual nsresult GetDBFolderInfoAndDB(nsIDBFolderInfo **folderInfo, nsIMsgDatabase **db) = 0;
|
||||
|
||||
|
||||
NS_IMETHOD MatchName(nsString *name, PRBool *matches);
|
||||
|
||||
|
||||
protected:
|
||||
nsresult NotifyPropertyChanged(char *property, char* oldValue, char* newValue);
|
||||
nsresult NotifyPropertyFlagChanged(nsISupports *item, char *property, PRUint32 oldValue,
|
||||
PRUint32 newValue);
|
||||
nsresult NotifyItemAdded(nsISupports *item);
|
||||
nsresult NotifyItemDeleted(nsISupports *item);
|
||||
|
||||
nsresult NotifyFolderLoaded();
|
||||
// this is a little helper function that is not part of the public interface.
|
||||
// we use it to get the IID of the incoming server for the derived folder.
|
||||
// w/out a function like this we would have to implement GetServer in each
|
||||
// derived folder class.
|
||||
virtual const char* GetIncomingServerType() = 0;
|
||||
|
||||
protected:
|
||||
PRUint32 mFlags;
|
||||
nsIFolder *mParent; //This won't be refcounted for ownership reasons.
|
||||
PRInt32 mNumUnreadMessages; /* count of unread messages (-1 means
|
||||
unknown; -2 means unknown but we already
|
||||
tried to find out.) */
|
||||
PRInt32 mNumTotalMessages; /* count of existing messages. */
|
||||
nsCOMPtr<nsISupportsArray> mSubFolders;
|
||||
nsVoidArray *mListeners; //This can't be an nsISupportsArray because due to
|
||||
//ownership issues, listeners can't be AddRef'd
|
||||
|
||||
PRInt32 mPrefFlags; // prefs like MSG_PREF_OFFLINE, MSG_PREF_ONE_PANE, etc
|
||||
nsISupports *mSemaphoreHolder; // set when the folder is being written to
|
||||
//Due to ownership issues, this won't be AddRef'd.
|
||||
|
||||
nsIMsgIncomingServer* m_server; //this won't be addrefed....ownership issue here
|
||||
|
||||
#ifdef HAVE_DB
|
||||
nsMsgKey m_lastMessageLoaded;
|
||||
#endif
|
||||
// These values are used for tricking the front end into thinking that we have more
|
||||
// messages than are really in the DB. This is usually after and IMAP message copy where
|
||||
// we don't want to do an expensive select until the user actually opens that folder
|
||||
PRInt32 mNumPendingUnreadMessages;
|
||||
PRInt32 mNumPendingTotalMessages;
|
||||
|
||||
PRUint32 mBiffState;
|
||||
PRInt32 mNumNewBiffMessages;
|
||||
|
||||
PRBool mIsCachable;
|
||||
|
||||
//
|
||||
// stuff from the uri
|
||||
//
|
||||
|
||||
PRBool mIsServer;
|
||||
nsString mName;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,598 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "msgCore.h" // precompiled header...
|
||||
#include "prlog.h"
|
||||
|
||||
#include "nsMsgGroupRecord.h"
|
||||
|
||||
#include "plstr.h"
|
||||
#include "prmem.h"
|
||||
#include "nsEscape.h"
|
||||
#include "nsCRT.h"
|
||||
|
||||
// mscott: this is lame...I know....
|
||||
#define MK_OUT_OF_MEMORY 1
|
||||
|
||||
const PRUint32 F_ISGROUP = 0x00000001;
|
||||
const PRUint32 F_EXPANDED = 0x00000002;
|
||||
const PRUint32 F_CATCONT = 0x00000004;
|
||||
const PRUint32 F_VIRTUAL = 0x00000008;
|
||||
const PRUint32 F_DIRTY = 0x00000010;
|
||||
const PRUint32 F_DESCENDENTSLOADED = 0x00000020;
|
||||
const PRUint32 F_HTMLOKGROUP = 0x00000040;
|
||||
const PRUint32 F_HTMLOKTREE = 0x00000080;
|
||||
const PRUint32 F_NEEDEXTRAINFO = 0x00000100;
|
||||
const PRUint32 F_DOESNOTEXIST = 0x00000200;
|
||||
const PRUint32 RUNTIMEFLAGS = // Flags to be sure *not* to write to disk.
|
||||
F_DIRTY | F_DESCENDENTSLOADED | F_EXPANDED;
|
||||
|
||||
|
||||
|
||||
int
|
||||
nsMsgGroupRecord::GroupNameCompare(const char* name1, const char* name2,
|
||||
char delimiter, PRBool caseInsensitive)
|
||||
{
|
||||
if (caseInsensitive)
|
||||
{
|
||||
while (*name1 && (nsCRT::ToUpper(*name1) == nsCRT::ToUpper(*name2))) {
|
||||
name1++;
|
||||
name2++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (*name1 && *name1 == *name2) {
|
||||
name1++;
|
||||
name2++;
|
||||
}
|
||||
}
|
||||
|
||||
if (*name1 && *name2) {
|
||||
if (*name1 == delimiter) return -1;
|
||||
if (*name2 == delimiter) return 1;
|
||||
}
|
||||
|
||||
if (caseInsensitive)
|
||||
return int(nsCRT::ToUpper(*name1)) - int(nsCRT::ToUpper(*name2));
|
||||
else
|
||||
return int(*name1) - int(*name2);
|
||||
}
|
||||
|
||||
|
||||
nsMsgGroupRecord*
|
||||
nsMsgGroupRecord::Create(nsMsgGroupRecord* parent, const char* partname,
|
||||
PRInt64 aTime, PRInt32 uniqueid, PRInt32 fileoffset)
|
||||
{
|
||||
nsMsgGroupRecord* result = new nsMsgGroupRecord(parent, partname,
|
||||
aTime, uniqueid, fileoffset);
|
||||
if (result && partname && !result->m_partname) {
|
||||
// We ran out of memory.
|
||||
delete result;
|
||||
result = NULL;
|
||||
}
|
||||
result->InitializeSibling();
|
||||
return result;
|
||||
}
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsMsgGroupRecord);
|
||||
|
||||
nsMsgGroupRecord::nsMsgGroupRecord(nsMsgGroupRecord* parent, const char* partname,
|
||||
PRInt64 aTime, PRInt32 uniqueid, PRInt32 fileoffset,
|
||||
char delimiter /* = '.' */)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsMsgGroupRecord);
|
||||
int length;
|
||||
m_prettyname = NULL;
|
||||
m_parent = parent;
|
||||
m_children = NULL;
|
||||
m_sibling = NULL;
|
||||
m_flags = 0;
|
||||
m_partname = NULL;
|
||||
m_addtime = aTime;
|
||||
m_uniqueId = uniqueid;
|
||||
m_fileoffset = fileoffset;
|
||||
m_delimiter = delimiter;
|
||||
if (partname) {
|
||||
length = PL_strlen(partname);
|
||||
// PR_ASSERT(parent != NULL);
|
||||
m_partname = new char [length + 1];
|
||||
if (!m_partname) {
|
||||
m_parent = NULL;
|
||||
return;
|
||||
}
|
||||
PL_strcpy(m_partname, partname);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nsMsgGroupRecord::~nsMsgGroupRecord()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsMsgGroupRecord);
|
||||
delete [] m_partname;
|
||||
m_partname = NULL;
|
||||
delete [] m_prettyname;
|
||||
m_prettyname = NULL;
|
||||
while (m_children) {
|
||||
delete m_children;
|
||||
}
|
||||
m_children = NULL;
|
||||
if (m_parent) {
|
||||
nsMsgGroupRecord** ptr;
|
||||
for (ptr = &(m_parent->m_children);
|
||||
*ptr;
|
||||
ptr = &((*ptr)->m_sibling)) {
|
||||
if (*ptr == this) {
|
||||
*ptr = m_sibling;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nsMsgGroupRecord::InitializeSibling()
|
||||
{
|
||||
if (m_parent) {
|
||||
PR_ASSERT(m_partname != NULL);
|
||||
nsMsgGroupRecord** ptr;
|
||||
for (ptr = &(m_parent->m_children) ; *ptr ; ptr = &((*ptr)->m_sibling)) {
|
||||
int comp = GroupNameCompare((*ptr)->m_partname, m_partname, m_delimiter, IsIMAPGroupRecord());
|
||||
PR_ASSERT(comp != 0);
|
||||
if (comp >= 0) break;
|
||||
}
|
||||
m_sibling = *ptr;
|
||||
*ptr = this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nsMsgGroupRecord*
|
||||
nsMsgGroupRecord::FindDescendant(const char* name)
|
||||
{
|
||||
if (!name || !*name) return this;
|
||||
char* ptr = PL_strchr(name, m_delimiter);
|
||||
if (ptr) *ptr = '\0';
|
||||
nsMsgGroupRecord* child;
|
||||
for (child = m_children ; child ; child = child->m_sibling) {
|
||||
if (PL_strcmp(child->m_partname, name) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ptr) {
|
||||
*ptr++ = m_delimiter;
|
||||
if (child) {
|
||||
return child->FindDescendant(ptr);
|
||||
}
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
|
||||
nsMsgGroupRecord*
|
||||
nsMsgGroupRecord::GetSiblingOrAncestorSibling()
|
||||
{
|
||||
if (m_sibling) return m_sibling;
|
||||
if (m_parent) return m_parent->GetSiblingOrAncestorSibling();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nsMsgGroupRecord*
|
||||
nsMsgGroupRecord::GetNextAlphabetic()
|
||||
{
|
||||
nsMsgGroupRecord* result;
|
||||
if (m_children) result = m_children;
|
||||
else result = GetSiblingOrAncestorSibling();
|
||||
#ifdef DEBUG_slowAndParanoid
|
||||
if (result) {
|
||||
char* ptr1 = GetFullName();
|
||||
char* ptr2 = result->GetFullName();
|
||||
PR_ASSERT(GroupNameCompare(ptr1, ptr2) < 0);
|
||||
delete [] ptr1;
|
||||
delete [] ptr2;
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
nsMsgGroupRecord*
|
||||
nsMsgGroupRecord::GetNextAlphabeticNoCategories()
|
||||
{
|
||||
if (IsCategoryContainer()) {
|
||||
return GetSiblingOrAncestorSibling();
|
||||
} else {
|
||||
return GetNextAlphabetic();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
nsMsgGroupRecord::GetFullName()
|
||||
{
|
||||
int length = 0;
|
||||
nsMsgGroupRecord* ptr;
|
||||
for (ptr = this ; ptr ; ptr = ptr->m_parent) {
|
||||
if (ptr->m_partname) length += PL_strlen(ptr->m_partname) + 1;
|
||||
}
|
||||
PR_ASSERT(length > 0);
|
||||
if (length <= 0) return NULL;
|
||||
char* result = new char [length];
|
||||
if (result) {
|
||||
SuckInName(result);
|
||||
PR_ASSERT(int(PL_strlen(result)) + 1 == length);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
nsMsgGroupRecord::SuckInName(char* ptr)
|
||||
{
|
||||
if (m_parent && m_parent->m_partname) {
|
||||
ptr = m_parent->SuckInName(ptr);
|
||||
*ptr++ = m_delimiter;
|
||||
}
|
||||
PL_strcpy(ptr, m_partname);
|
||||
return ptr + PL_strlen(ptr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
nsMsgGroupRecord::SetPrettyName(const char* name)
|
||||
{
|
||||
if (name == NULL && m_prettyname == NULL) return 0;
|
||||
m_flags |= F_DIRTY;
|
||||
delete [] m_prettyname;
|
||||
m_prettyname = NULL;
|
||||
if (!name || !*name) {
|
||||
return 0;
|
||||
}
|
||||
int length = PL_strlen(name);
|
||||
m_prettyname = new char [length + 1];
|
||||
if (!m_prettyname) {
|
||||
return MK_OUT_OF_MEMORY;
|
||||
}
|
||||
PL_strcpy(m_prettyname, name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsMsgGroupRecord::IsCategory()
|
||||
{
|
||||
return GetCategoryContainer() != NULL;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsMsgGroupRecord::IsCategoryContainer()
|
||||
{
|
||||
return (m_flags & F_CATCONT) != 0;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsMsgGroupRecord::NeedsExtraInfo()
|
||||
{
|
||||
return (m_flags & F_NEEDEXTRAINFO) != 0;
|
||||
}
|
||||
|
||||
int
|
||||
nsMsgGroupRecord::SetNeedsExtraInfo(PRBool value)
|
||||
{
|
||||
return TweakFlag(F_NEEDEXTRAINFO, value);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nsMsgGroupRecord::SetIsCategoryContainer(PRBool value)
|
||||
{
|
||||
// refuse to set a group to be a category container if it has a parent
|
||||
// that's a category container.
|
||||
if (! (value && GetCategoryContainer()))
|
||||
return TweakFlag(F_CATCONT, value);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
nsMsgGroupRecord*
|
||||
nsMsgGroupRecord::GetCategoryContainer()
|
||||
{
|
||||
if (IsCategoryContainer()) return NULL;
|
||||
for (nsMsgGroupRecord* ptr = m_parent ; ptr ; ptr = ptr->m_parent) {
|
||||
if (ptr->IsCategoryContainer()) return ptr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsMsgGroupRecord::IsVirtual(PRBool *retval)
|
||||
{
|
||||
*retval =( (m_flags & F_VIRTUAL) != 0);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgGroupRecord::SetIsVirtual(PRBool value)
|
||||
{
|
||||
TweakFlag(F_VIRTUAL, value);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PRBool
|
||||
nsMsgGroupRecord::IsExpanded()
|
||||
{
|
||||
return (m_flags & F_EXPANDED) != 0;
|
||||
}
|
||||
|
||||
int
|
||||
nsMsgGroupRecord::SetIsExpanded(PRBool value)
|
||||
{
|
||||
return TweakFlag(F_EXPANDED, value);
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsMsgGroupRecord::IsHTMLOKGroup()
|
||||
{
|
||||
return (m_flags & F_HTMLOKGROUP) != 0;
|
||||
}
|
||||
|
||||
int
|
||||
nsMsgGroupRecord::SetIsHTMLOKGroup(PRBool value)
|
||||
{
|
||||
return TweakFlag(F_HTMLOKGROUP, value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
PRBool
|
||||
nsMsgGroupRecord::IsHTMLOKTree()
|
||||
{
|
||||
return (m_flags & F_HTMLOKTREE) != 0;
|
||||
}
|
||||
|
||||
int
|
||||
nsMsgGroupRecord::SetIsHTMLOKTree(PRBool value)
|
||||
{
|
||||
return TweakFlag(F_HTMLOKTREE, value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
PRBool
|
||||
nsMsgGroupRecord::IsGroup()
|
||||
{
|
||||
return (m_flags & F_ISGROUP) != 0;
|
||||
}
|
||||
|
||||
int
|
||||
nsMsgGroupRecord::SetIsGroup(PRBool value)
|
||||
{
|
||||
return TweakFlag(F_ISGROUP, value);
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsMsgGroupRecord::IsDescendentsLoaded()
|
||||
{
|
||||
return (m_flags & F_DESCENDENTSLOADED) != 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nsMsgGroupRecord::SetIsDescendentsLoaded(PRBool value)
|
||||
{
|
||||
PR_ASSERT(value); // No reason we'd ever unset this.
|
||||
TweakFlag(F_DESCENDENTSLOADED, PR_TRUE);
|
||||
nsMsgGroupRecord* child;
|
||||
for (child = m_children ; child ; child = child->m_sibling) {
|
||||
child->SetIsDescendentsLoaded(value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRBool nsMsgGroupRecord::DoesNotExistOnServer()
|
||||
{
|
||||
return (m_flags & F_DOESNOTEXIST) != 0;
|
||||
}
|
||||
|
||||
int nsMsgGroupRecord::SetDoesNotExistOnServer(PRBool value)
|
||||
{
|
||||
if (value) // turn off group flag if doesn't exist on server.
|
||||
TweakFlag(F_ISGROUP, PR_FALSE);
|
||||
return TweakFlag(F_DOESNOTEXIST, value);
|
||||
}
|
||||
|
||||
int
|
||||
nsMsgGroupRecord::TweakFlag(PRUint32 flagbit, PRBool value)
|
||||
{
|
||||
if (value) {
|
||||
if (!(m_flags & flagbit)) {
|
||||
m_flags |= flagbit;
|
||||
if (flagbit & ~RUNTIMEFLAGS)
|
||||
m_flags |= F_DIRTY;
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if (m_flags & flagbit) {
|
||||
m_flags &= ~flagbit;
|
||||
if (flagbit & ~RUNTIMEFLAGS)
|
||||
m_flags |= F_DIRTY;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
PRInt32
|
||||
nsMsgGroupRecord::GetNumKids()
|
||||
{
|
||||
PRInt32 result = 0;
|
||||
nsMsgGroupRecord* child;
|
||||
for (child = m_children ; child ; child = child->m_sibling) {
|
||||
if (IsIMAPGroupRecord())
|
||||
result++;
|
||||
else
|
||||
if (child->m_flags & F_ISGROUP) result++;
|
||||
|
||||
if (!IsIMAPGroupRecord())
|
||||
result += child->GetNumKids();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
char*
|
||||
nsMsgGroupRecord::GetSaveString()
|
||||
{
|
||||
char* pretty = NULL;
|
||||
char* result = nsnull;
|
||||
|
||||
if (m_prettyname) {
|
||||
pretty = nsEscape(m_prettyname, url_XAlphas);
|
||||
if (!pretty) return NULL;
|
||||
}
|
||||
char* fullname = GetFullName();
|
||||
if (!fullname) return NULL; {
|
||||
long nAddTime;
|
||||
LL_L2I(nAddTime, m_addtime);
|
||||
result = PR_smprintf("%s,%s,%lx,%lx,%lx" MSG_LINEBREAK,
|
||||
fullname, pretty ? pretty : "",
|
||||
(long) (m_flags & ~RUNTIMEFLAGS),
|
||||
nAddTime,
|
||||
(long) m_uniqueId);
|
||||
}
|
||||
delete [] fullname;
|
||||
if (pretty) nsCRT::free(pretty);
|
||||
m_flags &= ~F_DIRTY;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsMsgGroupRecord::IsDirty()
|
||||
{
|
||||
return (m_flags & F_DIRTY) != 0;
|
||||
}
|
||||
|
||||
|
||||
PRInt32
|
||||
nsMsgGroupRecord::GetDepth()
|
||||
{
|
||||
PRInt32 result = 0;
|
||||
nsMsgGroupRecord* tmp = m_parent;
|
||||
while (tmp) {
|
||||
tmp = tmp->m_parent;
|
||||
result++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
nsMsgGroupRecord*
|
||||
nsMsgGroupRecord::Create(nsMsgGroupRecord* parent, const char* saveline,
|
||||
PRInt32 savelinelength, PRInt32 fileoffset)
|
||||
{
|
||||
char* tmp;
|
||||
char* ptr;
|
||||
char* endptr;
|
||||
char* partname;
|
||||
char* prettyname;
|
||||
PRInt32 flags;
|
||||
PRInt32 addtime;
|
||||
PRInt32 uniqueid;
|
||||
nsMsgGroupRecord* result = NULL;
|
||||
|
||||
if (savelinelength < 0) savelinelength = PL_strlen(saveline);
|
||||
tmp = (char*) PR_Malloc(savelinelength + 1);
|
||||
if (!tmp) return NULL;
|
||||
PL_strncpy(tmp, saveline, savelinelength);
|
||||
tmp[savelinelength] = '\0';
|
||||
ptr = PL_strchr(tmp, ',');
|
||||
PR_ASSERT(ptr);
|
||||
if (!ptr) goto FAIL;
|
||||
*ptr++ = '\0';
|
||||
partname = PL_strrchr(tmp, '.');
|
||||
if (!partname) partname = tmp;
|
||||
else partname++;
|
||||
|
||||
#ifdef DEBUG_slowAndParanoid
|
||||
if (parent->m_partname) {
|
||||
char* parentname = parent->GetFullName();
|
||||
PR_ASSERT(partname > tmp && partname[-1] == '.');
|
||||
partname[-1] = '\0';
|
||||
PR_ASSERT(PL_strcmp(parentname, tmp) == 0);
|
||||
partname[-1] = '.';
|
||||
delete [] parentname;
|
||||
parentname = NULL;
|
||||
} else {
|
||||
PR_ASSERT(partname == tmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
endptr = PL_strchr(ptr, ',');
|
||||
PR_ASSERT(endptr);
|
||||
if (!endptr) goto FAIL;
|
||||
*endptr++ = '\0';
|
||||
prettyname = nsUnescape(ptr);
|
||||
|
||||
ptr = endptr;
|
||||
endptr = PL_strchr(ptr, ',');
|
||||
PR_ASSERT(endptr);
|
||||
if (!endptr) goto FAIL;
|
||||
*endptr++ = '\0';
|
||||
flags = strtol(ptr, NULL, 16);
|
||||
|
||||
ptr = endptr;
|
||||
endptr = PL_strchr(ptr, ',');
|
||||
PR_ASSERT(endptr);
|
||||
if (!endptr) goto FAIL;
|
||||
*endptr++ = '\0';
|
||||
addtime = strtol(ptr, NULL, 16);
|
||||
|
||||
ptr = endptr;
|
||||
uniqueid = strtol(ptr, NULL, 16);
|
||||
|
||||
PRInt64 llAddtime;
|
||||
LL_I2L(llAddtime, addtime);
|
||||
result = Create(parent, partname, llAddtime, uniqueid, fileoffset);
|
||||
if (result) {
|
||||
PRBool maybeCategoryContainer = flags & F_CATCONT;
|
||||
flags &= ~F_CATCONT;
|
||||
result->m_flags = flags;
|
||||
if (maybeCategoryContainer)
|
||||
result->SetIsCategoryContainer(PR_TRUE);
|
||||
if (prettyname && *prettyname) result->SetPrettyName(prettyname);
|
||||
}
|
||||
|
||||
FAIL:
|
||||
PR_Free(tmp);
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,160 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
// This class should only be used by the subscribe UI and by newshost.cpp.
|
||||
// And, well, a bit by the category code. Everyone else should use the stuff
|
||||
// in newshost.h.
|
||||
|
||||
#ifndef _nsMsgGroupRecord_h_
|
||||
#define _nsMsgGroupRecord_h__
|
||||
|
||||
#include "msgCore.h"
|
||||
#include "prtypes.h"
|
||||
#include "nsISupports.h"
|
||||
|
||||
class nsIMAPGroupRecord;
|
||||
|
||||
class NS_MSG_BASE nsMsgGroupRecord {
|
||||
public:
|
||||
static nsMsgGroupRecord* Create(nsMsgGroupRecord* parent,
|
||||
const char* partname,
|
||||
PRInt64 m_addtime,
|
||||
PRInt32 uniqueid,
|
||||
PRInt32 fileoffset);
|
||||
static nsMsgGroupRecord* Create(nsMsgGroupRecord* parent,
|
||||
const char* saveline,
|
||||
PRInt32 savelinelength,
|
||||
PRInt32 fileoffset);
|
||||
|
||||
|
||||
virtual void InitializeSibling();
|
||||
virtual PRBool IsIMAPGroupRecord() { return PR_FALSE; }
|
||||
virtual nsIMAPGroupRecord *GetIMAPGroupRecord() { return 0; }
|
||||
|
||||
// This is just like PL_strcmp(), except it works on news group names.
|
||||
// A container groupname is always less than any contained groups.
|
||||
// So, "netscape.devs-client-technical" > "netscape.devs.directory", even
|
||||
// though PL_strcmp says otherwise. (YICK!)
|
||||
static int GroupNameCompare(const char* name1,
|
||||
const char* name2,
|
||||
char delimiter = '.',
|
||||
PRBool caseInsensitive = PR_FALSE);
|
||||
|
||||
|
||||
virtual ~nsMsgGroupRecord();
|
||||
|
||||
nsMsgGroupRecord* FindDescendant(const char* name);
|
||||
|
||||
nsMsgGroupRecord* GetParent() {return m_parent;}
|
||||
nsMsgGroupRecord* GetChildren() {return m_children;}
|
||||
nsMsgGroupRecord* GetSibling() {return m_sibling;}
|
||||
nsMsgGroupRecord* GetSiblingOrAncestorSibling();
|
||||
nsMsgGroupRecord* GetNextAlphabetic();
|
||||
|
||||
nsMsgGroupRecord* GetNextAlphabeticNoCategories();
|
||||
|
||||
const char* GetPartName() {return m_partname;}
|
||||
|
||||
// The resulting string must be free'd using delete[].
|
||||
char* GetFullName();
|
||||
|
||||
const char* GetPrettyName() {return m_prettyname;}
|
||||
int SetPrettyName(const char* prettyname);
|
||||
|
||||
PRInt64 GetAddTime() {return m_addtime;}
|
||||
|
||||
virtual PRBool IsCategory();
|
||||
virtual PRBool IsCategoryContainer();
|
||||
virtual int SetIsCategoryContainer(PRBool value);
|
||||
|
||||
nsMsgGroupRecord* GetCategoryContainer();
|
||||
|
||||
// Get/Set whether this is a virtual newsgroup.
|
||||
nsresult IsVirtual(PRBool *retval);
|
||||
nsresult SetIsVirtual(PRBool value);
|
||||
|
||||
// Get/Set whether this is really a newsgroup (and not just a container
|
||||
// for newsgroups).
|
||||
virtual PRBool IsGroup();
|
||||
int SetIsGroup(PRBool value);
|
||||
|
||||
PRBool IsDescendentsLoaded();
|
||||
int SetIsDescendentsLoaded(PRBool value);
|
||||
|
||||
PRBool IsExpanded();
|
||||
int SetIsExpanded(PRBool value);
|
||||
|
||||
PRBool IsHTMLOKGroup();
|
||||
int SetIsHTMLOKGroup(PRBool value);
|
||||
|
||||
PRBool IsHTMLOKTree();
|
||||
int SetIsHTMLOKTree(PRBool value);
|
||||
|
||||
PRBool NeedsExtraInfo();
|
||||
int SetNeedsExtraInfo(PRBool value);
|
||||
|
||||
PRBool DoesNotExistOnServer();
|
||||
int SetDoesNotExistOnServer(PRBool value);
|
||||
|
||||
PRInt32 GetUniqueID() {return m_uniqueId;}
|
||||
|
||||
PRInt32 GetFileOffset() {return m_fileoffset;}
|
||||
int SetFileOffset(PRInt32 value) {m_fileoffset = value; return 0;}
|
||||
|
||||
// Get the number of descendents (not including ourself) that are
|
||||
// really newsgroups.
|
||||
PRInt32 GetNumKids();
|
||||
|
||||
// Gets the string that represents this group in the save file. The
|
||||
// resulting string must be free'd with PR_Free().
|
||||
char* GetSaveString();
|
||||
|
||||
PRBool IsDirty(); // Whether this record has had changes made
|
||||
// to it. Cleared by calls to GetSaveString().
|
||||
|
||||
PRInt32 GetDepth(); // Returns how deep in the heirarchy we are.
|
||||
// Basically, the number of dots in the full
|
||||
// newsgroup name, plus 1.
|
||||
virtual char GetHierarchySeparator() { return '.'; }
|
||||
|
||||
protected:
|
||||
nsMsgGroupRecord(nsMsgGroupRecord* parent,
|
||||
const char* partname,
|
||||
PRInt64 m_addtime,
|
||||
PRInt32 uniqueid,
|
||||
PRInt32 fileoffset,
|
||||
char delimiter = '.');
|
||||
int TweakFlag(PRUint32 flagbit, PRBool value);
|
||||
char* SuckInName(char* ptr);
|
||||
|
||||
char* m_partname;
|
||||
char* m_prettyname;
|
||||
nsMsgGroupRecord* m_parent;
|
||||
nsMsgGroupRecord* m_children;
|
||||
nsMsgGroupRecord* m_sibling;
|
||||
PRUint32 m_flags;
|
||||
PRInt64 m_addtime;
|
||||
PRInt32 m_uniqueId;
|
||||
PRInt32 m_fileoffset;
|
||||
char m_delimiter;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* _grec_h_ */
|
||||
@@ -1,363 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
// as does this
|
||||
#define NS_IMPL_IDS
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsICharsetConverterManager.h"
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsIPref.h"
|
||||
#include "nsIMimeConverter.h"
|
||||
#include "msgCore.h"
|
||||
#include "rosetta_mailnews.h"
|
||||
#include "nsMsgI18N.h"
|
||||
#include "nsFileSpec.h"
|
||||
#include "nsFileStream.h"
|
||||
#include "nsMsgMimeCID.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsIEntityConverter.h"
|
||||
#include "nsISaveAsCharset.h"
|
||||
|
||||
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
|
||||
static NS_DEFINE_CID(kCMimeConverterCID, NS_MIME_CONVERTER_CID);
|
||||
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
|
||||
static NS_DEFINE_CID(kEntityConverterCID, NS_ENTITYCONVERTER_CID);
|
||||
static NS_DEFINE_CID(kSaveAsCharsetCID, NS_SAVEASCHARSET_CID);
|
||||
|
||||
//
|
||||
// International functions necessary for composition
|
||||
//
|
||||
|
||||
// Convert an unicode string to a C string with a given charset.
|
||||
nsresult ConvertFromUnicode(const nsString& aCharset,
|
||||
const nsString& inString,
|
||||
char** outCString)
|
||||
{
|
||||
nsresult res;
|
||||
|
||||
NS_WITH_SERVICE(nsICharsetConverterManager, ccm, kCharsetConverterManagerCID, &res);
|
||||
|
||||
if(NS_SUCCEEDED(res) && (nsnull != ccm)) {
|
||||
nsIUnicodeEncoder* encoder = nsnull;
|
||||
nsString convCharset;
|
||||
|
||||
// map to converter charset
|
||||
if (aCharset.EqualsIgnoreCase("us-ascii")) {
|
||||
convCharset.SetString("iso-8859-1");
|
||||
}
|
||||
else {
|
||||
convCharset = aCharset;
|
||||
}
|
||||
|
||||
// get an unicode converter
|
||||
res = ccm->GetUnicodeEncoder(&convCharset, &encoder);
|
||||
if(NS_SUCCEEDED(res) && (nsnull != encoder)) {
|
||||
PRUnichar *unichars = (PRUnichar *) inString.GetUnicode();
|
||||
PRInt32 unicharLength = inString.Length();
|
||||
PRInt32 dstLength;
|
||||
res = encoder->GetMaxLength(unichars, unicharLength, &dstLength);
|
||||
// allocale an output buffer
|
||||
*outCString = (char *) PR_Malloc(dstLength + 1);
|
||||
if (nsnull != *outCString) {
|
||||
PRInt32 oldUnicharLength = unicharLength;
|
||||
char *tempCString = *outCString;
|
||||
PRInt32 totalCLength = 0;
|
||||
while (1) {
|
||||
res = encoder->Convert(unichars, &unicharLength, tempCString, &dstLength);
|
||||
|
||||
// increment for destination
|
||||
tempCString += dstLength;
|
||||
totalCLength += dstLength;
|
||||
|
||||
// break: this is usually the case
|
||||
// source length <= zero and no error or unrecoverable error
|
||||
if (0 >= unicharLength || NS_ERROR_UENC_NOMAPPING != res) {
|
||||
break;
|
||||
}
|
||||
// could not map unicode to the destination charset, skip one unichar and continue
|
||||
// increment for source unicode, skip one unichar
|
||||
unichars += unicharLength + 1;
|
||||
oldUnicharLength -= (unicharLength + 1);
|
||||
unicharLength = oldUnicharLength;
|
||||
// estimate target length again
|
||||
(void) encoder->GetMaxLength(unichars, unicharLength, &dstLength);
|
||||
}
|
||||
(*outCString)[totalCLength] = '\0';
|
||||
}
|
||||
else {
|
||||
res = NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
NS_IF_RELEASE(encoder);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// Convert a C string to an unicode string.
|
||||
nsresult ConvertToUnicode(const nsString& aCharset,
|
||||
const char* inCString,
|
||||
nsString& outString)
|
||||
{
|
||||
nsresult res;
|
||||
NS_WITH_SERVICE(nsICharsetConverterManager, ccm, kCharsetConverterManagerCID, &res);
|
||||
|
||||
if(NS_SUCCEEDED(res) && (nsnull != ccm)) {
|
||||
nsIUnicodeDecoder* decoder = nsnull;
|
||||
PRUnichar *unichars;
|
||||
PRInt32 unicharLength;
|
||||
nsString convCharset;
|
||||
|
||||
// map to converter charset
|
||||
if (aCharset.EqualsIgnoreCase("us-ascii")) {
|
||||
convCharset.SetString("iso-8859-1");
|
||||
}
|
||||
else {
|
||||
convCharset = aCharset;
|
||||
}
|
||||
// get an unicode converter
|
||||
res = ccm->GetUnicodeDecoder(&convCharset, &decoder);
|
||||
if(NS_SUCCEEDED(res) && (nsnull != decoder)) {
|
||||
PRInt32 srcLen = PL_strlen(inCString);
|
||||
res = decoder->GetMaxLength(inCString, srcLen, &unicharLength);
|
||||
// allocale an output buffer
|
||||
unichars = (PRUnichar *) PR_Malloc(unicharLength * sizeof(PRUnichar));
|
||||
if (unichars != nsnull) {
|
||||
// convert to unicode
|
||||
res = decoder->Convert(inCString, &srcLen, unichars, &unicharLength);
|
||||
outString.SetString(unichars, unicharLength);
|
||||
PR_Free(unichars);
|
||||
}
|
||||
else {
|
||||
res = NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
NS_IF_RELEASE(decoder);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// Charset to be used for the internatl processing.
|
||||
const char *msgCompHeaderInternalCharset()
|
||||
{
|
||||
// UTF-8 is a super set of us-ascii.
|
||||
// We can use the same string manipulation methods as us-ascii without breaking non us-ascii characters.
|
||||
return "UTF-8";
|
||||
}
|
||||
|
||||
// MIME encoder, output string should be freed by PR_FREE
|
||||
char * nsMsgI18NEncodeMimePartIIStr(const char *header, const char *charset, PRBool bUseMime)
|
||||
{
|
||||
// No MIME, just duplicate the string.
|
||||
if (PR_FALSE == bUseMime) {
|
||||
return PL_strdup(header);
|
||||
}
|
||||
|
||||
char *encodedString = nsnull;
|
||||
nsIMimeConverter *converter;
|
||||
nsresult res = nsComponentManager::CreateInstance(kCMimeConverterCID, nsnull,
|
||||
nsCOMTypeInfo<nsIMimeConverter>::GetIID(), (void **)&converter);
|
||||
if (NS_SUCCEEDED(res) && nsnull != converter) {
|
||||
res = converter->EncodeMimePartIIStr_UTF8(header, charset, kMIME_ENCODED_WORD_SIZE, &encodedString);
|
||||
NS_RELEASE(converter);
|
||||
}
|
||||
return NS_SUCCEEDED(res) ? encodedString : nsnull;
|
||||
}
|
||||
|
||||
// MIME decoder
|
||||
nsresult nsMsgI18NDecodeMimePartIIStr(const nsString& header, nsString& charset, nsString& decodedString)
|
||||
{
|
||||
nsIMimeConverter *converter;
|
||||
nsresult res = nsComponentManager::CreateInstance(kCMimeConverterCID, nsnull,
|
||||
nsCOMTypeInfo<nsIMimeConverter>::GetIID(), (void **)&converter);
|
||||
if (NS_SUCCEEDED(res) && nsnull != converter) {
|
||||
res = converter->DecodeMimePartIIStr(header, charset, decodedString);
|
||||
NS_RELEASE(converter);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// Get a default mail character set.
|
||||
char * nsMsgI18NGetDefaultMailCharset()
|
||||
{
|
||||
nsresult res = NS_OK;
|
||||
char * retVal = nsnull;
|
||||
NS_WITH_SERVICE(nsIPref, prefs, kPrefCID, &res);
|
||||
if (nsnull != prefs && NS_SUCCEEDED(res))
|
||||
{
|
||||
char *prefValue;
|
||||
res = prefs->CopyCharPref("intl.character_set_name", &prefValue);
|
||||
|
||||
if (NS_SUCCEEDED(res))
|
||||
{
|
||||
//TODO: map to mail charset (e.g. Shift_JIS -> ISO-2022-JP) bug#3941.
|
||||
retVal = prefValue;
|
||||
}
|
||||
else
|
||||
retVal = PL_strdup("iso-8859-1");
|
||||
}
|
||||
|
||||
return (nsnull != retVal) ? retVal : PL_strdup("iso-8859-1");
|
||||
}
|
||||
|
||||
// Return True if a charset is stateful (e.g. JIS).
|
||||
PRBool nsMsgI18Nstateful_charset(const char *charset)
|
||||
{
|
||||
//TODO: use charset manager's service
|
||||
return (PL_strcasecmp(charset, "iso-2022-jp") == 0);
|
||||
}
|
||||
|
||||
// Check 7bit in a given buffer.
|
||||
// This is expensive (both memory and performance).
|
||||
// The check would be very simple if applied to an unicode text (e.g. nsString or utf-8).
|
||||
// Possible optimazaion is to search ESC(0x1B) in case of iso-2022-jp and iso-2022-kr.
|
||||
// Or convert and check line by line.
|
||||
PRBool nsMsgI18N7bit_data_part(const char *charset, const char *inString, const PRUint32 size)
|
||||
{
|
||||
char *aCString;
|
||||
nsString aCharset(charset);
|
||||
nsString outString;
|
||||
nsresult res;
|
||||
|
||||
aCString = (char *) PR_Malloc(size + 1);
|
||||
if (nsnull != aCString) {
|
||||
PL_strncpy(aCString, inString, size); // make a C string
|
||||
res = ConvertToUnicode(aCharset, aCString, outString);
|
||||
PR_Free(aCString);
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
for (PRInt32 i = 0; i < outString.Length(); i++) {
|
||||
if (outString.CharAt(i) > 127) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return PR_TRUE; // all 7 bit
|
||||
}
|
||||
|
||||
// Simple parser to parse META charset.
|
||||
// It only supports the case when the description is within one line.
|
||||
const char *
|
||||
nsMsgI18NParseMetaCharset(nsFileSpec* fileSpec)
|
||||
{
|
||||
static char charset[65];
|
||||
char buffer[512];
|
||||
nsInputFileStream fileStream(*fileSpec);
|
||||
|
||||
*charset = '\0';
|
||||
|
||||
while (!fileStream.eof() && !fileStream.failed() &&
|
||||
fileStream.is_open()) {
|
||||
fileStream.readline(buffer, 512);
|
||||
if (*buffer == CR || *buffer == LF || *buffer == 0)
|
||||
continue;
|
||||
|
||||
for (int i = 0; i < (int)PL_strlen(buffer); i++) {
|
||||
buffer[i] = toupper(buffer[i]);
|
||||
}
|
||||
|
||||
if (PL_strstr(buffer, "/HEAD"))
|
||||
break;
|
||||
|
||||
if (PL_strstr(buffer, "META") &&
|
||||
PL_strstr(buffer, "HTTP-EQUIV") &&
|
||||
PL_strstr(buffer, "CONTENT-TYPE") &&
|
||||
PL_strstr(buffer, "CHARSET")
|
||||
)
|
||||
{
|
||||
char *cp = PL_strstr(PL_strstr(buffer, "CHARSET"), "=") + 1;
|
||||
char seps[] = " \"\'";
|
||||
char *token;
|
||||
char* newStr;
|
||||
token = nsCRT::strtok(cp, seps, &newStr);
|
||||
if (token != NULL)
|
||||
{
|
||||
PL_strcpy(charset, token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return charset;
|
||||
}
|
||||
|
||||
nsresult nsMsgI18NConvertToEntity(const nsString& inString, nsString* outString)
|
||||
{
|
||||
nsresult res;
|
||||
|
||||
outString->SetString("");
|
||||
nsCOMPtr <nsIEntityConverter> entityConv;
|
||||
res = nsComponentManager::CreateInstance(kEntityConverterCID, NULL,
|
||||
nsIEntityConverter::GetIID(), getter_AddRefs(entityConv));
|
||||
if(NS_SUCCEEDED(res)) {
|
||||
PRUnichar *entities = NULL;
|
||||
res = entityConv->ConvertToEntities(inString.GetUnicode(), nsIEntityConverter::html40Latin1, &entities);
|
||||
if (NS_SUCCEEDED(res) && (NULL != entities)) {
|
||||
outString->SetString(entities);
|
||||
nsAllocator::Free(entities);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
nsresult nsMsgI18NSaveAsCharset(const char* contentType, const char *charset, const PRUnichar* inString, char** outString)
|
||||
{
|
||||
NS_ASSERTION(contentType, "null ptr- contentType");
|
||||
NS_ASSERTION(charset, "null ptr- charset");
|
||||
NS_ASSERTION(outString, "null ptr- outString");
|
||||
if(!contentType || !charset || !outString)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
*outString = NULL;
|
||||
|
||||
PRBool bTEXT_HTML = PR_FALSE;
|
||||
nsresult res;
|
||||
|
||||
if (!nsCRT::strcasecmp(contentType, TEXT_HTML)) {
|
||||
bTEXT_HTML = PR_TRUE;
|
||||
}
|
||||
else if (nsCRT::strcasecmp(contentType, TEXT_PLAIN)) {
|
||||
return NS_ERROR_ILLEGAL_VALUE; // not supported type
|
||||
}
|
||||
|
||||
nsCOMPtr <nsISaveAsCharset> aConv; // charset converter plus entity, NCR generation
|
||||
res = nsComponentManager::CreateInstance(kSaveAsCharsetCID, NULL,
|
||||
nsISaveAsCharset::GetIID(), getter_AddRefs(aConv));
|
||||
if(NS_SUCCEEDED(res)) {
|
||||
// attribute:
|
||||
// html text - charset conv then fallback to entity or NCR
|
||||
// plain text - charset conv then fallback to '?'
|
||||
res = aConv->Init(charset,
|
||||
bTEXT_HTML ?
|
||||
nsISaveAsCharset::attr_EntityAfterCharsetConv + nsISaveAsCharset::attr_FallbackDecimalNCR :
|
||||
nsISaveAsCharset::attr_plainTextDefault + nsISaveAsCharset::attr_FallbackQuestionMark,
|
||||
nsIEntityConverter::html40);
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
res = aConv->Convert(inString, outString);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// RICHIE - not sure about this one?? need to see what it did in the old
|
||||
// world.
|
||||
char *
|
||||
nsMsgI18NGetAcceptLanguage(void)
|
||||
{
|
||||
return "en";
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _nsMsgI18N_H_
|
||||
#define _nsMsgI18N_H_
|
||||
|
||||
#include "nscore.h"
|
||||
#include "msgCore.h"
|
||||
|
||||
|
||||
NS_MSG_BASE char *nsMsgI18NEncodeMimePartIIStr(const char *header, const char *charset, PRBool bUseMime);
|
||||
NS_MSG_BASE PRBool nsMsgI18Nstateful_charset(const char *charset);
|
||||
NS_MSG_BASE PRBool nsMsgI18N7bit_data_part(const char *charset, const char *string, const PRUint32 size);
|
||||
NS_MSG_BASE char *nsMsgI18NGetAcceptLanguage(void);
|
||||
|
||||
NS_MSG_BASE const char *msgCompHeaderInternalCharset(void);
|
||||
|
||||
NS_MSG_BASE char * nsMsgI18NGetDefaultMailCharset(void);
|
||||
NS_MSG_BASE nsresult ConvertFromUnicode(const nsString& aCharset,
|
||||
const nsString& inString,
|
||||
char** outCString);
|
||||
NS_MSG_BASE nsresult ConvertToUnicode(const nsString& aCharset,
|
||||
const char* inCString,
|
||||
nsString& outString);
|
||||
|
||||
NS_MSG_BASE nsresult nsMsgI18NDecodeMimePartIIStr(const nsString& header, nsString& charset, nsString& decodedString);
|
||||
|
||||
NS_MSG_BASE const char *nsMsgI18NParseMetaCharset(nsFileSpec* fileSpec);
|
||||
|
||||
NS_MSG_BASE nsresult nsMsgI18NConvertToEntity(const nsString& inString, nsString* outString);
|
||||
|
||||
NS_MSG_BASE nsresult nsMsgI18NSaveAsCharset(const char* contentType, const char* charset, const PRUnichar* inString, char** outString);
|
||||
|
||||
#endif /* _nsMsgI18N_H_ */
|
||||
@@ -1,356 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "msgCore.h" // for pre-compiled headers
|
||||
#include "nsMsgIdentity.h"
|
||||
#include "nsIPref.h"
|
||||
#include "nsXPIDLString.h"
|
||||
|
||||
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsMsgIdentity,
|
||||
nsIMsgIdentity,
|
||||
nsIShutdownListener)
|
||||
|
||||
nsMsgIdentity::nsMsgIdentity():
|
||||
m_signature(0),
|
||||
m_vCard(0),
|
||||
m_identityKey(0),
|
||||
m_prefs(0)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsMsgIdentity::~nsMsgIdentity()
|
||||
{
|
||||
PR_FREEIF(m_identityKey);
|
||||
if (m_prefs) nsServiceManager::ReleaseService(kPrefServiceCID,
|
||||
m_prefs,
|
||||
nsnull);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIdentity::getPrefService()
|
||||
{
|
||||
if (m_prefs) return NS_OK;
|
||||
return nsServiceManager::GetService(kPrefServiceCID,
|
||||
nsCOMTypeInfo<nsIPref>::GetIID(),
|
||||
(nsISupports**)&m_prefs,
|
||||
this);
|
||||
}
|
||||
|
||||
|
||||
/* called if the prefs service goes offline */
|
||||
NS_IMETHODIMP
|
||||
nsMsgIdentity::OnShutdown(const nsCID& aClass, nsISupports *service)
|
||||
{
|
||||
if (aClass.Equals(kPrefServiceCID)) {
|
||||
if (m_prefs) nsServiceManager::ReleaseService(kPrefServiceCID, m_prefs);
|
||||
m_prefs = nsnull;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* accessors for pulling values directly out of preferences
|
||||
* instead of member variables, etc
|
||||
*/
|
||||
|
||||
/* convert an identity key and preference name
|
||||
to mail.identity.<identityKey>.<prefName>
|
||||
*/
|
||||
char *
|
||||
nsMsgIdentity::getPrefName(const char *identityKey,
|
||||
const char *prefName)
|
||||
{
|
||||
return PR_smprintf("mail.identity.%s.%s", identityKey, prefName);
|
||||
}
|
||||
|
||||
// this will be slightly faster than the above, and allows
|
||||
// the "default" identity preference root to be set in one place
|
||||
char *
|
||||
nsMsgIdentity::getDefaultPrefName(const char *fullPrefName)
|
||||
{
|
||||
return PR_smprintf("mail.identity.default.%s", fullPrefName);
|
||||
}
|
||||
|
||||
/* The following are equivalent to the nsIPref's Get/CopyXXXPref
|
||||
except they construct the preference name with the above function
|
||||
*/
|
||||
nsresult
|
||||
nsMsgIdentity::getBoolPref(const char *prefname,
|
||||
PRBool *val)
|
||||
{
|
||||
nsresult rv = getPrefService();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
char *fullPrefName = getPrefName(m_identityKey, prefname);
|
||||
rv = m_prefs->GetBoolPref(fullPrefName, val);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
rv = getDefaultBoolPref(prefname, val);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIdentity::getDefaultBoolPref(const char *prefname,
|
||||
PRBool *val) {
|
||||
|
||||
nsresult rv = getPrefService();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
char *fullPrefName = getDefaultPrefName(prefname);
|
||||
rv = m_prefs->GetBoolPref(fullPrefName, val);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
*val = PR_FALSE;
|
||||
rv = NS_OK;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIdentity::setBoolPref(const char *prefname,
|
||||
PRBool val)
|
||||
{
|
||||
nsresult rv = getPrefService();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
char *prefName = getPrefName(m_identityKey, prefname);
|
||||
rv = m_prefs->SetBoolPref(prefName, val);
|
||||
PR_Free(prefName);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIdentity::getCharPref(const char *prefname,
|
||||
char **val)
|
||||
{
|
||||
nsresult rv = getPrefService();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
char *fullPrefName = getPrefName(m_identityKey, prefname);
|
||||
rv = m_prefs->CopyCharPref(fullPrefName, val);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
rv = getDefaultCharPref(prefname, val);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIdentity::getDefaultCharPref(const char *prefname,
|
||||
char **val)
|
||||
{
|
||||
nsresult rv = getPrefService();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
char *fullPrefName = getDefaultPrefName(prefname);
|
||||
rv = m_prefs->CopyCharPref(fullPrefName, val);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
*val = nsnull; // null is ok to return here
|
||||
rv = NS_OK;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIdentity::setCharPref(const char *prefname,
|
||||
const char *val)
|
||||
{
|
||||
nsresult rv = getPrefService();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = NS_OK;
|
||||
char *prefName = getPrefName(m_identityKey, prefname);
|
||||
if (val)
|
||||
rv = m_prefs->SetCharPref(prefName, val);
|
||||
else
|
||||
m_prefs->ClearUserPref(prefName);
|
||||
PR_Free(prefName);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIdentity::getIntPref(const char *prefname,
|
||||
PRInt32 *val)
|
||||
{
|
||||
nsresult rv = getPrefService();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
char *fullPrefName = getPrefName(m_identityKey, prefname);
|
||||
rv = m_prefs->GetIntPref(fullPrefName, val);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
rv = getDefaultIntPref(prefname, val);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIdentity::getDefaultIntPref(const char *prefname,
|
||||
PRInt32 *val) {
|
||||
|
||||
nsresult rv = getPrefService();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
char *fullPrefName = getDefaultPrefName(prefname);
|
||||
rv = m_prefs->GetIntPref(fullPrefName, val);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
*val = 0;
|
||||
rv = NS_OK;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIdentity::setIntPref(const char *prefname,
|
||||
PRInt32 val)
|
||||
{
|
||||
nsresult rv = getPrefService();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
char *prefName = getPrefName(m_identityKey, prefname);
|
||||
rv = m_prefs->SetIntPref(prefName, val);
|
||||
PR_Free(prefName);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIdentity::SetKey(const char* identityKey)
|
||||
{
|
||||
PR_FREEIF(m_identityKey);
|
||||
m_identityKey = PL_strdup(identityKey);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIdentity::GetIdentityName(char **idName) {
|
||||
if (!idName) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*idName = nsnull;
|
||||
nsresult rv = getCharPref("identityName",idName);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// there's probably a better way of doing this
|
||||
// thats unicode friendly?
|
||||
if (!(*idName)) {
|
||||
nsXPIDLCString fullName;
|
||||
rv = GetFullName(getter_Copies(fullName));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsXPIDLCString email;
|
||||
rv = GetEmail(getter_Copies(email));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
*idName = PR_smprintf("%s <%s>", (const char*)fullName,
|
||||
(const char*)email);
|
||||
rv = NS_OK;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMsgIdentity::SetIdentityName(const char *idName) {
|
||||
return setCharPref("identityName", idName);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIdentity::ToString(PRUnichar **aResult)
|
||||
{
|
||||
nsString idname("[nsIMsgIdentity: ");
|
||||
idname += m_identityKey;
|
||||
idname += "]";
|
||||
|
||||
*aResult = idname.ToNewUnicode();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* Identity attribute accessors */
|
||||
|
||||
// XXX - these are a COM objects, use NS_ADDREF
|
||||
//NS_IMPL_GETSET(nsMsgIdentity, Signature, nsIMsgSignature*, m_signature);
|
||||
NS_IMETHODIMP
|
||||
nsMsgIdentity::GetSignature(nsIFileSpec **sig) {
|
||||
nsresult rv = getPrefService();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
char *prefName = getPrefName(m_identityKey, "sig_file");
|
||||
rv = m_prefs->GetFilePref(prefName, sig);
|
||||
if (NS_FAILED(rv))
|
||||
*sig = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIdentity::SetSignature(nsIFileSpec *sig)
|
||||
{
|
||||
|
||||
nsresult rv = getPrefService();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = NS_OK;
|
||||
char *prefName = getPrefName(m_identityKey, "sig_file");
|
||||
if (sig)
|
||||
rv = m_prefs->SetFilePref(NS_CONST_CAST(const char*,prefName), sig,
|
||||
PR_FALSE);
|
||||
/*
|
||||
else
|
||||
m_prefs->ClearFilePref(prefName);
|
||||
*/
|
||||
PR_Free(prefName);
|
||||
return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_GETSET(nsMsgIdentity, VCard, nsIMsgVCard*, m_vCard);
|
||||
|
||||
NS_IMPL_GETTER_STR(nsMsgIdentity::GetKey, m_identityKey);
|
||||
|
||||
NS_IMPL_IDPREF_STR(FullName, "fullName");
|
||||
NS_IMPL_IDPREF_STR(Email, "useremail");
|
||||
NS_IMPL_IDPREF_STR(ReplyTo, "reply_to");
|
||||
NS_IMPL_IDPREF_STR(Organization, "organization");
|
||||
NS_IMPL_IDPREF_BOOL(ComposeHtml, "compose_html");
|
||||
NS_IMPL_IDPREF_BOOL(AttachVCard, "attach_vcard");
|
||||
NS_IMPL_IDPREF_BOOL(AttachSignature, "attach_signature");
|
||||
|
||||
NS_IMPL_IDPREF_BOOL(DoFcc, "fcc");
|
||||
NS_IMPL_IDPREF_STR(FccFolder, "fcc_folder");
|
||||
|
||||
NS_IMPL_IDPREF_BOOL(BccSelf, "bcc_self");
|
||||
NS_IMPL_IDPREF_BOOL(BccOthers, "bcc_other");
|
||||
NS_IMPL_IDPREF_STR (BccList, "bcc_other_list");
|
||||
|
||||
NS_IMPL_IDPREF_STR (DraftFolder, "draft_folder");
|
||||
NS_IMPL_IDPREF_STR (StationaryFolder, "stationary_folder");
|
||||
NS_IMPL_IDPREF_STR (JunkMailFolder, "spam_folder");
|
||||
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef nsMsgIdentity_h___
|
||||
#define nsMsgIdentity_h___
|
||||
|
||||
#include "nsIMsgIdentity.h"
|
||||
#include "nsIPref.h"
|
||||
#include "msgCore.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// an identity is an object designed to encapsulate all the information we need
|
||||
// to know about a user identity. I expect this interface to grow and change a lot
|
||||
// as we flesh out our thoughts on multiple identities and what properties go into
|
||||
// these identities.
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
class NS_MSG_BASE nsMsgIdentity : public nsIMsgIdentity,
|
||||
public nsIShutdownListener
|
||||
{
|
||||
public:
|
||||
nsMsgIdentity();
|
||||
virtual ~nsMsgIdentity();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIMSGIDENTITY
|
||||
|
||||
// nsIShutdownListener
|
||||
|
||||
NS_IMETHOD OnShutdown(const nsCID& aClass, nsISupports *service);
|
||||
|
||||
private:
|
||||
nsIMsgSignature* m_signature;
|
||||
nsIMsgVCard* m_vCard;
|
||||
char *m_identityKey;
|
||||
nsIPref *m_prefs;
|
||||
|
||||
protected:
|
||||
nsresult getPrefService();
|
||||
char *getPrefName(const char *identityKey, const char *pref);
|
||||
char *getDefaultPrefName(const char *pref);
|
||||
nsresult getCharPref(const char *pref, char **);
|
||||
nsresult getDefaultCharPref(const char *pref, char **);
|
||||
nsresult setCharPref(const char *pref, const char *);
|
||||
|
||||
nsresult getBoolPref(const char *pref, PRBool *);
|
||||
nsresult getDefaultBoolPref(const char *pref, PRBool *);
|
||||
nsresult setBoolPref(const char *pref, PRBool);
|
||||
|
||||
nsresult getIntPref(const char *pref, PRInt32 *);
|
||||
nsresult getDefaultIntPref(const char *pref, PRInt32 *);
|
||||
nsresult setIntPref(const char *pref, PRInt32);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#define NS_IMPL_IDPREF_STR(_postfix, _prefname) \
|
||||
NS_IMETHODIMP \
|
||||
nsMsgIdentity::Get##_postfix(char **retval) \
|
||||
{ \
|
||||
return getCharPref(_prefname, retval); \
|
||||
} \
|
||||
NS_IMETHODIMP \
|
||||
nsMsgIdentity::Set##_postfix(const char *value) \
|
||||
{ \
|
||||
return setCharPref(_prefname, value);\
|
||||
}
|
||||
|
||||
#define NS_IMPL_IDPREF_BOOL(_postfix, _prefname)\
|
||||
NS_IMETHODIMP \
|
||||
nsMsgIdentity::Get##_postfix(PRBool *retval) \
|
||||
{ \
|
||||
return getBoolPref(_prefname, retval); \
|
||||
} \
|
||||
NS_IMETHODIMP \
|
||||
nsMsgIdentity::Set##_postfix(PRBool value) \
|
||||
{ \
|
||||
return setBoolPref(_prefname, value); \
|
||||
}
|
||||
|
||||
#define NS_IMPL_IDPREF_INT(_postfix, _prefname) \
|
||||
NS_IMETHODIMP \
|
||||
nsMsgIdentity::Get##_postfix(PRInt32 *retval) \
|
||||
{ \
|
||||
return getIntPref(_prefname, retval); \
|
||||
} \
|
||||
NS_IMETHODIMP \
|
||||
nsMsgIdentity::Set##_postfix(PRInt32 value) \
|
||||
{ \
|
||||
return setIntPref(_prefname, value); \
|
||||
}
|
||||
|
||||
|
||||
#endif /* nsMsgIdentity_h___ */
|
||||
@@ -1,603 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsMsgIncomingServer.h"
|
||||
#include "nscore.h"
|
||||
#include "nsCom.h"
|
||||
#include "plstr.h"
|
||||
#include "prmem.h"
|
||||
#include "prprf.h"
|
||||
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIPref.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIMsgFolder.h"
|
||||
#include "nsIMsgFolderCache.h"
|
||||
#include "nsIMsgFolderCacheElement.h"
|
||||
#include "nsINetSupportDialogService.h"
|
||||
#include "nsIPrompt.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIMsgProtocolInfo.h"
|
||||
#include "nsRDFCID.h"
|
||||
|
||||
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
|
||||
static NS_DEFINE_CID(kNetSupportDialogCID, NS_NETSUPPORTDIALOG_CID);
|
||||
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsMsgIncomingServer);
|
||||
|
||||
nsMsgIncomingServer::nsMsgIncomingServer():
|
||||
m_prefs(0),
|
||||
m_serverKey(0),
|
||||
m_rootFolder(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsMsgIncomingServer);
|
||||
|
||||
NS_INIT_REFCNT();
|
||||
m_serverBusy = PR_FALSE;
|
||||
m_password = "";
|
||||
}
|
||||
|
||||
nsMsgIncomingServer::~nsMsgIncomingServer()
|
||||
{
|
||||
|
||||
MOZ_COUNT_DTOR(nsMsgIncomingServer);
|
||||
|
||||
if (m_prefs) nsServiceManager::ReleaseService(kPrefServiceCID,
|
||||
m_prefs,
|
||||
nsnull);
|
||||
PR_FREEIF(m_serverKey)
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsMsgIncomingServer, nsIMsgIncomingServer)
|
||||
|
||||
NS_IMPL_GETSET(nsMsgIncomingServer, ServerBusy, PRBool, m_serverBusy)
|
||||
NS_IMPL_GETTER_STR(nsMsgIncomingServer::GetKey, m_serverKey)
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::SetKey(const char * serverKey)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
// in order to actually make use of the key, we need the prefs
|
||||
if (!m_prefs)
|
||||
rv = nsServiceManager::GetService(kPrefServiceCID,
|
||||
nsCOMTypeInfo<nsIPref>::GetIID(),
|
||||
(nsISupports**)&m_prefs);
|
||||
|
||||
PR_FREEIF(m_serverKey);
|
||||
m_serverKey = PL_strdup(serverKey);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::SetRootFolder(nsIFolder * aRootFolder)
|
||||
{
|
||||
m_rootFolder = aRootFolder;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::GetRootFolder(nsIFolder * *aRootFolder)
|
||||
{
|
||||
if (!aRootFolder)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
if (m_rootFolder) {
|
||||
*aRootFolder = m_rootFolder;
|
||||
NS_ADDREF(*aRootFolder);
|
||||
} else {
|
||||
nsresult rv = CreateRootFolder();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
*aRootFolder = m_rootFolder;
|
||||
NS_IF_ADDREF(*aRootFolder);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::PerformBiff()
|
||||
{
|
||||
//This had to be implemented in the derived class, but in case someone doesn't implement it
|
||||
//just return not implemented.
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgIncomingServer::WriteToFolderCache(nsIMsgFolderCache *folderCache)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
if (m_rootFolder)
|
||||
{
|
||||
nsCOMPtr <nsIMsgFolder> msgFolder = do_QueryInterface(m_rootFolder, &rv);
|
||||
if (NS_SUCCEEDED(rv) && msgFolder)
|
||||
rv = msgFolder->WriteToFolderCache(folderCache);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::CloseCachedConnections()
|
||||
{
|
||||
// derived class should override if they cache connections.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::GetServerURI(char **)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIncomingServer::CreateRootFolder()
|
||||
{
|
||||
nsresult rv;
|
||||
// get the URI from the incoming server
|
||||
nsXPIDLCString serverUri;
|
||||
rv = GetServerURI(getter_Copies(serverUri));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
NS_WITH_SERVICE(nsIRDFService, rdf,
|
||||
kRDFServiceCID, &rv);
|
||||
|
||||
// get the corresponding RDF resource
|
||||
// RDF will create the server resource if it doesn't already exist
|
||||
nsCOMPtr<nsIRDFResource> serverResource;
|
||||
rv = rdf->GetResource(serverUri, getter_AddRefs(serverResource));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// make incoming server know about its root server folder so we
|
||||
// can find sub-folders given an incoming server.
|
||||
m_rootFolder = do_QueryInterface(serverResource, &rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
char *
|
||||
nsMsgIncomingServer::getPrefName(const char *serverKey,
|
||||
const char *fullPrefName)
|
||||
{
|
||||
return PR_smprintf("mail.server.%s.%s", serverKey, fullPrefName);
|
||||
}
|
||||
|
||||
// this will be slightly faster than the above, and allows
|
||||
// the "default" server preference root to be set in one place
|
||||
char *
|
||||
nsMsgIncomingServer::getDefaultPrefName(const char *fullPrefName)
|
||||
{
|
||||
return PR_smprintf("mail.server.default.%s", fullPrefName);
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsMsgIncomingServer::GetBoolValue(const char *prefname,
|
||||
PRBool *val)
|
||||
{
|
||||
char *fullPrefName = getPrefName(m_serverKey, prefname);
|
||||
nsresult rv = m_prefs->GetBoolPref(fullPrefName, val);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
rv = getDefaultBoolPref(prefname, val);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIncomingServer::getDefaultBoolPref(const char *prefname,
|
||||
PRBool *val) {
|
||||
|
||||
char *fullPrefName = getDefaultPrefName(prefname);
|
||||
nsresult rv = m_prefs->GetBoolPref(fullPrefName, val);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
*val = PR_FALSE;
|
||||
rv = NS_OK;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIncomingServer::SetBoolValue(const char *prefname,
|
||||
PRBool val)
|
||||
{
|
||||
nsresult rv;
|
||||
char *fullPrefName = getPrefName(m_serverKey, prefname);
|
||||
|
||||
PRBool defaultValue;
|
||||
rv = getDefaultBoolPref(prefname, &defaultValue);
|
||||
|
||||
if (NS_SUCCEEDED(rv) &&
|
||||
val == defaultValue)
|
||||
m_prefs->ClearUserPref(fullPrefName);
|
||||
else
|
||||
rv = m_prefs->SetBoolPref(fullPrefName, val);
|
||||
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIncomingServer::GetIntValue(const char *prefname,
|
||||
PRInt32 *val)
|
||||
{
|
||||
char *fullPrefName = getPrefName(m_serverKey, prefname);
|
||||
nsresult rv = m_prefs->GetIntPref(fullPrefName, val);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
rv = getDefaultIntPref(prefname, val);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIncomingServer::GetFileValue(const char* prefname,
|
||||
nsIFileSpec **spec)
|
||||
{
|
||||
char *fullPrefName = getPrefName(m_serverKey, prefname);
|
||||
nsresult rv = m_prefs->GetFilePref(fullPrefName, spec);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIncomingServer::SetFileValue(const char* prefname,
|
||||
nsIFileSpec *spec)
|
||||
{
|
||||
char *fullPrefName = getPrefName(m_serverKey, prefname);
|
||||
nsresult rv = m_prefs->SetFilePref(fullPrefName, spec, PR_FALSE);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIncomingServer::getDefaultIntPref(const char *prefname,
|
||||
PRInt32 *val) {
|
||||
|
||||
char *fullPrefName = getDefaultPrefName(prefname);
|
||||
nsresult rv = m_prefs->GetIntPref(fullPrefName, val);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
*val = 0;
|
||||
rv = NS_OK;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIncomingServer::SetIntValue(const char *prefname,
|
||||
PRInt32 val)
|
||||
{
|
||||
nsresult rv;
|
||||
char *fullPrefName = getPrefName(m_serverKey, prefname);
|
||||
|
||||
PRInt32 defaultVal;
|
||||
rv = getDefaultIntPref(prefname, &defaultVal);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && defaultVal == val)
|
||||
m_prefs->ClearUserPref(fullPrefName);
|
||||
else
|
||||
rv = m_prefs->SetIntPref(fullPrefName, val);
|
||||
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIncomingServer::GetCharValue(const char *prefname,
|
||||
char **val)
|
||||
{
|
||||
char *fullPrefName = getPrefName(m_serverKey, prefname);
|
||||
nsresult rv = m_prefs->CopyCharPref(fullPrefName, val);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
rv = getDefaultCharPref(prefname, val);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIncomingServer::getDefaultCharPref(const char *prefname,
|
||||
char **val) {
|
||||
|
||||
char *fullPrefName = getDefaultPrefName(prefname);
|
||||
nsresult rv = m_prefs->CopyCharPref(fullPrefName, val);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
*val = nsnull; // null is ok to return here
|
||||
rv = NS_OK;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgIncomingServer::SetCharValue(const char *prefname,
|
||||
const char * val)
|
||||
{
|
||||
nsresult rv;
|
||||
char *fullPrefName = getPrefName(m_serverKey, prefname);
|
||||
|
||||
if (!val) {
|
||||
m_prefs->ClearUserPref(fullPrefName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
char *defaultVal=nsnull;
|
||||
rv = getDefaultCharPref(prefname, &defaultVal);
|
||||
|
||||
if (NS_SUCCEEDED(rv) &&
|
||||
PL_strcmp(defaultVal, val) == 0)
|
||||
m_prefs->ClearUserPref(fullPrefName);
|
||||
else
|
||||
rv = m_prefs->SetCharPref(fullPrefName, val);
|
||||
|
||||
PR_FREEIF(defaultVal);
|
||||
PR_Free(fullPrefName);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// pretty name is the display name to show to the user
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::GetPrettyName(PRUnichar **retval) {
|
||||
|
||||
char *val=nsnull;
|
||||
nsresult rv = GetCharValue("name", &val);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsString prettyName;
|
||||
|
||||
// if there's no name, then just return the hostname
|
||||
if (val) {
|
||||
prettyName = val;
|
||||
} else {
|
||||
|
||||
nsXPIDLCString username;
|
||||
rv = GetUsername(getter_Copies(username));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if ((const char*)username &&
|
||||
PL_strcmp((const char*)username, "")!=0) {
|
||||
prettyName = username;
|
||||
prettyName += " on ";
|
||||
}
|
||||
|
||||
nsXPIDLCString hostname;
|
||||
rv = GetHostName(getter_Copies(hostname));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
|
||||
prettyName += hostname;
|
||||
}
|
||||
|
||||
*retval = prettyName.ToNewUnicode();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::SetPrettyName(const PRUnichar *value) {
|
||||
// this is lossy. Not sure what to do.
|
||||
nsCString str(value);
|
||||
return SetCharValue("name", str.GetBuffer());
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::ToString(PRUnichar** aResult) {
|
||||
nsString servername("[nsIMsgIncomingServer: ");
|
||||
servername += m_serverKey;
|
||||
servername += "]";
|
||||
|
||||
*aResult = servername.ToNewUnicode();
|
||||
NS_ASSERTION(*aResult, "no server name!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMsgIncomingServer::SetPassword(const char * aPassword)
|
||||
{
|
||||
// if remember password is turned on, write the password to preferences
|
||||
// otherwise, just set the password so we remember it for the rest of the current
|
||||
// session.
|
||||
|
||||
PRBool rememberPassword = PR_FALSE;
|
||||
GetRememberPassword(&rememberPassword);
|
||||
|
||||
if (rememberPassword)
|
||||
{
|
||||
SetPrefPassword((char *) aPassword);
|
||||
}
|
||||
|
||||
m_password = aPassword;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgIncomingServer::GetPassword(char ** aPassword)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
PRBool rememberPassword = PR_FALSE;
|
||||
// okay, here's the scoop for this messs...
|
||||
// (1) if we have a password already, go ahead and use it!
|
||||
// (2) if remember password is turned on, try reading in from the prefs and if we have one, go ahead
|
||||
// and use it
|
||||
// (3) otherwise prompt the user for a password and then remember that password in the server
|
||||
|
||||
if (m_password.IsEmpty())
|
||||
{
|
||||
|
||||
// case (2)
|
||||
GetRememberPassword(&rememberPassword);
|
||||
if (rememberPassword)
|
||||
{
|
||||
nsXPIDLCString password;
|
||||
GetPrefPassword(getter_Copies(password));
|
||||
m_password = password;
|
||||
}
|
||||
}
|
||||
|
||||
*aPassword = m_password.ToNewCString();
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::GetPasswordWithUI(const PRUnichar * aPromptMessage, char **aPassword)
|
||||
{
|
||||
|
||||
nsXPIDLCString prefvalue;
|
||||
GetPassword(getter_Copies(prefvalue));
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
if (m_password.IsEmpty()) {
|
||||
// prompt the user for the password
|
||||
NS_WITH_SERVICE(nsIPrompt, dialog, kNetSupportDialogCID, &rv);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
PRUnichar * uniPassword;
|
||||
PRBool okayValue = PR_TRUE;
|
||||
dialog->PromptPassword(aPromptMessage, &uniPassword, &okayValue);
|
||||
|
||||
if (!okayValue) // if the user pressed cancel, just return NULL;
|
||||
{
|
||||
*aPassword = nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
// we got a password back...so remember it
|
||||
nsCString aCStr(uniPassword);
|
||||
|
||||
SetPassword((const char *) aCStr);
|
||||
} // if we got a prompt dialog
|
||||
} // if the password is empty
|
||||
|
||||
*aPassword = m_password.ToNewCString();
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::SetDefaultLocalPath(nsIFileSpec *aDefaultLocalPath)
|
||||
{
|
||||
nsresult rv;
|
||||
nsXPIDLCString type;
|
||||
GetType(getter_Copies(type));
|
||||
|
||||
nsCAutoString progid(NS_MSGPROTOCOLINFO_PROGID_PREFIX);
|
||||
progid += type;
|
||||
|
||||
NS_WITH_SERVICE(nsIMsgProtocolInfo, protocolInfo, progid, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = protocolInfo->SetDefaultLocalPath(aDefaultLocalPath);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::GetLocalPath(nsIFileSpec **aLocalPath)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// if the local path has already been set, use it
|
||||
rv = GetFileValue("directory", aLocalPath);
|
||||
if (NS_SUCCEEDED(rv) && *aLocalPath) return rv;
|
||||
|
||||
// otherwise, create the path using. note we are using the
|
||||
// server key instead of the hostname
|
||||
//
|
||||
// TODO: handle the case where they migrated a server of hostname "server4"
|
||||
// and we create a server (with the account wizard) with key "server4"
|
||||
// we'd get a collision.
|
||||
// need to modify the code that creates keys to check for disk collision
|
||||
nsXPIDLCString type;
|
||||
GetType(getter_Copies(type));
|
||||
|
||||
nsCAutoString progid(NS_MSGPROTOCOLINFO_PROGID_PREFIX);
|
||||
progid += type;
|
||||
|
||||
NS_WITH_SERVICE(nsIMsgProtocolInfo, protocolInfo, progid, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIFileSpec> path;
|
||||
rv = protocolInfo->GetDefaultLocalPath(getter_AddRefs(path));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
path->CreateDir();
|
||||
|
||||
nsXPIDLCString key;
|
||||
rv = GetKey(getter_Copies(key));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = path->AppendRelativeUnixPath(key);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = SetLocalPath(path);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
*aLocalPath = path;
|
||||
NS_ADDREF(*aLocalPath);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::SetLocalPath(nsIFileSpec *spec)
|
||||
{
|
||||
if (spec) {
|
||||
spec->CreateDir();
|
||||
return SetFileValue("directory", spec);
|
||||
}
|
||||
else {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::SetRememberPassword(PRBool value)
|
||||
{
|
||||
if (value)
|
||||
SetPrefPassword(m_password);
|
||||
else
|
||||
SetPrefPassword(nsnull);
|
||||
return SetBoolValue("remember_password", value);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgIncomingServer::GetRememberPassword(PRBool* value)
|
||||
{
|
||||
return GetBoolValue("remember_password", value);
|
||||
}
|
||||
|
||||
// use the convenience macros to implement the accessors
|
||||
NS_IMPL_SERVERPREF_STR(nsMsgIncomingServer, HostName, "hostname");
|
||||
NS_IMPL_SERVERPREF_STR(nsMsgIncomingServer, Username, "userName");
|
||||
NS_IMPL_SERVERPREF_STR(nsMsgIncomingServer, PrefPassword, "password");
|
||||
NS_IMPL_SERVERPREF_BOOL(nsMsgIncomingServer, DoBiff, "check_new_mail");
|
||||
NS_IMPL_SERVERPREF_INT(nsMsgIncomingServer, BiffMinutes, "check_time");
|
||||
NS_IMPL_SERVERPREF_STR(nsMsgIncomingServer, Type, "type");
|
||||
|
||||
/* what was this called in 4.x? */
|
||||
// pref("mail.pop3_gets_new_mail", true);
|
||||
|
||||
NS_IMPL_SERVERPREF_BOOL(nsMsgIncomingServer, DownloadOnBiff, "download_on_biff");
|
||||
@@ -1,70 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef nsMsgIncomingServer_h__
|
||||
#define nsMsgIncomingServer_h__
|
||||
|
||||
#include "nsIMsgIncomingServer.h"
|
||||
#include "nsIPref.h"
|
||||
#include "msgCore.h"
|
||||
#include "nsIFolder.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsIMsgFolderCache;
|
||||
|
||||
/*
|
||||
* base class for nsIMsgIncomingServer - derive your class from here
|
||||
* if you want to get some free implementation
|
||||
*
|
||||
* this particular implementation is not meant to be used directly.
|
||||
*/
|
||||
|
||||
class NS_MSG_BASE nsMsgIncomingServer : public nsIMsgIncomingServer {
|
||||
public:
|
||||
nsMsgIncomingServer();
|
||||
virtual ~nsMsgIncomingServer();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_DECL_NSIMSGINCOMINGSERVER
|
||||
|
||||
private:
|
||||
nsIPref *m_prefs;
|
||||
char *m_serverKey;
|
||||
nsCString m_password;
|
||||
PRBool m_serverBusy;
|
||||
|
||||
protected:
|
||||
char *getPrefName(const char *serverKey, const char *pref);
|
||||
char *getDefaultPrefName(const char *pref);
|
||||
|
||||
// these are private pref getters and setters for the password
|
||||
// field. Callers should be using Get/Set Password
|
||||
NS_IMETHOD GetPrefPassword(char * *aPassword);
|
||||
NS_IMETHOD SetPrefPassword(const char * aPassword);
|
||||
|
||||
nsCOMPtr <nsIFolder> m_rootFolder;
|
||||
nsresult getDefaultCharPref(const char *pref, char **);
|
||||
nsresult getDefaultBoolPref(const char *pref, PRBool *);
|
||||
nsresult getDefaultIntPref(const char *pref, PRInt32 *);
|
||||
|
||||
nsresult CreateRootFolder();
|
||||
|
||||
};
|
||||
|
||||
#endif // nsMsgIncomingServer_h__
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,115 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _nsMsgKeySet_H_
|
||||
#define _nsMsgKeySet_H_
|
||||
|
||||
#include "msgCore.h"
|
||||
|
||||
// nsMsgKeySet represents a set of articles. Typically, it is the set of
|
||||
// read articles from a .newsrc file, but it can be used for other purposes
|
||||
// too.
|
||||
|
||||
#if 0
|
||||
// If a MSG_NewsHost* is supplied to the creation routine, then that
|
||||
// MSG_NewsHost will be notified whenever a change is made to set.
|
||||
class MSG_NewsHost;
|
||||
#endif
|
||||
|
||||
class NS_MSG_BASE nsMsgKeySet {
|
||||
public:
|
||||
// Creates an empty set.
|
||||
static nsMsgKeySet* Create(/* MSG_NewsHost* host = NULL*/);
|
||||
|
||||
// Creates a set from the list of numbers, as might be found in a
|
||||
// newsrc file.
|
||||
static nsMsgKeySet* Create(const char* str/* , MSG_NewsHost* host = NULL*/);
|
||||
~nsMsgKeySet();
|
||||
|
||||
// FirstNonMember() returns the lowest non-member of the set that is
|
||||
// greater than 0.
|
||||
PRInt32 FirstNonMember();
|
||||
|
||||
// Output() converts to a string representation suitable for writing to a
|
||||
// .newsrc file. (The result must be freed by the caller using delete[].)
|
||||
char* Output();
|
||||
|
||||
// IsMember() returns whether the given article is a member of this set.
|
||||
PRBool IsMember(PRInt32 art);
|
||||
|
||||
// Add() adds the given article to the set. (Returns 1 if a change was
|
||||
// made, 0 if it was already there, and negative on error.)
|
||||
int Add(PRInt32 art);
|
||||
|
||||
// Remove() removes the given article from the set.
|
||||
int Remove(PRInt32 art);
|
||||
|
||||
// AddRange() adds the (inclusive) given range of articles to the set.
|
||||
int AddRange(PRInt32 first, PRInt32 last);
|
||||
|
||||
// CountMissingInRange() takes an inclusive range of articles and returns
|
||||
// the number of articles in that range which are not in the set.
|
||||
PRInt32 CountMissingInRange(PRInt32 start, PRInt32 end);
|
||||
|
||||
// FirstMissingRange() takes an inclusive range and finds the first range
|
||||
// of articles that are not in the set. If none, return zeros.
|
||||
int FirstMissingRange(PRInt32 min, PRInt32 max, PRInt32* first, PRInt32* last);
|
||||
|
||||
|
||||
// LastMissingRange() takes an inclusive range and finds the last range
|
||||
// of articles that are not in the set. If none, return zeros.
|
||||
int LastMissingRange(PRInt32 min, PRInt32 max, PRInt32* first, PRInt32* last);
|
||||
|
||||
PRInt32 GetLastMember();
|
||||
PRInt32 GetFirstMember();
|
||||
void SetLastMember(PRInt32 highWaterMark);
|
||||
// For debugging only...
|
||||
PRInt32 getLength() {return m_length;}
|
||||
|
||||
#ifdef DEBUG
|
||||
static void RunTests();
|
||||
#endif
|
||||
|
||||
protected:
|
||||
nsMsgKeySet(/* MSG_NewsHost* host */);
|
||||
nsMsgKeySet(const char* /* , MSG_NewsHost* host */);
|
||||
PRBool Grow();
|
||||
PRBool Optimize();
|
||||
|
||||
#ifdef DEBUG
|
||||
static void test_decoder(const char*);
|
||||
static void test_adder();
|
||||
static void test_ranges();
|
||||
static void test_member(PRBool with_cache);
|
||||
#endif
|
||||
|
||||
PRInt32 *m_data; /* the numbers composing the `chunks' */
|
||||
PRInt32 m_data_size; /* size of that malloc'ed block */
|
||||
PRInt32 m_length; /* active area */
|
||||
|
||||
PRInt32 m_cached_value; /* a potential set member, or -1 if unset*/
|
||||
PRInt32 m_cached_value_index; /* the index into `data' at which a search
|
||||
to determine whether `cached_value' was
|
||||
a member of the set ended. */
|
||||
#ifdef NEWSRC_DOES_HOST_STUFF
|
||||
MSG_NewsHost* m_host;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#endif /* _nsMsgKeySet_H_ */
|
||||
@@ -1,384 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "msgCore.h"
|
||||
#include "prlog.h"
|
||||
#include "nsMsgLineBuffer.h"
|
||||
|
||||
#include "nsIInputStream.h" // used by nsMsgLineStreamBuffer
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsByteArray);
|
||||
|
||||
nsByteArray::nsByteArray()
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsByteArray);
|
||||
m_buffer = NULL;
|
||||
m_bufferSize = 0;
|
||||
m_bufferPos = 0;
|
||||
}
|
||||
|
||||
nsByteArray::~nsByteArray()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsByteArray);
|
||||
PR_FREEIF(m_buffer);
|
||||
}
|
||||
|
||||
nsresult nsByteArray::GrowBuffer(PRUint32 desired_size, PRUint32 quantum)
|
||||
{
|
||||
if (m_bufferSize < desired_size)
|
||||
{
|
||||
char *new_buf;
|
||||
PRUint32 increment = desired_size - m_bufferSize;
|
||||
if (increment < quantum) /* always grow by a minimum of N bytes */
|
||||
increment = quantum;
|
||||
|
||||
|
||||
new_buf = (m_buffer
|
||||
? (char *) PR_REALLOC (m_buffer, (m_bufferSize + increment))
|
||||
: (char *) PR_MALLOC (m_bufferSize + increment));
|
||||
if (! new_buf)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
m_buffer = new_buf;
|
||||
m_bufferSize += increment;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
nsresult nsByteArray::AppendString(const char *string)
|
||||
{
|
||||
PRUint32 strLength = (string) ? PL_strlen(string) : 0;
|
||||
return AppendBuffer(string, strLength);
|
||||
|
||||
}
|
||||
|
||||
nsresult nsByteArray::AppendBuffer(const char *buffer, PRUint32 length)
|
||||
{
|
||||
nsresult ret = NS_OK;
|
||||
if (m_bufferPos + length > m_bufferSize)
|
||||
ret = GrowBuffer(m_bufferPos + length, 1024);
|
||||
if (ret == NS_OK)
|
||||
{
|
||||
memcpy(m_buffer + m_bufferPos, buffer, length);
|
||||
m_bufferPos += length;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsMsgLineBuffer);
|
||||
|
||||
nsMsgLineBuffer::nsMsgLineBuffer(nsMsgLineBufferHandler *handler, PRBool convertNewlinesP)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsMsgLineBuffer);
|
||||
m_handler = handler;
|
||||
m_convertNewlinesP = convertNewlinesP;
|
||||
m_lookingForCRLF = PR_TRUE;
|
||||
}
|
||||
|
||||
nsMsgLineBuffer::~nsMsgLineBuffer()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsMsgLineBuffer);
|
||||
}
|
||||
|
||||
void
|
||||
nsMsgLineBuffer::SetLookingForCRLF(PRBool b)
|
||||
{
|
||||
m_lookingForCRLF = b;
|
||||
}
|
||||
|
||||
PRInt32 nsMsgLineBuffer::BufferInput(const char *net_buffer, PRInt32 net_buffer_size)
|
||||
{
|
||||
int status = 0;
|
||||
if (m_bufferPos > 0 && m_buffer && m_buffer[m_bufferPos - 1] == CR &&
|
||||
net_buffer_size > 0 && net_buffer[0] != LF) {
|
||||
/* The last buffer ended with a CR. The new buffer does not start
|
||||
with a LF. This old buffer should be shipped out and discarded. */
|
||||
PR_ASSERT(m_bufferSize > m_bufferPos);
|
||||
if (m_bufferSize <= m_bufferPos) return -1;
|
||||
status = ConvertAndSendBuffer();
|
||||
if (status < 0)
|
||||
return status;
|
||||
m_bufferPos = 0;
|
||||
}
|
||||
while (net_buffer_size > 0)
|
||||
{
|
||||
const char *net_buffer_end = net_buffer + net_buffer_size;
|
||||
const char *newline = 0;
|
||||
const char *s;
|
||||
|
||||
|
||||
for (s = net_buffer; s < net_buffer_end; s++)
|
||||
{
|
||||
if (m_lookingForCRLF) {
|
||||
/* Move forward in the buffer until the first newline.
|
||||
Stop when we see CRLF, CR, or LF, or the end of the buffer.
|
||||
*But*, if we see a lone CR at the *very end* of the buffer,
|
||||
treat this as if we had reached the end of the buffer without
|
||||
seeing a line terminator. This is to catch the case of the
|
||||
buffers splitting a CRLF pair, as in "FOO\r\nBAR\r" "\nBAZ\r\n".
|
||||
*/
|
||||
if (*s == CR || *s == LF) {
|
||||
newline = s;
|
||||
if (newline[0] == CR) {
|
||||
if (s == net_buffer_end - 1) {
|
||||
/* CR at end - wait for the next character. */
|
||||
newline = 0;
|
||||
break;
|
||||
}
|
||||
else if (newline[1] == LF) {
|
||||
/* CRLF seen; swallow both. */
|
||||
newline++;
|
||||
}
|
||||
}
|
||||
newline++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* if not looking for a CRLF, stop at CR or LF. (for example, when parsing the newsrc file). this fixes #9896, where we'd lose the last line of anything we'd parse that used CR as the line break. */
|
||||
if (*s == CR || *s == LF) {
|
||||
newline = s;
|
||||
newline++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure room in the net_buffer and append some or all of the current
|
||||
chunk of data to it. */
|
||||
{
|
||||
const char *end = (newline ? newline : net_buffer_end);
|
||||
PRUint32 desired_size = (end - net_buffer) + m_bufferPos + 1;
|
||||
|
||||
if (desired_size >= m_bufferSize)
|
||||
{
|
||||
status = GrowBuffer (desired_size, 1024);
|
||||
if (status < 0)
|
||||
return status;
|
||||
}
|
||||
memcpy (m_buffer + m_bufferPos, net_buffer, (end - net_buffer));
|
||||
m_bufferPos += (end - net_buffer);
|
||||
}
|
||||
|
||||
/* Now m_buffer contains either a complete line, or as complete
|
||||
a line as we have read so far.
|
||||
|
||||
If we have a line, process it, and then remove it from `m_buffer'.
|
||||
Then go around the loop again, until we drain the incoming data.
|
||||
*/
|
||||
if (!newline)
|
||||
return 0;
|
||||
|
||||
status = ConvertAndSendBuffer();
|
||||
if (status < 0) return status;
|
||||
|
||||
net_buffer_size -= (newline - net_buffer);
|
||||
net_buffer = newline;
|
||||
m_bufferPos = 0;
|
||||
}
|
||||
#ifdef DEBUG_bienvenu
|
||||
printf("returning from buffer input m_bufferPos = %ld\n", m_bufferPos);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRInt32 nsMsgLineBuffer::HandleLine(char *line, PRUint32 line_length)
|
||||
{
|
||||
NS_ASSERTION(PR_FALSE, "must override this method if you don't provide a handler");
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRInt32 nsMsgLineBuffer::ConvertAndSendBuffer()
|
||||
{
|
||||
/* Convert the line terminator to the native form.
|
||||
*/
|
||||
|
||||
char *buf = m_buffer;
|
||||
PRInt32 length = m_bufferPos;
|
||||
|
||||
char* newline;
|
||||
|
||||
PR_ASSERT(buf && length > 0);
|
||||
if (!buf || length <= 0)
|
||||
return -1;
|
||||
newline = buf + length;
|
||||
|
||||
PR_ASSERT(newline[-1] == CR || newline[-1] == LF);
|
||||
if (newline[-1] != CR && newline[-1] != LF)
|
||||
return -1;
|
||||
|
||||
if (!m_convertNewlinesP)
|
||||
{
|
||||
}
|
||||
#if (MSG_LINEBREAK_LEN == 1)
|
||||
else if ((newline - buf) >= 2 &&
|
||||
newline[-2] == CR &&
|
||||
newline[-1] == LF)
|
||||
{
|
||||
/* CRLF -> CR or LF */
|
||||
buf [length - 2] = MSG_LINEBREAK[0];
|
||||
length--;
|
||||
}
|
||||
else if (newline > buf + 1 &&
|
||||
newline[-1] != MSG_LINEBREAK[0])
|
||||
{
|
||||
/* CR -> LF or LF -> CR */
|
||||
buf [length - 1] = MSG_LINEBREAK[0];
|
||||
}
|
||||
#else
|
||||
else if (((newline - buf) >= 2 && newline[-2] != CR) ||
|
||||
((newline - buf) >= 1 && newline[-1] != LF))
|
||||
{
|
||||
/* LF -> CRLF or CR -> CRLF */
|
||||
length++;
|
||||
buf[length - 2] = MSG_LINEBREAK[0];
|
||||
buf[length - 1] = MSG_LINEBREAK[1];
|
||||
}
|
||||
#endif
|
||||
|
||||
return (m_handler) ? m_handler->HandleLine(buf, length) : HandleLine(buf, length);
|
||||
}
|
||||
|
||||
// If there's still some data (non CRLF terminated) flush it out
|
||||
PRInt32 nsMsgLineBuffer::FlushLastLine()
|
||||
{
|
||||
char *buf = m_buffer + m_bufferPos;
|
||||
PRInt32 length = m_bufferPos - 1;
|
||||
if (length > 0)
|
||||
return (m_handler) ? m_handler->HandleLine(buf, length) : HandleLine(buf, length);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This is a utility class used to efficiently extract lines from an input stream by buffering
|
||||
// read but unprocessed stream data in a buffer.
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsMsgLineStreamBuffer::nsMsgLineStreamBuffer(PRUint32 aBufferSize, const char * aEndOfLineToken,
|
||||
PRBool aAllocateNewLines, PRBool aEatCRLFs)
|
||||
: m_eatCRLFs(aEatCRLFs), m_allocateNewLines(aAllocateNewLines),
|
||||
m_endOfLineToken(aEndOfLineToken)
|
||||
{
|
||||
NS_PRECONDITION(aBufferSize > 0, "invalid buffer size!!!");
|
||||
m_dataBuffer = nsnull;
|
||||
m_startPos = nsnull;
|
||||
|
||||
// used to buffer incoming data by ReadNextLineFromInput
|
||||
if (aBufferSize > 0)
|
||||
{
|
||||
m_dataBuffer = (char *) PR_CALLOC(sizeof(char) * aBufferSize);
|
||||
m_startPos = m_dataBuffer;
|
||||
}
|
||||
|
||||
m_dataBufferSize = aBufferSize;
|
||||
}
|
||||
|
||||
nsMsgLineStreamBuffer::~nsMsgLineStreamBuffer()
|
||||
{
|
||||
PR_FREEIF(m_dataBuffer); // release our buffer...
|
||||
}
|
||||
|
||||
// the design for this method has an inherit bug: if the length of the line is greater than the size of m_dataBufferSize,
|
||||
// then we'll never find the next line because we can't hold the whole line in memory.
|
||||
// aInputStream - the input stream we want to read a line from
|
||||
// aPauseForMoreData is returned as PR_TRUE if the stream does not yet contain a line and we must wait for more
|
||||
// data to come into the stream.
|
||||
|
||||
// Note to people wishing to modify this function: Be *VERY CAREFUL* this is a critical function used by all of
|
||||
// our mail protocols including imap, nntp, and pop. If you screw it up, you could break a lot of stuff.....
|
||||
|
||||
char * nsMsgLineStreamBuffer::ReadNextLine(nsIInputStream * aInputStream, PRUint32 &aNumBytesInLine, PRBool &aPauseForMoreData)
|
||||
{
|
||||
// try to extract a line from m_inputBuffer. If we don't have an entire line,
|
||||
// then read more bytes out from the stream. If the stream is empty then wait
|
||||
// on the monitor for more data to come in.
|
||||
|
||||
NS_PRECONDITION(m_startPos && m_dataBufferSize > 0, "invalid input arguments for read next line from input");
|
||||
|
||||
// initialize out values
|
||||
aPauseForMoreData = PR_FALSE;
|
||||
aNumBytesInLine = 0;
|
||||
char * endOfLine = nsnull;
|
||||
|
||||
PRUint32 numBytesInBuffer = PL_strlen(m_startPos);
|
||||
|
||||
if (numBytesInBuffer > 0) // any data in our internal buffer?
|
||||
endOfLine = PL_strstr(m_startPos, m_endOfLineToken); // see if we already have a line ending...
|
||||
|
||||
// it's possible that we got here before the first time we receive data from the server
|
||||
// so aInputStream will be nsnull...
|
||||
if (!endOfLine && aInputStream) // get some more data from the server
|
||||
{
|
||||
PRUint32 numBytesInStream = 0;
|
||||
PRUint32 numBytesCopied = 0;
|
||||
aInputStream->Available(&numBytesInStream);
|
||||
// if the number of bytes we want to read from the stream, is greater than the number
|
||||
// of bytes left in our buffer, then we need to shift the start pos and its contents
|
||||
// down to the beginning of m_dataBuffer...
|
||||
PRUint32 numFreeBytesInBuffer = (m_dataBuffer + m_dataBufferSize) - (m_startPos + numBytesInBuffer);
|
||||
if (numBytesInStream >= numFreeBytesInBuffer)
|
||||
{
|
||||
nsCRT::memcpy(m_dataBuffer, m_startPos, numBytesInBuffer);
|
||||
m_dataBuffer[numBytesInBuffer] = '\0'; // make sure the end of the buffer is terminated
|
||||
m_startPos = m_dataBuffer; // update the new start position
|
||||
// update the number of free bytes in the buffer
|
||||
numFreeBytesInBuffer = m_dataBufferSize - numBytesInBuffer;
|
||||
}
|
||||
|
||||
PRUint32 numBytesToCopy = PR_MIN(numFreeBytesInBuffer - 1 /* leave one for a null terminator */, numBytesInStream);
|
||||
// read the data into the end of our data buffer
|
||||
if (numBytesToCopy > 0)
|
||||
{
|
||||
aInputStream->Read(m_startPos + numBytesInBuffer, numBytesToCopy, &numBytesCopied);
|
||||
m_startPos[numBytesInBuffer + numBytesCopied] = '\0';
|
||||
}
|
||||
|
||||
// okay, now that we've tried to read in more data from the stream, look for another end of line
|
||||
// character
|
||||
endOfLine = PL_strstr(m_startPos, m_endOfLineToken);
|
||||
|
||||
}
|
||||
|
||||
// okay, now check again for endOfLine.
|
||||
if (endOfLine)
|
||||
{
|
||||
if (!m_eatCRLFs)
|
||||
endOfLine += PL_strlen(m_endOfLineToken); // count for CRLF
|
||||
|
||||
// PR_CALLOC zeros out the allocated line
|
||||
char* newLine = (char*) PR_CALLOC(endOfLine-m_startPos+1);
|
||||
if (!newLine)
|
||||
return nsnull;
|
||||
|
||||
nsCRT::memcpy(newLine, m_startPos, endOfLine-m_startPos); // copy the string into the new line buffer
|
||||
aNumBytesInLine = endOfLine - m_startPos;
|
||||
|
||||
if (m_eatCRLFs)
|
||||
endOfLine += PL_strlen(m_endOfLineToken); // advance past CRLF if we haven't already done so...
|
||||
|
||||
// now we need to update the data buffer to go past the line we just read out.
|
||||
if (PL_strlen(endOfLine) <= 0) // if no more data in the buffer, then just zero out the buffer...
|
||||
m_startPos[0] = '\0';
|
||||
else // advance
|
||||
m_startPos = endOfLine; // move us up to the end of the line
|
||||
return newLine;
|
||||
}
|
||||
|
||||
aPauseForMoreData = PR_TRUE;
|
||||
return nsnull; // if we somehow got here. we don't have another line in the buffer yet...need to wait for more data...
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
#ifndef _nsMsgLineBuffer_H
|
||||
#define _nsMsgLineBuffer_H
|
||||
|
||||
#include "msgCore.h" // precompiled header...
|
||||
|
||||
// I can't believe I have to have this stupid class, but I can't find
|
||||
// anything suitable (nsStrImpl might be, when its done). nsIByteBuffer
|
||||
// would do, if I had a stream for input, which I don't.
|
||||
|
||||
class NS_MSG_BASE nsByteArray
|
||||
{
|
||||
public:
|
||||
nsByteArray();
|
||||
virtual ~nsByteArray();
|
||||
PRUint32 GetSize() {return m_bufferSize;}
|
||||
PRUint32 GetBufferPos() {return m_bufferPos;}
|
||||
nsresult GrowBuffer(PRUint32 desired_size, PRUint32 quantum = 1024);
|
||||
nsresult AppendString(const char *string);
|
||||
nsresult AppendBuffer(const char *buffer, PRUint32 length);
|
||||
void ResetWritePos() {m_bufferPos = 0;}
|
||||
char *GetBuffer() {return m_buffer;}
|
||||
protected:
|
||||
char *m_buffer;
|
||||
PRUint32 m_bufferSize;
|
||||
PRUint32 m_bufferPos; // write Pos in m_buffer - where the next byte should go.
|
||||
};
|
||||
|
||||
|
||||
class NS_MSG_BASE nsMsgLineBufferHandler : public nsByteArray
|
||||
{
|
||||
public:
|
||||
virtual PRInt32 HandleLine(char *line, PRUint32 line_length) = 0;
|
||||
};
|
||||
|
||||
class NS_MSG_BASE nsMsgLineBuffer : public nsByteArray
|
||||
{
|
||||
public:
|
||||
nsMsgLineBuffer(nsMsgLineBufferHandler *handler, PRBool convertNewlinesP);
|
||||
|
||||
virtual ~nsMsgLineBuffer();
|
||||
PRInt32 BufferInput(const char *net_buffer, PRInt32 net_buffer_size);
|
||||
// Not sure why anyone cares, by NNTPHost seems to want to know the buf pos.
|
||||
PRUint32 GetBufferPos() {return m_bufferPos;}
|
||||
|
||||
virtual PRInt32 HandleLine(char *line, PRUint32 line_length);
|
||||
// flush last line, though it won't be CRLF terminated.
|
||||
virtual PRInt32 FlushLastLine();
|
||||
protected:
|
||||
nsMsgLineBuffer(PRBool convertNewlinesP);
|
||||
|
||||
PRInt32 ConvertAndSendBuffer();
|
||||
void SetLookingForCRLF(PRBool b);
|
||||
|
||||
nsMsgLineBufferHandler *m_handler;
|
||||
PRBool m_convertNewlinesP;
|
||||
PRBool m_lookingForCRLF;
|
||||
};
|
||||
|
||||
// I'm adding this utility class here for lack of a better place. This utility class is similar to nsMsgLineBuffer
|
||||
// except it works from an input stream. It is geared towards efficiently parsing new lines out of a stream by storing
|
||||
// read but unprocessed bytes in a buffer. I envision the primary use of this to be our mail protocols such as imap, news and
|
||||
// pop which need to process line by line data being returned in the form of a proxied stream from the server.
|
||||
|
||||
class nsIInputStream;
|
||||
|
||||
class NS_MSG_BASE nsMsgLineStreamBuffer
|
||||
{
|
||||
public:
|
||||
// aBufferSize -- size of the buffer you want us to use for buffering stream data
|
||||
// aEndOfLinetoken -- The delimeter string to be used for determining the end of line. This
|
||||
// allows us to parse platform specific end of line endings by making it
|
||||
// a parameter.
|
||||
// aAllocateNewLines -- PR_TRUE if you want calls to ReadNextLine to allocate new memory for the line.
|
||||
// if false, the char * returned is just a ptr into the buffer. Subsequent calls to
|
||||
// ReadNextLine will alter the data so your ptr only has a life time of a per call.
|
||||
// aEatCRLFs -- PR_TRUE if you don't want to see the CRLFs on the lines returned by ReadNextLine.
|
||||
// PR_FALSE if you do want to see them.
|
||||
nsMsgLineStreamBuffer(PRUint32 aBufferSize, const char * aEndOfLineToken, PRBool aAllocateNewLines, PRBool aEatCRLFs = PR_TRUE); // specify the size of the buffer you want the class to use....
|
||||
virtual ~nsMsgLineStreamBuffer();
|
||||
|
||||
// Caller must free the line returned using PR_Free
|
||||
// aEndOfLinetoken -- delimeter used to denote the end of a line.
|
||||
// aNumBytesInLine -- The number of bytes in the line returned
|
||||
// aPauseForMoreData -- There is not enough data in the stream to make a line at this time...
|
||||
char * ReadNextLine(nsIInputStream * aInputStream, PRUint32 &anumBytesInLine, PRBool &aPauseForMoreData);
|
||||
protected:
|
||||
PRBool m_eatCRLFs;
|
||||
PRBool m_allocateNewLines;
|
||||
char * m_dataBuffer;
|
||||
char * m_startPos;
|
||||
const char * m_endOfLineToken;
|
||||
PRUint32 m_dataBufferSize;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,399 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "msgCore.h"
|
||||
#include "nsMsgMailNewsUrl.h"
|
||||
#include "nsMsgBaseCID.h"
|
||||
#include "nsIMsgMailSession.h"
|
||||
#include "nsXPIDLString.h"
|
||||
|
||||
static NS_DEFINE_CID(kUrlListenerManagerCID, NS_URLLISTENERMANAGER_CID);
|
||||
static NS_DEFINE_CID(kStandardUrlCID, NS_STANDARDURL_CID);
|
||||
static NS_DEFINE_CID(kMsgMailSessionCID, NS_MSGMAILSESSION_CID);
|
||||
|
||||
nsMsgMailNewsUrl::nsMsgMailNewsUrl()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
// nsIURI specific state
|
||||
m_errorMessage = nsnull;
|
||||
m_runningUrl = PR_FALSE;
|
||||
m_updatingFolder = PR_FALSE;
|
||||
|
||||
nsComponentManager::CreateInstance(kUrlListenerManagerCID, nsnull, nsCOMTypeInfo<nsIUrlListenerManager>::GetIID(), (void **) getter_AddRefs(m_urlListeners));
|
||||
nsComponentManager::CreateInstance(kStandardUrlCID, nsnull, nsCOMTypeInfo<nsIURL>::GetIID(), (void **) getter_AddRefs(m_baseURL));
|
||||
}
|
||||
|
||||
nsMsgMailNewsUrl::~nsMsgMailNewsUrl()
|
||||
{
|
||||
PR_FREEIF(m_errorMessage);
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(nsMsgMailNewsUrl);
|
||||
NS_IMPL_RELEASE(nsMsgMailNewsUrl);
|
||||
|
||||
nsresult nsMsgMailNewsUrl::QueryInterface(const nsIID &aIID, void** aInstancePtr)
|
||||
{
|
||||
if (NULL == aInstancePtr) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (aIID.Equals(nsCOMTypeInfo<nsIURI>::GetIID())) {
|
||||
*aInstancePtr = (void*) ((nsIURI*)this);
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(nsCOMTypeInfo<nsIURL>::GetIID())) {
|
||||
*aInstancePtr = (void*) ((nsIURL*)this);
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(nsCOMTypeInfo<nsIMsgMailNewsUrl>::GetIID()))
|
||||
{
|
||||
*aInstancePtr = (void *) ((nsIMsgMailNewsUrl*) this);
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aIID.Equals(nsCOMTypeInfo<nsISupports>::GetIID()))
|
||||
{
|
||||
*aInstancePtr = (void *) ((nsIMsgMailNewsUrl*) this);
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
#if defined(NS_DEBUG)
|
||||
/*
|
||||
* Check for the debug-only interface indicating thread-safety
|
||||
*/
|
||||
static NS_DEFINE_IID(kIsThreadsafeIID, NS_ISTHREADSAFE_IID);
|
||||
if (aIID.Equals(kIsThreadsafeIID)) {
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// Begin nsIMsgMailNewsUrl specific support
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult nsMsgMailNewsUrl::GetUrlState(PRBool * aRunningUrl)
|
||||
{
|
||||
if (aRunningUrl)
|
||||
*aRunningUrl = m_runningUrl;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsMsgMailNewsUrl::SetUrlState(PRBool aRunningUrl, nsresult aExitCode)
|
||||
{
|
||||
m_runningUrl = aRunningUrl;
|
||||
nsCOMPtr <nsIMsgStatusFeedback> statusFeedback;
|
||||
|
||||
if (NS_SUCCEEDED(GetStatusFeedback(getter_AddRefs(statusFeedback))) && statusFeedback)
|
||||
{
|
||||
if (m_runningUrl)
|
||||
statusFeedback->StartMeteors();
|
||||
else
|
||||
{
|
||||
statusFeedback->ShowProgress(0);
|
||||
statusFeedback->StopMeteors();
|
||||
}
|
||||
}
|
||||
if (m_urlListeners)
|
||||
{
|
||||
if (m_runningUrl)
|
||||
{
|
||||
m_urlListeners->OnStartRunningUrl(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_urlListeners->OnStopRunningUrl(this, aExitCode);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsMsgMailNewsUrl::RegisterListener (nsIUrlListener * aUrlListener)
|
||||
{
|
||||
if (m_urlListeners)
|
||||
m_urlListeners->RegisterListener(aUrlListener);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsMsgMailNewsUrl::UnRegisterListener (nsIUrlListener * aUrlListener)
|
||||
{
|
||||
if (m_urlListeners)
|
||||
m_urlListeners->UnRegisterListener(aUrlListener);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsMsgMailNewsUrl::SetErrorMessage (const char * errorMessage)
|
||||
{
|
||||
// functionality has been moved to nsIMsgStatusFeedback
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult nsMsgMailNewsUrl::GetErrorMessage (char ** errorMessage)
|
||||
{
|
||||
// functionality has been moved to nsIMsgStatusFeedback
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetServer(nsIMsgIncomingServer ** aIncomingServer)
|
||||
{
|
||||
// mscott --> we could cache a copy of the server here....but if we did, we run
|
||||
// the risk of leaking the server if any single url gets leaked....of course that
|
||||
// shouldn't happen...but it could. so i'm going to look it up every time and
|
||||
// we can look at caching it later.
|
||||
|
||||
nsXPIDLCString host;
|
||||
nsXPIDLCString scheme;
|
||||
|
||||
nsresult rv = GetHost(getter_Copies(host));
|
||||
rv = GetScheme(getter_Copies(scheme));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
NS_WITH_SERVICE(nsIMsgMailSession, session, kMsgMailSessionCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIMsgAccountManager> accountManager;
|
||||
rv = session->GetAccountManager(getter_AddRefs(accountManager));
|
||||
if(NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIMsgIncomingServer> server;
|
||||
rv = accountManager->FindServer(GetUserName(),
|
||||
host,
|
||||
scheme,
|
||||
aIncomingServer);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetStatusFeedback(nsIMsgStatusFeedback *aMsgFeedback)
|
||||
{
|
||||
if (aMsgFeedback)
|
||||
m_statusFeedback = do_QueryInterface(aMsgFeedback);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetStatusFeedback(nsIMsgStatusFeedback **aMsgFeedback)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
// note: it is okay to return a null status feedback and not return an error
|
||||
// it's possible the url really doesn't have status feedback
|
||||
if (!m_statusFeedback)
|
||||
{
|
||||
NS_WITH_SERVICE(nsIMsgMailSession, mailSession, kMsgMailSessionCID, &rv);
|
||||
|
||||
if(NS_SUCCEEDED(rv))
|
||||
mailSession->GetTemporaryMsgStatusFeedback(getter_AddRefs(m_statusFeedback));
|
||||
}
|
||||
if (aMsgFeedback)
|
||||
{
|
||||
*aMsgFeedback = m_statusFeedback;
|
||||
NS_IF_ADDREF(*aMsgFeedback);
|
||||
}
|
||||
else
|
||||
rv = NS_ERROR_NULL_POINTER;
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetUpdatingFolder(PRBool *aResult)
|
||||
{
|
||||
if (!aResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
*aResult = m_updatingFolder;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetUpdatingFolder(PRBool updatingFolder)
|
||||
{
|
||||
m_updatingFolder = updatingFolder;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// End nsIMsgMailNewsUrl specific support
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// Begin nsIURI support
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetSpec(char * *aSpec)
|
||||
{
|
||||
return m_baseURL->GetSpec(aSpec);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetSpec(const char * aSpec)
|
||||
{
|
||||
return m_baseURL->SetSpec(aSpec);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetScheme(char * *aScheme)
|
||||
{
|
||||
return m_baseURL->GetScheme(aScheme);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetScheme(const char * aScheme)
|
||||
{
|
||||
return m_baseURL->SetScheme(aScheme);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetPreHost(char * *aPreHost)
|
||||
{
|
||||
return m_baseURL->GetPreHost(aPreHost);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetPreHost(const char * aPreHost)
|
||||
{
|
||||
return m_baseURL->SetPreHost(aPreHost);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetHost(char * *aHost)
|
||||
{
|
||||
return m_baseURL->GetHost(aHost);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetHost(const char * aHost)
|
||||
{
|
||||
return m_baseURL->SetHost(aHost);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetPort(PRInt32 *aPort)
|
||||
{
|
||||
return m_baseURL->GetPort(aPort);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetPort(PRInt32 aPort)
|
||||
{
|
||||
return m_baseURL->SetPort(aPort);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetPath(char * *aPath)
|
||||
{
|
||||
return m_baseURL->GetPath(aPath);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetPath(const char * aPath)
|
||||
{
|
||||
return m_baseURL->SetPath(aPath);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::Equals(nsIURI *other, PRBool *_retval)
|
||||
{
|
||||
return m_baseURL->Equals(other, _retval);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::Clone(nsIURI **_retval)
|
||||
{
|
||||
return m_baseURL->Clone(_retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetRelativePath(const char *i_RelativePath)
|
||||
{
|
||||
return m_baseURL->SetRelativePath(i_RelativePath);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetDirectory(char * *aDirectory)
|
||||
{
|
||||
return m_baseURL->GetDirectory(aDirectory);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetDirectory(const char *aDirectory)
|
||||
{
|
||||
|
||||
return m_baseURL->SetDirectory(aDirectory);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetFileName(char * *aFileName)
|
||||
{
|
||||
return m_baseURL->GetFileName(aFileName);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetFileBaseName(char * *aFileBaseName)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetFileBaseName(const char * aFileBaseName)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetFileExtension(char * *aFileExtension)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetFileExtension(const char * aFileExtension)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetFileName(const char * aFileName)
|
||||
{
|
||||
return m_baseURL->SetFileName(aFileName);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetParam(char * *aParam)
|
||||
{
|
||||
return m_baseURL->GetParam(aParam);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetParam(const char *aParam)
|
||||
{
|
||||
return m_baseURL->SetParam(aParam);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetQuery(char * *aQuery)
|
||||
{
|
||||
return m_baseURL->GetQuery(aQuery);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetQuery(const char *aQuery)
|
||||
{
|
||||
return m_baseURL->SetQuery(aQuery);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetRef(char * *aRef)
|
||||
{
|
||||
return m_baseURL->GetRef(aRef);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetRef(const char *aRef)
|
||||
{
|
||||
return m_baseURL->SetRef(aRef);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::GetFilePath(char **o_DirFile)
|
||||
{
|
||||
return m_baseURL->GetFilePath(o_DirFile);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgMailNewsUrl::SetFilePath(const char *i_DirFile)
|
||||
{
|
||||
return m_baseURL->SetFilePath(i_DirFile);
|
||||
}
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef nsMsgMailNewsUrl_h___
|
||||
#define nsMsgMailNewsUrl_h___
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsIUrlListener.h"
|
||||
#include "nsIUrlListenerManager.h"
|
||||
#include "nsIMsgStatusFeedback.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIMsgMailNewsUrl.h"
|
||||
#include "nsIURL.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Okay, I found that all of the mail and news url interfaces needed to support
|
||||
// several common interfaces (in addition to those provided through nsIURI).
|
||||
// So I decided to group them all in this implementation so we don't have to
|
||||
// duplicate the code.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class NS_MSG_BASE nsMsgMailNewsUrl : public nsIMsgMailNewsUrl
|
||||
{
|
||||
public:
|
||||
nsMsgMailNewsUrl();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIMSGMAILNEWSURL
|
||||
NS_DECL_NSIURI
|
||||
NS_DECL_NSIURL
|
||||
|
||||
protected:
|
||||
virtual ~nsMsgMailNewsUrl();
|
||||
|
||||
// a helper function I needed from derived urls...
|
||||
virtual const char * GetUserName() = 0;
|
||||
|
||||
nsCOMPtr<nsIURL> m_baseURL;
|
||||
nsCOMPtr<nsIMsgStatusFeedback> m_statusFeedback;
|
||||
char *m_errorMessage;
|
||||
PRBool m_runningUrl;
|
||||
PRBool m_updatingFolder;
|
||||
|
||||
// manager of all of current url listeners....
|
||||
nsCOMPtr<nsIUrlListenerManager> m_urlListeners;
|
||||
};
|
||||
|
||||
|
||||
#endif /* nsMsgMailNewsUrl_h___ */
|
||||
@@ -1,369 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "msgCore.h"
|
||||
#include "nsMsgProtocol.h"
|
||||
#include "nsIMsgMailNewsUrl.h"
|
||||
#include "nsISocketTransportService.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsSpecialSystemDirectory.h"
|
||||
#include "nsILoadGroup.h"
|
||||
#include "nsIIOService.h"
|
||||
|
||||
static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
|
||||
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
|
||||
|
||||
NS_IMPL_ISUPPORTS3(nsMsgProtocol, nsIStreamListener, nsIStreamObserver, nsIChannel)
|
||||
|
||||
nsMsgProtocol::nsMsgProtocol()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
m_flags = 0;
|
||||
m_startPosition = 0;
|
||||
m_readCount = 0;
|
||||
m_socketIsOpen = PR_FALSE;
|
||||
|
||||
m_tempMsgFileSpec = nsSpecialSystemDirectory(nsSpecialSystemDirectory::OS_TemporaryDirectory);
|
||||
m_tempMsgFileSpec += "tempMessage.eml";
|
||||
}
|
||||
|
||||
nsMsgProtocol::~nsMsgProtocol()
|
||||
{}
|
||||
|
||||
nsresult nsMsgProtocol::OpenNetworkSocket(nsIURI * aURL) // open a connection on this url
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsXPIDLCString hostName;
|
||||
PRInt32 port = 0;
|
||||
|
||||
m_readCount = -1; // with socket connections we want to read as much data as arrives
|
||||
m_startPosition = 0;
|
||||
|
||||
NS_WITH_SERVICE(nsISocketTransportService, socketService, kSocketTransportServiceCID, &rv);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && aURL)
|
||||
{
|
||||
aURL->GetPort(&port);
|
||||
aURL->GetHost(getter_Copies(hostName));
|
||||
|
||||
rv = socketService->CreateTransport(hostName, port, nsnull, getter_AddRefs(m_channel));
|
||||
if (NS_SUCCEEDED(rv) && m_channel)
|
||||
{
|
||||
m_socketIsOpen = PR_FALSE;
|
||||
rv = SetupTransportState();
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMsgProtocol::OpenFileSocket(nsIURI * aURL, const nsFileSpec * aFileSpec, PRUint32 aStartPosition, PRInt32 aReadCount)
|
||||
{
|
||||
// mscott - file needs to be encoded directly into aURL. I should be able to get
|
||||
// rid of this method completely.
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
m_startPosition = aStartPosition;
|
||||
m_readCount = aReadCount;
|
||||
|
||||
NS_WITH_SERVICE(nsIIOService, netService, kIOServiceCID, &rv);
|
||||
if (NS_SUCCEEDED(rv) && aURL)
|
||||
{
|
||||
// extract the file path from the uri...
|
||||
nsXPIDLCString filePath;
|
||||
aURL->GetPath(getter_Copies(filePath));
|
||||
char * urlSpec = PR_smprintf("file://%s", (const char *) filePath);
|
||||
|
||||
rv = netService->NewChannel("Load", urlSpec,
|
||||
nsnull, // null base URI
|
||||
nsnull, // null load group
|
||||
nsnull, // null eventsink getter
|
||||
getter_AddRefs(m_channel));
|
||||
PR_FREEIF(urlSpec);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && m_channel)
|
||||
{
|
||||
m_socketIsOpen = PR_FALSE;
|
||||
// rv = SetupTransportState();
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMsgProtocol::SetupTransportState()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (!m_socketIsOpen && m_channel)
|
||||
{
|
||||
rv = m_channel->OpenOutputStream(0 /* start position */, getter_AddRefs(m_outputStream));
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create an output stream");
|
||||
// we want to open the stream
|
||||
} // if m_transport
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMsgProtocol::CloseSocket()
|
||||
{
|
||||
// release all of our socket state
|
||||
m_socketIsOpen = PR_FALSE;
|
||||
m_outputStream = null_nsCOMPtr();
|
||||
m_channel = null_nsCOMPtr();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes the data contained in dataBuffer into the current output stream. It also informs
|
||||
* the transport layer that this data is now available for transmission.
|
||||
* Returns a positive number for success, 0 for failure (not all the bytes were written to the
|
||||
* stream, etc). We need to make another pass through this file to install an error system (mscott)
|
||||
*/
|
||||
|
||||
PRInt32 nsMsgProtocol::SendData(nsIURI * aURL, const char * dataBuffer)
|
||||
{
|
||||
PRUint32 writeCount = 0;
|
||||
PRInt32 status = 0;
|
||||
|
||||
// NS_PRECONDITION(m_outputStream, "oops....we don't have an output stream...how did that happen?");
|
||||
if (dataBuffer && m_outputStream)
|
||||
{
|
||||
status = m_outputStream->Write(dataBuffer, PL_strlen(dataBuffer), &writeCount);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Whenever data arrives from the connection, core netlib notifices the protocol by calling
|
||||
// OnDataAvailable. We then read and process the incoming data from the input stream.
|
||||
NS_IMETHODIMP nsMsgProtocol::OnDataAvailable(nsIChannel * /* aChannel */, nsISupports *ctxt, nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count)
|
||||
{
|
||||
// right now, this really just means turn around and churn through the state machine
|
||||
nsCOMPtr<nsIURI> uri = do_QueryInterface(ctxt);
|
||||
return ProcessProtocolState(uri, inStr, sourceOffset, count);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::OnStartRequest(nsIChannel * aChannel, nsISupports *ctxt)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr <nsIMsgMailNewsUrl> aMsgUrl = do_QueryInterface(ctxt, &rv);
|
||||
if (NS_SUCCEEDED(rv) && aMsgUrl)
|
||||
rv = aMsgUrl->SetUrlState(PR_TRUE, NS_OK);
|
||||
|
||||
// if we are set up as a channel, we should notify our channel listener that we are starting...
|
||||
// so pass in ourself as the channel and not the underlying socket or file channel the protocol
|
||||
// happens to be using
|
||||
if (m_channelListener)
|
||||
rv = m_channelListener->OnStartRequest(this, m_channelContext);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// stop binding is a "notification" informing us that the stream associated with aURL is going away.
|
||||
NS_IMETHODIMP nsMsgProtocol::OnStopRequest(nsIChannel * aChannel, nsISupports *ctxt, nsresult aStatus, const PRUnichar* aMsg)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr <nsIMsgMailNewsUrl> aMsgUrl = do_QueryInterface(ctxt, &rv);
|
||||
if (NS_SUCCEEDED(rv) && aMsgUrl)
|
||||
rv = aMsgUrl->SetUrlState(PR_FALSE, aStatus);
|
||||
|
||||
// if we are set up as a channel, we should notify our channel listener that we are starting...
|
||||
// so pass in ourself as the channel and not the underlying socket or file channel the protocol
|
||||
// happens to be using
|
||||
if (m_channelListener)
|
||||
rv = m_channelListener->OnStopRequest(this, m_channelContext, aStatus, aMsg);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMsgProtocol::LoadUrl(nsIURI * aURL, nsISupports * aConsumer)
|
||||
{
|
||||
// okay now kick us off to the next state...
|
||||
// our first state is a process state so drive the state machine...
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr <nsIMsgMailNewsUrl> aMsgUrl = do_QueryInterface(aURL);
|
||||
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = aMsgUrl->SetUrlState(PR_TRUE, NS_OK); // set the url as a url currently being run...
|
||||
|
||||
// if the url is given a stream consumer then we should use it to forward calls to...
|
||||
if (!m_channelListener && aConsumer) // if we don't have a registered listener already
|
||||
{
|
||||
m_channelListener = do_QueryInterface(aConsumer);
|
||||
if (!m_channelContext)
|
||||
m_channelContext = do_QueryInterface(aURL);
|
||||
}
|
||||
|
||||
if (!m_socketIsOpen)
|
||||
{
|
||||
nsCOMPtr<nsISupports> urlSupports = do_QueryInterface(aURL);
|
||||
|
||||
// put us in a state where we are always notified of incoming data
|
||||
m_channel->AsyncRead(m_startPosition, m_readCount, urlSupports ,this /* stream observer */);
|
||||
m_socketIsOpen = PR_TRUE; // mark the channel as open
|
||||
} // if we got an event queue service
|
||||
else // the connection is already open so we should begin processing our new url...
|
||||
rv = ProcessProtocolState(aURL, nsnull, 0, 0);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// The rest of this file is mostly nsIChannel mumbo jumbo stuff
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult nsMsgProtocol::SetUrl(nsIURI * aURL)
|
||||
{
|
||||
m_url = dont_QueryInterface(aURL);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsMsgProtocol::SetLoadGroup(nsILoadGroup * aLoadGroup)
|
||||
{
|
||||
m_loadGroup = dont_QueryInterface(aLoadGroup);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::GetURI(nsIURI * *aURI)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
if (aURI)
|
||||
{
|
||||
if (m_url)
|
||||
rv = m_url->QueryInterface(NS_GET_IID(nsIURI), (void **) aURI);
|
||||
else
|
||||
*aURI = nsnull;
|
||||
}
|
||||
else
|
||||
rv = NS_ERROR_NULL_POINTER;
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::OpenInputStream(PRUint32 startPosition, PRInt32 readCount, nsIInputStream **_retval)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::OpenOutputStream(PRUint32 startPosition, nsIOutputStream **_retval)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::AsyncOpen(nsIStreamObserver *observer, nsISupports* ctxt)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::AsyncRead(PRUint32 startPosition, PRInt32 readCount, nsISupports *ctxt, nsIStreamListener *listener)
|
||||
{
|
||||
// set the stream listener and then load the url
|
||||
m_channelContext = ctxt;
|
||||
m_channelListener = listener;
|
||||
|
||||
// the following load group code is completely bogus....
|
||||
nsresult rv = NS_OK;
|
||||
if (m_loadGroup)
|
||||
{
|
||||
nsCOMPtr<nsILoadGroupListenerFactory> factory;
|
||||
//
|
||||
// Create a load group "proxy" listener...
|
||||
//
|
||||
rv = m_loadGroup->GetGroupListenerFactory(getter_AddRefs(factory));
|
||||
if (factory)
|
||||
{
|
||||
nsCOMPtr<nsIStreamListener> newListener;
|
||||
rv = factory->CreateLoadGroupListener(m_channelListener, getter_AddRefs(newListener));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
m_channelListener = newListener;
|
||||
}
|
||||
} // if aLoadGroup
|
||||
|
||||
return LoadUrl(m_url, nsnull);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::AsyncWrite(nsIInputStream *fromStream, PRUint32 startPosition, PRInt32 writeCount, nsISupports *ctxt, nsIStreamObserver *observer)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::GetLoadAttributes(nsLoadFlags *aLoadAttributes)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::SetLoadAttributes(nsLoadFlags aLoadAttributes)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::GetContentType(char * *aContentType)
|
||||
{
|
||||
*aContentType = nsCRT::strdup("message/rfc822");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::GetContentLength(PRInt32 * aContentLength)
|
||||
{
|
||||
*aContentLength = -1;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::GetOwner(nsISupports * *aPrincipal)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::SetOwner(nsISupports * aPrincipal)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::GetLoadGroup(nsILoadGroup * *aLoadGroup)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// From nsIRequest
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::IsPending(PRBool *result)
|
||||
{
|
||||
*result = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::Cancel()
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::Suspend()
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgProtocol::Resume()
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef nsMsgProtocol_h__
|
||||
#define nsMsgProtocol_h__
|
||||
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIEventQueue.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsILoadGroup.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
// This is a helper class used to encapsulate code shared between all of the
|
||||
// mailnews protocol objects (imap, news, pop, smtp, etc.) In particular,
|
||||
// it unifies the core networking code for the protocols. My hope is that
|
||||
// this will make unification with Necko easier as we'll only have to change
|
||||
// this class and not all of the mailnews protocols.
|
||||
class NS_MSG_BASE nsMsgProtocol : public nsIStreamListener, public nsIChannel
|
||||
{
|
||||
public:
|
||||
nsMsgProtocol();
|
||||
virtual ~nsMsgProtocol();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
// nsIChannel support
|
||||
NS_DECL_NSICHANNEL
|
||||
NS_DECL_NSIREQUEST
|
||||
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSISTREAMOBSERVER
|
||||
|
||||
// LoadUrl -- A protocol typically overrides this function, sets up any local state for the url and
|
||||
// then calls the base class which opens the socket if it needs opened. If the socket is
|
||||
// already opened then we just call ProcessProtocolState to start the churning process.
|
||||
// aConsumer is the consumer for the url. It can be null if this argument is not appropriate
|
||||
virtual nsresult LoadUrl(nsIURI * aURL, nsISupports * aConsumer = nsnull);
|
||||
|
||||
virtual nsresult SetUrl(nsIURI * aURL); // sometimes we want to set the url before we load it
|
||||
virtual nsresult SetLoadGroup(nsILoadGroup * aLoadGroup);
|
||||
|
||||
// Flag manipulators
|
||||
PRBool TestFlag (PRUint32 flag) {return flag & m_flags;}
|
||||
void SetFlag (PRUint32 flag) { m_flags |= flag; }
|
||||
void ClearFlag (PRUint32 flag) { m_flags &= ~flag; }
|
||||
|
||||
protected:
|
||||
// methods for opening and closing a socket with core netlib....
|
||||
// mscott -okay this is lame. I should break this up into a file protocol and a socket based
|
||||
// protocool class instead of cheating and putting both methods here...
|
||||
virtual nsresult OpenNetworkSocket(nsIURI * aURL); // open a connection on this url
|
||||
virtual nsresult OpenFileSocket(nsIURI * aURL, const nsFileSpec * aFileSpec, PRUint32 aStartPosition, PRInt32 aReadCount); // used to open a file socket connection
|
||||
|
||||
// a Protocol typically overrides this method. They free any of their own connection state and then
|
||||
// they call up into the base class to free the generic connection objects
|
||||
virtual nsresult CloseSocket();
|
||||
|
||||
virtual nsresult SetupTransportState(); // private method used by OpenNetworkSocket and OpenFileSocket
|
||||
|
||||
// ProcessProtocolState - This is the function that gets churned by calls to OnDataAvailable.
|
||||
// As data arrives on the socket, OnDataAvailable calls ProcessProtocolState.
|
||||
|
||||
virtual nsresult ProcessProtocolState(nsIURI * url, nsIInputStream * inputStream,
|
||||
PRUint32 sourceOffset, PRUint32 length) = 0;
|
||||
|
||||
// SendData -- Writes the data contained in dataBuffer into the current output stream.
|
||||
// It also informs the transport layer that this data is now available for transmission.
|
||||
// Returns a positive number for success, 0 for failure (not all the bytes were written to the
|
||||
// stream, etc).
|
||||
virtual PRInt32 SendData(nsIURI * aURL, const char * dataBuffer);
|
||||
|
||||
// Ouput stream for writing commands to the socket
|
||||
nsCOMPtr<nsIChannel> m_channel;
|
||||
nsCOMPtr<nsIOutputStream> m_outputStream; // this will be obtained from the transport interface
|
||||
|
||||
PRBool m_socketIsOpen; // mscott: we should look into keeping this state in the nsSocketTransport...
|
||||
// I'm using it to make sure I open the socket the first time a URL is loaded into the connection
|
||||
PRUint32 m_flags; // used to store flag information
|
||||
PRUint32 m_startPosition;
|
||||
PRInt32 m_readCount;
|
||||
|
||||
nsFileSpec m_tempMsgFileSpec; // we currently have a hack where displaying a msg involves writing it to a temp file first
|
||||
|
||||
// the following is a catch all for nsIChannel related data
|
||||
nsCOMPtr<nsIURI> m_url; // the running url
|
||||
nsCOMPtr<nsIStreamListener> m_channelListener;
|
||||
nsCOMPtr<nsISupports> m_channelContext;
|
||||
nsCOMPtr<nsILoadGroup> m_loadGroup;
|
||||
};
|
||||
|
||||
#endif /* nsMsgProtocol_h__ */
|
||||
@@ -1,99 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998, 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsMsgTxn.h"
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
static NS_DEFINE_IID(kITransactionIID, NS_ITRANSACTION_IID);
|
||||
|
||||
NS_IMPL_ADDREF(nsMsgTxn)
|
||||
NS_IMPL_RELEASE(nsMsgTxn)
|
||||
|
||||
// note that aEditor is not refcounted
|
||||
nsMsgTxn::nsMsgTxn()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsMsgTxn::~nsMsgTxn()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgTxn::Do(void)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgTxn::GetIsTransient(PRBool *aIsTransient)
|
||||
{
|
||||
if (nsnull!=aIsTransient)
|
||||
*aIsTransient = PR_FALSE;
|
||||
else
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgTxn::Write(nsIOutputStream *aOutputStream)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgTxn::GetUndoString(nsString *aString)
|
||||
{
|
||||
if (nsnull!=aString)
|
||||
*aString="Undo";
|
||||
else
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgTxn::GetRedoString(nsString *aString)
|
||||
{
|
||||
if (nsnull!=aString)
|
||||
*aString="Redo";
|
||||
else
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgTxn::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
||||
{
|
||||
if (NULL == aInstancePtr) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (aIID.Equals(kISupportsIID)) {
|
||||
*aInstancePtr = (void*)(nsISupports*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(kITransactionIID)) {
|
||||
*aInstancePtr = (void*)(nsITransaction*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
*aInstancePtr = 0;
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998, 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef nsMsgTxn_h__
|
||||
#define nsMsgTxn_h__
|
||||
|
||||
#include "nsITransaction.h"
|
||||
#include "msgCore.h"
|
||||
|
||||
#define NS_MESSAGETRANSACTION_IID \
|
||||
{ /* da621b30-1efc-11d3-abe4-00805f8ac968 */ \
|
||||
0xda621b30, 0x1efc, 0x11d3, \
|
||||
{ 0xab, 0xe4, 0x00, 0x80, 0x5f, 0x8a, 0xc9, 0x68 } }
|
||||
/**
|
||||
* base class for all message undo/redo transactions.
|
||||
*/
|
||||
class NS_MSG_BASE nsMsgTxn : public nsITransaction
|
||||
{
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsMsgTxn();
|
||||
virtual ~nsMsgTxn();
|
||||
|
||||
NS_IMETHOD Do(void);
|
||||
|
||||
NS_IMETHOD Undo(void) = 0;
|
||||
|
||||
NS_IMETHOD Redo(void) = 0;
|
||||
|
||||
NS_IMETHOD GetIsTransient(PRBool *aIsTransient);
|
||||
|
||||
NS_IMETHOD Merge(PRBool *aDidMerge, nsITransaction *aTransaction);
|
||||
|
||||
NS_IMETHOD Write(nsIOutputStream *aOutputStream);
|
||||
|
||||
NS_IMETHOD GetUndoString(nsString *aString);
|
||||
|
||||
NS_IMETHOD GetRedoString(nsString *aString);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,326 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "msgCore.h"
|
||||
#include "nsIMessage.h"
|
||||
#include "nsIMsgHdr.h"
|
||||
#include "nsMsgUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "nsFileSpec.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIImapUrl.h"
|
||||
#include "nsIMailboxUrl.h"
|
||||
#include "nsINntpUrl.h"
|
||||
#include "nsMsgNewsCID.h"
|
||||
#include "nsMsgLocalCID.h"
|
||||
#include "nsMsgBaseCID.h"
|
||||
#include "nsMsgImapCID.h"
|
||||
|
||||
static NS_DEFINE_CID(kImapUrlCID, NS_IMAPURL_CID);
|
||||
static NS_DEFINE_CID(kCMailboxUrl, NS_MAILBOXURL_CID);
|
||||
static NS_DEFINE_CID(kCNntpUrlCID, NS_NNTPURL_CID);
|
||||
|
||||
#if defined(DEBUG_sspitzer_) || defined(DEBUG_seth_)
|
||||
#define DEBUG_NS_MsgHashIfNecessary 1
|
||||
#endif
|
||||
|
||||
nsresult GetMessageServiceProgIDForURI(const char *uri, nsString &progID)
|
||||
{
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
//Find protocol
|
||||
nsString uriStr = uri;
|
||||
PRInt32 pos = uriStr.FindChar(':');
|
||||
if(pos == -1)
|
||||
return NS_ERROR_FAILURE;
|
||||
nsString protocol;
|
||||
uriStr.Left(protocol, pos);
|
||||
|
||||
//Build message service progid
|
||||
progID = "component://netscape/messenger/messageservice;type=";
|
||||
progID += protocol;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult GetMessageServiceFromURI(const char *uri, nsIMsgMessageService **messageService)
|
||||
{
|
||||
|
||||
nsAutoString progID;
|
||||
nsresult rv;
|
||||
|
||||
rv = GetMessageServiceProgIDForURI(uri, progID);
|
||||
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = nsServiceManager::GetService((const char *) nsCAutoString(progID), nsCOMTypeInfo<nsIMsgMessageService>::GetIID(),
|
||||
(nsISupports**)messageService, nsnull);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
nsresult ReleaseMessageServiceFromURI(const char *uri, nsIMsgMessageService *messageService)
|
||||
{
|
||||
nsAutoString progID;
|
||||
nsresult rv;
|
||||
|
||||
rv = GetMessageServiceProgIDForURI(uri, progID);
|
||||
if(NS_SUCCEEDED(rv))
|
||||
rv = nsServiceManager::ReleaseService(nsCAutoString(progID), messageService);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
nsresult CreateStartupUrl(char *uri, nsIURI** aUrl)
|
||||
{
|
||||
nsresult rv = NS_ERROR_NULL_POINTER;
|
||||
if (!uri || !*uri || !aUrl) return rv;
|
||||
*aUrl = nsnull;
|
||||
if (PL_strncasecmp(uri, "imap", 4) == 0)
|
||||
{
|
||||
nsCOMPtr<nsIImapUrl> imapUrl;
|
||||
rv = nsComponentManager::CreateInstance(kImapUrlCID, nsnull,
|
||||
nsIImapUrl::GetIID(),
|
||||
getter_AddRefs(imapUrl));
|
||||
if (NS_SUCCEEDED(rv) && imapUrl)
|
||||
rv = imapUrl->QueryInterface(nsCOMTypeInfo<nsIURI>::GetIID(),
|
||||
(void**) aUrl);
|
||||
}
|
||||
else if (PL_strncasecmp(uri, "mailbox", 7) == 0)
|
||||
{
|
||||
nsCOMPtr<nsIMailboxUrl> mailboxUrl;
|
||||
rv = nsComponentManager::CreateInstance(kCMailboxUrl, nsnull,
|
||||
nsIMailboxUrl::GetIID(),
|
||||
getter_AddRefs(mailboxUrl));
|
||||
if (NS_SUCCEEDED(rv) && mailboxUrl)
|
||||
rv = mailboxUrl->QueryInterface(nsCOMTypeInfo<nsIURI>::GetIID(),
|
||||
(void**) aUrl);
|
||||
}
|
||||
else if (PL_strncasecmp(uri, "news", 4) == 0)
|
||||
{
|
||||
nsCOMPtr<nsINntpUrl> nntpUrl;
|
||||
rv = nsComponentManager::CreateInstance(kCNntpUrlCID, nsnull,
|
||||
nsINntpUrl::GetIID(),
|
||||
getter_AddRefs(nntpUrl));
|
||||
if (NS_SUCCEEDED(rv) && nntpUrl)
|
||||
rv = nntpUrl->QueryInterface(nsCOMTypeInfo<nsIURI>::GetIID(),
|
||||
(void**) aUrl);
|
||||
}
|
||||
if (*aUrl)
|
||||
(*aUrl)->SetSpec(uri);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsMessageFromMsgHdrEnumerator, nsCOMTypeInfo<nsISimpleEnumerator>::GetIID())
|
||||
|
||||
nsMessageFromMsgHdrEnumerator::nsMessageFromMsgHdrEnumerator(nsISimpleEnumerator *srcEnumerator,
|
||||
nsIMsgFolder *folder)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
mSrcEnumerator = dont_QueryInterface(srcEnumerator);
|
||||
mFolder = dont_QueryInterface(folder);
|
||||
|
||||
}
|
||||
|
||||
nsMessageFromMsgHdrEnumerator::~nsMessageFromMsgHdrEnumerator()
|
||||
{
|
||||
//member variables are nsCOMPtr's
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMessageFromMsgHdrEnumerator::GetNext(nsISupports **aItem)
|
||||
{
|
||||
nsCOMPtr<nsISupports> currentItem;
|
||||
nsCOMPtr<nsIMsgDBHdr> msgDBHdr;
|
||||
nsCOMPtr<nsIMessage> message;
|
||||
nsresult rv;
|
||||
|
||||
rv = mSrcEnumerator->GetNext(getter_AddRefs(currentItem));
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
msgDBHdr = do_QueryInterface(currentItem, &rv);
|
||||
}
|
||||
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = mFolder->CreateMessageFromMsgDBHdr(msgDBHdr, getter_AddRefs(message));
|
||||
}
|
||||
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
currentItem = do_QueryInterface(message, &rv);
|
||||
*aItem = currentItem;
|
||||
NS_IF_ADDREF(*aItem);
|
||||
}
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),"getnext shouldn't fail");
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessageFromMsgHdrEnumerator::HasMoreElements(PRBool *aResult)
|
||||
{
|
||||
return mSrcEnumerator->HasMoreElements(aResult);
|
||||
}
|
||||
|
||||
nsresult NS_NewMessageFromMsgHdrEnumerator(nsISimpleEnumerator *srcEnumerator,
|
||||
nsIMsgFolder *folder,
|
||||
nsMessageFromMsgHdrEnumerator **messageEnumerator)
|
||||
{
|
||||
if(!messageEnumerator)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*messageEnumerator = new nsMessageFromMsgHdrEnumerator(srcEnumerator, folder);
|
||||
|
||||
if(!messageEnumerator)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(*messageEnumerator);
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
// Where should this live? It's a utility used to convert a string priority, e.g., "High, Low, Normal" to an enum.
|
||||
// Perhaps we should have an interface that groups together all these utilities...
|
||||
nsresult NS_MsgGetPriorityFromString(const char *priority, nsMsgPriority *outPriority)
|
||||
{
|
||||
if (!outPriority)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsMsgPriority retPriority = nsMsgPriorityNormal;
|
||||
|
||||
if (PL_strcasestr(priority, "Normal") != NULL)
|
||||
retPriority = nsMsgPriorityNormal;
|
||||
else if (PL_strcasestr(priority, "Lowest") != NULL)
|
||||
retPriority = nsMsgPriorityLowest;
|
||||
else if (PL_strcasestr(priority, "Highest") != NULL)
|
||||
retPriority = nsMsgPriorityHighest;
|
||||
else if (PL_strcasestr(priority, "High") != NULL ||
|
||||
PL_strcasestr(priority, "Urgent") != NULL)
|
||||
retPriority = nsMsgPriorityHigh;
|
||||
else if (PL_strcasestr(priority, "Low") != NULL ||
|
||||
PL_strcasestr(priority, "Non-urgent") != NULL)
|
||||
retPriority = nsMsgPriorityLow;
|
||||
else if (PL_strcasestr(priority, "1") != NULL)
|
||||
retPriority = nsMsgPriorityHighest;
|
||||
else if (PL_strcasestr(priority, "2") != NULL)
|
||||
retPriority = nsMsgPriorityHigh;
|
||||
else if (PL_strcasestr(priority, "3") != NULL)
|
||||
retPriority = nsMsgPriorityNormal;
|
||||
else if (PL_strcasestr(priority, "4") != NULL)
|
||||
retPriority = nsMsgPriorityLow;
|
||||
else if (PL_strcasestr(priority, "5") != NULL)
|
||||
retPriority = nsMsgPriorityLowest;
|
||||
else
|
||||
retPriority = nsMsgPriorityNormal;
|
||||
*outPriority = retPriority;
|
||||
return NS_OK;
|
||||
//return nsMsgNoPriority;
|
||||
}
|
||||
|
||||
|
||||
nsresult NS_MsgGetUntranslatedPriorityName (nsMsgPriority p, nsString *outName)
|
||||
{
|
||||
if (!outName)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
switch (p)
|
||||
{
|
||||
case nsMsgPriorityNotSet:
|
||||
case nsMsgPriorityNone:
|
||||
*outName = "None";
|
||||
break;
|
||||
case nsMsgPriorityLowest:
|
||||
*outName = "Lowest";
|
||||
break;
|
||||
case nsMsgPriorityLow:
|
||||
*outName = "Low";
|
||||
break;
|
||||
case nsMsgPriorityNormal:
|
||||
*outName = "Normal";
|
||||
break;
|
||||
case nsMsgPriorityHigh:
|
||||
*outName = "High";
|
||||
break;
|
||||
case nsMsgPriorityHighest:
|
||||
*outName = "Highest";
|
||||
break;
|
||||
default:
|
||||
NS_ASSERTION(PR_FALSE, "invalid priority value");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* this used to be XP_StringHash2 from xp_hash.c */
|
||||
/* phong's linear congruential hash */
|
||||
static PRUint32 StringHash(const char *ubuf)
|
||||
{
|
||||
unsigned char * buf = (unsigned char*) ubuf;
|
||||
PRUint32 h=1;
|
||||
while(*buf) {
|
||||
h = 0x63c63cd9*h + 0x9c39c33d + (int32)*buf;
|
||||
buf++;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
nsresult NS_MsgHashIfNecessary(nsCAutoString &name)
|
||||
{
|
||||
#if defined(XP_WIN16) || defined(XP_OS2)
|
||||
const PRUint32 MAX_LEN = 8;
|
||||
#elif defined(XP_MAC)
|
||||
const PRUint32 MAX_LEN = 25;
|
||||
#elif defined(XP_UNIX) || defined(XP_PC) || defined(XP_BEOS)
|
||||
const PRUint32 MAX_LEN = 55;
|
||||
#else
|
||||
#error need_to_define_your_max_filename_length
|
||||
#endif
|
||||
nsCAutoString str(name);
|
||||
|
||||
#ifdef DEBUG_NS_MsgHashIfNecessary
|
||||
printf("in: %s\n",str.GetBuffer());
|
||||
#endif
|
||||
|
||||
// Given a name, use either that name, if it fits on our
|
||||
// filesystem, or a hashified version of it, if the name is too
|
||||
// long to fit.
|
||||
char hashedname[MAX_LEN + 1];
|
||||
PRBool needshash = PL_strlen(str.GetBuffer()) > MAX_LEN;
|
||||
#if defined(XP_WIN16) || defined(XP_OS2)
|
||||
if (!needshash) {
|
||||
needshash = PL_strchr(str.GetBuffer(), '.') != NULL ||
|
||||
PL_strchr(str.GetBuffer(), ':') != NULL;
|
||||
}
|
||||
#endif
|
||||
PL_strncpy(hashedname, str.GetBuffer(), MAX_LEN + 1);
|
||||
if (needshash) {
|
||||
PR_snprintf(hashedname + MAX_LEN - 8, 9, "%08lx",
|
||||
(unsigned long) StringHash(str.GetBuffer()));
|
||||
}
|
||||
name = hashedname;
|
||||
#ifdef DEBUG_NS_MsgHashIfNecessary
|
||||
printf("out: %s\n",hashedname);
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _NSMSGUTILS_H
|
||||
#define _NSMSGUTILS_H
|
||||
|
||||
#include "nsIURL.h"
|
||||
#include "nsIMsgMessageService.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIEnumerator.h"
|
||||
#include "nsIMsgFolder.h"
|
||||
#include "msgCore.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
//These are utility functions that can used throughout the mailnews code
|
||||
|
||||
//Utilities for getting a message service.
|
||||
NS_MSG_BASE nsresult GetMessageServiceProgIDForURI(const char *uri, nsString &progID);
|
||||
//Use ReleaseMessageServiceFromURI to release the service.
|
||||
NS_MSG_BASE nsresult GetMessageServiceFromURI(const char *uri, nsIMsgMessageService **messageService);
|
||||
NS_MSG_BASE nsresult ReleaseMessageServiceFromURI(const char *uri, nsIMsgMessageService *messageService);
|
||||
|
||||
NS_MSG_BASE nsresult CreateStartupUrl(char *uri, nsIURI** aUrl);
|
||||
|
||||
//An enumerator for converting nsIMsgHdrs to nsIMessages.
|
||||
class NS_MSG_BASE nsMessageFromMsgHdrEnumerator: public nsISimpleEnumerator
|
||||
{
|
||||
protected:
|
||||
nsCOMPtr<nsISimpleEnumerator> mSrcEnumerator;
|
||||
nsCOMPtr<nsIMsgFolder> mFolder;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
nsMessageFromMsgHdrEnumerator(nsISimpleEnumerator *srcEnumerator, nsIMsgFolder *folder);
|
||||
nsMessageFromMsgHdrEnumerator(){} //Default constructor that does nothing so nsComPtr will work.
|
||||
virtual ~nsMessageFromMsgHdrEnumerator();
|
||||
|
||||
NS_DECL_NSISIMPLEENUMERATOR
|
||||
};
|
||||
|
||||
NS_MSG_BASE nsresult NS_NewMessageFromMsgHdrEnumerator(nsISimpleEnumerator *srcEnumerator,
|
||||
nsIMsgFolder *folder,
|
||||
nsMessageFromMsgHdrEnumerator **messageEnumerator);
|
||||
|
||||
NS_MSG_BASE nsresult NS_MsgGetPriorityFromString(const char *priority, nsMsgPriority *outPriority);
|
||||
|
||||
NS_MSG_BASE nsresult NS_MsgGetUntranslatedPriorityName (nsMsgPriority p, nsString *outName);
|
||||
|
||||
NS_MSG_BASE nsresult NS_MsgHashIfNecessary(nsCAutoString &name);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsNewsSummarySpec.h"
|
||||
#include "plstr.h"
|
||||
#include "nsString.h"
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsNewsSummarySpec);
|
||||
|
||||
nsNewsSummarySpec::~nsNewsSummarySpec()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsNewsSummarySpec);
|
||||
}
|
||||
|
||||
nsNewsSummarySpec::nsNewsSummarySpec()
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsNewsSummarySpec);
|
||||
}
|
||||
|
||||
nsNewsSummarySpec::nsNewsSummarySpec(const char *folderPath)
|
||||
: nsFileSpec(folderPath)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsNewsSummarySpec);
|
||||
CreateSummaryFileName();
|
||||
}
|
||||
|
||||
nsNewsSummarySpec::nsNewsSummarySpec(const nsFileSpec& inFolderPath)
|
||||
: nsFileSpec(inFolderPath)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsNewsSummarySpec);
|
||||
CreateSummaryFileName();
|
||||
}
|
||||
|
||||
nsNewsSummarySpec::nsNewsSummarySpec(const nsFilePath &inFolderPath) : nsFileSpec(inFolderPath)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsNewsSummarySpec);
|
||||
CreateSummaryFileName();
|
||||
}
|
||||
|
||||
void nsNewsSummarySpec::SetFolderName(const char *folderPath)
|
||||
{
|
||||
*this = folderPath;
|
||||
}
|
||||
|
||||
void nsNewsSummarySpec::CreateSummaryFileName()
|
||||
{
|
||||
char *leafName = GetLeafName();
|
||||
|
||||
nsCAutoString fullLeafName((const char*)leafName);
|
||||
|
||||
// Append .msf (message summary file)
|
||||
fullLeafName += ".msf";
|
||||
|
||||
SetLeafName(fullLeafName.GetBuffer());
|
||||
PL_strfree(leafName);
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _nsNewsSummarySpec_H
|
||||
#define _nsNewsSummarySpec_H
|
||||
|
||||
#include "nsFileSpec.h"
|
||||
#include "msgCore.h"
|
||||
|
||||
// Class to name a summary file for a newsgroup,
|
||||
// given a full folder file spec.
|
||||
// Note this class expects the invoking code to fully specify the folder path.
|
||||
// This class does NOT prepend the local folder directory, or put .sbd on the containing
|
||||
// directory names.
|
||||
class NS_MSG_BASE nsNewsSummarySpec : public nsFileSpec
|
||||
{
|
||||
public:
|
||||
nsNewsSummarySpec();
|
||||
nsNewsSummarySpec(const char *folderPath);
|
||||
nsNewsSummarySpec(const nsFileSpec& inFolderPath);
|
||||
nsNewsSummarySpec(const nsFilePath &inFolderPath);
|
||||
~nsNewsSummarySpec();
|
||||
void SetFolderName(const char *folderPath);
|
||||
|
||||
protected:
|
||||
void CreateSummaryFileName();
|
||||
|
||||
};
|
||||
|
||||
#endif /* _nsNewsSummarySpec_H */
|
||||
@@ -1,277 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "msgCore.h" // precompiled header...
|
||||
#include "prlog.h"
|
||||
|
||||
#include "MailNewsTypes.h"
|
||||
#include "nsUInt32Array.h"
|
||||
#include "nsQuickSort.h"
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsUInt32Array);
|
||||
|
||||
nsUInt32Array::nsUInt32Array()
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsUInt32Array);
|
||||
m_nSize = 0;
|
||||
m_nMaxSize = 0;
|
||||
m_nGrowBy = 0;
|
||||
m_pData = NULL;
|
||||
}
|
||||
|
||||
nsUInt32Array::~nsUInt32Array()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsUInt32Array);
|
||||
SetSize(0);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PRUint32 nsUInt32Array::GetSize() const
|
||||
{
|
||||
return m_nSize;
|
||||
}
|
||||
|
||||
PRBool nsUInt32Array::SetSize(PRUint32 nSize,
|
||||
PRBool adjustGrowth,
|
||||
PRUint32 nGrowBy)
|
||||
{
|
||||
if (adjustGrowth)
|
||||
m_nGrowBy = nGrowBy;
|
||||
|
||||
#ifdef MAX_ARR_ELEMS
|
||||
if (nSize > MAX_ARR_ELEMS);
|
||||
{
|
||||
PR_ASSERT(nSize <= MAX_ARR_ELEMS); // Will fail
|
||||
return PR_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (nSize == 0)
|
||||
{
|
||||
// Remove all elements
|
||||
PR_Free(m_pData);
|
||||
m_nSize = 0;
|
||||
m_nMaxSize = 0;
|
||||
m_pData = NULL;
|
||||
}
|
||||
else if (m_pData == NULL)
|
||||
{
|
||||
// Create a new array
|
||||
m_nMaxSize = PR_MAX(8, nSize);
|
||||
m_pData = (PRUint32 *)PR_Calloc(1, m_nMaxSize * sizeof(PRUint32));
|
||||
if (m_pData)
|
||||
m_nSize = nSize;
|
||||
else
|
||||
m_nSize = m_nMaxSize = 0;
|
||||
}
|
||||
else if (nSize <= m_nMaxSize)
|
||||
{
|
||||
// The new size is within the current maximum size, make sure new
|
||||
// elements are to initialized to zero
|
||||
if (nSize > m_nSize)
|
||||
nsCRT::memset(&m_pData[m_nSize], 0, (nSize - m_nSize) * sizeof(PRUint32));
|
||||
|
||||
m_nSize = nSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The array needs to grow, figure out how much
|
||||
PRUint32 nMaxSize;
|
||||
nGrowBy = PR_MAX(m_nGrowBy, PR_MIN(1024, PR_MAX(8, m_nSize / 8)));
|
||||
nMaxSize = PR_MAX(nSize, m_nMaxSize + nGrowBy);
|
||||
#ifdef MAX_ARR_ELEMS
|
||||
nMaxSize = PR_MIN(MAX_ARR_ELEMS, nMaxSize);
|
||||
#endif
|
||||
|
||||
PRUint32 *pNewData = (PRUint32 *)PR_Malloc(nMaxSize * sizeof(PRUint32));
|
||||
if (pNewData)
|
||||
{
|
||||
// Copy the data from the old array to the new one
|
||||
nsCRT::memcpy(pNewData, m_pData, m_nSize * sizeof(PRUint32));
|
||||
|
||||
// Zero out the remaining elements
|
||||
nsCRT::memset(&pNewData[m_nSize], 0, (nSize - m_nSize) * sizeof(PRUint32));
|
||||
m_nSize = nSize;
|
||||
m_nMaxSize = nMaxSize;
|
||||
|
||||
// Free the old array
|
||||
PR_Free(m_pData);
|
||||
m_pData = pNewData;
|
||||
}
|
||||
}
|
||||
|
||||
return nSize == m_nSize;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PRUint32 &nsUInt32Array::ElementAt(PRUint32 nIndex)
|
||||
{
|
||||
PR_ASSERT(nIndex < m_nSize);
|
||||
return m_pData[nIndex];
|
||||
}
|
||||
|
||||
PRUint32 nsUInt32Array::GetAt(PRUint32 nIndex) const
|
||||
{
|
||||
PR_ASSERT(nIndex < m_nSize);
|
||||
return m_pData[nIndex];
|
||||
}
|
||||
|
||||
PRUint32 *nsUInt32Array::GetData()
|
||||
{
|
||||
return m_pData;
|
||||
}
|
||||
|
||||
void nsUInt32Array::SetAt(PRUint32 nIndex, PRUint32 newElement)
|
||||
{
|
||||
PR_ASSERT(nIndex < m_nSize);
|
||||
m_pData[nIndex] = newElement;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PRUint32 nsUInt32Array::Add(PRUint32 newElement)
|
||||
{
|
||||
PRUint32 nIndex = m_nSize;
|
||||
|
||||
#ifdef MAX_ARR_ELEMS
|
||||
if (nIndex >= MAX_ARR_ELEMS)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
SetAtGrow(nIndex, newElement);
|
||||
return nIndex;
|
||||
}
|
||||
|
||||
PRUint32 nsUInt32Array::Add(PRUint32 *elementPtr, PRUint32 numElements)
|
||||
{
|
||||
if (SetSize(m_nSize + numElements))
|
||||
nsCRT::memcpy(m_pData + m_nSize, elementPtr, numElements * sizeof(PRUint32));
|
||||
|
||||
return m_nSize;
|
||||
}
|
||||
|
||||
PRUint32 *nsUInt32Array::CloneData()
|
||||
{
|
||||
PRUint32 *copyOfData = (PRUint32 *)PR_Malloc(m_nSize * sizeof(PRUint32));
|
||||
if (copyOfData)
|
||||
nsCRT::memcpy(copyOfData, m_pData, m_nSize * sizeof(PRUint32));
|
||||
|
||||
return copyOfData;
|
||||
}
|
||||
|
||||
void nsUInt32Array::InsertAt(PRUint32 nIndex, PRUint32 newElement, PRUint32 nCount)
|
||||
{
|
||||
PR_ASSERT(nCount > 0);
|
||||
|
||||
if (nIndex >= m_nSize)
|
||||
{
|
||||
// If the new element is after the end of the array, grow the array
|
||||
SetSize(nIndex + nCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The element is being insert inside the array
|
||||
int nOldSize = m_nSize;
|
||||
SetSize(m_nSize + nCount);
|
||||
|
||||
// Move the data after the insertion point
|
||||
nsCRT::memmove(&m_pData[nIndex + nCount], &m_pData[nIndex],
|
||||
(nOldSize - nIndex) * sizeof(PRUint32));
|
||||
}
|
||||
|
||||
// Insert the new elements
|
||||
PR_ASSERT(nIndex + nCount <= m_nSize);
|
||||
while (nCount--)
|
||||
m_pData[nIndex++] = newElement;
|
||||
}
|
||||
|
||||
void nsUInt32Array::InsertAt(PRUint32 nStartIndex, const nsUInt32Array *pNewArray)
|
||||
{
|
||||
PR_ASSERT(pNewArray != NULL);
|
||||
|
||||
if (pNewArray->GetSize() > 0)
|
||||
{
|
||||
InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
|
||||
for (PRUint32 i = 1; i < pNewArray->GetSize(); i++)
|
||||
m_pData[nStartIndex + i] = pNewArray->GetAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
void nsUInt32Array::RemoveAll()
|
||||
{
|
||||
SetSize(0);
|
||||
}
|
||||
|
||||
void nsUInt32Array::RemoveAt(PRUint32 nIndex, PRUint32 nCount)
|
||||
{
|
||||
PR_ASSERT(nIndex + nCount <= m_nSize);
|
||||
|
||||
if (nCount > 0)
|
||||
{
|
||||
// Make sure not to overstep the end of the array
|
||||
int nMoveCount = m_nSize - (nIndex + nCount);
|
||||
if (nCount && nMoveCount)
|
||||
nsCRT::memmove(&m_pData[nIndex], &m_pData[nIndex + nCount],
|
||||
nMoveCount * sizeof(PRUint32));
|
||||
|
||||
m_nSize -= nCount;
|
||||
}
|
||||
}
|
||||
|
||||
void nsUInt32Array::SetAtGrow(PRUint32 nIndex, PRUint32 newElement)
|
||||
{
|
||||
if (nIndex >= m_nSize)
|
||||
SetSize(nIndex+1);
|
||||
m_pData[nIndex] = newElement;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void nsUInt32Array::CopyArray(nsUInt32Array *oldA)
|
||||
{
|
||||
CopyArray(*oldA);
|
||||
}
|
||||
|
||||
void nsUInt32Array::CopyArray(nsUInt32Array &oldA)
|
||||
{
|
||||
if (m_pData)
|
||||
PR_Free(m_pData);
|
||||
m_nSize = oldA.m_nSize;
|
||||
m_nMaxSize = oldA.m_nMaxSize;
|
||||
m_pData = (PRUint32 *)PR_Malloc(m_nSize * sizeof(PRUint32));
|
||||
if (m_pData)
|
||||
nsCRT::memcpy(m_pData, oldA.m_pData, m_nSize * sizeof(PRUint32));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int CompareDWord (const void *v1, const void *v2, void *)
|
||||
{
|
||||
// QuickSort callback to compare array values
|
||||
PRUint32 i1 = *(PRUint32 *)v1;
|
||||
PRUint32 i2 = *(PRUint32 *)v2;
|
||||
return i1 - i2;
|
||||
}
|
||||
|
||||
void nsUInt32Array::QuickSort (int (*compare) (const void *elem1, const void *elem2, void *data))
|
||||
{
|
||||
if (m_nSize > 1)
|
||||
NS_QuickSort(m_pData, m_nSize, sizeof(void*), compare ? compare : CompareDWord, nsnull);
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
#ifndef _nsUInt32Array_H_
|
||||
#define _nsUInt32Array_H_
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsCRT.h"
|
||||
#include "prmem.h"
|
||||
#include "msgCore.h"
|
||||
|
||||
class NS_MSG_BASE nsUInt32Array
|
||||
{
|
||||
public:
|
||||
// Construction/destruction
|
||||
nsUInt32Array();
|
||||
virtual ~nsUInt32Array();
|
||||
|
||||
// State/attribute member functions
|
||||
PRUint32 GetSize() const;
|
||||
PRBool SetSize(PRUint32 nNewSize, PRBool AdjustGrowth=PR_FALSE, PRUint32 nGrowBy = 0);
|
||||
|
||||
// Accessor member functions
|
||||
PRUint32 &ElementAt(PRUint32 nIndex);
|
||||
PRUint32 GetAt(PRUint32 nIndex) const;
|
||||
PRUint32 *GetData();
|
||||
void SetAt(PRUint32 nIndex, PRUint32 newElement);
|
||||
|
||||
// Insertion/deletion member functions
|
||||
PRUint32 Add(PRUint32 newElement);
|
||||
PRUint32 Add(PRUint32 *elementPtr, PRUint32 numElements);
|
||||
void InsertAt(PRUint32 nIndex, PRUint32 newElement, PRUint32 nCount = 1);
|
||||
void InsertAt(PRUint32 nStartIndex, const nsUInt32Array *pNewArray);
|
||||
void RemoveAll();
|
||||
void RemoveAt(PRUint32 nIndex, PRUint32 nCount = 1);
|
||||
void SetAtGrow(PRUint32 nIndex, PRUint32 newElement);
|
||||
|
||||
// Sorting member functions
|
||||
void QuickSort(int (*compare) (const void *elem1, const void *elem2, void *) = NULL);
|
||||
|
||||
// Overloaded operators
|
||||
PRUint32 operator[](PRUint32 nIndex) const { return GetAt(nIndex); }
|
||||
PRUint32 &operator[](PRUint32 nIndex) { return ElementAt(nIndex); }
|
||||
|
||||
// Miscellaneous member functions
|
||||
PRUint32 *CloneData();
|
||||
void CopyArray(nsUInt32Array *oldA);
|
||||
void CopyArray(nsUInt32Array &oldA);
|
||||
|
||||
protected:
|
||||
// Member data
|
||||
PRUint32 m_nSize;
|
||||
PRUint32 m_nMaxSize;
|
||||
PRUint32 m_nGrowBy;
|
||||
PRUint32* m_pData;
|
||||
};
|
||||
|
||||
|
||||
#endif // _DWordArray_H_
|
||||
1153
mozilla/netwerk/base/src/nsFileTransport.cpp
Normal file
1153
mozilla/netwerk/base/src/nsFileTransport.cpp
Normal file
File diff suppressed because it is too large
Load Diff
38
mozilla/netwerk/cache/Makefile.in
vendored
Normal file
38
mozilla/netwerk/cache/Makefile.in
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape 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/NPL/
|
||||
#
|
||||
# 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 mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
DIRS = \
|
||||
public \
|
||||
memcache \
|
||||
filecache \
|
||||
mgr \
|
||||
build \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
33
mozilla/netwerk/cache/Makefile.win
vendored
Executable file
33
mozilla/netwerk/cache/Makefile.win
vendored
Executable file
@@ -0,0 +1,33 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape 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/NPL/
|
||||
#
|
||||
# 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 mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
|
||||
|
||||
DEPTH=..\..
|
||||
DIRS= \
|
||||
public \
|
||||
mgr \
|
||||
memcache \
|
||||
filecache \
|
||||
build \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
@@ -22,54 +22,33 @@ VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = msgbaseutil
|
||||
LIBRARY_NAME = msgbaseutil
|
||||
MODULE = nkcacke
|
||||
LIBRARY_NAME = necko_cache
|
||||
IS_COMPONENT = 1
|
||||
|
||||
CPPSRCS = \
|
||||
nsMsgGroupRecord.cpp \
|
||||
nsMsgLineBuffer.cpp \
|
||||
nsMsgFolder.cpp \
|
||||
nsMsgDBFolder.cpp \
|
||||
nsUInt32Array.cpp \
|
||||
nsMsgKeySet.cpp \
|
||||
nsLocalFolderSummarySpec.cpp \
|
||||
nsNewsSummarySpec.cpp \
|
||||
nsMsgIdentity.cpp \
|
||||
nsMsgIncomingServer.cpp \
|
||||
nsMsgUtils.cpp \
|
||||
nsMessage.cpp \
|
||||
nsMsgProtocol.cpp \
|
||||
nsMsgMailNewsUrl.cpp \
|
||||
nsMsgTxn.cpp \
|
||||
nsMsgI18N.cpp \
|
||||
CPPSRCS = nsNetDataCacheModule.cpp
|
||||
|
||||
SHARED_LIBRARY_LIBS = \
|
||||
$(DIST)/lib/libnkcachemgr_s.a \
|
||||
$(DIST)/lib/libnkfilecache_s.a \
|
||||
$(DIST)/lib/libnkmemcache_s.a \
|
||||
$(DIST)/lib/libmozdbm_s.a \
|
||||
$(DIST)/lib/libxpcomio_s.a \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
nsMsgGroupRecord.h \
|
||||
nsMsgLineBuffer.h \
|
||||
nsUInt32Array.h \
|
||||
nsMsgKeySet.h \
|
||||
nsMsgFolder.h \
|
||||
nsMsgDBFolder.h \
|
||||
nsLocalFolderSummarySpec.h \
|
||||
nsNewsSummarySpec.h \
|
||||
nsMsgIdentity.h \
|
||||
nsMsgIncomingServer.h \
|
||||
nsMsgUtils.h \
|
||||
nsMessage.h \
|
||||
nsMsgProtocol.h \
|
||||
nsMsgMailNewsUrl.h \
|
||||
nsMsgTxn.h \
|
||||
nsMsgI18N.h \
|
||||
LOCAL_INCLUDES = \
|
||||
-I$(DEPTH)/netwerk/cache/memcache \
|
||||
-I$(DEPTH)/netwerk/cache/filecache \
|
||||
-I$(DEPTH)/netwerk/cache/mgr \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_DSO_LDOPTS = \
|
||||
-L$(DIST)/bin \
|
||||
-L$(DIST)/lib \
|
||||
-lxpcom \
|
||||
-lrdfutil_s \
|
||||
$(NSPR_LIBS) \
|
||||
$(NULL)
|
||||
$(MKSHLIB_FORCE_ALL) \
|
||||
$(SHARED_LIBRARY_LIBS) \
|
||||
$(MKSHLIB_UNFORCE_ALL) \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
$(LIBRARY) $(SHARED_LIBRARY): $(SHARED_LIBRARY_LIBS) Makefile
|
||||
|
||||
51
mozilla/netwerk/cache/build/makefile.win
vendored
Normal file
51
mozilla/netwerk/cache/build/makefile.win
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape 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/NPL/
|
||||
#
|
||||
# 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 mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
|
||||
DEPTH=..\..\..
|
||||
MODULE=nkcache
|
||||
|
||||
MAKE_OBJ_TYPE=DLL
|
||||
DLLNAME=nkcache
|
||||
DLL=.\$(OBJDIR)\$(DLLNAME).dll
|
||||
|
||||
CPP_OBJS= \
|
||||
.\$(OBJDIR)\nsNetDataCacheModule.obj \
|
||||
$(NULL)
|
||||
|
||||
LLIBS= \
|
||||
$(DIST)\lib\nkcachemgr_s.lib \
|
||||
$(DIST)\lib\nkfilecache_s.lib \
|
||||
$(DIST)\lib\nkmemcache_s.lib \
|
||||
$(DIST)\lib\dbm32.lib \
|
||||
$(DIST)\lib\xpcom.lib \
|
||||
$(LIBNSPR)
|
||||
|
||||
INCS = $(INCS) \
|
||||
-I$(DEPTH)\netwerk\cache\memcache \
|
||||
-I$(DEPTH)\netwerk\cache\filecache \
|
||||
-I$(DEPTH)\netwerk\cache\mgr \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
install:: $(DLL)
|
||||
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin\components
|
||||
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).lib $(DIST)\lib
|
||||
|
||||
49
mozilla/netwerk/cache/build/nsNetDataCacheModule.cpp
vendored
Normal file
49
mozilla/netwerk/cache/build/nsNetDataCacheModule.cpp
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIModule.h"
|
||||
#include "nscore.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIGenericFactory.h"
|
||||
|
||||
#include "nsINetDataCache.h"
|
||||
#include "nsINetDataCacheManager.h"
|
||||
#include "nsMemCacheCID.h"
|
||||
#include "nsMemCache.h"
|
||||
#include "nsNetDiskCache.h"
|
||||
#include "nsNetDiskCacheCID.h"
|
||||
#include "nsCacheManager.h"
|
||||
|
||||
// Factory method to create a new nsMemCache instance. Used
|
||||
// by nsNetDataCacheModule
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMemCache, Init)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsNetDiskCache, Init)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsCacheManager, Init)
|
||||
|
||||
static nsModuleComponentInfo components[] = {
|
||||
{ "Memory Cache", NS_MEM_CACHE_FACTORY_CID, NS_NETWORK_MEMORY_CACHE_PROGID, nsMemCacheConstructor },
|
||||
{ "File Cache", NS_NETDISKCACHE_CID, NS_NETWORK_FILE_CACHE_PROGID, nsNetDiskCacheConstructor },
|
||||
{ "Cache Manager",NS_CACHE_MANAGER_CID, NS_NETWORK_CACHE_MANAGER_PROGID,nsCacheManagerConstructor }
|
||||
};
|
||||
|
||||
NS_IMPL_NSGETMODULE("Network Data Cache", components)
|
||||
60
mozilla/netwerk/cache/filecache/Makefile.in
vendored
Normal file
60
mozilla/netwerk/cache/filecache/Makefile.in
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
#
|
||||
# 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 Mozilla Communicator.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Intel Corp.
|
||||
# Portions created by Intel Corp. are
|
||||
# Copyright (C) 1999, 1999 Intel Corp. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
# Carl Wong <carl.wong@intel.com>
|
||||
#
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
srcdir = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = nkcache
|
||||
|
||||
LIBRARY_NAME = nkfilecache_s
|
||||
|
||||
REQUIRES = nspr dbm
|
||||
|
||||
EXTRA_DSO_LDOPTS += -L$(DIST)/lib -lmozdbm_s
|
||||
|
||||
EXPORTS=nsNetDiskCacheCID.h \
|
||||
nsNetDiskCache.h \
|
||||
nsIDBAccessor.h \
|
||||
nsDBAccessor.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
nsDBAccessor.cpp\
|
||||
nsDBEnumerator.cpp \
|
||||
nsNetDiskCache.cpp \
|
||||
nsDiskCacheRecord.cpp \
|
||||
nsDiskCacheRecordChannel.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_LIBS = $(NSPR_LIBS)
|
||||
|
||||
# we don't want the shared lib, but we want to force the creation of a
|
||||
# static lib.
|
||||
override NO_SHARED_LIB=1
|
||||
override NO_STATIC_LIB=
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
44
mozilla/netwerk/cache/filecache/makefile.win
vendored
Normal file
44
mozilla/netwerk/cache/filecache/makefile.win
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
|
||||
DEPTH=..\..\..
|
||||
|
||||
include <$(DEPTH)/config/config.mak>
|
||||
|
||||
MODULE = nkcache
|
||||
|
||||
LIBRARY_NAME = nkfilecache_s
|
||||
|
||||
CPP_OBJS= \
|
||||
.\$(OBJDIR)\nsDBAccessor.obj \
|
||||
.\$(OBJDIR)\nsDBEnumerator.obj \
|
||||
.\$(OBJDIR)\nsNetDiskCache.obj \
|
||||
.\$(OBJDIR)\nsDiskCacheRecord.obj \
|
||||
.\$(OBJDIR)\nsDiskCacheRecordChannel.obj \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS=nsNetDiskCacheCID.h
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
install:: $(LIBRARY)
|
||||
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
|
||||
|
||||
clobber::
|
||||
rm -rf $(OBJDIR)
|
||||
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib
|
||||
|
||||
416
mozilla/netwerk/cache/filecache/nsDBAccessor.cpp
vendored
Normal file
416
mozilla/netwerk/cache/filecache/nsDBAccessor.cpp
vendored
Normal file
@@ -0,0 +1,416 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 Mozilla Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of filecache implementation.
|
||||
*
|
||||
* nsIDBAccessor is a interface that shields all the direct database access
|
||||
* method from nsNetDiskCache.
|
||||
*
|
||||
* nsDBAccessor is a implementation of the nsIDBAccessor interface. It
|
||||
* uses dbm(Berkely) as the database.
|
||||
*
|
||||
* a nsDiskCacheRecord is mapped into two entries in the database,
|
||||
* key->recordID
|
||||
* recordID->metadata
|
||||
*/
|
||||
|
||||
#include "nsDBAccessor.h"
|
||||
#include "nscore.h"
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "plhash.h"
|
||||
#include "nsCRT.h"
|
||||
|
||||
nsDBAccessor::nsDBAccessor() :
|
||||
mDB(0) ,
|
||||
mDBFile(0) ,
|
||||
mSessionID(0) ,
|
||||
mSessionCntr(0) ,
|
||||
mDBFilesize(0)
|
||||
{
|
||||
mLastSyncTime = PR_IntervalNow() ;
|
||||
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsDBAccessor::~nsDBAccessor()
|
||||
{
|
||||
Shutdown() ;
|
||||
}
|
||||
|
||||
//
|
||||
// Implement nsISupports methods
|
||||
//
|
||||
NS_IMPL_ISUPPORTS(nsDBAccessor, NS_GET_IID(nsIDBAccessor))
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// nsIDBAccessor methods
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::Init(nsIFileSpec* dbfile)
|
||||
{
|
||||
char* dbname ;
|
||||
|
||||
// this should cover all platforms.
|
||||
dbfile->GetNativePath(&dbname) ;
|
||||
|
||||
mDBFile = dbfile ;
|
||||
|
||||
// FUR - how is page size chosen ? It's worth putting a comment
|
||||
// in here about the possible usefulness of tuning these parameters
|
||||
HASHINFO hash_info = {
|
||||
16*1024 , /* bucket size */
|
||||
0 , /* fill factor */
|
||||
0 , /* number of elements */
|
||||
0 , /* bytes to cache */
|
||||
0 , /* hash function */
|
||||
0} ; /* byte order */
|
||||
|
||||
mDB = dbopen(dbname,
|
||||
O_RDWR | O_CREAT ,
|
||||
0600 ,
|
||||
DB_HASH ,
|
||||
& hash_info) ;
|
||||
|
||||
nsCRT::free(dbname) ;
|
||||
|
||||
if(!mDB)
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
// set mSessionID
|
||||
DBT db_key, db_data ;
|
||||
|
||||
db_key.data = NS_CONST_CAST(char*, SessionKey) ;
|
||||
db_key.size = PL_strlen(SessionKey) ;
|
||||
|
||||
int status = (*mDB->get)(mDB, &db_key, &db_data, 0) ;
|
||||
if(status == -1) {
|
||||
NS_ERROR("ERROR: failed get session id in database.") ;
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
|
||||
if(status == 0) {
|
||||
// get the last session id
|
||||
PRInt16 *old_ID = NS_STATIC_CAST(PRInt16*, db_data.data) ;
|
||||
if(*old_ID < ini_sessionID) {
|
||||
NS_ERROR("ERROR: Bad Session ID in database, corrupted db.") ;
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
|
||||
mSessionID = *old_ID + 1 ;
|
||||
}
|
||||
else if(status == 1) {
|
||||
// must be a new db
|
||||
mSessionID = ini_sessionID ;
|
||||
}
|
||||
db_data.data = NS_REINTERPRET_CAST(void*, &mSessionID) ;
|
||||
db_data.size = sizeof(PRInt16) ;
|
||||
|
||||
// store the new session id
|
||||
status = (*mDB->put)(mDB, &db_key, &db_data, 0) ;
|
||||
|
||||
if(status == 0) {
|
||||
(*mDB->sync)(mDB, 0) ;
|
||||
|
||||
// initialize database filesize
|
||||
return mDBFile->GetFileSize(&mDBFilesize) ;
|
||||
}
|
||||
else {
|
||||
NS_ERROR("reset session ID failure.") ;
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::Shutdown(void)
|
||||
{
|
||||
if(mDB) {
|
||||
(*mDB->sync)(mDB, 0) ;
|
||||
(*mDB->close)(mDB) ;
|
||||
mDB = nsnull ;
|
||||
}
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::Get(PRInt32 aID, void** anEntry, PRUint32 *aLength)
|
||||
{
|
||||
if(!anEntry)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*anEntry = nsnull ;
|
||||
*aLength = 0 ;
|
||||
|
||||
NS_ASSERTION(mDB, "no database") ;
|
||||
|
||||
DBT db_key, db_data ;
|
||||
|
||||
db_key.data = NS_REINTERPRET_CAST(void*, &aID) ;
|
||||
db_key.size = sizeof(PRInt32) ;
|
||||
|
||||
int status = 0 ;
|
||||
status = (*mDB->get)(mDB, &db_key, &db_data, 0) ;
|
||||
|
||||
if(status == 0) {
|
||||
*anEntry = db_data.data ;
|
||||
*aLength = db_data.size ;
|
||||
return NS_OK ;
|
||||
}
|
||||
else if(status == 1)
|
||||
return NS_OK ;
|
||||
else
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::Put(PRInt32 aID, void* anEntry, PRUint32 aLength)
|
||||
{
|
||||
NS_ASSERTION(mDB, "no database") ;
|
||||
|
||||
DBT db_key, db_data ;
|
||||
|
||||
db_key.data = NS_REINTERPRET_CAST(void*, &aID) ;
|
||||
db_key.size = sizeof(PRInt32) ;
|
||||
|
||||
db_data.data = anEntry ;
|
||||
db_data.size = aLength ;
|
||||
|
||||
if(0 == (*mDB->put)(mDB, &db_key, &db_data, 0)) {
|
||||
return Sync() ;
|
||||
}
|
||||
else {
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* It's more important to remove the id->metadata entry first since
|
||||
* key->id mapping is just a reference
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::Del(PRInt32 aID, void* anEntry, PRUint32 aLength)
|
||||
{
|
||||
NS_ASSERTION(mDB, "no database") ;
|
||||
|
||||
DBT db_key ;
|
||||
|
||||
// delete recordID->metadata
|
||||
db_key.data = NS_REINTERPRET_CAST(void*, &aID) ;
|
||||
db_key.size = sizeof(PRInt32) ;
|
||||
|
||||
PRInt32 status = -1 ;
|
||||
status = (*mDB->del)(mDB, &db_key, 0) ;
|
||||
|
||||
if(-1 == status) {
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
|
||||
// delete key->recordID
|
||||
db_key.data = anEntry ;
|
||||
db_key.size = aLength ;
|
||||
status = (*mDB->del)(mDB, &db_key, 0) ;
|
||||
if(-1 == status) {
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
|
||||
return Sync() ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::GetID(const char* key, PRUint32 length, PRInt32* aID)
|
||||
{
|
||||
NS_ASSERTION(mDB, "no database") ;
|
||||
|
||||
DBT db_key, db_data ;
|
||||
|
||||
db_key.data = NS_CONST_CAST(char*, key) ;
|
||||
db_key.size = length ;
|
||||
|
||||
int status = (*mDB->get)(mDB, &db_key, &db_data, 0) ;
|
||||
if(status == 0) {
|
||||
// found recordID
|
||||
*aID = *(NS_REINTERPRET_CAST(PRInt32*, db_data.data)) ;
|
||||
return NS_OK ;
|
||||
}
|
||||
else if(status == 1) {
|
||||
// create a new one
|
||||
PRInt32 id = 0 ;
|
||||
id = mSessionID << 16 | mSessionCntr++ ;
|
||||
|
||||
// add new id into mDB
|
||||
db_data.data = NS_REINTERPRET_CAST(void*, &id) ;
|
||||
db_data.size = sizeof(PRInt32) ;
|
||||
|
||||
status = (*mDB->put)(mDB, &db_key, &db_data, 0) ;
|
||||
if(status != 0) {
|
||||
NS_ERROR("updating db failure.") ;
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
*aID = id ;
|
||||
return Sync() ;
|
||||
}
|
||||
else {
|
||||
NS_ERROR("ERROR: keydb failure.") ;
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::EnumEntry(void** anEntry, PRUint32* aLength, PRBool bReset)
|
||||
{
|
||||
if(!anEntry)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*anEntry = nsnull ;
|
||||
*aLength = 0 ;
|
||||
|
||||
NS_ASSERTION(mDB, "no database") ;
|
||||
|
||||
PRUint32 flag ;
|
||||
|
||||
if(bReset)
|
||||
flag = R_FIRST ;
|
||||
else
|
||||
flag = R_NEXT ;
|
||||
|
||||
DBT db_key, db_data ;
|
||||
|
||||
PRUint32 len = PL_strlen(SessionKey) ;
|
||||
|
||||
int status ;
|
||||
|
||||
do {
|
||||
status = (*mDB->seq)(mDB, &db_key, &db_data, flag) ;
|
||||
flag = R_NEXT ;
|
||||
if(status == -1)
|
||||
return NS_ERROR_FAILURE ;
|
||||
// get next if it's a key->recordID
|
||||
if(db_key.size > sizeof(PRInt32) && db_data.size == sizeof(PRInt32))
|
||||
continue ;
|
||||
// get next if it's a sessionID entry
|
||||
if(db_key.size == len && db_data.size == sizeof(PRInt16))
|
||||
continue ;
|
||||
// recordID is always 32 bits long
|
||||
if(db_key.size == sizeof(PRInt32))
|
||||
break ;
|
||||
} while(!status) ;
|
||||
|
||||
if (0 == status) {
|
||||
*anEntry = db_data.data ;
|
||||
*aLength = db_data.size ;
|
||||
}
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
/*
|
||||
* returns the cached database file size.
|
||||
* mDBFilesize will be updated during Sync().
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::GetDBFilesize(PRUint32* aSize)
|
||||
{
|
||||
*aSize = mDBFilesize ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::GetSpecialEntry(void** anEntry, PRUint32* aLength)
|
||||
{
|
||||
if(!anEntry)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*anEntry = nsnull ;
|
||||
*aLength = 0 ;
|
||||
|
||||
DBT db_key, db_data ;
|
||||
|
||||
db_key.data = NS_CONST_CAST(char*, SpecialEntry) ;
|
||||
db_key.size = PL_strlen(SpecialEntry) ;
|
||||
|
||||
int status = (*mDB->get)(mDB, &db_key, &db_data, 0) ;
|
||||
|
||||
if(status == -1) {
|
||||
NS_ERROR("ERROR: failed get special entry in database.") ;
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
|
||||
if(status == 0) {
|
||||
*anEntry = db_data.data ;
|
||||
*aLength = db_data.size ;
|
||||
}
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBAccessor::SetSpecialEntry(void* anEntry, PRUint32 aLength)
|
||||
{
|
||||
DBT db_key, db_data ;
|
||||
|
||||
db_key.data = NS_CONST_CAST(char*, SpecialEntry) ;
|
||||
db_key.size = PL_strlen(SpecialEntry) ;
|
||||
|
||||
db_data.data = anEntry ;
|
||||
db_data.size = aLength ;
|
||||
|
||||
if(0 == (*mDB->put)(mDB, &db_key, &db_data, 0)) {
|
||||
(*mDB->sync)(mDB, 0) ;
|
||||
return NS_OK ;
|
||||
}
|
||||
else {
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sync routine is only called when the SyncInterval is reached. Otherwise
|
||||
* it just returns. If db synced, the filesize will be updated at the
|
||||
* same time.
|
||||
*/
|
||||
nsresult
|
||||
nsDBAccessor::Sync(void)
|
||||
{
|
||||
PRIntervalTime time = PR_IntervalNow() ;
|
||||
PRIntervalTime duration = time - mLastSyncTime ;
|
||||
|
||||
if (PR_IntervalToMilliseconds(duration) > SyncInterval) {
|
||||
int status = (*mDB->sync)(mDB, 0) ;
|
||||
if(status == 0) {
|
||||
// printf("\tsynced\n") ;
|
||||
mLastSyncTime = time ;
|
||||
|
||||
// update db filesize here
|
||||
return mDBFile->GetFileSize(&mDBFilesize) ;
|
||||
|
||||
} else
|
||||
return NS_ERROR_FAILURE ;
|
||||
} else {
|
||||
// printf("\tnot synced\n") ;
|
||||
return NS_OK ;
|
||||
}
|
||||
}
|
||||
93
mozilla/netwerk/cache/filecache/nsDBAccessor.h
vendored
Normal file
93
mozilla/netwerk/cache/filecache/nsDBAccessor.h
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
/*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 Mozilla Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of filecache implementation.
|
||||
*
|
||||
* nsIDBAccessor is a interface that shields all the direct database access
|
||||
* method from nsNetDiskCache.
|
||||
*
|
||||
* nsDBAccessor is a implementation of the nsIDBAccessor interface. It
|
||||
* uses dbm(Berkely) as the database.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _NSIDBACCESSOR_H_
|
||||
#define _NSIDBACCESSOR_H_
|
||||
|
||||
#include "nsIDBAccessor.h"
|
||||
#include "mcom_db.h"
|
||||
#include "prinrval.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
// bogus string for the key of session id
|
||||
static const char * const SessionKey = "SK" ;
|
||||
|
||||
// bogus string for the size
|
||||
static const char * const SpecialEntry = "SE" ;
|
||||
|
||||
// initial session id number
|
||||
static const PRInt16 ini_sessionID = 0xff ;
|
||||
|
||||
static const PRUint16 SyncInterval = 1000 ;
|
||||
|
||||
class nsDBAccessor : public nsIDBAccessor
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsDBAccessor() ;
|
||||
virtual ~nsDBAccessor() ;
|
||||
|
||||
NS_IMETHOD Init(nsIFileSpec* dbfile) ;
|
||||
NS_IMETHOD Shutdown(void) ;
|
||||
|
||||
NS_IMETHOD Put(PRInt32 aID, void* anEntry, PRUint32 aLength) ;
|
||||
|
||||
NS_IMETHOD Get(PRInt32 aID, void** anEntry, PRUint32 *aLength) ;
|
||||
|
||||
NS_IMETHOD Del(PRInt32 aID, void* anEntry, PRUint32 aLength) ;
|
||||
|
||||
NS_IMETHOD GetID(const char* key, PRUint32 length, PRInt32* aID) ;
|
||||
|
||||
NS_IMETHOD EnumEntry(void* *anEntry, PRUint32* aLength, PRBool bReset) ;
|
||||
|
||||
NS_IMETHOD GetDBFilesize(PRUint32* aSize) ;
|
||||
|
||||
NS_IMETHOD GetSpecialEntry(void** anEntry, PRUint32 *aLength) ;
|
||||
NS_IMETHOD SetSpecialEntry(void* anEntry, PRUint32 aLength) ;
|
||||
|
||||
protected:
|
||||
nsresult Sync(void) ;
|
||||
|
||||
private:
|
||||
DB * mDB ;
|
||||
nsCOMPtr<nsIFileSpec> mDBFile ;
|
||||
PRInt16 mSessionID ;
|
||||
PRInt16 mSessionCntr ;
|
||||
PRIntervalTime mLastSyncTime ;
|
||||
PRUint32 mDBFilesize ; // cached DB filesize,
|
||||
// updated on every sync for now
|
||||
} ;
|
||||
|
||||
#endif // _NSIDBACCESSOR_H_
|
||||
108
mozilla/netwerk/cache/filecache/nsDBEnumerator.cpp
vendored
Normal file
108
mozilla/netwerk/cache/filecache/nsDBEnumerator.cpp
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 Mozilla Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of filecache implementation.
|
||||
*
|
||||
* It implements a simple iterator for the database, see nsDBAccessor.
|
||||
*/
|
||||
|
||||
#include "nsDBEnumerator.h"
|
||||
#include "nsDiskCacheRecord.h"
|
||||
|
||||
nsDBEnumerator::nsDBEnumerator(nsIDBAccessor* aDB, nsNetDiskCache* aCache) :
|
||||
m_DB(aDB) ,
|
||||
m_DiskCache(aCache) ,
|
||||
m_tempEntry(0) ,
|
||||
m_tempEntry_length(0) ,
|
||||
m_CacheEntry(0) ,
|
||||
m_bReset(PR_TRUE)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
}
|
||||
|
||||
nsDBEnumerator::~nsDBEnumerator()
|
||||
{
|
||||
NS_IF_RELEASE(m_CacheEntry) ;
|
||||
}
|
||||
|
||||
//
|
||||
// Implement nsISupports methods
|
||||
//
|
||||
NS_IMPL_ISUPPORTS(nsDBEnumerator, NS_GET_IID(nsIEnumerator))
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// nsISimpleEnumerator methods
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDBEnumerator::HasMoreElements(PRBool *_retval)
|
||||
{
|
||||
*_retval = PR_FALSE ;
|
||||
|
||||
nsresult rv = m_DB->EnumEntry(&m_tempEntry, &m_tempEntry_length, m_bReset) ;
|
||||
|
||||
if(NS_FAILED(rv)) {
|
||||
// do some error recovery
|
||||
m_DiskCache->DBRecovery() ;
|
||||
return rv ;
|
||||
}
|
||||
|
||||
m_bReset = PR_FALSE ;
|
||||
|
||||
if(m_tempEntry && m_tempEntry_length != 0)
|
||||
*_retval = PR_TRUE ;
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
// this routine does not create a new item by itself
|
||||
// Rather it reuses the item inside the object. So if you need to use the
|
||||
// item later, you have to
|
||||
// create a new item specifically, using copy constructor or some other dup
|
||||
// function. And don't forget to release it after you're done
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
nsDBEnumerator::GetNext(nsISupports **_retval)
|
||||
{
|
||||
if(!m_CacheEntry) {
|
||||
m_CacheEntry = new nsDiskCacheRecord(m_DB, m_DiskCache) ;
|
||||
if(m_CacheEntry)
|
||||
NS_ADDREF(m_CacheEntry) ;
|
||||
else
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
}
|
||||
|
||||
if(!_retval)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
*_retval = nsnull ;
|
||||
|
||||
nsresult rv = m_CacheEntry->RetrieveInfo(m_tempEntry, m_tempEntry_length) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
*_retval = NS_STATIC_CAST(nsISupports*, m_CacheEntry) ;
|
||||
NS_ADDREF(*_retval) ; // all good getter addref
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
60
mozilla/netwerk/cache/filecache/nsDBEnumerator.h
vendored
Normal file
60
mozilla/netwerk/cache/filecache/nsDBEnumerator.h
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 Mozilla Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of filecache implementation.
|
||||
*
|
||||
* It implements a simple iterator for the database, see nsDBAccessor.
|
||||
*/
|
||||
|
||||
#ifndef _NS_DBENUMERATOR_H_
|
||||
#define _NS_DBENUMERATOR_H_
|
||||
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsINetDataCacheRecord.h"
|
||||
#include "nsIDBAccessor.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsNetDiskCache.h"
|
||||
#include "nsDiskCacheRecord.h"
|
||||
|
||||
class nsCachedDiskData ; /* forward decl */
|
||||
|
||||
class nsDBEnumerator : public nsISimpleEnumerator {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_DECL_NSISIMPLEENUMERATOR
|
||||
|
||||
nsDBEnumerator(nsIDBAccessor* aDB, nsNetDiskCache* aCache) ;
|
||||
virtual ~nsDBEnumerator() ;
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIDBAccessor> m_DB ;
|
||||
nsCOMPtr<nsNetDiskCache> m_DiskCache ;
|
||||
void * m_tempEntry ;
|
||||
PRUint32 m_tempEntry_length ;
|
||||
nsDiskCacheRecord* m_CacheEntry ;
|
||||
PRBool m_bReset ;
|
||||
};
|
||||
|
||||
#endif // _NS_DBENUMERATOR_H_
|
||||
456
mozilla/netwerk/cache/filecache/nsDiskCacheRecord.cpp
vendored
Normal file
456
mozilla/netwerk/cache/filecache/nsDiskCacheRecord.cpp
vendored
Normal file
@@ -0,0 +1,456 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 Mozilla Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
#include "nsDiskCacheRecord.h"
|
||||
#include "nsINetDataDiskCache.h"
|
||||
#include "nsNetDiskCacheCID.h"
|
||||
#include "nsDiskCacheRecordChannel.h"
|
||||
#include "nsFileStream.h"
|
||||
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIProtocolHandler.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsIAllocator.h"
|
||||
|
||||
#include "plstr.h"
|
||||
#include "prprf.h"
|
||||
#include "prmem.h"
|
||||
#include "prlog.h"
|
||||
#include "prtypes.h"
|
||||
#include "netCore.h"
|
||||
|
||||
#include "nsDBAccessor.h"
|
||||
|
||||
#if !defined(IS_LITTLE_ENDIAN) && !defined(IS_BIG_ENDIAN)
|
||||
ERROR! Must have a byte order
|
||||
#endif
|
||||
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define COPY_INT32(_a,_b) memcpy(_a, _b, sizeof(int32))
|
||||
#else
|
||||
#define COPY_INT32(_a,_b) /* swap */ \
|
||||
do { \
|
||||
((char *)(_a))[0] = ((char *)(_b))[3]; \
|
||||
((char *)(_a))[1] = ((char *)(_b))[2]; \
|
||||
((char *)(_a))[2] = ((char *)(_b))[1]; \
|
||||
((char *)(_a))[3] = ((char *)(_b))[0]; \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
nsDiskCacheRecord::nsDiskCacheRecord(nsIDBAccessor* db, nsNetDiskCache* aCache) :
|
||||
mKey(0) ,
|
||||
mKeyLength(0) ,
|
||||
mRecordID(0) ,
|
||||
mMetaData(0) ,
|
||||
mMetaDataLength(0) ,
|
||||
mDB(db) ,
|
||||
mInfo(0) ,
|
||||
mInfoSize(0) ,
|
||||
mNumChannels(0) ,
|
||||
mDiskCache(aCache)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
NS_ASSERTION(mDiskCache, "Must have an nsNetDiskCache");
|
||||
NS_ADDREF(mDiskCache);
|
||||
}
|
||||
|
||||
// mem alloced. so caller should do free() on key.
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::Init(const char* key, PRUint32 length, PRInt32 ID)
|
||||
{
|
||||
NS_NewFileSpec(getter_AddRefs(mFile));
|
||||
if(!mFile)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
// copy key
|
||||
mKeyLength = length ;
|
||||
mKey = NS_STATIC_CAST(char*, nsAllocator::Alloc(mKeyLength*sizeof(char))) ;
|
||||
if(!mKey)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
memcpy(mKey, key, length) ;
|
||||
|
||||
// get RecordID
|
||||
mRecordID = ID ;
|
||||
|
||||
// setup the file name
|
||||
nsCOMPtr<nsIFileSpec> dbFolder ;
|
||||
mDiskCache->GetDiskCacheFolder(getter_AddRefs(dbFolder)) ;
|
||||
|
||||
nsresult rv = mFile->FromFileSpec(dbFolder) ;
|
||||
if(NS_FAILED(rv))
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
// dir is a hash result of mRecordID%32, hope it's enough
|
||||
char filename[9], dirName[3] ;
|
||||
|
||||
PR_snprintf(dirName, 3, "%02x", (((PRUint32)mRecordID) % 32)) ;
|
||||
mFile->AppendRelativeUnixPath(dirName) ;
|
||||
|
||||
PR_snprintf(filename, 9, "%08x", mRecordID) ;
|
||||
mFile->AppendRelativeUnixPath(filename) ;
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
nsDiskCacheRecord::~nsDiskCacheRecord()
|
||||
{
|
||||
if(mKey)
|
||||
nsAllocator::Free(mKey) ;
|
||||
if(mMetaData)
|
||||
nsAllocator::Free(mMetaData) ;
|
||||
if(mInfo)
|
||||
nsAllocator::Free(mInfo) ;
|
||||
|
||||
NS_IF_RELEASE(mDiskCache);
|
||||
}
|
||||
|
||||
//
|
||||
// Implement nsISupports methods
|
||||
//
|
||||
NS_IMPL_ISUPPORTS(nsDiskCacheRecord, NS_GET_IID(nsINetDataCacheRecord))
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// nsINetDataCacheRecord methods
|
||||
|
||||
// yes, mem alloced on *_retval.
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::GetKey(PRUint32 *length, char** _retval)
|
||||
{
|
||||
if(!_retval)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*length = mKeyLength ;
|
||||
*_retval = NS_STATIC_CAST(char*, nsAllocator::Alloc(mKeyLength*sizeof(char))) ;
|
||||
if(!*_retval)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
memcpy(*_retval, mKey, mKeyLength) ;
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::GetRecordID(PRInt32* aRecordID)
|
||||
{
|
||||
*aRecordID = mRecordID ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
// yes, mem alloced on *_retval.
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::GetMetaData(PRUint32 *length, char **_retval)
|
||||
{
|
||||
if(!_retval)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
// always null the return value first.
|
||||
*_retval = nsnull ;
|
||||
|
||||
*length = mMetaDataLength ;
|
||||
|
||||
if(mMetaDataLength) {
|
||||
*_retval = NS_STATIC_CAST(char*, nsAllocator::Alloc(mMetaDataLength*sizeof(char))) ;
|
||||
if(!*_retval)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
memcpy(*_retval, mMetaData, mMetaDataLength) ;
|
||||
}
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::SetMetaData(PRUint32 length, const char* data)
|
||||
{
|
||||
// set the mMetaData
|
||||
mMetaDataLength = length ;
|
||||
if(mMetaData)
|
||||
nsAllocator::Free(mMetaData) ;
|
||||
mMetaData = NS_STATIC_CAST(char*, nsAllocator::Alloc(mMetaDataLength*sizeof(char))) ;
|
||||
if(!mMetaData) {
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
}
|
||||
memcpy(mMetaData, data, length) ;
|
||||
|
||||
// Generate mInfo
|
||||
nsresult rv = GenInfo() ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
// write through into mDB
|
||||
rv = mDB->Put(mRecordID, mInfo, mInfoSize) ;
|
||||
|
||||
return rv ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::GetStoredContentLength(PRUint32 *aStoredContentLength)
|
||||
{
|
||||
return mFile->GetFileSize(aStoredContentLength) ;
|
||||
}
|
||||
|
||||
// untill nsIFileSpec::Truncate() is in, we have to do all this ugly stuff
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::SetStoredContentLength(PRUint32 aStoredContentLength)
|
||||
{
|
||||
PRUint32 len = 0 ;
|
||||
nsresult rv = mFile->GetFileSize(&len) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
if(len < aStoredContentLength)
|
||||
{
|
||||
NS_ERROR("Error: can not set filesize to something bigger than itself.\n") ;
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
else {
|
||||
rv = mFile->Truncate(aStoredContentLength) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
mDiskCache->m_StorageInUse -= (len - aStoredContentLength) ;
|
||||
return NS_OK ;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::Delete(void)
|
||||
{
|
||||
if(mNumChannels)
|
||||
return NS_ERROR_NOT_AVAILABLE ;
|
||||
|
||||
PRUint32 len ;
|
||||
mFile->GetFileSize(&len) ;
|
||||
|
||||
nsFileSpec cache_file ;
|
||||
nsresult rv = mFile->GetFileSpec(&cache_file) ;
|
||||
|
||||
if(NS_FAILED(rv))
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
cache_file.Delete(PR_TRUE) ;
|
||||
|
||||
// updata the storage size
|
||||
mDiskCache->m_StorageInUse -= len ;
|
||||
|
||||
rv = mDB->Del(mRecordID, mKey, mKeyLength) ;
|
||||
if(NS_FAILED(rv))
|
||||
return NS_ERROR_FAILURE ;
|
||||
else
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::GetFilename(nsIFileSpec * *aFilename)
|
||||
{
|
||||
if(!aFilename)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*aFilename = mFile ;
|
||||
NS_ADDREF(*aFilename) ;
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::NewChannel(nsILoadGroup *loadGroup, nsIChannel **_retval)
|
||||
{
|
||||
nsDiskCacheRecordChannel* channel = new nsDiskCacheRecordChannel(this, loadGroup) ;
|
||||
if(!channel)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
nsresult rv = channel->Init() ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
NS_ADDREF(channel) ;
|
||||
*_retval = NS_STATIC_CAST(nsIChannel*, channel) ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// nsDiskCacheRecord methods
|
||||
|
||||
// file name is represented by a url string. I hope this would be more
|
||||
// generic
|
||||
nsresult
|
||||
nsDiskCacheRecord::GenInfo()
|
||||
{
|
||||
if(mInfo)
|
||||
nsAllocator::Free(mInfo) ;
|
||||
|
||||
char* file_url=nsnull ;
|
||||
PRUint32 name_len ;
|
||||
mFile->GetURLString(&file_url) ;
|
||||
name_len = PL_strlen(file_url)+1 ;
|
||||
|
||||
mInfoSize = sizeof(PRUint32) ; // checksum for mInfoSize
|
||||
mInfoSize += sizeof(PRInt32) ; // RecordID
|
||||
mInfoSize += sizeof(PRUint32) ; // key length
|
||||
mInfoSize += mKeyLength ; // key
|
||||
mInfoSize += sizeof(PRUint32) ; // metadata length
|
||||
mInfoSize += mMetaDataLength ; // metadata
|
||||
mInfoSize += sizeof(PRUint32) ; // filename length
|
||||
mInfoSize += name_len ; // filename
|
||||
|
||||
void* newInfo = nsAllocator::Alloc(mInfoSize*sizeof(char)) ;
|
||||
if(!newInfo) {
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
}
|
||||
|
||||
// copy the checksum mInfoSize
|
||||
char* cur_ptr = NS_STATIC_CAST(char*, newInfo) ;
|
||||
COPY_INT32(cur_ptr, &mInfoSize) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// copy RecordID
|
||||
COPY_INT32(cur_ptr, &mRecordID) ;
|
||||
cur_ptr += sizeof(PRInt32) ;
|
||||
|
||||
// copy key length
|
||||
COPY_INT32(cur_ptr, &mKeyLength) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// copy key
|
||||
memcpy(cur_ptr, mKey, mKeyLength) ;
|
||||
cur_ptr += mKeyLength ;
|
||||
|
||||
// copy metadata length
|
||||
COPY_INT32(cur_ptr, &mMetaDataLength) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// copy metadata
|
||||
memcpy(cur_ptr, mMetaData, mMetaDataLength) ;
|
||||
cur_ptr += mMetaDataLength ;
|
||||
|
||||
// copy file name length
|
||||
COPY_INT32(cur_ptr, &name_len) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// copy file name
|
||||
memcpy(cur_ptr, file_url, name_len) ;
|
||||
cur_ptr += name_len ;
|
||||
|
||||
PR_ASSERT(cur_ptr == NS_STATIC_CAST(char*, newInfo) + mInfoSize);
|
||||
mInfo = newInfo ;
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
/*
|
||||
* This Method suppose to get all the info from the db record
|
||||
* and set them to accroding members. the original values
|
||||
* will all be overwritten. only minimal error checking is performed.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecord::RetrieveInfo(void* aInfo, PRUint32 aInfoLength)
|
||||
{
|
||||
// reset everything
|
||||
if(mInfo) {
|
||||
nsAllocator::Free(mInfo) ;
|
||||
mInfo = nsnull ;
|
||||
}
|
||||
|
||||
if(mKey) {
|
||||
nsAllocator::Free(mKey) ;
|
||||
mKey = nsnull ;
|
||||
}
|
||||
if(mMetaData) {
|
||||
nsAllocator::Free(mMetaData) ;
|
||||
mMetaData = nsnull ;
|
||||
}
|
||||
|
||||
char * cur_ptr = NS_STATIC_CAST(char*, aInfo) ;
|
||||
|
||||
char* file_url ;
|
||||
PRUint32 name_len ;
|
||||
|
||||
// set mInfoSize
|
||||
COPY_INT32(&mInfoSize, cur_ptr) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// check this at least
|
||||
if(mInfoSize != aInfoLength)
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
// set mRecordID
|
||||
COPY_INT32(&mRecordID, cur_ptr) ;
|
||||
cur_ptr += sizeof(PRInt32) ;
|
||||
|
||||
// set mKeyLength
|
||||
COPY_INT32(&mKeyLength, cur_ptr) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// set mKey
|
||||
mKey = NS_STATIC_CAST(char*, nsAllocator::Alloc(mKeyLength*sizeof(char))) ;
|
||||
if(!mKey)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
memcpy(mKey, cur_ptr, mKeyLength) ;
|
||||
cur_ptr += mKeyLength ;
|
||||
|
||||
PRInt32 id ;
|
||||
mDB->GetID(mKey, mKeyLength, &id) ;
|
||||
NS_ASSERTION(id==mRecordID, "\t ++++++ bad record, somethings wrong\n") ;
|
||||
|
||||
// set mMetaDataLength
|
||||
COPY_INT32(&mMetaDataLength, cur_ptr) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// set mMetaData
|
||||
mMetaData = NS_STATIC_CAST(char*, nsAllocator::Alloc(mMetaDataLength*sizeof(char))) ;
|
||||
if(!mMetaData)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
memcpy(mMetaData, cur_ptr, mMetaDataLength) ;
|
||||
cur_ptr += mMetaDataLength ;
|
||||
|
||||
// get mFile name length
|
||||
COPY_INT32(&name_len, cur_ptr) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// get mFile native name
|
||||
file_url = NS_STATIC_CAST(char*, nsAllocator::Alloc(name_len*sizeof(char))) ;
|
||||
if(!file_url)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
memcpy(file_url, cur_ptr, name_len) ;
|
||||
cur_ptr += name_len ;
|
||||
|
||||
PR_ASSERT(cur_ptr == NS_STATIC_CAST(char*, aInfo) + mInfoSize);
|
||||
|
||||
// create mFile if Init() isn't called
|
||||
if(!mFile) {
|
||||
NS_NewFileSpec(getter_AddRefs(mFile));
|
||||
if(!mFile)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
}
|
||||
|
||||
// setup mFile
|
||||
mFile->SetURLString(file_url) ;
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
71
mozilla/netwerk/cache/filecache/nsDiskCacheRecord.h
vendored
Normal file
71
mozilla/netwerk/cache/filecache/nsDiskCacheRecord.h
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 Mozilla Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
#ifndef _NET_CACHEDDISKDATA_H_
|
||||
#define _NET_CACHEDDISKDATA_H_
|
||||
|
||||
#include "nsINetDataCacheRecord.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDBAccessor.h"
|
||||
#include "prtypes.h"
|
||||
#include "nsILoadGroup.h"
|
||||
#include "nsIFileChannel.h"
|
||||
#include "nsNetDiskCache.h"
|
||||
|
||||
class nsDiskCacheRecord : public nsINetDataCacheRecord
|
||||
{
|
||||
public:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSINETDATACACHERECORD
|
||||
|
||||
protected:
|
||||
|
||||
nsDiskCacheRecord(nsIDBAccessor* db, nsNetDiskCache* aCache) ;
|
||||
virtual ~nsDiskCacheRecord() ;
|
||||
|
||||
NS_IMETHOD RetrieveInfo(void* aInfo, PRUint32 aInfoLength) ;
|
||||
NS_IMETHOD Init(const char* key, PRUint32 length, PRInt32 ID) ;
|
||||
|
||||
nsresult GenInfo(void) ;
|
||||
|
||||
private:
|
||||
|
||||
char* mKey ;
|
||||
PRUint32 mKeyLength ;
|
||||
PRInt32 mRecordID ;
|
||||
char* mMetaData ;
|
||||
PRUint32 mMetaDataLength ;
|
||||
nsCOMPtr<nsIFileSpec> mFile ;
|
||||
nsCOMPtr<nsIDBAccessor> mDB ;
|
||||
void* mInfo ;
|
||||
PRUint32 mInfoSize ;
|
||||
PRUint32 mNumChannels ;
|
||||
nsNetDiskCache* mDiskCache ;
|
||||
|
||||
friend class nsDiskCacheRecordChannel ;
|
||||
friend class nsDBEnumerator ;
|
||||
friend class nsNetDiskCache ;
|
||||
} ;
|
||||
|
||||
#endif // _NET_CACHEDDISKDATA_H_
|
||||
552
mozilla/netwerk/cache/filecache/nsDiskCacheRecordChannel.cpp
vendored
Normal file
552
mozilla/netwerk/cache/filecache/nsDiskCacheRecordChannel.cpp
vendored
Normal file
@@ -0,0 +1,552 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 Mozilla Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Most of the code are taken from nsFileChannel.
|
||||
*/
|
||||
|
||||
#include "nsDiskCacheRecordChannel.h"
|
||||
#include "nsIFileTransportService.h"
|
||||
//#include "nsIIOService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "netCore.h"
|
||||
#include "nsIMIMEService.h"
|
||||
#include "nsISupportsUtils.h"
|
||||
|
||||
//static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
|
||||
static NS_DEFINE_CID(kFileTransportServiceCID, NS_FILETRANSPORTSERVICE_CID);
|
||||
static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID);
|
||||
static NS_DEFINE_CID(kMIMEServiceCID, NS_MIMESERVICE_CID);
|
||||
|
||||
// This is copied from nsMemCacheChannel, We should consolidate these two.
|
||||
class WriteStreamWrapper : public nsIOutputStream
|
||||
{
|
||||
public:
|
||||
WriteStreamWrapper(nsDiskCacheRecordChannel* aChannel,
|
||||
nsIOutputStream *aBaseStream) ;
|
||||
|
||||
virtual ~WriteStreamWrapper() ;
|
||||
|
||||
static nsresult
|
||||
Create(nsDiskCacheRecordChannel* aChannel, nsIOutputStream *aBaseStream, nsIOutputStream* *aWrapper) ;
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIBASESTREAM
|
||||
NS_DECL_NSIOUTPUTSTREAM
|
||||
|
||||
private:
|
||||
nsDiskCacheRecordChannel* mChannel;
|
||||
nsCOMPtr<nsIOutputStream> mBaseStream;
|
||||
} ;
|
||||
|
||||
// implement nsISupports
|
||||
NS_IMPL_ISUPPORTS(WriteStreamWrapper, NS_GET_IID(nsIOutputStream))
|
||||
|
||||
WriteStreamWrapper::WriteStreamWrapper(nsDiskCacheRecordChannel* aChannel,
|
||||
nsIOutputStream *aBaseStream)
|
||||
: mChannel(aChannel), mBaseStream(aBaseStream)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
NS_ADDREF(mChannel);
|
||||
}
|
||||
|
||||
WriteStreamWrapper::~WriteStreamWrapper()
|
||||
{
|
||||
NS_RELEASE(mChannel);
|
||||
}
|
||||
|
||||
nsresult
|
||||
WriteStreamWrapper::Create(nsDiskCacheRecordChannel*aChannel, nsIOutputStream *aBaseStream, nsIOutputStream* * aWrapper)
|
||||
{
|
||||
WriteStreamWrapper *wrapper = new WriteStreamWrapper(aChannel, aBaseStream);
|
||||
if (!wrapper) return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(wrapper);
|
||||
*aWrapper = wrapper;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WriteStreamWrapper::Write(const char *aBuffer, PRUint32 aCount, PRUint32 *aNumWritten)
|
||||
{
|
||||
*aNumWritten = 0;
|
||||
nsresult rv = mBaseStream->Write(aBuffer, aCount, aNumWritten);
|
||||
mChannel->NotifyStorageInUse(*aNumWritten);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WriteStreamWrapper::Flush()
|
||||
{
|
||||
return mBaseStream->Flush();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WriteStreamWrapper::Close()
|
||||
{
|
||||
return mBaseStream->Close();
|
||||
}
|
||||
|
||||
nsDiskCacheRecordChannel::nsDiskCacheRecordChannel(nsDiskCacheRecord *aRecord,
|
||||
nsILoadGroup *aLoadGroup)
|
||||
: mRecord(aRecord) ,
|
||||
mLoadGroup(aLoadGroup)
|
||||
{
|
||||
NS_INIT_REFCNT() ;
|
||||
NS_ADDREF(mRecord);
|
||||
mRecord->mNumChannels++ ;
|
||||
}
|
||||
|
||||
nsDiskCacheRecordChannel::~nsDiskCacheRecordChannel()
|
||||
{
|
||||
mRecord->mNumChannels-- ;
|
||||
NS_RELEASE(mRecord);
|
||||
}
|
||||
|
||||
// I know that I gave conflicting advice on the issue of file
|
||||
// transport versus file protocol handler, but I thought that the
|
||||
// last word was that we would use the raw transport, when I wrote:
|
||||
//
|
||||
// > I just thought of an argument for the other side of the coin, i.e. the
|
||||
// > benefit of *not* reusing the file protocol handler: On the Mac, it's
|
||||
// > expensive to convert from a string URL to an nsFileSpec, because the Mac
|
||||
// > is brain-dead and scans every directory on the path to the file. It's
|
||||
// > cheaper to create a nsFileSpec for a cache file by combining a single,
|
||||
// > static nsFileSpec that corresponds to the cache directory with the
|
||||
// > relative path to the cache file (using nsFileSpec's operator +). This
|
||||
// > operation is optimized on the Mac to avoid the scanning operation.
|
||||
//
|
||||
// The Mac guys will eat us alive if we do path string to nsFileSpec
|
||||
// conversions for every cache file we open.
|
||||
|
||||
nsresult
|
||||
nsDiskCacheRecordChannel::Init(void)
|
||||
{
|
||||
nsresult rv = mRecord->mFile->GetFileSpec(&mSpec) ;
|
||||
|
||||
#ifdef XP_MAC
|
||||
|
||||
// Don't assume we actually created a good file spec
|
||||
FSSpec theSpec = mSpec.GetFSSpec();
|
||||
if (!theSpec.name[0]) {
|
||||
NS_ERROR("failed to create a file spec");
|
||||
|
||||
// Since we didn't actually create the file spec
|
||||
// we return an error
|
||||
return NS_ERROR_MALFORMED_URI;
|
||||
}
|
||||
#endif
|
||||
|
||||
return rv ;
|
||||
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDiskCacheRecordChannel::NotifyStorageInUse(PRInt32 aBytesUsed)
|
||||
{
|
||||
return mRecord->mDiskCache->m_StorageInUse += aBytesUsed ;
|
||||
}
|
||||
|
||||
// implement nsISupports
|
||||
NS_IMPL_ISUPPORTS4(nsDiskCacheRecordChannel,
|
||||
nsIChannel,
|
||||
nsIRequest,
|
||||
nsIStreamListener,
|
||||
nsIStreamObserver)
|
||||
|
||||
// implement nsIRequest
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::IsPending(PRBool *aIsPending)
|
||||
{
|
||||
*aIsPending = PR_FALSE ;
|
||||
if(!mFileTransport)
|
||||
return NS_OK ;
|
||||
|
||||
return mFileTransport->IsPending(aIsPending) ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::Cancel(void)
|
||||
{
|
||||
if(!mFileTransport)
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
return mFileTransport->Cancel() ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::Suspend(void)
|
||||
{
|
||||
if(!mFileTransport)
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
return mFileTransport->Suspend() ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::Resume(void)
|
||||
{
|
||||
if(!mFileTransport)
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
return mFileTransport->Resume() ;
|
||||
}
|
||||
|
||||
// implement nsIChannel
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::GetOriginalURI(nsIURI* *aURI)
|
||||
{
|
||||
// FUR - might need to implement this - not sure
|
||||
return NS_ERROR_NOT_IMPLEMENTED ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::GetURI(nsIURI * *aURI)
|
||||
{
|
||||
if(!mFileTransport)
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
return mFileTransport->GetURI(aURI) ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::OpenInputStream(PRUint32 aStartPosition,
|
||||
PRInt32 aReadCount,
|
||||
nsIInputStream* *aResult)
|
||||
{
|
||||
nsresult rv ;
|
||||
|
||||
if(mFileTransport)
|
||||
return NS_ERROR_IN_PROGRESS ;
|
||||
|
||||
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv) ;
|
||||
if(NS_FAILED(rv)) return rv ;
|
||||
|
||||
rv = fts->CreateTransport(mSpec, "load", 0, 0, getter_AddRefs(mFileTransport)) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
// we don't need to worry about notification callbacks
|
||||
|
||||
rv = mFileTransport->OpenInputStream(aStartPosition, aReadCount, aResult) ;
|
||||
if(NS_FAILED(rv))
|
||||
mFileTransport = nsnull ;
|
||||
|
||||
return rv ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::OpenOutputStream(PRUint32 startPosition,
|
||||
nsIOutputStream* *aResult)
|
||||
{
|
||||
nsresult rv ;
|
||||
NS_ENSURE_ARG(aResult) ;
|
||||
|
||||
if(mFileTransport)
|
||||
return NS_ERROR_IN_PROGRESS ;
|
||||
|
||||
nsCOMPtr<nsIOutputStream> outputStream ;
|
||||
|
||||
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv) ;
|
||||
if(NS_FAILED(rv)) return rv ;
|
||||
|
||||
rv = fts->CreateTransport(mSpec, "load", 0, 0, getter_AddRefs(mFileTransport)) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
// we don't need to worry about notification callbacks
|
||||
|
||||
rv = mFileTransport->OpenOutputStream(startPosition, getter_AddRefs(outputStream)) ;
|
||||
if(NS_FAILED(rv)) {
|
||||
mFileTransport = nsnull ;
|
||||
return rv ;
|
||||
}
|
||||
|
||||
return WriteStreamWrapper::Create(this, outputStream, aResult) ;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::AsyncOpen(nsIStreamObserver *observer,
|
||||
nsISupports *ctxt)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::AsyncRead(PRUint32 aStartPosition,
|
||||
PRInt32 aReadCount,
|
||||
nsISupports *aContext,
|
||||
nsIStreamListener *aListener)
|
||||
{
|
||||
nsresult rv ;
|
||||
|
||||
if(mFileTransport)
|
||||
return NS_ERROR_IN_PROGRESS ;
|
||||
|
||||
mRealListener = aListener;
|
||||
nsCOMPtr<nsIStreamListener> tempListener = this;
|
||||
|
||||
if (mLoadGroup) {
|
||||
nsCOMPtr<nsILoadGroupListenerFactory> factory;
|
||||
//
|
||||
// Create a load group "proxy" listener...
|
||||
//
|
||||
rv = mLoadGroup->GetGroupListenerFactory(getter_AddRefs(factory));
|
||||
if (factory) {
|
||||
nsIStreamListener *newListener;
|
||||
rv = factory->CreateLoadGroupListener(mRealListener, &newListener);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mRealListener = newListener;
|
||||
NS_RELEASE(newListener);
|
||||
}
|
||||
}
|
||||
|
||||
rv = mLoadGroup->AddChannel(this, nsnull);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
|
||||
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = fts->CreateTransport(mSpec, "load", 0, 0, getter_AddRefs(mFileTransport));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// no callbacks
|
||||
|
||||
rv = mFileTransport->AsyncRead(aStartPosition,
|
||||
aReadCount,
|
||||
aContext,
|
||||
tempListener);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
// release the transport so that we don't think we're in progress
|
||||
mFileTransport = nsnull;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::AsyncWrite(nsIInputStream *fromStream,
|
||||
PRUint32 startPosition,
|
||||
PRInt32 writeCount,
|
||||
nsISupports *ctxt,
|
||||
nsIStreamObserver *observer)
|
||||
|
||||
{
|
||||
/*
|
||||
if(!mFileTransport)
|
||||
return NS_ERROR_FAILURE ;
|
||||
|
||||
return mFileTransport->AsyncWrite(fromStream,
|
||||
startPosition,
|
||||
writeCount,
|
||||
ctxt,
|
||||
observer) ;
|
||||
*/
|
||||
|
||||
// I can't do this since the write is not monitored, and I won't be
|
||||
// able to updata the storage.
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::GetLoadAttributes(nsLoadFlags *aLoadAttributes)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::SetLoadAttributes(nsLoadFlags aLoadAttributes)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
#define DUMMY_TYPE "text/html"
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::GetContentType(char * *aContentType)
|
||||
{
|
||||
nsresult rv ;
|
||||
|
||||
if (mSpec.IsDirectory()) {
|
||||
*aContentType = nsCRT::strdup("application/http-index-format");
|
||||
return *aContentType ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
else {
|
||||
// I wish I can make this simplier
|
||||
|
||||
char* urlStr ;
|
||||
mRecord->mFile->GetURLString(&urlStr) ;
|
||||
|
||||
// file: URLs (currently) have no additional structure beyond that provided by standard
|
||||
// URLs, so there is no "outer" given to CreateInstance
|
||||
|
||||
nsCOMPtr<nsIURI> url;
|
||||
rv = nsComponentManager::CreateInstance(kStandardURLCID, nsnull,
|
||||
NS_GET_IID(nsIURI),
|
||||
//(void**)&url);
|
||||
getter_AddRefs(url)) ;
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = url->SetSpec((char*)urlStr);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
NS_WITH_SERVICE(nsIMIMEService, MIMEService, kMIMEServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = MIMEService->GetTypeFromURI(url, aContentType);
|
||||
if (NS_SUCCEEDED(rv)) return rv;
|
||||
}
|
||||
|
||||
// if all else fails treat it as text/html?
|
||||
*aContentType = nsCRT::strdup(DUMMY_TYPE);
|
||||
if (!*aContentType) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
} else {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::GetContentLength(PRInt32 *aContentLength)
|
||||
{
|
||||
nsresult rv;
|
||||
PRUint32 length;
|
||||
|
||||
rv = mRecord->mFile->GetFileSize(&length);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
*aContentLength = (PRInt32)length;
|
||||
} else {
|
||||
*aContentLength = -1;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::GetOwner(nsISupports* *aOwner)
|
||||
{
|
||||
*aOwner = mOwner.get() ;
|
||||
NS_IF_ADDREF(*aOwner) ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::SetOwner(nsISupports* aOwner)
|
||||
{
|
||||
mOwner = aOwner ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aNotificationCallbacks)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsIStreamListener methods:
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::OnStartRequest(nsIChannel* transportChannel, nsISupports* context)
|
||||
{
|
||||
NS_ASSERTION(mRealListener, "No listener...");
|
||||
return mRealListener->OnStartRequest(this, context);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::OnStopRequest(nsIChannel* transportChannel, nsISupports* context,
|
||||
nsresult aStatus, const PRUnichar* aMsg)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = mRealListener->OnStopRequest(this, context, aStatus, aMsg);
|
||||
|
||||
if (mLoadGroup) {
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mLoadGroup->RemoveChannel(this, context, aStatus, aMsg);
|
||||
}
|
||||
}
|
||||
|
||||
// Release the reference to the consumer stream listener...
|
||||
mRealListener = null_nsCOMPtr();
|
||||
mFileTransport = null_nsCOMPtr();
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDiskCacheRecordChannel::OnDataAvailable(nsIChannel* transportChannel, nsISupports* context,
|
||||
nsIInputStream *aIStream, PRUint32 aSourceOffset,
|
||||
PRUint32 aLength)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = mRealListener->OnDataAvailable(this, context, aIStream,
|
||||
aSourceOffset, aLength);
|
||||
|
||||
//
|
||||
// If the connection is being aborted cancel the transport. This will
|
||||
// insure that the transport will go away even if it is blocked waiting
|
||||
// for the consumer to empty the pipe...
|
||||
//
|
||||
if (NS_FAILED(rv)) {
|
||||
mFileTransport->Cancel();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
76
mozilla/netwerk/cache/filecache/nsDiskCacheRecordChannel.h
vendored
Normal file
76
mozilla/netwerk/cache/filecache/nsDiskCacheRecordChannel.h
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 Mozilla Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
#ifndef _ns_DiskCacheRecordChannel_h_
|
||||
#define _ns_DiskCacheRecordChannel_h_
|
||||
|
||||
#include "nsIChannel.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDiskCacheRecord.h"
|
||||
#include "nsIStreamListener.h"
|
||||
|
||||
/*
|
||||
* This class is plagiarized from nsMemCacheChannel
|
||||
*/
|
||||
|
||||
class nsDiskCacheRecordChannel : public nsIChannel,
|
||||
public nsIStreamListener
|
||||
{
|
||||
public:
|
||||
|
||||
nsDiskCacheRecordChannel(nsDiskCacheRecord *aRecord, nsILoadGroup *aLoadGroup);
|
||||
virtual ~nsDiskCacheRecordChannel() ;
|
||||
|
||||
// Declare nsISupports methods
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// Declare nsIRequest methods
|
||||
NS_DECL_NSIREQUEST
|
||||
|
||||
// Declare nsIChannel methods
|
||||
NS_DECL_NSICHANNEL
|
||||
|
||||
// Declare nsIStreamObserver methods
|
||||
NS_DECL_NSISTREAMOBSERVER
|
||||
|
||||
// Declare nsIStreamListener methods
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
|
||||
nsresult Init(void) ;
|
||||
|
||||
private:
|
||||
|
||||
nsresult NotifyStorageInUse(PRInt32 aBytesUsed) ;
|
||||
|
||||
nsDiskCacheRecord* mRecord ;
|
||||
nsCOMPtr<nsILoadGroup> mLoadGroup ;
|
||||
nsCOMPtr<nsISupports> mOwner ;
|
||||
nsCOMPtr<nsIChannel> mFileTransport ;
|
||||
nsFileSpec mSpec ;
|
||||
nsCOMPtr<nsIStreamListener> mRealListener;
|
||||
|
||||
friend class WriteStreamWrapper ;
|
||||
} ;
|
||||
|
||||
#endif // _ns_DiskCacheRecordChannel_h_
|
||||
|
||||
66
mozilla/netwerk/cache/filecache/nsIDBAccessor.h
vendored
Normal file
66
mozilla/netwerk/cache/filecache/nsIDBAccessor.h
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 Mozilla Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
#ifndef _NS_IDBACCESSOR_H_
|
||||
#define _NS_IDBACCESSOR_H_
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsIFileSpec.h"
|
||||
|
||||
// nsIDBAccessorIID {6AADD4D0-7785-11d3-87FE-000629D01344}
|
||||
#define NS_IDBACCESSOR_IID \
|
||||
{ 0x6aadd4d0, 0x7785, 0x11d3, \
|
||||
{0x87, 0xfe, 0x0, 0x6, 0x29, 0xd0, 0x13, 0x44}}
|
||||
|
||||
// nsDBAccessorCID {6AADD4D1-7785-11d3-87FE-000629D01344}
|
||||
#define NS_DBACCESSOR_CID \
|
||||
{ 0x6aadd4d1, 0x7785, 0x11d3, \
|
||||
{ 0x87, 0xfe, 0x0, 0x6, 0x29, 0xd0, 0x13, 0x44 }}
|
||||
|
||||
class nsIDBAccessor : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IDBACCESSOR_IID)
|
||||
|
||||
NS_IMETHOD Init(nsIFileSpec* DBFile) = 0 ;
|
||||
NS_IMETHOD Shutdown(void) = 0 ;
|
||||
|
||||
NS_IMETHOD Put(PRInt32 aID, void* anEntry, PRUint32 aLength) = 0 ;
|
||||
|
||||
NS_IMETHOD Get(PRInt32 aID, void** anEntry, PRUint32 *aLength) = 0 ;
|
||||
|
||||
NS_IMETHOD Del(PRInt32 aID, void* anEntry, PRUint32 aLength) = 0 ;
|
||||
|
||||
NS_IMETHOD GetID(const char* key, PRUint32 length, PRInt32* aID) = 0 ;
|
||||
|
||||
NS_IMETHOD EnumEntry(void* *anEntry, PRUint32* aLength, PRBool bReset) = 0 ;
|
||||
|
||||
NS_IMETHOD GetDBFilesize(PRUint32* aSize) = 0 ;
|
||||
|
||||
NS_IMETHOD GetSpecialEntry(void** anEntry, PRUint32 *aLength) = 0 ;
|
||||
NS_IMETHOD SetSpecialEntry(void* anEntry, PRUint32 aLength) = 0 ;
|
||||
|
||||
} ;
|
||||
|
||||
#endif // _NS_IDBACCESSOR_H_
|
||||
|
||||
704
mozilla/netwerk/cache/filecache/nsNetDiskCache.cpp
vendored
Normal file
704
mozilla/netwerk/cache/filecache/nsNetDiskCache.cpp
vendored
Normal file
@@ -0,0 +1,704 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 Mozilla Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
#include "nsNetDiskCache.h"
|
||||
#include "nscore.h"
|
||||
|
||||
#include "plstr.h"
|
||||
#include "prprf.h"
|
||||
#include "prtypes.h"
|
||||
#include "prio.h"
|
||||
#include "prsystem.h" // Directory Seperator
|
||||
#include "plhash.h"
|
||||
#include "prclist.h"
|
||||
#include "prmem.h"
|
||||
#include "prlog.h"
|
||||
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
|
||||
#include "nsIPref.h"
|
||||
#include "mcom_db.h"
|
||||
#include "nsDBEnumerator.h"
|
||||
|
||||
#include "nsDiskCacheRecord.h"
|
||||
#include "netCore.h"
|
||||
|
||||
#if !defined(IS_LITTLE_ENDIAN) && !defined(IS_BIG_ENDIAN)
|
||||
ERROR! Must have a byte order
|
||||
#endif
|
||||
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define COPY_INT32(_a,_b) memcpy(_a, _b, sizeof(int32))
|
||||
#else
|
||||
#define COPY_INT32(_a,_b) /* swap */ \
|
||||
do { \
|
||||
((char *)(_a))[0] = ((char *)(_b))[3]; \
|
||||
((char *)(_a))[1] = ((char *)(_b))[2]; \
|
||||
((char *)(_a))[2] = ((char *)(_b))[1]; \
|
||||
((char *)(_a))[3] = ((char *)(_b))[0]; \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID) ;
|
||||
static NS_DEFINE_CID(kDBAccessorCID, NS_DBACCESSOR_CID) ;
|
||||
|
||||
static const PRUint32 DISK_CACHE_SIZE_DEFAULT = 5*1024*1024 ; // 5MB
|
||||
static const char * const DISK_CACHE_PREF = "browser.cache.disk_cache_size";
|
||||
static const char * const CACHE_DIR_PREF = "browser.cache.directory";
|
||||
|
||||
class nsDiskCacheRecord ;
|
||||
|
||||
nsNetDiskCache::nsNetDiskCache() :
|
||||
m_Enabled(PR_TRUE) ,
|
||||
m_NumEntries(0) ,
|
||||
m_pNextCache(0) ,
|
||||
m_pDiskCacheFolder(0) ,
|
||||
m_StorageInUse(0) ,
|
||||
m_DB(0) ,
|
||||
m_DBCorrupted(PR_FALSE)
|
||||
{
|
||||
// set it to INF for now
|
||||
m_MaxEntries = (PRUint32)-1 ;
|
||||
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
}
|
||||
|
||||
nsNetDiskCache::~nsNetDiskCache()
|
||||
{
|
||||
SetSpecialEntry() ;
|
||||
|
||||
NS_IF_RELEASE(m_DB) ;
|
||||
|
||||
|
||||
// FUR
|
||||
// I think that, eventually, we also want a distinguished key in the DB which
|
||||
// means "clean cache shutdown". You clear this flag when the db is first
|
||||
// opened and set it just before the db is closed. If the db wasn't shutdown
|
||||
// cleanly in a prior session, i.e. because the app crashed, on startup you
|
||||
// scan all the individual files in directories and look for "orphans",
|
||||
// i.e. cache files which don't have corresponding entries in the db. That's
|
||||
// also when storage-in-use and number of entries would be recomputed.
|
||||
//
|
||||
// We don't necessarily need all this functionality immediately, though.
|
||||
|
||||
|
||||
if(m_DBCorrupted) {
|
||||
|
||||
nsFileSpec cacheFolder ;
|
||||
m_pDiskCacheFolder->GetFileSpec(&cacheFolder) ;
|
||||
|
||||
char nameInt[6] ;
|
||||
|
||||
for(nsDirectoryIterator di(cacheFolder, PR_FALSE); di.Exists(); di++) {
|
||||
char* filename = di.Spec().GetLeafName() ;
|
||||
char* pname = nameInt ;
|
||||
pname = PL_strncpyz(pname, filename, 6) ;
|
||||
|
||||
if(PL_strcmp(pname, "trash") == 0)
|
||||
RemoveFolder(di.Spec()) ;
|
||||
|
||||
nsCRT::free(filename) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::Init(void)
|
||||
{
|
||||
nsresult rv ;
|
||||
|
||||
// don't initialize if no cache folder is set.
|
||||
if(!m_pDiskCacheFolder) return NS_OK ;
|
||||
|
||||
if(!m_DB) {
|
||||
m_DB = new nsDBAccessor() ;
|
||||
if(!m_DB)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
else
|
||||
NS_ADDREF(m_DB) ;
|
||||
}
|
||||
|
||||
// create cache sub directories
|
||||
nsCOMPtr<nsIFileSpec> cacheSubDir;
|
||||
rv = NS_NewFileSpec(getter_AddRefs(cacheSubDir));
|
||||
|
||||
for (int i=0; i < 32; i++) {
|
||||
rv = cacheSubDir->FromFileSpec(m_pDiskCacheFolder) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
char dirName[3];
|
||||
PR_snprintf (dirName, 3, "%0.2x", i);
|
||||
cacheSubDir->AppendRelativeUnixPath (dirName) ;
|
||||
CreateDir(cacheSubDir);
|
||||
}
|
||||
|
||||
return InitDB() ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::InitDB(void)
|
||||
{
|
||||
nsresult rv ;
|
||||
|
||||
if(!m_DBFile) {
|
||||
NS_NewFileSpec(getter_AddRefs(m_DBFile)) ;
|
||||
if(!m_DBFile)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
}
|
||||
|
||||
rv = m_DBFile->FromFileSpec(m_pDiskCacheFolder) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
m_DBFile->AppendRelativeUnixPath("cache.db") ;
|
||||
|
||||
rv = m_DB->Init(m_DBFile) ;
|
||||
|
||||
if(rv == NS_ERROR_FAILURE) {
|
||||
// try recovery if error
|
||||
DBRecovery() ;
|
||||
}
|
||||
|
||||
rv = GetSpecialEntry() ;
|
||||
if(rv == NS_ERROR_FAILURE) {
|
||||
// try recovery if error
|
||||
DBRecovery() ;
|
||||
}
|
||||
|
||||
return rv ;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// nsISupports methods
|
||||
|
||||
NS_IMPL_ISUPPORTS3(nsNetDiskCache,
|
||||
nsINetDataDiskCache,
|
||||
nsINetDataCache,
|
||||
nsISupports)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// nsINetDataCache Method
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetDescription(PRUnichar* *aDescription)
|
||||
{
|
||||
nsAutoString description("Disk Cache") ;
|
||||
*aDescription = description.ToNewUnicode() ;
|
||||
if(!*aDescription)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
/* don't alloc mem for nsICachedNetData.
|
||||
* RecordID is generated using the same scheme in nsCacheDiskData,
|
||||
* see GetCachedNetData() for detail.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::Contains(const char* key, PRUint32 length, PRBool *_retval)
|
||||
{
|
||||
*_retval = PR_FALSE ;
|
||||
|
||||
NS_ASSERTION(m_DB, "no db.") ;
|
||||
|
||||
PRInt32 id = 0 ;
|
||||
nsresult rv = m_DB->GetID(key, length, &id) ;
|
||||
|
||||
if(NS_FAILED(rv)) {
|
||||
// try recovery if error
|
||||
DBRecovery() ;
|
||||
return rv ;
|
||||
}
|
||||
|
||||
void* info = 0 ;
|
||||
PRUint32 info_size = 0 ;
|
||||
|
||||
rv = m_DB->Get(id, &info, &info_size) ;
|
||||
if(NS_SUCCEEDED(rv) && info)
|
||||
*_retval = PR_TRUE ;
|
||||
|
||||
if(NS_FAILED(rv)) {
|
||||
// try recovery if error
|
||||
DBRecovery() ;
|
||||
}
|
||||
|
||||
return rv ;
|
||||
}
|
||||
|
||||
/* regardless if it's cached or not, a copy of nsNetDiskCache would
|
||||
* always be returned. so release it appropriately.
|
||||
* if mem alloced, updata m_NumEntries also.
|
||||
* for now, the new nsCachedNetData is not written into db yet since
|
||||
* we have nothing to write.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetCachedNetData(const char* key, PRUint32 length, nsINetDataCacheRecord **_retval)
|
||||
{
|
||||
NS_ASSERTION(m_DB, "no db.") ;
|
||||
|
||||
nsresult rv = 0 ;
|
||||
if (!_retval)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*_retval = nsnull ;
|
||||
|
||||
PRInt32 id = 0 ;
|
||||
rv = m_DB->GetID(key, length, &id) ;
|
||||
if(NS_FAILED(rv)) {
|
||||
// try recovery if error
|
||||
DBRecovery() ;
|
||||
return rv ;
|
||||
}
|
||||
|
||||
// construct an empty record
|
||||
nsDiskCacheRecord* newRecord = new nsDiskCacheRecord(m_DB, this) ;
|
||||
if(!newRecord)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
rv = newRecord->Init(key, length, id) ;
|
||||
if(NS_FAILED(rv)) {
|
||||
delete newRecord ;
|
||||
return rv ;
|
||||
}
|
||||
|
||||
NS_ADDREF(newRecord) ; // addref for _retval
|
||||
*_retval = (nsINetDataCacheRecord*) newRecord ;
|
||||
|
||||
void* info = 0 ;
|
||||
PRUint32 info_size = 0 ;
|
||||
|
||||
rv = m_DB->Get(id, &info, &info_size) ;
|
||||
if(NS_SUCCEEDED(rv) && info) {
|
||||
|
||||
// this is a previously cached record
|
||||
nsresult r1 ;
|
||||
r1 = newRecord->RetrieveInfo(info, info_size) ;
|
||||
|
||||
if(NS_SUCCEEDED(rv))
|
||||
return NS_OK ;
|
||||
else {
|
||||
// probably a bad one
|
||||
NS_RELEASE(newRecord) ;
|
||||
*_retval = nsnull ;
|
||||
return r1;
|
||||
}
|
||||
|
||||
} else if (NS_SUCCEEDED(rv) && !info) {
|
||||
// this is a new record.
|
||||
m_NumEntries ++ ;
|
||||
return NS_OK ;
|
||||
} else {
|
||||
// database error.
|
||||
DBRecovery() ;
|
||||
return rv ;
|
||||
}
|
||||
}
|
||||
|
||||
/* get an nsICachedNetData, mem needs to be de-alloced if not found. */
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetCachedNetDataByID(PRInt32 RecordID, nsINetDataCacheRecord **_retval)
|
||||
{
|
||||
NS_ASSERTION(m_DB, "no db.") ;
|
||||
|
||||
if (!_retval)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*_retval = nsnull ;
|
||||
|
||||
nsresult rv ;
|
||||
|
||||
void* info = 0 ;
|
||||
PRUint32 info_size = 0 ;
|
||||
|
||||
rv = m_DB->Get(RecordID, &info, &info_size) ;
|
||||
if(NS_SUCCEEDED(rv) && info) {
|
||||
|
||||
// construct an empty record if only found in db
|
||||
nsDiskCacheRecord* newRecord = new nsDiskCacheRecord(m_DB, this) ;
|
||||
if(!newRecord)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
NS_ADDREF(newRecord) ; // addref for _retval
|
||||
rv = newRecord->RetrieveInfo(info, info_size) ;
|
||||
|
||||
if(NS_SUCCEEDED(rv)) {
|
||||
*_retval = (nsINetDataCacheRecord*) newRecord ;
|
||||
return NS_OK ;
|
||||
}
|
||||
else {
|
||||
// bad record, I guess
|
||||
NS_RELEASE(newRecord) ; // release if bad things happen
|
||||
return rv ;
|
||||
}
|
||||
} else {
|
||||
NS_ERROR("Error: RecordID not in DB\n") ;
|
||||
DBRecovery() ;
|
||||
return rv ;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetEnabled(PRBool *aEnabled)
|
||||
{
|
||||
*aEnabled = m_Enabled ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::SetEnabled(PRBool aEnabled)
|
||||
{
|
||||
m_Enabled = aEnabled ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetFlags(PRUint32 *aFlags)
|
||||
{
|
||||
*aFlags = FILE_PER_URL_CACHE;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetNumEntries(PRUint32 *aNumEntries)
|
||||
{
|
||||
*aNumEntries = m_NumEntries ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetMaxEntries(PRUint32 *aMaxEntries)
|
||||
{
|
||||
*aMaxEntries = m_MaxEntries ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::NewCacheEntryIterator(nsISimpleEnumerator **_retval)
|
||||
{
|
||||
NS_ASSERTION(m_DB, "no db.") ;
|
||||
|
||||
if(!_retval)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*_retval = nsnull ;
|
||||
|
||||
nsISimpleEnumerator* enumerator = new nsDBEnumerator(m_DB, this) ;
|
||||
if(enumerator) {
|
||||
NS_ADDREF(enumerator) ;
|
||||
*_retval = enumerator ;
|
||||
return NS_OK ;
|
||||
}
|
||||
else
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetNextCache(nsINetDataCache * *aNextCache)
|
||||
{
|
||||
if(!aNextCache)
|
||||
return NS_ERROR_NULL_POINTER ;
|
||||
|
||||
*aNextCache = m_pNextCache ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::SetNextCache(nsINetDataCache *aNextCache)
|
||||
{
|
||||
m_pNextCache = aNextCache ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
// db size can always be measured at the last minute. Since it's hard
|
||||
// to know before hand.
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetStorageInUse(PRUint32 *aStorageInUse)
|
||||
{
|
||||
NS_ASSERTION(m_DB, "no db.") ;
|
||||
|
||||
PRUint32 total_size = m_StorageInUse ;
|
||||
|
||||
/*
|
||||
PRUint32 len = 0 ;
|
||||
// add the size of the db.
|
||||
m_DB->GetDBFilesize(&len) ;
|
||||
total_size += len ;
|
||||
*/
|
||||
|
||||
// we need size in kB
|
||||
total_size = total_size >> 10 ;
|
||||
|
||||
*aStorageInUse = total_size ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
/*
|
||||
* The whole cache dirs can be whiped clean since all the cache
|
||||
* files are resides in seperate hashed dirs. It's safe to do so.
|
||||
*/
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::RemoveAll(void)
|
||||
{
|
||||
NS_ASSERTION(m_DB, "no db.") ;
|
||||
NS_ASSERTION(m_pDiskCacheFolder, "no cache folder.") ;
|
||||
|
||||
// remove all the sub folders
|
||||
nsFileSpec cacheSubDir;
|
||||
|
||||
for (int i=0; i < 32; i++) {
|
||||
m_pDiskCacheFolder->GetFileSpec(&cacheSubDir) ;
|
||||
|
||||
char dirName[3];
|
||||
PR_snprintf (dirName, 3, "%0.2x", i);
|
||||
cacheSubDir += dirName ;
|
||||
RemoveFolder(cacheSubDir) ;
|
||||
}
|
||||
|
||||
// don't forget the db file itself
|
||||
m_DB->Shutdown() ;
|
||||
nsFileSpec dbfile ;
|
||||
m_DBFile->GetFileSpec(&dbfile) ;
|
||||
dbfile.Delete(PR_TRUE) ;
|
||||
|
||||
// reinitilize
|
||||
return Init() ;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// nsINetDataDiskCache methods
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetDiskCacheFolder(nsIFileSpec * *aDiskCacheFolder)
|
||||
{
|
||||
*aDiskCacheFolder = nsnull ;
|
||||
NS_ASSERTION(m_pDiskCacheFolder, "no cache folder.") ;
|
||||
|
||||
*aDiskCacheFolder = m_pDiskCacheFolder ;
|
||||
NS_ADDREF(*aDiskCacheFolder) ;
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::SetDiskCacheFolder(nsIFileSpec * aDiskCacheFolder)
|
||||
{
|
||||
if(!m_pDiskCacheFolder) {
|
||||
NS_NewFileSpec(getter_AddRefs(m_pDiskCacheFolder));
|
||||
if(!m_pDiskCacheFolder)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
m_pDiskCacheFolder = aDiskCacheFolder ;
|
||||
return Init() ;
|
||||
}
|
||||
else {
|
||||
char *newfolder, *oldfolder ;
|
||||
m_pDiskCacheFolder->GetNativePath(&oldfolder) ;
|
||||
aDiskCacheFolder->GetNativePath(&newfolder) ;
|
||||
|
||||
if(PL_strcmp(newfolder, oldfolder) != 0) {
|
||||
m_pDiskCacheFolder = aDiskCacheFolder ;
|
||||
|
||||
// do we need to blow away old cache before building a new one?
|
||||
// return RemoveAll() ;
|
||||
|
||||
m_DB->Shutdown() ;
|
||||
return Init() ;
|
||||
|
||||
} else
|
||||
return NS_OK ;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// nsNetDiskCache methods
|
||||
|
||||
// create a directory (recursively)
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::CreateDir(nsIFileSpec* dir_spec)
|
||||
{
|
||||
PRBool does_exist ;
|
||||
nsCOMPtr<nsIFileSpec> p_spec ;
|
||||
|
||||
dir_spec->Exists(&does_exist) ;
|
||||
if(does_exist)
|
||||
return NS_OK ;
|
||||
|
||||
nsresult rv = dir_spec->GetParent(getter_AddRefs(p_spec)) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
p_spec->Exists(&does_exist) ;
|
||||
if(!does_exist) {
|
||||
CreateDir(p_spec) ;
|
||||
rv = dir_spec->CreateDir() ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
}
|
||||
else {
|
||||
rv = dir_spec->CreateDir() ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
}
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
// We can't afford to make a *separate* pass over the whole db on every
|
||||
// startup, just to figure out m_NumEntries and m_StorageInUse. (This is a
|
||||
// several second operation on a large db). We'll likely need to store
|
||||
// distinguished keys in the db that contain these values and update them
|
||||
// incrementally, except when failure to shut down the db cleanly is detected.
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::GetSpecialEntry(void)
|
||||
{
|
||||
void* pInfo ;
|
||||
PRUint32 InfoSize ;
|
||||
|
||||
nsresult rv = m_DB->GetSpecialEntry(&pInfo, &InfoSize) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
if(!pInfo && InfoSize == 0) {
|
||||
// must be a new DB
|
||||
m_NumEntries = 0 ;
|
||||
m_StorageInUse = 0 ;
|
||||
}
|
||||
else {
|
||||
char * cur_ptr = NS_STATIC_CAST(char*, pInfo) ;
|
||||
|
||||
// get m_NumEntries
|
||||
COPY_INT32(&m_NumEntries, cur_ptr) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
// get m_StorageInUse
|
||||
COPY_INT32(&m_StorageInUse, cur_ptr) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
PR_ASSERT(cur_ptr == NS_STATIC_CAST(char*, pInfo) + InfoSize);
|
||||
}
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::SetSpecialEntry(void)
|
||||
{
|
||||
PRUint32 InfoSize ;
|
||||
|
||||
InfoSize = sizeof m_NumEntries ;
|
||||
InfoSize += sizeof m_StorageInUse ;
|
||||
|
||||
void* pInfo = nsAllocator::Alloc(InfoSize*sizeof(char)) ;
|
||||
if(!pInfo)
|
||||
return NS_ERROR_OUT_OF_MEMORY ;
|
||||
|
||||
char* cur_ptr = NS_STATIC_CAST(char*, pInfo) ;
|
||||
|
||||
COPY_INT32(cur_ptr, &m_NumEntries) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
COPY_INT32(cur_ptr, &m_StorageInUse) ;
|
||||
cur_ptr += sizeof(PRUint32) ;
|
||||
|
||||
PR_ASSERT(cur_ptr == NS_STATIC_CAST(char*, pInfo) + InfoSize);
|
||||
|
||||
return m_DB->SetSpecialEntry(pInfo, InfoSize) ;
|
||||
}
|
||||
|
||||
// this routine will be called everytime we have a db corruption.
|
||||
// m_DB will be re-initialized, m_StorageInUse and m_NumEntries will
|
||||
// be reset.
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::DBRecovery(void)
|
||||
{
|
||||
// rename all the sub cache dirs and remove them later during dtor.
|
||||
nsresult rv = RenameCacheSubDirs() ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
// remove corrupted db file, don't care if db->shutdown fails or not.
|
||||
m_DB->Shutdown() ;
|
||||
|
||||
nsFileSpec dbfile ;
|
||||
m_DBFile->GetFileSpec(&dbfile) ;
|
||||
dbfile.Delete(PR_TRUE) ;
|
||||
|
||||
// make sure it's not there any more
|
||||
PRBool exists = dbfile.Exists() ;
|
||||
if(exists) {
|
||||
NS_ERROR("can't remove old db.") ;
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
|
||||
// reinitilize DB
|
||||
return InitDB() ;
|
||||
}
|
||||
|
||||
// this routine will add string "trash" to current CacheSubDir names.
|
||||
// e.g. 00->trash00, 1f->trash1f. and update the m_DBCorrupted.
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::RenameCacheSubDirs(void)
|
||||
{
|
||||
nsCOMPtr<nsIFileSpec> cacheSubDir;
|
||||
nsresult rv = NS_NewFileSpec(getter_AddRefs(cacheSubDir)) ;
|
||||
|
||||
for (int i=0; i < 32; i++) {
|
||||
rv = cacheSubDir->FromFileSpec(m_pDiskCacheFolder) ;
|
||||
if(NS_FAILED(rv))
|
||||
return rv ;
|
||||
|
||||
char oldName[3], newName[8];
|
||||
PR_snprintf(oldName, 3, "%0.2x", i) ;
|
||||
cacheSubDir->AppendRelativeUnixPath(oldName) ;
|
||||
|
||||
// re-name the directory
|
||||
PR_snprintf(newName, 8, "trash%0.2x", i) ;
|
||||
rv = cacheSubDir->Rename(newName) ;
|
||||
if(NS_FAILED(rv))
|
||||
// TODO, error checking
|
||||
return NS_ERROR_FAILURE ;
|
||||
}
|
||||
|
||||
// update m_DBCorrupted
|
||||
m_DBCorrupted = PR_TRUE ;
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
|
||||
// this routine is used by dtor and RemoveAll() to clean up dirs.
|
||||
NS_IMETHODIMP
|
||||
nsNetDiskCache::RemoveFolder(nsFileSpec aFolder)
|
||||
{
|
||||
for(nsDirectoryIterator di(aFolder, PR_FALSE); di.Exists(); di++) {
|
||||
di.Spec().Delete(PR_TRUE) ;
|
||||
}
|
||||
|
||||
aFolder.Delete(PR_FALSE) ; // recursive delete
|
||||
|
||||
return NS_OK ;
|
||||
}
|
||||
91
mozilla/netwerk/cache/filecache/nsNetDiskCache.h
vendored
Normal file
91
mozilla/netwerk/cache/filecache/nsNetDiskCache.h
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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 Mozilla Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of filecache implementation.
|
||||
*
|
||||
* nsNetDiskCache is the main disk cache module that will create
|
||||
* the cache database, and then store and retrieve nsDiskCacheRecord
|
||||
* objects from it. It also contains some basic error recovery procedure.
|
||||
*/
|
||||
|
||||
#ifndef __gen_nsNetDiskCache_h__
|
||||
#define __gen_nsNetDiskCache_h__
|
||||
|
||||
#include "nsINetDataDiskCache.h"
|
||||
#include "nsNetDiskCacheCID.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIPref.h"
|
||||
#include "nsDBAccessor.h"
|
||||
|
||||
class nsIURI; /* forward decl */
|
||||
class nsICachedNetData; /* forward decl */
|
||||
class nsISimpleEnumerator; /* forward decl */
|
||||
class nsIFileSpec; /* forward decl */
|
||||
|
||||
/* starting interface: nsNetDiskCache */
|
||||
|
||||
class nsNetDiskCache : public nsINetDataDiskCache {
|
||||
public:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSINETDATACACHE
|
||||
NS_DECL_NSINETDATADISKCACHE
|
||||
|
||||
NS_IMETHOD Init(void) ;
|
||||
|
||||
nsNetDiskCache() ;
|
||||
virtual ~nsNetDiskCache() ;
|
||||
|
||||
protected:
|
||||
|
||||
NS_IMETHOD InitDB(void) ;
|
||||
NS_IMETHOD CreateDir(nsIFileSpec* dir_spec) ;
|
||||
NS_IMETHOD GetSpecialEntry(void) ;
|
||||
NS_IMETHOD SetSpecialEntry(void) ;
|
||||
|
||||
NS_IMETHOD RenameCacheSubDirs(void) ;
|
||||
NS_IMETHOD DBRecovery(void) ;
|
||||
NS_IMETHOD RemoveFolder(nsFileSpec aFolder) ;
|
||||
|
||||
private:
|
||||
|
||||
PRBool m_Enabled ;
|
||||
PRUint32 m_NumEntries ;
|
||||
nsCOMPtr<nsINetDataCache> m_pNextCache ;
|
||||
nsCOMPtr<nsIFileSpec> m_pDiskCacheFolder ;
|
||||
nsCOMPtr<nsIFileSpec> m_DBFile ;
|
||||
|
||||
PRUint32 m_MaxEntries ;
|
||||
PRUint32 m_StorageInUse ;
|
||||
nsIDBAccessor* m_DB ;
|
||||
|
||||
// this is used to indicate a db corruption
|
||||
PRBool m_DBCorrupted ;
|
||||
|
||||
friend class nsDiskCacheRecord ;
|
||||
friend class nsDiskCacheRecordChannel ;
|
||||
friend class nsDBEnumerator ;
|
||||
} ;
|
||||
|
||||
#endif /* __gen_nsNetDiskCache_h__ */
|
||||
32
mozilla/netwerk/cache/filecache/nsNetDiskCacheCID.h
vendored
Normal file
32
mozilla/netwerk/cache/filecache/nsNetDiskCacheCID.h
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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 Mozilla Communicator.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Intel Corp.
|
||||
* Portions created by Intel Corp. are
|
||||
* Copyright (C) 1999, 1999 Intel Corp. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
|
||||
* Carl Wong <carl.wong@intel.com>
|
||||
*/
|
||||
|
||||
#ifndef _nsNetDiskCacheCID_h_
|
||||
#define _nsNetDiskCacheCID_h_
|
||||
|
||||
#define NS_NETDISKCACHE_CID_STR "ECFEEA00-7201-11d3-87FE-000629D01344"
|
||||
|
||||
#define NS_NETDISKCACHE_CID \
|
||||
{ 0xecfeea00, 0x7201, 0x11d3, \
|
||||
{ 0x87, 0xfe, 0x0, 0x6, 0x29, 0xd0, 0x13, 0x44 }}
|
||||
|
||||
#endif /* _nsNetDiskCacheCID_h_ */
|
||||
50
mozilla/netwerk/cache/filecache/test/Makefile.in
vendored
Normal file
50
mozilla/netwerk/cache/filecache/test/Makefile.in
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
REQUIRES = libreg xpcom
|
||||
|
||||
CPPSRCS = \
|
||||
diskcache.cpp \
|
||||
$(NULL)
|
||||
|
||||
SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=)
|
||||
|
||||
ifdef NO_LD_ARCHIVE_FLAGS
|
||||
LOST_SYM_LIBS = -lxpcomds_s -lxptinfo -lmozreg_s
|
||||
endif
|
||||
|
||||
LIBS = \
|
||||
-lmozjs \
|
||||
-lxpcom \
|
||||
-lmozdbm_s \
|
||||
$(MOZ_NECKO_UTIL_LIBS) \
|
||||
$(LOST_SYM_LIBS) \
|
||||
$(NSPR_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
LOCAL_INCLUDES = -I$(srcdir)/..
|
||||
|
||||
DEFINES += -DUSE_NSREG -DCACHE
|
||||
836
mozilla/netwerk/cache/filecache/test/diskcache.cpp
vendored
Normal file
836
mozilla/netwerk/cache/filecache/test/diskcache.cpp
vendored
Normal file
@@ -0,0 +1,836 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIStreamObserver.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIEventQueue.h"
|
||||
#include "nsIEventQueueService.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "nsINetDataCache.h"
|
||||
#include "nsINetDataCacheRecord.h"
|
||||
//#include "nsMemCacheCID.h"
|
||||
#include "nsNetDiskCache.h"
|
||||
#include "nsIPref.h"
|
||||
#include "prenv.h"
|
||||
#include "nsIFileStream.h"
|
||||
|
||||
// Number of test entries to be placed in the cache
|
||||
#define NUM_CACHE_ENTRIES 250
|
||||
|
||||
// Cache content stream length will have random length between zero and
|
||||
// MAX_CONTENT_LENGTH bytes
|
||||
#define MAX_CONTENT_LENGTH 20000
|
||||
|
||||
// Length of random-data cache entry key
|
||||
#define CACHE_KEY_LENGTH 15
|
||||
|
||||
// Length of random-data cache entry meta-data
|
||||
#define CACHE_METADATA_LENGTH 100
|
||||
|
||||
//static NS_DEFINE_CID(kMemCacheCID, NS_MEM_CACHE_FACTORY_CID);
|
||||
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
||||
static NS_DEFINE_CID(kDiskCacheCID, NS_NETDISKCACHE_CID) ;
|
||||
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
|
||||
static NS_DEFINE_IID(kIPrefIID, NS_IPREF_IID);
|
||||
|
||||
// Mapping from test case number to RecordID
|
||||
static PRInt32 recordID[NUM_CACHE_ENTRIES];
|
||||
|
||||
static PRInt32
|
||||
mapRecordIdToTestNum(PRInt32 aRecordID)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < NUM_CACHE_ENTRIES; i++) {
|
||||
if (recordID[i] == aRecordID)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// A supply of stream data to either store or compare with
|
||||
class nsITestDataStream {
|
||||
public:
|
||||
virtual ~nsITestDataStream() {};
|
||||
virtual PRUint32 Next() = 0;
|
||||
virtual void Read(char* aBuf, PRUint32 aCount) = 0;
|
||||
|
||||
virtual PRBool Match(char* aBuf, PRUint32 aCount) = 0;
|
||||
virtual void Skip(PRUint32 aCount) = 0;
|
||||
};
|
||||
|
||||
// A reproducible stream of random data.
|
||||
class RandomStream : public nsITestDataStream {
|
||||
public:
|
||||
RandomStream(PRUint32 aSeed) {
|
||||
mStartSeed = mState = aSeed;
|
||||
}
|
||||
|
||||
PRUint32 GetStartSeed() {
|
||||
return mStartSeed;
|
||||
}
|
||||
|
||||
PRUint32 Next() {
|
||||
mState = 1103515245 * mState + 12345;
|
||||
return mState;
|
||||
}
|
||||
|
||||
void Read(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
*aBuf++ = Next();
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
Match(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
if (*aBuf++ != (char)(Next() & 0xff))
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
Skip(PRUint32 aCount) {
|
||||
while (aCount--)
|
||||
Next();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
PRUint32 mState;
|
||||
PRUint32 mStartSeed;
|
||||
};
|
||||
|
||||
// A stream of data that increments on each byte that is read, modulo 256
|
||||
class CounterStream : public nsITestDataStream {
|
||||
public:
|
||||
CounterStream(PRUint32 aSeed) {
|
||||
mStartSeed = mState = aSeed;
|
||||
}
|
||||
|
||||
PRUint32 GetStartSeed() {
|
||||
return mStartSeed;
|
||||
}
|
||||
|
||||
PRUint32 Next() {
|
||||
mState += 1;
|
||||
mState &= 0xff;
|
||||
return mState;
|
||||
}
|
||||
|
||||
void Read(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
*aBuf++ = Next();
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
Match(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
if (*aBuf++ != (char)Next())
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
Skip(PRUint32 aCount) {
|
||||
mState += aCount;
|
||||
mState &= 0xff;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
PRUint32 mState;
|
||||
PRUint32 mStartSeed;
|
||||
};
|
||||
|
||||
static int gNumReaders = 0;
|
||||
static PRUint32 gTotalBytesRead = 0;
|
||||
static PRUint32 gTotalDuration = 0;
|
||||
|
||||
class nsReader : public nsIStreamListener {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsReader()
|
||||
: mStartTime(0), mBytesRead(0)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
gNumReaders++;
|
||||
}
|
||||
|
||||
virtual ~nsReader() {
|
||||
delete mTestDataStream;
|
||||
gNumReaders--;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Init(nsIChannel *aChannel, nsITestDataStream* aRandomStream, PRUint32 aExpectedStreamLength) {
|
||||
mChannel = aChannel;
|
||||
mTestDataStream = aRandomStream;
|
||||
mExpectedStreamLength = aExpectedStreamLength;
|
||||
mRefCnt = 1;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnStartRequest(nsIChannel* channel,
|
||||
nsISupports* context) {
|
||||
mStartTime = PR_IntervalNow();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnDataAvailable(nsIChannel* channel,
|
||||
nsISupports* context,
|
||||
nsIInputStream *aIStream,
|
||||
PRUint32 aSourceOffset,
|
||||
PRUint32 aLength) {
|
||||
char buf[1025];
|
||||
while (aLength > 0) {
|
||||
PRUint32 amt;
|
||||
PRBool match;
|
||||
aIStream->Read(buf, sizeof buf, &amt);
|
||||
if (amt == 0) break;
|
||||
aLength -= amt;
|
||||
mBytesRead += amt;
|
||||
match = mTestDataStream->Match(buf, amt);
|
||||
NS_ASSERTION(match, "Stored data was corrupted on read");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnStopRequest(nsIChannel* channel,
|
||||
nsISupports* context,
|
||||
nsresult aStatus,
|
||||
const PRUnichar* aMsg) {
|
||||
PRIntervalTime endTime;
|
||||
PRIntervalTime duration;
|
||||
|
||||
endTime = PR_IntervalNow();
|
||||
duration = (endTime - mStartTime);
|
||||
|
||||
if (NS_FAILED(aStatus)) printf("channel failed.\n");
|
||||
// printf("read %d bytes\n", mBytesRead);
|
||||
|
||||
NS_ASSERTION(mBytesRead == mExpectedStreamLength,
|
||||
"Stream in cache is wrong length");
|
||||
|
||||
gTotalBytesRead += mBytesRead;
|
||||
gTotalDuration += duration;
|
||||
|
||||
// Release channel
|
||||
mChannel = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
PRIntervalTime mStartTime;
|
||||
PRUint32 mBytesRead;
|
||||
nsITestDataStream* mTestDataStream;
|
||||
PRUint32 mExpectedStreamLength;
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsReader, nsIStreamListener, nsIStreamObserver)
|
||||
|
||||
static nsIEventQueue* eventQueue;
|
||||
|
||||
nsresult
|
||||
InitQueue() {
|
||||
nsresult rv;
|
||||
|
||||
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue service");
|
||||
|
||||
rv = eventQService->CreateThreadEventQueue();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create event queue");
|
||||
|
||||
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQueue);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue for main thread");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Process events until all streams are OnStopRequest'ed
|
||||
nsresult
|
||||
WaitForEvents() {
|
||||
while (gNumReaders) {
|
||||
eventQueue->ProcessPendingEvents();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Read data for a single cache record and compare against testDataStream
|
||||
nsresult
|
||||
TestReadStream(nsINetDataCacheRecord *record, nsITestDataStream *testDataStream,
|
||||
PRUint32 expectedStreamLength)
|
||||
{
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsresult rv;
|
||||
PRUint32 actualContentLength;
|
||||
|
||||
rv = record->NewChannel(0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = record->GetStoredContentLength(&actualContentLength);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(actualContentLength == expectedStreamLength,
|
||||
"nsINetDataCacheRecord::GetContentLength() busted ?");
|
||||
|
||||
nsReader *reader = new nsReader;
|
||||
reader->AddRef();
|
||||
rv = reader->Init(channel, testDataStream, expectedStreamLength);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = channel->AsyncRead(0, -1, 0, reader);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
reader->Release();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check that records can be retrieved using their record-ID, in addition
|
||||
// to using the opaque key.
|
||||
nsresult
|
||||
TestRecordID(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
RandomStream *randomStream;
|
||||
PRUint32 metaDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char *metaData;
|
||||
PRUint32 testNum;
|
||||
PRBool match;
|
||||
|
||||
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
rv = cache->GetCachedNetDataByID(recordID[testNum], getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't obtain record using record ID");
|
||||
|
||||
// Match against previously stored meta-data
|
||||
rv = record->GetMetaData(&metaDataLength, &metaData);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get record meta-data");
|
||||
match = randomStream->Match(metaData, metaDataLength);
|
||||
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
|
||||
|
||||
nsAllocator::Free(metaData);
|
||||
delete randomStream;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check that all cache entries in the database are enumerated and that
|
||||
// no duplicates appear.
|
||||
nsresult
|
||||
TestEnumeration(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
nsCOMPtr<nsISupports> tempISupports;
|
||||
nsCOMPtr<nsISimpleEnumerator> iterator;
|
||||
RandomStream *randomStream;
|
||||
PRUint32 metaDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char *metaData;
|
||||
PRUint32 testNum;
|
||||
PRBool match;
|
||||
PRInt32 recID;
|
||||
|
||||
int numRecords = 0;
|
||||
|
||||
// Iterate over all records in the cache
|
||||
rv = cache->NewCacheEntryIterator(getter_AddRefs(iterator));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create new cache entry iterator");
|
||||
|
||||
PRBool notDone;
|
||||
while (1) {
|
||||
|
||||
// Done iterating ?
|
||||
rv = iterator->HasMoreElements(¬Done);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!notDone)
|
||||
break;
|
||||
|
||||
// Get next record in iteration
|
||||
rv = iterator->GetNext(getter_AddRefs(tempISupports));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "iterator bustage");
|
||||
record = do_QueryInterface(tempISupports);
|
||||
|
||||
numRecords++;
|
||||
|
||||
// Get record ID
|
||||
rv = record->GetRecordID(&recID);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get Record ID");
|
||||
testNum = mapRecordIdToTestNum(recID);
|
||||
NS_ASSERTION(testNum != -1, "Corrupted Record ID ?");
|
||||
|
||||
// Erase mapping from table, so that duplicate enumerations are detected
|
||||
recordID[testNum] = -1;
|
||||
|
||||
// Make sure stream matches test data
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
// Match against previously stored meta-data
|
||||
rv = record->GetMetaData(&metaDataLength, &metaData);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get record meta-data");
|
||||
match = randomStream->Match(metaData, metaDataLength);
|
||||
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
|
||||
nsAllocator::Free(metaData);
|
||||
|
||||
delete randomStream;
|
||||
}
|
||||
|
||||
NS_ASSERTION(numRecords == NUM_CACHE_ENTRIES, "Iteration bug");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Read the test data that was written in FillCache(), checking for
|
||||
// corruption, truncation.
|
||||
nsresult
|
||||
TestRead(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
PRBool inCache;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
RandomStream *randomStream;
|
||||
PRUint32 metaDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char *metaData, *storedCacheKey;
|
||||
PRUint32 testNum, storedCacheKeyLength;
|
||||
PRBool match;
|
||||
|
||||
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
// Ensure that entry is in the cache
|
||||
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(inCache, "nsINetDataCache::Contains error");
|
||||
|
||||
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
// Match against previously stored meta-data
|
||||
match = record->GetMetaData(&metaDataLength, &metaData);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
match = randomStream->Match(metaData, metaDataLength);
|
||||
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
|
||||
nsAllocator::Free(metaData);
|
||||
|
||||
// Test GetKey() method
|
||||
rv = record->GetKey(&storedCacheKeyLength, &storedCacheKey);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) &&
|
||||
(storedCacheKeyLength == sizeof cacheKey) &&
|
||||
!memcmp(storedCacheKey, &cacheKey[0], sizeof cacheKey),
|
||||
"nsINetDataCacheRecord::GetKey failed");
|
||||
nsAllocator::Free(storedCacheKey);
|
||||
|
||||
PRUint32 expectedStreamLength = randomStream->Next() & 0xffff;
|
||||
|
||||
TestReadStream(record, randomStream, expectedStreamLength);
|
||||
}
|
||||
|
||||
WaitForEvents();
|
||||
|
||||
// Compute rate in MB/s
|
||||
double rate = gTotalBytesRead / PR_IntervalToMilliseconds(gTotalDuration);
|
||||
rate *= NUM_CACHE_ENTRIES;
|
||||
rate *= 1000;
|
||||
rate /= (1024 * 1024);
|
||||
printf("Read %d bytes at a rate of %5.1f MB per second \n",
|
||||
gTotalBytesRead, rate);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Repeatedly call SetStoredContentLength() on a cache entry and make
|
||||
// read the stream's data to ensure that it's not corrupted by the effect
|
||||
nsresult
|
||||
TestTruncation(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
RandomStream *randomStream;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
|
||||
randomStream = new RandomStream(0);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
randomStream->Skip(CACHE_METADATA_LENGTH);
|
||||
PRUint32 initialStreamLength = randomStream->Next() & 0xffff;
|
||||
delete randomStream;
|
||||
|
||||
PRUint32 i;
|
||||
PRUint32 delta = initialStreamLength / 64;
|
||||
for (i = initialStreamLength; i >= delta; i -= delta) {
|
||||
PRUint32 expectedStreamLength = i;
|
||||
|
||||
// Do the truncation
|
||||
record->SetStoredContentLength(expectedStreamLength);
|
||||
randomStream = new RandomStream(0);
|
||||
randomStream->Skip(CACHE_KEY_LENGTH + CACHE_METADATA_LENGTH + 1);
|
||||
|
||||
TestReadStream(record, randomStream, expectedStreamLength);
|
||||
WaitForEvents();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Write known data to random offsets in a single cache entry and test
|
||||
// resulting stream for correctness.
|
||||
nsresult
|
||||
TestOffsetWrites(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsCOMPtr<nsIOutputStream> outStream;
|
||||
char buf[512];
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
RandomStream *randomStream;
|
||||
|
||||
randomStream = new RandomStream(0);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't access record via opaque cache key");
|
||||
|
||||
|
||||
nsCOMPtr<nsIFileSpec> file ;
|
||||
record->GetFilename(getter_AddRefs(file)) ;
|
||||
char* name ;
|
||||
file->GetUnixStyleFilePath(&name) ;
|
||||
printf(" file name is %s \n", name) ;
|
||||
|
||||
// Write buffer-fulls of data at random offsets into the cache entry.
|
||||
// Data written is (offset % 0xff)
|
||||
PRUint32 startingOffset;
|
||||
PRUint32 streamLength = 0;
|
||||
PRUint32 len = 0 ;
|
||||
CounterStream *counterStream;
|
||||
|
||||
int i = 0;
|
||||
for (i = 0; i < 257; i++) {
|
||||
rv = record->NewChannel(0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
startingOffset = streamLength ? streamLength - (randomStream->Next() % sizeof buf): 0;
|
||||
rv = channel->OpenOutputStream(startingOffset, getter_AddRefs(outStream));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
truncate(name, startingOffset) ;
|
||||
|
||||
counterStream = new CounterStream(startingOffset);
|
||||
counterStream->Read(buf, sizeof buf);
|
||||
|
||||
nsresult status ;
|
||||
nsCOMPtr<nsIRandomAccessStore> ras = do_QueryInterface(outStream, &status);
|
||||
if (NS_FAILED(status)) {
|
||||
// mState = END_WRITE;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
PRIntn offset ;
|
||||
ras->Tell(&offset) ;
|
||||
// printf(" offset is %d \n", offset) ;
|
||||
|
||||
PRUint32 numWritten;
|
||||
rv = outStream->Write(buf, sizeof buf, &numWritten);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(numWritten == sizeof buf, "Write() bug?");
|
||||
streamLength = startingOffset + sizeof buf;
|
||||
|
||||
rv = outStream->Close();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't close channel");
|
||||
delete counterStream;
|
||||
|
||||
record->GetStoredContentLength(&len) ;
|
||||
if(len != streamLength)
|
||||
printf(" offset = %d is wrong, filesize = %d\n", startingOffset, len) ;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
rv = record->NewChannel(0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
startingOffset = 208;
|
||||
rv = channel->OpenOutputStream(startingOffset, getter_AddRefs(outStream));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
counterStream = new CounterStream(startingOffset);
|
||||
counterStream->Read(buf, sizeof buf);
|
||||
|
||||
nsresult status ;
|
||||
nsCOMPtr<nsIRandomAccessStore> ras = do_QueryInterface(outStream, &status);
|
||||
if (NS_FAILED(status)) {
|
||||
// mState = END_WRITE;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
PRIntn offset = 0 ;
|
||||
ras->Tell(&offset) ;
|
||||
printf(" offset is %d \n", offset) ;
|
||||
|
||||
PRUint32 numWritten;
|
||||
rv = outStream->Write(buf, sizeof buf, &numWritten);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(numWritten == sizeof buf, "Write() bug?");
|
||||
streamLength = startingOffset + sizeof buf;
|
||||
|
||||
rv = outStream->Close();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't close channel");
|
||||
delete counterStream;
|
||||
|
||||
record->GetStoredContentLength(&len) ;
|
||||
if(len != streamLength)
|
||||
printf(" offset = %d is wrong, filesize = %d\n", startingOffset, len) ;
|
||||
*/
|
||||
|
||||
delete randomStream;
|
||||
|
||||
counterStream = new CounterStream(0);
|
||||
TestReadStream(record, counterStream, streamLength);
|
||||
WaitForEvents();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Create entries in the network data cache, using random data for the
|
||||
// key, the meta-data and the stored content data.
|
||||
nsresult
|
||||
FillCache(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
PRBool inCache;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsCOMPtr<nsIOutputStream> outStream;
|
||||
char buf[1000];
|
||||
PRUint32 metaDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char metaData[CACHE_METADATA_LENGTH];
|
||||
PRUint32 testNum;
|
||||
char *data;
|
||||
RandomStream *randomStream;
|
||||
|
||||
PRIntervalTime startTime = PR_IntervalNow();
|
||||
|
||||
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
// No entry should be in cache until we add it
|
||||
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(!inCache, "nsINetDataCache::Contains error");
|
||||
|
||||
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't access record via opaque cache key");
|
||||
|
||||
// Test nsINetDataCacheRecord::GetRecordID()
|
||||
rv = record->GetRecordID(&recordID[testNum]);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get Record ID");
|
||||
|
||||
// Test nsINetDataCache::GetNumEntries()
|
||||
PRUint32 numEntries = (PRUint32)-1;
|
||||
rv = cache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == testNum + 1, "GetNumEntries failure");
|
||||
|
||||
// Record meta-data should be initially empty
|
||||
rv = record->GetMetaData(&metaDataLength, &data);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
if ((metaDataLength != 0) || (data != 0))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Store random data as meta-data
|
||||
randomStream->Read(metaData, sizeof metaData);
|
||||
record->SetMetaData(sizeof metaData, metaData);
|
||||
|
||||
rv = record->NewChannel(0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = channel->OpenOutputStream(0, getter_AddRefs(outStream));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
PRUint32 beforeOccupancy;
|
||||
rv = cache->GetStorageInUse(&beforeOccupancy);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
|
||||
|
||||
int streamLength = randomStream->Next() & 0xffff;
|
||||
int remaining = streamLength;
|
||||
while (remaining) {
|
||||
PRUint32 numWritten;
|
||||
int amount = PR_MIN(sizeof buf, remaining);
|
||||
randomStream->Read(buf, amount);
|
||||
|
||||
rv = outStream->Write(buf, amount, &numWritten);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(numWritten == (PRUint32)amount, "Write() bug?");
|
||||
|
||||
remaining -= amount;
|
||||
}
|
||||
outStream->Close();
|
||||
|
||||
PRUint32 afterOccupancy;
|
||||
rv = cache->GetStorageInUse(&afterOccupancy);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
|
||||
PRUint32 streamLengthInKB = streamLength >> 10;
|
||||
NS_ASSERTION((afterOccupancy - beforeOccupancy) >= streamLengthInKB,
|
||||
"nsINetDataCache::GetStorageInUse() is busted");
|
||||
|
||||
|
||||
// *Now* there should be an entry in the cache
|
||||
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(inCache, "nsINetDataCache::Contains error");
|
||||
|
||||
delete randomStream;
|
||||
}
|
||||
|
||||
PRIntervalTime endTime = PR_IntervalNow();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult NS_AutoregisterComponents()
|
||||
{
|
||||
nsresult rv = nsComponentManager::AutoRegister(nsIComponentManager::NS_Startup,
|
||||
NULL /* default */);
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRBool initPref ()
|
||||
{
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIPref, prefPtr, kPrefCID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return false;
|
||||
|
||||
nsCOMPtr<nsIFileSpec> fileSpec;
|
||||
rv = NS_NewFileSpec (getter_AddRefs(fileSpec));
|
||||
if (NS_FAILED(rv))
|
||||
return false;
|
||||
|
||||
nsCString defaultPrefFile = PR_GetEnv ("MOZILLA_FIVE_HOME");
|
||||
if (defaultPrefFile.Length())
|
||||
defaultPrefFile += "/";
|
||||
else
|
||||
defaultPrefFile = "./";
|
||||
defaultPrefFile += "default_prefs.js";
|
||||
|
||||
fileSpec->SetUnixStyleFilePath (defaultPrefFile.GetBuffer());
|
||||
|
||||
PRBool exists = false;
|
||||
fileSpec->Exists(&exists);
|
||||
if (exists)
|
||||
prefPtr->ReadUserPrefsFrom(fileSpec);
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
initPref() ;
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCache> cache;
|
||||
|
||||
rv = NS_AutoregisterComponents();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't register XPCOM components");
|
||||
|
||||
rv = nsComponentManager::CreateInstance(kDiskCacheCID, nsnull,
|
||||
NS_GET_IID(nsINetDataCache),
|
||||
getter_AddRefs(cache));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create memory cache factory");
|
||||
|
||||
InitQueue();
|
||||
|
||||
PRUnichar* description;
|
||||
rv = cache->GetDescription(&description);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache description");
|
||||
nsCAutoString descStr(description);
|
||||
printf("Testing: %s\n", descStr.GetBuffer());
|
||||
|
||||
rv = cache->RemoveAll();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
|
||||
|
||||
PRUint32 startOccupancy;
|
||||
rv = cache->GetStorageInUse(&startOccupancy);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
|
||||
|
||||
PRUint32 numEntries = (PRUint32)-1;
|
||||
rv = cache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
|
||||
|
||||
rv = FillCache(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't fill cache with random test data");
|
||||
|
||||
rv = TestRead(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't read random test data from cache");
|
||||
|
||||
rv = TestRecordID(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't index records using record ID");
|
||||
|
||||
rv = TestEnumeration(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully enumerate records");
|
||||
|
||||
rv = TestTruncation(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully truncate records");
|
||||
|
||||
rv = TestOffsetWrites(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully write to records using non-zero offsets");
|
||||
|
||||
rv = cache->RemoveAll();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
|
||||
rv = cache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
|
||||
|
||||
PRUint32 endOccupancy;
|
||||
rv = cache->GetStorageInUse(&endOccupancy);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
|
||||
|
||||
NS_ASSERTION(startOccupancy == endOccupancy, "Cache occupancy not correctly computed ?");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
48
mozilla/netwerk/cache/memcache/Makefile.in
vendored
Normal file
48
mozilla/netwerk/cache/memcache/Makefile.in
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
# Generated automatically from Makefile.in by configure.
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
# http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
# for the specific language governing rights and limitations under the
|
||||
# NPL.
|
||||
#
|
||||
# The Initial Developer of this code under the NPL is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
srcdir = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = nkcache
|
||||
|
||||
LIBRARY_NAME = nkmemcache_s
|
||||
|
||||
REQUIRES = nspr dbm
|
||||
|
||||
EXPORTS=nsMemCacheCID.h \
|
||||
nsMemCache.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
nsMemCache.cpp \
|
||||
nsMemCacheRecord.cpp \
|
||||
nsMemCacheChannel.cpp \
|
||||
$(NULL)
|
||||
|
||||
# we don't want the shared lib, but we want to force the creation of a
|
||||
# static lib.
|
||||
override NO_SHARED_LIB=1
|
||||
override NO_STATIC_LIB=
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#!nmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public License
|
||||
# Version 1.0 (the "NPL"); you may not use this file except in
|
||||
# compliance with the NPL. You may obtain a copy of the NPL at
|
||||
@@ -12,24 +14,29 @@
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
# Reserved.
|
||||
#
|
||||
# This is a list of local files which get copied to the mozilla:dist:mailnews directory
|
||||
#
|
||||
|
||||
nsMsgLineBuffer.h
|
||||
nsMsgGroupRecord.h
|
||||
nsUInt32Array.h
|
||||
nsMsgKeySet.h
|
||||
nsMsgFolder.h
|
||||
nsMsgDBFolder.h
|
||||
nsLocalFolderSummarySpec.h
|
||||
nsMsgIdentity.h
|
||||
nsMsgIncomingServer.h
|
||||
nsNewsSummarySpec.h
|
||||
nsMsgUtils.h
|
||||
nsMessage.h
|
||||
nsMsgProtocol.h
|
||||
nsMsgTxn.h
|
||||
nsMsgMailNewsUrl.h
|
||||
nsMsgI18N.h
|
||||
DEPTH=..\..\..
|
||||
|
||||
include <$(DEPTH)/config/config.mak>
|
||||
|
||||
MODULE = nkcache
|
||||
|
||||
LIBRARY_NAME = nkmemcache_s
|
||||
|
||||
CPP_OBJS = \
|
||||
.\$(OBJDIR)\nsMemCache.obj \
|
||||
.\$(OBJDIR)\nsMemCacheRecord.obj \
|
||||
.\$(OBJDIR)\nsMemCacheChannel.obj \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS=nsMemCacheCID.h
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
install:: $(LIBRARY)
|
||||
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
|
||||
|
||||
clobber::
|
||||
rm -rf $(OBJDIR)
|
||||
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib
|
||||
|
||||
334
mozilla/netwerk/cache/memcache/nsMemCache.cpp
vendored
Normal file
334
mozilla/netwerk/cache/memcache/nsMemCache.cpp
vendored
Normal file
@@ -0,0 +1,334 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* nsMemCache is the implementation of an in-memory network-data
|
||||
* cache, used to cache the responses to network retrieval commands.
|
||||
* Each cache entry may contain both content, e.g. GIF image data, and
|
||||
* associated metadata, e.g. HTTP headers. Each entry is indexed by
|
||||
* two different keys: a record id number and an opaque key, which is
|
||||
* created by the cache manager by combining the URI with a "secondary
|
||||
* key", e.g. HTTP post data.
|
||||
*/
|
||||
|
||||
#include "nsMemCache.h"
|
||||
#include "nsMemCacheRecord.h"
|
||||
#include "nsIGenericFactory.h"
|
||||
#include "nsString.h"
|
||||
#include "nsHashtable.h"
|
||||
#include "nsHashtableEnumerator.h"
|
||||
#include "nsEnumeratorUtils.h"
|
||||
|
||||
PRInt32 nsMemCache::gRecordSerialNumber = 0;
|
||||
|
||||
nsMemCache::nsMemCache()
|
||||
: mNumEntries(0), mOccupancy(0), mEnabled(PR_TRUE),
|
||||
mHashTable(0)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsMemCache::~nsMemCache()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = RemoveAll();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) && (mNumEntries == 0),
|
||||
"Failure to shut down memory cache. "
|
||||
"Somewhere, someone is holding references to at least one cache record");
|
||||
delete mHashTable;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMemCache::Init()
|
||||
{
|
||||
mHashTable = new nsHashtable(256);
|
||||
if (!mHashTable)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsMemCache, NS_GET_IID(nsINetDataCache))
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetDescription(PRUnichar * *aDescription)
|
||||
{
|
||||
nsAutoString description("Memory Cache");
|
||||
*aDescription = description.ToNewUnicode();
|
||||
if (!*aDescription)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::Contains(const char *aKey, PRUint32 aKeyLength, PRBool *aFound)
|
||||
{
|
||||
nsOpaqueKey *opaqueKey = new nsOpaqueKey(aKey, aKeyLength);
|
||||
if (!opaqueKey)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
*aFound = mHashTable->Exists(opaqueKey);
|
||||
delete opaqueKey;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetCachedNetData(const char *aKey, PRUint32 aKeyLength,
|
||||
nsINetDataCacheRecord* *aRecord)
|
||||
{
|
||||
nsresult rv;
|
||||
nsMemCacheRecord* record = 0;
|
||||
nsOpaqueKey *opaqueKey2 = 0;
|
||||
nsOpaqueKey *opaqueKey3 = 0;
|
||||
nsOpaqueKey *opaqueKey;
|
||||
|
||||
opaqueKey = new nsOpaqueKey(aKey, aKeyLength);
|
||||
if (!opaqueKey)
|
||||
goto out_of_memory;
|
||||
record = (nsMemCacheRecord*)mHashTable->Get(opaqueKey);
|
||||
delete opaqueKey;
|
||||
|
||||
// No existing cache database entry was found. Create a new one.
|
||||
// This requires two mappings in the hash table:
|
||||
// Record ID ==> record
|
||||
// Opaque key ==> record
|
||||
if (!record) {
|
||||
record = new nsMemCacheRecord;
|
||||
if (!record)
|
||||
goto out_of_memory;
|
||||
rv = record->Init(aKey, aKeyLength, ++gRecordSerialNumber, this);
|
||||
if (NS_FAILED(rv)) goto out_of_memory;
|
||||
|
||||
// Index the record by opaque key
|
||||
opaqueKey2 = new nsOpaqueKey(record->mKey, record->mKeyLength);
|
||||
if (!opaqueKey2) goto out_of_memory;
|
||||
mHashTable->Put(opaqueKey2, record);
|
||||
|
||||
// Index the record by it's record ID
|
||||
char *recordIDbytes = NS_REINTERPRET_CAST(char *, &record->mRecordID);
|
||||
opaqueKey3 = new nsOpaqueKey(recordIDbytes,
|
||||
sizeof record->mRecordID);
|
||||
if (!opaqueKey3) {
|
||||
// Clean up the first record from the hash table
|
||||
mHashTable->Remove(opaqueKey);
|
||||
goto out_of_memory;
|
||||
}
|
||||
mHashTable->Put(opaqueKey3, record);
|
||||
|
||||
// The hash table holds on to the record
|
||||
record->AddRef();
|
||||
|
||||
delete opaqueKey2;
|
||||
delete opaqueKey3;
|
||||
mNumEntries++;
|
||||
}
|
||||
|
||||
record->AddRef();
|
||||
*aRecord = record;
|
||||
return NS_OK;
|
||||
|
||||
out_of_memory:
|
||||
delete opaqueKey2;
|
||||
delete opaqueKey3;
|
||||
delete record;
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetCachedNetDataByID(PRInt32 RecordID,
|
||||
nsINetDataCacheRecord* *aRecord)
|
||||
{
|
||||
nsOpaqueKey opaqueKey(NS_REINTERPRET_CAST(const char *, &RecordID),
|
||||
sizeof RecordID);
|
||||
*aRecord = (nsINetDataCacheRecord*)mHashTable->Get(&opaqueKey);
|
||||
if (*aRecord) {
|
||||
NS_ADDREF(*aRecord);
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_METHOD
|
||||
nsMemCache::Delete(nsMemCacheRecord* aRecord)
|
||||
{
|
||||
nsMemCacheRecord *removedRecord;
|
||||
|
||||
char *recordIDbytes = NS_REINTERPRET_CAST(char *, &aRecord->mRecordID);
|
||||
nsOpaqueKey opaqueRecordIDKey(recordIDbytes,
|
||||
sizeof aRecord->mRecordID);
|
||||
removedRecord = (nsMemCacheRecord*)mHashTable->Remove(&opaqueRecordIDKey);
|
||||
NS_ASSERTION(removedRecord == aRecord, "memory cache database inconsistent");
|
||||
|
||||
nsOpaqueKey opaqueKey(aRecord->mKey, aRecord->mKeyLength);
|
||||
removedRecord = (nsMemCacheRecord*)mHashTable->Remove(&opaqueKey);
|
||||
NS_ASSERTION(removedRecord == aRecord, "memory cache database inconsistent");
|
||||
|
||||
aRecord->Release();
|
||||
|
||||
mNumEntries--;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetEnabled(PRBool *aEnabled)
|
||||
{
|
||||
NS_ENSURE_ARG(aEnabled);
|
||||
*aEnabled = mEnabled;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::SetEnabled(PRBool aEnabled)
|
||||
{
|
||||
mEnabled = aEnabled;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetFlags(PRUint32 *aFlags)
|
||||
{
|
||||
NS_ENSURE_ARG(aFlags);
|
||||
*aFlags = MEMORY_CACHE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetNumEntries(PRUint32 *aNumEntries)
|
||||
{
|
||||
NS_ENSURE_ARG(aNumEntries);
|
||||
*aNumEntries = mNumEntries;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetMaxEntries(PRUint32 *aMaxEntries)
|
||||
{
|
||||
NS_ENSURE_ARG(aMaxEntries);
|
||||
*aMaxEntries = MEM_CACHE_MAX_ENTRIES;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static NS_METHOD
|
||||
HashEntryConverter(nsHashKey *aKey, void *aValue,
|
||||
void *unused, nsISupports **retval)
|
||||
{
|
||||
nsMemCacheRecord *record;
|
||||
nsOpaqueKey *opaqueKey;
|
||||
|
||||
record = (nsMemCacheRecord*)aValue;
|
||||
opaqueKey = (nsOpaqueKey*)aKey;
|
||||
|
||||
// Hash table keys that index cache entries by their record ID
|
||||
// shouldn't be enumerated.
|
||||
if ((opaqueKey->GetKeyLength() == sizeof(PRInt32))) {
|
||||
|
||||
#ifdef DEBUG
|
||||
PRInt32 recordID;
|
||||
record->GetRecordID(&recordID);
|
||||
NS_ASSERTION(*((PRInt32*)opaqueKey->GetKey()) == recordID,
|
||||
"Key has incorrect key length");
|
||||
#endif
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(record);
|
||||
*retval = NS_STATIC_CAST(nsISupports*, record);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::NewCacheEntryIterator(nsISimpleEnumerator* *aIterator)
|
||||
{
|
||||
nsCOMPtr<nsIEnumerator> iterator;
|
||||
|
||||
NS_ENSURE_ARG(aIterator);
|
||||
NS_NewHashtableEnumerator(mHashTable, HashEntryConverter,
|
||||
mHashTable, getter_AddRefs(iterator));
|
||||
return NS_NewAdapterEnumerator(aIterator, iterator);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetNextCache(nsINetDataCache* *aNextCache)
|
||||
{
|
||||
NS_ENSURE_ARG(aNextCache);
|
||||
*aNextCache = mNextCache;
|
||||
NS_ADDREF(*aNextCache);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::SetNextCache(nsINetDataCache* aNextCache)
|
||||
{
|
||||
mNextCache = aNextCache;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::GetStorageInUse(PRUint32 *aStorageInUse)
|
||||
{
|
||||
NS_ENSURE_ARG(aStorageInUse);
|
||||
|
||||
// Convert from bytes to KB
|
||||
*aStorageInUse = (mOccupancy >> 10);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCache::RemoveAll(void)
|
||||
{
|
||||
PRBool failed;
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> iterator;
|
||||
nsCOMPtr<nsISupports> recordSupports;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
nsresult rv;
|
||||
|
||||
failed = PR_FALSE;
|
||||
rv = NewCacheEntryIterator(getter_AddRefs(iterator));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
PRBool notDone;
|
||||
while (1) {
|
||||
rv = iterator->HasMoreElements(¬Done);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!notDone)
|
||||
break;
|
||||
|
||||
iterator->GetNext(getter_AddRefs(recordSupports));
|
||||
record = do_QueryInterface(recordSupports);
|
||||
recordSupports = 0;
|
||||
|
||||
PRUint32 bytesUsed;
|
||||
record->GetStoredContentLength(&bytesUsed);
|
||||
rv = record->Delete();
|
||||
if (NS_FAILED(rv)) {
|
||||
failed = PR_TRUE;
|
||||
continue;
|
||||
}
|
||||
mOccupancy -= bytesUsed;
|
||||
}
|
||||
|
||||
if (failed)
|
||||
return NS_ERROR_FAILURE;
|
||||
return NS_OK;
|
||||
}
|
||||
83
mozilla/netwerk/cache/memcache/nsMemCache.h
vendored
Normal file
83
mozilla/netwerk/cache/memcache/nsMemCache.h
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* nsMemCache is the implementation of an in-memory network-data
|
||||
* cache, used to cache the responses to network retrieval commands.
|
||||
* Each cache entry may contain both content, e.g. GIF image data, and
|
||||
* associated metadata, e.g. HTTP headers. Each entry is indexed by
|
||||
* two different keys: a record id number and an opaque key, which is
|
||||
* created by the cache manager by combining the URI with a "secondary
|
||||
* key", e.g. HTTP post data.
|
||||
*/
|
||||
|
||||
#ifndef _nsMemCache_h_
|
||||
#define _nsMemCache_h_
|
||||
|
||||
#include "nsINetDataCache.h"
|
||||
|
||||
// Maximum number of URIs that may be resident in the cache
|
||||
#define MEM_CACHE_MAX_ENTRIES 1000
|
||||
|
||||
#define MEM_CACHE_SEGMENT_SIZE (1 << 12)
|
||||
#define MEM_CACHE_MAX_ENTRY_SIZE (1 << 20)
|
||||
|
||||
class nsHashtable;
|
||||
class nsMemCacheRecord;
|
||||
|
||||
class nsMemCache : public nsINetDataCache
|
||||
{
|
||||
public:
|
||||
nsMemCache();
|
||||
virtual ~nsMemCache();
|
||||
nsresult Init();
|
||||
|
||||
// nsISupports methods
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsINetDataCache methods
|
||||
NS_DECL_NSINETDATACACHE
|
||||
|
||||
// Factory
|
||||
static NS_METHOD nsMemCacheConstructor(nsISupports *aOuter, REFNSIID aIID,
|
||||
void **aResult);
|
||||
|
||||
protected:
|
||||
|
||||
PRUint32 mNumEntries;
|
||||
PRUint32 mOccupancy; // Memory used, in bytes
|
||||
PRBool mEnabled; // If false, bypass mem cache
|
||||
|
||||
nsINetDataCache* mNextCache;
|
||||
|
||||
// Mapping from either opaque key or record ID to nsMemCacheRecord
|
||||
nsHashtable* mHashTable;
|
||||
|
||||
// Used to assign record ID's
|
||||
static PRInt32 gRecordSerialNumber;
|
||||
|
||||
NS_METHOD Delete(nsMemCacheRecord* aRecord);
|
||||
|
||||
friend class nsMemCacheRecord;
|
||||
friend class nsMemCacheChannel;
|
||||
};
|
||||
|
||||
#endif // _nsMemCache_h_
|
||||
36
mozilla/netwerk/cache/memcache/nsMemCacheCID.h
vendored
Normal file
36
mozilla/netwerk/cache/memcache/nsMemCacheCID.h
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
// XPCOM Class ID for the network data in-memory cache
|
||||
|
||||
#ifndef nsMEMCACHECID_h__
|
||||
#define nsMEMCACHECID_h__
|
||||
|
||||
// {e4710560-7de2-11d3-90cb-0040056a906e}
|
||||
#define NS_MEM_CACHE_FACTORY_CID \
|
||||
{ \
|
||||
0xe4710560, \
|
||||
0x7de2, \
|
||||
0x11d3, \
|
||||
{0x90, 0xcb, 0x00, 0x40, 0x05, 0x6a, 0x90, 0x6e} \
|
||||
}
|
||||
|
||||
#endif // nsMEMCACHECID_h__
|
||||
462
mozilla/netwerk/cache/memcache/nsMemCacheChannel.cpp
vendored
Normal file
462
mozilla/netwerk/cache/memcache/nsMemCacheChannel.cpp
vendored
Normal file
@@ -0,0 +1,462 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "nsMemCache.h"
|
||||
#include "nsMemCacheChannel.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIStorageStream.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIEventQueueService.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsILoadGroup.h"
|
||||
|
||||
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
|
||||
static NS_DEFINE_CID(kEventQueueService, NS_EVENTQUEUESERVICE_CID);
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsMemCacheChannel, NS_GET_IID(nsIChannel))
|
||||
|
||||
void
|
||||
nsMemCacheChannel::NotifyStorageInUse(PRInt32 aBytesUsed)
|
||||
{
|
||||
mRecord->mCache->mOccupancy += aBytesUsed;
|
||||
}
|
||||
|
||||
/**
|
||||
* This class acts as an adaptor around a synchronous input stream to add async
|
||||
* read capabilities. It adds methods for initiating, suspending, resuming and
|
||||
* cancelling async reads.
|
||||
*/
|
||||
class AsyncReadStreamAdaptor : public nsIInputStream {
|
||||
public:
|
||||
AsyncReadStreamAdaptor(nsMemCacheChannel* aChannel, nsIInputStream *aSyncStream):
|
||||
mSyncStream(aSyncStream), mDataAvailCursor(0),
|
||||
mRemaining(0), mAvailable(0), mChannel(aChannel), mAborted(PR_FALSE), mSuspended(PR_FALSE)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
NS_ADDREF(mChannel);
|
||||
}
|
||||
|
||||
virtual ~AsyncReadStreamAdaptor() {
|
||||
mChannel->mAsyncReadStream = 0;
|
||||
NS_RELEASE(mChannel);
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsresult
|
||||
IsPending(PRBool* aIsPending) {
|
||||
*aIsPending = (mRemaining != 0) && !mAborted;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Cancel(void) {
|
||||
mAborted = PR_TRUE;
|
||||
return mStreamListener->OnStopRequest(mChannel, mContext, NS_BINDING_ABORTED, nsnull);
|
||||
}
|
||||
|
||||
nsresult
|
||||
Suspend(void) { mSuspended = PR_TRUE; return NS_OK; }
|
||||
|
||||
nsresult
|
||||
Resume(void) {
|
||||
if (!mSuspended)
|
||||
return NS_ERROR_FAILURE;
|
||||
mSuspended = PR_FALSE;
|
||||
return NextListenerEvent();
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Available(PRUint32 *aNumBytes) { return mAvailable; }
|
||||
|
||||
NS_IMETHOD
|
||||
Read(char* aBuf, PRUint32 aCount, PRUint32 *aBytesRead) {
|
||||
if (mAborted)
|
||||
return NS_ERROR_ABORT;
|
||||
|
||||
*aBytesRead = 0;
|
||||
aCount = PR_MIN(aCount, mAvailable);
|
||||
nsresult rv = mSyncStream->Read(aBuf, aCount, aBytesRead);
|
||||
mAvailable -= *aBytesRead;
|
||||
|
||||
if (NS_FAILED(rv) && (rv != NS_BASE_STREAM_WOULD_BLOCK)) {
|
||||
Fail();
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!mSuspended && !mAvailable) {
|
||||
rv = NextListenerEvent();
|
||||
if (NS_FAILED(rv)) {
|
||||
Fail();
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Close() {
|
||||
nsresult rv = mSyncStream->Close();
|
||||
mSyncStream = 0;
|
||||
mContext = 0;
|
||||
mStreamListener = 0;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
AsyncRead(PRUint32 aStartPosition, PRInt32 aReadCount,
|
||||
nsISupports* aContext, nsIStreamListener* aListener) {
|
||||
|
||||
nsresult rv;
|
||||
nsIEventQueue *eventQ;
|
||||
|
||||
mContext = aContext;
|
||||
mStreamListener = aListener;
|
||||
mRemaining = aReadCount;
|
||||
|
||||
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueService, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQ);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = NS_NewAsyncStreamListener(aListener, eventQ,
|
||||
getter_AddRefs(mStreamListener));
|
||||
NS_RELEASE(eventQ);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mStreamListener->OnStartRequest(mChannel, aContext);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NextListenerEvent();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
nsresult
|
||||
Fail(void) {
|
||||
mAborted = PR_TRUE;
|
||||
return mStreamListener->OnStopRequest(mChannel, mContext, NS_BINDING_FAILED, nsnull);
|
||||
}
|
||||
|
||||
nsresult
|
||||
NextListenerEvent() {
|
||||
PRUint32 available;
|
||||
nsresult rv = mSyncStream->Available(&available);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
available -= mAvailable;
|
||||
available = PR_MIN(available, mRemaining);
|
||||
|
||||
if (available) {
|
||||
PRUint32 size = PR_MIN(available, MEM_CACHE_SEGMENT_SIZE);
|
||||
rv = mStreamListener->OnDataAvailable(mChannel, mContext, this,
|
||||
mDataAvailCursor, size);
|
||||
mDataAvailCursor += size;
|
||||
mRemaining -= size;
|
||||
mAvailable += size;
|
||||
return rv;
|
||||
} else {
|
||||
rv = mStreamListener->OnStopRequest(mChannel, mContext, NS_OK, nsnull);
|
||||
AsyncReadStreamAdaptor* thisAlias = this;
|
||||
NS_RELEASE(thisAlias);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsISupports> mContext; // Opaque context passed to AsyncRead()
|
||||
nsCOMPtr<nsIStreamListener> mStreamListener; // Stream listener that has been proxied
|
||||
nsCOMPtr<nsIInputStream> mSyncStream; // Underlying synchronous stream that is
|
||||
// being converted to an async stream
|
||||
PRUint32 mDataAvailCursor;
|
||||
PRUint32 mRemaining; // Size of AsyncRead request less bytes for
|
||||
// consumer OnDataAvailable's that were fired
|
||||
PRUint32 mAvailable; // Number of bytes for which OnDataAvailable fired
|
||||
nsMemCacheChannel* mChannel; // Associated memory cache channel, strong link
|
||||
// but can not use nsCOMPtr
|
||||
PRBool mAborted; // Abort() has been called
|
||||
PRBool mSuspended; // Suspend() has been called
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(AsyncReadStreamAdaptor, NS_GET_IID(nsIInputStream))
|
||||
|
||||
// The only purpose of this output stream wrapper is to adjust the cache's
|
||||
// overall occupancy as new data flows into the cache entry.
|
||||
class MemCacheWriteStreamWrapper : public nsIOutputStream {
|
||||
public:
|
||||
MemCacheWriteStreamWrapper(nsMemCacheChannel* aChannel, nsIOutputStream *aBaseStream):
|
||||
mBaseStream(aBaseStream), mChannel(aChannel)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
NS_ADDREF(mChannel);
|
||||
}
|
||||
|
||||
virtual ~MemCacheWriteStreamWrapper() { NS_RELEASE(mChannel); };
|
||||
|
||||
static nsresult
|
||||
Create(nsMemCacheChannel* aChannel, nsIOutputStream *aBaseStream, nsIOutputStream* *aWrapper) {
|
||||
MemCacheWriteStreamWrapper *wrapper =
|
||||
new MemCacheWriteStreamWrapper(aChannel, aBaseStream);
|
||||
if (!wrapper) return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(wrapper);
|
||||
*aWrapper = wrapper;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD
|
||||
Write(const char *aBuffer, PRUint32 aCount, PRUint32 *aNumWritten) {
|
||||
*aNumWritten = 0;
|
||||
nsresult rv = mBaseStream->Write(aBuffer, aCount, aNumWritten);
|
||||
mChannel->NotifyStorageInUse(*aNumWritten);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Flush() { return mBaseStream->Flush(); }
|
||||
|
||||
NS_IMETHOD
|
||||
Close() { return mBaseStream->Close(); }
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIOutputStream> mBaseStream;
|
||||
nsMemCacheChannel* mChannel;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(MemCacheWriteStreamWrapper, NS_GET_IID(nsIOutputStream))
|
||||
|
||||
nsMemCacheChannel::nsMemCacheChannel(nsMemCacheRecord *aRecord, nsILoadGroup *aLoadGroup)
|
||||
: mRecord(aRecord)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mRecord->mNumChannels++;
|
||||
}
|
||||
|
||||
nsMemCacheChannel::~nsMemCacheChannel()
|
||||
{
|
||||
mRecord->mNumChannels--;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::IsPending(PRBool* aIsPending)
|
||||
{
|
||||
*aIsPending = PR_FALSE;
|
||||
if (!mAsyncReadStream)
|
||||
return NS_OK;
|
||||
return mAsyncReadStream->IsPending(aIsPending);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::Cancel(void)
|
||||
{
|
||||
if (!mAsyncReadStream)
|
||||
return NS_ERROR_FAILURE;
|
||||
return mAsyncReadStream->Cancel();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::Suspend(void)
|
||||
{
|
||||
if (!mAsyncReadStream)
|
||||
return NS_ERROR_FAILURE;
|
||||
return mAsyncReadStream->Suspend();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::Resume(void)
|
||||
{
|
||||
if (!mAsyncReadStream)
|
||||
return NS_ERROR_FAILURE;
|
||||
return mAsyncReadStream->Resume();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::GetOriginalURI(nsIURI * *aURI)
|
||||
{
|
||||
// Not required
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::GetURI(nsIURI * *aURI)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::OpenInputStream(PRUint32 aStartPosition, PRInt32 aReadCount,
|
||||
nsIInputStream* *aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
NS_ENSURE_ARG(aResult);
|
||||
if (mInputStream)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
rv = mRecord->mStorageStream->NewInputStream(aStartPosition, getter_AddRefs(mInputStream));
|
||||
*aResult = mInputStream;
|
||||
NS_ADDREF(*aResult);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::OpenOutputStream(PRUint32 startPosition, nsIOutputStream* *aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
NS_ENSURE_ARG(aResult);
|
||||
|
||||
nsCOMPtr<nsIOutputStream> outputStream;
|
||||
|
||||
PRUint32 oldLength;
|
||||
mRecord->mStorageStream->GetLength(&oldLength);
|
||||
rv = mRecord->mStorageStream->GetOutputStream(startPosition, getter_AddRefs(outputStream));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (startPosition < oldLength)
|
||||
NotifyStorageInUse(startPosition - oldLength);
|
||||
|
||||
return MemCacheWriteStreamWrapper::Create(this, outputStream, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::AsyncOpen(nsIStreamObserver *observer, nsISupports *ctxt)
|
||||
{
|
||||
// Not required
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::AsyncRead(PRUint32 aStartPosition, PRInt32 aReadCount,
|
||||
nsISupports *aContext, nsIStreamListener *aListener)
|
||||
{
|
||||
nsCOMPtr<nsIInputStream> inputStream;
|
||||
nsresult rv = OpenInputStream(aStartPosition, aReadCount, getter_AddRefs(inputStream));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
AsyncReadStreamAdaptor *asyncReadStreamAdaptor;
|
||||
asyncReadStreamAdaptor = new AsyncReadStreamAdaptor(this, inputStream);
|
||||
if (!asyncReadStreamAdaptor)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(asyncReadStreamAdaptor);
|
||||
mAsyncReadStream = asyncReadStreamAdaptor;
|
||||
|
||||
rv = asyncReadStreamAdaptor->AsyncRead(aStartPosition, aReadCount, aContext, aListener);
|
||||
if (NS_FAILED(rv))
|
||||
delete asyncReadStreamAdaptor;
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::AsyncWrite(nsIInputStream *fromStream, PRUint32 startPosition,
|
||||
PRInt32 writeCount, nsISupports *ctxt,
|
||||
nsIStreamObserver *observer)
|
||||
{
|
||||
// Not required to be implemented
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::GetLoadAttributes(nsLoadFlags *aLoadAttributes)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::SetLoadAttributes(nsLoadFlags aLoadAttributes)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::GetContentType(char* *aContentType)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::GetContentLength(PRInt32 *aContentLength)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::GetOwner(nsISupports* *aOwner)
|
||||
{
|
||||
*aOwner = mOwner.get();
|
||||
NS_IF_ADDREF(*aOwner);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::SetOwner(nsISupports* aOwner)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
mOwner = aOwner;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aNotificationCallbacks)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
|
||||
{
|
||||
// Not required to be implemented, since it is implemented by cache manager
|
||||
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
61
mozilla/netwerk/cache/memcache/nsMemCacheChannel.h
vendored
Normal file
61
mozilla/netwerk/cache/memcache/nsMemCacheChannel.h
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _nsMemCacheChannel_h_
|
||||
#define _nsMemCacheChannel_h_
|
||||
|
||||
#include "nsMemCacheRecord.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
|
||||
class AsyncReadStreamAdaptor;
|
||||
|
||||
class nsMemCacheChannel : public nsIChannel
|
||||
{
|
||||
public:
|
||||
// Constructors and Destructor
|
||||
nsMemCacheChannel(nsMemCacheRecord *aRecord, nsILoadGroup *aLoadGroup);
|
||||
virtual ~nsMemCacheChannel();
|
||||
|
||||
// Declare nsISupports methods
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// Declare nsIRequest methods
|
||||
NS_DECL_NSIREQUEST
|
||||
|
||||
// Declare nsIChannel methods
|
||||
NS_DECL_NSICHANNEL
|
||||
|
||||
protected:
|
||||
void NotifyStorageInUse(PRInt32 aBytesUsed);
|
||||
|
||||
nsCOMPtr<nsMemCacheRecord> mRecord;
|
||||
nsCOMPtr<nsIInputStream> mInputStream;
|
||||
nsCOMPtr<nsISupports> mOwner;
|
||||
AsyncReadStreamAdaptor* mAsyncReadStream; // non-owning pointer
|
||||
|
||||
friend class MemCacheWriteStreamWrapper;
|
||||
friend class AsyncReadStreamAdaptor;
|
||||
};
|
||||
|
||||
#endif // _nsMemCacheChannel_h_
|
||||
164
mozilla/netwerk/cache/memcache/nsMemCacheRecord.cpp
vendored
Normal file
164
mozilla/netwerk/cache/memcache/nsMemCacheRecord.cpp
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "nsMemCache.h"
|
||||
#include "nsMemCacheRecord.h"
|
||||
#include "nsMemCacheChannel.h"
|
||||
#include "nsIAllocator.h"
|
||||
#include "nsStorageStream.h"
|
||||
|
||||
static NS_DEFINE_IID(kINetDataCacheRecord, NS_INETDATACACHERECORD_IID);
|
||||
|
||||
nsMemCacheRecord::nsMemCacheRecord()
|
||||
: mKey(0), mKeyLength(0), mMetaData(0), mMetaDataLength(0), mNumChannels(0)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsMemCacheRecord::~nsMemCacheRecord()
|
||||
{
|
||||
if (mMetaData)
|
||||
delete[] mMetaData;
|
||||
if (mKey)
|
||||
delete[] mKey;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsMemCacheRecord, NS_GET_IID(nsINetDataCacheRecord))
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::GetKey(PRUint32 *aLength, char **aResult)
|
||||
{
|
||||
NS_ENSURE_ARG(aResult);
|
||||
*aResult = (char *)nsAllocator::Alloc(mKeyLength);
|
||||
if (!*aResult)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
memcpy(*aResult, mKey, mKeyLength);
|
||||
*aLength = mKeyLength;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMemCacheRecord::Init(const char *aKey, PRUint32 aKeyLength,
|
||||
PRUint32 aRecordID, nsMemCache *aCache)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
NS_ASSERTION(!mKey, "Memory cache record key set multiple times");
|
||||
|
||||
rv = NS_NewStorageStream(MEM_CACHE_SEGMENT_SIZE, MEM_CACHE_MAX_ENTRY_SIZE,
|
||||
getter_AddRefs(mStorageStream));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mKey = new char[aKeyLength];
|
||||
if (!mKey)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
memcpy(mKey, aKey, aKeyLength);
|
||||
mKeyLength = aKeyLength;
|
||||
mRecordID = aRecordID;
|
||||
mCache = aCache;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::GetRecordID(PRInt32 *aRecordID)
|
||||
{
|
||||
NS_ENSURE_ARG(aRecordID);
|
||||
*aRecordID = mRecordID;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::GetMetaData(PRUint32 *aLength, char **aResult)
|
||||
{
|
||||
NS_ENSURE_ARG(aResult);
|
||||
|
||||
*aResult = 0;
|
||||
if (mMetaDataLength) {
|
||||
*aResult = (char*)nsAllocator::Alloc(mMetaDataLength);
|
||||
if (!*aResult)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
memcpy(*aResult, mMetaData, mMetaDataLength);
|
||||
}
|
||||
*aLength = mMetaDataLength;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::SetMetaData(PRUint32 aLength, const char *aData)
|
||||
{
|
||||
if (mMetaData)
|
||||
delete[] mMetaData;
|
||||
mMetaData = new char[aLength];
|
||||
if (!mMetaData)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
memcpy(mMetaData, aData, aLength);
|
||||
mMetaDataLength = aLength;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::GetStoredContentLength(PRUint32 *aStoredContentLength)
|
||||
{
|
||||
NS_ENSURE_ARG(aStoredContentLength);
|
||||
return mStorageStream->GetLength(aStoredContentLength);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::SetStoredContentLength(PRUint32 aStoredContentLength)
|
||||
{
|
||||
PRUint32 before, after;
|
||||
mStorageStream->GetLength(&before);
|
||||
nsresult rv = mStorageStream->SetLength(aStoredContentLength);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
mStorageStream->GetLength(&after);
|
||||
mCache->mOccupancy -= (before - after);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::Delete(void)
|
||||
{
|
||||
if (mNumChannels)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
return mCache->Delete(this);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::GetFilename(nsIFileSpec* *aFilename)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemCacheRecord::NewChannel(nsILoadGroup *aLoadGroup, nsIChannel* *aResult)
|
||||
{
|
||||
NS_ENSURE_ARG(aResult);
|
||||
|
||||
nsMemCacheChannel* channel = new nsMemCacheChannel(this, aLoadGroup);
|
||||
if (!channel)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(channel);
|
||||
*aResult = NS_STATIC_CAST(nsIChannel*, channel);
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
65
mozilla/netwerk/cache/memcache/nsMemCacheRecord.h
vendored
Normal file
65
mozilla/netwerk/cache/memcache/nsMemCacheRecord.h
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _nsMemCacheRecord_h_
|
||||
#define _nsMemCacheRecord_h_
|
||||
|
||||
#include "nsINetDataCacheRecord.h"
|
||||
#include "nsIStorageStream.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsMemCache;
|
||||
|
||||
class nsMemCacheRecord : public nsINetDataCacheRecord
|
||||
{
|
||||
|
||||
public:
|
||||
// Declare interface methods
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSINETDATACACHERECORD
|
||||
|
||||
protected:
|
||||
// Constructors and Destructor
|
||||
nsMemCacheRecord();
|
||||
virtual ~nsMemCacheRecord();
|
||||
|
||||
nsresult Init(const char *aKey, PRUint32 aKeyLength,
|
||||
PRUint32 aRecordID, nsMemCache *aCache);
|
||||
|
||||
char* mKey; // opaque database key for this record
|
||||
PRUint32 mKeyLength; // length, in bytes, of mKey
|
||||
|
||||
PRInt32 mRecordID; // An alternate key for this record
|
||||
|
||||
char* mMetaData; // opaque URI metadata
|
||||
PRUint32 mMetaDataLength; // length, in bytes, of mMetaData
|
||||
|
||||
nsMemCache* mCache; // weak pointer to the cache database
|
||||
// that this record inhabits
|
||||
|
||||
nsCOMPtr<nsIStorageStream> mStorageStream;
|
||||
PRUint32 mNumChannels; // Count un-Release'ed nsIChannels
|
||||
|
||||
friend class nsMemCache;
|
||||
friend class nsMemCacheChannel;
|
||||
};
|
||||
|
||||
#endif // _nsMemCacheRecord_h_
|
||||
55
mozilla/netwerk/cache/mgr/Makefile.in
vendored
Normal file
55
mozilla/netwerk/cache/mgr/Makefile.in
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape 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/NPL/
|
||||
#
|
||||
# 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 mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = nkcache
|
||||
LIBRARY_NAME = nkcachemgr_s
|
||||
|
||||
REQUIRES = nspr
|
||||
|
||||
EXPORTS = \
|
||||
nsCacheManager.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
nsCacheManager.cpp \
|
||||
nsCachedNetData.cpp \
|
||||
nsReplacementPolicy.cpp \
|
||||
nsCacheEntryChannel.cpp \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES = -I$(srcdir)/../public -I$(srcdir)/../include
|
||||
|
||||
EXTRA_LIBS = $(NSPR_LIBS)
|
||||
|
||||
# we don't want the shared lib, but we want to force the creation of a
|
||||
# static lib.
|
||||
override NO_SHARED_LIB=1
|
||||
override NO_STATIC_LIB=
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
45
mozilla/netwerk/cache/mgr/Makefile.win
vendored
Executable file
45
mozilla/netwerk/cache/mgr/Makefile.win
vendored
Executable file
@@ -0,0 +1,45 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape 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/NPL/
|
||||
#
|
||||
# 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 mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
|
||||
DEPTH=..\..\..
|
||||
|
||||
include <$(DEPTH)/config/config.mak>
|
||||
|
||||
MODULE = nkcache
|
||||
|
||||
LIBRARY_NAME = nkcachemgr_s
|
||||
|
||||
CPP_OBJS = \
|
||||
.\$(OBJDIR)\nsCacheManager.obj \
|
||||
.\$(OBJDIR)\nsCachedNetData.obj \
|
||||
.\$(OBJDIR)\nsReplacementPolicy.obj \
|
||||
.\$(OBJDIR)\nsCacheEntryChannel.obj \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
install:: $(LIBRARY)
|
||||
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
|
||||
|
||||
clobber::
|
||||
rm -rf $(OBJDIR)
|
||||
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib
|
||||
|
||||
261
mozilla/netwerk/cache/mgr/nsCacheEntryChannel.cpp
vendored
Normal file
261
mozilla/netwerk/cache/mgr/nsCacheEntryChannel.cpp
vendored
Normal file
@@ -0,0 +1,261 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Furman, fur@netscape.com
|
||||
*/
|
||||
|
||||
#include "nsCacheManager.h"
|
||||
#include "nsCacheEntryChannel.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIStreamListener.h"
|
||||
|
||||
nsCacheEntryChannel::nsCacheEntryChannel(nsCachedNetData* aCacheEntry, nsIChannel* aChannel,
|
||||
nsILoadGroup* aLoadGroup):
|
||||
nsChannelProxy(aChannel), mCacheEntry(aCacheEntry), mLoadGroup(aLoadGroup), mLoadAttributes(0)
|
||||
{
|
||||
NS_ASSERTION(aCacheEntry->mChannelCount < 0xFF, "Overflowed channel counter");
|
||||
mCacheEntry->mChannelCount++;
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsCacheEntryChannel::~nsCacheEntryChannel()
|
||||
{
|
||||
mCacheEntry->mChannelCount--;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS3(nsCacheEntryChannel, nsISupports, nsIChannel, nsIRequest)
|
||||
|
||||
// A proxy for nsIOutputStream
|
||||
class CacheOutputStream : public nsIOutputStream {
|
||||
|
||||
public:
|
||||
CacheOutputStream(nsIOutputStream *aOutputStream, nsCachedNetData *aCacheEntry):
|
||||
mOutputStream(aOutputStream), mCacheEntry(aCacheEntry), mStartTime(PR_Now())
|
||||
{ NS_INIT_REFCNT(); }
|
||||
|
||||
virtual ~CacheOutputStream() {
|
||||
mCacheEntry->NoteDownloadTime(mStartTime, PR_Now());
|
||||
mCacheEntry->ClearFlag(nsCachedNetData::UPDATE_IN_PROGRESS);
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD Close() {
|
||||
return mOutputStream->Close();
|
||||
}
|
||||
|
||||
NS_IMETHOD Flush() { return mOutputStream->Flush(); }
|
||||
|
||||
NS_IMETHOD
|
||||
Write(const char *aBuf, PRUint32 aCount, PRUint32 *aActualBytes) {
|
||||
nsresult rv;
|
||||
|
||||
*aActualBytes = 0;
|
||||
rv = mOutputStream->Write(aBuf, aCount, aActualBytes);
|
||||
mCacheEntry->mLogicalLength += *aActualBytes;
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsCacheManager::LimitCacheSize();
|
||||
return rv;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIOutputStream> mOutputStream;
|
||||
nsCOMPtr<nsCachedNetData> mCacheEntry;
|
||||
|
||||
// Time at which stream was opened
|
||||
PRTime mStartTime;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(CacheOutputStream, NS_GET_IID(nsIOutputStream))
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::OpenOutputStream(PRUint32 aStartPosition, nsIOutputStream* *aOutputStream)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIOutputStream> baseOutputStream;
|
||||
|
||||
rv = mChannel->OpenOutputStream(aStartPosition, getter_AddRefs(baseOutputStream));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mCacheEntry->NoteUpdate();
|
||||
mCacheEntry->NoteAccess();
|
||||
mCacheEntry->mLogicalLength = aStartPosition;
|
||||
|
||||
*aOutputStream = new CacheOutputStream(baseOutputStream, mCacheEntry);
|
||||
if (!*aOutputStream)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(*aOutputStream);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::OpenInputStream(PRUint32 aStartPosition, PRInt32 aReadCount,
|
||||
nsIInputStream* *aInputStream)
|
||||
{
|
||||
mCacheEntry->NoteAccess();
|
||||
return mChannel->OpenInputStream(aStartPosition, aReadCount, aInputStream);
|
||||
}
|
||||
|
||||
class CacheManagerStreamListener: public nsIStreamListener {
|
||||
|
||||
public:
|
||||
|
||||
CacheManagerStreamListener(nsIStreamListener *aListener,
|
||||
nsILoadGroup *aLoadGroup, nsIChannel *aChannel):
|
||||
mListener(aListener), mLoadGroup(aLoadGroup), mChannel(aChannel)
|
||||
{ NS_INIT_REFCNT(); }
|
||||
|
||||
virtual ~CacheManagerStreamListener() {}
|
||||
|
||||
private:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD
|
||||
OnDataAvailable(nsIChannel *channel, nsISupports *aContext,
|
||||
nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count) {
|
||||
return mListener->OnDataAvailable(mChannel, aContext, inStr, sourceOffset, count);
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnStartRequest(nsIChannel *channel, nsISupports *aContext) {
|
||||
if (mLoadGroup)
|
||||
mLoadGroup->AddChannel(mChannel, aContext);
|
||||
return mListener->OnStartRequest(mChannel, aContext);
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnStopRequest(nsIChannel *channel, nsISupports *aContext,
|
||||
nsresult status, const PRUnichar *errorMsg) {
|
||||
nsresult rv;
|
||||
rv = mListener->OnStopRequest(mChannel, aContext, status, errorMsg);
|
||||
if (mLoadGroup)
|
||||
mLoadGroup->RemoveChannel(mChannel, aContext, status, errorMsg);
|
||||
return rv;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
nsCOMPtr<nsIStreamListener> mListener;
|
||||
nsCOMPtr<nsILoadGroup> mLoadGroup;
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS2(CacheManagerStreamListener, nsIStreamListener, nsIStreamObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::AsyncRead(PRUint32 aStartPosition, PRInt32 aReadCount,
|
||||
nsISupports *aContext, nsIStreamListener *aListener)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
mCacheEntry->NoteAccess();
|
||||
|
||||
nsCOMPtr<nsIStreamListener> headListener;
|
||||
if (mLoadGroup) {
|
||||
mLoadGroup->GetDefaultLoadAttributes(&mLoadAttributes);
|
||||
|
||||
// Create a load group "proxy" listener...
|
||||
nsCOMPtr<nsILoadGroupListenerFactory> factory;
|
||||
rv = mLoadGroup->GetGroupListenerFactory(getter_AddRefs(factory));
|
||||
if (NS_SUCCEEDED(rv) && factory) {
|
||||
rv = factory->CreateLoadGroupListener(aListener,
|
||||
getter_AddRefs(headListener));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
} else {
|
||||
headListener = aListener;
|
||||
}
|
||||
|
||||
CacheManagerStreamListener* cacheManagerStreamListener;
|
||||
nsIChannel *channelForListener;
|
||||
|
||||
channelForListener = mProxyChannel ? mProxyChannel.get() : NS_STATIC_CAST(nsIChannel*, this);
|
||||
cacheManagerStreamListener =
|
||||
new CacheManagerStreamListener(headListener, mLoadGroup, channelForListener);
|
||||
if (!cacheManagerStreamListener) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(cacheManagerStreamListener);
|
||||
rv = mChannel->AsyncRead(aStartPosition, aReadCount, aContext,
|
||||
cacheManagerStreamListener);
|
||||
NS_RELEASE(cacheManagerStreamListener);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// No async writes allowed to the cache yet
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::AsyncWrite(nsIInputStream *aFromStream, PRUint32 aStartPosition,
|
||||
PRInt32 aWriteCount, nsISupports *aContext,
|
||||
nsIStreamObserver *aObserver)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
|
||||
{
|
||||
*aLoadGroup = mLoadGroup;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::GetLoadAttributes(nsLoadFlags *aLoadAttributes)
|
||||
{
|
||||
*aLoadAttributes = mLoadAttributes;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::SetLoadAttributes(nsLoadFlags aLoadAttributes)
|
||||
{
|
||||
mLoadAttributes = aLoadAttributes;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::GetURI(nsIURI * *aURI)
|
||||
{
|
||||
char* spec;
|
||||
nsresult rv;
|
||||
|
||||
rv = mCacheEntry->GetUriSpec(&spec);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = serv->NewURI(spec, 0, aURI);
|
||||
nsAllocator::Free(spec);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheEntryChannel::GetOriginalURI(nsIURI * *aURI)
|
||||
{
|
||||
// FIXME - should return original URI passed into NewChannel() ?
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
82
mozilla/netwerk/cache/mgr/nsCacheEntryChannel.h
vendored
Normal file
82
mozilla/netwerk/cache/mgr/nsCacheEntryChannel.h
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Furman, fur@netscape.com
|
||||
*/
|
||||
|
||||
#ifndef _nsCacheEntryChannel_h_
|
||||
#define _nsCacheEntryChannel_h_
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsCachedNetData.h"
|
||||
#include "nsILoadGroup.h"
|
||||
|
||||
class nsIStreamListener;
|
||||
|
||||
// A proxy for an nsIChannel, useful when only a few nsIChannel
|
||||
// methods must be overridden
|
||||
class nsChannelProxy : public nsIChannel {
|
||||
|
||||
public:
|
||||
NS_FORWARD_NSICHANNEL(mChannel->)
|
||||
NS_FORWARD_NSIREQUEST(mChannel->)
|
||||
|
||||
protected:
|
||||
nsChannelProxy(nsIChannel* aChannel):mChannel(aChannel) {};
|
||||
virtual ~nsChannelProxy() {};
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
};
|
||||
|
||||
// Override several nsIChannel methods so that they interact with the cache manager
|
||||
class nsCacheEntryChannel : public nsChannelProxy {
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD OpenOutputStream(PRUint32 aStartPosition, nsIOutputStream* *aOutputStream);
|
||||
NS_IMETHOD OpenInputStream(PRUint32 aStartPosition, PRInt32 aReadCount,
|
||||
nsIInputStream* *aInputStream);
|
||||
NS_IMETHOD AsyncRead(PRUint32 aStartPosition, PRInt32 aReadCount,
|
||||
nsISupports *aContext, nsIStreamListener *aListener);
|
||||
NS_IMETHOD AsyncWrite(nsIInputStream *aFromStream, PRUint32 aStartPosition,
|
||||
PRInt32 aWriteCount, nsISupports *aContext,
|
||||
nsIStreamObserver *aObserver);
|
||||
NS_IMETHOD GetLoadAttributes(nsLoadFlags *aLoadAttributes);
|
||||
NS_IMETHOD SetLoadAttributes(nsLoadFlags aLoadAttributes);
|
||||
NS_IMETHOD GetLoadGroup(nsILoadGroup* *aLoadGroup);
|
||||
NS_IMETHOD GetURI(nsIURI * *aURI);
|
||||
NS_IMETHOD GetOriginalURI(nsIURI * *aURI);
|
||||
|
||||
protected:
|
||||
nsCacheEntryChannel(nsCachedNetData* aCacheEntry, nsIChannel* aChannel, nsILoadGroup* aLoadGroup);
|
||||
virtual ~nsCacheEntryChannel();
|
||||
|
||||
friend class nsCachedNetData;
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsCachedNetData> mCacheEntry;
|
||||
nsCOMPtr<nsILoadGroup> mLoadGroup;
|
||||
nsCOMPtr<nsIChannel> mProxyChannel;
|
||||
nsLoadFlags mLoadAttributes;
|
||||
};
|
||||
|
||||
#endif // _nsCacheEntryChannel_h_
|
||||
497
mozilla/netwerk/cache/mgr/nsCacheManager.cpp
vendored
Normal file
497
mozilla/netwerk/cache/mgr/nsCacheManager.cpp
vendored
Normal file
@@ -0,0 +1,497 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Furman, fur@netscape.com
|
||||
*/
|
||||
|
||||
#include "nsINetDataCache.h"
|
||||
#include "nsCacheManager.h"
|
||||
#include "nsCachedNetData.h"
|
||||
#include "nsReplacementPolicy.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsHashtable.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsINetDataDiskCache.h"
|
||||
|
||||
// Limit the number of entries in the cache to conserve memory space
|
||||
// in the nsReplacementPolicy code
|
||||
#define MAX_MEM_CACHE_ENTRIES 800
|
||||
#define MAX_DISK_CACHE_ENTRIES 3200
|
||||
|
||||
// Cache capacities in MB, overridable via APIs
|
||||
#define DEFAULT_MEMORY_CACHE_CAPACITY 1024
|
||||
#define DEFAULT_DISK_CACHE_CAPACITY 10000
|
||||
|
||||
#define CACHE_HIGH_WATER_MARK(capacity) ((PRUint32)(0.98 * (capacity)))
|
||||
#define CACHE_LOW_WATER_MARK(capacity) ((PRUint32)(0.97 * (capacity)))
|
||||
|
||||
nsCacheManager* gCacheManager = 0;
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsCacheManager, NS_GET_IID(nsINetDataCacheManager))
|
||||
|
||||
nsCacheManager::nsCacheManager()
|
||||
: mActiveCacheRecords(0),
|
||||
mDiskCacheCapacity(DEFAULT_DISK_CACHE_CAPACITY),
|
||||
mMemCacheCapacity(DEFAULT_MEMORY_CACHE_CAPACITY)
|
||||
{
|
||||
NS_ASSERTION(!gCacheManager, "Multiple cache managers created");
|
||||
gCacheManager = this;
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
nsCacheManager::~nsCacheManager()
|
||||
{
|
||||
gCacheManager = 0;
|
||||
delete mActiveCacheRecords;
|
||||
delete mMemSpaceManager;
|
||||
delete mDiskSpaceManager;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCacheManager::Init()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
mActiveCacheRecords = new nsHashtable(64);
|
||||
if (!mActiveCacheRecords)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// Instantiate the memory cache component
|
||||
rv = nsComponentManager::CreateInstance(NS_NETWORK_MEMORY_CACHE_PROGID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsINetDataCache),
|
||||
getter_AddRefs(mMemCache));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
rv = nsComponentManager::CreateInstance(NS_NETWORK_FLAT_CACHE_PROGID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsINetDataCache),
|
||||
|
||||
getter_AddRefs(mFlatCache));
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
// For now, we don't require a flat cache module to be present
|
||||
if (rv != NS_ERROR_FACTORY_NOT_REGISTERED)
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifdef FILE_CACHE_IS_READY
|
||||
// Instantiate the file cache component
|
||||
rv = nsComponentManager::CreateInstance(NS_NETWORK_FILE_CACHE_PROGID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsINetDataCache),
|
||||
getter_AddRefs(mFileCache));
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("No disk cache present");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set up linked list of caches in search order
|
||||
mCacheSearchChain = mMemCache;
|
||||
if (mFlatCache) {
|
||||
mMemCache->SetNextCache(mFlatCache);
|
||||
mFlatCache->SetNextCache(mFileCache);
|
||||
} else {
|
||||
mMemCache->SetNextCache(mFileCache);
|
||||
}
|
||||
|
||||
// TODO - Load any extension caches here
|
||||
|
||||
// Initialize replacement policy for memory cache module
|
||||
mMemSpaceManager = new nsReplacementPolicy;
|
||||
if (!mMemSpaceManager)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
rv = mMemSpaceManager->Init(MAX_MEM_CACHE_ENTRIES);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = mMemSpaceManager->AddCache(mMemCache);
|
||||
|
||||
// Initialize replacement policy for disk cache modules (file
|
||||
// cache and flat cache)
|
||||
mDiskSpaceManager = new nsReplacementPolicy;
|
||||
if (!mDiskSpaceManager)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
rv = mDiskSpaceManager->Init(MAX_DISK_CACHE_ENTRIES);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (mFileCache) {
|
||||
rv = mDiskSpaceManager->AddCache(mFileCache);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
if (mFlatCache) {
|
||||
rv = mDiskSpaceManager->AddCache(mFlatCache);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::GetCachedNetData(const char *aUriSpec, const char *aSecondaryKey,
|
||||
PRUint32 aSecondaryKeyLength,
|
||||
PRUint32 aFlags, nsICachedNetData* *aResult)
|
||||
{
|
||||
nsCachedNetData *cachedData;
|
||||
nsresult rv;
|
||||
nsINetDataCache *cache;
|
||||
nsReplacementPolicy *spaceManager;
|
||||
|
||||
if (aFlags & CACHE_AS_FILE) {
|
||||
cache = mFileCache;
|
||||
spaceManager = mDiskSpaceManager;
|
||||
|
||||
// Ensure that cache is initialized
|
||||
if (mDiskCacheCapacity == (PRUint32)-1)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
} else if ((aFlags & BYPASS_PERSISTENT_CACHE) ||
|
||||
(!mFileCache && !mFlatCache) || !mDiskCacheCapacity) {
|
||||
cache = mMemCache;
|
||||
spaceManager = mMemSpaceManager;
|
||||
} else {
|
||||
cache = mFlatCache ? mFlatCache : mFileCache;
|
||||
spaceManager = mDiskSpaceManager;
|
||||
}
|
||||
|
||||
// Construct the cache key by appending the secondary key to the URI spec
|
||||
nsCAutoString cacheKey(aUriSpec);
|
||||
|
||||
// Insert NUL at end of URI spec
|
||||
cacheKey += '\0';
|
||||
if (aSecondaryKey)
|
||||
cacheKey.Append(aSecondaryKey, aSecondaryKeyLength);
|
||||
|
||||
nsStringKey key(cacheKey);
|
||||
cachedData = (nsCachedNetData*)mActiveCacheRecords->Get(&key);
|
||||
|
||||
// There is no existing instance of nsCachedNetData for this URL.
|
||||
// Make one from the corresponding record in the cache module.
|
||||
if (cachedData) {
|
||||
NS_ASSERTION(cache == cachedData->mCache,
|
||||
"Cannot yet handle simultaneously active requests for the "
|
||||
"same URL using different caches");
|
||||
NS_ADDREF(cachedData);
|
||||
} else {
|
||||
rv = spaceManager->GetCachedNetData(cacheKey.GetBuffer(), cacheKey.Length(),
|
||||
cache, &cachedData);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mActiveCacheRecords->Put(&key, cachedData);
|
||||
}
|
||||
|
||||
*aResult = cachedData;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Remove this cache entry from the list of active ones
|
||||
nsresult
|
||||
nsCacheManager::NoteDormant(nsCachedNetData* aEntry)
|
||||
{
|
||||
nsresult rv;
|
||||
PRUint32 keyLength;
|
||||
char* key;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
nsCachedNetData* deletedEntry;
|
||||
|
||||
rv = aEntry->GetRecord(getter_AddRefs(record));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = record->GetKey(&keyLength, &key);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsStringKey hashTableKey(nsCString(key, keyLength));
|
||||
deletedEntry = (nsCachedNetData*)gCacheManager->mActiveCacheRecords->Remove(&hashTableKey);
|
||||
// NS_ASSERTION(deletedEntry == aEntry, "Hash table inconsistency");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::Contains(const char *aUriSpec, const char *aSecondaryKey,
|
||||
PRUint32 aSecondaryKeyLength,
|
||||
PRUint32 aFlags, PRBool *aResult)
|
||||
{
|
||||
nsINetDataCache *cache;
|
||||
nsReplacementPolicy *spaceManager;
|
||||
nsCachedNetData *cachedData;
|
||||
|
||||
if (aFlags & CACHE_AS_FILE) {
|
||||
cache = mFileCache;
|
||||
spaceManager = mDiskSpaceManager;
|
||||
} else if ((aFlags & BYPASS_PERSISTENT_CACHE) ||
|
||||
(!mFileCache && !mFlatCache) || !mDiskCacheCapacity) {
|
||||
cache = mMemCache;
|
||||
spaceManager = mMemSpaceManager;
|
||||
} else {
|
||||
cache = mFlatCache ? mFlatCache : mFileCache;
|
||||
spaceManager = mDiskSpaceManager;
|
||||
}
|
||||
|
||||
// Construct the cache key by appending the secondary key to the URI spec
|
||||
nsCAutoString cacheKey(aUriSpec);
|
||||
|
||||
// Insert NUL between URI spec and secondary key
|
||||
cacheKey += '\0';
|
||||
cacheKey.Append(aSecondaryKey, aSecondaryKeyLength);
|
||||
|
||||
// Locate the record using (URI + secondary key)
|
||||
nsStringKey key(cacheKey);
|
||||
cachedData = (nsCachedNetData*)mActiveCacheRecords->Get(&key);
|
||||
|
||||
if (cachedData && (cache == cachedData->mCache)) {
|
||||
*aResult = PR_TRUE;
|
||||
return NS_OK;
|
||||
} else {
|
||||
// No active cache entry, see if there is a dormant one
|
||||
return cache->Contains(cacheKey.GetBuffer(), cacheKey.Length(), aResult);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::GetNumEntries(PRUint32 *aNumEntries)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISimpleEnumerator> iterator;
|
||||
nsCOMPtr<nsISupports> cacheSupports;
|
||||
nsCOMPtr<nsINetDataCache> cache;
|
||||
|
||||
PRUint32 totalEntries = 0;
|
||||
|
||||
rv = NewCacheModuleIterator(getter_AddRefs(iterator));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
while (1) {
|
||||
PRBool notDone;
|
||||
rv = iterator->HasMoreElements(¬Done);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!notDone)
|
||||
break;
|
||||
|
||||
iterator->GetNext(getter_AddRefs(cacheSupports));
|
||||
cache = do_QueryInterface(cacheSupports);
|
||||
|
||||
PRUint32 numEntries;
|
||||
rv = cache->GetNumEntries(&numEntries);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
totalEntries += numEntries;
|
||||
}
|
||||
|
||||
*aNumEntries = totalEntries;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::NewCacheEntryIterator(nsISimpleEnumerator* *aResult)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
class CacheEnumerator : public nsISimpleEnumerator
|
||||
{
|
||||
public:
|
||||
CacheEnumerator(nsINetDataCache* aFirstCache):mCache(aFirstCache)
|
||||
{ NS_INIT_REFCNT(); }
|
||||
|
||||
virtual ~CacheEnumerator() {};
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHODIMP
|
||||
HasMoreElements(PRBool* aMoreElements) {
|
||||
*aMoreElements = (mCache != 0);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
GetNext(nsISupports* *aSupports) {
|
||||
*aSupports = mCache;
|
||||
if (!mCache)
|
||||
return NS_ERROR_FAILURE;
|
||||
NS_ADDREF(*aSupports);
|
||||
|
||||
nsCOMPtr<nsINetDataCache> nextCache;
|
||||
nsresult rv = mCache->GetNextCache(getter_AddRefs(nextCache));
|
||||
mCache = nextCache;
|
||||
return rv;
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsINetDataCache> mCache;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(CacheEnumerator, NS_GET_IID(nsISimpleEnumerator))
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::NewCacheModuleIterator(nsISimpleEnumerator* *aResult)
|
||||
{
|
||||
*aResult = new CacheEnumerator(mCacheSearchChain);
|
||||
if (!*aResult)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::RemoveAll(void)
|
||||
{
|
||||
nsresult rv, result;
|
||||
nsCOMPtr<nsISimpleEnumerator> iterator;
|
||||
nsCOMPtr<nsINetDataCache> cache;
|
||||
nsCOMPtr<nsISupports> iSupports;
|
||||
|
||||
result = NS_OK;
|
||||
rv = NewCacheModuleIterator(getter_AddRefs(iterator));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
while (1) {
|
||||
PRBool notDone;
|
||||
rv = iterator->HasMoreElements(¬Done);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!notDone)
|
||||
break;
|
||||
|
||||
iterator->GetNext(getter_AddRefs(iSupports));
|
||||
cache = do_QueryInterface(iSupports);
|
||||
|
||||
PRUint32 cacheFlags;
|
||||
rv = cache->GetFlags(&cacheFlags);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if ((cacheFlags & nsINetDataCache::READ_ONLY) == 0) {
|
||||
rv = cache->RemoveAll();
|
||||
if (NS_FAILED(rv))
|
||||
result = rv;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCacheManager::LimitMemCacheSize()
|
||||
{
|
||||
nsresult rv;
|
||||
nsReplacementPolicy* spaceManager;
|
||||
|
||||
NS_ASSERTION(gCacheManager, "No cache manager");
|
||||
|
||||
spaceManager = gCacheManager->mMemSpaceManager;
|
||||
|
||||
PRUint32 occupancy;
|
||||
rv = spaceManager->GetStorageInUse(&occupancy);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRUint32 memCacheCapacity = gCacheManager->mMemCacheCapacity;
|
||||
if (occupancy > CACHE_HIGH_WATER_MARK(memCacheCapacity))
|
||||
return spaceManager->Evict(CACHE_LOW_WATER_MARK(memCacheCapacity));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCacheManager::LimitDiskCacheSize()
|
||||
{
|
||||
nsresult rv;
|
||||
nsReplacementPolicy* spaceManager;
|
||||
|
||||
NS_ASSERTION(gCacheManager, "No cache manager");
|
||||
|
||||
spaceManager = gCacheManager->mDiskSpaceManager;
|
||||
|
||||
PRUint32 occupancy;
|
||||
rv = spaceManager->GetStorageInUse(&occupancy);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRUint32 diskCacheCapacity = gCacheManager->mDiskCacheCapacity;
|
||||
if (occupancy > CACHE_HIGH_WATER_MARK(diskCacheCapacity))
|
||||
return spaceManager->Evict(CACHE_LOW_WATER_MARK(diskCacheCapacity));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCacheManager::LimitCacheSize()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = LimitDiskCacheSize();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = LimitMemCacheSize();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::SetMemCacheCapacity(PRUint32 aCapacity)
|
||||
{
|
||||
mMemCacheCapacity = aCapacity;
|
||||
LimitCacheSize();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::GetMemCacheCapacity(PRUint32* aCapacity)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCapacity);
|
||||
*aCapacity = mMemCacheCapacity;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::SetDiskCacheCapacity(PRUint32 aCapacity)
|
||||
{
|
||||
mDiskCacheCapacity = aCapacity;
|
||||
LimitCacheSize();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::GetDiskCacheCapacity(PRUint32* aCapacity)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCapacity);
|
||||
*aCapacity = mDiskCacheCapacity;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::SetDiskCacheFolder(nsIFileSpec* aFolder)
|
||||
{
|
||||
NS_ENSURE_ARG(aFolder);
|
||||
|
||||
if (!mFileCache)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
nsCOMPtr<nsINetDataDiskCache> fileCache;
|
||||
fileCache = do_QueryInterface(mFileCache);
|
||||
return fileCache->SetDiskCacheFolder(aFolder);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCacheManager::GetDiskCacheFolder(nsIFileSpec* *aFolder)
|
||||
{
|
||||
NS_ENSURE_ARG(aFolder);
|
||||
|
||||
if (!mFileCache)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
nsCOMPtr<nsINetDataDiskCache> fileCache;
|
||||
fileCache = do_QueryInterface(mFileCache);
|
||||
return fileCache->GetDiskCacheFolder(aFolder);
|
||||
}
|
||||
100
mozilla/netwerk/cache/mgr/nsCacheManager.h
vendored
Normal file
100
mozilla/netwerk/cache/mgr/nsCacheManager.h
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Furman, fur@netscape.com
|
||||
*/
|
||||
|
||||
#ifndef _nsCacheManager_h_
|
||||
#define _nsCacheManager_h_
|
||||
|
||||
// 2030f0b0-9567-11d3-90d3-0040056a906e
|
||||
#define NS_CACHE_MANAGER_CID \
|
||||
{ \
|
||||
0x2030f0b0, \
|
||||
0x9567, \
|
||||
0x11d3, \
|
||||
{0x90, 0xd3, 0x00, 0x40, 0x05, 0x6a, 0x90, 0x6e} \
|
||||
}
|
||||
|
||||
#include "nsINetDataCacheManager.h"
|
||||
#include "nsINetDataCache.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsHashtable;
|
||||
class nsReplacementPolicy;
|
||||
class nsCachedNetData;
|
||||
|
||||
class nsCacheManager : public nsINetDataCacheManager {
|
||||
|
||||
public:
|
||||
nsCacheManager();
|
||||
virtual ~nsCacheManager();
|
||||
|
||||
NS_METHOD Init();
|
||||
|
||||
// nsISupports methods
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsINetDataCacheManager methods
|
||||
NS_DECL_NSINETDATACACHEMANAGER
|
||||
|
||||
private:
|
||||
|
||||
// Mapping from cache key to nsCachedNetData, but only for those cache
|
||||
// entries with external references, i.e. those referred to outside the
|
||||
// cache manager
|
||||
nsHashtable* mActiveCacheRecords;
|
||||
|
||||
// Memory cache
|
||||
nsCOMPtr<nsINetDataCache> mMemCache;
|
||||
|
||||
// Flat-file database cache; All content aggregated into single disk file
|
||||
nsCOMPtr<nsINetDataCache> mFlatCache;
|
||||
|
||||
// stream-as-file cache
|
||||
nsCOMPtr<nsINetDataCache> mFileCache;
|
||||
|
||||
// Unified replacement policy for flat-cache and file-cache
|
||||
nsReplacementPolicy* mDiskSpaceManager;
|
||||
|
||||
// Replacement policy for memory cache
|
||||
nsReplacementPolicy* mMemSpaceManager;
|
||||
|
||||
// List of caches in search order
|
||||
nsINetDataCache* mCacheSearchChain;
|
||||
|
||||
// Combined file/flat cache capacity, in KB
|
||||
PRUint32 mDiskCacheCapacity;
|
||||
|
||||
// Memory cache capacity, in KB
|
||||
PRUint32 mMemCacheCapacity;
|
||||
|
||||
protected:
|
||||
static nsresult NoteDormant(nsCachedNetData* aEntry);
|
||||
static nsresult LimitCacheSize();
|
||||
static nsresult LimitMemCacheSize();
|
||||
static nsresult LimitDiskCacheSize();
|
||||
|
||||
friend class nsCachedNetData;
|
||||
friend class CacheOutputStream;
|
||||
};
|
||||
|
||||
#endif // _nsCacheManager_h_
|
||||
1155
mozilla/netwerk/cache/mgr/nsCachedNetData.cpp
vendored
Normal file
1155
mozilla/netwerk/cache/mgr/nsCachedNetData.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
242
mozilla/netwerk/cache/mgr/nsCachedNetData.h
vendored
Normal file
242
mozilla/netwerk/cache/mgr/nsCachedNetData.h
vendored
Normal file
@@ -0,0 +1,242 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Furman, fur@netscape.com
|
||||
*/
|
||||
|
||||
#ifndef _nsCachedNetData_h_
|
||||
#define _nsCachedNetData_h_
|
||||
|
||||
#include "nsICachedNetData.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsINetDataCacheRecord.h"
|
||||
|
||||
class nsINetDataCache;
|
||||
class nsIStreamAsFileObserver;
|
||||
class nsIStreamAsFile;
|
||||
class nsIArena;
|
||||
class StreamAsFileObserverClosure;
|
||||
class CacheMetaData;
|
||||
|
||||
// Number of recent access times recorded
|
||||
#define MAX_K 3
|
||||
|
||||
/**
|
||||
* FIXME - add comment. There are a lot of these data structures resident in
|
||||
* memory, so be careful about adding members unnecessarily.
|
||||
*/
|
||||
class nsCachedNetData : public nsICachedNetData {
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsICachedNetData methods
|
||||
NS_DECL_NSICACHEDNETDATA
|
||||
|
||||
NS_METHOD Init(nsINetDataCacheRecord *aRecord, nsINetDataCache *aCache);
|
||||
|
||||
protected:
|
||||
|
||||
// Bits for mFlags, below
|
||||
typedef enum {
|
||||
DIRTY = 1 << 0, // Cache entry data needs to be flushed to database
|
||||
|
||||
// ==== Flags that can be set by the protocol handler ====
|
||||
ALLOW_PARTIAL = 1 << 1, // Protocol handler supports partial fetching
|
||||
UPDATE_IN_PROGRESS = 1 << 2, // Protocol handler now modifying cache data
|
||||
|
||||
// ==== Cache-entry state flags. At most one of these flags can be set ====
|
||||
TRUNCATED_CONTENT = 1 << 4, // Entry contains valid content, but it has
|
||||
// been truncated by cache manager
|
||||
|
||||
// A previously-used cache entry, which has been purged of all cached
|
||||
// content and protocol-private data. This cache entry can be refilled
|
||||
// with new content or it may be retained in this vestigial state
|
||||
// because the usage statistics it contains will be used by the
|
||||
// replacement policy if the same URI is ever cached again.
|
||||
VESTIGIAL = 1 << 5,
|
||||
|
||||
// ==== Memory usage status bits. At most one of these flags can be set ====
|
||||
RECYCLED = 1 << 8, // Previously associated database record has
|
||||
// been deleted; This cache entry is available
|
||||
// for recycling.
|
||||
|
||||
DORMANT = 1 << 9, // No references to this cache entry, except by
|
||||
// the cache manager itself
|
||||
|
||||
// ==== Setter bits ====
|
||||
LAST_MODIFIED_KNOWN = 1 <<12, // Protocol handler called SetLastModifiedTime()
|
||||
EXPIRATION_KNOWN = 1 <<13, // Protocol handler called SetExpirationTime()
|
||||
STALE_TIME_KNOWN = 1 <<14, // Protocol handler called SetStaleTime()
|
||||
|
||||
// ==== Useful flag combinations ====
|
||||
// Cache entry not eligible for eviction
|
||||
UNEVICTABLE = VESTIGIAL | RECYCLED | UPDATE_IN_PROGRESS,
|
||||
|
||||
// State flags that are in-memory only, i.e. not persistent
|
||||
TRANSIENT_FLAGS = DIRTY | RECYCLED | DORMANT
|
||||
} Flag;
|
||||
|
||||
PRBool GetFlag(Flag aFlag) { return (mFlags & aFlag) != 0; }
|
||||
nsresult GetFlag(PRBool *aResult, Flag aFlag) { *aResult = GetFlag(aFlag); return NS_OK; }
|
||||
|
||||
// Set a boolean flag for the cache entry
|
||||
nsresult SetFlag(PRBool aValue, Flag aFlag);
|
||||
nsresult SetFlag(Flag aFlag) { return SetFlag(PR_TRUE, aFlag); }
|
||||
nsresult ClearFlag(Flag aFlag) { return SetFlag(PR_FALSE, aFlag); }
|
||||
|
||||
void ComputeProfit(PRUint32 aCurrentTime);
|
||||
static int Compare(const void *a, const void *b, void *unused);
|
||||
|
||||
void NoteAccess();
|
||||
void NoteUpdate();
|
||||
|
||||
// Get underlying raw cache database record.
|
||||
nsresult GetRecord(nsINetDataCacheRecord* *aRecord);
|
||||
|
||||
nsresult GetRecordID(PRInt32 *aRecordID);
|
||||
|
||||
nsresult Evict(PRUint32 aTruncatedContentLength);
|
||||
|
||||
nsresult GetFileSpec(nsIFileSpec* *aFileSpec);
|
||||
|
||||
void NoteDownloadTime(PRTime start, PRTime end);
|
||||
|
||||
// placement new for arena-allocation
|
||||
void *operator new (size_t aSize, nsIArena *aArena);
|
||||
|
||||
friend class nsReplacementPolicy;
|
||||
friend class nsCacheManager;
|
||||
friend class StreamAsFile;
|
||||
friend class nsCacheEntryChannel;
|
||||
friend class CacheOutputStream;
|
||||
friend class InterceptStreamListener;
|
||||
|
||||
private:
|
||||
|
||||
nsCachedNetData() {};
|
||||
virtual ~nsCachedNetData() {};
|
||||
|
||||
// Initialize internal fields of this nsCachedNetData instance from the
|
||||
// underlying raw cache database record.
|
||||
nsresult Deserialize(PRBool aDeserializeFlags);
|
||||
|
||||
// Notify stream-as-file observers about change in cache entry status
|
||||
nsresult Notify(PRUint32 aMessage, nsresult aError);
|
||||
|
||||
// Add/Remove stream-as-file observers
|
||||
nsresult AddObserver(nsIStreamAsFile *aStreamAsFile, nsIStreamAsFileObserver* aObserver);
|
||||
nsresult RemoveObserver(nsIStreamAsFileObserver* aObserver);
|
||||
|
||||
// Mark cache entry to indicate a write out to the cache database is required
|
||||
void SetDirty() { mFlags |= DIRTY; }
|
||||
|
||||
nsresult Resurrect(nsINetDataCacheRecord *aRecord);
|
||||
|
||||
nsresult CommitFlags();
|
||||
|
||||
CacheMetaData* FindTaggedMetaData(const char* aTag, PRBool aCreate);
|
||||
|
||||
private:
|
||||
|
||||
// List of nsIStreamAsFileObserver's that will receive notification events
|
||||
// when the cache manager or a client desires to delete/truncate a cache
|
||||
// entry file.
|
||||
StreamAsFileObserverClosure* mObservers;
|
||||
|
||||
// Protocol-specific meta-data, opaque to the cache manager
|
||||
CacheMetaData *mMetaData;
|
||||
|
||||
// Next in chain for a single bucket in the replacement policy hash table
|
||||
// that maps from record ID to nsCachedNetData
|
||||
nsCachedNetData* mNext;
|
||||
|
||||
// See flag bits, above
|
||||
// NOTE: 16 bit member is combined with members below for
|
||||
// struct packing efficiency. Do not change order of members!
|
||||
PRUint16 mFlags;
|
||||
|
||||
protected:
|
||||
|
||||
// Number of nsCacheEntryChannels referring to this record
|
||||
PRUint8 mChannelCount;
|
||||
|
||||
// Below members are statistics kept per cache-entry, used to decide how
|
||||
// profitable it will be to evict a record from the cache relative to other
|
||||
// existing records. Note: times are measured in *seconds* since the
|
||||
// 1/1/70 epoch, same as a unix time_t.
|
||||
|
||||
// Number of accesses for this cache record
|
||||
// NOTE: 8 bit member is combined with members above for
|
||||
// struct packing efficiency. Do not change order of members!
|
||||
PRUint8 mNumAccesses;
|
||||
|
||||
// A reference to the underlying, raw cache database record, either as a
|
||||
// pointer to an in-memory object or as a database record identifier
|
||||
union {
|
||||
nsINetDataCacheRecord* mRecord;
|
||||
|
||||
// Database record ID of associated cache record. See
|
||||
// nsINetDataCache::GetRecordByID().
|
||||
PRInt32 mRecordID;
|
||||
};
|
||||
|
||||
// Weak link to parent cache
|
||||
nsINetDataCache* mCache;
|
||||
|
||||
// Length of stored content, which may be less than storage consumed if
|
||||
// compression is used
|
||||
PRUint32 mLogicalLength;
|
||||
|
||||
// Most recent cache entry access times, used to compute access frequency
|
||||
PRUint32 mAccessTime[MAX_K];
|
||||
|
||||
// We use modification time of the original document for replacement policy
|
||||
// computations, i.e. to compute a document's age, but if we don't know it,
|
||||
// we use the time that the document was last written to the cache.
|
||||
union {
|
||||
// Document modification time, if known.
|
||||
PRUint32 mLastModifiedTime;
|
||||
|
||||
// Time of last cache update for this doc
|
||||
PRUint32 mLastUpdateTime;
|
||||
};
|
||||
|
||||
union {
|
||||
// Time until which document is fresh, i.e. does not have to be validated
|
||||
// with server and, therefore, data in cache is guaranteed usable
|
||||
PRUint32 mExpirationTime;
|
||||
|
||||
// Heuristic time at which cached document is likely to be out-of-date
|
||||
// with respect to canonical copy on server. Used for cache replacement
|
||||
// policy, not for validation.
|
||||
PRUint32 mStaleTime;
|
||||
};
|
||||
|
||||
// Download time per byte, measure roughly in units of KB/s
|
||||
float mDownloadRate;
|
||||
|
||||
// Heuristic estimate of cache entry future benefits, based on above values
|
||||
float mProfit;
|
||||
};
|
||||
|
||||
#endif // _nsCachedNetData_h_
|
||||
|
||||
666
mozilla/netwerk/cache/mgr/nsReplacementPolicy.cpp
vendored
Normal file
666
mozilla/netwerk/cache/mgr/nsReplacementPolicy.cpp
vendored
Normal file
@@ -0,0 +1,666 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Furman, fur@netscape.com
|
||||
*/
|
||||
|
||||
#include "nsReplacementPolicy.h"
|
||||
#include "nsCachedNetData.h"
|
||||
|
||||
#include "nsQuickSort.h"
|
||||
#include "nsIAllocator.h"
|
||||
#include "nsIEnumerator.h"
|
||||
#include "prtime.h"
|
||||
#include "prbit.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include <math.h>
|
||||
|
||||
// Constant used to estimate frequency of access to a document based on size
|
||||
#define CACHE_CONST_B 1.35
|
||||
|
||||
// A cache whose space is managed by this replacement policy
|
||||
class nsReplacementPolicy::CacheInfo {
|
||||
public:
|
||||
CacheInfo(nsINetDataCache* aCache):mCache(aCache),mNext(0) {}
|
||||
|
||||
nsINetDataCache* mCache;
|
||||
CacheInfo* mNext;
|
||||
};
|
||||
|
||||
nsReplacementPolicy::nsReplacementPolicy()
|
||||
: mRankedEntries(0), mCaches(0), mRecordsRemovedSinceLastRanking(0),
|
||||
mNumEntries(0), mCapacityRankedEntriesArray(0), mLastRankTime(0) {}
|
||||
|
||||
nsReplacementPolicy::~nsReplacementPolicy()
|
||||
{
|
||||
if (mRankedEntries)
|
||||
nsAllocator::Free(mRankedEntries);
|
||||
if (mMapRecordIdToEntry)
|
||||
nsAllocator::Free(mMapRecordIdToEntry);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsReplacementPolicy::Init(PRUint32 aMaxCacheEntries)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = NS_NewHeapArena(getter_AddRefs(mArena), sizeof(nsCachedNetData) * 32);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mMaxEntries = aMaxCacheEntries;
|
||||
|
||||
mHashArrayLength = PR_CeilingLog2(aMaxCacheEntries) >> 3;
|
||||
size_t numBytes = mHashArrayLength * sizeof(*mMapRecordIdToEntry);
|
||||
mMapRecordIdToEntry = (nsCachedNetData**)nsAllocator::Alloc(numBytes);
|
||||
if (!mMapRecordIdToEntry)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsCRT::zero(mMapRecordIdToEntry, numBytes);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsReplacementPolicy::AddCache(nsINetDataCache *aCache)
|
||||
{
|
||||
CacheInfo *cacheInfo = new CacheInfo(aCache);
|
||||
if (!cacheInfo)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
cacheInfo->mNext = mCaches;
|
||||
mCaches = cacheInfo;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
nsReplacementPolicy::HashRecordID(PRInt32 aRecordID)
|
||||
{
|
||||
return ((aRecordID >> 16) ^ aRecordID) & (mHashArrayLength - 1);
|
||||
}
|
||||
|
||||
nsCachedNetData*
|
||||
nsReplacementPolicy::FindCacheEntryByRecordID(PRInt32 aRecordID, nsINetDataCache *aCache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCachedNetData* cacheEntry;
|
||||
PRUint32 bucket = HashRecordID(aRecordID);
|
||||
|
||||
cacheEntry = mMapRecordIdToEntry[bucket];
|
||||
for (;cacheEntry; cacheEntry = cacheEntry->mNext) {
|
||||
|
||||
PRInt32 recordID;
|
||||
rv = cacheEntry->GetRecordID(&recordID);
|
||||
if (NS_FAILED(rv))
|
||||
continue;
|
||||
|
||||
if ((recordID == aRecordID) && (cacheEntry->mCache == aCache))
|
||||
return cacheEntry;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Add a cache entry to the hash table that maps record ID to entries
|
||||
void
|
||||
nsReplacementPolicy::AddCacheEntry(nsCachedNetData* aCacheEntry, PRInt32 aRecordID)
|
||||
{
|
||||
nsCachedNetData** cacheEntryp;
|
||||
PRUint32 bucket = HashRecordID(aRecordID);
|
||||
|
||||
cacheEntryp = &mMapRecordIdToEntry[bucket];
|
||||
while (*cacheEntryp)
|
||||
cacheEntryp = &(*cacheEntryp)->mNext;
|
||||
*cacheEntryp = aCacheEntry;
|
||||
aCacheEntry->mNext = 0;
|
||||
}
|
||||
|
||||
// Delete a cache entry from the hash table that maps record ID to entries
|
||||
nsresult
|
||||
nsReplacementPolicy::DeleteCacheEntry(nsCachedNetData* aCacheEntry)
|
||||
{
|
||||
nsresult rv;
|
||||
PRInt32 recordID;
|
||||
rv = aCacheEntry->GetRecordID(&recordID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRUint32 bucket = HashRecordID(recordID);
|
||||
|
||||
nsCachedNetData** cacheEntryp;
|
||||
cacheEntryp = &mMapRecordIdToEntry[bucket];
|
||||
while (*cacheEntryp) {
|
||||
if (*cacheEntryp == aCacheEntry) {
|
||||
*cacheEntryp = aCacheEntry->mNext;
|
||||
return NS_OK;
|
||||
}
|
||||
cacheEntryp = &(*cacheEntryp)->mNext;
|
||||
}
|
||||
|
||||
NS_ASSERTION(0, "hash table inconsistency");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsReplacementPolicy::AddAllRecordsInCache(nsINetDataCache *aCache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISimpleEnumerator> iterator;
|
||||
nsCOMPtr<nsISupports> iSupports;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
rv = aCache->NewCacheEntryIterator(getter_AddRefs(iterator));
|
||||
if (!NS_SUCCEEDED(rv)) return rv;
|
||||
|
||||
while (1) {
|
||||
PRBool notDone;
|
||||
|
||||
rv = iterator->HasMoreElements(¬Done);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!notDone)
|
||||
break;
|
||||
|
||||
rv = iterator->GetNext(getter_AddRefs(iSupports));
|
||||
if (!NS_SUCCEEDED(rv)) return rv;
|
||||
record = do_QueryInterface(iSupports);
|
||||
|
||||
rv = AssociateCacheEntryWithRecord(record, aCache, 0);
|
||||
if (!NS_SUCCEEDED(rv)) return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Get current time and convert to seconds since the epoch
|
||||
static PRUint32
|
||||
now32()
|
||||
{
|
||||
double nowFP;
|
||||
PRInt64 now64 = PR_Now();
|
||||
LL_L2D(nowFP, now64);
|
||||
PRUint32 now = (PRUint32)(nowFP * 1e-6);
|
||||
return now;
|
||||
}
|
||||
|
||||
void
|
||||
nsCachedNetData::NoteDownloadTime(PRTime start, PRTime end)
|
||||
{
|
||||
double startFP, endFP, rate, duration;
|
||||
|
||||
LL_L2D(startFP, start);
|
||||
LL_L2D(endFP, end);
|
||||
|
||||
duration = endFP - startFP;
|
||||
|
||||
// If the data arrives so fast that it can not be timed due to the clock
|
||||
// granularity, assume a data arrival duration of 10 ms
|
||||
if (!duration)
|
||||
duration = 10000;
|
||||
|
||||
// Compute download rate in kB/s
|
||||
rate = mLogicalLength / (duration * (1e-6 * 1024.0));
|
||||
|
||||
if (mDownloadRate) {
|
||||
// Exponentially smooth download rate
|
||||
const double alpha = 0.5;
|
||||
mDownloadRate = (float)(mDownloadRate * alpha + rate * (1.0 - alpha));
|
||||
} else {
|
||||
mDownloadRate = (float)rate;
|
||||
}
|
||||
}
|
||||
|
||||
// 1 hour
|
||||
#define MIN_HALFLIFE (60 * 60)
|
||||
|
||||
// 1 week
|
||||
#define TYPICAL_HALFLIFE (7 * 24 * 60 * 60)
|
||||
|
||||
/**
|
||||
* Estimate the profit that would be lost if the given cache entry was evicted
|
||||
* from the cache. Profit is defined as the future expected download delay per
|
||||
* byte of cached content. The profit computation is made based on projected
|
||||
* frequency of access, prior download performance and a heuristic staleness
|
||||
* criteria. The technique used is a variation of that described in the
|
||||
* following paper:
|
||||
*
|
||||
* "A Case for Delay-Conscious Caching of Web Documents"
|
||||
* http://www.bell-labs.com/user/rvingral/www97.html
|
||||
*
|
||||
* Briefly, expected profit is:
|
||||
*
|
||||
* (projected frequency of access) * (download time per byte) * (probability freshness)
|
||||
*/
|
||||
void
|
||||
nsCachedNetData::ComputeProfit(PRUint32 aNow)
|
||||
{
|
||||
PRUint32 K, now;
|
||||
|
||||
if (aNow)
|
||||
now = aNow;
|
||||
else
|
||||
now = now32();
|
||||
|
||||
K = PR_MIN(MAX_K, mNumAccesses);
|
||||
if (!K) {
|
||||
mProfit = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Compute time, in seconds, since k'th most recent access
|
||||
double timeSinceKthAccess = now - mAccessTime[K - 1];
|
||||
if (timeSinceKthAccess <= 0.0) // Sanity check
|
||||
timeSinceKthAccess = 1.0;
|
||||
|
||||
// Estimate frequency of future document access based on past
|
||||
// access frequency
|
||||
double frequencyAccess = K / timeSinceKthAccess;
|
||||
|
||||
// If we don't have much historical data on access frequency
|
||||
// use a heuristic based on document size as an estimate
|
||||
if (mLogicalLength) {
|
||||
if (K == 1) {
|
||||
frequencyAccess /= pow(mLogicalLength, CACHE_CONST_B);
|
||||
} else if (K == 2) {
|
||||
frequencyAccess /= pow(mLogicalLength, CACHE_CONST_B / 2);
|
||||
}
|
||||
}
|
||||
|
||||
// Estimate likelihood that data in cache is fresh, i.e.
|
||||
// that it corresponds to the document on the server
|
||||
double probabilityFreshness;
|
||||
PRInt32 halfLife, age, docTime;
|
||||
PRBool potentiallyStale;
|
||||
|
||||
docTime = GetFlag(LAST_MODIFIED_KNOWN) ? mLastModifiedTime : mLastUpdateTime;
|
||||
age = now - docTime;
|
||||
|
||||
probabilityFreshness = 1.0; // Optimistic
|
||||
|
||||
if (GetFlag(EXPIRATION_KNOWN)) {
|
||||
potentiallyStale = now > mExpirationTime;
|
||||
halfLife = mExpirationTime - mLastModifiedTime;
|
||||
} else if (GetFlag(STALE_TIME_KNOWN)) {
|
||||
potentiallyStale = PR_TRUE;
|
||||
halfLife = mStaleTime - docTime;
|
||||
} else {
|
||||
potentiallyStale = PR_TRUE;
|
||||
halfLife = TYPICAL_HALFLIFE;
|
||||
}
|
||||
|
||||
if (potentiallyStale) {
|
||||
if (halfLife < MIN_HALFLIFE)
|
||||
halfLife = MIN_HALFLIFE;
|
||||
|
||||
probabilityFreshness = pow(0.5, (double)age / (double)halfLife);
|
||||
}
|
||||
|
||||
mProfit = (float)(frequencyAccess * probabilityFreshness);
|
||||
if (mDownloadRate)
|
||||
mProfit /= mDownloadRate;
|
||||
}
|
||||
|
||||
// Number of entries to grow mRankedEntries array when it's full
|
||||
#define STATS_GROWTH_INCREMENT 256
|
||||
|
||||
|
||||
// Sorting predicate for NS_Quicksort
|
||||
int
|
||||
nsCachedNetData::Compare(const void *a, const void *b, void *unused)
|
||||
{
|
||||
nsCachedNetData* entryA = *(nsCachedNetData**)a;
|
||||
nsCachedNetData* entryB = *(nsCachedNetData**)b;
|
||||
|
||||
// Percolate deleted or empty entries to the end of the mRankedEntries
|
||||
// array, so that they can be recycled.
|
||||
if (!entryA || entryA->GetFlag(RECYCLED)) {
|
||||
if (!entryB || entryB->GetFlag(RECYCLED))
|
||||
return 0;
|
||||
else
|
||||
return +1;
|
||||
}
|
||||
if (!entryB || entryB->GetFlag(RECYCLED))
|
||||
return -1;
|
||||
|
||||
// Evicted entries (those with no content data) and active entries (those
|
||||
// currently being updated) are collected towards the end of the sorted
|
||||
// array just prior to the deleted cache entries, since evicted entries
|
||||
// can't be re-evicted.
|
||||
if (entryA->GetFlag(UPDATE_IN_PROGRESS)) {
|
||||
if (entryB->GetFlag(UPDATE_IN_PROGRESS))
|
||||
return 0;
|
||||
else
|
||||
return +1;
|
||||
}
|
||||
if (entryB->GetFlag(UPDATE_IN_PROGRESS))
|
||||
return -1;
|
||||
|
||||
PRUint16 Ka = PR_MIN(MAX_K, entryA->mNumAccesses);
|
||||
PRUint16 Kb = PR_MIN(MAX_K, entryB->mNumAccesses);
|
||||
|
||||
// Order cache entries by the number of times they've been accessed
|
||||
if (Ka < Kb)
|
||||
return -1;
|
||||
if (Ka > Kb)
|
||||
return +1;
|
||||
|
||||
/*
|
||||
* Among records that have been accessed an equal number of times, order
|
||||
* them by profit.
|
||||
*/
|
||||
if (entryA->mProfit > entryB->mProfit)
|
||||
return +1;
|
||||
if (entryA->mProfit < entryB->mProfit)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rank cache entries in terms of their elegibility for eviction.
|
||||
*/
|
||||
nsresult
|
||||
nsReplacementPolicy::RankRecords()
|
||||
{
|
||||
PRUint32 i, now;
|
||||
|
||||
// Add all cache records if this is the first ranking
|
||||
if (!mLastRankTime) {
|
||||
nsresult rv;
|
||||
CacheInfo *cacheInfo;
|
||||
|
||||
cacheInfo = mCaches;
|
||||
while (cacheInfo) {
|
||||
rv = AddAllRecordsInCache(cacheInfo->mCache);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
cacheInfo = cacheInfo->mNext;
|
||||
}
|
||||
}
|
||||
|
||||
// Get current time and convert to seconds since the epoch
|
||||
now = now32();
|
||||
|
||||
// Recompute profit for every known cache record, except deleted ones
|
||||
for (i = 0; i < mNumEntries; i++) {
|
||||
nsCachedNetData* entry = mRankedEntries[i];
|
||||
if (entry && !entry->GetFlag(nsCachedNetData::RECYCLED))
|
||||
entry->ComputeProfit(now);
|
||||
}
|
||||
NS_QuickSort(mRankedEntries, mNumEntries, sizeof *mRankedEntries,
|
||||
nsCachedNetData::Compare, 0);
|
||||
|
||||
mNumEntries -= mRecordsRemovedSinceLastRanking;
|
||||
mRecordsRemovedSinceLastRanking = 0;
|
||||
mLastRankTime = now;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// A heuristic policy to avoid the cost of re-ranking cache records by
|
||||
// profitability every single time space must be made available in the cache.
|
||||
void
|
||||
nsReplacementPolicy::MaybeRerankRecords()
|
||||
{
|
||||
// Rank at most once per minute
|
||||
PRUint32 now = now32();
|
||||
if ((now - mLastRankTime) >= 60)
|
||||
RankRecords();
|
||||
}
|
||||
|
||||
void
|
||||
nsReplacementPolicy::CompactRankedEntriesArray()
|
||||
{
|
||||
if (mRecordsRemovedSinceLastRanking || !mLastRankTime)
|
||||
RankRecords();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsReplacementPolicy::CheckForTooManyCacheEntries()
|
||||
{
|
||||
if (mCapacityRankedEntriesArray == mMaxEntries) {
|
||||
return DeleteOneEntry(0);
|
||||
} else {
|
||||
nsresult rv;
|
||||
CacheInfo *cacheInfo;
|
||||
|
||||
cacheInfo = mCaches;
|
||||
while (cacheInfo) {
|
||||
PRUint32 numEntries, maxEntries;
|
||||
|
||||
rv = cacheInfo->mCache->GetNumEntries(&numEntries);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = cacheInfo->mCache->GetMaxEntries(&maxEntries);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (numEntries == maxEntries)
|
||||
return DeleteOneEntry(cacheInfo->mCache);
|
||||
|
||||
cacheInfo = cacheInfo->mNext;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new association between a low-level cache database record and a
|
||||
* cache entry. Add the entry to the set of entries eligible for eviction from
|
||||
* the cache. This would typically be done when the cache entry is created.
|
||||
*/
|
||||
nsresult
|
||||
nsReplacementPolicy::AssociateCacheEntryWithRecord(nsINetDataCacheRecord *aRecord,
|
||||
nsINetDataCache* aCache,
|
||||
nsCachedNetData** aResult)
|
||||
{
|
||||
nsCachedNetData* cacheEntry;
|
||||
nsresult rv;
|
||||
|
||||
// First, see if the record is already known to the replacement policy
|
||||
PRInt32 recordID;
|
||||
rv = aRecord->GetRecordID(&recordID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
cacheEntry = FindCacheEntryByRecordID(recordID, aCache);
|
||||
if (cacheEntry) {
|
||||
if (aResult) {
|
||||
if (cacheEntry->GetFlag(nsCachedNetData::DORMANT))
|
||||
cacheEntry->Resurrect(aRecord);
|
||||
NS_ADDREF(cacheEntry);
|
||||
*aResult = cacheEntry;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Compact the array of cache entry statistics, so that free entries appear
|
||||
// at the end, for possible reuse.
|
||||
if (mNumEntries && (mNumEntries == mCapacityRankedEntriesArray))
|
||||
CompactRankedEntriesArray();
|
||||
|
||||
// If compaction doesn't yield available entries in the
|
||||
// mRankedEntries array, then extend the array.
|
||||
if (mNumEntries == mCapacityRankedEntriesArray) {
|
||||
PRUint32 newCapacity;
|
||||
|
||||
rv = CheckForTooManyCacheEntries();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
newCapacity = mCapacityRankedEntriesArray + STATS_GROWTH_INCREMENT;
|
||||
if (newCapacity > mMaxEntries)
|
||||
newCapacity = mMaxEntries;
|
||||
|
||||
nsCachedNetData** newRankedEntriesArray;
|
||||
PRUint32 numBytes = sizeof(nsCachedNetData*) * newCapacity;
|
||||
newRankedEntriesArray =
|
||||
(nsCachedNetData**)nsAllocator::Realloc(mRankedEntries, numBytes);
|
||||
if (!newRankedEntriesArray)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
mRankedEntries = newRankedEntriesArray;
|
||||
mCapacityRankedEntriesArray = newCapacity;
|
||||
|
||||
PRUint32 i;
|
||||
for (i = mNumEntries; i < newCapacity; i++)
|
||||
mRankedEntries[i] = 0;
|
||||
}
|
||||
|
||||
// Recycle the record after the last in-use record in the array
|
||||
nsCachedNetData *entry = mRankedEntries[mNumEntries];
|
||||
NS_ASSERTION(!entry || !entry->GetFlag(nsCachedNetData::RECYCLED),
|
||||
"Only deleted cache entries should appear at end of array");
|
||||
|
||||
if (!entry) {
|
||||
entry = new(mArena) nsCachedNetData;
|
||||
if (!entry)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
mRankedEntries[mNumEntries] = entry;
|
||||
} else {
|
||||
// Clear out recycled data structure
|
||||
nsCRT::zero(entry, sizeof(*entry));
|
||||
}
|
||||
|
||||
entry->Init(aRecord, aCache);
|
||||
AddCacheEntry(entry, recordID);
|
||||
|
||||
// Add one reference to the cache entry from the cache manager
|
||||
NS_ADDREF(entry);
|
||||
|
||||
if (aResult) {
|
||||
// And one reference from our caller
|
||||
NS_ADDREF(entry);
|
||||
*aResult = entry;
|
||||
}
|
||||
|
||||
mNumEntries++;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsReplacementPolicy::GetCachedNetData(const char* cacheKey, PRUint32 cacheKeyLength,
|
||||
nsINetDataCache* aCache,
|
||||
nsCachedNetData** aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
|
||||
rv = aCache->GetCachedNetData(cacheKey, cacheKeyLength,
|
||||
getter_AddRefs(record));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
return AssociateCacheEntryWithRecord(record, aCache, aResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the least desirable record from the cache database. This is used
|
||||
* when the addition of another record would exceed either the cache manager or
|
||||
* the cache's maximum permitted number of records.
|
||||
*/
|
||||
nsresult
|
||||
nsReplacementPolicy::DeleteOneEntry(nsINetDataCache *aCache)
|
||||
{
|
||||
PRUint32 i;
|
||||
nsresult rv;
|
||||
nsCachedNetData *entry;
|
||||
|
||||
i = 0;
|
||||
while (1) {
|
||||
MaybeRerankRecords();
|
||||
for (; i < mNumEntries; i++) {
|
||||
entry = mRankedEntries[i];
|
||||
if (!entry || entry->GetFlag(nsCachedNetData::RECYCLED))
|
||||
continue;
|
||||
if (!aCache || (entry->mCache == aCache))
|
||||
break;
|
||||
}
|
||||
|
||||
// Report error if no record found to delete
|
||||
if (i == mNumEntries)
|
||||
return NS_ERROR_FAILURE;
|
||||
rv = entry->Delete();
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = DeleteCacheEntry(entry);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsReplacementPolicy::GetStorageInUse(PRUint32* aStorageInUse)
|
||||
{
|
||||
nsresult rv;
|
||||
CacheInfo *cacheInfo;
|
||||
|
||||
*aStorageInUse = 0;
|
||||
cacheInfo = mCaches;
|
||||
while (cacheInfo) {
|
||||
PRUint32 cacheStorage;
|
||||
rv = cacheInfo->mCache->GetStorageInUse(&cacheStorage);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
*aStorageInUse += cacheStorage;
|
||||
cacheInfo = cacheInfo->mNext;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the least desirable records from the cache until the occupancy of the
|
||||
* cache has been reduced by the given number of KB. This is used when the
|
||||
* addition of more cache data would exceed the cache's capacity.
|
||||
*/
|
||||
nsresult
|
||||
nsReplacementPolicy::Evict(PRUint32 aTargetOccupancy)
|
||||
{
|
||||
PRUint32 i;
|
||||
nsCachedNetData *entry;
|
||||
nsresult rv;
|
||||
PRUint32 occupancy;
|
||||
PRInt32 truncatedLength;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
|
||||
MaybeRerankRecords();
|
||||
for (i = 0; i < mNumEntries; i++) {
|
||||
rv = GetStorageInUse(&occupancy);
|
||||
if (!NS_SUCCEEDED(rv)) return rv;
|
||||
|
||||
if (occupancy <= aTargetOccupancy)
|
||||
return NS_OK;
|
||||
|
||||
entry = mRankedEntries[i];
|
||||
|
||||
// Skip deleted/empty cache entries and ones that have already been evicted
|
||||
if (!entry || entry->GetFlag(nsCachedNetData::UNEVICTABLE))
|
||||
continue;
|
||||
|
||||
if (entry->GetFlag(nsCachedNetData::ALLOW_PARTIAL)) {
|
||||
rv = entry->GetRecord(getter_AddRefs(record));
|
||||
if (NS_FAILED(rv))
|
||||
continue;
|
||||
|
||||
PRUint32 contentLength;
|
||||
rv = record->GetStoredContentLength(&contentLength);
|
||||
if (NS_FAILED(rv))
|
||||
continue;
|
||||
|
||||
// Additional cache storage required, in KB
|
||||
PRUint32 storageToReclaim = (occupancy - aTargetOccupancy) << 10;
|
||||
|
||||
truncatedLength = (PRInt32)(contentLength - storageToReclaim);
|
||||
if (truncatedLength < 0)
|
||||
truncatedLength = 0;
|
||||
} else {
|
||||
truncatedLength = 0;
|
||||
}
|
||||
rv = entry->Evict(truncatedLength);
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
136
mozilla/netwerk/cache/mgr/nsReplacementPolicy.h
vendored
Normal file
136
mozilla/netwerk/cache/mgr/nsReplacementPolicy.h
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Furman, fur@netscape.com
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class manages one or more caches that share a storage resource, e.g. a
|
||||
* file cache and a flat-database cache might each occupy space on the disk and
|
||||
* they would share a single instance of nsReplacementPolicy. The replacement
|
||||
* policy heuristically chooses which cache entries to evict when storage is
|
||||
* required to accommodate incoming cache data.
|
||||
*/
|
||||
|
||||
#ifndef _nsReplacementPolicy_h_
|
||||
#define _nsReplacementPolicy_h_
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsISupportsUtils.h"
|
||||
#include "nsINetDataCache.h"
|
||||
#include "nsICachedNetData.h"
|
||||
#include "nsIArena.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsHashtable.h"
|
||||
|
||||
class nsCachedNetData;
|
||||
struct PL_HashTable;
|
||||
|
||||
/**
|
||||
* This private class is responsible for implementing the network data cache's
|
||||
* replacement policy, i.e. it decides which cache data should be evicted to
|
||||
* make room for new incoming data.
|
||||
*/
|
||||
class nsReplacementPolicy {
|
||||
|
||||
public:
|
||||
|
||||
nsReplacementPolicy();
|
||||
~nsReplacementPolicy();
|
||||
|
||||
protected:
|
||||
|
||||
nsresult Init(PRUint32 aMaxCacheEntries);
|
||||
nsresult AddCache(nsINetDataCache *aCache);
|
||||
nsresult GetCachedNetData(const char* cacheKey, PRUint32 cacheKeyLength,
|
||||
nsINetDataCache* aCache,
|
||||
nsCachedNetData** aResult);
|
||||
nsresult GetStorageInUse(PRUint32* aNumKBytes);
|
||||
|
||||
friend class nsCacheManager;
|
||||
|
||||
private:
|
||||
nsresult RankRecords();
|
||||
void MaybeRerankRecords();
|
||||
void CompactRankedEntriesArray();
|
||||
nsresult DeleteOneEntry(nsINetDataCache* aCache);
|
||||
nsresult Evict(PRUint32 aTargetOccupancy);
|
||||
|
||||
nsCachedNetData* FindCacheEntryByRecordID(PRInt32 aRecordID, nsINetDataCache *aCache);
|
||||
void AddCacheEntry(nsCachedNetData* aCacheEntry, PRInt32 aRecordID);
|
||||
nsresult DeleteCacheEntry(nsCachedNetData* aCacheEntry);
|
||||
PRUint32 HashRecordID(PRInt32 aRecordID);
|
||||
nsresult AssociateCacheEntryWithRecord(nsINetDataCacheRecord *aRecord,
|
||||
nsINetDataCache* aCache,
|
||||
nsCachedNetData** aResult);
|
||||
|
||||
nsresult AddAllRecordsInCache(nsINetDataCache *aCache);
|
||||
nsresult CheckForTooManyCacheEntries();
|
||||
|
||||
class CacheInfo;
|
||||
|
||||
private:
|
||||
|
||||
// Growable array of pointers to individual cache entries; It is sorted by
|
||||
// profitability, such that low-numbered array indices refer to cache
|
||||
// entries that are the least profitable to retain. New cache entries are
|
||||
// added to the end of the array. Deleted cache entries are specially
|
||||
// marked and percolate to the end of the array for recycling whenever
|
||||
// mRankedEntries is sorted. Evicted cache entries (those with no
|
||||
// associated content data) are retained for the purpose of improving the
|
||||
// replacement policy efficacy, and are percolated towards the end of the
|
||||
// array, just prior to the deleted cache entries.
|
||||
//
|
||||
// The array is not in sorted order 100% of the time; For efficiency
|
||||
// reasons, sorting is only done when heuristically deemed necessary.
|
||||
nsCachedNetData** mRankedEntries;
|
||||
|
||||
// Hash table buckets to map Record ID to cache entry. We use this instead
|
||||
// of a PL_HashTable to reduce storage requirements
|
||||
nsCachedNetData** mMapRecordIdToEntry;
|
||||
|
||||
// Length of mMapRecordIdToEntry array
|
||||
PRUint32 mHashArrayLength;
|
||||
|
||||
// Linked list of caches that share this replacement policy
|
||||
CacheInfo* mCaches;
|
||||
|
||||
// Allocation area for cache entry (nsCachedNetData) instances
|
||||
nsCOMPtr<nsIArena> mArena;
|
||||
|
||||
// Bookkeeping
|
||||
PRUint32 mRecordsRemovedSinceLastRanking;
|
||||
|
||||
// Maximum permitted length of mRankedEntries array
|
||||
PRUint32 mMaxEntries;
|
||||
|
||||
// Number of occupied slots in mRankedEntries array
|
||||
PRUint32 mNumEntries;
|
||||
|
||||
// Capacity of mRankedEntries array
|
||||
PRUint32 mCapacityRankedEntriesArray;
|
||||
|
||||
// Time at which cache entries were last ranked by profitability
|
||||
PRUint32 mLastRankTime;
|
||||
};
|
||||
|
||||
|
||||
#endif // _nsReplacementPolicy_h_
|
||||
43
mozilla/netwerk/cache/public/Makefile.in
vendored
Normal file
43
mozilla/netwerk/cache/public/Makefile.in
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
#
|
||||
# The contents of this file are subject to the Netscape 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/NPL/
|
||||
#
|
||||
# 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 mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
MODULE = nkcache
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsICachedNetData.idl \
|
||||
nsINetDataCacheManager.idl \
|
||||
nsINetDataCache.idl \
|
||||
nsINetDataCacheRecord.idl \
|
||||
nsINetDataDiskCache.idl \
|
||||
nsIStreamAsFile.idl \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
41
mozilla/netwerk/cache/public/Makefile.win
vendored
Executable file
41
mozilla/netwerk/cache/public/Makefile.win
vendored
Executable file
@@ -0,0 +1,41 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape 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/NPL/
|
||||
#
|
||||
# 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 mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
|
||||
MODULE = nkcache
|
||||
|
||||
DEPTH = ..\..\..
|
||||
include <$(DEPTH)/config/config.mak>
|
||||
|
||||
|
||||
EXPORTS = \
|
||||
$(NULL)
|
||||
|
||||
XPIDLSRCS = \
|
||||
.\nsICachedNetData.idl \
|
||||
.\nsINetDataCacheManager.idl \
|
||||
.\nsINetDataCache.idl \
|
||||
.\nsINetDataCacheRecord.idl \
|
||||
.\nsINetDataDiskCache.idl \
|
||||
.\nsIStreamAsFile.idl \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)/config/rules.mak>
|
||||
|
||||
229
mozilla/netwerk/cache/public/nsICachedNetData.idl
vendored
Normal file
229
mozilla/netwerk/cache/public/nsICachedNetData.idl
vendored
Normal file
@@ -0,0 +1,229 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsrootidl.idl"
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIFileSpec;
|
||||
interface nsIURI;
|
||||
interface nsIObserver;
|
||||
interface nsIChannel;
|
||||
interface nsINetDataCache;
|
||||
interface nsINetDataCacheRecord;
|
||||
interface nsILoadGroup;
|
||||
interface nsIStreamListener;
|
||||
|
||||
/**
|
||||
* The nsICachedNetData interface represents a single entry in a database that
|
||||
* caches data retrieved from the network. This interface is implemented by the
|
||||
* cache manager on top of the low-level nsINetDataCacheRecord and
|
||||
* nsINetDataCache interfaces that are implemented by the database.
|
||||
*
|
||||
* Each cache record may contain both content and metadata. The content may
|
||||
* be, for example, GIF image data or HTML, and it is accessed through
|
||||
* nsIChannel's streaming API. The opaque metadata, which may contain HTTP
|
||||
* headers among other things, is stored as a byte array. Each entry in the
|
||||
* cache is indexed by two different keys: a record id number and a key created
|
||||
* by combining the URI with a "secondary key", e.g. HTTP post data.
|
||||
*
|
||||
* @See nsINetDataCacheRecord
|
||||
* @See nsINetDataCache
|
||||
* @See nsINetDataDiskCache
|
||||
* @See nsINetDataCacheManager
|
||||
*/
|
||||
[scriptable, uuid(6aeb2a40-6d43-11d3-90c8-000064657374)]
|
||||
interface nsICachedNetData : nsISupports
|
||||
{
|
||||
/**
|
||||
* String form of the URI provided as an argument to the call to
|
||||
* nsINetDataCacheManager::GetCachedNetData() that created this record.
|
||||
*/
|
||||
readonly attribute string uriSpec;
|
||||
|
||||
/**
|
||||
* Getter for the opaque secondary database key provided as an argument to
|
||||
* the call to nsINetDataCacheManager::GetCachedNetData() that created this
|
||||
* record.
|
||||
*/
|
||||
void getSecondaryKey(out unsigned long length,
|
||||
[retval, size_is(length)] out string secondaryKey);
|
||||
|
||||
/**
|
||||
* This flag may be set by a protocol handler to indicate that it supports
|
||||
* partial fetching of data. In that case, the cache manager is permitted
|
||||
* to truncate the entry's content to accommodate incoming data for other
|
||||
* cache entries rather than deleting it wholesale.
|
||||
*/
|
||||
attribute boolean allowPartial;
|
||||
|
||||
/**
|
||||
* This flag indicates that the write stream supplying content data for the
|
||||
* cache did not complete normally and, therefore, the content may be
|
||||
* truncated.
|
||||
*/
|
||||
readonly attribute boolean partialFlag;
|
||||
|
||||
/**
|
||||
* This flag can be set and cleared by a protocol handler as a form of
|
||||
* self-notification, so as to avoid race conditions in which a protocol
|
||||
* handler issues two identical network requests to fill the same cache
|
||||
* entry. The cache manager itself largely ignores this flag.
|
||||
*/
|
||||
attribute boolean updateInProgress;
|
||||
|
||||
/**
|
||||
* inUse is set if any existing channels are associated with this cache
|
||||
* entry or if the updateInProgess flag is set. This can be used to
|
||||
* prevent writing to a cache entry by a protocol handler if it's being
|
||||
* read or written elsewhere.
|
||||
*/
|
||||
readonly attribute boolean inUse;
|
||||
|
||||
/**
|
||||
* Date/time that the document was last stored on the origin server, as
|
||||
* supplied by the protocol handler. This value is used as input to the
|
||||
* cache replacement policy, i.e. it is not used for validation. If the
|
||||
* protocol can't supply a last-modified time, this attribute should remain
|
||||
* unset. When unset, the value of this attribute is zero.
|
||||
*
|
||||
* FIXME: Should use nsIDateTime interface, once it's created
|
||||
* instead of PRTime, for improved scriptability ?
|
||||
*/
|
||||
attribute PRTime lastModifiedTime;
|
||||
|
||||
/**
|
||||
* Supplied by the protocol handler, the expirationTime attribute specifies
|
||||
* the time until which the document is guaranteed fresh, i.e. the document
|
||||
* does not have to be validated with the server and, therefore, any data
|
||||
* in cache is definitely usable. The value of this attribute serves as a
|
||||
* hint to the cache replacement policy. Only one of either staleTime or
|
||||
* expirationTime may be set for a single cache record. When unset, the
|
||||
* value of this attribute is zero.
|
||||
*/
|
||||
attribute PRTime expirationTime;
|
||||
|
||||
/**
|
||||
* Date/time supplied by the protocol handler, at which point the content
|
||||
* is *likely* to be stale, i.e. the data in the cache may be out-of-date
|
||||
* with respect to the data on the server. This heuristic date does not
|
||||
* necessarily correspond to the HTTP Expires header, as it does not
|
||||
* determine when cached network data must be validated with the origin
|
||||
* server, but only serves as a hint to the cache replacement policy. Only
|
||||
* one of either staleTime or expirationTime may be set for a single cache
|
||||
* record. When unset, the value of this attribute is zero.
|
||||
*/
|
||||
attribute PRTime staleTime;
|
||||
|
||||
/**
|
||||
* Date/time of last access of the data in this cache record, as determined
|
||||
* by the cache manager.
|
||||
*/
|
||||
readonly attribute PRTime lastAccessTime;
|
||||
|
||||
/**
|
||||
* Number of times this record has been accessed since it was first stored.
|
||||
*/
|
||||
readonly attribute PRUint16 numberAccesses;
|
||||
|
||||
/**
|
||||
* Accessor methods for opaque meta-data which can be read and updated
|
||||
* independently of the content data.
|
||||
*
|
||||
* The aTag argument can be used to accommodate multiple clients of the
|
||||
* cache API, each of which wants to store its own private meta-data into
|
||||
* the cache. For example, there could be a "headers" tag that the HTTP
|
||||
* protocol handler uses to store http response headers and a "image size"
|
||||
* tag used to store the image dimensions of a GIF file. The aData
|
||||
* argument refers to an opaque blob of arbitrary bytes.
|
||||
*
|
||||
* IMPORTANT: If aData does not contain byte-oriented data, i.e. it's not a
|
||||
* string, the contents of aData must be byte-swapped by the,
|
||||
* caller, so as to make the cache files endian-independent.
|
||||
*/
|
||||
void getAnnotation(in string aTag,
|
||||
out PRUint32 aLength, [size_is(aLength), retval] out string aData);
|
||||
void setAnnotation(in string aTag,
|
||||
in PRUint32 aLength, [size_is(aLength)] in string aData);
|
||||
|
||||
/**
|
||||
* As a getter, return the number of content bytes stored in the cache,
|
||||
* i.e. via the nsIChannel streaming APIs. This may be less than the
|
||||
* complete content length if a partial cache fill occurred. The cached
|
||||
* content can be truncated by setting the value of this attribute. The
|
||||
* value of the attribute represents a logical, not a physical, length. If
|
||||
* compression has been used, the content may consume less storage than
|
||||
* indicated by this attribute.
|
||||
*
|
||||
* When this attribute is set to zero the associated cache disk file, if
|
||||
* any, should be deleted.
|
||||
*/
|
||||
attribute PRUint32 storedContentLength;
|
||||
|
||||
/**
|
||||
* Notify any observers associated with this cache entry of the deletion
|
||||
* request. If all observers drop their reference to the cache entry,
|
||||
* proceed to delete the underlying cache database record and associated
|
||||
* content storage.
|
||||
*/
|
||||
void delete();
|
||||
|
||||
/**
|
||||
* Flush any changes in this entry's data to the cache database. This
|
||||
* method will automatically be called when the last reference to the cache
|
||||
* is dropped, but it can also be called explicitly for a synchronous
|
||||
* effect.
|
||||
*/
|
||||
void commit();
|
||||
|
||||
/**
|
||||
* Parent container cache for this entry.
|
||||
*/
|
||||
readonly attribute nsINetDataCache cache;
|
||||
|
||||
/**
|
||||
* Create a channel for reading or writing a stream of content into the
|
||||
* entry. It is expected that many of the nsIChannel methods return
|
||||
* NS_NOT_IMPLEMENTED, including:
|
||||
*
|
||||
* + GetURI()
|
||||
* + GetContentType()
|
||||
* + GetContentLength()
|
||||
*
|
||||
* Though nsIChannel provides for both async and synchronous I/O APIs, both
|
||||
* may not be implemented. Only AsyncRead() and OpenOutputStream() is
|
||||
* required. The aProxyChannel argument allows another channel to be
|
||||
* specified as the proffered argument to nsIStreamListener methods rather
|
||||
* than the cache's own channel.
|
||||
*/
|
||||
nsIChannel newChannel(in nsILoadGroup aLoadGroup,
|
||||
in nsIChannel aProxyChannel);
|
||||
|
||||
/**
|
||||
* This method can be used by a caching protocol handler to store data in
|
||||
* the cache by forking an asynchronous read stream so that it is
|
||||
* simultaneously sent to a requester and written into the cache. This
|
||||
* method implicitly sets the updateInProgress flag, if it has not already
|
||||
* been set.
|
||||
*/
|
||||
nsIStreamListener interceptAsyncRead(in nsIStreamListener aOriginalListener,
|
||||
in PRUint32 aStartOffset);
|
||||
};
|
||||
143
mozilla/netwerk/cache/public/nsINetDataCache.idl
vendored
Normal file
143
mozilla/netwerk/cache/public/nsINetDataCache.idl
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIURI;
|
||||
interface nsINetDataCacheRecord;
|
||||
interface nsISimpleEnumerator;
|
||||
interface nsIFileSpec;
|
||||
|
||||
/**
|
||||
* The nsINetDataCache defines the low-level API for a network-data
|
||||
* cache, used to cache the responses to network retrieval commands.
|
||||
* This interface, along with nsINetDataCacheRecord, is implemented by
|
||||
* the memory cache, the file cache and, optionally, by some extension
|
||||
* caches. This interface is essentially a pseudo-private API for the
|
||||
* cache manager. Other clients should never use this interface.
|
||||
*
|
||||
* Each cache entry may contain both content, e.g. GIF image data, and
|
||||
* associated metadata, e.g. HTTP headers. Each entry is indexed by two
|
||||
* different keys: a record id number and a key created by combining the URI
|
||||
* with a "secondary key", e.g. HTTP post data.
|
||||
*
|
||||
* The nsINetDataCache interface is agnostic as to where the data is
|
||||
* stored and whether the storage is volatile or persistent. The
|
||||
* memory cache, any disk caches and any extension caches must all
|
||||
* implement this interface.
|
||||
*
|
||||
*/
|
||||
[scriptable, uuid(ccfc58c0-6dde-11d3-90c8-000064657374)]
|
||||
interface nsINetDataCache : nsISupports
|
||||
{
|
||||
/**
|
||||
* Human-readable description of the cache module, e.g. "Disk Cache"
|
||||
*/
|
||||
readonly attribute wstring description;
|
||||
|
||||
/**
|
||||
* Returns true if cached data is available for the given opaque key,
|
||||
* even if only partial data is stored.
|
||||
*/
|
||||
boolean contains([size_is(length)] in string key, in PRUint32 length);
|
||||
|
||||
/**
|
||||
* Fetch the cache entry record for the given opaque key. If one does not
|
||||
* exist, create a new, empty record.
|
||||
*/
|
||||
nsINetDataCacheRecord getCachedNetData([size_is(length)] in string key,
|
||||
in PRUint32 length);
|
||||
|
||||
/**
|
||||
* Fetch the cache entry record for the given URI using the record ID as a key.
|
||||
*/
|
||||
nsINetDataCacheRecord getCachedNetDataByID(in PRInt32 RecordID);
|
||||
|
||||
/**
|
||||
* False indicates that this cache is entirely bypassed.
|
||||
*/
|
||||
attribute boolean enabled;
|
||||
|
||||
/**
|
||||
* Constants for flags attribute, below
|
||||
*/
|
||||
|
||||
// Used for extension caches, e.g. a CD-ROM cache
|
||||
const long READ_ONLY = 1 << 0;
|
||||
|
||||
// One of these bits must be set
|
||||
const long MEMORY_CACHE = 1 << 1;
|
||||
const long FLAT_FILE_CACHE = 1 << 2;
|
||||
const long FILE_PER_URL_CACHE = 1 << 3;
|
||||
|
||||
/**
|
||||
* See constants defined above.
|
||||
*/
|
||||
readonly attribute PRUint32 flags;
|
||||
|
||||
/**
|
||||
* Total number of URI entries stored in the cache.
|
||||
*/
|
||||
readonly attribute PRUint32 numEntries;
|
||||
|
||||
/**
|
||||
* Maximum number of URI entries that may be stored in the cache.
|
||||
*/
|
||||
readonly attribute PRUint32 maxEntries;
|
||||
|
||||
/**
|
||||
* Enumerate the URI entries stored in the cache.
|
||||
*/
|
||||
nsISimpleEnumerator newCacheEntryIterator();
|
||||
|
||||
/**
|
||||
* Contains a reference to the next cache in search order. For the memory
|
||||
* cache, this attribute always references the disk cache. For the disk
|
||||
* cache, it contains a reference to the first extension cache.
|
||||
*/
|
||||
attribute nsINetDataCache nextCache;
|
||||
|
||||
/**
|
||||
* An estimate of the amount of storage occupied by the cache, in kB.
|
||||
* Actual use may be slightly higher than reported due to cache overhead
|
||||
* and heap fragmentation (in the memory cache) or block quantization (in
|
||||
* the disk cache).
|
||||
*/
|
||||
readonly attribute PRUint32 storageInUse;
|
||||
|
||||
/**
|
||||
* Remove all entries from a writable cache. This could be used, for
|
||||
* example, after a guest ends a browser session. This is equivalent to
|
||||
* setting the cache's Capacity to zero, except that all cache entries,
|
||||
* even those in active use, will be deleted. Also, any global cache
|
||||
* database files will be deleted.
|
||||
*/
|
||||
void removeAll();
|
||||
};
|
||||
|
||||
%{ C++
|
||||
// ProgID prefix for Components that implement this interface
|
||||
#define NS_NETWORK_CACHE_PROGID "component://netscape/network/cache"
|
||||
#define NS_NETWORK_MEMORY_CACHE_PROGID NS_NETWORK_CACHE_PROGID "?name=memory-cache"
|
||||
#define NS_NETWORK_FLAT_CACHE_PROGID NS_NETWORK_CACHE_PROGID "?name=flat-cache"
|
||||
#define NS_NETWORK_FILE_CACHE_PROGID NS_NETWORK_CACHE_PROGID "?name=file-cache"
|
||||
%}
|
||||
163
mozilla/netwerk/cache/public/nsINetDataCacheManager.idl
vendored
Normal file
163
mozilla/netwerk/cache/public/nsINetDataCacheManager.idl
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsISimpleEnumerator;
|
||||
interface nsICachedNetData;
|
||||
interface nsINetDataCache;
|
||||
interface nsINetDataDiskCache;
|
||||
interface nsIURI;
|
||||
interface nsIFileSpec;
|
||||
|
||||
/**
|
||||
* The network-response cache manager is partly responsible for the caching of
|
||||
* content and associated metadata that has been retrieved via the network.
|
||||
* (The remaining responsibility for caching lies with individual network
|
||||
* protocol handlers.)
|
||||
*
|
||||
* The cache manager supervises the actions of individual cache components,
|
||||
* such as the memory cache, the disk cache and any extension caches, e.g. a
|
||||
* read-only CD-ROM cache.
|
||||
*
|
||||
* @See nsINetDataCache
|
||||
* @See nsICachedNetData
|
||||
*/
|
||||
[scriptable, uuid(71c8ab00-6d5c-11d3-90c8-000064657374)]
|
||||
interface nsINetDataCacheManager : nsISupports
|
||||
{
|
||||
/**
|
||||
* Flag for the GetCachedNetData() method: If set, the memory cache is
|
||||
* neither searched nor will any data be stored into it. This might be
|
||||
* appropriate, for example, with images, because they have their own
|
||||
* cache for storing *decoded* images.
|
||||
*/
|
||||
const unsigned long BYPASS_MEMORY_CACHE = 1 << 0;
|
||||
|
||||
/**
|
||||
* Flag for the GetCachedNetData() method: If set, the disk cache
|
||||
* is neither searched nor will any be data stored into it.
|
||||
* However, read-only extension caches may be searched. This
|
||||
* might be used to avoid leaving persistent records of secure
|
||||
* data.
|
||||
*/
|
||||
const unsigned long BYPASS_PERSISTENT_CACHE = 1 << 1;
|
||||
|
||||
/**
|
||||
* Flag for the GetCachedNetData() method: If set, any stream
|
||||
* content is stored in the cache as a single disk file. Content
|
||||
* will not be cached in the memory cache nor is it cached in a
|
||||
* flat-file cache database. This is used to implement the jar
|
||||
* protocol handler and to provide the stream-as-file semantics
|
||||
* required by the classic bowser plugin API.
|
||||
*/
|
||||
const unsigned long CACHE_AS_FILE = 1 << 2;
|
||||
|
||||
/**
|
||||
* Fetch the cache entry record for the given URI. If one does not exist,
|
||||
* create a new, empty record. The normal search order for caches is:
|
||||
* + Memory cache
|
||||
* + Disk cache
|
||||
* + File cache (stream-as-file cache)
|
||||
* + All extension caches
|
||||
*
|
||||
* When writing, data is typically stored in both the memory cache and the
|
||||
* disk cache. Both the search order and this write policy can be modified by
|
||||
* setting one or more of the flag argument bits, as defined above.
|
||||
*
|
||||
* The optionally-NULL secondaryKey argument can be used, e.g. for form
|
||||
* post data or for HTTP headers in the case of HTTP.
|
||||
*/
|
||||
nsICachedNetData getCachedNetData(in string uri,
|
||||
[size_is(secondaryKeyLength)] in string secondaryKey,
|
||||
in PRUint32 secondaryKeyLength,
|
||||
in PRUint32 flags);
|
||||
|
||||
/**
|
||||
* Returns true if cached content is available for the given URI, even if
|
||||
* only partial data is stored. The flags argument behaves the same as for
|
||||
* the GetCachedNetData() method, above.
|
||||
*/
|
||||
boolean contains(in string uri,
|
||||
[size_is(secondaryKeyLength)] in string secondaryKey,
|
||||
in PRUint32 secondaryKeyLength,
|
||||
in PRUint32 flags);
|
||||
|
||||
/**
|
||||
* Total number of unexpired URI entries stored in all caches. This number
|
||||
* does not take into account duplicate URIs, e.g. because the memory cache
|
||||
* and the disk cache might each contain an entry for the same URI.
|
||||
*/
|
||||
readonly attribute PRUint32 numEntries;
|
||||
|
||||
/**
|
||||
* Enumerate the unexpired URI entries stored in all caches. Some URIs may
|
||||
* be enumerated more than once, e.g. because the the memory cache and the
|
||||
* disk cache might each contain an entry for the same URI.
|
||||
*/
|
||||
nsISimpleEnumerator newCacheEntryIterator();
|
||||
|
||||
/*
|
||||
* Enumerate all the loaded nsINetDataCache-implementing cache modules.
|
||||
* The first module enumerated will be the memory cache, the second will be
|
||||
* the disk cache, then the file cache, followed by all the extension
|
||||
* caches, in search order.
|
||||
*/
|
||||
nsISimpleEnumerator newCacheModuleIterator();
|
||||
|
||||
/**
|
||||
* Remove all entries from all writable caches. This could be used, for
|
||||
* example, after a guest ends a browser session. This is equivalent to
|
||||
* setting the DiskCacheCapacity to zero, except that all cache entries,
|
||||
* even those in active use, will be deleted. Also, any global cache
|
||||
* database files will be deleted.
|
||||
*/
|
||||
void RemoveAll();
|
||||
|
||||
/**
|
||||
* The disk cache is made up of the file cache (for stream-as-file
|
||||
* requests) and a (possibly independent) persistent cache that handles all
|
||||
* other cache requests. This attribute sets/gets the combined capacity of
|
||||
* these caches, measured in KBytes. Setting the capacity lower than the
|
||||
* current amount of space currently in use may cause cache entries to be
|
||||
* evicted from the cache to accomodate the requested capacity.
|
||||
*/
|
||||
attribute PRUint32 diskCacheCapacity;
|
||||
|
||||
/**
|
||||
* This attribute sets/gets the capacity of the memory cache, measured in
|
||||
* KBytes. Setting the capacity lower than the current amount of space
|
||||
* currently in use may cause cache entries to be evicted from the cache to
|
||||
* accomodate the requested capacity.
|
||||
*/
|
||||
attribute PRUint32 memCacheCapacity;
|
||||
|
||||
/**
|
||||
* This attribute must be set before attempting to store into the disk cache.
|
||||
*/
|
||||
attribute nsIFileSpec diskCacheFolder;
|
||||
};
|
||||
|
||||
%{ C++
|
||||
// ProgID prefix for Components that implement this interface
|
||||
#define NS_NETWORK_CACHE_MANAGER_PROGID NS_NETWORK_CACHE_PROGID "?name=manager"
|
||||
%}
|
||||
125
mozilla/netwerk/cache/public/nsINetDataCacheRecord.idl
vendored
Normal file
125
mozilla/netwerk/cache/public/nsINetDataCacheRecord.idl
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsrootidl.idl"
|
||||
|
||||
interface nsIFileSpec;
|
||||
interface nsIChannel;
|
||||
interface nsINetDataCache;
|
||||
|
||||
/**
|
||||
* The nsINetDataCacheRecord represents a single entry in a database that
|
||||
* caches data retrieved from the network. On top of this low-level interface
|
||||
* to the raw record data, the cache manager implements a higher-level record
|
||||
* interface, nsICachedNetData. Each instance of nsINetDataCacheRecord is
|
||||
* (internally) associated with a parent database, an instance of the
|
||||
* nsINetDataCache interface. This interface is essentially a pseudo-private
|
||||
* API for the cache manager. Other clients should never use this interface.
|
||||
*
|
||||
* Each cache record may contain both content and metadata. The content may
|
||||
* be, for example, GIF image data or HTML, and it is accessed through
|
||||
* nsIChannel's streaming API. The opaque metadata, which may contain HTTP
|
||||
* headers among other things, is accessed as a contiguous byte array. Each
|
||||
* entry in the cache is indexed by two different keys: a unique record id
|
||||
* number, generated by the cache, and an opaque string. The latter contains
|
||||
* the URI and other secondary key information, e.g. HTTP form post key/value
|
||||
* pairs.
|
||||
*
|
||||
* The nsINetDataCacheRecord interface is agnostic as to where the data is
|
||||
* stored and whether the storage is volatile or persistent. The memory cache,
|
||||
* the disk cache, a flat-file cache and any read-only extension caches must
|
||||
* all implement this interface.
|
||||
*
|
||||
* @See nsICachedNetData
|
||||
* @See nsINetDataCache
|
||||
* @See nsINetDataDiskCache
|
||||
* @See nsINetDataCacheManager
|
||||
*/
|
||||
|
||||
interface nsILoadGroup;
|
||||
|
||||
[scriptable, uuid(fdcdd6a0-7461-11d3-90ca-0040056a906e)]
|
||||
interface nsINetDataCacheRecord : nsISupports
|
||||
{
|
||||
/**
|
||||
* As far as the nsINetDataCacheRecord implementation is concerned, the
|
||||
* cache entry database key is an opaque blob, but it's intended to contain
|
||||
* both the URI and any secondary keys, such as HTTP post data.
|
||||
*/
|
||||
void getKey(out unsigned long length, [size_is(length), retval] out string key);
|
||||
|
||||
/**
|
||||
* A persistent record number assigned by the cache which must be unique
|
||||
* among all entries stored within the same cache. The record ID serves as
|
||||
* an alternate key to the cache record. Providing that they satisfy the
|
||||
* afforementioned uniqueness requirement, record IDs can be assigned any
|
||||
* value by the database except that they may never be zero.
|
||||
*/
|
||||
readonly attribute PRInt32 recordID;
|
||||
|
||||
/**
|
||||
* Opaque data which can be updated for each cache entry independently of
|
||||
* the content data. This data is a combination of protocol-independent
|
||||
* data provided by the cache manager and protocol-specific meta-data,
|
||||
* e.g. HTTP headers.
|
||||
*/
|
||||
void getMetaData(out PRUint32 length, [size_is(length), retval] out string metaData);
|
||||
void setMetaData(in PRUint32 length, [size_is(length)] in string data);
|
||||
|
||||
/**
|
||||
* Number of content bytes stored in the cache, i.e. via the nsIChannel
|
||||
* streaming APIs. This may be less than the complete content length if a
|
||||
* partial cache fill occurred. Additionally, the cached content can be
|
||||
* truncated by reducing the value of this attribute. When this attribute
|
||||
* is set to zero the associated cache disk file, if any, should be
|
||||
* deleted.
|
||||
*/
|
||||
attribute PRUint32 storedContentLength;
|
||||
|
||||
/**
|
||||
* Delete this cache entry and its associated content.
|
||||
*/
|
||||
void delete();
|
||||
|
||||
/**
|
||||
* Create a channel for reading or writing a stream of content into the
|
||||
* entry. However, many of the nsIChannel methods may return
|
||||
* NS_NOT_IMPLEMENTED, including:
|
||||
*
|
||||
* + GetURI()
|
||||
* + GetContentType()
|
||||
* + GetContentLength()
|
||||
*/
|
||||
nsIChannel newChannel(in nsILoadGroup loadGroup);
|
||||
|
||||
/**
|
||||
* If a cache is implemented such that it stores each URI's content in an
|
||||
* individual disk file, this method will identify the file corresponding
|
||||
* to this record. This may be used to implement the "stream-as-file"
|
||||
* semantics required by some plugins and by the 'jar:' protocol handler.
|
||||
* However, not all cache implementations are *required* to store the data
|
||||
* from each URI in an individual file, so it is acceptable for an
|
||||
* implementation of this method to signal NS_NOT_IMPLEMENTED.
|
||||
*/
|
||||
readonly attribute nsIFileSpec filename;
|
||||
};
|
||||
42
mozilla/netwerk/cache/public/nsINetDataDiskCache.idl
vendored
Normal file
42
mozilla/netwerk/cache/public/nsINetDataDiskCache.idl
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsINetDataCache.idl"
|
||||
|
||||
interface nsIFileSpec;
|
||||
|
||||
/**
|
||||
/**
|
||||
* A network-data disk cache is used to persistently cache the responses to
|
||||
* network retrieval commands. Each cache entry may contain both content,
|
||||
* e.g. GIF image data, and associated metadata, e.g. HTTP headers.
|
||||
*/
|
||||
[scriptable, uuid(6408e390-6f13-11d3-90c8-000064657374)]
|
||||
interface nsINetDataDiskCache : nsINetDataCache
|
||||
{
|
||||
/**
|
||||
* This attribute must be set before calling any other methods of this
|
||||
* interface.
|
||||
*/
|
||||
attribute nsIFileSpec diskCacheFolder;
|
||||
};
|
||||
|
||||
106
mozilla/netwerk/cache/public/nsIStreamAsFile.idl
vendored
Normal file
106
mozilla/netwerk/cache/public/nsIStreamAsFile.idl
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Scott Furman, fur@netscape.com
|
||||
*/
|
||||
#include "nsrootidl.idl"
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIFileSpec;
|
||||
interface nsIStreamAsFileObserver;
|
||||
|
||||
/**
|
||||
* In addition to enhancing effective network response time via caching, the
|
||||
* cache manager serves a second purpose by providing the stream-as-file
|
||||
* service required by traditional browser plugins and the jar: protocol
|
||||
* handler. The interface below provides a means for a client to determine the
|
||||
* filename associated with a stream and to detect modification/deletion of
|
||||
* that file.
|
||||
*/
|
||||
[scriptable, uuid(0eedbbf0-92d9-11d3-90d3-0040056a906e)]
|
||||
interface nsIStreamAsFile : nsISupports
|
||||
{
|
||||
/**
|
||||
* Filename containing stream-as-file
|
||||
*/
|
||||
readonly attribute nsIFileSpec fileSpec;
|
||||
|
||||
/**
|
||||
* Add an observer for this cache record. When the cache wants to delete
|
||||
* or truncate a record, so as to make space for another cache entry's
|
||||
* content data, it will call <code>aObserver</code>'s Observe() method,
|
||||
* passing the nsIStreamAsFile instance as the <code>aSubject</code>
|
||||
* argument and an appropriate message. If the observer does not wish to
|
||||
* inhibit deletion/truncation, it should Release() any references it has to the
|
||||
* cache record.
|
||||
*
|
||||
* @See nsIStreamAsFileObserver
|
||||
*/
|
||||
void addObserver(in nsIStreamAsFileObserver aObserver);
|
||||
|
||||
/**
|
||||
* Delete an observer that was added by the AddObserver() method.
|
||||
*/
|
||||
void removeObserver(in nsIStreamAsFileObserver aObserver);
|
||||
};
|
||||
|
||||
/**
|
||||
* This interface can be implemented by a client to receive notifications of
|
||||
* either modification or deletion of a file created by the cache manager using
|
||||
* the stream-as-file semantics.
|
||||
*/
|
||||
[scriptable, uuid(a26e27c0-92da-11d3-90d3-0040056a906e)]
|
||||
interface nsIStreamAsFileObserver : nsISupports
|
||||
{
|
||||
/**
|
||||
* Flag bits for argument to Observe() method.
|
||||
*/
|
||||
const long NOTIFY_AVAILABLE = 1 << 0; // Stream-as-file now available for reading
|
||||
const long NOTIFY_ERROR = 1 << 1; // Error while loading stream / creating file
|
||||
const long REQUEST_DELETION = 1 << 2; // Cache manager wishes to delete/truncate file
|
||||
const long INVALIDATE = 1 << 3; // File is out-of-date
|
||||
|
||||
// Convenience value
|
||||
const long MAKE_UNAVAILABLE = REQUEST_DELETION | INVALIDATE;
|
||||
|
||||
/**
|
||||
* Receive either a notification or a request concerning a file that has
|
||||
* been opened using stream-as-file. The aMessage and aError arguments
|
||||
* have varying values depending on the nature of the notification.
|
||||
* aMessage is set to NOTIFY_AVAILABLE when a complete stream has been read
|
||||
* and stored on disk in a file. At that point, and no sooner, may the
|
||||
* filename attribute of the associated nsIStreamAsFile be accessed via the
|
||||
* associated nsIStreamAsFile interface. If the aMessage argument is
|
||||
* NOTIFY_ERROR, the aError argument contains the relevant error code. If
|
||||
* the aMessage argument is either REQUEST_DELETION or REQUEST_TRUNCATION,
|
||||
* the callee should immediately Release() all references to the
|
||||
* nsIStreamAsFile (and any references to its associated nsICachedNetData
|
||||
* instances), unless it wishes to inhibit the requested file modification.
|
||||
* If the aMessage argument is INVALIDATE, the cache manager is replacing
|
||||
* the file with a more recent version. If a client wants to continue
|
||||
* using the (now out-of-date) file, it must delete it when it has finished,
|
||||
* as the cache manager will effectively relinquished ownership of the
|
||||
* file.
|
||||
*/
|
||||
void ObserveStreamAsFile(in nsIStreamAsFile aStreamAsFile,
|
||||
in PRUint32 aMessage,
|
||||
in nsresult aError);
|
||||
};
|
||||
39
mozilla/netwerk/makefile.win
Normal file
39
mozilla/netwerk/makefile.win
Normal file
@@ -0,0 +1,39 @@
|
||||
#!gmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape 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/NPL/
|
||||
#
|
||||
# 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 mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
|
||||
DEPTH = ..
|
||||
|
||||
MODULE = necko
|
||||
|
||||
DIRS= \
|
||||
base \
|
||||
dns \
|
||||
build \
|
||||
protocol \
|
||||
socket \
|
||||
util \
|
||||
mime \
|
||||
streamconv \
|
||||
cache \
|
||||
test \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
32
mozilla/netwerk/protocol/http/public/nsIHTTPHeader.idl
Normal file
32
mozilla/netwerk/protocol/http/public/nsIHTTPHeader.idl
Normal file
@@ -0,0 +1,32 @@
|
||||
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIAtom;
|
||||
|
||||
[scriptable, uuid(a3ec67f0-465a-11d3-9a89-0080c7cb1080)]
|
||||
interface nsIHTTPHeader : nsISupports
|
||||
{
|
||||
nsIAtom GetField();
|
||||
string GetValue();
|
||||
};
|
||||
603
mozilla/netwerk/test/TestCacheMgr.cpp
Normal file
603
mozilla/netwerk/test/TestCacheMgr.cpp
Normal file
@@ -0,0 +1,603 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIStreamObserver.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIEventQueue.h"
|
||||
#include "nsIEventQueueService.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#include "nsINetDataCache.h"
|
||||
#include "nsINetDataCacheManager.h"
|
||||
#include "nsICachedNetData.h"
|
||||
|
||||
|
||||
// Number of test entries to be placed in the cache
|
||||
// FIXME - temporary
|
||||
#define NUM_CACHE_ENTRIES 25
|
||||
|
||||
// Cache content stream length will have random length between zero and
|
||||
// MAX_CONTENT_LENGTH bytes
|
||||
#define MAX_CONTENT_LENGTH 20000
|
||||
|
||||
// Limits, converted to KB
|
||||
#define DISK_CACHE_CAPACITY ((MAX_CONTENT_LENGTH * 4) >> 10)
|
||||
#define MEM_CACHE_CAPACITY ((MAX_CONTENT_LENGTH * 3) >> 10)
|
||||
|
||||
// Length of random-data cache entry URI key
|
||||
#define CACHE_KEY_LENGTH 13
|
||||
|
||||
// Length of random-data cache entry secondary key
|
||||
#define CACHE_SECONDARY_KEY_LENGTH 10
|
||||
|
||||
// Length of random-data cache entry meta-data
|
||||
#define CACHE_PROTOCOL_PRIVATE_LENGTH 10
|
||||
|
||||
// Mapping from test case number to RecordID
|
||||
static PRInt32 recordID[NUM_CACHE_ENTRIES];
|
||||
|
||||
static PRInt32
|
||||
mapRecordIdToTestNum(PRInt32 aRecordID)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < NUM_CACHE_ENTRIES; i++) {
|
||||
if (recordID[i] == aRecordID)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// A supply of stream data to either store or compare with
|
||||
class nsITestDataStream {
|
||||
public:
|
||||
virtual ~nsITestDataStream() {};
|
||||
virtual PRUint32 Next() = 0;
|
||||
virtual void Read(char* aBuf, PRUint32 aCount) = 0;
|
||||
virtual void ReadString(char* aBuf, PRUint32 aCount) = 0;
|
||||
|
||||
virtual PRBool Match(char* aBuf, PRUint32 aCount) = 0;
|
||||
virtual PRBool MatchString(char* aBuf, PRUint32 aCount) = 0;
|
||||
virtual void Skip(PRUint32 aCount) = 0;
|
||||
virtual void SkipString(PRUint32 aCount) = 0;
|
||||
};
|
||||
|
||||
// A reproducible stream of random data.
|
||||
class RandomStream : public nsITestDataStream {
|
||||
public:
|
||||
RandomStream(PRUint32 aSeed) {
|
||||
mStartSeed = mState = aSeed;
|
||||
}
|
||||
|
||||
PRUint32 GetStartSeed() {
|
||||
return mStartSeed;
|
||||
}
|
||||
|
||||
PRUint32 Next() {
|
||||
mState = 1103515245 * mState + 12345 ^ (mState >> 16);
|
||||
return mState;
|
||||
}
|
||||
|
||||
PRUint8 NextChar() {
|
||||
PRUint8 c;
|
||||
do {
|
||||
c = Next();
|
||||
} while (!isalnum(c));
|
||||
return c;
|
||||
}
|
||||
|
||||
void Read(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
*aBuf++ = Next();
|
||||
}
|
||||
}
|
||||
|
||||
// Same as Read(), but using only printable chars and
|
||||
// with a terminating NUL
|
||||
void ReadString(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
*aBuf++ = NextChar();
|
||||
}
|
||||
*aBuf = 0;
|
||||
}
|
||||
|
||||
PRBool
|
||||
Match(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
if (*aBuf++ != (char)(Next() & 0xff))
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
MatchString(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
if (*aBuf++ != (char)(NextChar() & 0xff))
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// Check for terminating NUL character
|
||||
if (*aBuf)
|
||||
return PR_FALSE;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
Skip(PRUint32 aCount) {
|
||||
while (aCount--)
|
||||
Next();
|
||||
}
|
||||
|
||||
void
|
||||
SkipString(PRUint32 aCount) {
|
||||
while (aCount--)
|
||||
NextChar();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
PRUint32 mState;
|
||||
PRUint32 mStartSeed;
|
||||
};
|
||||
|
||||
static int gNumReaders = 0;
|
||||
static PRUint32 gTotalBytesRead = 0;
|
||||
static PRUint32 gTotalBytesWritten = 0;
|
||||
static PRUint32 gTotalDuration = 0;
|
||||
|
||||
class nsReader : public nsIStreamListener {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsReader()
|
||||
: mStartTime(0), mBytesRead(0)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
gNumReaders++;
|
||||
}
|
||||
|
||||
virtual ~nsReader() {
|
||||
delete mTestDataStream;
|
||||
gNumReaders--;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Init(nsITestDataStream* aRandomStream, PRUint32 aExpectedStreamLength) {
|
||||
mTestDataStream = aRandomStream;
|
||||
mExpectedStreamLength = aExpectedStreamLength;
|
||||
mRefCnt = 1;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnStartRequest(nsIChannel* channel,
|
||||
nsISupports* context) {
|
||||
mStartTime = PR_IntervalNow();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnDataAvailable(nsIChannel* channel,
|
||||
nsISupports* context,
|
||||
nsIInputStream *aIStream,
|
||||
PRUint32 aSourceOffset,
|
||||
PRUint32 aLength) {
|
||||
char buf[1025];
|
||||
while (aLength > 0) {
|
||||
PRUint32 amt;
|
||||
PRBool match;
|
||||
aIStream->Read(buf, sizeof buf, &amt);
|
||||
if (amt == 0) break;
|
||||
aLength -= amt;
|
||||
mBytesRead += amt;
|
||||
match = mTestDataStream->Match(buf, amt);
|
||||
NS_ASSERTION(match, "Stored data was corrupted on read");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnStopRequest(nsIChannel* channel,
|
||||
nsISupports* context,
|
||||
nsresult aStatus,
|
||||
const PRUnichar* aMsg) {
|
||||
PRIntervalTime endTime;
|
||||
PRIntervalTime duration;
|
||||
|
||||
endTime = PR_IntervalNow();
|
||||
duration = (endTime - mStartTime);
|
||||
|
||||
if (NS_FAILED(aStatus)) printf("channel failed.\n");
|
||||
// printf("read %d bytes\n", mBytesRead);
|
||||
|
||||
//FIXME NS_ASSERTION(mBytesRead == mExpectedStreamLength,
|
||||
// "Stream in cache is wrong length");
|
||||
|
||||
gTotalBytesRead += mBytesRead;
|
||||
gTotalDuration += duration;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
PRIntervalTime mStartTime;
|
||||
PRUint32 mBytesRead;
|
||||
nsITestDataStream* mTestDataStream;
|
||||
PRUint32 mExpectedStreamLength;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsReader, nsIStreamListener, nsIStreamObserver)
|
||||
|
||||
static nsIEventQueue* eventQueue;
|
||||
|
||||
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
||||
|
||||
nsresult
|
||||
InitQueue() {
|
||||
nsresult rv;
|
||||
|
||||
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue service");
|
||||
|
||||
rv = eventQService->CreateThreadEventQueue();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create event queue");
|
||||
|
||||
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQueue);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue for main thread");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Process events until all streams are OnStopRequest'ed
|
||||
nsresult
|
||||
WaitForEvents() {
|
||||
while (gNumReaders) {
|
||||
eventQueue->ProcessPendingEvents();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Read data for a single cache record and compare against testDataStream
|
||||
nsresult
|
||||
TestReadStream(nsICachedNetData *cacheEntry, nsITestDataStream *testDataStream,
|
||||
PRUint32 expectedStreamLength)
|
||||
{
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsresult rv;
|
||||
PRUint32 actualContentLength;
|
||||
|
||||
rv = cacheEntry->NewChannel(0, 0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = cacheEntry->GetStoredContentLength(&actualContentLength);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
// FIXME NS_ASSERTION(actualContentLength == expectedStreamLength,
|
||||
// "nsICachedNetData::GetContentLength() busted ?");
|
||||
|
||||
nsReader *reader = new nsReader;
|
||||
reader->AddRef();
|
||||
rv = reader->Init(testDataStream, expectedStreamLength);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = channel->AsyncRead(0, -1, 0, reader);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
reader->Release();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Convert PRTime to unix-style time_t, i.e. seconds since the epoch
|
||||
static PRUint32
|
||||
convertPRTimeToSeconds(PRTime aTime64)
|
||||
{
|
||||
double fpTime;
|
||||
LL_L2D(fpTime, aTime64);
|
||||
return (PRUint32)(fpTime * 1e-6 + 0.5);
|
||||
}
|
||||
|
||||
// Convert unix-style time_t, i.e. seconds since the epoch, to PRTime
|
||||
static PRTime
|
||||
convertSecondsToPRTime(PRUint32 aSeconds)
|
||||
{
|
||||
PRInt64 t64;
|
||||
LL_L2I(t64, aSeconds);
|
||||
LL_MUL(t64, t64, 1000000);
|
||||
return t64;
|
||||
}
|
||||
|
||||
// Read the test data that was written in FillCache(), checking for
|
||||
// corruption, truncation.
|
||||
nsresult
|
||||
TestRead(nsINetDataCacheManager *aCache, PRUint32 aFlags)
|
||||
{
|
||||
nsresult rv;
|
||||
PRBool inCache;
|
||||
nsCOMPtr<nsICachedNetData> cacheEntry;
|
||||
RandomStream *randomStream;
|
||||
char uriCacheKey[CACHE_KEY_LENGTH];
|
||||
char secondaryCacheKey[CACHE_SECONDARY_KEY_LENGTH];
|
||||
char *storedUriKey;
|
||||
PRUint32 testNum;
|
||||
|
||||
gTotalBytesRead = 0;
|
||||
gTotalDuration = 0;
|
||||
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->ReadString(uriCacheKey, sizeof uriCacheKey - 1);
|
||||
randomStream->Read(secondaryCacheKey, sizeof secondaryCacheKey);
|
||||
|
||||
// Ensure that entry is in the cache
|
||||
rv = aCache->Contains(uriCacheKey,
|
||||
secondaryCacheKey, sizeof secondaryCacheKey,
|
||||
aFlags, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(inCache, "nsINetDataCacheManager::Contains error");
|
||||
|
||||
rv = aCache->GetCachedNetData(uriCacheKey,
|
||||
secondaryCacheKey, sizeof secondaryCacheKey,
|
||||
aFlags,
|
||||
getter_AddRefs(cacheEntry));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
// Test GetUriSpec() method
|
||||
rv = cacheEntry->GetUriSpec(&storedUriKey);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) &&
|
||||
!memcmp(storedUriKey, &uriCacheKey[0], sizeof uriCacheKey),
|
||||
"nsICachedNetData::GetKey failed");
|
||||
nsAllocator::Free(storedUriKey);
|
||||
|
||||
// Test GetSecondaryKey() method
|
||||
PRUint32 storedSecondaryKeyLength;
|
||||
char* storedSecondaryKey;
|
||||
rv = cacheEntry->GetSecondaryKey(&storedSecondaryKeyLength, &storedSecondaryKey);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) &&
|
||||
!memcmp(storedSecondaryKey, &secondaryCacheKey[0],
|
||||
sizeof secondaryCacheKey),
|
||||
"nsICachedNetData::GetSecondaryKey failed");
|
||||
|
||||
// Compare against stored protocol data
|
||||
char *storedProtocolData;
|
||||
PRUint32 storedProtocolDataLength;
|
||||
rv = cacheEntry->GetAnnotation("test data", &storedProtocolDataLength, &storedProtocolData);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) &&
|
||||
storedProtocolDataLength == CACHE_PROTOCOL_PRIVATE_LENGTH,
|
||||
"nsICachedNetData::GetAnnotation() failed");
|
||||
randomStream->Match(storedProtocolData, storedProtocolDataLength);
|
||||
|
||||
// Test GetAllowPartial()
|
||||
PRBool allowPartial;
|
||||
rv = cacheEntry->GetAllowPartial(&allowPartial);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) &&
|
||||
(allowPartial == (PRBool)(randomStream->Next() & 1)),
|
||||
"nsICachedNetData::GetAllowPartial() failed");
|
||||
|
||||
// Test GetExpirationTime()
|
||||
PRTime expirationTime;
|
||||
PRTime expectedExpirationTime = convertSecondsToPRTime(randomStream->Next() & 0xffffff);
|
||||
rv = cacheEntry->GetExpirationTime(&expirationTime);
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) && LL_EQ(expirationTime, expectedExpirationTime),
|
||||
"nsICachedNetData::GetExpirationTime() failed");
|
||||
|
||||
PRUint32 expectedStreamLength = randomStream->Next() % MAX_CONTENT_LENGTH;
|
||||
|
||||
TestReadStream(cacheEntry, randomStream, expectedStreamLength);
|
||||
}
|
||||
|
||||
WaitForEvents();
|
||||
|
||||
// Compute rate in MB/s
|
||||
double rate = gTotalBytesRead / PR_IntervalToMilliseconds(gTotalDuration);
|
||||
rate *= NUM_CACHE_ENTRIES;
|
||||
rate *= 1000;
|
||||
rate /= (1024 * 1024);
|
||||
printf("Read %7d bytes at a rate of %5.1f MB per second \n",
|
||||
gTotalBytesRead, rate);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Create entries in the network data cache, using random data for the
|
||||
// key, the meta-data and the stored content data.
|
||||
nsresult
|
||||
FillCache(nsINetDataCacheManager *aCache, PRUint32 aFlags, PRUint32 aCacheCapacity)
|
||||
{
|
||||
nsresult rv;
|
||||
PRBool inCache;
|
||||
nsCOMPtr<nsICachedNetData> cacheEntry;
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsCOMPtr<nsIOutputStream> outStream;
|
||||
nsCOMPtr<nsINetDataCache> containingCache;
|
||||
char buf[1000];
|
||||
PRUint32 protocolDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char secondaryCacheKey[CACHE_SECONDARY_KEY_LENGTH];
|
||||
char protocolData[CACHE_PROTOCOL_PRIVATE_LENGTH];
|
||||
PRUint32 testNum;
|
||||
RandomStream *randomStream;
|
||||
|
||||
gTotalBytesWritten = 0;
|
||||
PRIntervalTime startTime = PR_IntervalNow();
|
||||
|
||||
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->ReadString(cacheKey, sizeof cacheKey - 1);
|
||||
randomStream->Read(secondaryCacheKey, sizeof secondaryCacheKey);
|
||||
|
||||
// No entry should be in cache until we add it
|
||||
rv = aCache->Contains(cacheKey,
|
||||
secondaryCacheKey, sizeof secondaryCacheKey,
|
||||
aFlags, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(!inCache, "nsINetDataCacheManager::Contains error");
|
||||
|
||||
rv = aCache->GetCachedNetData(cacheKey,
|
||||
secondaryCacheKey, sizeof secondaryCacheKey,
|
||||
aFlags,
|
||||
getter_AddRefs(cacheEntry));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't access cacheEntry via cache key");
|
||||
|
||||
// Test nsINetDataCacheManager::GetNumEntries()
|
||||
PRUint32 numEntries = (PRUint32)-1;
|
||||
rv = aCache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == testNum + 1, "GetNumEntries failure");
|
||||
|
||||
// Record meta-data should be initially empty
|
||||
char *protocolDatap;
|
||||
rv = cacheEntry->GetAnnotation("test data", &protocolDataLength, &protocolDatap);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
if ((protocolDataLength != 0) || (protocolDatap != 0))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Store random data as meta-data
|
||||
randomStream->Read(protocolData, sizeof protocolData);
|
||||
cacheEntry->SetAnnotation("test data", sizeof protocolData, protocolData);
|
||||
|
||||
// Store random data as allow-partial flag
|
||||
PRBool allowPartial = randomStream->Next() & 1;
|
||||
rv = cacheEntry->SetAllowPartial(allowPartial);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"nsICachedNetData::SetAllowPartial() failed");
|
||||
|
||||
// Store random data as expiration time
|
||||
PRTime expirationTime = convertSecondsToPRTime(randomStream->Next() & 0xffffff);
|
||||
rv = cacheEntry->SetExpirationTime(expirationTime);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"nsICachedNetData::SetExpirationTime() failed");
|
||||
|
||||
// Cache manager complains if expiration set without setting last-modified time
|
||||
rv = cacheEntry->SetLastModifiedTime(expirationTime);
|
||||
|
||||
rv = cacheEntry->NewChannel(0, 0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = cacheEntry->GetCache(getter_AddRefs(containingCache));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = channel->OpenOutputStream(0, getter_AddRefs(outStream));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
int streamLength = randomStream->Next() % MAX_CONTENT_LENGTH;
|
||||
int remaining = streamLength;
|
||||
while (remaining) {
|
||||
PRUint32 numWritten;
|
||||
int amount = PR_MIN(sizeof buf, remaining);
|
||||
randomStream->Read(buf, amount);
|
||||
|
||||
rv = outStream->Write(buf, amount, &numWritten);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(numWritten == (PRUint32)amount, "Write() bug?");
|
||||
|
||||
remaining -= amount;
|
||||
|
||||
PRUint32 storageInUse;
|
||||
rv = containingCache->GetStorageInUse(&storageInUse);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) && (storageInUse <= aCacheCapacity),
|
||||
"Cache manager failed to limit cache growth");
|
||||
}
|
||||
outStream->Close();
|
||||
gTotalBytesWritten += streamLength;
|
||||
|
||||
// *Now* there should be an entry in the cache
|
||||
rv = aCache->Contains(cacheKey,
|
||||
secondaryCacheKey, sizeof secondaryCacheKey,
|
||||
aFlags, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(inCache, "nsINetDataCacheManager::Contains error");
|
||||
|
||||
delete randomStream;
|
||||
}
|
||||
|
||||
PRIntervalTime endTime = PR_IntervalNow();
|
||||
|
||||
// Compute rate in MB/s
|
||||
double rate = gTotalBytesWritten / PR_IntervalToMilliseconds(endTime - startTime);
|
||||
rate *= 1000;
|
||||
rate /= (1024 * 1024);
|
||||
printf("Wrote %7d bytes at a rate of %5.1f MB per second \n",
|
||||
gTotalBytesWritten, rate);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult NS_AutoregisterComponents()
|
||||
{
|
||||
nsresult rv = nsComponentManager::AutoRegister(nsIComponentManager::NS_Startup,
|
||||
NULL /* default */);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Test(nsINetDataCacheManager *aCache, PRUint32 aFlags, PRUint32 aCacheCapacity)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = aCache->RemoveAll();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
|
||||
|
||||
PRUint32 numEntries = (PRUint32)-1;
|
||||
rv = aCache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
|
||||
|
||||
rv = FillCache(aCache, aFlags, aCacheCapacity);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't fill cache with random test data");
|
||||
|
||||
rv = TestRead(aCache, aFlags);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't read random test data from cache");
|
||||
|
||||
rv = aCache->RemoveAll();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
|
||||
|
||||
rv = aCache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
|
||||
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheManager> cache;
|
||||
|
||||
rv = NS_AutoregisterComponents();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't register XPCOM components");
|
||||
|
||||
rv = nsComponentManager::CreateInstance(NS_NETWORK_CACHE_MANAGER_PROGID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsINetDataCacheManager),
|
||||
getter_AddRefs(cache));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create cache manager factory") ;
|
||||
|
||||
cache->SetDiskCacheCapacity(DISK_CACHE_CAPACITY);
|
||||
cache->SetMemCacheCapacity(MEM_CACHE_CAPACITY);
|
||||
|
||||
InitQueue();
|
||||
|
||||
Test(cache, nsINetDataCacheManager::BYPASS_PERSISTENT_CACHE, MEM_CACHE_CAPACITY);
|
||||
Test(cache, nsINetDataCacheManager::BYPASS_MEMORY_CACHE, DISK_CACHE_CAPACITY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
820
mozilla/netwerk/test/TestRawCache.cpp
Normal file
820
mozilla/netwerk/test/TestRawCache.cpp
Normal file
@@ -0,0 +1,820 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||||
* for the specific language governing rights and limitations under the
|
||||
* NPL.
|
||||
*
|
||||
* The Initial Developer of this code under the NPL is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIStreamObserver.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIEventQueue.h"
|
||||
#include "nsIEventQueueService.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include "nsINetDataCache.h"
|
||||
#include "nsINetDataDiskCache.h"
|
||||
#include "nsINetDataCacheRecord.h"
|
||||
#include "nsMemCacheCID.h"
|
||||
// file cache include
|
||||
#include "nsNetDiskCacheCID.h"
|
||||
#include "nsIPref.h"
|
||||
#include "prenv.h"
|
||||
#include "nsIFileStream.h"
|
||||
|
||||
|
||||
// Number of test entries to be placed in the cache
|
||||
#define NUM_CACHE_ENTRIES 250
|
||||
|
||||
// Cache content stream length will have random length between zero and
|
||||
// MAX_CONTENT_LENGTH bytes
|
||||
#define MAX_CONTENT_LENGTH 20000
|
||||
|
||||
// Length of random-data cache entry key
|
||||
#define CACHE_KEY_LENGTH 15
|
||||
|
||||
// Length of random-data cache entry meta-data
|
||||
#define CACHE_METADATA_LENGTH 100
|
||||
|
||||
static NS_DEFINE_CID(kMemCacheCID, NS_MEM_CACHE_FACTORY_CID);
|
||||
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
||||
|
||||
// file cache cid
|
||||
static NS_DEFINE_CID(kDiskCacheCID, NS_NETDISKCACHE_CID) ;
|
||||
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
|
||||
static NS_DEFINE_IID(kIPrefIID, NS_IPREF_IID);
|
||||
|
||||
// Mapping from test case number to RecordID
|
||||
static PRInt32 recordID[NUM_CACHE_ENTRIES];
|
||||
|
||||
static PRInt32
|
||||
mapRecordIdToTestNum(PRInt32 aRecordID)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < NUM_CACHE_ENTRIES; i++) {
|
||||
if (recordID[i] == aRecordID)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// A supply of stream data to either store or compare with
|
||||
class nsITestDataStream {
|
||||
public:
|
||||
virtual ~nsITestDataStream() {};
|
||||
virtual PRUint32 Next() = 0;
|
||||
virtual void Read(char* aBuf, PRUint32 aCount) = 0;
|
||||
|
||||
virtual PRBool Match(char* aBuf, PRUint32 aCount) = 0;
|
||||
virtual void Skip(PRUint32 aCount) = 0;
|
||||
};
|
||||
|
||||
// A reproducible stream of random data.
|
||||
class RandomStream : public nsITestDataStream {
|
||||
public:
|
||||
RandomStream(PRUint32 aSeed) {
|
||||
mStartSeed = mState = aSeed;
|
||||
}
|
||||
|
||||
PRUint32 GetStartSeed() {
|
||||
return mStartSeed;
|
||||
}
|
||||
|
||||
PRUint32 Next() {
|
||||
mState = 1103515245 * mState + 12345;
|
||||
return mState;
|
||||
}
|
||||
|
||||
void Read(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
*aBuf++ = Next();
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
Match(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
if (*aBuf++ != (char)(Next() & 0xff))
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
Skip(PRUint32 aCount) {
|
||||
while (aCount--)
|
||||
Next();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
PRUint32 mState;
|
||||
PRUint32 mStartSeed;
|
||||
};
|
||||
|
||||
// A stream of data that increments on each byte that is read, modulo 256
|
||||
class CounterStream : public nsITestDataStream {
|
||||
public:
|
||||
CounterStream(PRUint32 aSeed) {
|
||||
mStartSeed = mState = aSeed;
|
||||
}
|
||||
|
||||
PRUint32 GetStartSeed() {
|
||||
return mStartSeed;
|
||||
}
|
||||
|
||||
PRUint32 Next() {
|
||||
mState += 1;
|
||||
mState &= 0xff;
|
||||
return mState;
|
||||
}
|
||||
|
||||
void Read(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
*aBuf++ = Next();
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
Match(char* aBuf, PRUint32 aCount) {
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aCount; i++) {
|
||||
if (*aBuf++ != (char)Next())
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
Skip(PRUint32 aCount) {
|
||||
mState += aCount;
|
||||
mState &= 0xff;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
PRUint32 mState;
|
||||
PRUint32 mStartSeed;
|
||||
};
|
||||
|
||||
static int gNumReaders = 0;
|
||||
static PRUint32 gTotalBytesRead = 0;
|
||||
static PRUint32 gTotalDuration = 0;
|
||||
|
||||
class nsReader : public nsIStreamListener {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsReader()
|
||||
: mStartTime(0), mBytesRead(0)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
gNumReaders++;
|
||||
}
|
||||
|
||||
virtual ~nsReader() {
|
||||
delete mTestDataStream;
|
||||
gNumReaders--;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Init(nsITestDataStream* aRandomStream, PRUint32 aExpectedStreamLength) {
|
||||
mTestDataStream = aRandomStream;
|
||||
mExpectedStreamLength = aExpectedStreamLength;
|
||||
mRefCnt = 1;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnStartRequest(nsIChannel* channel,
|
||||
nsISupports* context) {
|
||||
mStartTime = PR_IntervalNow();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnDataAvailable(nsIChannel* channel,
|
||||
nsISupports* context,
|
||||
nsIInputStream *aIStream,
|
||||
PRUint32 aSourceOffset,
|
||||
PRUint32 aLength) {
|
||||
char buf[1025];
|
||||
while (aLength > 0) {
|
||||
PRUint32 amt;
|
||||
PRBool match;
|
||||
aIStream->Read(buf, sizeof buf, &amt);
|
||||
if (amt == 0) break;
|
||||
aLength -= amt;
|
||||
mBytesRead += amt;
|
||||
match = mTestDataStream->Match(buf, amt);
|
||||
NS_ASSERTION(match, "Stored data was corrupted on read");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnStopRequest(nsIChannel* channel,
|
||||
nsISupports* context,
|
||||
nsresult aStatus,
|
||||
const PRUnichar* aMsg) {
|
||||
PRIntervalTime endTime;
|
||||
PRIntervalTime duration;
|
||||
|
||||
endTime = PR_IntervalNow();
|
||||
duration = (endTime - mStartTime);
|
||||
|
||||
if (NS_FAILED(aStatus)) printf("channel failed.\n");
|
||||
// printf("read %d bytes\n", mBytesRead);
|
||||
|
||||
NS_ASSERTION(mBytesRead == mExpectedStreamLength,
|
||||
"Stream in cache is wrong length");
|
||||
|
||||
gTotalBytesRead += mBytesRead;
|
||||
gTotalDuration += duration;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
PRIntervalTime mStartTime;
|
||||
PRUint32 mBytesRead;
|
||||
nsITestDataStream* mTestDataStream;
|
||||
PRUint32 mExpectedStreamLength;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsReader, nsIStreamListener, nsIStreamObserver)
|
||||
|
||||
static nsIEventQueue* eventQueue;
|
||||
|
||||
nsresult
|
||||
InitQueue() {
|
||||
nsresult rv;
|
||||
|
||||
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue service");
|
||||
|
||||
rv = eventQService->CreateThreadEventQueue();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create event queue");
|
||||
|
||||
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQueue);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue for main thread");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Process events until all streams are OnStopRequest'ed
|
||||
nsresult
|
||||
WaitForEvents() {
|
||||
while (gNumReaders) {
|
||||
eventQueue->ProcessPendingEvents();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Read data for a single cache record and compare against testDataStream
|
||||
nsresult
|
||||
TestReadStream(nsINetDataCacheRecord *record, nsITestDataStream *testDataStream,
|
||||
PRUint32 expectedStreamLength)
|
||||
{
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsresult rv;
|
||||
PRUint32 actualContentLength;
|
||||
|
||||
rv = record->NewChannel(0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = record->GetStoredContentLength(&actualContentLength);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(actualContentLength == expectedStreamLength,
|
||||
"nsINetDataCacheRecord::GetContentLength() busted ?");
|
||||
|
||||
nsReader *reader = new nsReader;
|
||||
rv = reader->Init(testDataStream, expectedStreamLength);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = channel->AsyncRead(0, -1, 0, reader);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
reader->Release();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check that records can be retrieved using their record-ID, in addition
|
||||
// to using the opaque key.
|
||||
nsresult
|
||||
TestRecordID(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
RandomStream *randomStream;
|
||||
PRUint32 metaDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char *metaData;
|
||||
PRUint32 testNum;
|
||||
PRBool match;
|
||||
|
||||
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
rv = cache->GetCachedNetDataByID(recordID[testNum], getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't obtain record using record ID");
|
||||
|
||||
// Match against previously stored meta-data
|
||||
rv = record->GetMetaData(&metaDataLength, &metaData);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get record meta-data");
|
||||
match = randomStream->Match(metaData, metaDataLength);
|
||||
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
|
||||
|
||||
nsAllocator::Free(metaData);
|
||||
delete randomStream;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check that all cache entries in the database are enumerated and that
|
||||
// no duplicates appear.
|
||||
nsresult
|
||||
TestEnumeration(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
nsCOMPtr<nsISupports> tempISupports;
|
||||
nsCOMPtr<nsISimpleEnumerator> iterator;
|
||||
RandomStream *randomStream;
|
||||
PRUint32 metaDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char *metaData;
|
||||
PRUint32 testNum;
|
||||
PRBool match;
|
||||
PRInt32 recID;
|
||||
|
||||
int numRecords = 0;
|
||||
|
||||
// Iterate over all records in the cache
|
||||
rv = cache->NewCacheEntryIterator(getter_AddRefs(iterator));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create new cache entry iterator");
|
||||
|
||||
PRBool notDone;
|
||||
while (1) {
|
||||
|
||||
// Done iterating ?
|
||||
rv = iterator->HasMoreElements(¬Done);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!notDone)
|
||||
break;
|
||||
|
||||
// Get next record in iteration
|
||||
rv = iterator->GetNext(getter_AddRefs(tempISupports));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "iterator bustage");
|
||||
record = do_QueryInterface(tempISupports);
|
||||
|
||||
numRecords++;
|
||||
|
||||
// Get record ID
|
||||
rv = record->GetRecordID(&recID);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get Record ID");
|
||||
testNum = mapRecordIdToTestNum(recID);
|
||||
NS_ASSERTION(testNum != -1, "Corrupted Record ID ?");
|
||||
|
||||
// Erase mapping from table, so that duplicate enumerations are detected
|
||||
recordID[testNum] = -1;
|
||||
|
||||
// Make sure stream matches test data
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
// Match against previously stored meta-data
|
||||
rv = record->GetMetaData(&metaDataLength, &metaData);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get record meta-data");
|
||||
match = randomStream->Match(metaData, metaDataLength);
|
||||
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
|
||||
nsAllocator::Free(metaData);
|
||||
|
||||
delete randomStream;
|
||||
}
|
||||
|
||||
NS_ASSERTION(numRecords == NUM_CACHE_ENTRIES, "Iteration bug");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Read the test data that was written in FillCache(), checking for
|
||||
// corruption, truncation.
|
||||
nsresult
|
||||
TestRead(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
PRBool inCache;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
RandomStream *randomStream;
|
||||
PRUint32 metaDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char *metaData, *storedCacheKey;
|
||||
PRUint32 testNum, storedCacheKeyLength;
|
||||
PRBool match;
|
||||
|
||||
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
// Ensure that entry is in the cache
|
||||
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(inCache, "nsINetDataCache::Contains error");
|
||||
|
||||
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
// Match against previously stored meta-data
|
||||
match = record->GetMetaData(&metaDataLength, &metaData);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
match = randomStream->Match(metaData, metaDataLength);
|
||||
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
|
||||
nsAllocator::Free(metaData);
|
||||
|
||||
// Test GetKey() method
|
||||
rv = record->GetKey(&storedCacheKeyLength, &storedCacheKey);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv) &&
|
||||
(storedCacheKeyLength == sizeof cacheKey) &&
|
||||
!memcmp(storedCacheKey, &cacheKey[0], sizeof cacheKey),
|
||||
"nsINetDataCacheRecord::GetKey failed");
|
||||
nsAllocator::Free(storedCacheKey);
|
||||
|
||||
PRUint32 expectedStreamLength = randomStream->Next() % MAX_CONTENT_LENGTH;
|
||||
|
||||
TestReadStream(record, randomStream, expectedStreamLength);
|
||||
}
|
||||
|
||||
WaitForEvents();
|
||||
|
||||
// Compute rate in MB/s
|
||||
double rate = gTotalBytesRead / PR_IntervalToMilliseconds(gTotalDuration);
|
||||
rate *= NUM_CACHE_ENTRIES;
|
||||
rate *= 1000;
|
||||
rate /= (1024 * 1024);
|
||||
printf("Read %d bytes at a rate of %5.1f MB per second \n",
|
||||
gTotalBytesRead, rate);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Repeatedly call SetStoredContentLength() on a cache entry and make
|
||||
// read the stream's data to ensure that it's not corrupted by the effect
|
||||
nsresult
|
||||
TestTruncation(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
RandomStream *randomStream;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
|
||||
randomStream = new RandomStream(0);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
randomStream->Skip(CACHE_METADATA_LENGTH);
|
||||
PRUint32 initialStreamLength = randomStream->Next() % MAX_CONTENT_LENGTH;
|
||||
delete randomStream;
|
||||
|
||||
PRUint32 i;
|
||||
PRUint32 delta = initialStreamLength / 64;
|
||||
for (i = initialStreamLength; i >= delta; i -= delta) {
|
||||
PRUint32 expectedStreamLength = i;
|
||||
|
||||
// Do the truncation
|
||||
record->SetStoredContentLength(expectedStreamLength);
|
||||
randomStream = new RandomStream(0);
|
||||
randomStream->Skip(CACHE_KEY_LENGTH + CACHE_METADATA_LENGTH + 1);
|
||||
|
||||
PRUint32 afterContentLength;
|
||||
rv = record->GetStoredContentLength(&afterContentLength);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
NS_ASSERTION(afterContentLength == expectedStreamLength,
|
||||
"nsINetDataCacheRecord::SetContentLength() failed to truncate record");
|
||||
|
||||
TestReadStream(record, randomStream, expectedStreamLength);
|
||||
WaitForEvents();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Write known data to random offsets in a single cache entry and test
|
||||
// resulting stream for correctness.
|
||||
nsresult
|
||||
TestOffsetWrites(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsCOMPtr<nsIOutputStream> outStream;
|
||||
char buf[512];
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
RandomStream *randomStream;
|
||||
|
||||
randomStream = new RandomStream(0);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't access record via opaque cache key");
|
||||
|
||||
|
||||
// Write buffer-fulls of data at random offsets into the cache entry.
|
||||
// Data written is (offset % 0xff)
|
||||
PRUint32 startingOffset;
|
||||
PRUint32 streamLength = 0;
|
||||
CounterStream *counterStream;
|
||||
int i;
|
||||
for (i = 0; i < 100; i++) {
|
||||
rv = record->NewChannel(0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
startingOffset = streamLength ? streamLength - (randomStream->Next() % sizeof buf): 0;
|
||||
rv = channel->OpenOutputStream(startingOffset, getter_AddRefs(outStream));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
counterStream = new CounterStream(startingOffset);
|
||||
counterStream->Read(buf, sizeof buf);
|
||||
|
||||
PRUint32 numWritten;
|
||||
rv = outStream->Write(buf, sizeof buf, &numWritten);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(numWritten == sizeof buf, "Write() bug?");
|
||||
streamLength = startingOffset + sizeof buf;
|
||||
|
||||
rv = outStream->Close();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't close channel");
|
||||
delete counterStream;
|
||||
}
|
||||
|
||||
delete randomStream;
|
||||
|
||||
counterStream = new CounterStream(0);
|
||||
TestReadStream(record, counterStream, streamLength);
|
||||
WaitForEvents();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Create entries in the network data cache, using random data for the
|
||||
// key, the meta-data and the stored content data.
|
||||
nsresult
|
||||
FillCache(nsINetDataCache *cache)
|
||||
{
|
||||
nsresult rv;
|
||||
PRBool inCache;
|
||||
nsCOMPtr<nsINetDataCacheRecord> record;
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsCOMPtr<nsIOutputStream> outStream;
|
||||
char buf[1000];
|
||||
PRUint32 metaDataLength;
|
||||
char cacheKey[CACHE_KEY_LENGTH];
|
||||
char metaData[CACHE_METADATA_LENGTH];
|
||||
PRUint32 testNum;
|
||||
char *data;
|
||||
RandomStream *randomStream;
|
||||
PRUint32 totalBytesWritten = 0;
|
||||
|
||||
PRIntervalTime startTime = PR_IntervalNow();
|
||||
|
||||
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
|
||||
randomStream = new RandomStream(testNum);
|
||||
randomStream->Read(cacheKey, sizeof cacheKey);
|
||||
|
||||
// No entry should be in cache until we add it
|
||||
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(!inCache, "nsINetDataCache::Contains error");
|
||||
|
||||
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't access record via opaque cache key");
|
||||
|
||||
// Test nsINetDataCacheRecord::GetRecordID()
|
||||
rv = record->GetRecordID(&recordID[testNum]);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get Record ID");
|
||||
|
||||
// Test nsINetDataCache::GetNumEntries()
|
||||
PRUint32 numEntries = (PRUint32)-1;
|
||||
rv = cache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == testNum + 1, "GetNumEntries failure");
|
||||
|
||||
// Record meta-data should be initially empty
|
||||
rv = record->GetMetaData(&metaDataLength, &data);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
if ((metaDataLength != 0) || (data != 0))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Store random data as meta-data
|
||||
randomStream->Read(metaData, sizeof metaData);
|
||||
record->SetMetaData(sizeof metaData, metaData);
|
||||
|
||||
rv = record->NewChannel(0, getter_AddRefs(channel));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
rv = channel->OpenOutputStream(0, getter_AddRefs(outStream));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
|
||||
PRUint32 beforeOccupancy;
|
||||
rv = cache->GetStorageInUse(&beforeOccupancy);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
|
||||
|
||||
int streamLength = randomStream->Next() % MAX_CONTENT_LENGTH;
|
||||
int remaining = streamLength;
|
||||
while (remaining) {
|
||||
PRUint32 numWritten;
|
||||
int amount = PR_MIN(sizeof buf, remaining);
|
||||
randomStream->Read(buf, amount);
|
||||
|
||||
rv = outStream->Write(buf, amount, &numWritten);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(numWritten == (PRUint32)amount, "Write() bug?");
|
||||
|
||||
remaining -= amount;
|
||||
}
|
||||
outStream->Close();
|
||||
totalBytesWritten += streamLength;
|
||||
|
||||
PRUint32 afterOccupancy;
|
||||
rv = cache->GetStorageInUse(&afterOccupancy);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
|
||||
PRUint32 streamLengthInKB = streamLength >> 10;
|
||||
NS_ASSERTION((afterOccupancy - beforeOccupancy) >= streamLengthInKB,
|
||||
"nsINetDataCache::GetStorageInUse() is busted");
|
||||
|
||||
|
||||
// *Now* there should be an entry in the cache
|
||||
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
|
||||
NS_ASSERTION(inCache, "nsINetDataCache::Contains error");
|
||||
|
||||
delete randomStream;
|
||||
}
|
||||
|
||||
PRIntervalTime endTime = PR_IntervalNow();
|
||||
|
||||
// Compute rate in MB/s
|
||||
double rate = totalBytesWritten / PR_IntervalToMilliseconds(endTime - startTime);
|
||||
rate *= 1000;
|
||||
rate /= (1024 * 1024);
|
||||
printf("Wrote %7d bytes at a rate of %5.1f MB per second \n",
|
||||
totalBytesWritten, rate);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult NS_AutoregisterComponents()
|
||||
{
|
||||
nsresult rv = nsComponentManager::AutoRegister(nsIComponentManager::NS_Startup,
|
||||
NULL /* default */);
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRBool initPref ()
|
||||
{
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIPref, prefPtr, kPrefCID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return false;
|
||||
|
||||
nsCOMPtr<nsIFileSpec> fileSpec;
|
||||
rv = NS_NewFileSpec (getter_AddRefs(fileSpec));
|
||||
if (NS_FAILED(rv))
|
||||
return false;
|
||||
|
||||
nsCString defaultPrefFile = PR_GetEnv ("MOZILLA_FIVE_HOME");
|
||||
if (defaultPrefFile.Length())
|
||||
defaultPrefFile += "/";
|
||||
else
|
||||
defaultPrefFile = "./";
|
||||
defaultPrefFile += "default_prefs.js";
|
||||
|
||||
fileSpec->SetUnixStyleFilePath (defaultPrefFile.GetBuffer());
|
||||
|
||||
PRBool exists = false;
|
||||
fileSpec->Exists(&exists);
|
||||
if (exists)
|
||||
prefPtr->ReadUserPrefsFrom(fileSpec);
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if(argc <2) {
|
||||
printf(" %s -f to test filecache\n", argv[0]) ;
|
||||
printf(" %s -m to test memcache\n", argv[0]) ;
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
|
||||
rv = NS_AutoregisterComponents();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't register XPCOM components");
|
||||
|
||||
nsCOMPtr<nsINetDataCache> cache;
|
||||
|
||||
if (PL_strcasecmp(argv[1], "-m") == 0) {
|
||||
rv = nsComponentManager::CreateInstance(kMemCacheCID, nsnull,
|
||||
NS_GET_IID(nsINetDataCache),
|
||||
getter_AddRefs(cache));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create memory cache factory");
|
||||
} else if (PL_strcasecmp(argv[1], "-f") == 0) {
|
||||
|
||||
nsCOMPtr<nsINetDataDiskCache> diskcache ;
|
||||
|
||||
rv = nsComponentManager::CreateInstance(kDiskCacheCID, nsnull,
|
||||
NS_GET_IID(nsINetDataDiskCache),
|
||||
getter_AddRefs(diskcache));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create disk cache factory") ;
|
||||
|
||||
nsCOMPtr<nsIFileSpec> folder ;
|
||||
NS_NewFileSpec(getter_AddRefs(folder)) ;
|
||||
folder->SetUnixStyleFilePath("/tmp") ;
|
||||
diskcache->SetDiskCacheFolder(folder) ;
|
||||
|
||||
cache = diskcache ;
|
||||
|
||||
} else {
|
||||
printf(" %s -f to test filecache\n", argv[0]) ;
|
||||
printf(" %s -m to test memcache\n", argv[0]) ;
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
InitQueue();
|
||||
|
||||
PRUnichar* description;
|
||||
rv = cache->GetDescription(&description);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache description");
|
||||
nsCAutoString descStr(description);
|
||||
printf("Testing: %s\n", descStr.GetBuffer());
|
||||
|
||||
rv = cache->RemoveAll();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
|
||||
|
||||
PRUint32 startOccupancy;
|
||||
rv = cache->GetStorageInUse(&startOccupancy);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
|
||||
|
||||
PRUint32 numEntries = (PRUint32)-1;
|
||||
rv = cache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
|
||||
|
||||
rv = FillCache(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't fill cache with random test data");
|
||||
|
||||
rv = TestRead(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't read random test data from cache");
|
||||
|
||||
rv = TestRecordID(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't index records using record ID");
|
||||
|
||||
rv = TestEnumeration(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully enumerate records");
|
||||
|
||||
rv = TestTruncation(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully truncate records");
|
||||
|
||||
rv = TestOffsetWrites(cache);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully write to records using non-zero offsets");
|
||||
|
||||
rv = cache->RemoveAll();
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
|
||||
rv = cache->GetNumEntries(&numEntries);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
|
||||
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
|
||||
|
||||
PRUint32 endOccupancy;
|
||||
rv = cache->GetStorageInUse(&endOccupancy);
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
|
||||
|
||||
NS_ASSERTION(startOccupancy == endOccupancy, "Cache occupancy not correctly computed ?");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
82
mozilla/netwerk/test/makefile.win
Normal file
82
mozilla/netwerk/test/makefile.win
Normal file
@@ -0,0 +1,82 @@
|
||||
#!nmake
|
||||
#
|
||||
# The contents of this file are subject to the Netscape 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/NPL/
|
||||
#
|
||||
# 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 mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
|
||||
DEPTH=..\..
|
||||
|
||||
MAKE_OBJ_TYPE = EXE
|
||||
PROG1 = .\$(OBJDIR)\TestFileInput.exe
|
||||
PROG2 = .\$(OBJDIR)\TestSocketInput.exe
|
||||
PROG3 = .\$(OBJDIR)\TestSocketIO.exe
|
||||
PROG4 = .\$(OBJDIR)\TestProtocols.exe
|
||||
PROG5 = .\$(OBJDIR)\TestSocketTransport.exe
|
||||
PROG6 = .\$(OBJDIR)\urltest.exe
|
||||
PROG7 = .\$(OBJDIR)\TestFileInput2.exe
|
||||
PROG8 = .\$(OBJDIR)\TestFileTransport.exe
|
||||
PROG9 = .\$(OBJDIR)\TestRes.exe
|
||||
PROGA = .\$(OBJDIR)\TestRawCache.exe
|
||||
PROGB = .\$(OBJDIR)\TestCacheMgr.exe
|
||||
PROGRAMS = \
|
||||
#$(PROG1) $(PROG2) $(PROG3) $(PROG4) $(PROG5) $(PROG6) $(PROG7) $(PROG8) $(PROG9)\
|
||||
$(PROGA) $(PROGB)
|
||||
|
||||
LCFLAGS=-DUSE_NSREG -GX
|
||||
|
||||
REQUIRES=libreg
|
||||
|
||||
INCS = $(INCS) \
|
||||
-I$(DEPTH)\dist\include \
|
||||
$(NULL)
|
||||
|
||||
LLIBS= \
|
||||
$(DIST)\lib\xpcom.lib \
|
||||
$(LIBNSPR) \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)\config\rules.mak>
|
||||
|
||||
install:: $(PROGRAMS)
|
||||
-for %p in ($(PROGRAMS)) do $(MAKE_INSTALL) %p $(DIST)\bin
|
||||
|
||||
clobber::
|
||||
-for %p in ($(PROGRAMS)) do $(RM) %p $(DIST)\bin\%p
|
||||
|
||||
$(PROG1): $(OBJDIR) TestFileInput.cpp
|
||||
|
||||
$(PROG2): $(OBJDIR) TestSocketInput.cpp
|
||||
|
||||
$(PROG3): $(OBJDIR) TestSocketIO.cpp
|
||||
|
||||
$(PROG4): $(OBJDIR) TestProtocols.cpp
|
||||
|
||||
$(PROG5): $(OBJDIR) TestSocketTransport.cpp
|
||||
|
||||
$(PROG6): $(OBJDIR) urltest.cpp
|
||||
|
||||
$(PROG7): $(OBJDIR) TestFileInput2.cpp
|
||||
|
||||
$(PROG8): $(OBJDIR) TestFileTransport.cpp
|
||||
|
||||
$(PROG9): $(OBJDIR) TestRes.cpp
|
||||
|
||||
$(PROGA): $(OBJDIR) TestRawCache.cpp
|
||||
|
||||
$(PROGB): $(OBJDIR) TestCacheMgr.cpp
|
||||
|
||||
1857
mozilla/string/obsolete/nsString.cpp
Normal file
1857
mozilla/string/obsolete/nsString.cpp
Normal file
File diff suppressed because it is too large
Load Diff
226
mozilla/xpcom/base/nsError.h
Normal file
226
mozilla/xpcom/base/nsError.h
Normal file
@@ -0,0 +1,226 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef nsError_h
|
||||
#define nsError_h
|
||||
|
||||
#ifndef prtypes_h___
|
||||
#include "prtypes.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Generic result data type
|
||||
*/
|
||||
|
||||
typedef PRUint32 nsresult;
|
||||
|
||||
/*
|
||||
* To add error code to your module, you need to do the following:
|
||||
*
|
||||
* 1) Add a module offset code. Add yours to the bottom of the list
|
||||
* right below this comment, adding 1.
|
||||
*
|
||||
* 2) In your module, define a header file which uses one of the
|
||||
* NE_ERROR_GENERATExxxxxx macros. Some examples below:
|
||||
*
|
||||
* #define NS_ERROR_MYMODULE_MYERROR1 NS_ERROR_GENERATE(NS_ERROR_SEVERITY_ERROR,NS_ERROR_MODULE_MYMODULE,1)
|
||||
* #define NS_ERROR_MYMODULE_MYERROR2 NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_MYMODULE,2)
|
||||
* #define NS_ERROR_MYMODULE_MYERROR3 NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_MYMODULE,3)
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @name Standard Module Offset Code. Each Module should identify a unique number
|
||||
* and then all errors associated with that module become offsets from the
|
||||
* base associated with that module id. There are 16 bits of code bits for
|
||||
* each module.
|
||||
*/
|
||||
|
||||
#define NS_ERROR_MODULE_XPCOM 1
|
||||
#define NS_ERROR_MODULE_BASE 2
|
||||
#define NS_ERROR_MODULE_GFX 3
|
||||
#define NS_ERROR_MODULE_WIDGET 4
|
||||
#define NS_ERROR_MODULE_CALENDAR 5
|
||||
#define NS_ERROR_MODULE_NETWORK 6
|
||||
#define NS_ERROR_MODULE_PLUGINS 7
|
||||
#define NS_ERROR_MODULE_LAYOUT 8
|
||||
#define NS_ERROR_MODULE_HTMLPARSER 9
|
||||
#define NS_ERROR_MODULE_RDF 10
|
||||
#define NS_ERROR_MODULE_UCONV 11
|
||||
#define NS_ERROR_MODULE_REG 12
|
||||
#define NS_ERROR_MODULE_FILES 13
|
||||
#define NS_ERROR_MODULE_DOM 14
|
||||
#define NS_ERROR_MODULE_IMGLIB 15
|
||||
#define NS_ERROR_MODULE_MAILNEWS 16
|
||||
#define NS_ERROR_MODULE_EDITOR 17
|
||||
#define NS_ERROR_MODULE_XPCONNECT 18
|
||||
|
||||
/**
|
||||
* @name Standard Error Handling Macros
|
||||
*/
|
||||
|
||||
#define NS_FAILED(_nsresult) ((_nsresult) & 0x80000000)
|
||||
#define NS_SUCCEEDED(_nsresult) (!((_nsresult) & 0x80000000))
|
||||
|
||||
/**
|
||||
* @name Severity Code. This flag identifies the level of warning
|
||||
*/
|
||||
|
||||
#define NS_ERROR_SEVERITY_SUCCESS 0
|
||||
#define NS_ERROR_SEVERITY_ERROR 1
|
||||
|
||||
/**
|
||||
* @name Mozilla Code. This flag separates consumers of mozilla code
|
||||
* from the native platform
|
||||
*/
|
||||
|
||||
#define NS_ERROR_MODULE_BASE_OFFSET 0x45
|
||||
|
||||
/**
|
||||
* @name Standard Error Generating Macros
|
||||
*/
|
||||
|
||||
#define NS_ERROR_GENERATE(sev,module,code) \
|
||||
((nsresult) (((PRUint32)(sev)<<31) | ((PRUint32)(module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | ((PRUint32)(code))) )
|
||||
|
||||
#define NS_ERROR_GENERATE_SUCCESS(module,code) \
|
||||
((nsresult) (((PRUint32)(NS_ERROR_SEVERITY_SUCCESS)<<31) | ((PRUint32)(module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | ((PRUint32)(code))) )
|
||||
|
||||
#define NS_ERROR_GENERATE_FAILURE(module,code) \
|
||||
((nsresult) (((PRUint32)(NS_ERROR_SEVERITY_ERROR)<<31) | ((PRUint32)(module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | ((PRUint32)(code))) )
|
||||
|
||||
/**
|
||||
* @name Standard Macros for retrieving error bits
|
||||
*/
|
||||
|
||||
#define NS_ERROR_GET_CODE(err) ((err) & 0xffff)
|
||||
#define NS_ERROR_GET_MODULE(err) (((((err) >> 16) - NS_ERROR_MODULE_BASE_OFFSET) & 0x1fff))
|
||||
#define NS_ERROR_GET_SEVERITY(err) (((err) >> 31) & 0x1)
|
||||
|
||||
/**
|
||||
* @name Standard return values
|
||||
*/
|
||||
|
||||
/*@{*/
|
||||
|
||||
/* Standard "it worked" return value */
|
||||
#define NS_OK 0
|
||||
|
||||
/* The backwards COM false */
|
||||
#define NS_COMFALSE 1
|
||||
|
||||
#define NS_ERROR_BASE ((nsresult) 0xC1F30000)
|
||||
|
||||
/* Returned when an instance is not initialized */
|
||||
#define NS_ERROR_NOT_INITIALIZED (NS_ERROR_BASE + 1)
|
||||
|
||||
/* Returned when an instance is already initialized */
|
||||
#define NS_ERROR_ALREADY_INITIALIZED (NS_ERROR_BASE + 2)
|
||||
|
||||
/* Returned by a not implemented function */
|
||||
#define NS_ERROR_NOT_IMPLEMENTED ((nsresult) 0x80004001L)
|
||||
|
||||
/* Returned when a given interface is not supported. */
|
||||
#define NS_NOINTERFACE ((nsresult) 0x80004002L)
|
||||
#define NS_ERROR_NO_INTERFACE NS_NOINTERFACE
|
||||
|
||||
#define NS_ERROR_INVALID_POINTER ((nsresult) 0x80004003L)
|
||||
#define NS_ERROR_NULL_POINTER NS_ERROR_INVALID_POINTER
|
||||
|
||||
/* Returned when a function aborts */
|
||||
#define NS_ERROR_ABORT ((nsresult) 0x80004004L)
|
||||
|
||||
/* Returned when a function fails */
|
||||
#define NS_ERROR_FAILURE ((nsresult) 0x80004005L)
|
||||
|
||||
/* Returned when an unexpected error occurs */
|
||||
#define NS_ERROR_UNEXPECTED ((nsresult) 0x8000ffffL)
|
||||
|
||||
/* Returned when a memory allocation failes */
|
||||
#define NS_ERROR_OUT_OF_MEMORY ((nsresult) 0x8007000eL)
|
||||
|
||||
/* Returned when an illegal value is passed */
|
||||
#define NS_ERROR_ILLEGAL_VALUE ((nsresult) 0x80070057L)
|
||||
#define NS_ERROR_INVALID_ARG NS_ERROR_ILLEGAL_VALUE
|
||||
|
||||
/* Returned when a class doesn't allow aggregation */
|
||||
#define NS_ERROR_NO_AGGREGATION ((nsresult) 0x80040110L)
|
||||
|
||||
/* Returned when an operation can't complete due to an unavailable resource */
|
||||
#define NS_ERROR_NOT_AVAILABLE ((nsresult) 0x80040111L)
|
||||
|
||||
/* Returned when a class is not registered */
|
||||
#define NS_ERROR_FACTORY_NOT_REGISTERED ((nsresult) 0x80040154L)
|
||||
|
||||
/* Returned when a class cannot be registered, but may be tried again later */
|
||||
#define NS_ERROR_FACTORY_REGISTER_AGAIN ((nsresult) 0x80040155L)
|
||||
|
||||
/* Returned when a dynamically loaded factory couldn't be found */
|
||||
#define NS_ERROR_FACTORY_NOT_LOADED ((nsresult) 0x800401f8L)
|
||||
|
||||
/* Returned when a factory doesn't support signatures */
|
||||
#define NS_ERROR_FACTORY_NO_SIGNATURE_SUPPORT \
|
||||
(NS_ERROR_BASE + 0x101)
|
||||
|
||||
/* Returned when a factory already is registered */
|
||||
#define NS_ERROR_FACTORY_EXISTS (NS_ERROR_BASE + 0x100)
|
||||
|
||||
|
||||
/* For COM compatibility reasons, we want to use exact error code numbers
|
||||
for NS_ERROR_PROXY_INVALID_IN_PARAMETER and NS_ERROR_PROXY_INVALID_OUT_PARAMETER.
|
||||
The first matches:
|
||||
|
||||
#define RPC_E_INVALID_PARAMETER _HRESULT_TYPEDEF_(0x80010010L)
|
||||
|
||||
Errors returning this mean that the xpcom proxy code could not create a proxy for
|
||||
one of the in paramaters.
|
||||
|
||||
Because of this, we are ignoring the convention if using a base and offset for
|
||||
error numbers.
|
||||
|
||||
*/
|
||||
|
||||
/* Returned when a proxy could not be create a proxy for one of the IN parameters
|
||||
This is returned only when the "real" meathod has NOT been invoked.
|
||||
*/
|
||||
|
||||
#define NS_ERROR_PROXY_INVALID_IN_PARAMETER ((nsresult) 0x80010010L)
|
||||
|
||||
/* Returned when a proxy could not be create a proxy for one of the OUT parameters
|
||||
This is returned only when the "real" meathod has ALREADY been invoked.
|
||||
*/
|
||||
|
||||
#define NS_ERROR_PROXY_INVALID_OUT_PARAMETER ((nsresult) 0x80010011L)
|
||||
|
||||
|
||||
/*@}*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef XP_PC
|
||||
#pragma warning(disable: 4251) // 'nsCOMPtr<class nsIInputStream>' needs to have dll-interface to be used by clients of class 'nsInputStream'
|
||||
#pragma warning(disable: 4275) // non dll-interface class 'nsISupports' used as base for dll-interface class 'nsIRDFNode'
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
126
mozilla/xpcom/build/dlldeps.cpp
Normal file
126
mozilla/xpcom/build/dlldeps.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
// Force references to all of the symbols that we want exported from
|
||||
// the dll that are located in the .lib files we link with
|
||||
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsFileSpec.h"
|
||||
//#include "nsIBuffer.h"
|
||||
//#include "nsIByteBufferInputStream.h"
|
||||
#include "nsFileStream.h"
|
||||
#include "nsFileSpecStreaming.h"
|
||||
#include "nsSpecialSystemDirectory.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsDeque.h"
|
||||
#include "nsObserver.h"
|
||||
#include "nsTraceRefcnt.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsIEnumerator.h"
|
||||
#include "nsEnumeratorUtils.h"
|
||||
#include "nsQuickSort.h"
|
||||
#include "nsString2.h"
|
||||
#include "nsProxyEventPrivate.h"
|
||||
#include "xpt_xdr.h"
|
||||
#include "nsInterfaceInfo.h"
|
||||
#include "xptcall.h"
|
||||
#include "nsIFileSpec.h"
|
||||
#include "nsIGenericFactory.h"
|
||||
#include "nsAVLTree.h"
|
||||
#include "nsHashtableEnumerator.h"
|
||||
#include "nsPipe2.h"
|
||||
#include "nsCWeakReference.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsISizeOfHandler.h"
|
||||
#include "nsTextFormater.h"
|
||||
#include "nsStorageStream.h"
|
||||
#include "nsIBinaryInputStream.h"
|
||||
#ifdef DEBUG
|
||||
#include "pure.h"
|
||||
#endif
|
||||
|
||||
class dummyComparitor: public nsAVLNodeComparitor {
|
||||
public:
|
||||
virtual PRInt32 operator()(void* anItem1,void* anItem2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
extern NS_COM void
|
||||
TestSegmentedBuffer();
|
||||
#endif
|
||||
|
||||
void XXXNeverCalled()
|
||||
{
|
||||
nsTextFormater::snprintf(nsnull,0,nsnull);
|
||||
dummyComparitor dummy;
|
||||
nsVoidArray();
|
||||
nsAVLTree(dummy, nsnull);
|
||||
NS_GetNumberOfAtoms();
|
||||
nsFileURL(NULL);
|
||||
// NS_NewPipe(NULL, NULL, 0, 0, 0, NULL);
|
||||
NS_NewPipe(NULL, NULL, NULL, 0, 0);
|
||||
nsFileSpec s;
|
||||
NS_NewIOFileStream(NULL, s, 0, 0);
|
||||
nsInputFileStream(s, 0, 0);
|
||||
nsPersistentFileDescriptor d;
|
||||
ReadDescriptor(NULL, d);
|
||||
new nsSpecialSystemDirectory(nsSpecialSystemDirectory::OS_DriveDirectory);
|
||||
nsIThread::GetCurrent(NULL);
|
||||
nsDeque(NULL);
|
||||
NS_NewObserver(NULL, NULL);
|
||||
nsTraceRefcnt::DumpStatistics();
|
||||
nsXPIDLCString::Copy(NULL);
|
||||
NS_NewEmptyEnumerator(NULL);
|
||||
nsArrayEnumerator(NULL);
|
||||
NS_NewIntersectionEnumerator(NULL, NULL, NULL);
|
||||
NS_QuickSort(NULL, 0, 0, NULL, NULL);
|
||||
nsString2();
|
||||
nsProxyObject(NULL, 0, NULL);
|
||||
XPT_DoString(NULL, NULL);
|
||||
XPT_DoHeader(NULL, NULL);
|
||||
nsInterfaceInfo* info = NULL;
|
||||
info->GetName(NULL);
|
||||
#ifdef DEBUG
|
||||
info->print(NULL);
|
||||
PurePrintf(0);
|
||||
#endif
|
||||
XPTC_InvokeByIndex(NULL, 0, 0, NULL);
|
||||
NS_NewFileSpec(NULL);
|
||||
xptc_dummy();
|
||||
xptc_dummy2();
|
||||
XPTI_GetInterfaceInfoManager();
|
||||
NS_NewGenericFactory(NULL, NULL, NULL);
|
||||
NS_NewHashtableEnumerator(NULL, NULL, NULL, NULL);
|
||||
nsCWeakProxy(0, 0);
|
||||
nsCWeakReferent(0);
|
||||
NS_GetWeakReference(NULL);
|
||||
#ifdef DEBUG
|
||||
TestSegmentedBuffer();
|
||||
#endif
|
||||
NS_NewSizeOfHandler(0);
|
||||
nsStorageStream();
|
||||
NS_NewBinaryInputStream(0, 0);
|
||||
}
|
||||
170
mozilla/xpcom/components/nsIGenericFactory.h
Normal file
170
mozilla/xpcom/components/nsIGenericFactory.h
Normal file
@@ -0,0 +1,170 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef nsIGenericFactory_h___
|
||||
#define nsIGenericFactory_h___
|
||||
|
||||
#include "nsIFactory.h"
|
||||
|
||||
// {3bc97f01-ccdf-11d2-bab8-b548654461fc}
|
||||
#define NS_GENERICFACTORY_CID \
|
||||
{ 0x3bc97f01, 0xccdf, 0x11d2, { 0xba, 0xb8, 0xb5, 0x48, 0x65, 0x44, 0x61, 0xfc } }
|
||||
|
||||
// {3bc97f00-ccdf-11d2-bab8-b548654461fc}
|
||||
#define NS_IGENERICFACTORY_IID \
|
||||
{ 0x3bc97f00, 0xccdf, 0x11d2, { 0xba, 0xb8, 0xb5, 0x48, 0x65, 0x44, 0x61, 0xfc } }
|
||||
|
||||
#define NS_GENERICFACTORY_PROGID "component:/netscape/generic-factory"
|
||||
#define NS_GENERICFACTORY_CLASSNAME "Generic Factory"
|
||||
/**
|
||||
* Provides a Generic nsIFactory implementation that can be used by
|
||||
* DLLs with very simple factory needs.
|
||||
*/
|
||||
class nsIGenericFactory : public nsIFactory {
|
||||
public:
|
||||
static const nsIID& GetIID() { static nsIID iid = NS_IGENERICFACTORY_IID; return iid; }
|
||||
|
||||
typedef NS_CALLBACK(ConstructorProcPtr) (nsISupports *aOuter, REFNSIID aIID, void **aResult);
|
||||
typedef NS_CALLBACK(DestructorProcPtr) (void);
|
||||
|
||||
/**
|
||||
* Establishes the generic factory's constructor function, which will be called
|
||||
* by CreateInstance.
|
||||
*/
|
||||
NS_IMETHOD SetConstructor(ConstructorProcPtr constructor) = 0;
|
||||
|
||||
/**
|
||||
* Establishes the generic factory's destructor function, which will be called
|
||||
* whe the generic factory is deleted. This is used to notify the DLL that
|
||||
* an instance of one of its generic factories is going away.
|
||||
*/
|
||||
NS_IMETHOD SetDestructor(DestructorProcPtr destructor) = 0;
|
||||
};
|
||||
|
||||
extern NS_COM nsresult
|
||||
NS_NewGenericFactory(nsIGenericFactory* *result,
|
||||
nsIGenericFactory::ConstructorProcPtr constructor,
|
||||
nsIGenericFactory::DestructorProcPtr destructor = NULL);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Generic Modules
|
||||
//
|
||||
// (See xpcom/sample/nsSampleModule.cpp to see how to use this.)
|
||||
|
||||
#include "nsIModule.h"
|
||||
|
||||
/**
|
||||
* Use this type to define a list of module component info to pass to
|
||||
* NS_NewGenericModule. E.g.:
|
||||
* static nsModuleComponentInfo components[] = { ... };
|
||||
* See xpcom/sample/nsSampleModule.cpp for more info.
|
||||
*/
|
||||
struct nsModuleComponentInfo {
|
||||
const char* mDescription;
|
||||
nsCID mCID;
|
||||
const char* mProgID;
|
||||
nsIGenericFactory::ConstructorProcPtr mConstructor;
|
||||
};
|
||||
|
||||
extern NS_COM nsresult
|
||||
NS_NewGenericModule(const char* moduleName,
|
||||
PRUint32 componentCount,
|
||||
nsModuleComponentInfo* components,
|
||||
nsIModule* *result);
|
||||
|
||||
#define NS_IMPL_NSGETMODULE(_name, _components) \
|
||||
extern "C" NS_EXPORT nsresult NSGetModule(nsIComponentManager *servMgr, \
|
||||
nsIFileSpec* location, \
|
||||
nsIModule** result) \
|
||||
{ \
|
||||
return NS_NewGenericModule((_name), \
|
||||
sizeof(_components) / sizeof(_components[0]), \
|
||||
(_components), result); \
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define NS_GENERIC_FACTORY_CONSTRUCTOR(_InstanceClass) \
|
||||
static NS_IMETHODIMP \
|
||||
_InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, void **aResult) \
|
||||
{ \
|
||||
nsresult rv; \
|
||||
\
|
||||
_InstanceClass * inst; \
|
||||
\
|
||||
if (NULL == aResult) { \
|
||||
rv = NS_ERROR_NULL_POINTER; \
|
||||
return rv; \
|
||||
} \
|
||||
*aResult = NULL; \
|
||||
if (NULL != aOuter) { \
|
||||
rv = NS_ERROR_NO_AGGREGATION; \
|
||||
return rv; \
|
||||
} \
|
||||
\
|
||||
NS_NEWXPCOM(inst, _InstanceClass); \
|
||||
if (NULL == inst) { \
|
||||
rv = NS_ERROR_OUT_OF_MEMORY; \
|
||||
return rv; \
|
||||
} \
|
||||
NS_ADDREF(inst); \
|
||||
rv = inst->QueryInterface(aIID, aResult); \
|
||||
NS_RELEASE(inst); \
|
||||
\
|
||||
return rv; \
|
||||
} \
|
||||
|
||||
|
||||
#define NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(_InstanceClass, _InitMethod) \
|
||||
static NS_IMETHODIMP \
|
||||
_InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, void **aResult) \
|
||||
{ \
|
||||
nsresult rv; \
|
||||
\
|
||||
_InstanceClass * inst; \
|
||||
\
|
||||
if (NULL == aResult) { \
|
||||
rv = NS_ERROR_NULL_POINTER; \
|
||||
return rv; \
|
||||
} \
|
||||
*aResult = NULL; \
|
||||
if (NULL != aOuter) { \
|
||||
rv = NS_ERROR_NO_AGGREGATION; \
|
||||
return rv; \
|
||||
} \
|
||||
\
|
||||
NS_NEWXPCOM(inst, _InstanceClass); \
|
||||
if (NULL == inst) { \
|
||||
rv = NS_ERROR_OUT_OF_MEMORY; \
|
||||
return rv; \
|
||||
} \
|
||||
NS_ADDREF(inst); \
|
||||
rv = inst->_InitMethod(); \
|
||||
if(NS_SUCCEEDED(rv)) { \
|
||||
rv = inst->QueryInterface(aIID, aResult); \
|
||||
} \
|
||||
NS_RELEASE(inst); \
|
||||
\
|
||||
return rv; \
|
||||
} \
|
||||
|
||||
#endif /* nsIGenericFactory_h___ */
|
||||
521
mozilla/xpcom/ds/nsHashtable.cpp
Normal file
521
mozilla/xpcom/ds/nsHashtable.cpp
Normal file
@@ -0,0 +1,521 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include "prmem.h"
|
||||
#include "prlog.h"
|
||||
#include "nsHashtable.h"
|
||||
|
||||
//
|
||||
// Key operations
|
||||
//
|
||||
|
||||
static PR_CALLBACK PLHashNumber _hashValue(const void *key)
|
||||
{
|
||||
return ((const nsHashKey *) key)->HashValue();
|
||||
}
|
||||
|
||||
static PR_CALLBACK PRIntn _hashKeyCompare(const void *key1, const void *key2) {
|
||||
return ((const nsHashKey *) key1)->Equals((const nsHashKey *) key2);
|
||||
}
|
||||
|
||||
static PR_CALLBACK PRIntn _hashValueCompare(const void *value1,
|
||||
const void *value2) {
|
||||
// We're not going to make any assumptions about value equality
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Memory callbacks
|
||||
//
|
||||
|
||||
static PR_CALLBACK void *_hashAllocTable(void *pool, PRSize size) {
|
||||
return PR_MALLOC(size);
|
||||
}
|
||||
|
||||
static PR_CALLBACK void _hashFreeTable(void *pool, void *item) {
|
||||
PR_DELETE(item);
|
||||
}
|
||||
|
||||
static PR_CALLBACK PLHashEntry *_hashAllocEntry(void *pool, const void *key) {
|
||||
return PR_NEW(PLHashEntry);
|
||||
}
|
||||
|
||||
static PR_CALLBACK void _hashFreeEntry(void *pool, PLHashEntry *entry,
|
||||
PRUintn flag) {
|
||||
if (flag == HT_FREE_ENTRY) {
|
||||
delete (nsHashKey *) (entry->key);
|
||||
PR_DELETE(entry);
|
||||
}
|
||||
}
|
||||
|
||||
static PLHashAllocOps _hashAllocOps = {
|
||||
_hashAllocTable, _hashFreeTable,
|
||||
_hashAllocEntry, _hashFreeEntry
|
||||
};
|
||||
|
||||
//
|
||||
// Enumerator callback
|
||||
//
|
||||
|
||||
struct _HashEnumerateArgs {
|
||||
nsHashtableEnumFunc fn;
|
||||
void* arg;
|
||||
};
|
||||
|
||||
static PR_CALLBACK PRIntn _hashEnumerate(PLHashEntry *he, PRIntn i, void *arg)
|
||||
{
|
||||
_HashEnumerateArgs* thunk = (_HashEnumerateArgs*)arg;
|
||||
return thunk->fn((nsHashKey *) he->key, he->value, thunk->arg)
|
||||
? HT_ENUMERATE_NEXT
|
||||
: HT_ENUMERATE_STOP;
|
||||
}
|
||||
|
||||
//
|
||||
// HashKey
|
||||
//
|
||||
nsHashKey::nsHashKey(void)
|
||||
{
|
||||
}
|
||||
|
||||
nsHashKey::~nsHashKey(void)
|
||||
{
|
||||
}
|
||||
|
||||
nsHashtable::nsHashtable(PRUint32 aInitSize, PRBool threadSafe)
|
||||
: mLock(NULL)
|
||||
{
|
||||
hashtable = PL_NewHashTable(aInitSize,
|
||||
_hashValue,
|
||||
_hashKeyCompare,
|
||||
_hashValueCompare,
|
||||
&_hashAllocOps,
|
||||
NULL);
|
||||
if (threadSafe == PR_TRUE)
|
||||
{
|
||||
mLock = PR_NewLock();
|
||||
if (mLock == NULL)
|
||||
{
|
||||
// Cannot create a lock. If running on a multiprocessing system
|
||||
// we are sure to die.
|
||||
PR_ASSERT(mLock != NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsHashtable::~nsHashtable() {
|
||||
PL_HashTableDestroy(hashtable);
|
||||
if (mLock) PR_DestroyLock(mLock);
|
||||
}
|
||||
|
||||
PRBool nsHashtable::Exists(nsHashKey *aKey)
|
||||
{
|
||||
PLHashNumber hash = aKey->HashValue();
|
||||
|
||||
if (mLock) PR_Lock(mLock);
|
||||
|
||||
PLHashEntry **hep = PL_HashTableRawLookup(hashtable, hash, (void *) aKey);
|
||||
|
||||
if (mLock) PR_Unlock(mLock);
|
||||
|
||||
return *hep != NULL;
|
||||
}
|
||||
|
||||
void *nsHashtable::Put(nsHashKey *aKey, void *aData) {
|
||||
void *res = NULL;
|
||||
PLHashNumber hash = aKey->HashValue();
|
||||
PLHashEntry *he;
|
||||
|
||||
if (mLock) PR_Lock(mLock);
|
||||
|
||||
PLHashEntry **hep = PL_HashTableRawLookup(hashtable, hash, (void *) aKey);
|
||||
|
||||
if ((he = *hep) != NULL) {
|
||||
res = he->value;
|
||||
he->value = aData;
|
||||
} else {
|
||||
PL_HashTableRawAdd(hashtable, hep, hash,
|
||||
(void *) aKey->Clone(), aData);
|
||||
}
|
||||
|
||||
if (mLock) PR_Unlock(mLock);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void *nsHashtable::Get(nsHashKey *aKey) {
|
||||
|
||||
if (mLock) PR_Lock(mLock);
|
||||
|
||||
void *ret = PL_HashTableLookup(hashtable, (void *) aKey);
|
||||
|
||||
if (mLock) PR_Unlock(mLock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *nsHashtable::Remove(nsHashKey *aKey) {
|
||||
PLHashNumber hash = aKey->HashValue();
|
||||
PLHashEntry *he;
|
||||
|
||||
if (mLock) PR_Lock(mLock);
|
||||
|
||||
PLHashEntry **hep = PL_HashTableRawLookup(hashtable, hash, (void *) aKey);
|
||||
void *res = NULL;
|
||||
|
||||
if ((he = *hep) != NULL) {
|
||||
res = he->value;
|
||||
PL_HashTableRawRemove(hashtable, hep, he);
|
||||
}
|
||||
|
||||
if (mLock) PR_Unlock(mLock);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// XXX This method was called _hashEnumerateCopy, but it didn't copy the element!
|
||||
// I don't know how this was supposed to work since the elements are neither copied
|
||||
// nor refcounted.
|
||||
static PR_CALLBACK PRIntn _hashEnumerateShare(PLHashEntry *he, PRIntn i, void *arg)
|
||||
{
|
||||
nsHashtable *newHashtable = (nsHashtable *)arg;
|
||||
newHashtable->Put((nsHashKey *) he->key, he->value);
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
nsHashtable * nsHashtable::Clone() {
|
||||
PRBool threadSafe = PR_FALSE;
|
||||
if (mLock)
|
||||
threadSafe = PR_TRUE;
|
||||
nsHashtable *newHashTable = new nsHashtable(hashtable->nentries, threadSafe);
|
||||
|
||||
PL_HashTableEnumerateEntries(hashtable, _hashEnumerateShare, newHashTable);
|
||||
return newHashTable;
|
||||
}
|
||||
|
||||
void nsHashtable::Enumerate(nsHashtableEnumFunc aEnumFunc, void* closure) {
|
||||
_HashEnumerateArgs thunk;
|
||||
thunk.fn = aEnumFunc;
|
||||
thunk.arg = closure;
|
||||
PL_HashTableEnumerateEntries(hashtable, _hashEnumerate, &thunk);
|
||||
}
|
||||
|
||||
static PR_CALLBACK PRIntn _hashEnumerateRemove(PLHashEntry *he, PRIntn i, void *arg)
|
||||
{
|
||||
_HashEnumerateArgs* thunk = (_HashEnumerateArgs*)arg;
|
||||
if (thunk)
|
||||
return thunk->fn((nsHashKey *) he->key, he->value, thunk->arg)
|
||||
? HT_ENUMERATE_REMOVE
|
||||
: HT_ENUMERATE_STOP;
|
||||
else
|
||||
return HT_ENUMERATE_REMOVE;
|
||||
}
|
||||
|
||||
void nsHashtable::Reset() {
|
||||
Reset(NULL);
|
||||
}
|
||||
|
||||
void nsHashtable::Reset(nsHashtableEnumFunc destroyFunc, void* closure)
|
||||
{
|
||||
if (destroyFunc != NULL)
|
||||
{
|
||||
_HashEnumerateArgs thunk;
|
||||
thunk.fn = destroyFunc;
|
||||
thunk.arg = closure;
|
||||
PL_HashTableEnumerateEntries(hashtable, _hashEnumerateRemove, &thunk);
|
||||
}
|
||||
else
|
||||
PL_HashTableEnumerateEntries(hashtable, _hashEnumerateRemove, NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsStringKey::nsStringKey(const char* str)
|
||||
{
|
||||
mStr.Assign(str);
|
||||
}
|
||||
|
||||
nsStringKey::nsStringKey(const PRUnichar* str)
|
||||
{
|
||||
mStr.Assign(str);
|
||||
}
|
||||
|
||||
nsStringKey::nsStringKey(const nsStr& str)
|
||||
{
|
||||
mStr.Assign(str);
|
||||
}
|
||||
|
||||
nsStringKey::~nsStringKey(void)
|
||||
{
|
||||
}
|
||||
|
||||
PRUint32 nsStringKey::HashValue(void) const
|
||||
{
|
||||
if(mStr.IsUnicode())
|
||||
{
|
||||
PRUint32 h;
|
||||
PRUint32 n;
|
||||
PRUint32 m;
|
||||
const PRUnichar* c;
|
||||
|
||||
h = 0;
|
||||
n = mStr.Length();
|
||||
c = mStr.GetUnicode();
|
||||
if(n < 16)
|
||||
{ /* Hash every char in a short string. */
|
||||
for(; n; c++, n--)
|
||||
h = (h >> 28) ^ (h << 4) ^ *c;
|
||||
}
|
||||
else
|
||||
{ /* Sample a la jave.lang.String.hash(). */
|
||||
for(m = n / 8; n >= m; c += m, n -= m)
|
||||
h = (h >> 28) ^ (h << 4) ^ *c;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
return (PRUint32)PL_HashString((const void*) mStr.GetBuffer());
|
||||
}
|
||||
|
||||
PRBool nsStringKey::Equals(const nsHashKey* aKey) const
|
||||
{
|
||||
return ((nsStringKey*)aKey)->mStr == mStr;
|
||||
}
|
||||
|
||||
nsHashKey* nsStringKey::Clone() const
|
||||
{
|
||||
return new nsStringKey(mStr);
|
||||
}
|
||||
|
||||
const nsString& nsStringKey::GetString() const
|
||||
{
|
||||
return mStr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsObjectHashtable: an nsHashtable where the elements are C++ objects to be
|
||||
// deleted
|
||||
|
||||
nsObjectHashtable::nsObjectHashtable(nsHashtableCloneElementFunc cloneElementFun,
|
||||
void* cloneElementClosure,
|
||||
nsHashtableEnumFunc destroyElementFun,
|
||||
void* destroyElementClosure,
|
||||
PRUint32 aSize, PRBool threadSafe)
|
||||
: nsHashtable(aSize, threadSafe),
|
||||
mCloneElementFun(cloneElementFun),
|
||||
mCloneElementClosure(cloneElementClosure),
|
||||
mDestroyElementFun(destroyElementFun),
|
||||
mDestroyElementClosure(destroyElementClosure)
|
||||
{
|
||||
}
|
||||
|
||||
nsObjectHashtable::~nsObjectHashtable()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
PR_CALLBACK PRIntn
|
||||
nsObjectHashtable::CopyElement(PLHashEntry *he, PRIntn i, void *arg)
|
||||
{
|
||||
nsObjectHashtable *newHashtable = (nsObjectHashtable *)arg;
|
||||
void* newElement =
|
||||
newHashtable->mCloneElementFun((nsHashKey*)he->key, he->value,
|
||||
newHashtable->mCloneElementClosure);
|
||||
if (newElement == nsnull)
|
||||
return HT_ENUMERATE_STOP;
|
||||
newHashtable->Put((nsHashKey*)he->key, newElement);
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
nsHashtable*
|
||||
nsObjectHashtable::Clone()
|
||||
{
|
||||
PRBool threadSafe = PR_FALSE;
|
||||
if (mLock)
|
||||
threadSafe = PR_TRUE;
|
||||
nsObjectHashtable* newHashTable =
|
||||
new nsObjectHashtable(mCloneElementFun, mCloneElementClosure,
|
||||
mDestroyElementFun, mDestroyElementClosure,
|
||||
hashtable->nentries, threadSafe);
|
||||
|
||||
PL_HashTableEnumerateEntries(hashtable, CopyElement, newHashTable);
|
||||
return newHashTable;
|
||||
}
|
||||
|
||||
void
|
||||
nsObjectHashtable::Reset()
|
||||
{
|
||||
nsHashtable::Reset(mDestroyElementFun, mDestroyElementClosure);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsObjectHashtable::RemoveAndDelete(nsHashKey *aKey)
|
||||
{
|
||||
void *value = Remove(aKey);
|
||||
if (value && mDestroyElementFun)
|
||||
{
|
||||
return (*mDestroyElementFun)(aKey, value, mDestroyElementClosure);
|
||||
}
|
||||
else
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsSupportsHashtable: an nsHashtable where the elements are nsISupports*
|
||||
|
||||
static PR_CALLBACK PRBool
|
||||
_ReleaseElement(nsHashKey *aKey, void *aData, void* closure)
|
||||
{
|
||||
nsISupports* element = NS_STATIC_CAST(nsISupports*, aData);
|
||||
NS_IF_RELEASE(element);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
nsSupportsHashtable::~nsSupportsHashtable()
|
||||
{
|
||||
Enumerate(_ReleaseElement, nsnull);
|
||||
}
|
||||
|
||||
void*
|
||||
nsSupportsHashtable::Put(nsHashKey *aKey, void *aData)
|
||||
{
|
||||
nsISupports* element = NS_STATIC_CAST(nsISupports*, aData);
|
||||
NS_IF_ADDREF(element);
|
||||
return nsHashtable::Put(aKey, aData);
|
||||
}
|
||||
|
||||
void*
|
||||
nsSupportsHashtable::Get(nsHashKey *aKey)
|
||||
{
|
||||
void* data = nsHashtable::Get(aKey);
|
||||
if (!data)
|
||||
return nsnull;
|
||||
nsISupports* element = NS_STATIC_CAST(nsISupports*, data);
|
||||
NS_IF_ADDREF(element);
|
||||
return data;
|
||||
}
|
||||
|
||||
void*
|
||||
nsSupportsHashtable::Remove(nsHashKey *aKey)
|
||||
{
|
||||
void* data = nsHashtable::Remove(aKey);
|
||||
if (!data)
|
||||
return nsnull;
|
||||
nsISupports* element = NS_STATIC_CAST(nsISupports*, data);
|
||||
NS_IF_RELEASE(element);
|
||||
return data;
|
||||
}
|
||||
|
||||
static PR_CALLBACK PRIntn
|
||||
_hashEnumerateCopy(PLHashEntry *he, PRIntn i, void *arg)
|
||||
{
|
||||
nsHashtable *newHashtable = (nsHashtable *)arg;
|
||||
nsISupports* element = NS_STATIC_CAST(nsISupports*, he->value);
|
||||
NS_IF_ADDREF(element);
|
||||
newHashtable->Put((nsHashKey*)he->key, he->value);
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
nsHashtable*
|
||||
nsSupportsHashtable::Clone()
|
||||
{
|
||||
PRBool threadSafe = PR_FALSE;
|
||||
if (mLock)
|
||||
threadSafe = PR_TRUE;
|
||||
nsSupportsHashtable* newHashTable =
|
||||
new nsSupportsHashtable(hashtable->nentries, threadSafe);
|
||||
|
||||
PL_HashTableEnumerateEntries(hashtable, _hashEnumerateCopy, newHashTable);
|
||||
return newHashTable;
|
||||
}
|
||||
|
||||
void
|
||||
nsSupportsHashtable::Reset()
|
||||
{
|
||||
Enumerate(_ReleaseElement, nsnull);
|
||||
nsHashtable::Reset();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsOpaqueKey: Where keys are opaque byte array blobs
|
||||
//
|
||||
|
||||
// Note opaque keys are not copied by this constructor. If you want a private
|
||||
// copy in each hash key, you must create one and pass it in to this function.
|
||||
nsOpaqueKey::nsOpaqueKey(const char *aOpaqueKey, PRUint32 aKeyLength)
|
||||
{
|
||||
mOpaqueKey = aOpaqueKey;
|
||||
mKeyLength = aKeyLength;
|
||||
}
|
||||
|
||||
nsOpaqueKey::~nsOpaqueKey(void)
|
||||
{
|
||||
}
|
||||
|
||||
PRUint32
|
||||
nsOpaqueKey::HashValue(void) const
|
||||
{
|
||||
PRUint32 h, i, k;
|
||||
|
||||
h = 0;
|
||||
|
||||
// Same hashing technique as for java.lang.String.hashCode()
|
||||
if (mKeyLength <= 15) {
|
||||
// A short key; Use a dense sampling to compute the hash code
|
||||
for (i = 0; i < mKeyLength; i++)
|
||||
h += 37 * mOpaqueKey[i];
|
||||
} else {
|
||||
// A long key; Use a sparse sampling to compute the hash code
|
||||
k = mKeyLength >> 3;
|
||||
for (i = 0; i < mKeyLength; i += k)
|
||||
h += 39 * mOpaqueKey[i];
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsOpaqueKey::Equals(const nsHashKey* aKey) const
|
||||
{
|
||||
nsOpaqueKey *otherKey = (nsOpaqueKey*)aKey;
|
||||
if (mKeyLength != otherKey->mKeyLength)
|
||||
return PR_FALSE;
|
||||
return !(PRBool)memcmp(otherKey->mOpaqueKey, mOpaqueKey, mKeyLength);
|
||||
}
|
||||
|
||||
nsHashKey*
|
||||
nsOpaqueKey::Clone() const
|
||||
{
|
||||
return new nsOpaqueKey(mOpaqueKey, mKeyLength);
|
||||
}
|
||||
|
||||
PRUint32
|
||||
nsOpaqueKey::GetKeyLength() const
|
||||
{
|
||||
return mKeyLength;
|
||||
}
|
||||
|
||||
const char*
|
||||
nsOpaqueKey::GetKey() const
|
||||
{
|
||||
return mOpaqueKey;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
248
mozilla/xpcom/ds/nsHashtable.h
Normal file
248
mozilla/xpcom/ds/nsHashtable.h
Normal file
@@ -0,0 +1,248 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef nsHashtable_h__
|
||||
#define nsHashtable_h__
|
||||
|
||||
#include "plhash.h"
|
||||
#include "prlock.h"
|
||||
#include "nsCom.h"
|
||||
|
||||
class NS_COM nsHashKey {
|
||||
protected:
|
||||
nsHashKey(void);
|
||||
public:
|
||||
virtual ~nsHashKey(void);
|
||||
virtual PRUint32 HashValue(void) const = 0;
|
||||
virtual PRBool Equals(const nsHashKey *aKey) const = 0;
|
||||
virtual nsHashKey *Clone(void) const = 0;
|
||||
};
|
||||
|
||||
// Enumerator callback function. Use
|
||||
|
||||
typedef PRBool (*nsHashtableEnumFunc)(nsHashKey *aKey, void *aData, void* closure);
|
||||
|
||||
class NS_COM nsHashtable {
|
||||
protected:
|
||||
// members
|
||||
PLHashTable *hashtable;
|
||||
PRLock *mLock;
|
||||
|
||||
public:
|
||||
nsHashtable(PRUint32 aSize = 256, PRBool threadSafe = PR_FALSE);
|
||||
~nsHashtable();
|
||||
|
||||
PRInt32 Count(void) { return hashtable->nentries; }
|
||||
PRBool Exists(nsHashKey *aKey);
|
||||
void *Put(nsHashKey *aKey, void *aData);
|
||||
void *Get(nsHashKey *aKey);
|
||||
void *Remove(nsHashKey *aKey);
|
||||
nsHashtable *Clone();
|
||||
void Enumerate(nsHashtableEnumFunc aEnumFunc, void* closure = NULL);
|
||||
void Reset();
|
||||
void Reset(nsHashtableEnumFunc destroyFunc, void* closure = NULL);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsObjectHashtable: an nsHashtable where the elements are C++ objects to be
|
||||
// deleted
|
||||
|
||||
typedef void* (*nsHashtableCloneElementFunc)(nsHashKey *aKey, void *aData, void* closure);
|
||||
|
||||
class NS_COM nsObjectHashtable : public nsHashtable {
|
||||
public:
|
||||
nsObjectHashtable(nsHashtableCloneElementFunc cloneElementFun,
|
||||
void* cloneElementClosure,
|
||||
nsHashtableEnumFunc destroyElementFun,
|
||||
void* destroyElementClosure,
|
||||
PRUint32 aSize = 256, PRBool threadSafe = PR_FALSE);
|
||||
~nsObjectHashtable();
|
||||
|
||||
nsHashtable *Clone();
|
||||
void Reset();
|
||||
PRBool RemoveAndDelete(nsHashKey *aKey);
|
||||
|
||||
protected:
|
||||
static PR_CALLBACK PRIntn CopyElement(PLHashEntry *he, PRIntn i, void *arg);
|
||||
|
||||
nsHashtableCloneElementFunc mCloneElementFun;
|
||||
void* mCloneElementClosure;
|
||||
nsHashtableEnumFunc mDestroyElementFun;
|
||||
void* mDestroyElementClosure;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsSupportsHashtable: an nsHashtable where the elements are nsISupports*
|
||||
|
||||
class NS_COM nsSupportsHashtable : public nsHashtable {
|
||||
public:
|
||||
nsSupportsHashtable(PRUint32 aSize = 256, PRBool threadSafe = PR_FALSE)
|
||||
: nsHashtable(aSize, threadSafe) {}
|
||||
~nsSupportsHashtable();
|
||||
|
||||
void *Put(nsHashKey *aKey, void *aData);
|
||||
void *Get(nsHashKey *aKey);
|
||||
void *Remove(nsHashKey *aKey);
|
||||
nsHashtable *Clone();
|
||||
void Reset();
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsISupportsKey: Where keys are nsISupports objects that get refcounted.
|
||||
|
||||
#include "nsISupports.h"
|
||||
|
||||
class nsISupportsKey : public nsHashKey {
|
||||
protected:
|
||||
nsISupports* mKey;
|
||||
|
||||
public:
|
||||
nsISupportsKey(nsISupports* key) {
|
||||
mKey = key;
|
||||
NS_IF_ADDREF(mKey);
|
||||
}
|
||||
|
||||
~nsISupportsKey(void) {
|
||||
NS_IF_RELEASE(mKey);
|
||||
}
|
||||
|
||||
PRUint32 HashValue(void) const {
|
||||
return (PRUint32)mKey;
|
||||
}
|
||||
|
||||
PRBool Equals(const nsHashKey *aKey) const {
|
||||
return (mKey == ((nsISupportsKey *) aKey)->mKey);
|
||||
}
|
||||
|
||||
nsHashKey *Clone(void) const {
|
||||
return new nsISupportsKey(mKey);
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsVoidKey: Where keys are void* objects that don't get refcounted.
|
||||
|
||||
class nsVoidKey : public nsHashKey {
|
||||
protected:
|
||||
const void* mKey;
|
||||
|
||||
public:
|
||||
nsVoidKey(const void* key) {
|
||||
mKey = key;
|
||||
}
|
||||
|
||||
PRUint32 HashValue(void) const {
|
||||
return (PRUint32)mKey;
|
||||
}
|
||||
|
||||
PRBool Equals(const nsHashKey *aKey) const {
|
||||
return (mKey == ((const nsVoidKey *) aKey)->mKey);
|
||||
}
|
||||
|
||||
nsHashKey *Clone(void) const {
|
||||
return new nsVoidKey(mKey);
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsIDKey: Where keys are nsIDs (e.g. nsIID, nsCID).
|
||||
|
||||
#include "nsID.h"
|
||||
|
||||
class nsIDKey : public nsHashKey {
|
||||
protected:
|
||||
nsID mID;
|
||||
|
||||
public:
|
||||
nsIDKey(const nsID &aID) {
|
||||
mID = aID;
|
||||
}
|
||||
|
||||
PRUint32 HashValue(void) const {
|
||||
return mID.m0;
|
||||
}
|
||||
|
||||
PRBool Equals(const nsHashKey *aKey) const {
|
||||
return (mID.Equals(((const nsIDKey *) aKey)->mID));
|
||||
}
|
||||
|
||||
nsHashKey *Clone(void) const {
|
||||
return new nsIDKey(mID);
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsStringKey: Where keys are PRUnichar* or char*
|
||||
// Some uses: hashing ProgIDs, filenames, URIs
|
||||
|
||||
#include "nsString.h"
|
||||
|
||||
class NS_COM nsStringKey : public nsHashKey {
|
||||
protected:
|
||||
nsAutoString mStr;
|
||||
|
||||
public:
|
||||
nsStringKey(const char* str);
|
||||
nsStringKey(const PRUnichar* str);
|
||||
nsStringKey(const nsStr& str);
|
||||
|
||||
~nsStringKey(void);
|
||||
|
||||
PRUint32 HashValue(void) const;
|
||||
|
||||
PRBool Equals(const nsHashKey* aKey) const;
|
||||
|
||||
nsHashKey* Clone() const;
|
||||
|
||||
// For when the owner of the hashtable wants to peek at the actual
|
||||
// string in the key. No copy is made, so be careful.
|
||||
const nsString& GetString() const;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsOpaqueKey: Where keys are opaque byte-array blobs
|
||||
|
||||
#include "nsString.h"
|
||||
|
||||
class NS_COM nsOpaqueKey : public nsHashKey {
|
||||
protected:
|
||||
const char* mOpaqueKey; // Byte array of opaque data
|
||||
PRUint32 mKeyLength; // Length, in bytes, of mOpaqueKey
|
||||
|
||||
public:
|
||||
// Note opaque keys are not copied by this constructor. If you want a private
|
||||
// copy in each hash key, you must create one and pass it in to this function.
|
||||
nsOpaqueKey(const char* aOpaqueKey, PRUint32 aKeyLength);
|
||||
|
||||
~nsOpaqueKey(void);
|
||||
|
||||
PRUint32 HashValue(void) const;
|
||||
PRBool Equals(const nsHashKey* aKey) const;
|
||||
nsHashKey* Clone() const;
|
||||
|
||||
// For when the owner of the hashtable wants to peek at the actual
|
||||
// opaque array in the key. No copy is made, so be careful.
|
||||
const char* GetKey() const;
|
||||
PRUint32 GetKeyLength() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
247
mozilla/xpcom/ds/nsHashtableEnumerator.cpp
Normal file
247
mozilla/xpcom/ds/nsHashtableEnumerator.cpp
Normal file
@@ -0,0 +1,247 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
/*
|
||||
* Implementation of nsHashEnumerator.
|
||||
* Use it to expose nsIEnumerator interfaces around nsHashtable objects.
|
||||
* Contributed by Rob Ginda, rginda@ix.netcom.com
|
||||
*/
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsHashtableEnumerator.h"
|
||||
|
||||
class nsHashtableEnumerator : public nsIBidirectionalEnumerator
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIENUMERATOR
|
||||
NS_DECL_NSIBIDIRECTIONALENUMERATOR
|
||||
|
||||
public:
|
||||
virtual ~nsHashtableEnumerator ();
|
||||
nsHashtableEnumerator (nsHashtable *aHash,
|
||||
NS_HASH_ENUMERATOR_CONVERTER aConverter,
|
||||
void *aData);
|
||||
nsHashtableEnumerator (); /* no implementation */
|
||||
|
||||
private:
|
||||
NS_IMETHOD Reset(nsHashtable *aHash,
|
||||
NS_HASH_ENUMERATOR_CONVERTER aConverter,
|
||||
void *aData);
|
||||
NS_IMETHOD ReleaseElements();
|
||||
|
||||
nsISupports **mElements;
|
||||
PRInt16 mCount, mCurrent;
|
||||
PRBool mDoneFlag;
|
||||
|
||||
};
|
||||
|
||||
struct nsHashEnumClosure
|
||||
{
|
||||
NS_HASH_ENUMERATOR_CONVERTER Converter;
|
||||
nsISupports **Elements;
|
||||
PRInt16 Current;
|
||||
void *Data;
|
||||
};
|
||||
|
||||
extern "C" NS_COM nsresult
|
||||
NS_NewHashtableEnumerator (nsHashtable *aHash,
|
||||
NS_HASH_ENUMERATOR_CONVERTER aConverter,
|
||||
void *aData, nsIEnumerator **retval)
|
||||
{
|
||||
NS_PRECONDITION (retval, "null ptr");
|
||||
|
||||
*retval = nsnull;
|
||||
|
||||
nsHashtableEnumerator *hte = new nsHashtableEnumerator (aHash, aConverter,
|
||||
aData);
|
||||
if (!hte)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
return hte->QueryInterface (nsCOMTypeInfo<nsIEnumerator>::GetIID(),
|
||||
(void **)retval);
|
||||
}
|
||||
|
||||
nsHashtableEnumerator::nsHashtableEnumerator (nsHashtable *aHash,
|
||||
NS_HASH_ENUMERATOR_CONVERTER aConverter,
|
||||
void *aData)
|
||||
: mElements(nsnull), mCount(0), mDoneFlag(PR_TRUE)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
Reset (aHash, aConverter, aData);
|
||||
|
||||
}
|
||||
|
||||
PRBool
|
||||
hash_enumerator (nsHashKey *aKey, void *aObject, void *closure)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsHashEnumClosure *c = (nsHashEnumClosure *)closure;
|
||||
|
||||
rv = c->Converter (aKey, (void *)aObject, (void *)c->Data,
|
||||
&c->Elements[c->Current]);
|
||||
|
||||
if (!NS_FAILED(rv))
|
||||
c->Current++;
|
||||
|
||||
return PR_TRUE;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHashtableEnumerator::Reset (nsHashtable *aHash,
|
||||
NS_HASH_ENUMERATOR_CONVERTER aConverter,
|
||||
void *aData)
|
||||
{
|
||||
nsHashEnumClosure c;
|
||||
|
||||
ReleaseElements();
|
||||
|
||||
mCurrent = c.Current = 0;
|
||||
mCount = aHash->Count();
|
||||
if (mCount == 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
mElements = c.Elements = new nsISupports*[mCount];
|
||||
c.Data = aData;
|
||||
c.Converter = aConverter;
|
||||
aHash->Enumerate (&hash_enumerator, &c);
|
||||
|
||||
mCount = c.Current; /* some items may not have converted correctly */
|
||||
mDoneFlag = PR_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHashtableEnumerator::ReleaseElements()
|
||||
{
|
||||
|
||||
for (; mCount > 0; mCount--)
|
||||
if (mElements[mCount - 1])
|
||||
NS_RELEASE(mElements[mCount - 1]);
|
||||
|
||||
delete[] mElements;
|
||||
mElements = nsnull;
|
||||
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsHashtableEnumerator, nsIBidirectionalEnumerator, nsIEnumerator)
|
||||
|
||||
nsHashtableEnumerator::~nsHashtableEnumerator()
|
||||
{
|
||||
ReleaseElements();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHashtableEnumerator::First ()
|
||||
{
|
||||
if (!mElements || (mCount == 0))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
mCurrent = 0;
|
||||
mDoneFlag = PR_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHashtableEnumerator::Last ()
|
||||
{
|
||||
if (!mElements || (mCount == 0))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
mCurrent = mCount - 1;
|
||||
mDoneFlag = PR_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHashtableEnumerator::Prev ()
|
||||
{
|
||||
if (!mElements || (mCount == 0) || (mCurrent == 0)) {
|
||||
mDoneFlag = PR_TRUE;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mCurrent--;
|
||||
mDoneFlag = PR_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHashtableEnumerator::Next ()
|
||||
{
|
||||
if (!mElements || (mCount == 0) || (mCurrent == mCount - 1)) {
|
||||
mDoneFlag = PR_TRUE;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mCurrent++;
|
||||
mDoneFlag = PR_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHashtableEnumerator::CurrentItem (nsISupports **retval)
|
||||
{
|
||||
NS_PRECONDITION (retval, "null ptr");
|
||||
NS_PRECONDITION (mElements, "invalid state");
|
||||
NS_ASSERTION (mCurrent >= 0, "mCurrent less than zero");
|
||||
|
||||
if (mCount == 0)
|
||||
{
|
||||
*retval = nsnull;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_ASSERTION (mCurrent <= mCount - 1, "mCurrent too high");
|
||||
|
||||
*retval = mElements[mCurrent];
|
||||
|
||||
/* who says the item can't be null? */
|
||||
if (*retval)
|
||||
NS_ADDREF(*retval);
|
||||
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHashtableEnumerator::IsDone ()
|
||||
{
|
||||
|
||||
if ((!mElements) || (mCount == 0) || (mDoneFlag))
|
||||
return NS_OK;
|
||||
|
||||
return NS_COMFALSE;
|
||||
}
|
||||
47
mozilla/xpcom/ds/nsHashtableEnumerator.h
Normal file
47
mozilla/xpcom/ds/nsHashtableEnumerator.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
/*
|
||||
* This class can be used to expose nsI(BiDirectional)Enumerator interfaces
|
||||
* around nsHashtable objects.
|
||||
* Contributed by Rob Ginda, rginda@ix.netcom.com
|
||||
*/
|
||||
|
||||
#ifndef nsHashtableEnumerator_h___
|
||||
#define nsHashtableEnumerator_h___
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsIEnumerator.h"
|
||||
#include "nsHashtable.h"
|
||||
|
||||
typedef NS_CALLBACK(NS_HASH_ENUMERATOR_CONVERTER) (nsHashKey *key, void *data,
|
||||
void *convert_data,
|
||||
nsISupports **retval);
|
||||
|
||||
extern "C" NS_COM nsresult
|
||||
NS_NewHashtableEnumerator (nsHashtable *aHash,
|
||||
NS_HASH_ENUMERATOR_CONVERTER aConverter,
|
||||
void *aData, nsIEnumerator **retval);
|
||||
|
||||
|
||||
#endif /* nsHashtableEnumerator_h___ */
|
||||
|
||||
1857
mozilla/xpcom/ds/nsString.cpp
Normal file
1857
mozilla/xpcom/ds/nsString.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user