зеркало из https://github.com/mozilla/pjs.git
Bug 27971. Better strategy for resource: urls to use less memory. Saves about 0.4% of entire run just bring up one page (home.mozilla.org). r=waterson
This commit is contained in:
Родитель
d457cdec7b
Коммит
0063d9a736
|
@ -1315,6 +1315,9 @@ NS_IMETHODIMP nsChromeRegistry::GetSelectedLocale(const PRUnichar *aPackageName,
|
|||
return rv;
|
||||
}
|
||||
|
||||
if (mChromeDataSource == nsnull)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// Follow the "selectedLocale" arc.
|
||||
nsCOMPtr<nsIRDFNode> selectedProvider;
|
||||
if (NS_FAILED(rv = mChromeDataSource->GetTarget(resource, mSelectedLocale, PR_TRUE, getter_AddRefs(selectedProvider)))) {
|
||||
|
|
|
@ -1038,16 +1038,16 @@ nsStdURL::SetFile(nsIFile * aFile)
|
|||
while (*s)
|
||||
{
|
||||
#ifndef XP_OS2
|
||||
// We need to call IsDBCSLeadByte because
|
||||
// Japanese windows can have 0x5C in the sencond byte
|
||||
// of a Japanese character, for example 0x8F 0x5C is
|
||||
// one Japanese character
|
||||
if(::IsDBCSLeadByte(*s) && *(s+1) != nsnull) {
|
||||
s++;
|
||||
// We need to call IsDBCSLeadByte because
|
||||
// Japanese windows can have 0x5C in the sencond byte
|
||||
// of a Japanese character, for example 0x8F 0x5C is
|
||||
// one Japanese character
|
||||
if(::IsDBCSLeadByte(*s) && *(s+1) != nsnull) {
|
||||
s++;
|
||||
} else
|
||||
#endif
|
||||
if (*s == '\\')
|
||||
*s = '/';
|
||||
if (*s == '\\')
|
||||
*s = '/';
|
||||
s++;
|
||||
}
|
||||
#endif
|
||||
|
@ -1057,8 +1057,14 @@ nsStdURL::SetFile(nsIFile * aFile)
|
|||
#endif
|
||||
// Escape the path with the directory mask
|
||||
rv = nsURLEscape(ePath,nsIIOService::url_Directory+
|
||||
nsIIOService::url_Forced,escPath);
|
||||
nsIIOService::url_Forced,escPath);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
PRBool dir;
|
||||
rv = aFile->IsDirectory(&dir);
|
||||
if (NS_SUCCEEDED(rv) && dir && escPath[escPath.Length() - 1] != '/') {
|
||||
// make sure we have a trailing slash
|
||||
escPath += "/";
|
||||
}
|
||||
rv = SetPath(escPath.GetBuffer());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "nsIProtocolHandler.idl"
|
||||
|
||||
interface nsISimpleEnumerator;
|
||||
native nsCStringArrayPtr(nsCStringArray*);
|
||||
interface nsISupportsArray;
|
||||
|
||||
%{C++
|
||||
#include "nsVoidArray.h"
|
||||
|
@ -65,10 +65,10 @@ interface nsIResProtocolHandler : nsIProtocolHandler
|
|||
void removeSubstitution(in string root, in string url);
|
||||
|
||||
/**
|
||||
* Returns a string array containing all substitutions currently
|
||||
* registered for the root. This array is a snapshot of the
|
||||
* Returns an nsISupportsArray of nsIURIs containing all substitutions
|
||||
* currently registered for the root. This array is a snapshot of the
|
||||
* registered entries so it can be iterated over without fear of
|
||||
* thread-safety concerns.
|
||||
*/
|
||||
[noscript] nsCStringArrayPtr getSubstitutions(in string root);
|
||||
nsISupportsArray getSubstitutions(in string root);
|
||||
};
|
||||
|
|
|
@ -80,7 +80,6 @@ nsResChannel::nsResChannel()
|
|||
nsresult
|
||||
nsResChannel::Init(nsIResProtocolHandler* handler, nsIURI* uri)
|
||||
{
|
||||
mResolvedURI = uri;
|
||||
mHandler = handler;
|
||||
mResourceURI = uri;
|
||||
return NS_OK;
|
||||
|
@ -124,32 +123,24 @@ nsResChannel::Substitutions::Init()
|
|||
char* root;
|
||||
rv = channel->mResourceURI->GetHost(&root);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = channel->mHandler->GetSubstitutions(root, &mSubstitutions);
|
||||
rv = channel->mHandler->GetSubstitutions(root, getter_AddRefs(mSubstitutions));
|
||||
nsCRT::free(root);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsResChannel::Substitutions::Next(nsIURI* *result)
|
||||
nsResChannel::Substitutions::Next(char* *result)
|
||||
{
|
||||
nsresult rv;
|
||||
nsResChannel* channel = GET_SUBSTITUTIONS_CHANNEL(this);
|
||||
|
||||
nsCString* str = (nsCString*)mSubstitutions->CStringAt(0);
|
||||
if (str == nsnull) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIURI> resolvedURI;
|
||||
rv = nsComponentManager::CreateInstance(kStandardURLCID, nsnull,
|
||||
NS_GET_IID(nsIURI),
|
||||
getter_AddRefs(resolvedURI));
|
||||
nsCOMPtr<nsIURI> substURI;
|
||||
rv = mSubstitutions->GetElementAt(mCurrentIndex++, getter_AddRefs(substURI));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = resolvedURI->SetSpec(str->GetBuffer());
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRBool ok = mSubstitutions->RemoveCStringAt(0);
|
||||
if (!ok) return NS_ERROR_FAILURE;
|
||||
if (substURI == nsnull)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
char* path = nsnull;
|
||||
rv = channel->mResourceURI->GetPath(&path);
|
||||
|
@ -157,17 +148,12 @@ nsResChannel::Substitutions::Next(nsIURI* *result)
|
|||
|
||||
// XXX this path[0] check is a hack -- it seems to me that GetPath
|
||||
// shouldn't include the leading slash:
|
||||
nsXPIDLCString aResolvedURI;
|
||||
rv = resolvedURI->Resolve(path[0] == '/' ? path+1 : path,
|
||||
getter_Copies(aResolvedURI));
|
||||
char* aResolvedURI;
|
||||
rv = substURI->Resolve(path[0] == '/' ? path+1 : path, &aResolvedURI);
|
||||
nsCRT::free(path);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = resolvedURI->SetSpec(aResolvedURI);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
*result = resolvedURI;
|
||||
NS_IF_ADDREF(*result);
|
||||
*result = aResolvedURI;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -204,7 +190,7 @@ nsResChannel::Cancel(nsresult status)
|
|||
rv = mResolvedChannel->Cancel(status);
|
||||
}
|
||||
mStatus = status;
|
||||
mResolvedURI = mResourceURI; // remove the resolution
|
||||
mResolvedChannel = nsnull; // remove the resolution
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -254,9 +240,10 @@ nsResChannel::SetOriginalURI(nsIURI* aURI)
|
|||
NS_IMETHODIMP
|
||||
nsResChannel::GetURI(nsIURI* *aURI)
|
||||
{
|
||||
if (mResolvedURI == nsnull)
|
||||
mResolvedURI = mResourceURI;
|
||||
*aURI = mResolvedURI;
|
||||
if (mResolvedChannel) {
|
||||
return mResolvedChannel->GetURI(aURI);
|
||||
}
|
||||
*aURI = mResourceURI;
|
||||
NS_ADDREF(*aURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -271,15 +258,16 @@ nsresult
|
|||
nsResChannel::EnsureNextResolvedChannel()
|
||||
{
|
||||
nsresult rv;
|
||||
nsXPIDLCString resolvedURI;
|
||||
|
||||
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) goto done;
|
||||
|
||||
rv = mSubstitutions.Next(getter_AddRefs(mResolvedURI));
|
||||
rv = mSubstitutions.Next(getter_Copies(resolvedURI));
|
||||
if (NS_FAILED(rv)) goto done;
|
||||
|
||||
rv = serv->NewChannelFromURI(mResolvedURI,
|
||||
getter_AddRefs(mResolvedChannel));
|
||||
rv = serv->NewChannel(resolvedURI, nsnull,
|
||||
getter_AddRefs(mResolvedChannel));
|
||||
if (NS_FAILED(rv)) {
|
||||
rv = NS_OK; // returning NS_OK lets us try again
|
||||
goto done;
|
||||
|
@ -322,15 +310,12 @@ nsResChannel::EnsureNextResolvedChannel()
|
|||
#if defined(PR_LOGGING)
|
||||
nsXPIDLCString resURI;
|
||||
(void)mResourceURI->GetSpec(getter_Copies(resURI));
|
||||
nsXPIDLCString newURI;
|
||||
if (mResolvedURI)
|
||||
(void)mResolvedURI->GetSpec(getter_Copies(newURI));
|
||||
PR_LOG(gResChannelLog, PR_LOG_DEBUG,
|
||||
("nsResChannel: resolving %s ",
|
||||
(const char*)resURI));
|
||||
PR_LOG(gResChannelLog, PR_LOG_DEBUG,
|
||||
(" to %s => status %x\n",
|
||||
(const char*)newURI, rv));
|
||||
(const char*)resolvedURI, rv));
|
||||
#endif /* PR_LOGGING */
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsILoadGroup.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAutoLock.h"
|
||||
#ifdef DEBUG
|
||||
|
@ -59,19 +60,15 @@ public:
|
|||
protected:
|
||||
class Substitutions {
|
||||
public:
|
||||
Substitutions() : mSubstitutions(nsnull) {}
|
||||
~Substitutions(){
|
||||
if (mSubstitutions) {
|
||||
delete mSubstitutions;
|
||||
mSubstitutions = nsnull;
|
||||
}
|
||||
}
|
||||
Substitutions() : mCurrentIndex(0) {}
|
||||
~Substitutions() {}
|
||||
|
||||
nsresult Init();
|
||||
nsresult Next(nsIURI* *result);
|
||||
nsresult Next(char* *result);
|
||||
protected:
|
||||
nsCOMPtr<nsIURI> mResourceURI;
|
||||
nsCStringArray* mSubstitutions;
|
||||
nsCOMPtr<nsISupportsArray> mSubstitutions;
|
||||
PRUint32 mCurrentIndex;
|
||||
};
|
||||
friend class Substitutions;
|
||||
|
||||
|
@ -100,7 +97,6 @@ protected:
|
|||
protected:
|
||||
nsCOMPtr<nsIURI> mOriginalURI;
|
||||
nsCOMPtr<nsIURI> mResourceURI;
|
||||
nsCOMPtr<nsIURI> mResolvedURI;
|
||||
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
|
||||
PRUint32 mLoadAttributes;
|
||||
nsCOMPtr<nsILoadGroup> mLoadGroup;
|
||||
|
|
|
@ -37,14 +37,17 @@
|
|||
#include "nsResProtocolHandler.h"
|
||||
#include "nsAutoLock.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsResChannel.h"
|
||||
#include "prenv.h"
|
||||
#include "prmem.h"
|
||||
#include "prprf.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsIFile.h"
|
||||
|
||||
static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID);
|
||||
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -55,12 +58,27 @@ nsResProtocolHandler::nsResProtocolHandler()
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsResProtocolHandler::SetSpecialDir(const char* name, nsSpecialSystemDirectory::SystemDirectories sysDir)
|
||||
nsResProtocolHandler::SetSpecialDir(const char* rootName, const char* sysDir)
|
||||
{
|
||||
nsSpecialSystemDirectory dir(sysDir);
|
||||
nsFileURL fileURL(dir);
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIFile> file;
|
||||
rv = NS_GetSpecialDirectory(sysDir, getter_AddRefs(file));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return AppendSubstitution(name, fileURL.GetURLString());
|
||||
nsCOMPtr<nsIFileURL> fileURL;
|
||||
rv = nsComponentManager::CreateInstance(kStandardURLCID, nsnull,
|
||||
NS_GET_IID(nsIFileURL),
|
||||
getter_AddRefs(fileURL));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = fileURL->SetFile(file);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsXPIDLCString spec;
|
||||
rv = fileURL->GetSpec(getter_Copies(spec));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return AppendSubstitution(rootName, spec);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -73,36 +91,36 @@ nsResProtocolHandler::Init()
|
|||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// set up initial mappings
|
||||
rv = SetSpecialDir("ProgramDir", nsSpecialSystemDirectory::Moz_BinDirectory);
|
||||
rv = SetSpecialDir("ProgramDir", "system.OS_CurrentProcessDirectory");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// make "res:///" == "resource:/"
|
||||
rv = SetSpecialDir("", nsSpecialSystemDirectory::Moz_BinDirectory);
|
||||
rv = SetSpecialDir("", "system.OS_CurrentProcessDirectory");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = SetSpecialDir("CurrentDir", nsSpecialSystemDirectory::OS_CurrentWorkingDirectory);
|
||||
rv = SetSpecialDir("CurrentDir", "system.OS_CurrentWorkingDirectory");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = SetSpecialDir("CurrentDrive", nsSpecialSystemDirectory::OS_DriveDirectory);
|
||||
rv = SetSpecialDir("CurrentDrive", "system.OS_DriveDirectory");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = SetSpecialDir("TempDir", nsSpecialSystemDirectory::OS_TemporaryDirectory);
|
||||
rv = SetSpecialDir("TempDir", "system.OS_TemporaryDirectory");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = SetSpecialDir("ComponentsDir", nsSpecialSystemDirectory::XPCOM_CurrentProcessComponentDirectory);
|
||||
rv = SetSpecialDir("ComponentsDir", "xpcom.currentProcess.componentDirectory");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = SetSpecialDir("SystemDir",
|
||||
#ifdef XP_MAC
|
||||
nsSpecialSystemDirectory::Mac_SystemDirectory
|
||||
"system.SystemDirectory"
|
||||
#elif XP_OS2
|
||||
nsSpecialSystemDirectory::OS2_SystemDirectory
|
||||
"system.SystemDirectory"
|
||||
#elif XP_PC
|
||||
nsSpecialSystemDirectory::Win_SystemDirectory
|
||||
"system.SystemDirectory"
|
||||
#elif XP_BEOS
|
||||
nsSpecialSystemDirectory::BeOS_SystemDirectory
|
||||
"system.SystemDirectory"
|
||||
#else
|
||||
nsSpecialSystemDirectory::Unix_LibDirectory // XXX ???
|
||||
"system.LibDirectory" // XXX ???
|
||||
#endif
|
||||
);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
@ -110,78 +128,16 @@ nsResProtocolHandler::Init()
|
|||
// Set up the "Resource" root to point to the old resource location
|
||||
// such that:
|
||||
// resource://<path> == res://Resource/<path>
|
||||
#ifdef XP_PC
|
||||
|
||||
// XXX why is this one inconsistent -- Mac Unix and BeOS seem to look inthe current process dir
|
||||
rv = SetSpecialDir("Resource", nsSpecialSystemDirectory::XPCOM_CurrentProcessComponentRegistry);
|
||||
rv = SetSpecialDir("Resource", "system.OS_CurrentProcessDirectory");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
#elif defined (XP_MAC)
|
||||
|
||||
rv = SetSpecialDir("Resource", nsSpecialSystemDirectory::OS_CurrentProcessDirectory);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
#elif defined(XP_UNIX)
|
||||
|
||||
#ifndef MAXPATHLEN
|
||||
#define MAXPATHLEN 1024 // A good guess, i suppose
|
||||
#endif
|
||||
|
||||
// first add $MOZILLA_FIVE_HOME if it exists
|
||||
char* path = PR_GetEnv("MOZILLA_FIVE_HOME");
|
||||
if (path) {
|
||||
char* fileURL = PR_smprintf("file:///%s", path);
|
||||
rv = AppendSubstitution("Resource", fileURL);
|
||||
PR_Free(fileURL);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
// then add pwd
|
||||
char homepath[MAXPATHLEN];
|
||||
FILE* pp;
|
||||
if (!(pp = popen("pwd", "r"))) {
|
||||
NS_WARNING("res protocol: can't open pwd");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (fgets(homepath, MAXPATHLEN, pp)) {
|
||||
homepath[PL_strlen(homepath)-1] = 0;
|
||||
}
|
||||
else {
|
||||
NS_WARNING("res protocol: can't get homepath");
|
||||
|
||||
pclose(pp);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
pclose(pp);
|
||||
char* fileURL = PR_smprintf("file:///%s", homepath);
|
||||
rv = AppendSubstitution("Resource", fileURL);
|
||||
PR_Free(fileURL);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
#elif defined(XP_BEOS)
|
||||
|
||||
rv = SetSpecialDir("Resource", nsSpecialSystemDirectory::XPCOM_CurrentProcessComponentRegistry);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static PRBool PR_CALLBACK
|
||||
DeleteCStringArray(nsHashKey *aKey, void *aData, void* closure)
|
||||
{
|
||||
nsCStringArray* array = NS_STATIC_CAST(nsCStringArray*, aData);
|
||||
if (array)
|
||||
delete array;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
nsResProtocolHandler::~nsResProtocolHandler()
|
||||
{
|
||||
if (mLock)
|
||||
PR_DestroyLock(mLock);
|
||||
mSubstitutions.Enumerate(DeleteCStringArray, nsnull);
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS2(nsResProtocolHandler, nsIResProtocolHandler, nsIProtocolHandler)
|
||||
|
@ -277,97 +233,150 @@ nsResProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult
|
||||
nsResProtocolHandler::RawGetSubstitutions(const char *root, nsCStringArray* *result)
|
||||
NS_IMETHODIMP
|
||||
nsResProtocolHandler::PrependSubstitution(const char *root, const char *urlStr)
|
||||
{
|
||||
nsresult rv;
|
||||
nsAutoLock lock(mLock);
|
||||
|
||||
nsCOMPtr<nsIIOService> ioServ = do_GetService(kIOServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsCOMPtr<nsIURI> url;
|
||||
rv = ioServ->NewURI(urlStr, nsnull, getter_AddRefs(url));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsStringKey key(root);
|
||||
nsCStringArray* strings = (nsCStringArray*)mSubstitutions.Get(&key);
|
||||
nsCOMPtr<nsISupportsArray> strings;
|
||||
nsCOMPtr<nsISupportsArray> newStrings;
|
||||
|
||||
strings = getter_AddRefs((nsISupportsArray*)mSubstitutions.Get(&key));
|
||||
if (strings) {
|
||||
// we have to snapshot the array when inserting a new element because
|
||||
// someone could be iterating over the existing array
|
||||
rv = strings->Clone(getter_AddRefs(newStrings));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
else {
|
||||
rv = NS_NewISupportsArray(getter_AddRefs(newStrings));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
rv = newStrings->InsertElementAt(url, 0) ? NS_OK : NS_ERROR_FAILURE;
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// replace existing array
|
||||
(void)mSubstitutions.Put(&key, newStrings);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResProtocolHandler::AppendSubstitution(const char *root, const char *urlStr)
|
||||
{
|
||||
nsresult rv;
|
||||
nsAutoLock lock(mLock);
|
||||
|
||||
nsCOMPtr<nsIIOService> ioServ = do_GetService(kIOServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsCOMPtr<nsIURI> url;
|
||||
rv = ioServ->NewURI(urlStr, nsnull, getter_AddRefs(url));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsStringKey key(root);
|
||||
nsCOMPtr<nsISupportsArray> strings;
|
||||
nsCOMPtr<nsISupportsArray> newStrings;
|
||||
|
||||
strings = getter_AddRefs((nsISupportsArray*)mSubstitutions.Get(&key));
|
||||
if (strings) {
|
||||
// we have to snapshot the array when inserting a new element because
|
||||
// someone could be iterating over the existing array
|
||||
rv = strings->Clone(getter_AddRefs(newStrings));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
else {
|
||||
rv = NS_NewISupportsArray(getter_AddRefs(newStrings));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
rv = newStrings->AppendElement(url) ? NS_OK : NS_ERROR_FAILURE;
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// replace existing array
|
||||
(void)mSubstitutions.Put(&key, newStrings);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
struct CopyMostArgs {
|
||||
nsISupportsArray* mNewArray;
|
||||
nsIURI* mRemoveURL;
|
||||
};
|
||||
|
||||
static PRBool
|
||||
CopyMost(nsISupports* aElement, void *aData)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
CopyMostArgs* args = (CopyMostArgs*)aData;
|
||||
nsIURI* thisURL = (nsIURI*)aElement;
|
||||
PRBool eq;
|
||||
rv = thisURL->Equals(args->mRemoveURL, &eq);
|
||||
if (NS_FAILED(rv)) return PR_FALSE;
|
||||
if (!eq) {
|
||||
rv = args->mNewArray->AppendElement(thisURL) ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResProtocolHandler::RemoveSubstitution(const char *root, const char *urlStr)
|
||||
{
|
||||
nsresult rv;
|
||||
nsAutoLock lock(mLock);
|
||||
|
||||
nsCOMPtr<nsIIOService> ioServ = do_GetService(kIOServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsCOMPtr<nsIURI> url;
|
||||
rv = ioServ->NewURI(urlStr, nsnull, getter_AddRefs(url));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsStringKey key(root);
|
||||
nsCOMPtr<nsISupportsArray> strings;
|
||||
nsCOMPtr<nsISupportsArray> newStrings;
|
||||
|
||||
strings = getter_AddRefs((nsISupportsArray*)mSubstitutions.Get(&key));
|
||||
if (strings == nsnull) {
|
||||
strings = new nsCStringArray();
|
||||
if (strings == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
// can't remove element if it doesn't exist
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
rv = NS_NewISupportsArray(getter_AddRefs(newStrings));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
CopyMostArgs args;
|
||||
args.mNewArray = newStrings;
|
||||
args.mRemoveURL = url;
|
||||
PRBool ok = strings->EnumerateForwards(CopyMost, &args);
|
||||
rv = ok ? NS_OK : NS_ERROR_FAILURE;
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// replace existing array
|
||||
(void)mSubstitutions.Put(&key, newStrings);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResProtocolHandler::GetSubstitutions(const char *root, nsISupportsArray* *result)
|
||||
{
|
||||
nsresult rv;
|
||||
nsAutoLock lock(mLock);
|
||||
|
||||
nsStringKey key(root);
|
||||
nsISupportsArray* strings = (nsISupportsArray*)mSubstitutions.Get(&key);
|
||||
if (strings == nsnull) {
|
||||
rv = NS_NewISupportsArray(&strings);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
(void)mSubstitutions.Put(&key, strings);
|
||||
}
|
||||
*result = strings;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResProtocolHandler::PrependSubstitution(const char *root, const char *url)
|
||||
{
|
||||
nsresult rv;
|
||||
nsAutoLock lock(mLock);
|
||||
|
||||
nsCStringArray* strings;
|
||||
rv = RawGetSubstitutions(root, &strings);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCString urlStr(url);
|
||||
PRBool ok = strings->InsertCStringAt(urlStr, 0);
|
||||
if (!ok) return NS_ERROR_FAILURE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResProtocolHandler::AppendSubstitution(const char *root, const char *url)
|
||||
{
|
||||
nsresult rv;
|
||||
nsAutoLock lock(mLock);
|
||||
|
||||
nsCStringArray* strings;
|
||||
rv = RawGetSubstitutions(root, &strings);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCString urlStr(url);
|
||||
PRBool ok = strings->AppendCString(urlStr);
|
||||
if (!ok) return NS_ERROR_FAILURE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResProtocolHandler::RemoveSubstitution(const char *root, const char *url)
|
||||
{
|
||||
nsresult rv;
|
||||
nsAutoLock lock(mLock);
|
||||
|
||||
nsCStringArray* strings;
|
||||
rv = RawGetSubstitutions(root, &strings);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCString urlStr(url);
|
||||
PRBool ok = strings->RemoveCString(urlStr);
|
||||
if (!ok) return NS_ERROR_FAILURE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsResProtocolHandler::GetSubstitutions(const char *root, nsCStringArray* *result)
|
||||
{
|
||||
nsresult rv;
|
||||
nsAutoLock lock(mLock);
|
||||
|
||||
nsCStringArray* strings;
|
||||
rv = RawGetSubstitutions(root, &strings);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// XXX should put this in nsCStringArray::Clone
|
||||
nsCStringArray* subst = new nsCStringArray();
|
||||
if (subst == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
PRInt32 len = strings->Count();
|
||||
for (PRInt32 i = 0; i < len; i++) {
|
||||
PRBool ok = subst->AppendCString(*(*strings)[i]);
|
||||
if (!ok) {
|
||||
delete subst;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
*result = subst;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
#include "nsIResProtocolHandler.h"
|
||||
#include "nsHashtable.h"
|
||||
#include "nsSpecialSystemDirectory.h"
|
||||
#include "nsISupportsArray.h"
|
||||
|
||||
class nsResProtocolHandler : public nsIResProtocolHandler
|
||||
{
|
||||
|
@ -42,12 +42,11 @@ public:
|
|||
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
|
||||
|
||||
nsresult Init();
|
||||
nsresult SetSpecialDir(const char* name, nsSpecialSystemDirectory::SystemDirectories sysDir);
|
||||
nsresult RawGetSubstitutions(const char *root, nsCStringArray* *result);
|
||||
nsresult SetSpecialDir(const char* rootName, const char* specialDir);
|
||||
|
||||
protected:
|
||||
PRLock* mLock;
|
||||
nsHashtable mSubstitutions;
|
||||
nsSupportsHashtable mSubstitutions;
|
||||
};
|
||||
|
||||
#endif /* nsResProtocolHandler_h___ */
|
||||
|
|
|
@ -1315,6 +1315,9 @@ NS_IMETHODIMP nsChromeRegistry::GetSelectedLocale(const PRUnichar *aPackageName,
|
|||
return rv;
|
||||
}
|
||||
|
||||
if (mChromeDataSource == nsnull)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// Follow the "selectedLocale" arc.
|
||||
nsCOMPtr<nsIRDFNode> selectedProvider;
|
||||
if (NS_FAILED(rv = mChromeDataSource->GetTarget(resource, mSelectedLocale, PR_TRUE, getter_AddRefs(selectedProvider)))) {
|
||||
|
|
|
@ -85,6 +85,8 @@ interface nsISupportsArray : nsICollection {
|
|||
[notxpcom, noscript]
|
||||
boolean EnumerateBackwards(in nsISupportsArrayEnumFunc aFunc,
|
||||
in voidPtr aData);
|
||||
|
||||
nsISupportsArray clone();
|
||||
%{C++
|
||||
private:
|
||||
// NS_IMETHOD_(nsISupportsArray&) operator=(const nsISupportsArray& other) = 0;
|
||||
|
|
|
@ -382,6 +382,27 @@ nsSupportsArray::Enumerate(nsIEnumerator* *result)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
CopyElement(nsISupports* aElement, void *aData)
|
||||
{
|
||||
nsresult rv;
|
||||
nsISupportsArray* newArray = (nsISupportsArray*)aData;
|
||||
rv = newArray->AppendElement(aElement);
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSupportsArray::Clone(nsISupportsArray* *result)
|
||||
{
|
||||
nsresult rv;
|
||||
nsISupportsArray* newArray;
|
||||
rv = NS_NewISupportsArray(&newArray);
|
||||
PRBool ok = EnumerateForwards(CopyElement, newArray);
|
||||
if (!ok) return NS_ERROR_OUT_OF_MEMORY;
|
||||
*result = newArray;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_COM nsresult
|
||||
NS_NewISupportsArray(nsISupportsArray** aInstancePtrResult)
|
||||
{
|
||||
|
|
|
@ -115,6 +115,8 @@ public:
|
|||
NS_IMETHOD_(PRBool) EnumerateForwards(nsISupportsArrayEnumFunc aFunc, void* aData);
|
||||
NS_IMETHOD_(PRBool) EnumerateBackwards(nsISupportsArrayEnumFunc aFunc, void* aData);
|
||||
|
||||
NS_IMETHOD Clone(nsISupportsArray **_retval);
|
||||
|
||||
protected:
|
||||
NS_IMETHOD_(nsISupportsArray&) operator=(const nsISupportsArray& aOther);
|
||||
NS_IMETHOD_(PRBool) operator==(const nsISupportsArray& aOther) { return Equals(&aOther); }
|
||||
|
|
Загрузка…
Ссылка в новой задаче