From cae8263e6d7385c6d1cc39c03a5a95377f0fc454 Mon Sep 17 00:00:00 2001 From: "darin%meer.net" Date: Tue, 7 Sep 2004 18:59:07 +0000 Subject: [PATCH] landing v1.1 patch for 257162 "core changes required to enable XULRunner functionality" r=bsmedberg --- chrome/src/nsChromeFactory.cpp | 3 +- chrome/src/nsChromeProtocolHandler.cpp | 253 +++++------------- chrome/src/nsChromeProtocolHandler.h | 9 +- chrome/src/nsChromeRegistry.cpp | 135 +++++++--- chrome/src/nsChromeRegistry.h | 5 +- .../protocol/res/src/nsResProtocolHandler.cpp | 25 +- toolkit/xre/nsAppRunner.cpp | 93 ++++++- toolkit/xre/nsXREDirProvider.cpp | 88 ++++-- toolkit/xre/nsXREDirProvider.h | 3 +- xpcom/io/nsAppDirectoryServiceDefs.h | 1 + 10 files changed, 352 insertions(+), 263 deletions(-) diff --git a/chrome/src/nsChromeFactory.cpp b/chrome/src/nsChromeFactory.cpp index 084956d9028..3f0f089406e 100644 --- a/chrome/src/nsChromeFactory.cpp +++ b/chrome/src/nsChromeFactory.cpp @@ -48,6 +48,7 @@ #include "nsChromeRegistry.h" NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsChromeRegistry, Init) +NS_GENERIC_FACTORY_CONSTRUCTOR(nsChromeProtocolHandler) // The list of components we register static const nsModuleComponentInfo components[] = @@ -61,7 +62,7 @@ static const nsModuleComponentInfo components[] = { "Chrome Protocol Handler", NS_CHROMEPROTOCOLHANDLER_CID, NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "chrome", - nsChromeProtocolHandler::Create + nsChromeProtocolHandlerConstructor } }; diff --git a/chrome/src/nsChromeProtocolHandler.cpp b/chrome/src/nsChromeProtocolHandler.cpp index 6b7552a73d4..23aca0b8f6e 100644 --- a/chrome/src/nsChromeProtocolHandler.cpp +++ b/chrome/src/nsChromeProtocolHandler.cpp @@ -1,4 +1,5 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:set ts=4 sw=4 sts=4 et cin: */ /* ***** BEGIN LICENSE BLOCK ***** * Version: NPL 1.1/GPL 2.0/LGPL 2.1 * @@ -45,6 +46,7 @@ #include "nsCOMPtr.h" #include "nsContentCID.h" #include "nsCRT.h" +#include "nsEventQueueUtils.h" #include "nsIChannel.h" #include "nsIChromeRegistry.h" #include "nsIComponentManager.h" @@ -67,16 +69,13 @@ #include "nsIXULPrototypeCache.h" #include "nsIXULPrototypeDocument.h" #endif -#include "nsNetCID.h" +#include "nsNetUtil.h" #include "nsXPIDLString.h" #include "nsString.h" #include "prlog.h" //---------------------------------------------------------------------- -static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); -static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); -static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID); #ifdef MOZ_XUL static NS_DEFINE_CID(kXULPrototypeCacheCID, NS_XULPROTOTYPECACHE_CID); #endif @@ -105,12 +104,12 @@ extern nsIChromeRegistry* gChromeRegistry; // // For logging information, NSPR_LOG_MODULES=nsCachedChromeChannel:5 // +#define LOG(args) PR_LOG(gLog, PR_LOG_DEBUG, args) class nsCachedChromeChannel : public nsIChannel { protected: - nsCachedChromeChannel(nsIURI* aURI); - virtual ~nsCachedChromeChannel(); + ~nsCachedChromeChannel(); nsCOMPtr mURI; nsCOMPtr mLoadGroup; @@ -120,16 +119,10 @@ protected: nsCOMPtr mOwner; nsresult mStatus; - struct LoadEvent { - PLEvent mEvent; - nsCachedChromeChannel* mChannel; - }; - - static nsresult + static NS_HIDDEN_(nsresult) PostLoadEvent(nsCachedChromeChannel* aChannel, PLHandleEventProc aHandler); - static void* PR_CALLBACK HandleStartLoadEvent(PLEvent* aEvent); - static void* PR_CALLBACK HandleStopLoadEvent(PLEvent* aEvent); + static void* PR_CALLBACK HandleLoadEvent(PLEvent* aEvent); static void PR_CALLBACK DestroyLoadEvent(PLEvent* aEvent); #ifdef PR_LOGGING @@ -137,18 +130,17 @@ protected: #endif public: - static nsresult - Create(nsIURI* aURI, nsIChannel** aResult); - + nsCachedChromeChannel(nsIURI* aURI); + NS_DECL_ISUPPORTS // nsIRequest - NS_IMETHOD GetName(nsACString &result) { return NS_ERROR_NOT_IMPLEMENTED; } - NS_IMETHOD IsPending(PRBool *_retval) { *_retval = PR_TRUE; return NS_OK; } + NS_IMETHOD GetName(nsACString &result) { return mURI->GetSpec(result); } + NS_IMETHOD IsPending(PRBool *_retval) { *_retval = (mListener != nsnull); return NS_OK; } NS_IMETHOD GetStatus(nsresult *status) { *status = mStatus; return NS_OK; } NS_IMETHOD Cancel(nsresult status) { mStatus = status; return NS_OK; } - NS_IMETHOD Suspend(void) { return NS_OK; } - NS_IMETHOD Resume(void) { return NS_OK; } + NS_IMETHOD Suspend(void) { return NS_OK; } // XXX technically wrong + NS_IMETHOD Resume(void) { return NS_OK; } // XXX technically wrong NS_IMETHOD GetLoadGroup(nsILoadGroup **); NS_IMETHOD SetLoadGroup(nsILoadGroup *); NS_IMETHOD GetLoadFlags(nsLoadFlags *); @@ -167,40 +159,24 @@ NS_IMPL_ISUPPORTS2(nsCachedChromeChannel, nsIChannel, nsIRequest) -nsresult -nsCachedChromeChannel::Create(nsIURI* aURI, nsIChannel** aResult) -{ - NS_PRECONDITION(aURI != nsnull, "null ptr"); - if (! aURI) - return NS_ERROR_NULL_POINTER; - - nsCachedChromeChannel* channel = new nsCachedChromeChannel(aURI); - if (! channel) - return NS_ERROR_OUT_OF_MEMORY; - - *aResult = channel; - NS_ADDREF(*aResult); - return NS_OK; -} - - nsCachedChromeChannel::nsCachedChromeChannel(nsIURI* aURI) - : mURI(aURI), mLoadGroup(nsnull), mLoadFlags (nsIRequest::LOAD_NORMAL), mStatus(NS_OK) + : mURI(aURI) + , mLoadGroup(nsnull) + , mLoadFlags(nsIRequest::LOAD_NORMAL) + , mStatus(NS_OK) { #ifdef PR_LOGGING if (! gLog) gLog = PR_NewLogModule("nsCachedChromeChannel"); #endif - PR_LOG(gLog, PR_LOG_DEBUG, - ("nsCachedChromeChannel[%p]: created", this)); + LOG(("nsCachedChromeChannel[%p]: created", this)); } nsCachedChromeChannel::~nsCachedChromeChannel() { - PR_LOG(gLog, PR_LOG_DEBUG, - ("nsCachedChromeChannel[%p]: destroyed", this)); + LOG(("nsCachedChromeChannel[%p]: destroyed", this)); } @@ -215,11 +191,11 @@ nsCachedChromeChannel::GetOriginalURI(nsIURI* *aOriginalURI) NS_IMETHODIMP nsCachedChromeChannel::SetOriginalURI(nsIURI* aOriginalURI) { - // don't stp on a uri if we already have one there...this is a work around fix - // for Bug #34769. - if (!mURI) - mURI = aOriginalURI; - return NS_OK; + // don't stp on a uri if we already have one there...this is a work around fix + // for Bug #34769. + if (!mURI) + mURI = aOriginalURI; + return NS_OK; } NS_IMETHODIMP @@ -241,44 +217,31 @@ nsCachedChromeChannel::Open(nsIInputStream **_retval) NS_IMETHODIMP nsCachedChromeChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt) { - if (listener) { - nsresult rv; + NS_ENSURE_ARG_POINTER(listener); - if (mLoadGroup) { - PR_LOG(gLog, PR_LOG_DEBUG, - ("nsCachedChromeChannel[%p]: adding self to load group %p", - this, mLoadGroup.get())); + nsresult rv; - rv = mLoadGroup->AddRequest(this, nsnull); - if (NS_FAILED(rv)) return rv; - } + // Fire OnStartRequest and OnStopRequest, which will cause the XUL + // document to get embedded. + LOG(("nsCachedChromeChannel[%p]: posting load event for %p", + this, listener)); - // Fire the OnStartRequest(), which will cause the XUL - // document to get embedded. - PR_LOG(gLog, PR_LOG_DEBUG, - ("nsCachedChromeChannel[%p]: firing OnStartRequest for %p", - this, listener)); + // Queue an event to ourselves to let the stack unwind before + // calling OnStartRequest(). This allows embedding to occur + // before we fire OnStopRequest(). + rv = PostLoadEvent(this, HandleLoadEvent); + if (NS_FAILED(rv)) + return rv; - // Queue an event to ourselves to let the stack unwind before - // calling OnStartRequest(). This allows embedding to occur - // before we fire OnStopRequest(). - rv = PostLoadEvent(this, HandleStartLoadEvent); - if (NS_FAILED(rv)) { - if (mLoadGroup) { - PR_LOG(gLog, PR_LOG_DEBUG, - ("nsCachedChromeChannel[%p]: removing self from load group %p", - this, mLoadGroup.get())); + mContext = ctxt; + mListener = listener; - (void) mLoadGroup->RemoveRequest(this, nsnull, NS_OK); - } + if (mLoadGroup) { + LOG(("nsCachedChromeChannel[%p]: adding self to load group %p", + this, mLoadGroup.get())); - return rv; - } - - mContext = ctxt; - mListener = listener; + (void) mLoadGroup->AddRequest(this, nsnull); } - return NS_OK; } @@ -305,7 +268,7 @@ nsCachedChromeChannel::SetLoadFlags(nsLoadFlags aLoadFlags) NS_IMETHODIMP nsCachedChromeChannel::GetOwner(nsISupports * *aOwner) { - *aOwner = mOwner.get(); + *aOwner = mOwner; NS_IF_ADDREF(*aOwner); return NS_OK; } @@ -394,92 +357,55 @@ nsresult nsCachedChromeChannel::PostLoadEvent(nsCachedChromeChannel* aChannel, PLHandleEventProc aHandler) { - nsresult rv; - - nsCOMPtr svc = do_GetService(kEventQueueServiceCID, &rv); - if (NS_FAILED(rv)) return rv; - - if (! svc) - return NS_ERROR_UNEXPECTED; - nsCOMPtr queue; - rv = svc->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue)); - if (NS_FAILED(rv)) return rv; + nsresult rv = NS_GetCurrentEventQ(getter_AddRefs(queue)); + if (NS_FAILED(rv)) + return rv; - if (! queue) - return NS_ERROR_UNEXPECTED; - - LoadEvent* event = new LoadEvent; + PLEvent* event = new PLEvent; if (! event) return NS_ERROR_OUT_OF_MEMORY; - PL_InitEvent(NS_REINTERPRET_CAST(PLEvent*, event), - nsnull, + PL_InitEvent(event, + aChannel, aHandler, DestroyLoadEvent); + NS_ADDREF(aChannel); - event->mChannel = aChannel; - NS_ADDREF(event->mChannel); - - rv = queue->EnterMonitor(); - if (NS_SUCCEEDED(rv)) { - (void) queue->PostEvent(NS_REINTERPRET_CAST(PLEvent*, event)); - (void) queue->ExitMonitor(); - return NS_OK; - } - - // If we get here, something bad happened. Clean up. - NS_RELEASE(event->mChannel); - delete event; + rv = queue->PostEvent(event); + if (NS_FAILED(rv)) + PL_DestroyEvent(event); return rv; } void* PR_CALLBACK -nsCachedChromeChannel::HandleStartLoadEvent(PLEvent* aEvent) +nsCachedChromeChannel::HandleLoadEvent(PLEvent* aEvent) { // Fire the OnStartRequest() for the cached chrome channel, then // queue another event to trigger the OnStopRequest()... - LoadEvent* event = NS_REINTERPRET_CAST(LoadEvent*, aEvent); - nsCachedChromeChannel* channel = event->mChannel; + nsCachedChromeChannel* channel = (nsCachedChromeChannel*) aEvent->owner; // If the load has been cancelled, then just bail now. We won't // send On[Start|Stop]Request(). if (NS_FAILED(channel->mStatus)) - return nsnull; + return nsnull; - PR_LOG(gLog, PR_LOG_DEBUG, - ("nsCachedChromeChannel[%p]: firing OnStartRequest for %p", - channel, channel->mListener.get())); + LOG(("nsCachedChromeChannel[%p]: firing OnStartRequest for %p", + channel, channel->mListener.get())); (void) channel->mListener->OnStartRequest(channel, channel->mContext); - (void) PostLoadEvent(channel, HandleStopLoadEvent); - return nsnull; -} + LOG(("nsCachedChromeChannel[%p]: firing OnStopRequest for %p", + channel, channel->mListener.get())); -void* PR_CALLBACK -nsCachedChromeChannel::HandleStopLoadEvent(PLEvent* aEvent) -{ - // Fire the OnStopRequest() for the cached chrome channel, and - // remove it from the load group. - LoadEvent* event = NS_REINTERPRET_CAST(LoadEvent*, aEvent); - nsCachedChromeChannel* channel = event->mChannel; - nsIRequest* request = NS_REINTERPRET_CAST(nsIRequest*, channel); - - - PR_LOG(gLog, PR_LOG_DEBUG, - ("nsCachedChromeChannel[%p]: firing OnStopRequest for %p", - channel, channel->mListener.get())); - - (void) channel->mListener->OnStopRequest(request, channel->mContext, + (void) channel->mListener->OnStopRequest(channel, channel->mContext, channel->mStatus); if (channel->mLoadGroup) { - PR_LOG(gLog, PR_LOG_DEBUG, - ("nsCachedChromeChannel[%p]: removing self from load group %p", - channel, channel->mLoadGroup.get())); + LOG(("nsCachedChromeChannel[%p]: removing self from load group %p", + channel, channel->mLoadGroup.get())); - (void) channel->mLoadGroup->RemoveRequest(request, nsnull, NS_OK); + (void) channel->mLoadGroup->RemoveRequest(channel, nsnull, channel->mStatus); } channel->mListener = nsnull; @@ -491,54 +417,22 @@ nsCachedChromeChannel::HandleStopLoadEvent(PLEvent* aEvent) void PR_CALLBACK nsCachedChromeChannel::DestroyLoadEvent(PLEvent* aEvent) { - LoadEvent* event = NS_REINTERPRET_CAST(LoadEvent*, aEvent); - NS_RELEASE(event->mChannel); - delete event; + nsCachedChromeChannel* channel = (nsCachedChromeChannel*) aEvent->owner; + NS_RELEASE(channel); + delete aEvent; } //////////////////////////////////////////////////////////////////////////////// -nsChromeProtocolHandler::nsChromeProtocolHandler() -{ -} - -nsresult -nsChromeProtocolHandler::Init() -{ - return NS_OK; -} - -nsChromeProtocolHandler::~nsChromeProtocolHandler() -{ -} - NS_IMPL_THREADSAFE_ISUPPORTS2(nsChromeProtocolHandler, nsIProtocolHandler, nsISupportsWeakReference) -NS_METHOD -nsChromeProtocolHandler::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) -{ - if (aOuter) - return NS_ERROR_NO_AGGREGATION; - - nsChromeProtocolHandler* ph = new nsChromeProtocolHandler(); - if (ph == nsnull) - return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(ph); - nsresult rv = ph->Init(); - if (NS_SUCCEEDED(rv)) { - rv = ph->QueryInterface(aIID, aResult); - } - NS_RELEASE(ph); - return rv; -} - //////////////////////////////////////////////////////////////////////////////// // nsIProtocolHandler methods: NS_IMETHODIMP nsChromeProtocolHandler::GetScheme(nsACString &result) { - result = "chrome"; + result.AssignLiteral("chrome"); return NS_OK; } @@ -579,7 +473,7 @@ nsChromeProtocolHandler::NewURI(const nsACString &aSpec, // Chrome: URLs (currently) have no additional structure beyond that provided // by standard URLs, so there is no "outer" given to CreateInstance - nsCOMPtr url(do_CreateInstance(kStandardURLCID, &rv)); + nsCOMPtr url(do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv)); if (NS_FAILED(rv)) return rv; @@ -590,7 +484,7 @@ nsChromeProtocolHandler::NewURI(const nsACString &aSpec, nsCOMPtr uri(do_QueryInterface(url, &rv)); if (NS_FAILED(rv)) return rv; - + // Canonify the "chrome:" URL; e.g., so that we collapse // "chrome://navigator/content/" and "chrome://navigator/content" // and "chrome://navigator/content/navigator.xul". @@ -677,8 +571,9 @@ nsChromeProtocolHandler::NewChannel(nsIURI* aURI, if (proto) { // ...in which case, we'll create a dummy stream that'll just // load the thing. - rv = nsCachedChromeChannel::Create(aURI, getter_AddRefs(result)); - if (NS_FAILED(rv)) return rv; + result = new nsCachedChromeChannel(aURI); + if (! result) + return NS_ERROR_OUT_OF_MEMORY; } else #endif @@ -699,7 +594,7 @@ nsChromeProtocolHandler::NewChannel(nsIURI* aURI, reg->ConvertChromeURL(aURI, spec); if (NS_FAILED(rv)) return rv; - nsCOMPtr ioServ(do_GetService(kIOServiceCID, &rv)); + nsCOMPtr ioServ(do_GetIOService(&rv)); if (NS_FAILED(rv)) return rv; nsCOMPtr chromeURI; diff --git a/chrome/src/nsChromeProtocolHandler.h b/chrome/src/nsChromeProtocolHandler.h index e846d39e0b8..6ae1a4d79cc 100644 --- a/chrome/src/nsChromeProtocolHandler.h +++ b/chrome/src/nsChromeProtocolHandler.h @@ -58,13 +58,8 @@ public: NS_DECL_NSIPROTOCOLHANDLER // nsChromeProtocolHandler methods: - nsChromeProtocolHandler(); - virtual ~nsChromeProtocolHandler(); - - static NS_METHOD - Create(nsISupports *aOuter, REFNSIID aIID, void **aResult); - - nsresult Init(); + nsChromeProtocolHandler() {} + ~nsChromeProtocolHandler() {} }; #endif /* nsChromeProtocolHandler_h___ */ diff --git a/chrome/src/nsChromeRegistry.cpp b/chrome/src/nsChromeRegistry.cpp index 49e54874364..28f4f2afcda 100644 --- a/chrome/src/nsChromeRegistry.cpp +++ b/chrome/src/nsChromeRegistry.cpp @@ -3294,64 +3294,115 @@ NS_IMETHODIMP nsChromeRegistry::AllowScriptsForSkin(nsIURI* aChromeURI, PRBool * return NS_OK; } +static nsresult +GetFileAndLastModifiedTime(nsIProperties *aDirSvc, + const char *aDirKey, + const nsCSubstring &aLeafName, + nsCOMPtr &aFile, + PRTime *aLastModified) +{ + *aLastModified = LL_ZERO; + + nsresult rv; + rv = aDirSvc->Get(aDirKey, NS_GET_IID(nsILocalFile), getter_AddRefs(aFile)); + if (NS_FAILED(rv)) + return rv; + rv = aFile->AppendNative(aLeafName); + if (NS_SUCCEEDED(rv)) { + // if the file does not exist, this returns zero + aFile->GetLastModifiedTime(aLastModified); + } + return rv; +} + NS_IMETHODIMP nsChromeRegistry::CheckForNewChrome() { nsresult rv; rv = LoadInstallDataSource(); - if (NS_FAILED(rv)) return rv; + if (NS_FAILED(rv)) + return rv; - // open the installed-chrome file - nsCOMPtr listFile; - nsCOMPtr directoryService = + nsCOMPtr dirSvc = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; - rv = directoryService->Get(NS_APP_CHROME_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(listFile)); + + nsCOMPtr cacheFile, listFile; + nsInt64 cacheDate, listDate; + + // check the application directory first. + GetFileAndLastModifiedTime(dirSvc, NS_APP_CHROME_DIR, kChromeFileName, + cacheFile, &cacheDate.mValue); + GetFileAndLastModifiedTime(dirSvc, NS_APP_CHROME_DIR, kInstalledChromeFileName, + listFile, &listDate.mValue); + if (listDate > cacheDate) + ProcessNewChromeFile(listFile); + + // check the extra chrome directories + nsCOMPtr chromeDL; + rv = dirSvc->Get(NS_APP_CHROME_DIR_LIST, NS_GET_IID(nsISimpleEnumerator), + getter_AddRefs(chromeDL)); + if (NS_SUCCEEDED(rv)) { + // we assume that any other list files will only reference chrome that + // should be installed in the profile directory. we might want to add + // some actual checks to this effect. + GetFileAndLastModifiedTime(dirSvc, NS_APP_USER_CHROME_DIR, kChromeFileName, + cacheFile, &cacheDate.mValue); + PRBool hasMore; + while (NS_SUCCEEDED(chromeDL->HasMoreElements(&hasMore)) && hasMore) { + nsCOMPtr element; + chromeDL->GetNext(getter_AddRefs(element)); + if (!element) + continue; + listFile = do_QueryInterface(element); + if (!listFile) + continue; + rv = listFile->AppendNative(kInstalledChromeFileName); + if (NS_FAILED(rv)) + continue; + listFile->GetLastModifiedTime(&listDate.mValue); + if (listDate > cacheDate) + ProcessNewChromeFile(listFile); + } + } + + return rv; +} + +nsresult +nsChromeRegistry::ProcessNewChromeFile(nsILocalFile *aListFile) +{ + nsresult rv; + + PRFileDesc *file; + rv = aListFile->OpenNSPRFileDesc(PR_RDONLY, 0, &file); if (NS_FAILED(rv)) return rv; - nsCOMPtr chromeFile; - rv = listFile->Clone(getter_AddRefs(chromeFile)); - if (NS_FAILED(rv)) return rv; - rv = chromeFile->AppendNative(kChromeFileName); - if (NS_FAILED(rv)) return rv; - // XXXldb For the case where the file is nonexistent, we're depending - // on the fact that the nsInt64 constructor initializes to 0 and - // |GetLastModifiedTime| doesn't touch the out parameter. - nsInt64 chromeDate; - (void)chromeFile->GetLastModifiedTime(&chromeDate.mValue); + PRInt32 n, size; + char *buf; - rv = listFile->AppendRelativeNativePath(kInstalledChromeFileName); - if (NS_FAILED(rv)) return rv; - nsInt64 listFileDate; - (void)listFile->GetLastModifiedTime(&listFileDate.mValue); - - if (listFileDate < chromeDate) - return NS_OK; - - PRFileDesc *file; - rv = listFile->OpenNSPRFileDesc(PR_RDONLY, 0, &file); - if (NS_FAILED(rv)) return rv; - - // file is open. - - PRFileInfo finfo; - - if (PR_GetOpenFileInfo(file, &finfo) == PR_SUCCESS) { - char *dataBuffer = new char[finfo.size+1]; - if (dataBuffer) { - PRInt32 bufferSize = PR_Read(file, dataBuffer, finfo.size); - if (bufferSize > 0) { - rv = ProcessNewChromeBuffer(dataBuffer, bufferSize); - } - delete [] dataBuffer; - } + size = PR_Available(file); + if (size == -1) { + rv = NS_ERROR_UNEXPECTED; + goto end; } - PR_Close(file); - // listFile->Remove(PR_FALSE); + buf = (char *) malloc(size + 1); + if (!buf) { + rv = NS_ERROR_OUT_OF_MEMORY; + goto end; + } + + n = PR_Read(file, buf, size); + if (n > 0) + rv = ProcessNewChromeBuffer(buf, size); + free(buf); + +end: + PR_Close(file); return rv; } diff --git a/chrome/src/nsChromeRegistry.h b/chrome/src/nsChromeRegistry.h index 4c5f10f0d10..ed20716a6bf 100644 --- a/chrome/src/nsChromeRegistry.h +++ b/chrome/src/nsChromeRegistry.h @@ -48,6 +48,8 @@ class nsIRDFContainer; class nsIRDFContainerUtils; class nsIDOMWindowInternal; class nsIDocument; +class nsILocalFile; +class nsIProperties; #include "nsIChromeRegistry.h" #include "nsIXULOverlayProvider.h" @@ -220,7 +222,8 @@ private: nsresult UninstallFromDynamicDataSource(const nsACString& aPackageName, PRBool aIsOverlay, PRBool aUseProfile); - nsresult ProcessNewChromeBuffer(char *aBuffer, PRInt32 aLength); + NS_HIDDEN_(nsresult) ProcessNewChromeFile(nsILocalFile *aListFile); + NS_HIDDEN_(nsresult) ProcessNewChromeBuffer(char *aBuffer, PRInt32 aLength); PRBool GetProviderCount(const nsACString& aProviderType, nsIRDFDataSource* aDataSource); diff --git a/netwerk/protocol/res/src/nsResProtocolHandler.cpp b/netwerk/protocol/res/src/nsResProtocolHandler.cpp index 73aa4ca762a..93bd3a1c787 100644 --- a/netwerk/protocol/res/src/nsResProtocolHandler.cpp +++ b/netwerk/protocol/res/src/nsResProtocolHandler.cpp @@ -161,10 +161,13 @@ nsResProtocolHandler::Init() // // make resource://gre/ point to the GRE directory // - return AddSpecialDir(NS_GRE_DIR, NS_LITERAL_CSTRING("gre")); + rv = AddSpecialDir(NS_GRE_DIR, NS_LITERAL_CSTRING("gre")); + NS_ENSURE_SUCCESS(rv, rv); //XXXbsmedberg Neil wants a resource://pchrome/ for the profile chrome dir... // but once I finish multiple chrome registration I'm not sure that it is needed + + return rv; } //---------------------------------------------------------------------------- @@ -265,7 +268,25 @@ nsResProtocolHandler::GetSubstitution(const nsACString& root, nsIURI **result) { NS_ENSURE_ARG_POINTER(result); - return mSubstitutions.Get(root, result) ? NS_OK : NS_ERROR_NOT_AVAILABLE; + if (mSubstitutions.Get(root, result)) + return NS_OK; + + // try invoking the directory service for "resource:root" + + nsCAutoString key; + key.AppendLiteral("resource:"); + key.Append(root); + + nsCOMPtr file; + nsresult rv = NS_GetSpecialDirectory(key.get(), getter_AddRefs(file)); + if (NS_FAILED(rv)) + return NS_ERROR_NOT_AVAILABLE; + + rv = mIOService->NewFileURI(file, result); + if (NS_FAILED(rv)) + return NS_ERROR_NOT_AVAILABLE; + + return NS_OK; } NS_IMETHODIMP diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index d54c1ed678b..6b53567f924 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -382,6 +382,70 @@ CheckArg(const char* aArg, const char **aParam = nsnull) return ARG_NONE; } + +static const nsXREAppData* LoadAppData(const char* appDataFile) +{ + static char vendor[256], name[256], version[32], buildID[32], copyright[512]; + static const nsXREAppData data = { + vendor, name, version, buildID, copyright, PR_FALSE + }; + + nsCOMPtr lf; + NS_GetFileFromPath(appDataFile, getter_AddRefs(lf)); + if (!lf) + return nsnull; + + nsINIParser parser; + if (NS_FAILED(parser.Init(lf))) + return nsnull; + + // Ensure that this file specifies a compatible XRE version. + char xreVersion[32]; + nsresult rv = parser.GetString("XRE", "Version", xreVersion, sizeof(xreVersion)); + if (NS_FAILED(rv) || xreVersion[0] != '0' || xreVersion[1] != '.') { + fprintf(stderr, "Error: XRE version requirement not met.\n"); + return nsnull; + } + + const struct { + const char* key; + char* buf; + size_t bufLen; + PRBool required; + } fields[] = { + { "Vendor", vendor, sizeof(vendor), PR_FALSE }, + { "Name", name, sizeof(name), PR_TRUE }, + { "Version", version, sizeof(version), PR_FALSE }, + { "BuildID", buildID, sizeof(buildID), PR_TRUE }, + { "Copyright", copyright, sizeof(copyright), PR_FALSE } + }; + + for (int i=0; i<5; ++i) { + rv = parser.GetString("App", fields[i].key, fields[i].buf, fields[i].bufLen); + if (NS_FAILED(rv)) { + if (fields[i].required) { + fprintf(stderr, "Error: %x: No \"%s\" field.\n", rv, fields[i].key); + return nsnull; + } else { + fields[i].buf[0] = '\0'; + } + } + } + +#ifdef DEBUG + printf("---------------------------------------------------------\n"); + printf(" Vendor %s\n", data.appVendor); + printf(" Name %s\n", data.appName); + printf(" Version %s\n", data.appVersion); + printf(" BuildID %s\n", data.appBuildID); + printf(" Copyright %s\n", data.copyright); + printf("---------------------------------------------------------\n"); +#endif + + return &data; +} + + static nsresult OpenWindow(const nsAFlatCString& aChromeURL, const nsAFlatString& aAppArgs, PRInt32 aWidth, PRInt32 aHeight); @@ -1678,8 +1742,6 @@ int xre_main(int argc, char* argv[], const nsXREAppData* aAppData) fpsetmask(0); #endif - gAppData = aAppData; - #if defined(XP_UNIX) && !defined(XP_MACOSX) if (!GetBinaryPath(argv[0])) return 1; @@ -1688,6 +1750,17 @@ int xre_main(int argc, char* argv[], const nsXREAppData* aAppData) gArgc = argc; gArgv = argv; + // allow -app argument to override default app data + const char *appDataFile = nsnull; + if (CheckArg("app", &appDataFile)) + aAppData = LoadAppData(appDataFile); + + if (!aAppData) { + fprintf(stderr, "Error: Invalid or missing application data!\n"); + return 1; + } + gAppData = aAppData; + gRestartArgc = argc; gRestartArgv = (char**) malloc(sizeof(char*) * (argc + 1)); if (!gRestartArgv) return 1; @@ -1739,9 +1812,19 @@ int xre_main(int argc, char* argv[], const nsXREAppData* aAppData) #endif nsXREDirProvider dirProvider; - rv = dirProvider.Initialize(); - if (NS_FAILED(rv)) - return 1; + { + nsCOMPtr xulAppDir; + + if (appDataFile) { + nsCOMPtr lf; + NS_GetFileFromPath(appDataFile, getter_AddRefs(lf)); + lf->GetParent(getter_AddRefs(xulAppDir)); + } + + rv = dirProvider.Initialize(xulAppDir); + if (NS_FAILED(rv)) + return 1; + } // Check for -register, which registers chrome and then exits immediately. if (CheckArg("register")) { diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp index df623030b69..0bfcad1a2fa 100644 --- a/toolkit/xre/nsXREDirProvider.cpp +++ b/toolkit/xre/nsXREDirProvider.cpp @@ -101,8 +101,10 @@ nsXREDirProvider::~nsXREDirProvider() } nsresult -nsXREDirProvider::Initialize() +nsXREDirProvider::Initialize(nsIFile *aXULAppDir) { + mXULAppDir = aXULAppDir; + // We need to use platform-specific hackery to find the // path of this executable. This is copied, with some modifications, from // nsGREDirServiceProvider.cpp @@ -241,9 +243,9 @@ nsXREDirProvider::GetFile(const char* aProperty, PRBool* aPersistent, { rv = mAppDir->Clone(getter_AddRefs(file)); if (NS_SUCCEEDED(rv)) { - rv = file->AppendNative(nsDependentCString("defaults")); + rv = file->AppendNative(NS_LITERAL_CSTRING("defaults")); if (NS_SUCCEEDED(rv)) - rv = file->AppendNative(nsDependentCString("pref")); + rv = file->AppendNative(NS_LITERAL_CSTRING("pref")); } } else if (!strcmp(aProperty, NS_APP_APPLICATION_REGISTRY_DIR)) { @@ -257,20 +259,23 @@ nsXREDirProvider::GetFile(const char* aProperty, PRBool* aPersistent, rv = GetUserAppDataDirectory((nsILocalFile**)(nsIFile**) getter_AddRefs(file)); #if !defined(XP_UNIX) || defined(XP_MACOSX) - rv |= file->AppendNative(nsDependentCString("Profiles")); + rv |= file->AppendNative(NS_LITERAL_CSTRING("Profiles")); #endif // We must create the profile directory here if it does not exist. rv |= EnsureDirectoryExists(file); } + else if (mXULAppDir && !strcmp(aProperty, "resource:app")) { + rv = mXULAppDir->Clone(getter_AddRefs(file)); + } else if (mProfileDir) { if (!strcmp(aProperty, NS_XPCOM_COMPONENT_REGISTRY_FILE)) { rv = mProfileDir->Clone(getter_AddRefs(file)); - rv |= file->AppendNative(nsDependentCString("compreg.dat")); + rv |= file->AppendNative(NS_LITERAL_CSTRING("compreg.dat")); } else if (!strcmp(aProperty, NS_XPCOM_XPTI_REGISTRY_FILE)) { rv = mProfileDir->Clone(getter_AddRefs(file)); - rv |= file->AppendNative(nsDependentCString("xpti.dat")); + rv |= file->AppendNative(NS_LITERAL_CSTRING("xpti.dat")); } if (mProfileNotified) { if (!strcmp(aProperty, NS_APP_USER_PROFILE_50_DIR) || @@ -279,62 +284,62 @@ nsXREDirProvider::GetFile(const char* aProperty, PRBool* aPersistent, } else if (!strcmp(aProperty, NS_APP_PREFS_50_FILE)) { rv = mProfileDir->Clone(getter_AddRefs(file)); - rv |= file->AppendNative(nsDependentCString("prefs.js")); + rv |= file->AppendNative(NS_LITERAL_CSTRING("prefs.js")); } // XXXbsmedberg this needs rethinking... many of these are app-specific, // and apps are going to add new stuff. I don't have a good solution, // yet. else if (!strcmp(aProperty, NS_APP_USER_CHROME_DIR)) { rv = mProfileDir->Clone(getter_AddRefs(file)); - rv |= file->AppendNative(nsDependentCString("chrome")); + rv |= file->AppendNative(NS_LITERAL_CSTRING("chrome")); } else if (!strcmp(aProperty, NS_APP_LOCALSTORE_50_FILE)) { rv = mProfileDir->Clone(getter_AddRefs(file)); - rv |= file->AppendNative(nsDependentCString("localstore.rdf")); + rv |= file->AppendNative(NS_LITERAL_CSTRING("localstore.rdf")); EnsureProfileFileExists(file); } else if (!strcmp(aProperty, NS_APP_HISTORY_50_FILE)) { rv = mProfileDir->Clone(getter_AddRefs(file)); - rv |= file->AppendNative(nsDependentCString("history.dat")); + rv |= file->AppendNative(NS_LITERAL_CSTRING("history.dat")); } else if (!strcmp(aProperty, NS_APP_USER_PANELS_50_FILE)) { rv = mProfileDir->Clone(getter_AddRefs(file)); - rv |= file->AppendNative(nsDependentCString("panels.rdf")); + rv |= file->AppendNative(NS_LITERAL_CSTRING("panels.rdf")); EnsureProfileFileExists(file); } else if (!strcmp(aProperty, NS_APP_USER_MIMETYPES_50_FILE)) { rv = mProfileDir->Clone(getter_AddRefs(file)); - rv |= file->AppendNative(nsDependentCString("mimeTypes.rdf")); + rv |= file->AppendNative(NS_LITERAL_CSTRING("mimeTypes.rdf")); EnsureProfileFileExists(file); } else if (!strcmp(aProperty, NS_APP_BOOKMARKS_50_FILE)) { rv = mProfileDir->Clone(getter_AddRefs(file)); - rv |= file->AppendNative(nsDependentCString("bookmarks.html")); + rv |= file->AppendNative(NS_LITERAL_CSTRING("bookmarks.html")); } else if (!strcmp(aProperty, NS_APP_DOWNLOADS_50_FILE)) { rv = mProfileDir->Clone(getter_AddRefs(file)); - rv |= file->AppendNative(nsDependentCString("downloads.rdf")); + rv |= file->AppendNative(NS_LITERAL_CSTRING("downloads.rdf")); } else if (!strcmp(aProperty, NS_APP_SEARCH_50_FILE)) { rv = mProfileDir->Clone(getter_AddRefs(file)); - rv |= file->AppendNative(nsDependentCString("search.rdf")); + rv |= file->AppendNative(NS_LITERAL_CSTRING("search.rdf")); EnsureProfileFileExists(file); } else if (!strcmp(aProperty, NS_APP_MAIL_50_DIR)) { rv = mProfileDir->Clone(getter_AddRefs(file)); - rv |= file->AppendNative(nsDependentCString("Mail")); + rv |= file->AppendNative(NS_LITERAL_CSTRING("Mail")); } else if (!strcmp(aProperty, NS_APP_IMAP_MAIL_50_DIR)) { rv = mProfileDir->Clone(getter_AddRefs(file)); - rv |= file->AppendNative(nsDependentCString("ImapMail")); + rv |= file->AppendNative(NS_LITERAL_CSTRING("ImapMail")); } else if (!strcmp(aProperty, NS_APP_NEWS_50_DIR)) { rv = mProfileDir->Clone(getter_AddRefs(file)); - rv |= file->AppendNative(nsDependentCString("News")); + rv |= file->AppendNative(NS_LITERAL_CSTRING("News")); } else if (!strcmp(aProperty, NS_APP_MESSENGER_FOLDER_CACHE_50_DIR)) { rv = mProfileDir->Clone(getter_AddRefs(file)); - rv |= file->AppendNative(nsDependentCString("panacea.dat")); + rv |= file->AppendNative(NS_LITERAL_CSTRING("panacea.dat")); } } } @@ -389,16 +394,25 @@ nsXREDirProvider::GetFiles(const char* aProperty, nsISimpleEnumerator** aResult) if (!strcmp(aProperty, NS_XPCOM_COMPONENT_DIR_LIST)) { if (mRegisterExtraComponents) { nsCOMArray directories; + + if (mXULAppDir) { + nsCOMPtr file; + mXULAppDir->Clone(getter_AddRefs(file)); + file->AppendNative(NS_LITERAL_CSTRING("components")); + PRBool exists; + if (NS_SUCCEEDED(file->Exists(&exists)) && exists) + directories.AppendObject(file); + } nsCOMPtr appFile; mAppDir->Clone(getter_AddRefs(appFile)); - appFile->AppendNative(nsDependentCString("components.ini")); + appFile->AppendNative(NS_LITERAL_CSTRING("components.ini")); LoadDirsIntoArray(appFile, directories); nsCOMPtr profileFile; if (mProfileDir) { mProfileDir->Clone(getter_AddRefs(profileFile)); - profileFile->AppendNative(nsDependentCString("components.ini")); + profileFile->AppendNative(NS_LITERAL_CSTRING("components.ini")); LoadDirsIntoArray(profileFile, directories); } @@ -407,21 +421,45 @@ nsXREDirProvider::GetFiles(const char* aProperty, nsISimpleEnumerator** aResult) } else if (!strcmp(aProperty, NS_APP_PREFS_DEFAULTS_DIR_LIST)) { nsCOMArray directories; + + if (mXULAppDir) { + nsCOMPtr file; + mXULAppDir->Clone(getter_AddRefs(file)); + file->AppendNative(NS_LITERAL_CSTRING("defaults")); + file->AppendNative(NS_LITERAL_CSTRING("pref")); + PRBool exists; + if (NS_SUCCEEDED(file->Exists(&exists)) && exists) + directories.AppendObject(file); + } nsCOMPtr appFile; mAppDir->Clone(getter_AddRefs(appFile)); - appFile->AppendNative(nsDependentCString("defaults.ini")); + appFile->AppendNative(NS_LITERAL_CSTRING("defaults.ini")); LoadDirsIntoArray(appFile, directories); nsCOMPtr profileFile; if (mProfileDir) { mProfileDir->Clone(getter_AddRefs(profileFile)); - profileFile->AppendNative(nsDependentCString("defaults.ini")); + profileFile->AppendNative(NS_LITERAL_CSTRING("defaults.ini")); LoadDirsIntoArray(profileFile, directories); } rv = NS_NewArrayEnumerator(aResult, directories); } + else if (!strcmp(aProperty, NS_APP_CHROME_DIR_LIST)) { + nsCOMArray directories; + + if (mXULAppDir) { + nsCOMPtr file; + mXULAppDir->Clone(getter_AddRefs(file)); + file->AppendNative(NS_LITERAL_CSTRING("chrome")); + PRBool exists; + if (NS_SUCCEEDED(file->Exists(&exists)) && exists) + directories.AppendObject(file); + } + + rv = NS_NewArrayEnumerator(aResult, directories); + } else rv = NS_ERROR_FAILURE; @@ -728,8 +766,8 @@ nsXREDirProvider::GetProfileDefaultsDir(nsIFile* *aResult) rv = mAppDir->Clone(getter_AddRefs(defaultsDir)); NS_ENSURE_SUCCESS(rv, rv); - rv = defaultsDir->AppendNative(nsDependentCString("defaults")); - rv |= defaultsDir->AppendNative(nsDependentCString("profile")); + rv = defaultsDir->AppendNative(NS_LITERAL_CSTRING("defaults")); + rv |= defaultsDir->AppendNative(NS_LITERAL_CSTRING("profile")); NS_ENSURE_SUCCESS(rv, rv); NS_ADDREF(*aResult = defaultsDir); diff --git a/toolkit/xre/nsXREDirProvider.h b/toolkit/xre/nsXREDirProvider.h index d5901effe6d..965c903e234 100644 --- a/toolkit/xre/nsXREDirProvider.h +++ b/toolkit/xre/nsXREDirProvider.h @@ -57,7 +57,7 @@ public: NS_DECL_NSIPROFILESTARTUP nsXREDirProvider(); - nsresult Initialize(); + nsresult Initialize(nsIFile *aXULAppDir); ~nsXREDirProvider(); // We only set the profile dir, we don't ensure that it exists; @@ -86,6 +86,7 @@ protected: void EnsureProfileFileExists(nsIFile* aFile); nsCOMPtr mAppDir; + nsCOMPtr mXULAppDir; nsCOMPtr mProfileDir; PRBool mProfileNotified; PRBool mRegisterExtraComponents; diff --git a/xpcom/io/nsAppDirectoryServiceDefs.h b/xpcom/io/nsAppDirectoryServiceDefs.h index 3887f0105b0..768cb38fd6a 100755 --- a/xpcom/io/nsAppDirectoryServiceDefs.h +++ b/xpcom/io/nsAppDirectoryServiceDefs.h @@ -76,6 +76,7 @@ #define NS_APP_PLUGINS_DIR "APlugns" // Deprecated - use NS_APP_PLUGINS_DIR_LIST #define NS_APP_SEARCH_DIR "SrchPlugns" +#define NS_APP_CHROME_DIR_LIST "AChromDL" #define NS_APP_PLUGINS_DIR_LIST "APluginsDL" // --------------------------------------------------------------------------------------