From b28a40ed78cac2b9eb9da3ec7c7d02bf2f951c4d Mon Sep 17 00:00:00 2001 From: "bsmedberg%covad.net" Date: Sun, 20 Feb 2005 01:47:13 +0000 Subject: [PATCH] Backout bug 278534 due to tinderbox orange. git-svn-id: svn://10.0.0.236/trunk@169510 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/allmakefiles.sh | 1 - .../browser/installer/unix/packages-static | 2 +- mozilla/chrome/Makefile.in | 2 +- mozilla/chrome/public/Makefile.in | 48 - .../public/nsIToolkitChromeRegistry.idl | 72 - mozilla/chrome/src/Makefile.in | 1 + .../chrome/src/nsChromeProtocolHandler.cpp | 104 +- mozilla/chrome/src/nsChromeRegistry.cpp | 3493 +++++++++++------ mozilla/chrome/src/nsChromeRegistry.h | 257 +- .../content/base/public/nsIChromeRegistry.idl | 36 +- .../content/xbl/public/nsIBindingManager.h | 1 - mozilla/content/xbl/src/nsXBLDocumentInfo.cpp | 10 +- mozilla/embedding/lite/Makefile.in | 3 +- mozilla/mail/installer/windows/basemail-win | 1 - mozilla/netwerk/base/public/nsURIHashKey.h | 1 - .../chrome/public/nsIChromeRegistrySea.idl | 20 +- .../chrome/src/nsChromeProtocolHandler.cpp | 32 +- mozilla/rdf/chrome/src/nsChromeRegistry.cpp | 12 +- mozilla/rdf/chrome/src/nsChromeRegistry.h | 3 - .../extensions/src/nsExtensionManager.js.in | 441 ++- mozilla/toolkit/xre/Makefile.in | 2 - mozilla/toolkit/xre/nsAppRunner.h | 6 - mozilla/toolkit/xre/nsXREDirProvider.cpp | 115 +- mozilla/xpinstall/src/nsInstall.cpp | 48 +- mozilla/xpinstall/src/nsInstall.h | 40 +- mozilla/xpinstall/src/nsJSInstall.cpp | 5 +- mozilla/xpinstall/src/nsRegisterItem.cpp | 37 +- mozilla/xpinstall/src/nsSoftwareUpdate.cpp | 53 +- mozilla/xpinstall/src/nsSoftwareUpdateRun.cpp | 180 +- 29 files changed, 3079 insertions(+), 1947 deletions(-) delete mode 100644 mozilla/chrome/public/Makefile.in delete mode 100644 mozilla/chrome/public/nsIToolkitChromeRegistry.idl diff --git a/mozilla/allmakefiles.sh b/mozilla/allmakefiles.sh index 4abe7c0674b..f8168ddae59 100755 --- a/mozilla/allmakefiles.sh +++ b/mozilla/allmakefiles.sh @@ -919,7 +919,6 @@ xulrunner/app/profile/extensions/Makefile MAKEFILES_xulapp=" chrome/Makefile -chrome/public/Makefile chrome/src/Makefile chrome/tools/Makefile chrome/tools/chromereg/Makefile diff --git a/mozilla/browser/installer/unix/packages-static b/mozilla/browser/installer/unix/packages-static index d85ad840fd7..dc8724cf96e 100644 --- a/mozilla/browser/installer/unix/packages-static +++ b/mozilla/browser/installer/unix/packages-static @@ -61,7 +61,6 @@ bin/components/bookmarks.xpt bin/components/browsercompsbase.xpt bin/components/caps.xpt bin/components/chardet.xpt -bin/components/chrome.xpt bin/components/commandhandler.xpt bin/components/commandlines.xpt bin/components/composer.xpt @@ -135,6 +134,7 @@ bin/components/passwordmgr.xpt bin/components/plugin.xpt bin/components/prefetch.xpt bin/components/pref.xpt +bin/components/profile.xpt bin/components/progressDlg.xpt bin/components/proxyObjInst.xpt bin/components/rdf.xpt diff --git a/mozilla/chrome/Makefile.in b/mozilla/chrome/Makefile.in index e2fcbbff062..0f8e4ec7962 100644 --- a/mozilla/chrome/Makefile.in +++ b/mozilla/chrome/Makefile.in @@ -42,7 +42,7 @@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk -DIRS = public src tools +DIRS = src tools include $(topsrcdir)/config/rules.mk diff --git a/mozilla/chrome/public/Makefile.in b/mozilla/chrome/public/Makefile.in deleted file mode 100644 index 927c77e4072..00000000000 --- a/mozilla/chrome/public/Makefile.in +++ /dev/null @@ -1,48 +0,0 @@ -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is mozilla.org code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either of the GNU General Public License Version 2 or later (the "GPL"), -# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -DEPTH = ../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(DEPTH)/config/autoconf.mk - -MODULE = chrome - -XPIDLSRCS = nsIToolkitChromeRegistry.idl - -include $(topsrcdir)/config/rules.mk diff --git a/mozilla/chrome/public/nsIToolkitChromeRegistry.idl b/mozilla/chrome/public/nsIToolkitChromeRegistry.idl deleted file mode 100644 index d82c3f7cf62..00000000000 --- a/mozilla/chrome/public/nsIToolkitChromeRegistry.idl +++ /dev/null @@ -1,72 +0,0 @@ -/* -*- Mode: C++; tab-width; 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the XUL toolkit. - * - * The Initial Developer of the Original Code is - * Benjamin Smedberg - * - * Portions created by the Initial Developer are Copyright (C) 2005 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nsIChromeRegistry.idl" - -interface nsIURI; - -[scriptable, uuid(b1fe3107-fac6-432a-be34-fdfc26b0736c)] -interface nsIToolkitChromeRegistry : nsIXULChromeRegistry -{ - /** - * The "canonical" manifest is a plaintext file which sits outside of a - * JAR file. To provide backwards-compatibility with contents.rdf, we provide - * this function which reads a contents.rdf manifest and writes it to a file. - * - * @param aOldManifestURI The URI of an old manifest to read, without - * the trailing "contents.rdf", e.g. - * "jar:resource:///chrome/foo.jar!/content/foo/" - * @param aFile The URI of a manifest file to write. It's a good - * idea to use a resource: URI if possible. - * @param aAppend Whether we should append to an existing manifest - * or truncate and start empty. - * @param aSkinOnly Only allow skin packages. - */ - void processContentsManifest(in nsIURI aOldManifestURI, in nsIURI aFile, - in boolean aAppend, in boolean aSkinOnly); -}; - -/** - * The chrome registry will ask the directory service for this file list and - * process each file as a manifest. Skin manifests may contain only skin - * and style overlays. - */ -%{ C++ -#define NS_CHROME_MANIFESTS_FILE_LIST "ChromeML" -#define NS_SKIN_MANIFESTS_FILE_LIST "SkinML" -%} diff --git a/mozilla/chrome/src/Makefile.in b/mozilla/chrome/src/Makefile.in index 1e618f3678c..4828cf56274 100644 --- a/mozilla/chrome/src/Makefile.in +++ b/mozilla/chrome/src/Makefile.in @@ -75,6 +75,7 @@ REQUIRES = xpcom \ CPPSRCS = \ nsChromeFactory.cpp \ nsChromeRegistry.cpp \ + nsChromeUIDataSource.cpp \ nsChromeProtocolHandler.cpp \ $(NULL) diff --git a/mozilla/chrome/src/nsChromeProtocolHandler.cpp b/mozilla/chrome/src/nsChromeProtocolHandler.cpp index 98bd3a7a0b9..e654c84471f 100644 --- a/mozilla/chrome/src/nsChromeProtocolHandler.cpp +++ b/mozilla/chrome/src/nsChromeProtocolHandler.cpp @@ -43,7 +43,6 @@ */ #include "nsChromeProtocolHandler.h" -#include "nsChromeRegistry.h" #include "nsCOMPtr.h" #include "nsContentCID.h" #include "nsCRT.h" @@ -66,8 +65,10 @@ #include "nsIServiceManager.h" #include "nsIStandardURL.h" #include "nsIStreamListener.h" +#ifdef MOZ_XUL #include "nsIXULPrototypeCache.h" #include "nsIXULPrototypeDocument.h" +#endif #include "nsNetUtil.h" #include "nsXPIDLString.h" #include "nsString.h" @@ -75,7 +76,12 @@ //---------------------------------------------------------------------- +#ifdef MOZ_XUL static NS_DEFINE_CID(kXULPrototypeCacheCID, NS_XULPROTOTYPECACHE_CID); +#endif + +// This comes from nsChromeRegistry.cpp +extern nsIChromeRegistry* gChromeRegistry; //---------------------------------------------------------------------- // @@ -458,32 +464,50 @@ nsChromeProtocolHandler::NewURI(const nsACString &aSpec, nsIURI *aBaseURI, nsIURI **result) { + NS_PRECONDITION(result, "Null out param"); + nsresult rv; + *result = nsnull; + // Chrome: URLs (currently) have no additional structure beyond that provided // by standard URLs, so there is no "outer" given to CreateInstance - nsCOMPtr surl(do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv)); - NS_ENSURE_SUCCESS(rv, rv); - - rv = surl->Init(nsIStandardURL::URLTYPE_STANDARD, -1, aSpec, aCharset, aBaseURI); + nsCOMPtr url(do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv)); if (NS_FAILED(rv)) return rv; - nsCOMPtr url(do_QueryInterface(surl, &rv)); - NS_ENSURE_SUCCESS(rv, rv); + rv = url->Init(nsIStandardURL::URLTYPE_STANDARD, -1, aSpec, aCharset, aBaseURI); + if (NS_FAILED(rv)) + return rv; + + 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". - rv = nsChromeRegistry::Canonify(url); + // Try the global cache first. + nsCOMPtr reg = gChromeRegistry; + + // If that fails, the service has not been instantiated yet; let's + // do that now. + if (!reg) { + reg = do_GetService(NS_CHROMEREGISTRY_CONTRACTID, &rv); + if (NS_FAILED(rv)) + return rv; + } + + NS_ASSERTION(reg, "Must have a chrome registry by now"); + + rv = reg->Canonify(uri); if (NS_FAILED(rv)) return rv; - surl->SetMutable(PR_FALSE); - - NS_ADDREF(*result = url); + *result = uri; + NS_ADDREF(*result); return NS_OK; } @@ -497,17 +521,20 @@ nsChromeProtocolHandler::NewChannel(nsIURI* aURI, #ifdef DEBUG // Check that the uri we got is already canonified nsresult debug_rv; - nsCOMPtr debugClone; - debug_rv = aURI->Clone(getter_AddRefs(debugClone)); + nsCOMPtr debugReg(do_GetService(NS_CHROMEREGISTRY_CONTRACTID, &debug_rv)); if (NS_SUCCEEDED(debug_rv)) { - nsCOMPtr debugURL (do_QueryInterface(debugClone)); - debug_rv = nsChromeRegistry::Canonify(debugURL); + nsCOMPtr debugClone; + debug_rv = aURI->Clone(getter_AddRefs(debugClone)); if (NS_SUCCEEDED(debug_rv)) { - PRBool same; - debug_rv = aURI->Equals(debugURL, &same); + debug_rv = debugReg->Canonify(debugClone); if (NS_SUCCEEDED(debug_rv)) { - NS_ASSERTION(same, "Non-canonified chrome uri passed to nsChromeProtocolHandler::NewChannel!"); + PRBool same; + debug_rv = aURI->Equals(debugClone, &same); + if (NS_SUCCEEDED(debug_rv)) { + NS_ASSERTION(same, "Non-canonified chrome uri passed to nsChromeProtocolHandler::NewChannel!"); + } } + } } #endif @@ -515,16 +542,15 @@ nsChromeProtocolHandler::NewChannel(nsIURI* aURI, nsresult rv; nsCOMPtr result; +#ifdef MOZ_XUL // Check the prototype cache to see if we've already got the // document in the cache. - nsCOMPtr cache - (do_GetService(kXULPrototypeCacheCID)); - nsCOMPtr proto; + nsCOMPtr cache = + do_GetService(kXULPrototypeCacheCID, &rv); + if (NS_FAILED(rv)) return rv; - if (cache) - cache->GetPrototype(aURI, getter_AddRefs(proto)); - else - NS_WARNING("Unable to obtain the XUL prototype cache!"); + nsCOMPtr proto; + cache->GetPrototype(aURI, getter_AddRefs(proto)); // Same comment as nsXULDocument::StartDocumentLoad and // nsXULDocument::ResumeWalk @@ -549,31 +575,39 @@ nsChromeProtocolHandler::NewChannel(nsIURI* aURI, if (! result) return NS_ERROR_OUT_OF_MEMORY; } - else { + else +#endif + { // Miss. Resolve the chrome URL using the registry and do a // normal necko load. //nsXPIDLCString oldSpec; //aURI->GetSpec(getter_Copies(oldSpec)); //printf("*************************** %s\n", (const char*)oldSpec); - nsCOMPtr reg (do_GetService(NS_CHROMEREGISTRY_CONTRACTID)); - NS_ENSURE_TRUE(reg, NS_ERROR_FAILURE); + nsCOMPtr reg = gChromeRegistry; + if (!reg) { + reg = do_GetService(NS_CHROMEREGISTRY_CONTRACTID, &rv); + if (NS_FAILED(rv)) return rv; + } - nsCOMPtr resolvedURI; - rv = reg->ConvertChromeURL(aURI, getter_AddRefs(resolvedURI)); + nsCAutoString spec; + rv = reg->ConvertChromeURL(aURI, spec); if (NS_FAILED(rv)) { #ifdef DEBUG - nsCAutoString spec; aURI->GetSpec(spec); printf("Couldn't convert chrome URL: %s\n", spec.get()); #endif return rv; } - nsCOMPtr ioServ (do_GetIOService(&rv)); - NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr ioServ(do_GetIOService(&rv)); + if (NS_FAILED(rv)) return rv; - rv = ioServ->NewChannelFromURI(resolvedURI, getter_AddRefs(result)); + nsCOMPtr chromeURI; + rv = ioServ->NewURI(spec, nsnull, nsnull, getter_AddRefs(chromeURI)); + if (NS_FAILED(rv)) return rv; + + rv = ioServ->NewChannelFromURI(chromeURI, getter_AddRefs(result)); if (NS_FAILED(rv)) return rv; // XXX Will be removed someday when we handle remote chrome. @@ -666,8 +700,10 @@ nsChromeProtocolHandler::NewChannel(nsIURI* aURI, if (file) { rv = fastLoadServ->AddDependency(file); +#ifdef MOZ_XUL if (NS_FAILED(rv)) cache->AbortFastLoads(); +#endif } } } diff --git a/mozilla/chrome/src/nsChromeRegistry.cpp b/mozilla/chrome/src/nsChromeRegistry.cpp index 0e8864ce2d9..facc5faa2c2 100644 --- a/mozilla/chrome/src/nsChromeRegistry.cpp +++ b/mozilla/chrome/src/nsChromeRegistry.cpp @@ -22,7 +22,7 @@ * Contributor(s): * Original Author: David W. Hyatt (hyatt@netscape.com) * Gagan Saksena - * Benjamin Smedberg + * Benjamin Smedberg * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -38,71 +38,68 @@ * * ***** END LICENSE BLOCK ***** */ -#include "nsChromeRegistry.h" - #include - -#include "prio.h" - -#include "nsAppDirectoryServiceDefs.h" #include "nsArrayEnumerator.h" #include "nsCOMPtr.h" -#include "nsDOMError.h" -#include "nsEscape.h" -#include "nsInt64.h" -#include "nsLayoutCID.h" -#include "nsNetCID.h" -#include "nsNetUtil.h" -#include "nsReadableUtils.h" -#include "nsStaticAtom.h" -#include "nsString.h" -#include "nsWidgetsCID.h" -#include "nsXPIDLString.h" - -#include "nsIAtom.h" -#include "nsIBindingManager.h" -#include "nsICommandLine.h" -#include "nsICSSLoader.h" -#include "nsICSSStyleSheet.h" -#include "nsIDirectoryService.h" -#include "nsIDocument.h" -#include "nsIDOMDocument.h" -#include "nsIDocShell.h" -#include "nsIDocumentObserver.h" -#include "nsIDOMElement.h" -#include "nsIDOMLocation.h" -#include "nsIDOMWindowCollection.h" -#include "nsIDOMWindowInternal.h" -#include "nsIFileChannel.h" -#include "nsIFileURL.h" -#include "nsIIOService.h" -#include "nsIJARURI.h" -#include "nsILocalFile.h" -#include "nsILocaleService.h" -#include "nsILookAndFeel.h" -#include "nsIObserverService.h" -#include "nsIPrefService.h" -#include "nsIPrefBranch.h" -#include "nsIPrefBranchInternal.h" -#include "nsIPresShell.h" -#include "nsISimpleEnumerator.h" -#include "nsIStyleSheet.h" -#include "nsISupportsArray.h" -#include "nsIWindowMediator.h" - -// keep all the RDF stuff together, in case we can remove it in the far future -#include "rdf.h" -#include "nsRDFCID.h" -#include "nsIRDFService.h" +#include "nsIChromeRegistry.h" +#include "nsChromeRegistry.h" +#include "nsChromeUIDataSource.h" #include "nsIRDFDataSource.h" #include "nsIRDFObserver.h" #include "nsIRDFRemoteDataSource.h" #include "nsIRDFXMLSink.h" +#include "rdf.h" #include "nsIServiceManager.h" +#include "nsIRDFService.h" +#include "nsRDFCID.h" #include "nsIRDFResource.h" #include "nsIRDFDataSource.h" #include "nsIRDFContainer.h" #include "nsIRDFContainerUtils.h" +#include "nsHashtable.h" +#include "nsString.h" +#include "nsReadableUtils.h" +#include "nsXPIDLString.h" +#include "nsISimpleEnumerator.h" +#include "nsNetUtil.h" +#include "nsIFileChannel.h" +#include "nsIXBLService.h" +#include "nsIDOMWindowInternal.h" +#include "nsIDOMWindowCollection.h" +#include "nsIDOMLocation.h" +#include "nsIWindowMediator.h" +#include "nsIDocument.h" +#include "nsIDOMDocument.h" +#include "nsIStyleSheet.h" +#include "nsICSSLoader.h" +#include "nsICSSStyleSheet.h" +#include "nsIPresShell.h" +#include "nsIDocShell.h" +#include "nsISupportsArray.h" +#include "nsIDocumentObserver.h" +#include "nsIIOService.h" +#include "nsLayoutCID.h" +#include "nsIBindingManager.h" +#include "prio.h" +#include "nsInt64.h" +#include "nsIDirectoryService.h" +#include "nsILocalFile.h" +#include "nsAppDirectoryServiceDefs.h" +#include "nsIPrefService.h" +#include "nsIPrefBranch.h" +#include "nsIPrefBranchInternal.h" +#include "nsIObserverService.h" +#include "nsIDOMElement.h" +#include "nsIDOMWindowCollection.h" +#include "nsIAtom.h" +#include "nsStaticAtom.h" +#include "nsNetCID.h" +#include "nsIJARURI.h" +#include "nsIFileURL.h" +#include "nsILocaleService.h" +#include "nsICommandLine.h" +#include "nsILookAndFeel.h" +#include "nsWidgetsCID.h" #define UILOCALE_CMD_LINE_ARG "UILocale" @@ -112,241 +109,86 @@ #define DSS_SKIN_TO_SELECT "extensions.lastSelectedSkin" #define DSS_SWITCH_PENDING "extensions.dss.switchPending" +static char kChromePrefix[] = "chrome://"; +nsIAtom* nsChromeRegistry::sCPrefix; // atom for "c" + +#define kChromeFileName NS_LITERAL_CSTRING("chrome.rdf") +#define kInstalledChromeFileName NS_LITERAL_CSTRING("installed-chrome.txt") + +static NS_DEFINE_CID(kWindowMediatorCID, NS_WINDOWMEDIATOR_CID); +static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); +static NS_DEFINE_CID(kRDFXMLDataSourceCID, NS_RDFXMLDATASOURCE_CID); +static NS_DEFINE_CID(kRDFContainerUtilsCID, NS_RDFCONTAINERUTILS_CID); static NS_DEFINE_CID(kCSSLoaderCID, NS_CSS_LOADER_CID); static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID); -nsChromeRegistry* gChromeRegistry; +nsIChromeRegistry* gChromeRegistry = nsnull; #define CHROME_URI "http://www.mozilla.org/rdf/chrome#" +DEFINE_RDF_VOCAB(CHROME_URI, CHROME, baseURL); DEFINE_RDF_VOCAB(CHROME_URI, CHROME, packages); DEFINE_RDF_VOCAB(CHROME_URI, CHROME, package); DEFINE_RDF_VOCAB(CHROME_URI, CHROME, name); +DEFINE_RDF_VOCAB(CHROME_URI, CHROME, image); +DEFINE_RDF_VOCAB(CHROME_URI, CHROME, locType); +DEFINE_RDF_VOCAB(CHROME_URI, CHROME, allowScripts); +DEFINE_RDF_VOCAB(CHROME_URI, CHROME, hasOverlays); +DEFINE_RDF_VOCAB(CHROME_URI, CHROME, hasStylesheets); +DEFINE_RDF_VOCAB(CHROME_URI, CHROME, disabled); DEFINE_RDF_VOCAB(CHROME_URI, CHROME, platformPackage); //////////////////////////////////////////////////////////////////////////////// -// We use a "best-fit" algorithm for matching locales and themes. -// 1) the exact selected locale/theme -// 2) (locales only) same language, different country -// e.g. en-GB is the selected locale, only en-US is available -// 3) any available locale/theme - -/** - * Match the language-part of two lang-COUNTRY codes, hopefully but - * not guaranteed to be in the form ab-CD or abz-CD. "ab" should also - * work, any other garbage-in will produce undefined results as long - * as it does not crash. - */ -static PRBool -LanguagesMatch(const nsACString& a, const nsACString& b) +nsChromeRegistry::nsChromeRegistry() : mRDFService(nsnull), + mRDFContainerUtils(nsnull), + mInstallInitialized(PR_FALSE), + mProfileInitialized(PR_FALSE), + mBatchInstallFlushes(PR_FALSE) { - if (a.Length() < 2 || b.Length() < 2) + mDataSourceTable = nsnull; +} + + +static PRBool PR_CALLBACK +DatasourceEnumerator(nsHashKey *aKey, void *aData, void* closure) +{ + if (!closure || !aData) return PR_FALSE; - nsACString::const_iterator as, ae, bs, be; - a.BeginReading(as); - a.EndReading(ae); - b.BeginReading(bs); - b.EndReading(be); + nsIRDFCompositeDataSource* compositeDS = (nsIRDFCompositeDataSource*) closure; - while (*as == *bs) { - if (*as == '-') - return PR_TRUE; - - // reached the end - if (as == ae && bs == be) - return PR_TRUE; + nsCOMPtr supports = (nsISupports*)aData; - // "a" is short - if (as == ae) - return (*++bs == '-'); + nsCOMPtr dataSource = do_QueryInterface(supports); + if (!dataSource) + return PR_FALSE; - // "b" is short - if (bs == be) - return (*++as == '-'); - - ++as; ++bs; - } - - return PR_FALSE; -} - -nsChromeRegistry::ProviderEntry* -nsChromeRegistry::nsProviderArray::GetProvider(const nsACString& aPreferred, MatchType aType) -{ - PRInt32 i = mArray.Count(); - if (!i) - return nsnull; - - ProviderEntry* found = nsnull; // Only set if we find a partial-match locale - ProviderEntry* entry; - - while (i--) { - entry = NS_REINTERPRET_CAST(ProviderEntry*, mArray[i]); - if (aPreferred.Equals(entry->provider)) - return entry; - - if (aType == LOCALE && !found && LanguagesMatch(aPreferred, entry->provider)) - found = entry; - } - - if (!found && aType != EXACT) - return entry; - - return found; -} - -nsIURI* -nsChromeRegistry::nsProviderArray::GetBase(const nsACString& aPreferred, MatchType aType) -{ - ProviderEntry* provider = GetProvider(aPreferred, aType); - - if (!provider) - return nsnull; - - return provider->baseURI; -} - -const nsACString& -nsChromeRegistry::nsProviderArray::GetSelected(const nsACString& aPreferred, MatchType aType) -{ - ProviderEntry* entry = GetProvider(aPreferred, aType); - - if (entry) - return entry->provider; - - return EmptyCString(); -} - -void -nsChromeRegistry::nsProviderArray::SetBase(const nsACString& aProvider, nsIURI* aBaseURL) -{ - ProviderEntry* provider = GetProvider(aProvider, EXACT); - - if (provider) { - provider->baseURI = aBaseURL; - return; - } - - // no existing entries, add a new one - provider = new ProviderEntry(aProvider, aBaseURL); - if (!provider) - return; // It's safe to silently fail on OOM - - mArray.AppendElement(provider); -} - -void -nsChromeRegistry::nsProviderArray::Clear() -{ - PRInt32 i = mArray.Count(); - while (i--) { - ProviderEntry* entry = NS_REINTERPRET_CAST(ProviderEntry*, mArray[i]); - delete entry; - } - - mArray.Clear(); -} - -nsChromeRegistry::PackageEntry::PackageEntry(const nsACString& aPackage) : - package(aPackage), flags(0) -{ -} - -const void* -nsChromeRegistry::GetKey(PLDHashTable *table, PLDHashEntryHdr *entry) -{ - PackageEntry* pentry = NS_STATIC_CAST(PackageEntry*, entry); - return (nsACString*) &pentry->package; -} - -PLHashNumber -nsChromeRegistry::HashKey(PLDHashTable *table, const void *key) -{ - const nsACString& str = *NS_REINTERPRET_CAST(const nsACString*, key); - return HashString(str); -} - -PRBool -nsChromeRegistry::MatchKey(PLDHashTable *table, const PLDHashEntryHdr *entry, - const void *key) -{ - const nsACString& str = *NS_REINTERPRET_CAST(const nsACString*, key); - const PackageEntry* pentry = NS_STATIC_CAST(const PackageEntry*, entry); - return str.Equals(pentry->package); -} - -void -nsChromeRegistry::ClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry) -{ - PackageEntry* pentry = NS_STATIC_CAST(PackageEntry*, entry); - pentry->~PackageEntry(); -} - -PRBool -nsChromeRegistry::InitEntry(PLDHashTable *table, PLDHashEntryHdr *entry, - const void *key) -{ - const nsACString& str = *NS_REINTERPRET_CAST(const nsACString*, key); - - new (entry) PackageEntry(str); +#ifdef DEBUG + nsresult rv = +#endif + compositeDS->RemoveDataSource(dataSource); + NS_ASSERTION(NS_SUCCEEDED(rv), "failed to RemoveDataSource"); return PR_TRUE; } -const PLDHashTableOps -nsChromeRegistry::kTableOps = { - PL_DHashAllocTable, - PL_DHashFreeTable, - GetKey, - HashKey, - MatchKey, - PL_DHashMoveEntryStub, - ClearEntry, - PL_DHashFinalizeStub, - InitEntry -}; - -void -nsChromeRegistry::OverlayListEntry::AddURI(nsIURI* aURI) -{ - PRInt32 i = mArray.Count(); - while (i--) { - PRBool equals; - if (NS_SUCCEEDED(aURI->Equals(mArray[i], &equals)) && equals) - return; - } - - mArray.AppendObject(aURI); -} - -void -nsChromeRegistry::OverlayListHash::Add(nsIURI* aBase, nsIURI* aOverlay) -{ - OverlayListEntry* entry = mTable.PutEntry(aBase); - if (entry) - entry->AddURI(aOverlay); -} - -const nsCOMArray* -nsChromeRegistry::OverlayListHash::GetArray(nsIURI* aBase) -{ - OverlayListEntry* entry = mTable.GetEntry(aBase); - if (!entry) - return nsnull; - - return &entry->mArray; -} nsChromeRegistry::~nsChromeRegistry() { gChromeRegistry = nsnull; + + if (mDataSourceTable) { + mDataSourceTable->Enumerate(DatasourceEnumerator, mChromeDataSource); + delete mDataSourceTable; + } + + NS_IF_RELEASE(mRDFService); + NS_IF_RELEASE(mRDFContainerUtils); } -NS_IMPL_THREADSAFE_ISUPPORTS6(nsChromeRegistry, +NS_IMPL_THREADSAFE_ISUPPORTS5(nsChromeRegistry, nsIChromeRegistry, nsIXULChromeRegistry, - nsIToolkitChromeRegistry, nsIXULOverlayProvider, nsIObserver, nsISupportsWeakReference) @@ -373,32 +215,70 @@ getUILangCountry(nsACString& aUILang) nsresult nsChromeRegistry::Init() { - nsresult rv; - - // these atoms appear in almost every chrome registry contents.rdf + // these atoms appear in almost every chrome registry manifest.rdf // in some form or another. making static atoms prevents the atoms // from constantly being created/destroyed during parsing static const nsStaticAtom atoms[] = { + { "c", &sCPrefix }, { "chrome", nsnull }, { "NC", nsnull }, + { "baseURL", nsnull}, { "allowScripts", nsnull }, { "package", nsnull }, { "packages", nsnull }, + { "locType", nsnull }, + { "displayName", nsnull }, + { "author", nsnull }, + { "localeType", nsnull }, { "hasOverlays", nsnull }, + { "previewURL", nsnull }, }; NS_RegisterStaticAtoms(atoms, NS_ARRAY_LENGTH(atoms)); - if (!PL_DHashTableInit(&mPackagesHash, &kTableOps, - nsnull, sizeof(PackageEntry), 16)) - return NS_ERROR_FAILURE; - - if (!mOverlayHash.Init() || - !mStyleHash.Init()) - return NS_ERROR_FAILURE; + if (!mSelectedLocales.Init()) return NS_ERROR_FAILURE; + if (!mSelectedSkins.Init()) return NS_ERROR_FAILURE; gChromeRegistry = this; + + nsresult rv; + rv = CallGetService(kRDFServiceCID, &mRDFService); + NS_ENSURE_SUCCESS(rv, rv); + + rv = CallGetService(kRDFContainerUtilsCID, &mRDFContainerUtils); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mRDFService->GetResource(nsDependentCString(kURICHROME_baseURL), + getter_AddRefs(mBaseURL)); + rv |= mRDFService->GetResource(nsDependentCString(kURICHROME_packages), + getter_AddRefs(mPackages)); + rv |= mRDFService->GetResource(nsDependentCString(kURICHROME_package), + getter_AddRefs(mPackage)); + rv |= mRDFService->GetResource(nsDependentCString(kURICHROME_name), + getter_AddRefs(mName)); + rv |= mRDFService->GetResource(nsDependentCString(kURICHROME_image), + getter_AddRefs(mImage)); + rv |= mRDFService->GetResource(nsDependentCString(kURICHROME_locType), + getter_AddRefs(mLocType)); + rv |= mRDFService->GetResource(nsDependentCString(kURICHROME_allowScripts), + getter_AddRefs(mAllowScripts)); + rv |= mRDFService->GetResource(nsDependentCString(kURICHROME_hasOverlays), + getter_AddRefs(mHasOverlays)); + rv |= mRDFService->GetResource(nsDependentCString(kURICHROME_hasStylesheets), + getter_AddRefs(mHasStylesheets)); + rv |= mRDFService->GetResource(nsDependentCString(kURICHROME_disabled), + getter_AddRefs(mDisabled)); + rv |= mRDFService->GetResource(nsDependentCString(kURICHROME_platformPackage), + getter_AddRefs(mPlatformPackage)); + NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); + + nsCOMPtr observerService = + do_GetService("@mozilla.org/observer-service;1"); + if (observerService) { + observerService->AddObserver(this, "profile-before-change", PR_TRUE); + observerService->AddObserver(this, "profile-after-change", PR_TRUE); + } mSelectedLocale = NS_LITERAL_CSTRING("en-US"); mSelectedSkin = NS_LITERAL_CSTRING("classic/1.0"); @@ -467,176 +347,832 @@ nsChromeRegistry::Init() return NS_OK; } -nsresult -nsChromeRegistry::GetProviderAndPath(nsIURL* aChromeURL, - nsACString& aProvider, nsACString& aPath) + +static nsresult +SplitURL(nsIURI *aChromeURI, nsCString& aPackage, nsCString& aProvider, nsCString& aFile, + PRBool *aModified = nsnull) { + // Splits a "chrome:" URL into its package, provider, and file parts. + // Here are the current portions of a + // chrome: url that make up the chrome- + // + // chrome://global/skin/foo?bar + // \------/ \----/\---/ \-----/ + // | | | | + // | | | `-- RemainingPortion + // | | | + // | | `-- Provider + // | | + // | `-- Package + // | + // `-- Always "chrome://" + // + // + nsresult rv; -#ifdef DEBUG - PRBool isChrome; - aChromeURL->SchemeIs("chrome", &isChrome); - NS_ASSERTION(isChrome, "Non-chrome URI?"); -#endif + nsCAutoString str; + rv = aChromeURI->GetSpec(str); + if (NS_FAILED(rv)) return rv; - nsCAutoString path; - rv = aChromeURL->GetPath(path); - NS_ENSURE_SUCCESS(rv, rv); + // We only want to deal with "chrome:" URLs here. We could return + // an error code if the URL isn't properly prefixed here... + if (PL_strncmp(str.get(), kChromePrefix, sizeof(kChromePrefix) - 1) != 0) + return NS_ERROR_INVALID_ARG; - if (path.Length() < 3) - return NS_ERROR_FAILURE; + // Cull out the "package" string; e.g., "navigator" + aPackage = str.get() + sizeof(kChromePrefix) - 1; - path.SetLength(nsUnescapeCount(path.BeginWriting())); - NS_ASSERTION(path.First() == '/', "Path should always begin with a slash!"); + PRInt32 idx; + idx = aPackage.FindChar('/'); + if (idx < 0) + return NS_OK; - PRInt32 slash = path.FindChar('/', 1); - if (slash == 1) - return NS_ERROR_FAILURE; + // Cull out the "provider" string; e.g., "content" + aPackage.Right(aProvider, aPackage.Length() - (idx + 1)); + aPackage.Truncate(idx); - if (slash == -1) { - aPath.Truncate(); - } - else { - if (slash == (PRInt32) path.Length() - 1) - aPath.Truncate(); - else - aPath.Assign(path.get() + slash + 1, path.Length() - slash - 1); - - --slash; + idx = aProvider.FindChar('/'); + if (idx < 0) { + // Force the provider to end with a '/' + idx = aProvider.Length(); + aProvider.Append('/'); } - aProvider.Assign(path.get() + 1, slash); - return NS_OK; -} + // Cull out the "file"; e.g., "navigator.xul" + aProvider.Right(aFile, aProvider.Length() - (idx + 1)); + aProvider.Truncate(idx); -static NS_NAMED_LITERAL_CSTRING(kSlash, "/"); + PRBool nofile = aFile.IsEmpty(); + if (nofile) { + // If there is no file, then construct the default file + aFile = aPackage; -nsresult -nsChromeRegistry::Canonify(nsIURL* aChromeURL) -{ - nsresult rv; - - nsCAutoString provider, path; - rv = GetProviderAndPath(aChromeURL, provider, path); - NS_ENSURE_SUCCESS(rv, rv); - - if (path.IsEmpty()) { - nsCAutoString package; - rv = aChromeURL->GetHost(package); - NS_ENSURE_SUCCESS(rv, rv); - - // we re-use the "path" local string to build a new URL path - path.Assign(kSlash + provider + kSlash + package); - if (provider.EqualsLiteral("content")) { - path.AppendLiteral(".xul"); + if (aProvider.Equals("content")) { + aFile += ".xul"; } - else if (provider.EqualsLiteral("locale")) { - path.AppendLiteral(".dtd"); + else if (aProvider.Equals("skin")) { + aFile += ".css"; } - else if (provider.EqualsLiteral("skin")) { - path.AppendLiteral(".css"); + else if (aProvider.Equals("locale")) { + aFile += ".dtd"; } else { - // XXXbsmedberg: report this to the console service? - return NS_ERROR_INVALID_ARG; + NS_ERROR("unknown provider"); + return NS_ERROR_FAILURE; } - aChromeURL->SetPath(path); - } - else if (path.Find(NS_LITERAL_CSTRING("..")) != -1) { - return NS_ERROR_DOM_BAD_URI; - } + } else { + // Protect against URIs containing .. that reach up out of the + // chrome directory to grant chrome privileges to non-chrome files. + int depth = 0; + PRBool sawSlash = PR_TRUE; // .. at the beginning is suspect as well as /.. + for (const char* p=aFile.get(); *p; p++) { + if (sawSlash) { + if (p[0] == '.' && p[1] == '.'){ + depth--; // we have /.., decrement depth. + } else { + static const char escape[] = "%2E%2E"; + if (PL_strncasecmp(p, escape, sizeof(escape)-1) == 0) + depth--; // we have the HTML-escaped form of /.., decrement depth. + } + } else if (p[0] != '/') { + depth++; // we have /x for some x that is not / + } + sawSlash = (p[0] == '/'); + if (depth < 0) { + return NS_ERROR_FAILURE; + } + } + } + if (aModified) + *aModified = nofile; return NS_OK; } NS_IMETHODIMP -nsChromeRegistry::ConvertChromeURL(nsIURI* aChromeURI, nsIURI* *aResult) +nsChromeRegistry::Canonify(nsIURI* aChromeURI) { + // Canonicalize 'chrome:' URLs. We'll take any 'chrome:' URL + // without a filename, and change it to a URL -with- a filename; + // e.g., "chrome://navigator/content" to + // "chrome://navigator/content/navigator.xul". + if (! aChromeURI) + return NS_ERROR_NULL_POINTER; + + PRBool modified = PR_TRUE; // default is we do canonification + nsCAutoString package, provider, file; nsresult rv; - NS_ASSERTION(aChromeURI, "null url!"); + rv = SplitURL(aChromeURI, package, provider, file, &modified); + if (NS_FAILED(rv)) + return rv; - nsCOMPtr chromeURL (do_QueryInterface(aChromeURI)); - NS_ENSURE_TRUE(chromeURL, NS_NOINTERFACE); + if (!modified) + return NS_OK; - nsCAutoString package, provider, path; - rv = chromeURL->GetHostPort(package); - NS_ENSURE_SUCCESS(rv, rv); + nsCAutoString canonical( kChromePrefix ); + canonical += package; + canonical += "/"; + canonical += provider; + canonical += "/"; + canonical += file; - rv = GetProviderAndPath(chromeURL, provider, path); - NS_ENSURE_SUCCESS(rv, rv); + return aChromeURI->SetSpec(canonical); +} - PackageEntry* entry = - NS_STATIC_CAST(PackageEntry*, PL_DHashTableOperate(&mPackagesHash, - & (nsACString&) package, - PL_DHASH_LOOKUP)); +NS_IMETHODIMP +nsChromeRegistry::ConvertChromeURL(nsIURI* aChromeURL, nsACString& aResult) +{ + nsresult rv = NS_OK; + NS_ASSERTION(aChromeURL, "null url!"); + if (!aChromeURL) + return NS_ERROR_NULL_POINTER; - if (PL_DHASH_ENTRY_IS_FREE(entry)) - return NS_ERROR_FAILURE; + // No need to canonify as the SplitURL() that we + // do is the equivalent of canonification without modifying + // aChromeURL - if (entry->flags & PackageEntry::PLATFORM_PACKAGE) { -#if defined(XP_WIN) || defined(XP_OS2) - path.Insert("win/", 0); -#elif defined(XP_MACOSX) - path.Insert("mac/", 0); -#else - path.Insert("unix/", 0); + // Obtain the package, provider and remaining from the URL + nsCAutoString package, provider, remaining; + + rv = SplitURL(aChromeURL, package, provider, remaining); + if (NS_FAILED(rv)) return rv; + + // Try for the profile data source first because it + // will load the install data source as well. + if (!mProfileInitialized) { + rv = LoadProfileDataSource(); + if (NS_FAILED(rv)) return rv; + } + if (!mInstallInitialized) { + rv = LoadInstallDataSource(); + if (NS_FAILED(rv)) return rv; + } + + nsCAutoString finalURL; + + rv = GetBaseURL(package, provider, finalURL); + + if (NS_FAILED(rv)) { +#ifdef DEBUG + nsCAutoString msg("chrome: failed to get base url"); + nsCAutoString url; + nsresult rv2 = aChromeURL->GetSpec(url); + if (NS_SUCCEEDED(rv2)) { + msg += " for "; + msg += url.get(); + } + msg += " -- using wacky default"; + NS_WARNING(msg.get()); #endif + return rv; } - nsIURI* baseURI = nsnull; - if (provider.EqualsLiteral("locale")) { - baseURI = entry->locales.GetBase(mSelectedLocale, nsProviderArray::LOCALE); - } - else if (provider.EqualsLiteral("skin")) { - baseURI = entry->skins.GetBase(mSelectedSkin, nsProviderArray::SKIN); - } - else { - baseURI = entry->baseURI; - } - - if (!baseURI) - return NS_ERROR_FAILURE; - - return NS_NewURI(aResult, path, nsnull, baseURI); + aResult = finalURL + remaining; + return NS_OK; } nsresult nsChromeRegistry::GetSelectedLocale(const nsACString& aPackage, nsACString& aLocale) { - PackageEntry* entry = - NS_STATIC_CAST(PackageEntry*, PL_DHashTableOperate(&mPackagesHash, - & aPackage, - PL_DHASH_LOOKUP)); + nsresult rv; - if (PL_DHASH_ENTRY_IS_FREE(entry)) - return NS_ERROR_FAILURE; + // Try for the profile data source first because it + // will load the install data source as well. + if (!mProfileInitialized) { + rv = LoadProfileDataSource(); + if (NS_FAILED(rv)) return rv; + } + if (!mInstallInitialized) { + rv = LoadInstallDataSource(); + if (NS_FAILED(rv)) return rv; + } - aLocale = entry->locales.GetSelected(mSelectedLocale, nsProviderArray::LOCALE); - if (aLocale.IsEmpty()) + nsCOMPtr resource; + nsCOMPtr packageResource; + + rv = FindProvider(aPackage, NS_LITERAL_CSTRING("locale"), resource, packageResource); + if (NS_FAILED(rv)) return rv; + + // selectedProvider.mURI now looks like "urn:mozilla:locale:ja-JP:navigator" + const char *uri; + resource->GetValueConst(&uri); + + // trim down to "urn:mozilla:locale:ja-JP" + nsCAutoString packageStr(":"); + packageStr += aPackage; + + nsCAutoString ustr(uri); + PRInt32 pos = ustr.RFind(packageStr); + nsCAutoString urn; + ustr.Left(urn, pos); + + rv = GetResource(urn, getter_AddRefs(resource)); + NS_ENSURE_SUCCESS(rv, rv); + + // From this resource, follow the "name" arc. + return FollowArc(mChromeDataSource, aLocale, resource, mName); +} + +nsresult +nsChromeRegistry::GetBaseURL(const nsACString& aPackage, + const nsACString& aProvider, + nsACString& aBaseURL) +{ + nsresult rv; + nsCOMPtr resource; + nsCOMPtr packageResource; + + rv = FindProvider(aPackage, aProvider, resource, packageResource); + if (NS_FAILED(rv)) return rv; + + // From this resource, follow the "baseURL" arc. + rv = FollowArc(mChromeDataSource, aBaseURL, resource, mBaseURL); + NS_ENSURE_SUCCESS(rv, rv); + + nsCAutoString isPlatformPackage; + rv = FollowArc(mChromeDataSource, isPlatformPackage, packageResource, mPlatformPackage); + if (NS_FAILED(rv) || !isPlatformPackage.Equals("true")) return NS_OK; + +#if defined(XP_WIN) || defined(XP_OS2) + aBaseURL.Append("win/"); +#elif defined(XP_MACOSX) + aBaseURL.Append("mac/"); +#else + aBaseURL.Append("unix/"); +#endif + + return NS_OK; +} + +nsresult +nsChromeRegistry::FindProvider(const nsACString& aPackage, const nsACString& aProvider, + nsCOMPtr &aProviderResource, + nsCOMPtr &aPackageResource) +{ + nsresult rv; + + nsCAutoString resourceStr("urn:mozilla:package:"); + resourceStr += aPackage; + + // Obtain the resource. + rv = GetResource(resourceStr, getter_AddRefs(aPackageResource)); + NS_ENSURE_SUCCESS(rv, rv); + + if (aProvider.Equals(NS_LITERAL_CSTRING("skin"))) { + mSelectedSkins.Get(aPackage, getter_AddRefs(aProviderResource)); + if (!aProviderResource) { + rv = FindSubProvider(aPackage, aProvider, aProviderResource); + if (NS_FAILED(rv)) return rv; + } + } + else if (aProvider.Equals(NS_LITERAL_CSTRING("locale"))) { + mSelectedLocales.Get(aPackage, getter_AddRefs(aProviderResource)); + if (!aProviderResource) { + rv = FindSubProvider(aPackage, aProvider, aProviderResource); + if (NS_FAILED(rv)) return rv; + } + } + else { + NS_ASSERTION(aProvider.Equals(NS_LITERAL_CSTRING("content")), "Bad provider!"); + aProviderResource = aPackageResource; + } + + if (!aProviderResource) return NS_ERROR_FAILURE; return NS_OK; } +nsresult +nsChromeRegistry::TrySubProvider(const nsACString& aPackage, + nsIRDFResource* aProviderResource, + nsCOMPtr &aSelectedProvider) +{ + nsresult rv; + + // We've got a resource like in aProviderResource + // get its package list + nsCOMPtr packageNode; + rv = mChromeDataSource->GetTarget(aProviderResource, mPackages, + PR_TRUE, getter_AddRefs(packageNode)); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr packageList (do_QueryInterface(packageNode)); + if (!packageList) return NS_ERROR_FAILURE; + + nsCOMPtr container + (do_CreateInstance("@mozilla.org/rdf/container;1", &rv)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = container->Init(mChromeDataSource, packageList); + NS_ENSURE_SUCCESS(rv, rv); + + // step through its (seq) arcs + nsCOMPtr arcs; + rv = container->GetElements(getter_AddRefs(arcs)); + NS_ENSURE_SUCCESS(rv, rv); + + PRBool hasMore; + nsCOMPtr supports; + nsCOMPtr kid; + nsCOMPtr package; + + while (NS_SUCCEEDED(arcs->HasMoreElements(&hasMore)) && hasMore) { + // get next arc resource + rv = arcs->GetNext(getter_AddRefs(supports)); + NS_ENSURE_SUCCESS(rv, rv); + + kid = do_QueryInterface(supports); + if (!kid) continue; + + // get its package resource + rv = mChromeDataSource->GetTarget(kid, mPackage, PR_TRUE, + getter_AddRefs(packageNode)); + if (NS_FAILED(rv)) continue; + + package = do_QueryInterface(packageNode); + if (!package) continue; + + // get its name + nsCAutoString packageName; + rv = FollowArc(mChromeDataSource, packageName, package, mName); + if (NS_FAILED(rv)) continue; // don't fail if package has not yet been installed + + if (packageName.Equals(aPackage)) { + aSelectedProvider = kid; + return NS_OK; + } + } + + return NS_ERROR_FAILURE; +} + +// We use a "best-fit" algorithm for matching locales and themes. +// ANY: any available locale/theme +// LANGUAGE: (locales only) same language, different country +// e.g. en-GB is the selected locale, only en-US is available +// PRECISE: the exact selected locale/theme + +enum nsProviderQuality { + MISSING = 0, + ANY = 1, + LANGUAGE = 2, + PRECISE = 3 +}; + +/** + * Match the language-part of two lang-COUNTRY codes, hopefully but + * not guaranteed to be in the form ab-CD or abz-CD. "ab" should also + * work, any other garbage-in will produce undefined results as long + * as it does not crash. + */ +static PRBool +LanguagesMatch(const nsACString& a, const nsACString& b) +{ + if (a.Length() < 2 || b.Length() < 2) + return PR_FALSE; + + nsACString::const_iterator as, ae, bs, be; + a.BeginReading(as); + a.EndReading(ae); + b.BeginReading(bs); + b.EndReading(be); + + while (*as == *bs) { + if (*as == '-') + return PR_TRUE; + + // reached the end + if (as == ae && bs == be) + return PR_TRUE; + + // "a" is short + if (as == ae) + return (*++bs == '-'); + + // "b" is short + if (bs == be) + return (*++as == '-'); + + ++as; ++bs; + } + + return PR_FALSE; +} + +nsresult +nsChromeRegistry::FindSubProvider(const nsACString& aPackage, + const nsACString& aProvider, + nsCOMPtr &aSelectedProvider) +{ + nsresult rv; + + PRBool isLocale = aProvider.Equals(NS_LITERAL_CSTRING("locale")); + nsACString &selectedProvider = isLocale ? mSelectedLocale : mSelectedSkin; + + nsCAutoString rootStr(NS_LITERAL_CSTRING("urn:mozilla:")); + rootStr += aProvider; + rootStr += ":root"; + + nsCOMPtr resource; + rv = GetResource(rootStr, getter_AddRefs(resource)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr container = + do_CreateInstance("@mozilla.org/rdf/container;1", &rv); + NS_ENSURE_SUCCESS(rv, rv); + + rv = container->Init(mChromeDataSource, resource); + NS_ENSURE_SUCCESS(rv, rv); + + // step through its (seq) arcs + nsCOMPtr arcs; + rv = container->GetElements(getter_AddRefs(arcs)); + NS_ENSURE_SUCCESS(rv, rv); + + PRBool moreElements; + nsCOMPtr supports; + nsCOMPtr kid; + nsCAutoString name; + nsProviderQuality quality = MISSING; + + while (quality < PRECISE && + NS_SUCCEEDED(arcs->HasMoreElements(&moreElements)) && moreElements) { + // get next arc resource + rv = arcs->GetNext(getter_AddRefs(supports)); + NS_ENSURE_SUCCESS(rv, rv); + + kid = do_QueryInterface(supports); + if (!kid) continue; + + rv = FollowArc(mChromeDataSource, name, kid, mName); + if (NS_FAILED(rv)) + continue; // don't fail if package has not yet been installed + + nsProviderQuality thisQuality = ANY; + + if (name.Equals(selectedProvider)) + thisQuality = PRECISE; + else if (isLocale && LanguagesMatch(name, selectedProvider)) + thisQuality = LANGUAGE; + + if (thisQuality <= quality) + continue; + + rv = TrySubProvider(aPackage, kid, aSelectedProvider); + if (NS_FAILED(rv)) + continue; + + quality = thisQuality; + } + + if (quality == MISSING) + return NS_ERROR_FAILURE; + + // we found the locale/skin, cache it in memory + if (isLocale) + mSelectedLocales.Put(aPackage, aSelectedProvider); + else + mSelectedSkins.Put(aPackage, aSelectedProvider); + + return NS_OK; +} + +nsresult +nsChromeRegistry::GetDynamicDataSource(nsIURI *aChromeURL, + PRBool aIsOverlay, PRBool aUseProfile, + PRBool aCreateDS, + nsIRDFDataSource **aResult) +{ + *aResult = nsnull; + + nsresult rv; + + if (!mDataSourceTable) + return NS_OK; + + // Obtain the package, provider and remaining from the URL + nsCAutoString package, provider, remaining; + + rv = SplitURL(aChromeURL, package, provider, remaining); + NS_ENSURE_SUCCESS(rv, rv); + + if (!aCreateDS) { + // We are not supposed to create the data source, which means + // we should first check our chrome.rdf file to see if this + // package even has dynamic data. Only if it claims to have + // dynamic data are we willing to hand back a datasource. + nsDependentCString dataSourceStr(kChromeFileName); + nsCOMPtr mainDataSource; + rv = LoadDataSource(dataSourceStr, getter_AddRefs(mainDataSource), aUseProfile, nsnull); + NS_ENSURE_SUCCESS(rv, rv); + + // Now that we have the appropriate chrome.rdf file, we + // must check the package resource for stylesheets or overlays. + nsCOMPtr hasDynamicDataArc; + if (aIsOverlay) + hasDynamicDataArc = mHasOverlays; + else + hasDynamicDataArc = mHasStylesheets; + + // Obtain the resource for the package. + nsCAutoString packageResourceStr("urn:mozilla:package:"); + packageResourceStr += package; + nsCOMPtr packageResource; + GetResource(packageResourceStr, getter_AddRefs(packageResource)); + + // Follow the dynamic data arc to see if we should continue. + // Only if it claims to have dynamic data do we even bother. + nsCAutoString hasDynamicDS; + nsChromeRegistry::FollowArc(mainDataSource, hasDynamicDS, + packageResource, hasDynamicDataArc); + if (hasDynamicDS.IsEmpty()) + return NS_OK; // No data source exists. + } + + // Retrieve the mInner data source. + nsCAutoString overlayFile( "overlayinfo/" ); + overlayFile += package; + overlayFile += "/"; + + if (aIsOverlay) + overlayFile += "content/overlays.rdf"; + else overlayFile += "skin/stylesheets.rdf"; + + return LoadDataSource(overlayFile, aResult, aUseProfile, nsnull); +} + NS_IMETHODIMP nsChromeRegistry::GetStyleOverlays(nsIURI *aChromeURL, nsISimpleEnumerator **aResult) { - const nsCOMArray* parray = mStyleHash.GetArray(aChromeURL); - if (!parray) - return NS_NewEmptyEnumerator(aResult); - - return NS_NewArrayEnumerator(aResult, *parray); + return GetDynamicInfo(aChromeURL, PR_FALSE, aResult); } NS_IMETHODIMP nsChromeRegistry::GetXULOverlays(nsIURI *aChromeURL, nsISimpleEnumerator **aResult) { - const nsCOMArray* parray = mOverlayHash.GetArray(aChromeURL); - if (!parray) - return NS_NewEmptyEnumerator(aResult); + return GetDynamicInfo(aChromeURL, PR_TRUE, aResult); +} - return NS_NewArrayEnumerator(aResult, *parray); +nsresult +nsChromeRegistry::GetURIList(nsIRDFDataSource *aSource, + nsIRDFResource *aResource, + nsCOMArray& aArray) +{ + nsresult rv; + nsCOMPtr arcs; + nsCOMPtr container = + do_CreateInstance("@mozilla.org/rdf/container;1", &rv); + if (NS_FAILED(rv)) goto end_GetURIList; + + rv = container->Init(aSource, aResource); + if (NS_FAILED(rv)) { + rv = NS_OK; + goto end_GetURIList; + } + + rv = container->GetElements(getter_AddRefs(arcs)); + if (NS_FAILED(rv)) goto end_GetURIList; + + { + nsCOMPtr supports; + nsCOMPtr value; + nsCOMPtr uri; + PRBool hasMore; + + while (NS_SUCCEEDED(rv = arcs->HasMoreElements(&hasMore)) && hasMore) { + rv = arcs->GetNext(getter_AddRefs(supports)); + if (NS_FAILED(rv)) break; + + value = do_QueryInterface(supports, &rv); + if (NS_FAILED(rv)) continue; + + const PRUnichar* valueStr; + rv = value->GetValueConst(&valueStr); + if (NS_FAILED(rv)) continue; + + rv = NS_NewURI(getter_AddRefs(uri), NS_ConvertUTF16toUTF8(valueStr)); + if (NS_FAILED(rv)) continue; + + if (IsOverlayAllowed(uri)) { + if (!aArray.AppendObject(uri)) { + rv = NS_ERROR_OUT_OF_MEMORY; + break; + } + } + } + } + +end_GetURIList: + return rv; +} + +nsresult +nsChromeRegistry::GetDynamicInfo(nsIURI *aChromeURL, PRBool aIsOverlay, + nsISimpleEnumerator **aResult) +{ + *aResult = nsnull; + + nsresult rv; + + if (!mDataSourceTable) + return NS_OK; + + nsCOMPtr installSource; + rv = GetDynamicDataSource(aChromeURL, aIsOverlay, PR_FALSE, PR_FALSE, + getter_AddRefs(installSource)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr profileSource; + if (mProfileInitialized) { + rv = GetDynamicDataSource(aChromeURL, aIsOverlay, PR_TRUE, PR_FALSE, + getter_AddRefs(profileSource)); + NS_ENSURE_SUCCESS(rv, rv); + } + + nsCAutoString lookup; + rv = aChromeURL->GetSpec(lookup); + NS_ENSURE_SUCCESS(rv, rv); + + // Get the chromeResource from this lookup string + nsCOMPtr chromeResource; + rv = GetResource(lookup, getter_AddRefs(chromeResource)); + if (NS_FAILED(rv)) { + NS_ERROR("Unable to retrieve the resource corresponding to the chrome skin or content."); + return rv; + } + + nsCOMArray overlayURIs; + + if (installSource) { + GetURIList(installSource, chromeResource, overlayURIs); + } + if (profileSource) { + GetURIList(profileSource, chromeResource, overlayURIs); + } + + return NS_NewArrayEnumerator(aResult, overlayURIs); +} + +nsresult +nsChromeRegistry::LoadDataSource(const nsACString &aFileName, + nsIRDFDataSource **aResult, + PRBool aUseProfileDir, + const char *aProfilePath) +{ + // Init the data source to null. + *aResult = nsnull; + + nsCAutoString key; + + // Try the profile root first. + if (aUseProfileDir) { + // use given profile path if non-null + if (aProfilePath) { + key = aProfilePath; + key += "chrome/"; + } + else + key = mProfileRoot; + + key += aFileName; + } + else { + key = mInstallRoot; + key += aFileName; + } + + if (mDataSourceTable) + { + nsCStringKey skey(key); + nsCOMPtr supports = + getter_AddRefs(NS_STATIC_CAST(nsISupports*, mDataSourceTable->Get(&skey))); + + if (supports) + { + nsCOMPtr dataSource = do_QueryInterface(supports); + if (dataSource) + { + *aResult = dataSource; + NS_ADDREF(*aResult); + return NS_OK; + } + return NS_ERROR_FAILURE; + } + } + + nsresult rv = CallCreateInstance(kRDFXMLDataSourceCID, aResult); + if (NS_FAILED(rv)) return rv; + + // Seed the datasource with the ``chrome'' namespace + nsCOMPtr sink = do_QueryInterface(*aResult); + if (sink) + sink->AddNameSpace(sCPrefix, NS_ConvertASCIItoUCS2(CHROME_URI)); + + nsCOMPtr remote = do_QueryInterface(*aResult); + if (! remote) + return NS_ERROR_UNEXPECTED; + + if (!mDataSourceTable) + mDataSourceTable = new nsSupportsHashtable; + + // We need to read this synchronously. + rv = remote->Init(key.get()); + if (NS_SUCCEEDED(rv)) + rv = remote->Refresh(PR_TRUE); + + nsCOMPtr supports = do_QueryInterface(remote); + nsCStringKey skey(key); + mDataSourceTable->Put(&skey, supports.get()); + + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////////////// + +nsresult +nsChromeRegistry::GetResource(const nsACString& aURL, + nsIRDFResource** aResult) +{ + nsresult rv = NS_OK; + if (NS_FAILED(rv = mRDFService->GetResource(aURL, aResult))) { + NS_ERROR("Unable to retrieve a resource for this URL."); + *aResult = nsnull; + return rv; + } + return NS_OK; +} + +nsresult +nsChromeRegistry::FollowArc(nsIRDFDataSource *aDataSource, + nsACString& aResult, + nsIRDFResource* aChromeResource, + nsIRDFResource* aProperty) +{ + if (!aDataSource) + return NS_ERROR_FAILURE; + + nsresult rv; + + nsCOMPtr chromeBase; + rv = aDataSource->GetTarget(aChromeResource, aProperty, PR_TRUE, getter_AddRefs(chromeBase)); + if (NS_FAILED(rv)) { + NS_ERROR("Unable to obtain a base resource."); + return rv; + } + + if (chromeBase == nsnull) + return NS_ERROR_FAILURE; + + nsCOMPtr resource(do_QueryInterface(chromeBase)); + + if (resource) { + nsXPIDLCString uri; + rv = resource->GetValue(getter_Copies(uri)); + if (NS_FAILED(rv)) return rv; + aResult.Assign(uri); + return NS_OK; + } + + nsCOMPtr literal(do_QueryInterface(chromeBase)); + if (literal) { + const PRUnichar *s; + rv = literal->GetValueConst(&s); + if (NS_FAILED(rv)) return rv; + CopyUTF16toUTF8(s, aResult); + } + else { + // This should _never_ happen. + NS_ERROR("uh, this isn't a resource or a literal!"); + return NS_ERROR_UNEXPECTED; + } + + return NS_OK; +} + +nsresult +nsChromeRegistry::UpdateArc(nsIRDFDataSource *aDataSource, nsIRDFResource* aSource, + nsIRDFResource* aProperty, + nsIRDFNode *aTarget, PRBool aRemove) +{ + nsresult rv; + // Get the old targets + nsCOMPtr retVal; + rv = aDataSource->GetTarget(aSource, aProperty, PR_TRUE, getter_AddRefs(retVal)); + if (NS_FAILED(rv)) return rv; + + if (retVal) { + if (!aRemove) + aDataSource->Change(aSource, aProperty, retVal, aTarget); + else + aDataSource->Unassert(aSource, aProperty, aTarget); + } + else if (!aRemove) + aDataSource->Assert(aSource, aProperty, aTarget, PR_TRUE); + + return NS_OK; } //////////////////////////////////////////////////////////////////////// @@ -663,8 +1199,7 @@ static void FlushSkinBindingsForWindow(nsIDOMWindowInternal* aWindow) // XXXbsmedberg: move this to nsIWindowMediator NS_IMETHODIMP nsChromeRegistry::RefreshSkins() { - nsCOMPtr windowMediator - (do_GetService(NS_WINDOWMEDIATOR_CONTRACTID)); + nsCOMPtr windowMediator(do_GetService(kWindowMediatorCID)); if (!windowMediator) return NS_OK; @@ -702,13 +1237,16 @@ NS_IMETHODIMP nsChromeRegistry::RefreshSkins() } void + + + nsChromeRegistry::FlushSkinCaches() { nsCOMPtr obsSvc = do_GetService("@mozilla.org/observer-service;1"); NS_ASSERTION(obsSvc, "Couldn't get observer service."); - obsSvc->NotifyObservers(NS_STATIC_CAST(nsIChromeRegistry*, this), + obsSvc->NotifyObservers((nsIChromeRegistry*) this, NS_CHROME_FLUSH_SKINS_TOPIC, nsnull); } @@ -835,9 +1373,1057 @@ nsresult nsChromeRegistry::RefreshWindow(nsIDOMWindowInternal* aWindow) return NS_OK; } +nsresult +nsChromeRegistry::WriteInfoToDataSource(const char *aDocURI, + const PRUnichar *aOverlayURI, + PRBool aIsOverlay, + PRBool aUseProfile, + PRBool aRemove) +{ + nsresult rv; + nsCOMPtr uri; + nsCAutoString str(aDocURI); + rv = NS_NewURI(getter_AddRefs(uri), str); + if (NS_FAILED(rv)) return rv; + + if (!aRemove) { + // We are installing a dynamic overlay or package. + // We must split the doc URI and obtain our package or skin. + // We then annotate the chrome.rdf datasource in the appropriate + // install/profile dir (based off aUseProfile) with the knowledge + // that we have overlays or stylesheets. + nsCAutoString package, provider, file; + rv = SplitURL(uri, package, provider, file); + if (NS_FAILED(rv)) return NS_OK; + + // Obtain our chrome data source. + nsDependentCString dataSourceStr(kChromeFileName); + nsCOMPtr mainDataSource; + rv = LoadDataSource(dataSourceStr, getter_AddRefs(mainDataSource), aUseProfile, nsnull); + if (NS_FAILED(rv)) return rv; + + // Now that we have the appropriate chrome.rdf file, we + // must annotate the package resource with the knowledge of + // whether or not we have stylesheets or overlays. + nsCOMPtr hasDynamicDataArc; + if (aIsOverlay) + hasDynamicDataArc = mHasOverlays; + else + hasDynamicDataArc = mHasStylesheets; + + // Obtain the resource for the package. + nsCAutoString packageResourceStr("urn:mozilla:package:"); + packageResourceStr += package; + nsCOMPtr packageResource; + GetResource(packageResourceStr, getter_AddRefs(packageResource)); + + // Now add the arc to the package. + nsCOMPtr trueLiteral; + mRDFService->GetLiteral(NS_LITERAL_STRING("true").get(), getter_AddRefs(trueLiteral)); + nsChromeRegistry::UpdateArc(mainDataSource, packageResource, + hasDynamicDataArc, + trueLiteral, PR_FALSE); + } + + nsCOMPtr dataSource; + rv = GetDynamicDataSource(uri, aIsOverlay, aUseProfile, PR_TRUE, getter_AddRefs(dataSource)); + if (NS_FAILED(rv)) return rv; + + if (!dataSource) + return NS_OK; + + nsCOMPtr resource; + rv = GetResource(str, getter_AddRefs(resource)); + + if (NS_FAILED(rv)) + return NS_OK; + + nsCOMPtr container; + rv = mRDFContainerUtils->MakeSeq(dataSource, resource, getter_AddRefs(container)); + if (NS_FAILED(rv)) return rv; + if (!container) { + // Already exists. Create a container instead. + container = do_CreateInstance("@mozilla.org/rdf/container;1", &rv); + if (NS_FAILED(rv)) return rv; + rv = container->Init(dataSource, resource); + if (NS_FAILED(rv)) return rv; + } + + nsAutoString unistr(aOverlayURI); + nsCOMPtr literal; + rv = mRDFService->GetLiteral(unistr.get(), getter_AddRefs(literal)); + if (NS_FAILED(rv)) return rv; + + if (aRemove) { + rv = container->RemoveElement(literal, PR_TRUE); + if (NS_FAILED(rv)) return rv; + } + else { + PRInt32 index; + rv = container->IndexOf(literal, &index); + if (NS_FAILED(rv)) return rv; + if (index == -1) { + rv = container->AppendElement(literal); + if (NS_FAILED(rv)) return rv; + } + } + + nsCOMPtr remote = do_QueryInterface(dataSource, &rv); + if (NS_SUCCEEDED(rv)) { + rv = remote->Flush(); + } + + return rv; +} + +nsresult +nsChromeRegistry::UpdateDynamicDataSource(nsIRDFDataSource *aDataSource, + nsIRDFResource *aResource, + PRBool aIsOverlay, + PRBool aUseProfile, PRBool aRemove) +{ + nsresult rv; + + nsCOMPtr container = do_CreateInstance("@mozilla.org/rdf/container;1", &rv); + if (NS_FAILED(rv)) return rv; + + rv = container->Init(aDataSource, aResource); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr arcs; + rv = container->GetElements(getter_AddRefs(arcs)); + if (NS_FAILED(rv)) return rv; + + PRBool moreElements; + rv = arcs->HasMoreElements(&moreElements); + if (NS_FAILED(rv)) return rv; + + const char *value; + rv = aResource->GetValueConst(&value); + if (NS_FAILED(rv)) return rv; + + while (moreElements) + { + nsCOMPtr supports; + rv = arcs->GetNext(getter_AddRefs(supports)); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr literal = do_QueryInterface(supports, &rv); + + if (NS_SUCCEEDED(rv)) + { + const PRUnichar* valueStr; + rv = literal->GetValueConst(&valueStr); + if (NS_FAILED(rv)) return rv; + + rv = WriteInfoToDataSource(value, valueStr, aIsOverlay, aUseProfile, aRemove); + if (NS_FAILED(rv)) return rv; + } + rv = arcs->HasMoreElements(&moreElements); + if (NS_FAILED(rv)) return rv; + } + + return NS_OK; +} + + +nsresult +nsChromeRegistry::UpdateDynamicDataSources(nsIRDFDataSource *aDataSource, + PRBool aIsOverlay, + PRBool aUseProfile, PRBool aRemove) +{ + nsresult rv; + nsCOMPtr resource; + nsCAutoString root; + if (aIsOverlay) + root.Assign("urn:mozilla:overlays"); + else root.Assign("urn:mozilla:stylesheets"); + + rv = GetResource(root, getter_AddRefs(resource)); + + if (!resource) + return NS_OK; + + nsCOMPtr container(do_CreateInstance("@mozilla.org/rdf/container;1")); + if (!container) + return NS_OK; + + if (NS_FAILED(container->Init(aDataSource, resource))) + return NS_OK; + + nsCOMPtr arcs; + if (NS_FAILED(container->GetElements(getter_AddRefs(arcs)))) + return NS_OK; + + PRBool moreElements; + rv = arcs->HasMoreElements(&moreElements); + if (NS_FAILED(rv)) return rv; + + while (moreElements) + { + nsCOMPtr supports; + rv = arcs->GetNext(getter_AddRefs(supports)); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr resource2 = do_QueryInterface(supports, &rv); + + if (NS_SUCCEEDED(rv)) + { + rv = UpdateDynamicDataSource(aDataSource, resource2, aIsOverlay, aUseProfile, aRemove); + if (NS_FAILED(rv)) return rv; + } + + rv = arcs->HasMoreElements(&moreElements); + if (NS_FAILED(rv)) return rv; + } + + return NS_OK; +} + +nsresult +nsChromeRegistry::InstallProvider(const nsACString& aProviderType, + const nsACString& aBaseURL, + PRBool aUseProfile, PRBool aAllowScripts, + PRBool aRemove) +{ + // XXX don't allow local chrome overrides of install chrome! +#ifdef DEBUG2 + printf("*** Chrome Registration of %-7s: Checking for contents.rdf at %s\n", PromiseFlatCString(aProviderType).get(), PromiseFlatCString(aBaseURL).get()); +#endif + + // Load the data source found at the base URL. + nsresult rv; + nsCOMPtr dataSource = do_CreateInstance(kRDFXMLDataSourceCID, &rv); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr remote = do_QueryInterface(dataSource, &rv); + if (NS_FAILED(rv)) return rv; + + // We need to read this synchronously. + nsCAutoString key(aBaseURL); + key += "contents.rdf"; + remote->Init(key.get()); + remote->Refresh(PR_TRUE); + + PRBool skinCount = GetProviderCount(NS_LITERAL_CSTRING("skin"), dataSource); + PRBool localeCount = GetProviderCount(NS_LITERAL_CSTRING("locale"), dataSource); + PRBool packageCount = GetProviderCount(NS_LITERAL_CSTRING("package"), dataSource); + + PRBool appendPackage = PR_FALSE; + PRBool appendProvider = PR_FALSE; + PRBool appendProviderName = PR_FALSE; + + if (skinCount == 0 && localeCount == 0 && packageCount == 0) { + // Try the old-style manifest.rdf instead + key = aBaseURL; + key += "manifest.rdf"; + (void)remote->Init(key.get()); // ignore failure here + rv = remote->Refresh(PR_TRUE); + if (NS_FAILED(rv)) return rv; + appendPackage = PR_TRUE; + appendProvider = PR_TRUE; + NS_ERROR("Trying old-style manifest.rdf. Please update to contents.rdf."); + } + else { + if ((skinCount > 1 && aProviderType.Equals("skin")) || + (localeCount > 1 && aProviderType.Equals("locale"))) + appendProviderName = PR_TRUE; + + if (!appendProviderName && packageCount > 1) { + appendPackage = PR_TRUE; + } + + if (aProviderType.Equals("skin")) { + if (!appendProviderName && (localeCount == 1 || packageCount != 0)) + appendProvider = PR_TRUE; + } + else if (aProviderType.Equals("locale")) { + if (!appendProviderName && (skinCount == 1 || packageCount != 0)) + appendProvider = PR_TRUE; + } + else { + // Package install. + if (localeCount == 1 || skinCount == 1) + appendProvider = PR_TRUE; + } + } + + // Load the install data source that we wish to manipulate. + nsCOMPtr installSource; + rv = LoadDataSource(kChromeFileName, getter_AddRefs(installSource), aUseProfile, nsnull); + if (NS_FAILED(rv)) return rv; + NS_ASSERTION(installSource, "failed to get installSource"); + + // install our dynamic overlays + if (aProviderType.Equals("package")) + rv = UpdateDynamicDataSources(dataSource, PR_TRUE, aUseProfile, aRemove); + else if (aProviderType.Equals("skin")) + rv = UpdateDynamicDataSources(dataSource, PR_FALSE, aUseProfile, aRemove); + if (NS_FAILED(rv)) return rv; + + // Get the literal for our loc type. + nsAutoString locstr; + if (aUseProfile) + locstr.AssignLiteral("profile"); + else locstr.AssignLiteral("install"); + nsCOMPtr locLiteral; + rv = mRDFService->GetLiteral(locstr.get(), getter_AddRefs(locLiteral)); + if (NS_FAILED(rv)) return rv; + + // Get the literal for our script access. + nsCOMPtr scriptLiteral; + rv = mRDFService->GetLiteral(NS_LITERAL_STRING("false").get(), + getter_AddRefs(scriptLiteral)); + if (NS_FAILED(rv)) return rv; + + // Build the prefix string. Only resources with this prefix string will have their + // assertions copied. + nsCAutoString prefix( "urn:mozilla:" ); + prefix += aProviderType; + prefix += ":"; + + // Get all the resources + nsCOMPtr resources; + rv = dataSource->GetAllResources(getter_AddRefs(resources)); + if (NS_FAILED(rv)) return rv; + + // For each resource + PRBool moreElements; + rv = resources->HasMoreElements(&moreElements); + if (NS_FAILED(rv)) return rv; + + while (moreElements) { + nsCOMPtr supports; + rv = resources->GetNext(getter_AddRefs(supports)); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr resource = do_QueryInterface(supports); + + // Check against the prefix string + const char* value; + rv = resource->GetValueConst(&value); + if (NS_FAILED(rv)) return rv; + nsCAutoString val(value); + if (val.Find(prefix) == 0) { + // It's valid. + + if (aProviderType.Equals("package") && !val.Equals("urn:mozilla:package:root")) { + // Add arcs for the base url and loctype + // Get the value of the base literal. + nsCAutoString baseURL(aBaseURL); + + // Peel off the package. + const char* val2; + rv = resource->GetValueConst(&val2); + if (NS_FAILED(rv)) return rv; + nsCAutoString value2(val2); + PRInt32 index = value2.RFind(":"); + nsCAutoString packageName; + value2.Right(packageName, value2.Length() - index - 1); + + if (appendPackage) { + baseURL += packageName; + baseURL += "/"; + } + if (appendProvider) { + baseURL += "content/"; + } + + nsCOMPtr baseLiteral; + mRDFService->GetLiteral(NS_ConvertASCIItoUCS2(baseURL).get(), getter_AddRefs(baseLiteral)); + + rv = nsChromeRegistry::UpdateArc(installSource, resource, mBaseURL, baseLiteral, aRemove); + if (NS_FAILED(rv)) return rv; + rv = nsChromeRegistry::UpdateArc(installSource, resource, mLocType, locLiteral, aRemove); + if (NS_FAILED(rv)) return rv; + } + + nsCOMPtr container = do_CreateInstance("@mozilla.org/rdf/container;1", &rv); + if (NS_FAILED(rv)) return rv; + rv = container->Init(dataSource, resource); + if (NS_SUCCEEDED(rv)) { + // XXX Deal with BAGS and ALTs? Aww, to hell with it. Who cares? I certainly don't. + // We're a SEQ. Different rules apply. Do an AppendElement instead. + // First do the decoration in the install data source. + nsCOMPtr installContainer; + rv = mRDFContainerUtils->MakeSeq(installSource, resource, getter_AddRefs(installContainer)); + if (NS_FAILED(rv)) return rv; + if (!installContainer) { + // Already exists. Create a container instead. + installContainer = do_CreateInstance("@mozilla.org/rdf/container;1", &rv); + if (NS_FAILED(rv)) return rv; + rv = installContainer->Init(installSource, resource); + if (NS_FAILED(rv)) return rv; + } + + // Put all our elements into the install container. + nsCOMPtr seqKids; + rv = container->GetElements(getter_AddRefs(seqKids)); + if (NS_FAILED(rv)) return rv; + PRBool moreKids; + rv = seqKids->HasMoreElements(&moreKids); + if (NS_FAILED(rv)) return rv; + while (moreKids) { + nsCOMPtr supp; + rv = seqKids->GetNext(getter_AddRefs(supp)); + if (NS_FAILED(rv)) return rv; + nsCOMPtr kid = do_QueryInterface(supp); + if (aRemove) { + rv = installContainer->RemoveElement(kid, PR_TRUE); + if (NS_FAILED(rv)) return rv; + } + else { + PRInt32 index; + rv = installContainer->IndexOf(kid, &index); + if (NS_FAILED(rv)) return rv; + if (index == -1) { + rv = installContainer->AppendElement(kid); + if (NS_FAILED(rv)) return rv; + } + rv = seqKids->HasMoreElements(&moreKids); + if (NS_FAILED(rv)) return rv; + } + } + + // See if we're a packages seq in a skin/locale. If so, we need to set up the baseURL, allowScripts + // and package arcs. + if (val.Find(":packages") != -1 && !aProviderType.EqualsLiteral("package")) { + PRBool doAppendPackage = appendPackage; + PRInt32 perProviderPackageCount; + container->GetCount(&perProviderPackageCount); + if (perProviderPackageCount > 1) + doAppendPackage = PR_TRUE; + + // Iterate over our kids a second time. + nsCOMPtr seqKids2; + rv = container->GetElements(getter_AddRefs(seqKids2)); + if (NS_FAILED(rv)) return rv; + PRBool moreKids2; + rv = seqKids2->HasMoreElements(&moreKids2); + if (NS_FAILED(rv)) return rv; + while (moreKids2) { + nsCOMPtr supp; + rv = seqKids2->GetNext(getter_AddRefs(supp)); + if (NS_FAILED(rv)) return rv; + nsCOMPtr entry(do_QueryInterface(supp)); + if (entry) { + // Get the value of the base literal. + nsCAutoString baseURL(aBaseURL); + + // Peel off the package and the provider. + const char* val2; + rv = entry->GetValueConst(&val2); + if (NS_FAILED(rv)) return rv; + nsCAutoString value2(val2); + PRInt32 index = value2.RFind(":"); + nsCAutoString packageName; + value2.Right(packageName, value2.Length() - index - 1); + nsCAutoString remainder; + value2.Left(remainder, index); + + nsCAutoString providerName; + index = remainder.RFind(":"); + remainder.Right(providerName, remainder.Length() - index - 1); + + // Append them to the base literal and tack on a final slash. + if (appendProviderName) { + baseURL += providerName; + baseURL += "/"; + } + if (doAppendPackage) { + baseURL += packageName; + baseURL += "/"; + } + if (appendProvider) { + baseURL += aProviderType; + baseURL += "/"; + } + + nsCOMPtr baseLiteral; + mRDFService->GetLiteral(NS_ConvertASCIItoUCS2(baseURL).get(), getter_AddRefs(baseLiteral)); + + rv = nsChromeRegistry::UpdateArc(installSource, entry, mBaseURL, baseLiteral, aRemove); + if (NS_FAILED(rv)) return rv; + if (aProviderType.EqualsLiteral("skin") && !aAllowScripts) { + rv = nsChromeRegistry::UpdateArc(installSource, entry, mAllowScripts, scriptLiteral, aRemove); + if (NS_FAILED(rv)) return rv; + } + + // Now set up the package arc. + if (index != -1) { + // Peel off the package name. + + nsCAutoString resourceName("urn:mozilla:package:"); + resourceName += packageName; + nsCOMPtr packageResource; + rv = GetResource(resourceName, getter_AddRefs(packageResource)); + if (NS_FAILED(rv)) return rv; + if (packageResource) { + rv = nsChromeRegistry::UpdateArc(installSource, entry, mPackage, packageResource, aRemove); + if (NS_FAILED(rv)) return rv; + } + } + } + + rv = seqKids2->HasMoreElements(&moreKids2); + if (NS_FAILED(rv)) return rv; + } + } + } + else { + // We're not a seq. Get all of the arcs that go out. + nsCOMPtr arcs; + rv = dataSource->ArcLabelsOut(resource, getter_AddRefs(arcs)); + if (NS_FAILED(rv)) return rv; + + PRBool moreArcs; + rv = arcs->HasMoreElements(&moreArcs); + if (NS_FAILED(rv)) return rv; + while (moreArcs) { + nsCOMPtr supp; + rv = arcs->GetNext(getter_AddRefs(supp)); + if (NS_FAILED(rv)) return rv; + nsCOMPtr arc = do_QueryInterface(supp); + + if (arc == mPackages) { + // We are the main entry for a skin/locale. + // Set up our loctype and our script access + rv = nsChromeRegistry::UpdateArc(installSource, resource, mLocType, locLiteral, aRemove); + if (NS_FAILED(rv)) return rv; + } + + nsCOMPtr newTarget; + rv = dataSource->GetTarget(resource, arc, PR_TRUE, getter_AddRefs(newTarget)); + if (NS_FAILED(rv)) return rv; + + if (arc == mImage) { + // We are an image URL. Check to see if we're a relative URL. + nsCOMPtr literal(do_QueryInterface(newTarget)); + if (literal) { + const PRUnichar* valueStr; + literal->GetValueConst(&valueStr); + nsAutoString imageURL(valueStr); + if (imageURL.FindChar(':') == -1) { + // We're relative. Prepend the base URL of the + // package. + NS_ConvertUTF8toUCS2 fullURL(aBaseURL); + fullURL += imageURL; + mRDFService->GetLiteral(fullURL.get(), getter_AddRefs(literal)); + newTarget = do_QueryInterface(literal); + } + } + } + + rv = nsChromeRegistry::UpdateArc(installSource, resource, arc, newTarget, aRemove); + if (NS_FAILED(rv)) return rv; + + rv = arcs->HasMoreElements(&moreArcs); + if (NS_FAILED(rv)) return rv; + } + } + } + rv = resources->HasMoreElements(&moreElements); + if (NS_FAILED(rv)) return rv; + } + + // Flush the install source + nsCOMPtr remoteInstall = do_QueryInterface(installSource, &rv); + if (NS_FAILED(rv)) + return NS_OK; + + if (!mBatchInstallFlushes) + rv = remoteInstall->Flush(); + + // XXX Handle the installation of overlays. + + return rv; +} + +NS_IMETHODIMP nsChromeRegistry::SetAllowOverlaysForPackage(const PRUnichar *aPackageName, PRBool allowOverlays) +{ + nsCAutoString package("urn:mozilla:package:"); + AppendUTF16toUTF8(aPackageName, package); + + // Obtain the package resource. + nsCOMPtr packageResource; + nsresult rv = GetResource(package, getter_AddRefs(packageResource)); + if (NS_FAILED(rv)) { + NS_ERROR("Unable to obtain the package resource."); + return rv; + } + NS_ASSERTION(packageResource, "failed to get packageResource"); + + nsCOMPtr dataSource; + rv = LoadDataSource(kChromeFileName, getter_AddRefs(dataSource), PR_TRUE, nsnull); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr trueLiteral; + mRDFService->GetLiteral(NS_LITERAL_STRING("true").get(), getter_AddRefs(trueLiteral)); + nsChromeRegistry::UpdateArc(dataSource, packageResource, + mDisabled, + trueLiteral, allowOverlays); + + nsCOMPtr remote = do_QueryInterface(dataSource, &rv); + if (NS_FAILED(rv)) return rv; + + rv = remote->Flush(); + return rv; +} + +PRBool nsChromeRegistry::IsOverlayAllowed(nsIURI *aChromeURL) +{ + nsCAutoString package, provider, file; + nsresult rv = SplitURL(aChromeURL, package, provider, file); + if (NS_FAILED(rv)) return PR_FALSE; + + // Get the chrome resource for the package. + nsCAutoString rdfpackage( "urn:mozilla:package:" ); + rdfpackage.Append(package); + + // Obtain the package resource. + nsCOMPtr packageResource; + rv = GetResource(rdfpackage, getter_AddRefs(packageResource)); + if (NS_FAILED(rv) || !packageResource) { + NS_ERROR("Unable to obtain the package resource."); + return PR_FALSE; + } + + // See if the disabled arc is set for the package. + nsCAutoString disabled; + nsChromeRegistry::FollowArc(mChromeDataSource, disabled, packageResource, mDisabled); + return disabled.IsEmpty(); +} + +NS_IMETHODIMP nsChromeRegistry::InstallSkin(const char* aBaseURL, PRBool aUseProfile, PRBool aAllowScripts) +{ + return InstallProvider(NS_LITERAL_CSTRING("skin"), + nsDependentCString(aBaseURL), + aUseProfile, aAllowScripts, PR_FALSE); +} + +NS_IMETHODIMP nsChromeRegistry::InstallLocale(const char* aBaseURL, PRBool aUseProfile) +{ + return InstallProvider(NS_LITERAL_CSTRING("locale"), + nsDependentCString(aBaseURL), + aUseProfile, PR_TRUE, PR_FALSE); +} + +NS_IMETHODIMP nsChromeRegistry::InstallPackage(const char* aBaseURL, PRBool aUseProfile) +{ + return InstallProvider(NS_LITERAL_CSTRING("package"), + nsDependentCString(aBaseURL), + aUseProfile, PR_TRUE, PR_FALSE); +} + +NS_IMETHODIMP nsChromeRegistry::UninstallSkin(const nsACString& aSkinName, PRBool aUseProfile) +{ + mSelectedSkins.Clear(); + + // Now uninstall it. + return UninstallProvider(NS_LITERAL_CSTRING("skin"), aSkinName, aUseProfile); +} + +NS_IMETHODIMP nsChromeRegistry::UninstallLocale(const nsACString& aLocaleName, PRBool aUseProfile) +{ + mSelectedLocales.Clear(); + + return UninstallProvider(NS_LITERAL_CSTRING("locale"), aLocaleName, aUseProfile); +} + +static void GetURIForProvider(nsIIOService* aIOService, const nsACString& aProviderName, + const nsACString& aProviderType, nsIURI** aResult) +{ + nsCAutoString chromeURL("chrome://"); + chromeURL += aProviderName; + chromeURL += "/"; + chromeURL += aProviderType; + chromeURL += "/"; + + nsCOMPtr uri; + aIOService->NewURI(chromeURL, nsnull, nsnull, aResult); +} + +nsresult nsChromeRegistry::UninstallFromDynamicDataSource(const nsACString& aPackageName, + PRBool aIsOverlay, PRBool aUseProfile) +{ + nsresult rv; + + // Disconnect any overlay/stylesheet entries that this package may have + // supplied. This is a little tricky - the chrome registry identifies + // that packages may have dynamic overlays/stylesheets specified like so: + // - each package entry in the chrome registry datasource has a + // "chrome:hasOverlays"/"chrome:hasStylesheets" property set to "true" + // - if this property is set, the chrome registry knows to load a dynamic overlay + // datasource over in + // /chrome/overlayinfo//content/overlays.rdf + // or + // /chrome/overlayinfo//skin/stylesheets.rdf + // To remove this dynamic overlay info when we disable a package: + // - first get an enumeration of all the packages that have the + // "hasOverlays" and "hasStylesheets" properties set. + // - walk this list, loading the Dynamic Datasource (overlays.rdf/ + // stylesheets.rdf) for each package + // - enumerate the Seqs in each Dynamic Datasource + // - for each seq, remove entries that refer to chrome URLs that are supplied + // by the package we're removing. + nsCOMPtr ioServ(do_GetService(NS_IOSERVICE_CONTRACTID)); + + nsCOMPtr uninstallURI; + const nsACString& providerType = aIsOverlay ? NS_LITERAL_CSTRING("content") + : NS_LITERAL_CSTRING("skin"); + GetURIForProvider(ioServ, aPackageName, providerType, + getter_AddRefs(uninstallURI)); + if (!uninstallURI) return NS_ERROR_OUT_OF_MEMORY; + nsCAutoString uninstallHost; + uninstallURI->GetHost(uninstallHost); + + nsCOMPtr trueLiteral; + mRDFService->GetLiteral(NS_LITERAL_STRING("true").get(), getter_AddRefs(trueLiteral)); + + nsCOMPtr e; + mChromeDataSource->GetSources(aIsOverlay ? mHasOverlays : mHasStylesheets, + trueLiteral, PR_TRUE, getter_AddRefs(e)); + do { + PRBool hasMore; + e->HasMoreElements(&hasMore); + if (!hasMore) + break; + + nsCOMPtr res; + e->GetNext(getter_AddRefs(res)); + nsCOMPtr package(do_QueryInterface(res)); + + nsXPIDLCString val; + package->GetValue(getter_Copies(val)); + + val.Cut(0, NS_LITERAL_CSTRING("urn:mozilla:package:").Length()); + nsCOMPtr sourcePackageURI; + GetURIForProvider(ioServ, val, providerType, getter_AddRefs(sourcePackageURI)); + if (!sourcePackageURI) return NS_ERROR_OUT_OF_MEMORY; + + PRBool states[] = { PR_FALSE, PR_TRUE }; + for (PRInt32 i = 0; i < 2; ++i) { + nsCOMPtr overlayDS; + rv = GetDynamicDataSource(sourcePackageURI, aIsOverlay, states[i], PR_FALSE, + getter_AddRefs(overlayDS)); + if (NS_FAILED(rv) || !overlayDS) continue; + + PRBool dirty = PR_FALSE; + + // Look for all the seqs in this file + nsCOMPtr instanceOf, seq; + GetResource(NS_LITERAL_CSTRING("http://www.w3.org/1999/02/22-rdf-syntax-ns#instanceOf"), + getter_AddRefs(instanceOf)); + GetResource(NS_LITERAL_CSTRING("http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq"), + getter_AddRefs(seq)); + + nsCOMPtr seqs; + overlayDS->GetSources(instanceOf, seq, PR_TRUE, getter_AddRefs(seqs)); + + do { + PRBool hasMore; + seqs->HasMoreElements(&hasMore); + if (!hasMore) + break; + + nsCOMPtr res; + seqs->GetNext(getter_AddRefs(res)); + nsCOMPtr seq(do_QueryInterface(res)); + + nsCOMPtr container(do_CreateInstance("@mozilla.org/rdf/container;1")); + container->Init(overlayDS, seq); + + nsCOMPtr elements; + container->GetElements(getter_AddRefs(elements)); + + do { + PRBool hasMore; + elements->HasMoreElements(&hasMore); + if (!hasMore) + break; + + nsCOMPtr res; + elements->GetNext(getter_AddRefs(res)); + nsCOMPtr element(do_QueryInterface(res)); + + nsXPIDLString val; + element->GetValue(getter_Copies(val)); + + NS_ConvertUTF16toUTF8 valC(val); + nsCOMPtr targetURI; + rv = ioServ->NewURI(valC, nsnull, nsnull, getter_AddRefs(targetURI)); + if (NS_FAILED(rv)) return rv; + + nsCAutoString targetHost; + targetURI->GetHost(targetHost); + + // This overlay entry is for a package that is being uninstalled. Remove the + // entry from the overlay list. + if (targetHost.Equals(uninstallHost)) { + container->RemoveElement(element, PR_FALSE); + dirty = PR_TRUE; + } + } + while (PR_TRUE); + } + while (PR_TRUE); + + if (dirty) { + nsCOMPtr remote = do_QueryInterface(overlayDS); + rv = remote->Flush(); + } + } + } + while (PR_TRUE); + + return rv; +} + +static nsresult CleanResource(nsIRDFDataSource* aDS, nsIRDFResource* aResource) +{ + nsresult rv; + + nsCOMPtr arcs; + for (PRInt32 i = 0; i < 2; ++i) { + rv = i == 0 ? aDS->ArcLabelsOut(aResource, getter_AddRefs(arcs)) + : aDS->ArcLabelsIn(aResource, getter_AddRefs(arcs)) ; + if (NS_FAILED(rv)) return rv; + do { + PRBool hasMore; + arcs->HasMoreElements(&hasMore); + + if (!hasMore) + break; + + nsCOMPtr supp; + arcs->GetNext(getter_AddRefs(supp)); + + nsCOMPtr prop(do_QueryInterface(supp)); + nsCOMPtr target; + rv = aDS->GetTarget(aResource, prop, PR_TRUE, getter_AddRefs(target)); + if (NS_FAILED(rv)) continue; + + aDS->Unassert(aResource, prop, target); + } + while (1); + } + + return NS_OK; +} + +NS_IMETHODIMP nsChromeRegistry::UninstallPackage(const nsACString& aPackageName, PRBool aUseProfile) +{ + nsresult rv; + + // Uninstalling a package is a three step process: + // + // 1) Unhook all secondary resources + // 2) Remove the package from the package list + // 3) Remove references in the Dynamic Datasources (overlayinfo). + // + // Details: + // 1) The Chrome Registry holds information about a package like this: + // + // urn:mozilla:package:root + // --> urn:mozilla:package:newext1 + // --> c:baseURL = + // --> c:locType = "install" + // --> c:name = "newext1" + // + // urn:mozilla:skin:classic/1.0:packages + // --> urn:mozilla:skin:classic/1.0:newext1 + // --> c:baseURL = + // --> c:package = urn:mozilla:package:newext1 + // + // urn:mozilla:locale:en-US:packages + // --> urn:mozilla:locale:en-US:newext1 + // --> c:baseURL = + // --> c:package = urn:mozilla:package:newext1 + // + // We need to follow chrome:package arcs from the package resource to + // secondary resources and then clean them. This is so that a subsequent + // installation of the same package into the opposite datasource (profile + // vs. install) does not result in the chrome registry telling the necko + // to load from the wrong location by "hitting" on redundant entries in + // the opposing datasource first. + // + // 2) Then we have to clean the resource and remove it from the package list. + // 3) Then update the dynamic datasources. + // + + nsCAutoString packageResourceURI("urn:mozilla:package:"); + packageResourceURI += aPackageName; + + nsCOMPtr packageResource; + GetResource(packageResourceURI, getter_AddRefs(packageResource)); + + // Instantiate the data source we wish to modify. + nsCOMPtr installSource; + rv = LoadDataSource(kChromeFileName, getter_AddRefs(installSource), aUseProfile, nsnull); + if (NS_FAILED(rv)) return rv; + NS_ASSERTION(installSource, "failed to get installSource"); + + nsCOMPtr sources; + rv = installSource->GetSources(mPackage, packageResource, PR_TRUE, + getter_AddRefs(sources)); + if (NS_FAILED(rv)) return rv; + + do { + PRBool hasMore; + sources->HasMoreElements(&hasMore); + + if (!hasMore) + break; + + nsCOMPtr supp; + sources->GetNext(getter_AddRefs(supp)); + + nsCOMPtr res(do_QueryInterface(supp)); + rv = CleanResource(installSource, res); + if (NS_FAILED(rv)) continue; + } + while (1); + + // Clean the package resource + rv = CleanResource(installSource, packageResource); + if (NS_FAILED(rv)) return rv; + + // Remove the package from the package list + rv = UninstallProvider(NS_LITERAL_CSTRING("package"), aPackageName, aUseProfile); + if (NS_FAILED(rv)) return rv; + + rv = UninstallFromDynamicDataSource(aPackageName, PR_TRUE, aUseProfile); + if (NS_FAILED(rv)) return rv; + + return UninstallFromDynamicDataSource(aPackageName, PR_FALSE, aUseProfile); +} + +nsresult +nsChromeRegistry::UninstallProvider(const nsACString& aProviderType, + const nsACString& aProviderName, + PRBool aUseProfile) +{ + // XXX We are going to simply do a snip of the arc from the seq ROOT to + // the associated package. waterson is going to provide the ability to name + // roots in a datasource, and only resources that are reachable from the + // root will be saved. + nsresult rv = NS_OK; + nsCAutoString prefix( "urn:mozilla:" ); + prefix += aProviderType; + prefix += ":"; + + // Obtain the root. + nsCAutoString providerRoot(prefix); + providerRoot += "root"; + + // Obtain the child we wish to remove. + nsCAutoString specificChild(prefix); + specificChild += aProviderName; + + // Instantiate the data source we wish to modify. + nsCOMPtr installSource; + rv = LoadDataSource(kChromeFileName, getter_AddRefs(installSource), aUseProfile, nsnull); + if (NS_FAILED(rv)) return rv; + NS_ASSERTION(installSource, "failed to get installSource"); + + // Now make a container out of the root seq. + nsCOMPtr container(do_CreateInstance("@mozilla.org/rdf/container;1")); + + // Get the resource for the root. + nsCOMPtr chromeResource; + if (NS_FAILED(rv = GetResource(providerRoot, getter_AddRefs(chromeResource)))) { + NS_ERROR("Unable to retrieve the resource corresponding to the skin/locale root."); + return rv; + } + + if (NS_FAILED(container->Init(installSource, chromeResource))) + return NS_ERROR_FAILURE; + + // Get the resource for the child. + nsCOMPtr childResource; + if (NS_FAILED(rv = GetResource(specificChild, getter_AddRefs(childResource)))) { + NS_ERROR("Unable to retrieve the resource corresponding to the skin/locale child being removed."); + return rv; + } + + // Remove the child from the container. + container->RemoveElement(childResource, PR_TRUE); + + // Now flush the datasource. + nsCOMPtr remote = do_QueryInterface(installSource); + remote->Flush(); + + return NS_OK; +} + +nsresult +nsChromeRegistry::GetProfileRoot(nsACString& aFileURL) +{ + nsresult rv; + nsCOMPtr userChromeDir; + + // Build a fileSpec that points to the destination + // (profile dir + chrome) + rv = NS_GetSpecialDirectory(NS_APP_USER_CHROME_DIR, getter_AddRefs(userChromeDir)); + if (NS_FAILED(rv) || !userChromeDir) + return NS_ERROR_FAILURE; + + PRBool exists; + rv = userChromeDir->Exists(&exists); + if (NS_SUCCEEDED(rv) && !exists) { + rv = userChromeDir->Create(nsIFile::DIRECTORY_TYPE, 0755); + if (NS_SUCCEEDED(rv)) { + // now we need to put the userContent.css and userChrome.css + // stubs into place + + // first get the locations of the defaults + nsCOMPtr defaultUserContentFile; + nsCOMPtr defaultUserChromeFile; + rv = NS_GetSpecialDirectory(NS_APP_PROFILE_DEFAULTS_50_DIR, + getter_AddRefs(defaultUserContentFile)); + if (NS_FAILED(rv)) + rv = NS_GetSpecialDirectory(NS_APP_PROFILE_DEFAULTS_NLOC_50_DIR, + getter_AddRefs(defaultUserContentFile)); + if (NS_FAILED(rv)) + return(rv); + rv = NS_GetSpecialDirectory(NS_APP_PROFILE_DEFAULTS_50_DIR, + getter_AddRefs(defaultUserChromeFile)); + if (NS_FAILED(rv)) + rv = NS_GetSpecialDirectory(NS_APP_PROFILE_DEFAULTS_NLOC_50_DIR, + getter_AddRefs(defaultUserChromeFile)); + if (NS_FAILED(rv)) + return(rv); + defaultUserContentFile->AppendNative(NS_LITERAL_CSTRING("chrome")); + defaultUserContentFile->AppendNative(NS_LITERAL_CSTRING("userContent-example.css")); + defaultUserChromeFile->AppendNative(NS_LITERAL_CSTRING("chrome")); + defaultUserChromeFile->AppendNative(NS_LITERAL_CSTRING("userChrome-example.css")); + + const nsAFlatCString& empty = EmptyCString(); + + // copy along + // It aint an error if these files dont exist + defaultUserContentFile->CopyToNative(userChromeDir, empty); + defaultUserChromeFile->CopyToNative(userChromeDir, empty); + } + } + if (NS_FAILED(rv)) + return rv; + + return NS_GetURLSpecFromFile(userChromeDir, aFileURL); +} + +nsresult +nsChromeRegistry::GetInstallRoot(nsIFile** aFileURL) +{ + return NS_GetSpecialDirectory(NS_APP_CHROME_DIR, aFileURL); +} + void nsChromeRegistry::FlushAllCaches() { + mSelectedSkins.Clear(); + mSelectedLocales.Clear(); + nsCOMPtr obsSvc = do_GetService("@mozilla.org/observer-service;1"); NS_ASSERTION(obsSvc, "Couldn't get observer service."); @@ -855,9 +2441,8 @@ nsChromeRegistry::ReloadChrome() nsresult rv = NS_OK; // Get the window mediator - nsCOMPtr windowMediator - (do_GetService(NS_WINDOWMEDIATOR_CONTRACTID)); - if (windowMediator) { + nsCOMPtr windowMediator = do_GetService(kWindowMediatorCID, &rv); + if (NS_SUCCEEDED(rv)) { nsCOMPtr windowEnumerator; rv = windowMediator->GetEnumerator(nsnull, getter_AddRefs(windowEnumerator)); @@ -890,7 +2475,67 @@ nsChromeRegistry::ReloadChrome() } nsresult -nsChromeRegistry::LoadStyleSheetWithURL(nsIURI* aURL, nsICSSStyleSheet** aSheet) +nsChromeRegistry::GetArcs(nsIRDFDataSource* aDataSource, + const nsACString& aType, + nsISimpleEnumerator** aResult) +{ + nsresult rv; + nsCOMPtr container = do_CreateInstance("@mozilla.org/rdf/container;1", &rv); + if (NS_FAILED(rv)) + return NS_OK; + + nsCAutoString lookup("chrome:"); + lookup += aType; + + // Get the chromeResource from this lookup string + nsCOMPtr chromeResource; + if (NS_FAILED(rv = GetResource(lookup, getter_AddRefs(chromeResource)))) { + NS_ERROR("Unable to retrieve the resource corresponding to the chrome skin or content."); + return rv; + } + + if (NS_FAILED(container->Init(aDataSource, chromeResource))) + return NS_OK; + + nsCOMPtr arcs; + if (NS_FAILED(container->GetElements(getter_AddRefs(arcs)))) + return NS_OK; + + *aResult = arcs; + NS_IF_ADDREF(*aResult); + return NS_OK; +} + +nsresult +nsChromeRegistry::AddToCompositeDataSource(PRBool aUseProfile) +{ + nsresult rv = NS_OK; + if (!mChromeDataSource) { + mChromeDataSource = do_CreateInstance( + "@mozilla.org/rdf/datasource;1?name=composite-datasource", &rv); + if (NS_FAILED(rv)) + return rv; + + // Also create and hold on to our UI data source. + rv = NS_NewChromeUIDataSource(mChromeDataSource, getter_AddRefs(mUIDataSource)); + if (NS_FAILED(rv)) return rv; + } + + if (aUseProfile) { + // Profiles take precedence. Load them first. + nsCOMPtr dataSource; + LoadDataSource(kChromeFileName, getter_AddRefs(dataSource), PR_TRUE, nsnull); + mChromeDataSource->AddDataSource(dataSource); + } + + // Always load the install dir datasources + LoadDataSource(kChromeFileName, getter_AddRefs(mInstallDirChromeDataSource), PR_FALSE, nsnull); + mChromeDataSource->AddDataSource(mInstallDirChromeDataSource); + + return NS_OK; +} + +nsresult nsChromeRegistry::LoadStyleSheetWithURL(nsIURI* aURL, nsICSSStyleSheet** aSheet) { *aSheet = nsnull; @@ -900,29 +2545,103 @@ nsChromeRegistry::LoadStyleSheetWithURL(nsIURI* aURL, nsICSSStyleSheet** aSheet) return cssLoader->LoadAgentSheet(aURL, aSheet); } -NS_IMETHODIMP -nsChromeRegistry::AllowScriptsForSkin(nsIURI* aChromeURI, PRBool *aResult) +nsresult nsChromeRegistry::LoadInstallDataSource() { - nsresult rv; - *aResult = PR_FALSE; - - nsCOMPtr url (do_QueryInterface(aChromeURI)); - NS_ENSURE_TRUE(url, NS_NOINTERFACE); - - nsCAutoString provider, file; - rv = GetProviderAndPath(url, provider, file); + nsCOMPtr installRootFile; + + nsresult rv = GetInstallRoot(getter_AddRefs(installRootFile)); NS_ENSURE_SUCCESS(rv, rv); + + rv = NS_GetURLSpecFromFile(installRootFile, mInstallRoot); + NS_ENSURE_SUCCESS(rv, rv); + + mInstallInitialized = PR_TRUE; + return AddToCompositeDataSource(PR_FALSE); +} - if (!provider.EqualsLiteral("skin")) - *aResult = PR_TRUE; +nsresult nsChromeRegistry::LoadProfileDataSource() +{ + nsresult rv = GetProfileRoot(mProfileRoot); + if (NS_SUCCEEDED(rv)) { + // Load the profile search path for skins, content, and locales + // Prepend them to our list of substitutions. + mProfileInitialized = mInstallInitialized = PR_TRUE; + mChromeDataSource = nsnull; + rv = AddToCompositeDataSource(PR_TRUE); + if (NS_FAILED(rv)) return rv; + } + + nsCOMPtr pref (do_GetService(NS_PREFSERVICE_CONTRACTID)); + if (pref) { + PRBool pending; + rv = pref->GetBoolPref(DSS_SWITCH_PENDING, &pending); + if (NS_SUCCEEDED(rv) && pending) { + nsXPIDLCString skin; + rv = pref->GetCharPref(DSS_SKIN_TO_SELECT, getter_Copies(skin)); + if (NS_SUCCEEDED(rv)) { + pref->SetCharPref(SELECTED_SKIN_PREF, skin); + pref->ClearUserPref(DSS_SKIN_TO_SELECT); + pref->ClearUserPref(DSS_SWITCH_PENDING); + } + } + } return NS_OK; } -static PLDHashOperator -RemoveAll(PLDHashTable *table, PLDHashEntryHdr *entry, PRUint32 number, void *arg) +NS_IMETHODIMP nsChromeRegistry::AllowScriptsForSkin(nsIURI* aChromeURI, PRBool *aResult) { - return (PLDHashOperator) (PL_DHASH_NEXT | PL_DHASH_REMOVE); + *aResult = PR_TRUE; + + // split the url + nsCAutoString package, provider, file; + nsresult rv; + rv = SplitURL(aChromeURI, package, provider, file); + if (NS_FAILED(rv)) return NS_OK; + + // verify it's a skin url + if (!provider.Equals("skin")) + return NS_OK; + + nsCOMPtr selectedProvider; + nsCOMPtr packageResource; + + rv = FindProvider(package, provider, selectedProvider, packageResource); + if (NS_FAILED(rv)) return rv; + + // get its script access + nsCAutoString scriptAccess; + rv = nsChromeRegistry::FollowArc(mChromeDataSource, + scriptAccess, + selectedProvider, + mAllowScripts); + if (NS_FAILED(rv)) return rv; // NS_RDF_NO_VALUE is a success code, funny? + + if (!scriptAccess.IsEmpty()) + *aResult = PR_FALSE; + + 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 @@ -930,143 +2649,66 @@ nsChromeRegistry::CheckForNewChrome() { nsresult rv; - PL_DHashTableEnumerate(&mPackagesHash, RemoveAll, nsnull); - mOverlayHash.Clear(); - mStyleHash.Clear(); - - nsCOMPtr manifestURI; - rv = NS_NewURI(getter_AddRefs(manifestURI), - NS_LITERAL_CSTRING("resource:///chrome/app-chrome.manifest")); - - // this is the main manifest; if it doesn't exist we generate it from - // installed-chrome.txt. When the build system learns about the new system, - // this code can go away. - - nsCOMPtr manifestFileURL (do_QueryInterface(manifestURI)); - NS_ASSERTION(manifestFileURL, "Not a nsIFileURL!"); - - nsCOMPtr manifest; - manifestFileURL->GetFile(getter_AddRefs(manifest)); - NS_ENSURE_TRUE(manifest, NS_ERROR_FAILURE); - - PRBool exists; - rv = manifest->Exists(&exists); - NS_ENSURE_SUCCESS(rv, rv); - -#ifdef DEBUG - // In debug builds, installed-chrome.txt may change during development; - // we just rebuild it every time because we're not worried about startup - // time or other bad/goodness. - if (exists) - manifest->Remove(PR_FALSE); -#endif - - if (!exists) { - nsCOMPtr installed; - manifest->Clone(getter_AddRefs(installed)); - if (!installed) - return NS_ERROR_OUT_OF_MEMORY; - - nsCOMPtr linstalled (do_QueryInterface(installed)); - NS_ENSURE_TRUE(linstalled, NS_NOINTERFACE); - - linstalled->SetNativeLeafName(NS_LITERAL_CSTRING("installed-chrome.txt")); - - // process installed-chrome.txt into app-chrome.manifest - ProcessNewChromeFile(linstalled, manifestURI); - } - - nsCOMPtr dirSvc (do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID)); - NS_ENSURE_TRUE(dirSvc, NS_ERROR_FAILURE); - - // check the extra chrome directories - nsCOMPtr chromeML; - rv = dirSvc->Get(NS_CHROME_MANIFESTS_FILE_LIST, NS_GET_IID(nsISimpleEnumerator), - getter_AddRefs(chromeML)); + rv = LoadInstallDataSource(); if (NS_FAILED(rv)) return rv; - nsCOMPtr next; - while (NS_SUCCEEDED(chromeML->HasMoreElements(&exists)) && exists) { - chromeML->GetNext(getter_AddRefs(next)); - nsCOMPtr lmanifest = do_QueryInterface(next); - if (!lmanifest) { - NS_ERROR("Directory enumerator returned a non-nsILocalFile"); - continue; - } - - PRBool isDir; - if (NS_SUCCEEDED(lmanifest->IsDirectory(&isDir)) && isDir) { - nsCOMPtr entries; - rv = lmanifest->GetDirectoryEntries(getter_AddRefs(entries)); - if (NS_FAILED(rv)) { - NS_WARNING("Could not process chrome manifest directory."); - continue; - } - - while (NS_SUCCEEDED(entries->HasMoreElements(&exists)) && exists) { - entries->GetNext(getter_AddRefs(next)); - lmanifest = do_QueryInterface(next); - if (lmanifest) { - nsCAutoString leafName; - lmanifest->GetNativeLeafName(leafName); - if (StringEndsWith(leafName, NS_LITERAL_CSTRING(".manifest"))) { - rv = ProcessManifest(lmanifest, PR_FALSE); - if (NS_FAILED(rv)) { - NS_WARNING("Failed to process manifest."); - } - } - } - } - } - else { - rv = ProcessManifest(lmanifest, PR_FALSE); -#ifdef DEBUG - if (NS_FAILED(rv)) { - nsCString path; - lmanifest->GetNativePath(path); - path.Insert(NS_LITERAL_CSTRING("Failed to process chrome manifest: "), 0); - NS_WARNING(path.get()); - } -#endif - } - } - - rv = dirSvc->Get(NS_SKIN_MANIFESTS_FILE_LIST, NS_GET_IID(nsISimpleEnumerator), - getter_AddRefs(chromeML)); + nsCOMPtr dirSvc = + do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv); if (NS_FAILED(rv)) - return NS_OK; + return rv; - while (NS_SUCCEEDED(chromeML->HasMoreElements(&exists)) && exists) { - chromeML->GetNext(getter_AddRefs(next)); - nsCOMPtr lmanifest = do_QueryInterface(next); - if (!lmanifest) { - NS_ERROR("Directory enumerator returned a non-nsILocalFile"); - continue; - } + nsCOMPtr cacheFile, listFile; + nsInt64 cacheDate, listDate; - rv = ProcessManifest(lmanifest, PR_TRUE); -#ifdef DEBUG - if (NS_FAILED(rv)) { - nsCString path; - lmanifest->GetNativePath(path); - path.Insert(NS_LITERAL_CSTRING("Failed to process skin manifest: "), 0); - NS_WARNING(path.get()); + // 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); } -#endif } - return NS_OK; + return rv; } nsresult -nsChromeRegistry::ProcessNewChromeFile(nsILocalFile *aListFile, nsIURI* aManifest) +nsChromeRegistry::ProcessNewChromeFile(nsILocalFile *aListFile) { nsresult rv; PRFileDesc *file; rv = aListFile->OpenNSPRFileDesc(PR_RDONLY, 0, &file); - NS_ENSURE_SUCCESS(rv, rv); + if (NS_FAILED(rv)) + return rv; PRInt32 n, size; char *buf; @@ -1085,7 +2727,7 @@ nsChromeRegistry::ProcessNewChromeFile(nsILocalFile *aListFile, nsIURI* aManifes n = PR_Read(file, buf, size); if (n > 0) - rv = ProcessNewChromeBuffer(buf, size, aManifest); + rv = ProcessNewChromeBuffer(buf, size); free(buf); end: @@ -1093,9 +2735,9 @@ end: return rv; } +// flaming unthreadsafe function nsresult -nsChromeRegistry::ProcessNewChromeBuffer(char *aBuffer, PRInt32 aLength, - nsIURI* aManifest) +nsChromeRegistry::ProcessNewChromeBuffer(char *aBuffer, PRInt32 aLength) { nsresult rv = NS_OK; char *bufferEnd = aBuffer + aLength; @@ -1103,8 +2745,18 @@ nsChromeRegistry::ProcessNewChromeBuffer(char *aBuffer, PRInt32 aLength, *chromeProfile, // "install" or "profile" *chromeLocType, // type of location (local path or URL) *chromeLocation; // base location of chrome (jar file) + PRBool installModified = PR_FALSE, profileModified = PR_FALSE; - nsCOMPtr baseURI; + NS_NAMED_LITERAL_CSTRING(content, "content"); + NS_NAMED_LITERAL_CSTRING(locale, "locale"); + NS_NAMED_LITERAL_CSTRING(skin, "skin"); + NS_NAMED_LITERAL_CSTRING(profile, "profile"); + NS_NAMED_LITERAL_CSTRING(select, "select"); + NS_NAMED_LITERAL_CSTRING(path, "path"); + nsCAutoString fileURL; + nsCAutoString chromeURL; + + mBatchInstallFlushes = PR_TRUE; // process chromeType, chromeProfile, chromeLocType, chromeLocation while (aBuffer < bufferEnd) { @@ -1139,70 +2791,148 @@ nsChromeRegistry::ProcessNewChromeBuffer(char *aBuffer, PRInt32 aLength, ++aBuffer; *aBuffer = '\0'; + // process the parsed line + PRBool isSelection = select.Equals(chromeLocType); + PRBool isProfile = profile.Equals(chromeProfile); + if (isProfile) + { + if (!mProfileInitialized) + { // load profile chrome.rdf only if needed + rv = LoadProfileDataSource(); + if (NS_FAILED(rv)) + return rv; + } + profileModified = PR_TRUE; + } + else + { + installModified = PR_TRUE; + } + + if (path.Equals(chromeLocType)) { + // location is a (full) path. convert it to an URL. + + /* this is some convoluted shit... this creates a file, inits it with + * the path parsed above (chromeLocation), makes a url, and inits it + * with the file created. the purpose of this is just to have the + * canonical url of the stupid thing. + */ + nsCOMPtr chromeFile(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv)); + if (NS_FAILED(rv)) + return rv; + // assuming chromeLocation is given in the charset of the current locale + rv = chromeFile->InitWithNativePath(nsDependentCString(chromeLocation)); + if (NS_FAILED(rv)) + return rv; + + /* + * all we want here is the canonical url + */ + rv = NS_GetURLSpecFromFile(chromeFile, chromeURL); + if (NS_FAILED(rv)) return rv; + + /* if we're a file, we must be a jar file. do appropriate string munging. + * otherwise, the string we got from GetSpec is fine. + */ + PRBool isFile; + rv = chromeFile->IsFile(&isFile); + if (NS_FAILED(rv)) + return rv; + + if (isFile) { + fileURL = "jar:"; + fileURL += chromeURL; + fileURL += "!/"; + chromeURL = fileURL; + } + } + else { + // not "path". assume "url". + chromeURL = chromeLocation; + } + // process the line - // We don't do skin or locale selection from installed-chrome.txt since - // ffox 0.9. Just ignore the "select" lines. - if (strcmp(chromeLocType,"select")) { - if (!strcmp(chromeLocType, "path")) { - // location is a (full) path. convert it to an URL. - - /* this is some convoluted shit... this creates a file, inits it with - * the path parsed above (chromeLocation), makes a url, and inits it - * with the file created. the purpose of this is just to have the - * canonical url of the stupid thing. - */ - nsCOMPtr chromeFile; - rv = NS_NewNativeLocalFile(nsDependentCString(chromeLocation), - PR_TRUE, getter_AddRefs(chromeFile)); - NS_ENSURE_SUCCESS(rv, rv); - - /* - * all we want here is the canonical url - */ - rv = NS_NewFileURI(getter_AddRefs(baseURI), chromeFile); - if (NS_FAILED(rv)) return rv; - } - else { - rv = NS_NewURI(getter_AddRefs(baseURI), chromeLocation); - if (NS_FAILED(rv)) return rv; - } - - ProcessContentsManifest(baseURI, aManifest, PR_TRUE, strcmp(chromeType, "skin") == 0); + if (skin.Equals(chromeType)) { + /* We don't do selection from installed-chrome.txt any more; + just ignore "select" lines */ + if (!isSelection) + rv = InstallSkin(chromeURL.get(), isProfile, PR_FALSE); + } + else if (content.Equals(chromeType)) + rv = InstallPackage(chromeURL.get(), isProfile); + else if (locale.Equals(chromeType)) { + if (!isSelection) + rv = InstallLocale(chromeURL.get(), isProfile); } while (aBuffer < bufferEnd && (*aBuffer == '\0' || *aBuffer == ' ' || *aBuffer == '\r' || *aBuffer == '\n')) ++aBuffer; } + mBatchInstallFlushes = PR_FALSE; + + nsCOMPtr dataSource; + if (installModified) { + LoadDataSource(kChromeFileName, getter_AddRefs(dataSource), PR_FALSE, nsnull); + nsCOMPtr remote(do_QueryInterface(dataSource)); + remote->Flush(); + } + if (profileModified) { + LoadDataSource(kChromeFileName, getter_AddRefs(dataSource), PR_TRUE, nsnull); + nsCOMPtr remote(do_QueryInterface(dataSource)); + remote->Flush(); + } return NS_OK; } +PRBool +nsChromeRegistry::GetProviderCount(const nsACString& aProviderType, nsIRDFDataSource* aDataSource) +{ + nsresult rv; + + nsCAutoString rootStr("urn:mozilla:"); + rootStr += aProviderType; + rootStr += ":root"; + + // obtain the provider root resource + nsCOMPtr resource; + rv = GetResource(rootStr, getter_AddRefs(resource)); + if (NS_FAILED(rv)) + return 0; + + // wrap it in a container + nsCOMPtr container = + do_CreateInstance("@mozilla.org/rdf/container;1", &rv); + if (NS_FAILED(rv)) return 0; + + rv = container->Init(aDataSource, resource); + if (NS_FAILED(rv)) return 0; + + PRInt32 count; + container->GetCount(&count); + return count; +} + + NS_IMETHODIMP nsChromeRegistry::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *someData) { nsresult rv = NS_OK; - if (!strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic)) { - nsCOMPtr prefs (do_QueryInterface(aSubject)); - NS_ASSERTION(prefs, "Bad observer call!"); + if (!strcmp("profile-before-change", aTopic)) { - NS_ConvertUTF16toUTF8 pref(someData); + mChromeDataSource = nsnull; + mInstallInitialized = mProfileInitialized = PR_FALSE; - nsXPIDLCString provider; - rv = prefs->GetCharPref(pref.get(), getter_Copies(provider)); - if (NS_FAILED(rv)) { - NS_ERROR("Couldn't get new locale or skin pref!"); - return rv; + if (!strcmp("shutdown-cleanse", NS_ConvertUCS2toUTF8(someData).get())) { + nsCOMPtr userChromeDir; + rv = NS_GetSpecialDirectory(NS_APP_USER_CHROME_DIR, getter_AddRefs(userChromeDir)); + if (NS_SUCCEEDED(rv) && userChromeDir) + rv = userChromeDir->Remove(PR_TRUE); } - - if (pref.Equals(NS_LITERAL_CSTRING(SELECTED_SKIN_PREF))) { - mSelectedSkin = provider; - RefreshSkins(); - } - else if (pref.Equals(NS_LITERAL_CSTRING(SELECTED_LOCALE_PREF))) { - mSelectedLocale = provider; - FlushAllCaches(); - } else { - NS_ERROR("Unexpected pref!"); + } + else if (!strcmp("profile-after-change", aTopic)) { + if (!mProfileInitialized) { + rv = LoadProfileDataSource(); } } else if (!strcmp("command-line-startup", aTopic)) { @@ -1220,593 +2950,34 @@ NS_IMETHODIMP nsChromeRegistry::Observe(nsISupports *aSubject, const char *aTopi } } } + else if (!strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic)) { + nsCOMPtr prefs (do_QueryInterface(aSubject)); + NS_ASSERTION(prefs, "Bad observer call!"); + + NS_ConvertUTF16toUTF8 pref(someData); + + nsXPIDLCString provider; + rv = prefs->GetCharPref(pref.get(), getter_Copies(provider)); + if (NS_FAILED(rv)) { + NS_ERROR("Couldn't get new locale or skin pref!"); + return rv; + } + + if (pref.Equals(NS_LITERAL_CSTRING(SELECTED_SKIN_PREF))) { + mSelectedSkin = provider; + mSelectedSkins.Clear(); + RefreshSkins(); + } + else if (pref.Equals(NS_LITERAL_CSTRING(SELECTED_LOCALE_PREF))) { + mSelectedLocale = provider; + FlushAllCaches(); + } else { + NS_ERROR("Unexpected pref!"); + } + } else { NS_ERROR("Unexpected observer topic!"); } return rv; } - -static nsresult -GetContainerEnumerator(nsIRDFDataSource* ds, nsIRDFResource* res, - nsISimpleEnumerator* *aResult, PRInt32 *aCountResult = nsnull) -{ - nsresult rv; - - nsCOMPtr container - (do_CreateInstance("@mozilla.org/rdf/container;1")); - NS_ENSURE_TRUE(container, NS_ERROR_FAILURE); - - rv = container->Init(ds, res); - if (NS_FAILED(rv)) return rv; - - if (aCountResult) - container->GetCount(aCountResult); - - return container->GetElements(aResult); -} - -static void -FollowLiteral(nsIRDFDataSource* ds, nsIRDFResource* res, - nsIRDFResource* arc, nsACString& result) -{ - nsresult rv; - - nsCOMPtr node; - rv = ds->GetTarget(res, arc, PR_TRUE, getter_AddRefs(node)); - if (NS_FAILED(rv) || !node) { - result.Truncate(); - return; - } - - nsCOMPtr literal (do_QueryInterface(node)); - if (!literal) { - NS_ERROR("Arc found, but doesn't point to expected literal!"); - result.Truncate(); - return; - } - - const PRUnichar* value; - literal->GetValueConst(&value); - CopyUTF16toUTF8(value, result); -} - -static void -FollowResource(nsIRDFDataSource* ds, nsIRDFResource* res, nsIRDFResource* arc, - nsIRDFResource* *result) -{ - nsresult rv; - - nsCOMPtr node; - rv = ds->GetTarget(res, arc, PR_TRUE, getter_AddRefs(node)); - if (NS_FAILED(rv) || !node) { - *result = nsnull; - return; - } - - CallQueryInterface(node, result); -} - -static void -GetRelativePath(nsIURI* base, nsIURI* relative, nsACString& result) -{ - nsresult rv; - - nsCOMPtr jarrelative (do_QueryInterface(relative)); - if (jarrelative) { - nsCOMPtr jarbase; - jarrelative->GetJARFile(getter_AddRefs(jarbase)); - - nsCAutoString relativeBase; - GetRelativePath(base, jarbase, relativeBase); - - nsCAutoString jarEntry; - jarrelative->GetJAREntry(jarEntry); - - result.Assign(NS_LITERAL_CSTRING("jar:")); - result.Append(relativeBase); - result.Append(NS_LITERAL_CSTRING("!/")); - result.Append(jarEntry); - return; - } - - nsCOMPtr baseURL (do_QueryInterface(base)); - if (!baseURL) { - relative->GetSpec(result); - return; - } - - rv = baseURL->GetRelativeSpec(relative, result); - if (NS_FAILED(rv)) { - relative->GetSpec(result); - } -} - -static const PRInt32 kNSPR_APPEND_FLAGS = PR_WRONLY | PR_CREATE_FILE | PR_APPEND; -static const PRInt32 kNSPR_TRUNCATE_FLAGS = PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE; - -NS_IMETHODIMP -nsChromeRegistry::ProcessContentsManifest(nsIURI* aOldManifest, nsIURI* aFile, - PRBool aAppend, PRBool aSkinOnly) -{ - nsresult rv; - - nsCAutoString relativePath; - GetRelativePath(aFile, aOldManifest, relativePath); - - nsCAutoString spec; - aOldManifest->GetSpec(spec); - - NS_ASSERTION(spec.Last() == '/', "installed-chrome manifest URI doesn't end in a slash! It probably won't work."); - - spec.AppendLiteral("contents.rdf"); - - nsCOMPtr rdfs (do_GetService("@mozilla.org/rdf/rdf-service;1")); - NS_ENSURE_TRUE(rdfs, NS_ERROR_FAILURE); - - nsCOMPtr namearc, platformarc; - rdfs->GetResource(NS_LITERAL_CSTRING(kURICHROME_name), - getter_AddRefs(namearc)); - rdfs->GetResource(NS_LITERAL_CSTRING(kURICHROME_platformPackage), - getter_AddRefs(platformarc)); - if (!(namearc && platformarc)) - return NS_ERROR_FAILURE; - - nsCOMPtr ds; - rv = rdfs->GetDataSourceBlocking(spec.get(), getter_AddRefs(ds)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr fileURL (do_QueryInterface(aFile)); - NS_ENSURE_TRUE(fileURL, NS_ERROR_INVALID_ARG); - - nsCOMPtr file; - rv = fileURL->GetFile(getter_AddRefs(file)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr lfile (do_QueryInterface(file)); - NS_ENSURE_TRUE(lfile, NS_ERROR_NO_INTERFACE); - - PRFileDesc* fd; - rv = lfile->OpenNSPRFileDesc(aAppend ? kNSPR_APPEND_FLAGS : kNSPR_TRUNCATE_FLAGS, - 0664, &fd); - NS_ENSURE_SUCCESS(rv, rv); - - if (aAppend) - PR_Write(fd, "\n", 1); - - nsCOMPtr root; - rv = rdfs->GetResource(NS_LITERAL_CSTRING("urn:mozilla:skin:root"), - getter_AddRefs(root)); - if (NS_SUCCEEDED(rv)) - ProcessProvider(fd, rdfs, ds, root, PR_FALSE, relativePath); - - rv = rdfs->GetResource(NS_LITERAL_CSTRING("urn:mozilla:stylesheets"), - getter_AddRefs(root)); - if (NS_SUCCEEDED(rv)) - ProcessOverlays(fd, ds, root, NS_LITERAL_CSTRING("style")); - - if (!aSkinOnly) { - rv = rdfs->GetResource(NS_LITERAL_CSTRING("urn:mozilla:locale:root"), - getter_AddRefs(root)); - if (NS_SUCCEEDED(rv)) - ProcessProvider(fd, rdfs, ds, root, PR_TRUE, relativePath); - - rv = rdfs->GetResource(NS_LITERAL_CSTRING("urn:mozilla:overlays"), - getter_AddRefs(root)); - if (NS_SUCCEEDED(rv)) - ProcessOverlays(fd, ds, root, NS_LITERAL_CSTRING("overlay")); - - /* content packages are easier, but different */ - - rv = rdfs->GetResource(NS_LITERAL_CSTRING("urn:mozilla:package:root"), - getter_AddRefs(root)); - - nsCOMPtr packages; - if (NS_SUCCEEDED(rv)) - rv = GetContainerEnumerator(ds, root, getter_AddRefs(packages)); - - if (NS_SUCCEEDED(rv)) { - PRBool more; - nsCOMPtr next; - nsCOMPtr package; - - while (NS_SUCCEEDED(packages->HasMoreElements(&more)) && more) { - packages->GetNext(getter_AddRefs(next)); - - package = do_QueryInterface(next); - if (!package) { - NS_WARNING("Arc from urn:mozilla:package:root points to non-resource node."); - continue; - } - - nsCAutoString name; - FollowLiteral(ds, package, namearc, name); - if (name.IsEmpty()) - continue; - - nsCAutoString isPlatform; - FollowLiteral(ds, package, platformarc, isPlatform); - name.Insert(NS_LITERAL_CSTRING("content\t"), 0); - name.Append('\t'); - name.Append(relativePath); - if (!isPlatform.IsEmpty()) - name.AppendLiteral("\tplatform"); - - name.AppendLiteral(NS_LINEBREAK); - PR_Write(fd, name.get(), name.Length()); - } - } - } - - PR_Close(fd); - - return NS_OK; -} - -static void -GetResourceName(nsIRDFResource* res, nsACString& result) -{ - // we need to get the provider name. Instead of doing something sane, - // we munge the resource URI, looking from the right for colons. - - nsCAutoString providerURI; - res->GetValueUTF8(providerURI); - - PRInt32 found = providerURI.RFindChar(':'); - if (found == kNotFound) { - result.Truncate(); - return; - } - - result.Assign(Substring(providerURI, found + 1)); -} - -static NS_NAMED_LITERAL_CSTRING(kTab, "\t"); - -void -nsChromeRegistry::ProcessProvider(PRFileDesc *fd, nsIRDFService* aRDFs, - nsIRDFDataSource* aDS, nsIRDFResource* aRoot, - PRBool aIsLocale, const nsACString& aBaseURL) -{ - nsresult rv; - - nsCOMPtr packagesarc; - aRDFs->GetResource(NS_LITERAL_CSTRING(kURICHROME_packages), - getter_AddRefs(packagesarc)); - if (!packagesarc) return; - - nsCOMPtr providers; - rv = GetContainerEnumerator(aDS, aRoot, getter_AddRefs(providers)); - if (NS_FAILED(rv)) { - return; - } - - nsCOMPtr next; - - PRBool more; - while (NS_SUCCEEDED(providers->HasMoreElements(&more)) && more) { - providers->GetNext(getter_AddRefs(next)); - NS_ASSERTION(next, "GetNext failed after HasMoreElements succeeded."); - - nsCOMPtr provider (do_QueryInterface(next)); - if (!provider) { - NS_WARNING("Provider isn't a nsIRDFResource."); - continue; - } - - nsCAutoString providerName; - GetResourceName(provider, providerName); - if (providerName.IsEmpty()) { - NS_WARNING("Couldn't calculate resource name."); - continue; - } - - nsCOMPtr packages; - FollowResource(aDS, provider, packagesarc, getter_AddRefs(packages)); - if (!packages) { - NS_WARNING("No chrome:packages arc found!"); - continue; - } - - PRInt32 count; - nsCOMPtr packageList; - rv = GetContainerEnumerator(aDS, packages, getter_AddRefs(packageList), &count); - if (NS_FAILED(rv)) { - NS_WARNING("chrome:packages was not a sequence."); - continue; - } - - nsCOMPtr nextPackage; - - PRBool morePackages; - while (NS_SUCCEEDED(packageList->HasMoreElements(&morePackages)) && - morePackages) { - packageList->GetNext(getter_AddRefs(nextPackage)); - - nsCOMPtr packageRes (do_QueryInterface(nextPackage)); - if (!packageRes) { - NS_WARNING("chrome:packages Seq points to a non-resource!"); - continue; - } - - nsCAutoString packageName; - GetResourceName(packageRes, packageName); - if (packageName.IsEmpty()) { - NS_WARNING("couldn't extract a package name."); - continue; - } - - nsCAutoString line; - - if (aIsLocale) - line.AppendLiteral("locale\t"); - else - line.AppendLiteral("skin\t"); - - line += packageName + kTab + providerName + kTab + aBaseURL; - if (count > 1) { - line += packageName + kSlash; - } - line.AppendLiteral(NS_LINEBREAK); - PR_Write(fd, line.get(), line.Length()); - } - } -} - -static void -GetLiteralText(nsIRDFLiteral* lit, nsACString& result) -{ - const PRUnichar* value; - lit->GetValueConst(&value); - CopyUTF16toUTF8(value, result); -} - -static NS_NAMED_LITERAL_CSTRING(kLinebreak, NS_LINEBREAK); - -void -nsChromeRegistry::ProcessOverlays(PRFileDesc *fd, nsIRDFDataSource* aDS, - nsIRDFResource* aRoot, - const nsCSubstring& aType) -{ - nsresult rv; - - nsCOMPtr overlaids; - rv = GetContainerEnumerator(aDS, aRoot, getter_AddRefs(overlaids)); - if (NS_FAILED(rv)) { - return; - } - - nsCOMPtr next; - PRBool more; - while (NS_SUCCEEDED(overlaids->HasMoreElements(&more)) && more) { - overlaids->GetNext(getter_AddRefs(next)); - NS_ASSERTION(next, "GetNext failed after HasMoreElements succeeded."); - - nsCOMPtr overlaid (do_QueryInterface(next)); - if (!overlaid) { - NS_WARNING("Overlay arc is not a nsIRDFResource."); - continue; - } - - nsCAutoString overlaidName; - overlaid->GetValueUTF8(overlaidName); - - nsCOMPtr overlays; - rv = GetContainerEnumerator(aDS, overlaid, getter_AddRefs(overlays)); - if (NS_FAILED(rv)) - continue; - - while (NS_SUCCEEDED(overlays->HasMoreElements(&more)) && more) { - overlays->GetNext(getter_AddRefs(next)); - NS_ASSERTION(next, "GetNext failed after HasMoreElements succeeded."); - - nsCOMPtr overlay (do_QueryInterface(next)); - if (!overlay) { - NS_WARNING("Overlay was not an RDF literal."); - continue; - } - - nsCAutoString overlayName; - GetLiteralText(overlay, overlayName); - - overlayName.Insert(aType + kTab + overlaidName + kTab, 0); - overlayName.Append(kLinebreak); - PR_Write(fd, overlayName.get(), overlayName.Length()); - } - } -} - -nsresult -nsChromeRegistry::ProcessManifest(nsILocalFile* aManifest, PRBool aSkinOnly) -{ - nsresult rv; - - PRFileDesc* fd; - rv = aManifest->OpenNSPRFileDesc(PR_RDONLY, 0, &fd); - NS_ENSURE_SUCCESS(rv, rv); - - PRInt32 n, size; - char *buf; - - size = PR_Available(fd); - if (size == -1) { - rv = NS_ERROR_UNEXPECTED; - goto mend; - } - - buf = (char *) malloc(size + 1); - if (!buf) { - rv = NS_ERROR_OUT_OF_MEMORY; - goto mend; - } - - n = PR_Read(fd, buf, size); - if (n > 0) { - buf[size] = '\0'; - rv = ProcessManifestBuffer(buf, size, aManifest, aSkinOnly); - } - free(buf); - -mend: - PR_Close(fd); - return rv; -} - -static const char kWhitespace[] = "\t "; -static const char kNewlines[] = "\r\n"; - -nsresult -nsChromeRegistry::ProcessManifestBuffer(char *buf, PRInt32 length, - nsILocalFile* aManifest, - PRBool aSkinOnly) -{ - nsresult rv; - - nsCOMPtr io (do_GetIOService()); - if (!io) return NS_ERROR_FAILURE; - - nsCOMPtr manifestURI; - rv = io->NewFileURI(aManifest, getter_AddRefs(manifestURI)); - NS_ENSURE_SUCCESS(rv, rv); - - char *token; - char *newline = buf; - - // outer loop tokenizes by newline - while (nsnull != (token = nsCRT::strtok(newline, kNewlines, &newline))) { - char *whitespace = token; - token = nsCRT::strtok(whitespace, kWhitespace, &whitespace); - if (!token) continue; - - if (!strcmp(token, "content")) { - if (aSkinOnly) { - NS_WARNING("Skin manifest contained content registration. Ignoring."); - continue; - } - char *package = nsCRT::strtok(whitespace, kWhitespace, &whitespace); - char *uri = nsCRT::strtok(whitespace, kWhitespace, &whitespace); - if (!package || !uri) { - NS_WARNING("Malformed chrome manifest, content entry."); - continue; - } - PRBool platform = PR_FALSE; - while (nsnull != (token = nsCRT::strtok(whitespace, kWhitespace, &whitespace))) { - if (!strcmp(token, "platform")) - platform = PR_TRUE; - } - - nsCOMPtr resolved; - rv = io->NewURI(nsDependentCString(uri), nsnull, manifestURI, - getter_AddRefs(resolved)); - if (NS_FAILED(rv)) - continue; - - PackageEntry* entry = - NS_STATIC_CAST(PackageEntry*, PL_DHashTableOperate(&mPackagesHash, - & (const nsACString&) nsDependentCString(package), - PL_DHASH_ADD)); - if (!entry) - return NS_ERROR_OUT_OF_MEMORY; - - entry->baseURI = resolved; - - if (platform) - entry->flags |= PackageEntry::PLATFORM_PACKAGE; - } - else if (!strcmp(token, "locale")) { - if (aSkinOnly) { - NS_WARNING("Skin manifest contained locale registration. Ignoring."); - continue; - } - char *package = nsCRT::strtok(whitespace, kWhitespace, &whitespace); - char *provider = nsCRT::strtok(whitespace, kWhitespace, &whitespace); - char *uri = nsCRT::strtok(whitespace, kWhitespace, &whitespace); - if (!package || !provider || !uri) { - NS_WARNING("Malformed chrome manifest, locale entry."); - continue; - } - - nsCOMPtr resolved; - rv = io->NewURI(nsDependentCString(uri), nsnull, manifestURI, - getter_AddRefs(resolved)); - if (NS_FAILED(rv)) - continue; - - PackageEntry* entry = - NS_STATIC_CAST(PackageEntry*, PL_DHashTableOperate(&mPackagesHash, - & (const nsACString&) nsDependentCString(package), - PL_DHASH_ADD)); - if (!entry) - return NS_ERROR_OUT_OF_MEMORY; - - entry->locales.SetBase(nsDependentCString(provider), resolved); - } - else if (!strcmp(token, "skin")) { - char *package = nsCRT::strtok(whitespace, kWhitespace, &whitespace); - char *provider = nsCRT::strtok(whitespace, kWhitespace, &whitespace); - char *uri = nsCRT::strtok(whitespace, kWhitespace, &whitespace); - if (!package || !provider || !uri) { - NS_WARNING("Malformed chrome manifest, locale entry."); - continue; - } - - nsCOMPtr resolved; - rv = io->NewURI(nsDependentCString(uri), nsnull, manifestURI, - getter_AddRefs(resolved)); - if (NS_FAILED(rv)) - continue; - - PackageEntry* entry = - NS_STATIC_CAST(PackageEntry*, PL_DHashTableOperate(&mPackagesHash, - & (const nsACString&) nsDependentCString(package), - PL_DHASH_ADD)); - if (!entry) - return NS_ERROR_OUT_OF_MEMORY; - - entry->skins.SetBase(nsDependentCString(provider), resolved); - } - else if (!strcmp(token, "overlay")) { - if (aSkinOnly) { - NS_WARNING("Skin manifest contained overlay registration. Ignoring."); - continue; - } - char *base = nsCRT::strtok(whitespace, kWhitespace, &whitespace); - char *overlay = nsCRT::strtok(whitespace, kWhitespace, &whitespace); - if (!base || !overlay) - continue; - - nsCOMPtr baseuri, overlayuri; - rv = io->NewURI(nsDependentCString(base), nsnull, nsnull, - getter_AddRefs(baseuri)); - rv |= io->NewURI(nsDependentCString(overlay), nsnull, nsnull, - getter_AddRefs(overlayuri)); - if (NS_FAILED(rv)) { - NS_WARNING("Could not make URIs for overlay directive. Ignoring."); - continue; - } - - mOverlayHash.Add(baseuri, overlayuri); - } - else if (!strcmp(token, "style")) { - char *base = nsCRT::strtok(whitespace, kWhitespace, &whitespace); - char *overlay = nsCRT::strtok(whitespace, kWhitespace, &whitespace); - if (!base || !overlay) - continue; - - nsCOMPtr baseuri, overlayuri; - rv = io->NewURI(nsDependentCString(base), nsnull, nsnull, - getter_AddRefs(baseuri)); - rv |= io->NewURI(nsDependentCString(overlay), nsnull, nsnull, - getter_AddRefs(overlayuri)); - if (NS_FAILED(rv)) - continue; - - mStyleHash.Add(baseuri, overlayuri); - } - else { - NS_WARNING("Unrecognized chrome manifest instruction ignored."); - } - } - - return NS_OK; -} diff --git a/mozilla/chrome/src/nsChromeRegistry.h b/mozilla/chrome/src/nsChromeRegistry.h index 10bb4f4699a..e5445583d4f 100644 --- a/mozilla/chrome/src/nsChromeRegistry.h +++ b/mozilla/chrome/src/nsChromeRegistry.h @@ -21,7 +21,6 @@ * * Contributor(s): * Original Author: David W. Hyatt (hyatt@netscape.com) - * Benjamin Smedberg * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -37,36 +36,37 @@ * * ***** END LICENSE BLOCK ***** */ -#include "nsIChromeRegistry.h" -#include "nsIToolkitChromeRegistry.h" -#include "nsIXULOverlayProvider.h" -#include "nsIObserver.h" -#include "nsWeakReference.h" - -#include "pldhash.h" - -#include "nsCOMArray.h" -#include "nsString.h" -#include "nsTHashtable.h" -#include "nsURIHashKey.h" -#include "nsVoidArray.h" - -struct PRFileDesc; class nsIAtom; class nsICSSStyleSheet; -class nsIDOMWindowInternal; -class nsILocalFile; +class nsIRDFService; class nsIRDFDataSource; class nsIRDFResource; -class nsIRDFService; -class nsIURL; +class nsIRDFNode; +class nsISimpleEnumerator; +class nsSupportsHashtable; +class nsIRDFContainer; +class nsIRDFContainerUtils; +class nsIDOMWindowInternal; +class nsIDocument; +class nsILocalFile; +class nsIProperties; +#include "nsIChromeRegistry.h" +#include "nsIXULOverlayProvider.h" +#include "nsIRDFCompositeDataSource.h" +#include "nsIObserver.h" +#include "nsWeakReference.h" +#include "nsString.h" +#include "nsIZipReader.h" +#include "nsCOMArray.h" +#include "nsInterfaceHashtable.h" + // for component registration // {47049e42-1d87-482a-984d-56ae185e367a} #define NS_CHROMEREGISTRY_CID \ { 0x47049e42, 0x1d87, 0x482a, { 0x98, 0x4d, 0x56, 0xae, 0x18, 0x5e, 0x36, 0x7a } } -class nsChromeRegistry : public nsIToolkitChromeRegistry, +class nsChromeRegistry : public nsIXULChromeRegistry, public nsIXULOverlayProvider, public nsIObserver, public nsSupportsWeakReference @@ -77,22 +77,48 @@ public: // nsIChromeRegistry methods: NS_DECL_NSICHROMEREGISTRY NS_DECL_NSIXULCHROMEREGISTRY - NS_DECL_NSITOOLKITCHROMEREGISTRY NS_DECL_NSIXULOVERLAYPROVIDER NS_DECL_NSIOBSERVER // nsChromeRegistry methods: - nsChromeRegistry() { } - ~nsChromeRegistry(); + nsChromeRegistry(); + virtual ~nsChromeRegistry(); nsresult Init(); - static nsresult Canonify(nsIURL* aChromeURL); + +public: + static nsresult FollowArc(nsIRDFDataSource *aDataSource, + nsACString& aResult, + nsIRDFResource* aChromeResource, + nsIRDFResource* aProperty); + + static nsresult UpdateArc(nsIRDFDataSource *aDataSource, nsIRDFResource* aSource, nsIRDFResource* aProperty, + nsIRDFNode *aTarget, PRBool aRemove); protected: + nsresult GetDynamicDataSource(nsIURI *aChromeURL, PRBool aIsOverlay, PRBool aUseProfile, PRBool aCreateDS, nsIRDFDataSource **aResult); + nsresult GetURIList(nsIRDFDataSource *aDS, nsIRDFResource *aResource, nsCOMArray& aArray); nsresult GetDynamicInfo(nsIURI *aChromeURL, PRBool aIsOverlay, nsISimpleEnumerator **aResult); - static nsresult LoadStyleSheetWithURL(nsIURI* aURL, nsICSSStyleSheet** aSheet); + PRBool IsOverlayAllowed(nsIURI *aChromeURI); + + nsresult GetResource(const nsACString& aChromeType, nsIRDFResource** aResult); + + nsresult UpdateDynamicDataSource(nsIRDFDataSource *aDataSource, + nsIRDFResource *aResource, + PRBool aIsOverlay, PRBool + aUseProfile, PRBool aRemove); + nsresult UpdateDynamicDataSources(nsIRDFDataSource *aDataSource, + PRBool aIsOverlay, + PRBool aUseProfile, PRBool + aRemove); + nsresult WriteInfoToDataSource(const char *aDocURI, + const PRUnichar *aOverlayURI, + PRBool aIsOverlay, PRBool + aUseProfile, PRBool aRemove); + + nsresult LoadStyleSheetWithURL(nsIURI* aURL, nsICSSStyleSheet** aSheet); nsresult LoadInstallDataSource(); nsresult LoadProfileDataSource(); @@ -101,130 +127,89 @@ protected: void FlushAllCaches(); private: - static nsresult RefreshWindow(nsIDOMWindowInternal* aWindow); - static nsresult GetProviderAndPath(nsIURL* aChromeURL, - nsACString& aProvider, nsACString& aPath); + nsresult LoadDataSource(const nsACString &aFileName, + nsIRDFDataSource **aResult, + PRBool aUseProfileDirOnly = PR_FALSE, + const char *aProfilePath = nsnull); - NS_HIDDEN_(void) ProcessProvider(PRFileDesc *fd, nsIRDFService* aRDFs, - nsIRDFDataSource* ds, nsIRDFResource* aRoot, - PRBool aIsLocale, const nsACString& aBaseURL); - NS_HIDDEN_(void) ProcessOverlays(PRFileDesc *fd, nsIRDFDataSource* ds, - nsIRDFResource* aRoot, - const nsCSubstring& aType); + static nsresult GetProfileRoot(nsACString& aFileURL); + static nsresult GetInstallRoot(nsIFile** aFileURL); - NS_HIDDEN_(nsresult) ProcessManifest(nsILocalFile* aManifest, PRBool aSkinOnly); - NS_HIDDEN_(nsresult) ProcessManifestBuffer(char *aBuffer, PRInt32 aLength, nsILocalFile* aManifest, PRBool aSkinOnly); - NS_HIDDEN_(nsresult) ProcessNewChromeFile(nsILocalFile *aListFile, nsIURI* aManifest); - NS_HIDDEN_(nsresult) ProcessNewChromeBuffer(char *aBuffer, PRInt32 aLength, nsIURI* aManifest); + nsresult RefreshWindow(nsIDOMWindowInternal* aWindow); -public: - struct ProviderEntry - { - ProviderEntry(const nsACString& aProvider, nsIURI* aBase) : - provider(aProvider), - baseURI(aBase) { } + nsresult GetArcs(nsIRDFDataSource* aDataSource, + const nsACString& aType, + nsISimpleEnumerator** aResult); - nsCString provider; - nsCOMPtr baseURI; - }; + nsresult AddToCompositeDataSource(PRBool aUseProfile); + + nsresult GetBaseURL(const nsACString& aPackage, + const nsACString& aProvider, + nsACString& aBaseURL); - class nsProviderArray - { - public: - nsProviderArray() : - mArray(1) { } - ~nsProviderArray() - { Clear(); } + nsresult FindProvider(const nsACString& aPackage, + const nsACString& aProvider, + nsCOMPtr &aProviderResource, + nsCOMPtr &aPackageResource); - // When looking up locales and skins, the "selected" locale is not always - // available. This enum identifies what kind of match is desired/found. - enum MatchType { - EXACT = 0, - LOCALE = 1, // "en-GB" is selected, we found "en-US" - SKIN = 2 - }; + nsresult TrySubProvider(const nsACString& aPackage, + nsIRDFResource* aProviderResource, + nsCOMPtr &aSelectedProvider); - ProviderEntry* GetProvider(const nsACString& aPreferred, MatchType aType); - nsIURI* GetBase(const nsACString& aPreferred, MatchType aType); - const nsACString& GetSelected(const nsACString& aPreferred, MatchType aType); - void SetBase(const nsACString& aPreferred, nsIURI* base); - void Clear(); + nsresult FindSubProvider(const nsACString& aPackage, + const nsACString& aProvider, + nsCOMPtr &aSelectedProvider); - private: - nsVoidArray mArray; - }; + nsresult InstallProvider(const nsACString& aProviderType, + const nsACString& aBaseURL, + PRBool aUseProfile, PRBool aAllowScripts, PRBool aRemove); + nsresult UninstallProvider(const nsACString& aProviderType, const nsACString& aProviderName, PRBool aUseProfile); + nsresult UninstallFromDynamicDataSource(const nsACString& aPackageName, + PRBool aIsOverlay, PRBool aUseProfile); - struct PackageEntry : public PLDHashEntryHdr - { - PackageEntry(const nsACString& package); - ~PackageEntry() { } + NS_HIDDEN_(nsresult) ProcessNewChromeFile(nsILocalFile *aListFile); + NS_HIDDEN_(nsresult) ProcessNewChromeBuffer(char *aBuffer, PRInt32 aLength); - // Available flags - enum { - // This is a "platform" package (e.g. chrome://global-platform/). - // Appends one of win/ unix/ mac/ to the base URI. - PLATFORM_PACKAGE = 1 << 0 - }; + PRBool GetProviderCount(const nsACString& aProviderType, nsIRDFDataSource* aDataSource); - nsCString package; - nsCOMPtr baseURI; - PRUint32 flags; - nsProviderArray locales; - nsProviderArray skins; - }; +protected: + nsCString mProfileRoot; + nsCString mInstallRoot; -private: - static const void* GetKey(PLDHashTable *table, PLDHashEntryHdr *entry); - static PLDHashNumber HashKey(PLDHashTable *table, const void *key); - static PRBool MatchKey(PLDHashTable *table, const PLDHashEntryHdr *entry, - const void *key); - static void ClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry); - static PRBool InitEntry(PLDHashTable *table, PLDHashEntryHdr *entry, - const void *key); + nsCOMPtr mChromeDataSource; + nsCOMPtr mInstallDirChromeDataSource; + nsCOMPtr mUIDataSource; - static const PLDHashTableOps kTableOps; - -public: - class OverlayListEntry : public nsURIHashKey - { - public: - typedef nsURIHashKey::KeyType KeyType; - typedef nsURIHashKey::KeyTypePointer KeyTypePointer; - - OverlayListEntry(KeyTypePointer aKey) : nsURIHashKey(aKey) { } - OverlayListEntry(OverlayListEntry& toCopy) : nsURIHashKey(toCopy), - mArray(toCopy.mArray) { } - ~OverlayListEntry() { } - - void AddURI(nsIURI* aURI); - - nsCOMArray mArray; - }; - - class OverlayListHash - { - public: - OverlayListHash() { } - ~OverlayListHash() { } - - PRBool Init() { return mTable.Init(); } - void Add(nsIURI* aBase, nsIURI* aOverlay); - void Clear() { mTable.Clear(); } - const nsCOMArray* GetArray(nsIURI* aBase); - - private: - nsTHashtable mTable; - }; - -private: - // Hash of package names ("global") to PackageEntry objects - PLDHashTable mPackagesHash; - - // Hashes on the file to be overlaid (chrome://browser/content/browser.xul) - // to a list of overlays/stylesheets - OverlayListHash mOverlayHash; - OverlayListHash mStyleHash; + nsSupportsHashtable* mDataSourceTable; + nsIRDFService* mRDFService; + nsIRDFContainerUtils* mRDFContainerUtils; nsCString mSelectedLocale; nsCString mSelectedSkin; + + nsInterfaceHashtable mSelectedLocales; + nsInterfaceHashtable mSelectedSkins; + + // Resources + nsCOMPtr mBaseURL; + nsCOMPtr mPackages; + nsCOMPtr mPackage; + nsCOMPtr mName; + nsCOMPtr mImage; + nsCOMPtr mLocType; + nsCOMPtr mAllowScripts; + nsCOMPtr mHasOverlays; + nsCOMPtr mHasStylesheets; + nsCOMPtr mDisabled; + nsCOMPtr mPlatformPackage; + + // useful atoms - these are static atoms, so don't use nsCOMPtr + static nsIAtom* sCPrefix; // "c" + + PRPackedBool mInstallInitialized; + PRPackedBool mProfileInitialized; + + // Boolean that indicates we should batch flushes of the main + // chrome.rdf file. + PRPackedBool mBatchInstallFlushes; }; diff --git a/mozilla/content/base/public/nsIChromeRegistry.idl b/mozilla/content/base/public/nsIChromeRegistry.idl index 66f8cf6d034..fcf6c248845 100755 --- a/mozilla/content/base/public/nsIChromeRegistry.idl +++ b/mozilla/content/base/public/nsIChromeRegistry.idl @@ -40,7 +40,6 @@ * ***** END LICENSE BLOCK ***** */ #include "nsISupports.idl" - interface nsIURI; [scriptable, uuid(68389281-f6d0-4533-841d-344a2018140c)] @@ -51,8 +50,9 @@ interface nsIChromeRegistry : nsISupports const PRInt32 FULL = 2; /** - * Resolve a chrome URL to an loadable URI using the information in the - * registry. Does not modify aChromeURL. + * Convert a chrome URL into a canonical representation; specifically, + * + * chrome://package/provider/file * * Chrome URLs are allowed to be specified in "shorthand", leaving the * "file" portion off. In that case, the URL is expanded to: @@ -65,9 +65,17 @@ interface nsIChromeRegistry : nsISupports * "css" for a "skin" package, and * "dtd" for a "locale" package. * + * @param aChromeURL the URL that is to be canonified. + */ + void canonify(in nsIURI aChromeURL); + + /** + * Convert a chrome URL to a "real" using the information in the registry. + * Does not modify aChromeURL. + * * @param aChromeURL the URL that is to be converted. */ - nsIURI convertChromeURL(in nsIURI aChromeURL); + AUTF8String convertChromeURL(in nsIURI aChromeURL); /** * refresh the chrome list at runtime, looking for new packages/etc @@ -75,7 +83,7 @@ interface nsIChromeRegistry : nsISupports void checkForNewChrome(); }; -[scriptable, uuid(3e51f40b-b4b0-4e60-ac45-6c63477ebe41)] +[scriptable, uuid(a1208469-47cf-4776-9062-f8b431afb6fa)] interface nsIXULChromeRegistry : nsIChromeRegistry { /* Should be called when locales change to reload all chrome (including XUL). */ @@ -87,6 +95,24 @@ interface nsIXULChromeRegistry : nsIChromeRegistry void refreshSkins(); boolean allowScriptsForSkin(in nsIURI url); + + /* Whether or not an addon package can dynamically overlay another package. + You can use these APIs to effectively disable a chrome add-on without + uninstalling it. */ + void setAllowOverlaysForPackage(in wstring packageName, in boolean allowOverlays); + + /* Installation APIs */ + void installSkin(in string baseURL, + in boolean useProfile, + in boolean allowScripts); + + void uninstallSkin(in ACString skinName, in boolean useProfile); + + void installLocale(in string baseURL, in boolean useProfile); + void uninstallLocale(in ACString localeName, in boolean useProfile); + + void installPackage(in string baseURL, in boolean useProfile); + void uninstallPackage(in ACString packageName, in boolean useProfile); }; %{ C++ diff --git a/mozilla/content/xbl/public/nsIBindingManager.h b/mozilla/content/xbl/public/nsIBindingManager.h index 91fdb739bda..25102ccb8eb 100644 --- a/mozilla/content/xbl/public/nsIBindingManager.h +++ b/mozilla/content/xbl/public/nsIBindingManager.h @@ -48,7 +48,6 @@ #include "nsISupports.h" class nsIContent; -class nsIDocument; class nsIXBLBinding; class nsIXBLDocumentInfo; class nsIAtom; diff --git a/mozilla/content/xbl/src/nsXBLDocumentInfo.cpp b/mozilla/content/xbl/src/nsXBLDocumentInfo.cpp index 46a182b8d75..e29e2c0f4a8 100644 --- a/mozilla/content/xbl/src/nsXBLDocumentInfo.cpp +++ b/mozilla/content/xbl/src/nsXBLDocumentInfo.cpp @@ -329,11 +329,13 @@ nsXBLDocGlobalObject::GetPrincipal() return document->GetPrincipal(); } -static PRBool IsChromeURI(nsIURI* aURI) +static PRBool IsChromeOrResourceURI(nsIURI* aURI) { PRBool isChrome = PR_FALSE; - if (NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome))) - return isChrome; + PRBool isResource = PR_FALSE; + if (NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)) && + NS_SUCCEEDED(aURI->SchemeIs("resource", &isResource))) + return (isChrome || isResource); return PR_FALSE; } @@ -346,7 +348,7 @@ nsXBLDocumentInfo::nsXBLDocumentInfo(nsIDocument* aDocument) mBindingTable(nsnull) { nsIURI* uri = aDocument->GetDocumentURI(); - if (IsChromeURI(uri)) { + if (IsChromeOrResourceURI(uri)) { // Cache whether or not this chrome XBL can execute scripts. nsCOMPtr reg(do_GetService(NS_CHROMEREGISTRY_CONTRACTID)); if (reg) { diff --git a/mozilla/embedding/lite/Makefile.in b/mozilla/embedding/lite/Makefile.in index 1c8b4b728ac..914723f3bff 100644 --- a/mozilla/embedding/lite/Makefile.in +++ b/mozilla/embedding/lite/Makefile.in @@ -57,12 +57,11 @@ REQUIRES = xpcom \ $(NULL) CPPSRCS = \ + nsEmbedChromeRegistry.cpp \ nsEmbedGlobalHistory.cpp \ nsEmbedLiteModule.cpp \ $(NULL) -# nsEmbedChromeRegistry.cpp \ - # bring in the chrome protocol handler # LOBJS = $(topsrcdir)/rdf/chrome/src/nsChromeProtocolHandler.$(OBJ_SUFFIX) diff --git a/mozilla/mail/installer/windows/basemail-win b/mozilla/mail/installer/windows/basemail-win index 22f9c1fec6f..d6c8d941209 100644 --- a/mozilla/mail/installer/windows/basemail-win +++ b/mozilla/mail/installer/windows/basemail-win @@ -215,7 +215,6 @@ bin\components\toolkitprofile.xpt ; toolkit bin\components\appstartup.xpt bin\components\commandlines.xpt -bin\components\chrome.xpt ; rdf bin\components\rdf.xpt diff --git a/mozilla/netwerk/base/public/nsURIHashKey.h b/mozilla/netwerk/base/public/nsURIHashKey.h index 4f54c04730c..472b46ec3dc 100644 --- a/mozilla/netwerk/base/public/nsURIHashKey.h +++ b/mozilla/netwerk/base/public/nsURIHashKey.h @@ -39,7 +39,6 @@ #include "pldhash.h" #include "nsCOMPtr.h" #include "nsCRT.h" -#include "nsIURI.h" /** * Hashtable key class to use with nsTHashtable/nsBaseHashtable diff --git a/mozilla/rdf/chrome/public/nsIChromeRegistrySea.idl b/mozilla/rdf/chrome/public/nsIChromeRegistrySea.idl index d6a88d6b8d0..0d26e48dcf1 100644 --- a/mozilla/rdf/chrome/public/nsIChromeRegistrySea.idl +++ b/mozilla/rdf/chrome/public/nsIChromeRegistrySea.idl @@ -42,7 +42,7 @@ #include "nsISupports.idl" #include "nsIChromeRegistry.idl" -[scriptable, uuid(382370d0-a7cd-47ae-aa4e-af74f5edf652)] +[scriptable, uuid(ed47f6b3-8b7e-4dba-8cbd-d0560274ba4a)] interface nsIChromeRegistrySea : nsIXULChromeRegistry { /* Applies a skin or locale to all possible packages */ @@ -89,22 +89,4 @@ interface nsIChromeRegistrySea : nsIXULChromeRegistry in boolean useProfile); ACString getSelectedSkin(in ACString packageName); - - /* Installation APIs */ - void installSkin(in string baseURL, - in boolean useProfile, - in boolean allowScripts); - - void uninstallSkin(in ACString skinName, in boolean useProfile); - - void installLocale(in string baseURL, in boolean useProfile); - void uninstallLocale(in ACString localeName, in boolean useProfile); - - void installPackage(in string baseURL, in boolean useProfile); - void uninstallPackage(in ACString packageName, in boolean useProfile); - - /* Whether or not an addon package can dynamically overlay another package. - You can use these APIs to effectively disable a chrome add-on without - uninstalling it. */ - void setAllowOverlaysForPackage(in wstring packageName, in boolean allowOverlays); }; diff --git a/mozilla/rdf/chrome/src/nsChromeProtocolHandler.cpp b/mozilla/rdf/chrome/src/nsChromeProtocolHandler.cpp index a143c6dad7c..20d676f9b17 100644 --- a/mozilla/rdf/chrome/src/nsChromeProtocolHandler.cpp +++ b/mozilla/rdf/chrome/src/nsChromeProtocolHandler.cpp @@ -42,7 +42,6 @@ */ #include "nsChromeProtocolHandler.h" -#include "nsChromeRegistry.h" #include "nsCOMPtr.h" #include "nsContentCID.h" #include "nsCRT.h" @@ -69,7 +68,6 @@ #include "nsIXULPrototypeDocument.h" #endif #include "nsNetCID.h" -#include "nsNetUtil.h" #include "nsXPIDLString.h" #include "nsString.h" #include "prlog.h" @@ -596,7 +594,21 @@ nsChromeProtocolHandler::NewURI(const nsACString &aSpec, // Canonify the "chrome:" URL; e.g., so that we collapse // "chrome://navigator/content/" and "chrome://navigator/content" // and "chrome://navigator/content/navigator.xul". - rv = nsChromeRegistry::Canonify(uri); + + // Try the global cache first. + nsCOMPtr reg = gChromeRegistry; + + // If that fails, the service has not been instantiated yet; let's + // do that now. + if (!reg) { + reg = do_GetService(NS_CHROMEREGISTRY_CONTRACTID, &rv); + if (NS_FAILED(rv)) + return rv; + } + + NS_ASSERTION(reg, "Must have a chrome registry by now"); + + rv = reg->Canonify(uri); if (NS_FAILED(rv)) return rv; @@ -620,7 +632,7 @@ nsChromeProtocolHandler::NewChannel(nsIURI* aURI, nsCOMPtr debugClone; debug_rv = aURI->Clone(getter_AddRefs(debugClone)); if (NS_SUCCEEDED(debug_rv)) { - debug_rv = nsChromeRegistry::Canonify(debugClone); + debug_rv = debugReg->Canonify(debugClone); if (NS_SUCCEEDED(debug_rv)) { PRBool same; debug_rv = aURI->Equals(debugClone, &same); @@ -683,12 +695,16 @@ nsChromeProtocolHandler::NewChannel(nsIURI* aURI, if (NS_FAILED(rv)) return rv; } - nsCOMPtr chromeURI; - rv = reg->ConvertChromeURL(aURI, getter_AddRefs(chromeURI)); + nsCAutoString spec; + rv = reg->ConvertChromeURL(aURI, spec); if (NS_FAILED(rv)) return rv; - nsCOMPtr ioServ (do_GetIOService()); - if (!ioServ) return NS_ERROR_FAILURE; + nsCOMPtr ioServ(do_GetService(kIOServiceCID, &rv)); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr chromeURI; + rv = ioServ->NewURI(spec, nsnull, nsnull, getter_AddRefs(chromeURI)); + if (NS_FAILED(rv)) return rv; rv = ioServ->NewChannelFromURI(chromeURI, getter_AddRefs(result)); if (NS_FAILED(rv)) return rv; diff --git a/mozilla/rdf/chrome/src/nsChromeRegistry.cpp b/mozilla/rdf/chrome/src/nsChromeRegistry.cpp index 540280c3184..de6085faf59 100644 --- a/mozilla/rdf/chrome/src/nsChromeRegistry.cpp +++ b/mozilla/rdf/chrome/src/nsChromeRegistry.cpp @@ -440,7 +440,7 @@ GetBaseURLFile(const nsACString& aBaseURL, nsIFile** aFile) return NS_ERROR_FAILURE; } -nsresult +NS_IMETHODIMP nsChromeRegistry::Canonify(nsIURI* aChromeURI) { // Canonicalize 'chrome:' URLs. We'll take any 'chrome:' URL @@ -471,10 +471,12 @@ nsChromeRegistry::Canonify(nsIURI* aChromeURI) } NS_IMETHODIMP -nsChromeRegistry::ConvertChromeURL(nsIURI* aChromeURL, nsIURI* *aResult) +nsChromeRegistry::ConvertChromeURL(nsIURI* aChromeURL, nsACString& aResult) { nsresult rv = NS_OK; - NS_ENSURE_ARG_POINTER(aChromeURL); + NS_ASSERTION(aChromeURL, "null url!"); + if (!aChromeURL) + return NS_ERROR_NULL_POINTER; // No need to canonify as the SplitURL() that we // do is the equivalent of canonification without modifying @@ -539,9 +541,9 @@ nsChromeRegistry::ConvertChromeURL(nsIURI* aChromeURL, nsIURI* *aResult) } } - finalURL.Append(remaining); + aResult = finalURL + remaining; - return NS_NewURI(aResult, finalURL); + return NS_OK; } nsresult diff --git a/mozilla/rdf/chrome/src/nsChromeRegistry.h b/mozilla/rdf/chrome/src/nsChromeRegistry.h index b27bf6e6a97..b127147015a 100644 --- a/mozilla/rdf/chrome/src/nsChromeRegistry.h +++ b/mozilla/rdf/chrome/src/nsChromeRegistry.h @@ -86,9 +86,6 @@ public: nsresult Init(); - // used by the protocol handler - static nsresult Canonify(nsIURI* aChromeURL); - public: static nsresult FollowArc(nsIRDFDataSource *aDataSource, nsACString& aResult, diff --git a/mozilla/toolkit/mozapps/extensions/src/nsExtensionManager.js.in b/mozilla/toolkit/mozapps/extensions/src/nsExtensionManager.js.in index a98a94365fc..af82129d989 100644 --- a/mozilla/toolkit/mozapps/extensions/src/nsExtensionManager.js.in +++ b/mozilla/toolkit/mozapps/extensions/src/nsExtensionManager.js.in @@ -51,8 +51,7 @@ const PREF_EM_EXTENSION_FORMAT = "extensions.%UUID%."; const PREF_EM_ITEM_UPDATE_ENABLED = "extensions.%UUID%.update.enabled"; const PREF_EM_ITEM_UPDATE_URL = "extensions.%UUID%.update.url"; const PREF_EM_DSS_ENABLED = "extensions.dss.enabled"; -const PREF_DSS_SWITCHPENDING = "extensions.dss.switchPending"; -const PREF_DSS_SKIN_TO_SELECT = "extensions.lastSelectedSkin"; + const PREF_GENERAL_SKINS_SELECTEDSKIN = "general.skins.selectedSkin"; const DIR_EXTENSIONS = "extensions"; @@ -68,11 +67,11 @@ const DIR_CR_OVERLAYINFO = "overlayinfo"; const FILE_CR_CHROMEDS = "chrome.rdf"; const FILE_EXTENSIONS = "Extensions.rdf"; const FILE_UNINSTALL_LOG = "Uninstall"; -const FILE_EXTENSION_MANIFEST = "extensions.ini"; +const FILE_DEFAULTS = "defaults.ini"; +const FILE_COMPONENT_MANIFEST = "components.ini"; const FILE_AUTOREG = ".autoreg"; const FILE_INSTALL_MANIFEST = "install.rdf"; const FILE_CHROME_MANIFEST = "contents.rdf"; -const FILE_CHROMEREG_MANIFEST = "chrome.manifest"; const FILE_WASINSAFEMODE = "Safe Mode"; const FILE_INSTALLED_EXTENSIONS = "installed-extensions.txt" const FILE_INSTALLED_EXTENSIONS_PROCESSED = "installed-extensions-processed.txt" @@ -247,25 +246,11 @@ function stripPropertyPrefix(aProperty, aPrefix) function getURLSpecFromFile(aFile) { var ioServ = Components.classes["@mozilla.org/network/io-service;1"] - .getService(Components.interfaces.nsIIOService); + .getService(Components.interfaces.nsIIOService); var fph = ioServ.getProtocolHandler("file").QueryInterface(Components.interfaces.nsIFileProtocolHandler); return fph.getURLSpecFromFile(aFile); } -function newURI(aSpec) -{ - var ioServ = Components.classes["@mozilla.org/network/io-service;1"] - .getService(Components.interfaces.nsIIOService); - return ioServ.newURI(aSpec, null, null); -} - -function getURLFromFile(aFile) -{ - var ioServ = Components.classes["@mozilla.org/network/io-service;1"] - .getService(Components.interfaces.nsIIOService); - return ioServ.newFileURI(aFile); -} - function ensureExtensionsFiles(aIsProfile) { try { @@ -764,6 +749,15 @@ nsInstallLogReader.prototype = { dump("*** nsInstallLogReader::_parseLine - failed to remove file " + e + "\n"); } break; + case this.TOKEN_REGISTER_CHROME: + var isProfile = parts[1] == this.TOKEN_PROFILE; + try { + this._listener.onRegisterChrome(parts[3], lf, parts[2], isProfile); + } + catch (e) { + dump("*** nsInstallLogReader::_parseLine - failed to deregister chrome\n"); + } + break; case this.TOKEN_SKIN: var isProfile = parts[1] == this.TOKEN_PROFILE; try { @@ -1035,14 +1029,6 @@ nsExtensionInstaller.prototype = { var chromeDir = getDir(this._extDirKey, [DIR_EXTENSIONS, this._extensionID, DIR_CHROME]); - var manifestFile = getDirNoCreate(this._extDirKey, [DIR_EXTENSIONS, - this._extensionID, - FILE_CHROMEREG_MANIFEST]); - if (manifestFile.exists()) - manifestFile.remove(false); - - var manifestURI = getURLFromFile(manifestFile); - var files = this._metadataDS.GetTargets(this._sourceResource, this._fileProperty, true); while (files.hasMoreElements()) { var file = files.getNext().QueryInterface(Components.interfaces.nsIRDFResource); @@ -1055,32 +1041,111 @@ nsExtensionInstaller.prototype = { var items = this._metadataDS.GetTargets(file, providers[i], true); while (items.hasMoreElements()) { var item = items.getNext().QueryInterface(Components.interfaces.nsIRDFLiteral); - this._registerChrome(chromeFile, item.Value, manifestURI); + this._registerChrome(chromeFile, providers[i], item.Value); } } } }, - _registerChrome: function nsExtensionInstaller__registerChrome (aFile, aPath, aManifest) + _registerChrome: function nsExtensionInstaller__registerChrome (aFile, aChromeType, aPath) { - var fileURLSpec = getURLSpecFromFile(aFile); + var fileURL = getURLSpecFromFile(aFile); if (!aFile.isDirectory()) // .jar files - fileURLSpec = "jar:" + fileURLSpec + "!/" + aPath; + fileURL = "jar:" + fileURL + "!/" + aPath; else // flat chrome hierarchies - fileURLSpec = fileURLSpec + aPath; - - var fileURI = newURI(fileURLSpec); - + fileURL = fileURL + aPath; + var cr = Components.classes["@mozilla.org/chrome/chrome-registry;1"] - .getService(Components.interfaces.nsIToolkitChromeRegistry); + .getService(Components.interfaces.nsIXULChromeRegistry); + var type; + if (aChromeType.EqualsNode(this._provTypePackage)) { + try { + cr.installPackage(fileURL, this._isProfile); + } + catch (e) { + throw new nsChromeRegistrationException(fileURL, this._isProfile, "installPackage"); + } + type = this._writer.CHROME_TYPE_PACKAGE; + } + else if (aChromeType.EqualsNode(this._provTypeSkin)) { + try { + cr.installSkin(fileURL, this._isProfile, true); // Extension skins can execute scripts + } + catch (e) { + throw new nsChromeRegistrationException(fileURL, this._isProfile, "installSkin"); + } + type = this._writer.CHROME_TYPE_SKIN; + } + else if (aChromeType.EqualsNode(this._provTypeLocale)) { + try { + cr.installLocale(fileURL, this._isProfile); + } + catch (e) { + throw new nsChromeRegistrationException(fileURL, this._isProfile, "installLocale"); + } + type = this._writer.CHROME_TYPE_LOCALE; + } + var providerNames = this._getProviderNames(fileURL, type); + for (var i = 0; i < providerNames.length; ++i) { + this._writer.registerChrome(providerNames[i], type, this._isProfile); + + // Make sure we enable overlays for this extension so that if it is disabled by + // mismatch checking, installing a newer version (as opposed to enabling as a + // result of a version compatibility update) makes the extension's overlaid UI + // appear immediately. + cr.setAllowOverlaysForPackage(providerNames[i], true); + } + }, + + _getProviderNames: function nsExtensionInstaller__getProviderNames (aBaseURL, aType) + { + if (aBaseURL.charAt(aBaseURL.length-1) != "/") + aBaseURL += "/"; + var manifestURL = aBaseURL + "contents.rdf"; + + var providerNames = []; try { - cr.processContentsManifest(fileURI, aManifest, true, false); + // Discover the list of provider names to register for the location + // specified in the provider arc. + // + // The contents.rdf file will look like this: + // + // + // + // + // .. + // + // + // We need to explicitly walk this list here, we don't need to do so + // for nsIXULChromeRegistry's |installPackage| method since that does + // this same thing itself. + + var ds = gRDF.GetDataSourceBlocking(manifestURL); + + var ctr = Components.classes["@mozilla.org/rdf/container;1"] + .createInstance(Components.interfaces.nsIRDFContainer); + ctr.Init(ds, gRDF.GetResource("urn:mozilla:" + aType + ":root")); + + var items = ctr.GetElements(); + while (items.hasMoreElements()) { + var item = items.getNext().QueryInterface(Components.interfaces.nsIRDFResource); + + var nameArc = gRDF.GetResource(CHROME_NS("name")); + var name; + if (ds.hasArcOut(item, nameArc)) + name = stringData(ds.GetTarget(item, nameArc, true)); + else { + var parts = item.Value.split(":"); + name = parts[parts.length-1]; + } + providerNames.push(name); + } } - catch (e) { - throw new nsChromeRegistrationException(fileURLSpec, this._isProfile, "processContentsManifest"); - } - } + catch (e) { } + + return providerNames; + } }; /////////////////////////////////////////////////////////////////////////////// @@ -1089,11 +1154,14 @@ nsExtensionInstaller.prototype = { // function nsExtensionUninstaller(aExtensionDS) { + this._cr = Components.classes["@mozilla.org/chrome/chrome-registry;1"] + .getService(Components.interfaces.nsIXULChromeRegistry); this._extensionDS = aExtensionDS; } nsExtensionUninstaller.prototype = { _extensionDS : null, + _cr : null, _isProfile : true, _extDirKey : "", _extensionsDir: null, @@ -1147,7 +1215,36 @@ nsExtensionUninstaller.prototype = { !parent.equals(this._extensionsDir)) // stop at the extensions dir this._removeFile(parent); } - } + }, + + // XXXben - maybe we should find a way to + _packagesForExtension: [], + + onRegisterChrome: function nsExtensionUninstaller_onRegisterChrome (aProviderName, aFile, aChromeType, aIsProfile) + { + switch (aChromeType) { + case this._reader.CHROME_TYPE_PACKAGE: + this._packagesForExtension.push(aProviderName); + this._cr.uninstallPackage(aProviderName, aIsProfile) + break; + case this._reader.CHROME_TYPE_SKIN: + for (var i = 0; i < this._packagesForExtension.length; ++i) { + this._cr.deselectSkinForPackage(aProviderName, + this._packagesForExtension[i], + aIsProfile); + } + // this._cr.uninstallSkin(aProviderName, aIsProfile) + break; + case this._reader.CHROME_TYPE_LOCALE: + for (var i = 0; i < this._packagesForExtension.length; ++i) { + this._cr.deselectLocaleForPackage(aProviderName, + this._packagesForExtension[i], + aIsProfile); + } + // this._cr.uninstallLocale(aProviderName, aIsProfile) + break; + } + } }; /////////////////////////////////////////////////////////////////////////////// @@ -1156,11 +1253,14 @@ nsExtensionUninstaller.prototype = { // function nsExtensionEnabler(aExtensionDS) { + this._cr = Components.classes["@mozilla.org/chrome/chrome-registry;1"] + .getService(Components.interfaces.nsIXULChromeRegistry); this._extensionDS = aExtensionDS; } nsExtensionEnabler.prototype = { _extensionDS : null, + _cr : null, _enable : true, _isProfile : true, _extDirKey : "", @@ -1182,6 +1282,12 @@ nsExtensionEnabler.prototype = { this._reader.read(); }, + onRegisterChrome: function nsExtensionEnabler_onRegisterChrome (aProviderName, aFile, aChromeType, aIsProfile) + { + if (aChromeType == this._reader.CHROME_TYPE_PACKAGE) + this._cr.setAllowOverlaysForPackage(aProviderName, this._enable); + }, + onAddFile: function nsExtensionEnabler_onAddFile (aFile) { } @@ -1327,19 +1433,11 @@ nsThemeInstaller.prototype = { this._writer.addFile(destinationFile.QueryInterface(Components.interfaces.nsILocalFile)); this._writer.close(); - var uriSpec = "jar:" + getURLSpecFromFile(destinationFile) + "!/"; - var uri = newURI(uriSpec); - - var manifest = getDirNoCreate(extDirKey, [DIR_EXTENSIONS, - this._themeID, - FILE_CHROMEREG_MANIFEST]); - var manifestURI = getURLFromFile(manifest); - // Use the Chrome Registry API to install the theme there + var filePath = "jar:" + getURLSpecFromFile(destinationFile) + "!/"; var cr = Components.classes["@mozilla.org/chrome/chrome-registry;1"] - .getService(Components.interfaces.nsIToolkitChromeRegistry); - - cr.processContentsManifest(uri, manifestURI, false, true); + .getService(Components.interfaces.nsIXULChromeRegistry); + cr.installSkin(filePath, aIsProfile, false); // Insert the theme into the theme list. this._extensionDS.insertForthcomingItem(this._themeID, nsIUpdateItem.TYPE_THEME, @@ -1367,6 +1465,8 @@ nsThemeInstaller.prototype = { // function nsThemeUninstaller(aExtensionDS) { + this._cr = Components.classes["@mozilla.org/chrome/chrome-registry;1"] + .getService(Components.interfaces.nsIXULChromeRegistry); } nsThemeUninstaller.prototype = { @@ -1412,6 +1512,7 @@ nsThemeUninstaller.prototype = { onInstallSkin: function nsThemeUninstaller_onInstallSkin (aSkinName, aIsProfile) { + this._cr.uninstallSkin(aSkinName, aIsProfile); } }; @@ -1446,23 +1547,6 @@ nsExtensionManager.prototype = { observe: function nsExtensionManager_observe (aSubject, aTopic, aData) { switch (aTopic) { - case "app-startup": - gOS.addObserver(this, "profile-after-change", false); - break; - - case "profile-after-change": - gOS.removeObserver(this, "profile-after-change"); - try { - if (gPref.getBoolPref(PREF_DSS_SWITCHPENDING)) { - var toSelect = gPref.getCharPref(PREF_DSS_SKIN_TO_SELECT); - gPref.setCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN, toSelect); - gPref.clearUserPref(PREF_DSS_SWITCHPENDING); - gPref.clearUserPref(PREF_DSS_SKIN_TO_SELECT); - } - } - catch (e) { - } - case "quit-application-requested": if (this._downloadCount > 0) { var result; @@ -1521,7 +1605,7 @@ nsExtensionManager.prototype = { // Somehow the component list went away, and for that reason the new one // generated by this function is going to result in a different compreg. // We must force a restart. - var componentList = getFile(KEY_PROFILEDIR, [FILE_EXTENSION_MANIFEST]); + var componentList = getFile(KEY_PROFILEDIR, [FILE_COMPONENT_MANIFEST]); if (!componentList.exists()) needsRestart = true; @@ -1548,8 +1632,7 @@ nsExtensionManager.prototype = { gPref.clearUserPref(PREF_EM_LAST_SELECTED_SKIN); gPref.setCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN, lastSelectedSkin); } - catch (e) { - } + catch (e) { } // Walk the list of extensions and re-activate overlays for packages // that aren't disabled. @@ -1558,6 +1641,12 @@ nsExtensionManager.prototype = { this._finalizeEnableDisable(items[i], false); wasInSafeModeFile.remove(false); + + this._writeDefaults(true); + try { + this._writeDefaults(false); + } + catch (e) { } } catch (e) { dump("*** nsExtensionManager::start - failure, catching exception so finalize window can close = " + e + "\n"); @@ -1590,6 +1679,12 @@ nsExtensionManager.prototype = { this._finalizeEnableDisable(items[i].id, true); this._ds.safeMode = true; + + this._writeDefaults(true); + try { + this._writeDefaults(false); + } + catch (e) { } needsRestart = true; @@ -1609,7 +1704,6 @@ nsExtensionManager.prototype = { win.close(); } - return needsRestart; }, @@ -1673,7 +1767,8 @@ nsExtensionManager.prototype = { (new nsInstalledExtensionReader(this)).read(); // Write bin/components.ini - this._writeComponentManifest(false); + var manifest = getFile(KEY_APPDIR, [FILE_COMPONENT_MANIFEST]); + this._writeProfileFile(manifest, this._getComponentsDir, false); } }, @@ -1717,6 +1812,54 @@ nsExtensionManager.prototype = { return rv == 1; }, + // This function checks for and disables any "old-style" extensions + // from Firefox 0.8 and earlier created using the "chrome:extension=true" flag. + _disableObsoleteExtensions: function nsExtensionManager__disableObsoleteExtensions () + { + if (!gPref.prefHasUserValue(PREF_EM_DISABLEDOBSOLETE) || !gPref.getBoolPref(PREF_EM_DISABLEDOBSOLETE)) { + var win = this._showProgressWindow(); + try { + var cr = Components.classes["@mozilla.org/chrome/chrome-registry;1"] + .getService(Components.interfaces.nsIXULChromeRegistry); + var crDS = gRDF.GetDataSource("rdf:chrome"); + var disabled = false; + var sources = crDS.GetSources(gRDF.GetResource(CHROME_NS("extension")), gRDF.GetLiteral("true"), true); + while (sources.hasMoreElements()) { + disabled = true; + + var source = sources.getNext().QueryInterface(Components.interfaces.nsIRDFResource); + var name = crDS.GetTarget(source, gRDF.GetResource(CHROME_NS("name")), true); + if (name) { + name = name.QueryInterface(Components.interfaces.nsIRDFLiteral).Value; + cr.setAllowOverlaysForPackage(name, false); + } + } + + // Re-select the default theme to prevent any incompatibilities with old-style + // themes. + cr.selectSkin(KEY_DEFAULT_THEME, true); + } + catch (e) { + dump("*** nsExtensionManager::_disableObsoleteExtensions - failure, catching exception so finalize window can close\n"); + } + win.close(); + + if (disabled) { + const nsIPromptService = Components.interfaces.nsIPromptService; + var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] + .getService(nsIPromptService); + var sbs = Components.classes["@mozilla.org/intl/stringbundle;1"] + .getService(Components.interfaces.nsIStringBundleService); + var bundle = sbs.createBundle("chrome://mozapps/locale/extensions/extensions.properties"); + var title = bundle.GetStringFromName("disabledObsoleteTitle"); + var message = bundle.GetStringFromName("disabledObsoleteMessage"); + ps.alert(null, title, message); + } + + gPref.setBoolPref(PREF_EM_DISABLEDOBSOLETE, true); + } + }, + _checkForGlobalInstalls: function nsExtensionManager__checkForGlobalInstalls (aPath, aItemType) { #ifdef XP_UNIX @@ -1842,6 +1985,35 @@ nsExtensionManager.prototype = { "", "chrome,centerscreen,dialog", null); }, + _loadDefaults: function nsExtensionManager__loadDefaults () + { + // Load default preferences files for all extensions + var defaultsManifest = getFile(KEY_PROFILEDIR, + [DIR_EXTENSIONS, FILE_DEFAULTS]); + if (defaultsManifest.exists()) { + var fis = Components.classes["@mozilla.org/network/file-input-stream;1"] + .createInstance(Components.interfaces.nsIFileInputStream); + fis.init(defaultsManifest, -1, -1, false); + var lis = fis.QueryInterface(Components.interfaces.nsILineInputStream); + var line = { value: "" }; + var more = false; + do { + more = lis.readLine(line); + var lf = Components.classes["@mozilla.org/file/local;1"] + .createInstance(Components.interfaces.nsILocalFile); + var path = line.value; + if (path) { + lf.initWithPath(path); + + if (lf.exists()) + gPref.readUserPrefs(lf); + } + } + while (more); + fis.close(); + } + }, + ensurePreConfiguredItem: function nsExtensionManager_ensurePreConfiguredItem (aItemID, aItemType, aManifest) { this._ds.insertForthcomingItem(aItemID, aItemType, false); @@ -1853,6 +2025,8 @@ nsExtensionManager.prototype = { { var needsRestart = false; + this._disableObsoleteExtensions(); + // Check to see if the version of the application that is being started // now is the same one that was started last time. var currAppVersion = gPref.getCharPref(PREF_EM_APP_EXTENSIONS_VERSION); @@ -1893,7 +2067,7 @@ nsExtensionManager.prototype = { // Somehow the component list went away, and for that reason the new one // generated by this function is going to result in a different compreg. // We must force a restart. - var componentList = getFile(KEY_PROFILEDIR, [FILE_EXTENSION_MANIFEST]); + var componentList = getFile(KEY_PROFILEDIR, [FILE_COMPONENT_MANIFEST]); if (!componentList.exists()) needsRestart = true; @@ -1927,40 +2101,17 @@ nsExtensionManager.prototype = { // for people with write access to bin dir (i.e. uninstall, disable, // enable) this._writeComponentManifest(false); + this._writeDefaults(false); } catch (e) { dump("*** ExtensionManager:_updateManifests: no access privileges to application directory, skipping.\n"); }; this._writeComponentManifest(true); - }, - - _getActiveItems: function nsExtensionManager__getActiveItems (aExtensions, aIsProfile) - { - var validExtensions = []; - for (var i = 0; i < aExtensions.length; ++i) { - var extension = aExtensions[i]; - - // An extension entry is valid only if it is not disabled, not about to - // be disabled, and not about to be uninstalled. - var toBeDisabled = this._ds.getItemProperty(extension.id, "toBeDisabled"); - var toBeUninstalled = this._ds.getItemProperty(extension.id, "toBeUninstalled"); - var toBeInstalled = this._ds.getItemProperty(extension.id, "toBeInstalled"); - var disabled = this._ds.getItemProperty(extension.id, "disabled"); - if (toBeDisabled == "true" || toBeUninstalled == "true" || - disabled == "true" || toBeInstalled == "true") - continue; - - var isProfile = this._ds.isProfileItem(extension.id); - var sourceDir = getDirNoCreate(getDirKey(aIsProfile), [DIR_EXTENSIONS, extension.id]); - if ((aIsProfile == isProfile)) - validExtensions.push({ sourceDir: sourceDir, isProfile: isProfile }); - } - - return validExtensions; + this._writeDefaults(true); }, // XXXben write to temporary file then move to final when done. - _writeProfileFile: function nsExtensionManager__writeProfileFile (aFile, aIsProfile) + _writeProfileFile: function nsExtensionManager__writeProfileFile (aFile, aGetDirFunc, aIsProfile) { // When an operation is performed that requires a component re-registration // (extension enabled/disabled, installed, uninstalled), we must write the @@ -1971,15 +2122,6 @@ nsExtensionManager.prototype = { // about all valid items to the file. this._ensureDS(); - var validExtensions = - this._getActiveItems(this.getItemList(null, nsIUpdateItem.TYPE_EXTENSION, { }), - aIsProfile); - var validThemes = - this._getActiveItems(this.getItemList(null, nsIUpdateItem.TYPE_THEME, { }), - aIsProfile); - - var relativeDir = getDir(aIsProfile ? KEY_PROFILEDIR : KEY_APPDIR, []); - var fos = Components.classes["@mozilla.org/network/file-output-stream;1"] .createInstance(Components.interfaces.nsIFileOutputStream); const MODE_WRONLY = 0x02; @@ -1987,32 +2129,40 @@ nsExtensionManager.prototype = { const MODE_TRUNCATE = 0x20; fos.init(aFile, MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE, 0644, 0); - var lines = ["[ExtensionDirs]\r\n", + var extensions = this.getItemList(null, nsIUpdateItem.TYPE_EXTENSION, { }); + var validExtensions = []; + for (var i = 0; i < extensions.length; ++i) { + var extension = extensions[i]; + + // An extension entry is valid only if it is not disabled, not about to + // be disabled, and not about to be uninstalled. + var toBeDisabled = this._ds.getItemProperty(extension.id, "toBeDisabled"); + var toBeUninstalled = this._ds.getItemProperty(extension.id, "toBeUninstalled"); + var toBeInstalled = this._ds.getItemProperty(extension.id, "toBeInstalled"); + var disabled = this._ds.getItemProperty(extension.id, "disabled"); + if (toBeDisabled == "true" || toBeUninstalled == "true" || + disabled == "true" || toBeInstalled == "true") + continue; + + var isProfile = this._ds.isProfileItem(extension.id); + var sourceDir = aGetDirFunc(isProfile, extension.id); + if (sourceDir.exists() && (aIsProfile == isProfile)) + validExtensions.push({ sourceDir: sourceDir, isProfile: isProfile }); + } + + var lines = ["[Extra Files]\r\n", "Count=" + validExtensions.length + "\r\n"]; for (i = 0; i < lines.length; ++i) fos.write(lines[i], lines[i].length); for (i = 0; i < validExtensions.length; ++i) { var e = validExtensions[i]; + var relativeDir = getDir(e.isProfile ? KEY_PROFILEDIR : KEY_APPDIR, []); var lf = e.sourceDir.QueryInterface(Components.interfaces.nsILocalFile); var relDesc = lf.getRelativeDescriptor(relativeDir); - var line = "Extension" + i + "=" + relDesc + "\r\n"; + var line = "File" + i + "=" + relDesc + "\r\n"; fos.write(line, line.length); } - - var lines = ["[ThemeDirs]\r\n", - "Count=" + validThemes.length + "\r\n"]; - for (i = 0; i < lines.length; ++i) - fos.write(lines[i], lines[i].length); - - for (i = 0; i < validThemes.length; ++i) { - var e = validThemes[i]; - var lf = e.sourceDir.QueryInterface(Components.interfaces.nsILocalFile); - var relDesc = lf.getRelativeDescriptor(relativeDir); - var line = "Extension" + i + "=" + relDesc + "\r\n"; - fos.write(line, line.length); - } - fos.close(); }, @@ -2031,9 +2181,9 @@ nsExtensionManager.prototype = { _writeComponentManifest: function nsExtensionManager__writeComponentManifest (aIsProfile) { - var manifest = getFile(aIsProfile ? KEY_PROFILEDIR : KEY_APPDIR, - [FILE_EXTENSION_MANIFEST]); - this._writeProfileFile(manifest, aIsProfile); + var manifest = aIsProfile ? getFile(KEY_PROFILEDIR, [FILE_COMPONENT_MANIFEST]) : + getFile(KEY_APPDIR, [FILE_COMPONENT_MANIFEST]); + this._writeProfileFile(manifest, this._getComponentsDir, aIsProfile); // Now refresh the compatibility manifest. this._setComponentsListChanged(true); @@ -2055,6 +2205,13 @@ nsExtensionManager.prototype = { catch (e) {} }, + _writeDefaults: function nsExtensionManager__writeDefaults (aIsProfile) + { + var manifest = aIsProfile ? getFile(KEY_PROFILEDIR, [FILE_DEFAULTS]) : + getFile(KEY_APPDIR, [FILE_DEFAULTS]); + this._writeProfileFile(manifest, this._getPreferencesDir, aIsProfile); + }, + _cleanDirs: function nsExtensionManager__cleanDirs () { var keys = [KEY_PROFILEDIR, KEY_APPDIR]; @@ -2384,6 +2541,9 @@ nsExtensionManager.prototype = { // Update the Components Manifest this._writeComponentManifest(isProfile); + + // Update the Defaults Manifest + this._writeDefaults(isProfile); }, _finalizeEnableDisable: function nsExtensionManager__finalizeEnableDisable (aExtensionID, aDisable) @@ -2431,6 +2591,9 @@ nsExtensionManager.prototype = { // Update the Components Manifest this._writeComponentManifest(isProfile); + + // Update the Defaults Manifest + this._writeDefaults(isProfile); } else { // Bad download entry - uri is url, e.g. "http://www.foo.com/test.xpi" @@ -2447,6 +2610,9 @@ nsExtensionManager.prototype = { // Update the Components Manifest this._writeComponentManifest(isProfile); + + // Update the Defaults Manifest + this._writeDefaults(isProfile); }, disableExtension: function nsExtensionManager_disableExtension (aExtensionID) @@ -2457,6 +2623,9 @@ nsExtensionManager.prototype = { // Update the Components Manifest this._writeComponentManifest(isProfile); + + // Update the Defaults Manifest + this._writeDefaults(isProfile); }, enableTheme: function nsExtensionsDataSource_enableTheme (aThemeID) @@ -2497,16 +2666,14 @@ nsExtensionManager.prototype = { var isProfile = aFlags & nsIExtensionManager.FLAG_INSTALL_PROFILE; var installer = new nsThemeInstaller(this._ds, this); installer.install(aJARFile, isProfile); - this._writeComponentManifest(isProfile); + // XPInstall selects the theme, if necessary. }, - + uninstallTheme: function nsExtensionManager_uninstallTheme (aThemeID) { if (!this._ds.isDownloadItem(aThemeID)) { this._ensureDS(); - var isProfile = this._ds.isProfileItem(aThemeID); this._ds.uninstallTheme(aThemeID); - this._writeComponentManifest(isProfile); } else { // Bad download entry - uri is url, e.g. "http://www.foo.com/test.jar" @@ -4331,6 +4498,10 @@ var gModule = { registerSelf: function (aComponentManager, aFileSpec, aLocation, aType) { + if (this._firstTime) { + this._firstTime = false; + throw Components.results.NS_ERROR_FACTORY_REGISTER_AGAIN; + } aComponentManager = aComponentManager.QueryInterface(Components.interfaces.nsIComponentRegistrar); for (var key in this._objects) { @@ -4339,12 +4510,14 @@ var gModule = { aFileSpec, aLocation, aType); } +/* // Make the Extension Manager a startup observer var categoryManager = Components.classes["@mozilla.org/categorymanager;1"] .getService(Components.interfaces.nsICategoryManager); categoryManager.addCategoryEntry("app-startup", this._objects.manager.className, "service," + this._objects.manager.contractID, true, true, null); + */ }, getClassObject: function (aComponentManager, aCID, aIID) diff --git a/mozilla/toolkit/xre/Makefile.in b/mozilla/toolkit/xre/Makefile.in index 303ff5b6ad9..a8698053334 100644 --- a/mozilla/toolkit/xre/Makefile.in +++ b/mozilla/toolkit/xre/Makefile.in @@ -50,8 +50,6 @@ REQUIRES = \ appcomps \ toolkitcomps \ appshell \ - appstartup \ - chrome \ content \ docshell \ dom \ diff --git a/mozilla/toolkit/xre/nsAppRunner.h b/mozilla/toolkit/xre/nsAppRunner.h index 65ad3d58167..a0c6c223f70 100644 --- a/mozilla/toolkit/xre/nsAppRunner.h +++ b/mozilla/toolkit/xre/nsAppRunner.h @@ -50,12 +50,6 @@ #include "nscore.h" -// This directory service key is a lot like "ProfD", except that it will be -// available even when the profile hasn't been "started", or after is has been -// shut down. If we're in "no-profile" mode, such as showing the profile manager UI, -// this key will not be available. -#define NS_APP_PROFILE_DIR_STARTUP "ProfDS" - class nsACString; struct nsXREAppData; diff --git a/mozilla/toolkit/xre/nsXREDirProvider.cpp b/mozilla/toolkit/xre/nsXREDirProvider.cpp index 56d076edf01..1098749683b 100644 --- a/mozilla/toolkit/xre/nsXREDirProvider.cpp +++ b/mozilla/toolkit/xre/nsXREDirProvider.cpp @@ -47,7 +47,6 @@ #include "nsILocalFile.h" #include "nsIObserverService.h" #include "nsIProfileChangeStatus.h" -#include "nsIToolkitChromeRegistry.h" #include "nsAppDirectoryServiceDefs.h" #include "nsDirectoryServiceDefs.h" @@ -283,9 +282,6 @@ nsXREDirProvider::GetFile(const char* aProperty, PRBool* aPersistent, rv = mProfileDir->Clone(getter_AddRefs(file)); rv |= file->AppendNative(NS_LITERAL_CSTRING("chrome")); } - else if (!strcmp(aProperty, NS_APP_PROFILE_DIR_STARTUP) && mProfileDir) { - return mProfileDir->Clone(aFile); - } else if (mProfileNotified) { if (!strcmp(aProperty, NS_APP_USER_PROFILE_50_DIR) || !strcmp(aProperty, NS_APP_PREFS_50_DIR)) { @@ -360,48 +356,34 @@ nsXREDirProvider::GetFile(const char* aProperty, PRBool* aPersistent, } static void -LoadDirsIntoArray(nsIFile* aComponentsList, const char* aSection, - const char *const* aAppendList, - nsCOMArray& aDirectories) +LoadDirsIntoArray(nsIFile* aComponentsList, nsCOMArray& aDirectories) { nsINIParser parser; nsCOMPtr lf(do_QueryInterface(aComponentsList)); parser.Init(lf); char parserBuf[MAXPATHLEN]; - nsresult rv = parser.GetString(aSection, "Count", parserBuf, MAXPATHLEN); + nsresult rv = parser.GetString("Extra Files", "Count", parserBuf, MAXPATHLEN); if (NS_SUCCEEDED(rv)) { PRInt32 count = atoi(parserBuf); - char buf[18]; + char buf[10]; nsCOMPtr parent; aComponentsList->GetParent(getter_AddRefs(parent)); - nsCOMPtr lfParent (do_QueryInterface(parent)); - for (PRInt32 i = 0; i < count; ++i) { - sprintf(buf, "Extension%d", i); + sprintf(buf, "File%d", i); - rv = parser.GetString(aSection, buf, parserBuf, MAXPATHLEN); + rv = parser.GetString("Extra Files", buf, parserBuf, MAXPATHLEN); if (NS_SUCCEEDED(rv)) { + nsCOMPtr lfParent(do_QueryInterface(parent)); nsCOMPtr dir(do_CreateInstance("@mozilla.org/file/local;1")); dir->SetRelativeDescriptor(lfParent, nsDependentCString(parserBuf)); - const char* const* a = aAppendList; - while (*a) { - dir->AppendNative(nsDependentCString(*a)); - ++a; - } - - PRBool exists; - rv = dir->Exists(&exists); - if (NS_SUCCEEDED(rv) && exists) - aDirectories.AppendObject(dir); + nsCOMPtr dirAsFile(do_QueryInterface(dir)); + aDirectories.AppendObject(dirAsFile); } } } } -static const char *const kAppendChromeManifests[] = - { "chrome.manifest", nsnull }; - NS_IMETHODIMP nsXREDirProvider::GetFiles(const char* aProperty, nsISimpleEnumerator** aResult) { @@ -420,21 +402,16 @@ nsXREDirProvider::GetFiles(const char* aProperty, nsISimpleEnumerator** aResult) directories.AppendObject(file); } - static const char *const kAppendCompDir[] = { "components", nsnull }; - nsCOMPtr appFile; mAppDir->Clone(getter_AddRefs(appFile)); - appFile->AppendNative(NS_LITERAL_CSTRING("extensions.ini")); - LoadDirsIntoArray(appFile, "ExtensionDirs", - kAppendCompDir, directories); + appFile->AppendNative(NS_LITERAL_CSTRING("components.ini")); + LoadDirsIntoArray(appFile, directories); + nsCOMPtr profileFile; if (mProfileDir) { - nsCOMPtr profileFile; mProfileDir->Clone(getter_AddRefs(profileFile)); - profileFile->AppendNative(NS_LITERAL_CSTRING("extensions.ini")); - - LoadDirsIntoArray(profileFile, "ExtensionDirs", - kAppendCompDir, directories); + profileFile->AppendNative(NS_LITERAL_CSTRING("components.ini")); + LoadDirsIntoArray(profileFile, directories); } rv = NS_NewArrayEnumerator(aResult, directories); @@ -452,78 +429,20 @@ nsXREDirProvider::GetFiles(const char* aProperty, nsISimpleEnumerator** aResult) directories.AppendObject(file); } - static const char *const kAppendPrefDir[] = { "defaults", "pref", nsnull }; - nsCOMPtr appFile; mAppDir->Clone(getter_AddRefs(appFile)); - appFile->AppendNative(NS_LITERAL_CSTRING("extensions.ini")); - LoadDirsIntoArray(appFile, "ExtensionDirs", - kAppendPrefDir, directories); + appFile->AppendNative(NS_LITERAL_CSTRING("defaults.ini")); + LoadDirsIntoArray(appFile, directories); nsCOMPtr profileFile; if (mProfileDir) { mProfileDir->Clone(getter_AddRefs(profileFile)); - profileFile->AppendNative(NS_LITERAL_CSTRING("extensions.ini")); - LoadDirsIntoArray(profileFile, "ExtensionDirs", - kAppendPrefDir, directories); + profileFile->AppendNative(NS_LITERAL_CSTRING("defaults.ini")); + LoadDirsIntoArray(profileFile, directories); } rv = NS_NewArrayEnumerator(aResult, directories); } - else if (!strcmp(aProperty, NS_CHROME_MANIFESTS_FILE_LIST)) { - nsCOMArray manifests; - - nsCOMPtr manifest; - mAppDir->Clone(getter_AddRefs(manifest)); - manifest->AppendNative(NS_LITERAL_CSTRING("chrome")); - manifests.AppendObject(manifest); - - if (mXULAppDir) { - nsCOMPtr file; - mXULAppDir->Clone(getter_AddRefs(file)); - file->AppendNative(NS_LITERAL_CSTRING("chrome")); - PRBool exists; - if (NS_SUCCEEDED(file->Exists(&exists)) && exists) - manifests.AppendObject(file); - } - - nsCOMPtr appFile; - mAppDir->Clone(getter_AddRefs(appFile)); - appFile->AppendNative(NS_LITERAL_CSTRING("extensions.ini")); - LoadDirsIntoArray(appFile, "ExtensionDirs", - kAppendChromeManifests, manifests); - - if (mProfileDir) { - nsCOMPtr profileFile; - mProfileDir->Clone(getter_AddRefs(profileFile)); - profileFile->AppendNative(NS_LITERAL_CSTRING("extensions.ini")); - - LoadDirsIntoArray(profileFile, "ExtensionDirs", - kAppendChromeManifests, manifests); - } - - rv = NS_NewArrayEnumerator(aResult, manifests); - } - else if (!strcmp(aProperty, NS_SKIN_MANIFESTS_FILE_LIST)) { - nsCOMArray manifests; - - nsCOMPtr appFile; - mAppDir->Clone(getter_AddRefs(appFile)); - appFile->AppendNative(NS_LITERAL_CSTRING("extensions.ini")); - LoadDirsIntoArray(appFile, "ThemeDirs", - kAppendChromeManifests, manifests); - - if (mProfileDir) { - nsCOMPtr profileFile; - mProfileDir->Clone(getter_AddRefs(profileFile)); - profileFile->AppendNative(NS_LITERAL_CSTRING("extensions.ini")); - - LoadDirsIntoArray(profileFile, "ThemeDirs", - kAppendChromeManifests, manifests); - } - - rv = NS_NewArrayEnumerator(aResult, manifests); - } else if (!strcmp(aProperty, NS_APP_CHROME_DIR_LIST)) { nsCOMArray directories; diff --git a/mozilla/xpinstall/src/nsInstall.cpp b/mozilla/xpinstall/src/nsInstall.cpp index aca25c7452b..0d143f35dfb 100644 --- a/mozilla/xpinstall/src/nsInstall.cpp +++ b/mozilla/xpinstall/src/nsInstall.cpp @@ -53,10 +53,6 @@ #include "nsIFileChannel.h" #include "nsDirectoryService.h" #include "nsDirectoryServiceDefs.h" -#include "nsAppDirectoryServiceDefs.h" -#include "nsDirectoryServiceUtils.h" - -#include "nsNetUtil.h" #include "nsIPrefBranch.h" #include "nsIPrefService.h" @@ -173,7 +169,9 @@ nsInstallInfo::nsInstallInfo(PRUint32 aInstallType, const PRUnichar* aArgs, nsIPrincipal* aPrincipal, PRUint32 flags, - nsIXPIListener* aListener) + nsIXPIListener* aListener, + nsIXULChromeRegistry* aChromeRegistry, + nsIExtensionManager* aExtensionManager) : mPrincipal(aPrincipal), mError(0), mType(aInstallType), @@ -181,45 +179,11 @@ nsInstallInfo::nsInstallInfo(PRUint32 aInstallType, mURL(aURL), mArgs(aArgs), mFile(aFile), - mListener(aListener) + mListener(aListener), + mChromeRegistry(aChromeRegistry), + mExtensionManager(aExtensionManager) { MOZ_COUNT_CTOR(nsInstallInfo); - - nsresult rv; - - // Failure is an option, and will occur in the stub installer. - - NS_WITH_ALWAYS_PROXIED_SERVICE(CHROMEREG_IFACE, cr, - NS_CHROMEREGISTRY_CONTRACTID, - NS_UI_THREAD_EVENTQ, &rv); - if (NS_SUCCEEDED(rv)) { - mChromeRegistry = cr; - - nsCAutoString spec; - rv = NS_GetURLSpecFromFile(aFile, spec); - if (NS_SUCCEEDED(rv)) { - spec.Insert(NS_LITERAL_CSTRING("jar:"), 0); - spec.AppendLiteral("!/"); -#ifdef MOZ_XUL_APP - NS_NewURI(getter_AddRefs(mFileJARURL), spec); -#else - mFileJARSpec.Assign(spec); -#endif - } - } - -#ifdef MOZ_XUL_APP - NS_WITH_ALWAYS_PROXIED_SERVICE(nsIExtensionManager, em, - "@mozilla.org/extensions/manager;1", - NS_UI_THREAD_EVENTQ, &rv); - if (NS_SUCCEEDED(rv)) - mExtensionManager = em; - - nsCOMPtr manifest; - rv = NS_GetSpecialDirectory(NS_APP_CHROME_DIR, getter_AddRefs(manifest)); - if (NS_SUCCEEDED(rv)) - NS_NewFileURI(getter_AddRefs(mManifestURL), manifest); -#endif } diff --git a/mozilla/xpinstall/src/nsInstall.h b/mozilla/xpinstall/src/nsInstall.h index 6515f4543cf..743bdce2ca8 100644 --- a/mozilla/xpinstall/src/nsInstall.h +++ b/mozilla/xpinstall/src/nsInstall.h @@ -53,7 +53,6 @@ #include "nsHashtable.h" #include "nsCOMPtr.h" #include "nsILocalFile.h" -#include "nsIURI.h" #include "nsSoftwareUpdate.h" @@ -71,17 +70,10 @@ #include "nsIComponentManager.h" #include "nsIEnumerator.h" #include "nsIZipReader.h" +#include "nsIChromeRegistry.h" #include "nsIExtensionManager.h" #include "nsIPrincipal.h" -#ifdef MOZ_XUL_APP -#include "nsIToolkitChromeRegistry.h" -#define CHROMEREG_IFACE nsIToolkitChromeRegistry -#else -#include "nsIChromeRegistrySea.h" -#define CHROMEREG_IFACE nsIChromeRegistrySea -#endif - #define XPINSTALL_BUNDLE_URL "chrome://global/locale/xpinstall/xpinstall.properties" //file and directory name length maximums @@ -103,7 +95,9 @@ class nsInstallInfo const PRUnichar* aArgs, nsIPrincipal* mPrincipal, PRUint32 aFlags, - nsIXPIListener* aListener); + nsIXPIListener* aListener, + nsIXULChromeRegistry* aChromeReg, + nsIExtensionManager* aExtensionManager); virtual ~nsInstallInfo(); @@ -113,15 +107,8 @@ class nsInstallInfo PRUint32 GetFlags() { return mFlags; } PRUint32 GetType() { return mType; } nsIXPIListener* GetListener() { return mListener.get(); } - CHROMEREG_IFACE* GetChromeRegistry() { return mChromeRegistry; } - -#ifdef MOZ_XUL_APP - nsIExtensionManager* GetExtensionManager() { return mExtensionManager; } - nsIURI* GetFileJARURL() { return mFileJARURL; } - nsIURI* GetManifestURL() { return mManifestURL; } -#else - const nsCString& GetFileJARSpec() { return mFileJARSpec; } -#endif + nsIXULChromeRegistry* GetChromeRegistry() { return mChromeRegistry.get(); } + nsIExtensionManager* GetExtensionManager(){ return mExtensionManager.get(); } nsCOMPtr mPrincipal; @@ -136,15 +123,8 @@ class nsInstallInfo nsCOMPtr mFile; nsCOMPtr mListener; - nsCOMPtr mChromeRegistry; - -#ifdef MOZ_XUL_APP - nsCOMPtr mFileJARURL; - nsCOMPtr mManifestURL; + nsCOMPtr mChromeRegistry; nsCOMPtr mExtensionManager; -#else - nsCString mFileJARSpec; -#endif }; #if defined(XP_WIN) || defined(XP_OS2) @@ -326,8 +306,8 @@ class nsInstall PRInt32 GetInstallPlatform(nsCString& aPlatform); - CHROMEREG_IFACE* GetChromeRegistry() { return mChromeRegistry; } - void SetChromeRegistry(CHROMEREG_IFACE* reg) + nsIXULChromeRegistry* GetChromeRegistry() { return mChromeRegistry; } + void SetChromeRegistry(nsIXULChromeRegistry* reg) { mChromeRegistry = reg; } PRUint32 GetFinalStatus() { return mFinalStatus; } @@ -355,7 +335,7 @@ class nsInstall nsString mInstallURL; PRUint32 mInstallFlags; nsCString mInstallPlatform; - CHROMEREG_IFACE* mChromeRegistry; // we don't own it, it outlives us + nsIXULChromeRegistry* mChromeRegistry; // we don't own it, it outlives us nsInstallFolder* mPackageFolder; PRBool mUserCancelled; diff --git a/mozilla/xpinstall/src/nsJSInstall.cpp b/mozilla/xpinstall/src/nsJSInstall.cpp index 88231fc4e7d..eb367f86fdc 100644 --- a/mozilla/xpinstall/src/nsJSInstall.cpp +++ b/mozilla/xpinstall/src/nsJSInstall.cpp @@ -1881,13 +1881,16 @@ static JSFunctionSpec InstallMethods[] = }; + + + JSObject * InitXPInstallObjects(JSContext *jscontext, JSObject *global, nsIFile* jarfile, const PRUnichar* url, const PRUnichar* args, PRUint32 flags, - CHROMEREG_IFACE* reg, + nsIXULChromeRegistry* reg, nsIZipReader * theJARFile) { JSObject *installObject = nsnull; diff --git a/mozilla/xpinstall/src/nsRegisterItem.cpp b/mozilla/xpinstall/src/nsRegisterItem.cpp index cebfce47331..8cf222a4a4f 100644 --- a/mozilla/xpinstall/src/nsRegisterItem.cpp +++ b/mozilla/xpinstall/src/nsRegisterItem.cpp @@ -274,38 +274,11 @@ PRInt32 nsRegisterItem::Complete() { nsresult rv = NS_OK; PRInt32 result = nsInstall::SUCCESS; - CHROMEREG_IFACE* reg = mInstall->GetChromeRegistry(); -#ifndef MOZ_XUL_APP PRBool isProfile = mChromeType & CHROME_PROFILE; -#endif + nsIXULChromeRegistry* reg = mInstall->GetChromeRegistry(); if ( reg && !(mChromeType & CHROME_DELAYED) ) { -#ifdef MOZ_XUL_APP - nsCOMPtr baseuri; - rv = NS_NewURI(getter_AddRefs(baseuri), mURL); - if (NS_FAILED(rv)) { - LogError(NS_LITERAL_STRING("NS_NewURI failed."), rv); - } - else { - nsCOMPtr manifesturi; - rv = NS_NewURI(getter_AddRefs(manifesturi), - NS_LITERAL_CSTRING("resource:///chrome/xpinstall.manifest")); - if (NS_FAILED(rv)) { - LogError(NS_LITERAL_STRING("NS_NewURI failed."), rv); - } - else { - PRBool skinOnly = (mChromeType & CHROME_ALL) == CHROME_SKIN; - rv = reg->ProcessContentsManifest(baseuri, manifesturi, - PR_TRUE, - skinOnly); - if (NS_FAILED(rv)) { - LogError(NS_LITERAL_STRING("ProcessContentsManifest failed."), rv); - } - reg->CheckForNewChrome(); - } - } -#else // We can register right away if (mChromeType & CHROME_SKIN) rv = reg->InstallSkin(mURL.get(), isProfile, PR_TRUE); @@ -324,7 +297,6 @@ PRInt32 nsRegisterItem::Complete() if (NS_FAILED(rv)) { LogError(NS_LITERAL_STRING("InstallPackage() failed."), rv); } -#endif } else { @@ -468,13 +440,6 @@ PRInt32 nsRegisterItem::Complete() } } PR_Close(fd); - -#ifdef MOZ_XUL_APP - // app-chrome.manifest is not regenerated if it exists - rv = startupFile->SetNativeLeafName(NS_LITERAL_CSTRING("app-chrome.manifest")); - if (NS_SUCCEEDED(rv)) - startupFile->Remove(PR_FALSE); -#endif } else { diff --git a/mozilla/xpinstall/src/nsSoftwareUpdate.cpp b/mozilla/xpinstall/src/nsSoftwareUpdate.cpp index e8caa8f872b..65fb66aef63 100644 --- a/mozilla/xpinstall/src/nsSoftwareUpdate.cpp +++ b/mozilla/xpinstall/src/nsSoftwareUpdate.cpp @@ -313,9 +313,28 @@ nsSoftwareUpdate::InstallJar( nsIFile* aLocalFile, if ( !aLocalFile ) return NS_ERROR_NULL_POINTER; + // -- grab a proxied Chrome Registry now while we can + nsresult rv; + nsIXULChromeRegistry* chromeRegistry = nsnull; + NS_WITH_ALWAYS_PROXIED_SERVICE( nsIXULChromeRegistry, + tmpRegCR, + NS_CHROMEREGISTRY_CONTRACTID, + NS_UI_THREAD_EVENTQ, &rv); + if (NS_SUCCEEDED(rv)) + chromeRegistry = tmpRegCR; + + + NS_WITH_ALWAYS_PROXIED_SERVICE( nsIExtensionManager, + extensionManager, + "@mozilla.org/extensions/manager;1", + NS_UI_THREAD_EVENTQ, &rv); + if (NS_FAILED(rv)) + extensionManager = nsnull; + // we want to call this with or without a chrome registry nsInstallInfo *info = new nsInstallInfo( 0, aLocalFile, aURL, aArguments, aPrincipal, - flags, aListener); + flags, aListener, chromeRegistry, + extensionManager); if (!info) return NS_ERROR_OUT_OF_MEMORY; @@ -337,29 +356,33 @@ nsSoftwareUpdate::InstallChrome( PRUint32 aType, PRBool aSelect, nsIXPIListener* aListener) { + nsresult rv; + NS_WITH_ALWAYS_PROXIED_SERVICE( nsIXULChromeRegistry, + chromeRegistry, + NS_CHROMEREGISTRY_CONTRACTID, + NS_UI_THREAD_EVENTQ, &rv); + if (NS_FAILED(rv)) + return rv; + + NS_WITH_ALWAYS_PROXIED_SERVICE( nsIExtensionManager, + extensionManager, + "@mozilla.org/extensions/manager;1", + NS_UI_THREAD_EVENTQ, &rv); + if (NS_FAILED(rv)) + return rv; + nsInstallInfo *info = new nsInstallInfo( aType, aFile, URL, aName, nsnull, (PRUint32)aSelect, - aListener); + aListener, + chromeRegistry, + extensionManager); if (!info) return NS_ERROR_OUT_OF_MEMORY; - if (!info->GetChromeRegistry() || -#ifdef MOZ_XUL_APP - !info->GetExtensionManager() || - !info->GetFileJARURL() || - !info->GetManifestURL() -#else - info->GetFileJARSpec().IsEmpty() -#endif - ) { - delete info; - return NS_ERROR_FAILURE; - } - PR_CreateThread(PR_USER_THREAD, RunChromeInstallOnThread, (void*)info, diff --git a/mozilla/xpinstall/src/nsSoftwareUpdateRun.cpp b/mozilla/xpinstall/src/nsSoftwareUpdateRun.cpp index 505a87f8fdc..855eefe0da0 100644 --- a/mozilla/xpinstall/src/nsSoftwareUpdateRun.cpp +++ b/mozilla/xpinstall/src/nsSoftwareUpdateRun.cpp @@ -73,13 +73,17 @@ #include "nsIExtensionManager.h" +#ifndef MOZ_XUL_APP +#include "nsIChromeRegistrySea.h" +#endif + static NS_DEFINE_CID(kSoftwareUpdateCID, NS_SoftwareUpdate_CID); static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); extern JSObject *InitXPInstallObjects(JSContext *jscontext, JSObject *global, nsIFile* jarfile, const PRUnichar* url, const PRUnichar* args, PRUint32 flags, - CHROMEREG_IFACE* registry, + nsIXULChromeRegistry* registry, nsIZipReader* hZip); extern nsresult InitInstallVersionClass(JSContext *jscontext, JSObject *global, void** prototype); extern nsresult InitInstallTriggerGlobalClass(JSContext *jscontext, JSObject *global, void** prototype); @@ -90,7 +94,7 @@ static PRInt32 GetInstallScriptFromJarfile(nsIZipReader* hZip, char** scriptBuf static PRInt32 OpenAndValidateArchive(nsIZipReader* hZip, nsIFile* jarFile, nsIPrincipal* aPrincipal); static nsresult SetupInstallContext(nsIZipReader* hZip, nsIFile* jarFile, const PRUnichar* url, const PRUnichar* args, - PRUint32 flags, CHROMEREG_IFACE* reg, JSRuntime *jsRT, JSContext **jsCX, JSObject **jsGlob); + PRUint32 flags, nsIXULChromeRegistry* reg, JSRuntime *jsRT, JSContext **jsCX, JSObject **jsGlob); extern "C" void RunInstallOnThread(void *data); @@ -241,6 +245,7 @@ XPInstallErrorReporter(JSContext *cx, const char *message, JSErrorReport *report } + /////////////////////////////////////////////////////////////////////////////////////////////// // Function name : OpenAndValidateArchive // Description : Opens install archive and validates contents @@ -287,6 +292,7 @@ OpenAndValidateArchive(nsIZipReader* hZip, nsIFile* jarFile, nsIPrincipal* aPrin return nsInstall::SUCCESS; } + /////////////////////////////////////////////////////////////////////////////////////////////// // Function name : GetInstallScriptFromJarfile // Description : Extracts and reads in a install.js file from a passed jar file. @@ -364,7 +370,7 @@ static nsresult SetupInstallContext(nsIZipReader* hZip, const PRUnichar* url, const PRUnichar* args, PRUint32 flags, - CHROMEREG_IFACE* reg, + nsIXULChromeRegistry* reg, JSRuntime *rt, JSContext **jsCX, JSObject **jsGlob) @@ -492,13 +498,13 @@ extern "C" void RunInstallOnThread(void *data) nsCOMPtr jarpath = installInfo->GetFile(); + PRBool installed = PR_FALSE; finalStatus = OpenAndValidateArchive( hZip, jarpath, installInfo->mPrincipal); if (finalStatus == nsInstall::SUCCESS) { -#ifdef MOZ_XUL_APP if (NS_SUCCEEDED(hZip->Test("install.rdf"))) { // appears to be an Extension Manager install @@ -506,18 +512,16 @@ extern "C" void RunInstallOnThread(void *data) if (em) { rv = em->InstallExtension(jarpath, nsIExtensionManager::FLAG_INSTALL_PROFILE); - if (NS_FAILED(rv)) - finalStatus = nsInstall::EXECUTION_ERROR; - } else { - finalStatus = nsInstall::UNEXPECTED_ERROR; + if (NS_SUCCEEDED(rv)) + installed = PR_TRUE; } - // If install.rdf exists, but the install failed, we don't want - // to try an install.js install. - } else -#endif + } + + if (!installed) { - // If we're the suite, or there is no install.rdf, + // Either no install.rdf, EM doesn't exist (Suite), or EM install failed: // try original XPInstall + // XXX: Shouldn't the third case be an error and skip the old-style attempt? finalStatus = GetInstallScriptFromJarfile( hZip, &scriptBuffer, &scriptLength); @@ -639,91 +643,107 @@ extern "C" void RunChromeInstallOnThread(void *data) listener->OnInstallStart(info->GetURL()); // make sure we've got a chrome registry -- can't proceed if not - CHROMEREG_IFACE* reg = info->GetChromeRegistry(); - NS_ASSERTION(reg, "We shouldn't get here without a chrome registry."); - + nsIXULChromeRegistry* reg = info->GetChromeRegistry(); +#ifndef MOZ_XUL_APP + nsCOMPtr cr = do_QueryInterface(reg); +#endif if (reg) { -#ifdef MOZ_XUL_APP - PRBool installed = PR_FALSE; + // build up jar: URL + nsCString spec; + spec.SetCapacity(200); + spec = "jar:"; - if (info->GetType() == CHROME_SKIN) { - static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID); - nsCOMPtr hZip = do_CreateInstance(kZipReaderCID, &rv); - if (hZip) - rv = hZip->Init(info->GetFile()); - if (NS_SUCCEEDED(rv)) - rv = hZip->Open(); + nsCAutoString localURL; + rv = NS_GetURLSpecFromFile(info->GetFile(), localURL); + if (NS_SUCCEEDED(rv)) { + spec.Append(localURL); + spec.Append("!/"); + } - if (NS_SUCCEEDED(rv)) + // Now register the new chrome + if (NS_SUCCEEDED(rv)) + { + PRBool isSkin = (info->GetType() & CHROME_SKIN); + PRBool isLocale = (info->GetType() & CHROME_LOCALE); + PRBool isContent = (info->GetType() & CHROME_CONTENT); + PRBool selected = (info->GetFlags() != 0); + + if ( isContent ) { - rv = hZip->Test("install.rdf"); - nsIExtensionManager* em = info->GetExtensionManager(); - if (NS_SUCCEEDED(rv) && em) { - rv = em->InstallTheme(info->GetFile(), nsIExtensionManager::FLAG_INSTALL_PROFILE); - if (NS_SUCCEEDED(rv)) { - installed = PR_TRUE; - info->GetFile()->Remove(PR_FALSE); - // Extension Manager copies the theme .jar file to - // a different location, so remove the temporary file. + rv = reg->InstallPackage(spec.get(), PR_TRUE); + } + + if ( isSkin ) + { + PRBool installed = PR_FALSE; + + // Look for a theme manifest + + static NS_DEFINE_IID(kIZipReaderIID, NS_IZIPREADER_IID); + static NS_DEFINE_IID(kZipReaderCID, NS_ZIPREADER_CID); + nsresult rv; + nsCOMPtr hZip = do_CreateInstance(kZipReaderCID, &rv); + if (hZip) + rv = hZip->Init(info->GetFile()); + if (NS_SUCCEEDED(rv)) + { + hZip->Open(); + + nsIExtensionManager* em = info->GetExtensionManager(); + rv = hZip->Test("install.rdf"); + if (NS_SUCCEEDED(rv) && em) + { + rv = em->InstallTheme(info->GetFile(), nsIExtensionManager::FLAG_INSTALL_PROFILE); + if (NS_SUCCEEDED(rv)) + installed = PR_TRUE; } - } - hZip->Close(); - } - } - - if (!installed) { - reg->ProcessContentsManifest(info->GetFileJARURL(), - info->GetManifestURL(), - PR_TRUE, - info->GetType() == CHROME_SKIN); - reg->CheckForNewChrome(); - } - -#else - PRBool isSkin = (info->GetType() & CHROME_SKIN); - PRBool isLocale = (info->GetType() & CHROME_LOCALE); - PRBool isContent = (info->GetType() & CHROME_CONTENT); - PRBool selected = (info->GetFlags() != 0); - - const nsCString& spec = info->GetFileJARSpec(); - - if ( isContent ) - rv = reg->InstallPackage(spec.get(), PR_TRUE); - - if ( isSkin ) - { - rv = reg->InstallSkin(spec.get(), PR_TRUE, PR_FALSE); + hZip->Close(); + // Extension Manager copies the theme .jar file to + // a different location, so remove the temporary file. + info->GetFile()->Remove(PR_FALSE); + } - if (NS_SUCCEEDED(rv) && selected) - { - NS_ConvertUCS2toUTF8 utf8Args(info->GetArguments()); - rv = reg->SelectSkin(utf8Args, PR_TRUE); + // We either have an old-style theme with no theme.rdf + // manifest, OR we have a new style theme and InstallTheme + // returned an error (e.g. it's not implemented in Seamonkey, + // or something else went wrong) + if (!installed) + rv = reg->InstallSkin(spec.get(), PR_TRUE, PR_FALSE); + +#ifndef MOZ_XUL_APP + if (NS_SUCCEEDED(rv) && selected && cr) + { + NS_ConvertUCS2toUTF8 utf8Args(info->GetArguments()); + rv = cr->SelectSkin(utf8Args, PR_TRUE); + } +#endif } - } - if ( isLocale ) - { - rv = reg->InstallLocale(spec.get(), PR_TRUE); - - if (NS_SUCCEEDED(rv) && selected) + if ( isLocale ) { - NS_ConvertUCS2toUTF8 utf8Args(info->GetArguments()); - rv = reg->SelectLocale(utf8Args, PR_TRUE); - } - } + rv = reg->InstallLocale(spec.get(), PR_TRUE); - // now that all types are registered try to activate - if ( isSkin && selected ) - reg->RefreshSkins(); +#ifndef MOZ_XUL_APP + if (NS_SUCCEEDED(rv) && selected && cr) + { + NS_ConvertUCS2toUTF8 utf8Args(info->GetArguments()); + rv = cr->SelectLocale(utf8Args, PR_TRUE); + } +#endif + } + + // now that all types are registered try to activate + if ( isSkin && selected ) + reg->RefreshSkins(); #ifdef RELOAD_CHROME_WORKS // XXX ReloadChrome() crashes right now if ( isContent || (isLocale && selected) ) reg->ReloadChrome(); #endif -#endif + } } if (listener)