зеркало из https://github.com/mozilla/gecko-dev.git
3344 строки
110 KiB
C++
3344 строки
110 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.1 (the "License"); you may not use this file except in
|
|
* compliance with the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Netscape Communications Corporation.
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Original Author: David W. Hyatt (hyatt@netscape.com)
|
|
* Gagan Saksena <gagan@netscape.com>
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* 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 NPL, 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 NPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
/* build on macs with low memory */
|
|
#if defined(XP_MAC) && defined(MOZ_MAC_LOWMEM)
|
|
#pragma optimization_level 1
|
|
#endif
|
|
|
|
#include <string.h>
|
|
#include "nsCOMPtr.h"
|
|
#include "nsIFileSpec.h"
|
|
#include "nsSpecialSystemDirectory.h"
|
|
#include "nsIChromeRegistry.h"
|
|
#include "nsChromeRegistry.h"
|
|
#include "nsChromeUIDataSource.h"
|
|
#include "nsIRDFDataSource.h"
|
|
#include "nsIRDFObserver.h"
|
|
#include "nsIRDFRemoteDataSource.h"
|
|
#include "nsIRDFXMLSink.h"
|
|
#include "nsCRT.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 "nsIStringBundle.h"
|
|
#include "nsISimpleEnumerator.h"
|
|
#include "nsNetUtil.h"
|
|
#include "nsIFileChannel.h"
|
|
#include "nsIXBLService.h"
|
|
#include "nsPIDOMWindow.h"
|
|
#include "nsIDOMWindowInternal.h"
|
|
#include "nsIDOMWindowCollection.h"
|
|
#include "nsIDOMLocation.h"
|
|
#include "nsIWindowMediator.h"
|
|
#include "nsIDocument.h"
|
|
#include "nsIDOMDocument.h"
|
|
#include "nsIXULPrototypeCache.h"
|
|
#include "nsIStyleSheet.h"
|
|
#include "nsIHTMLCSSStyleSheet.h"
|
|
#include "nsIHTMLStyleSheet.h"
|
|
#include "nsIHTMLContentContainer.h"
|
|
#include "nsIPresShell.h"
|
|
#include "nsIDocShell.h"
|
|
#include "nsIStyleSet.h"
|
|
#include "nsISupportsArray.h"
|
|
#include "nsICSSLoader.h"
|
|
#include "nsIDocumentObserver.h"
|
|
#include "nsIXULDocument.h"
|
|
#include "nsINameSpaceManager.h"
|
|
#include "nsIIOService.h"
|
|
#include "nsIResProtocolHandler.h"
|
|
#include "nsLayoutCID.h"
|
|
#include "nsGfxCIID.h"
|
|
#include "nsIBindingManager.h"
|
|
#include "prio.h"
|
|
#include "nsInt64.h"
|
|
#include "nsIDirectoryService.h"
|
|
#include "nsAppDirectoryServiceDefs.h"
|
|
#include "nsIPref.h"
|
|
#include "nsIObserverService.h"
|
|
#include "nsIDOMElement.h"
|
|
#include "nsIChromeEventHandler.h"
|
|
#include "nsIContent.h"
|
|
#include "nsIDOMWindowCollection.h"
|
|
#include "imgICache.h"
|
|
|
|
static char kChromePrefix[] = "chrome://";
|
|
static char kChromeFileName[] = "chrome.rdf";
|
|
static char kInstalledChromeFileName[] = "installed-chrome.txt";
|
|
static char kUseXBLFormsPref[] = "nglayout.debug.enable_xbl_forms";
|
|
|
|
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(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
|
|
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
|
|
|
|
class nsChromeRegistry;
|
|
|
|
#define CHROME_URI "http://www.mozilla.org/rdf/chrome#"
|
|
|
|
DEFINE_RDF_VOCAB(CHROME_URI, CHROME, selectedSkin);
|
|
DEFINE_RDF_VOCAB(CHROME_URI, CHROME, selectedLocale);
|
|
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, skinVersion);
|
|
DEFINE_RDF_VOCAB(CHROME_URI, CHROME, localeVersion);
|
|
DEFINE_RDF_VOCAB(CHROME_URI, CHROME, packageVersion);
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
class nsOverlayEnumerator : public nsISimpleEnumerator
|
|
{
|
|
public:
|
|
NS_DECL_ISUPPORTS
|
|
NS_DECL_NSISIMPLEENUMERATOR
|
|
|
|
nsOverlayEnumerator(nsISimpleEnumerator *aInstallArcs,
|
|
nsISimpleEnumerator *aProfileArcs);
|
|
virtual ~nsOverlayEnumerator();
|
|
|
|
private:
|
|
nsCOMPtr<nsISimpleEnumerator> mInstallArcs;
|
|
nsCOMPtr<nsISimpleEnumerator> mProfileArcs;
|
|
nsCOMPtr<nsISimpleEnumerator> mCurrentArcs;
|
|
};
|
|
|
|
NS_IMPL_ISUPPORTS1(nsOverlayEnumerator, nsISimpleEnumerator)
|
|
|
|
nsOverlayEnumerator::nsOverlayEnumerator(nsISimpleEnumerator *aInstallArcs,
|
|
nsISimpleEnumerator *aProfileArcs)
|
|
{
|
|
NS_INIT_REFCNT();
|
|
mInstallArcs = aInstallArcs;
|
|
mProfileArcs = aProfileArcs;
|
|
mCurrentArcs = mInstallArcs;
|
|
}
|
|
|
|
nsOverlayEnumerator::~nsOverlayEnumerator()
|
|
{
|
|
}
|
|
|
|
NS_IMETHODIMP nsOverlayEnumerator::HasMoreElements(PRBool *aIsTrue)
|
|
{
|
|
*aIsTrue = PR_FALSE;
|
|
if (!mProfileArcs) {
|
|
if (!mInstallArcs)
|
|
return NS_OK; // No arcs period. We default to false,
|
|
return mInstallArcs->HasMoreElements(aIsTrue); // no profile arcs. use install arcs,
|
|
}
|
|
|
|
nsresult rv = mProfileArcs->HasMoreElements(aIsTrue);
|
|
if (*aIsTrue || !mInstallArcs)
|
|
return rv;
|
|
|
|
return mInstallArcs->HasMoreElements(aIsTrue);
|
|
}
|
|
|
|
NS_IMETHODIMP nsOverlayEnumerator::GetNext(nsISupports **aResult)
|
|
{
|
|
nsresult rv;
|
|
*aResult = nsnull;
|
|
|
|
if (!mCurrentArcs) {
|
|
mCurrentArcs = mInstallArcs;
|
|
if (!mCurrentArcs)
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
else if (mCurrentArcs == mProfileArcs) {
|
|
PRBool hasMore;
|
|
rv = mCurrentArcs->HasMoreElements(&hasMore);
|
|
if (NS_FAILED(rv)) return rv;
|
|
if (!hasMore)
|
|
mCurrentArcs = mInstallArcs;
|
|
if (!mInstallArcs)
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
nsCOMPtr<nsISupports> supports;
|
|
rv = mCurrentArcs->GetNext(getter_AddRefs(supports));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
nsCOMPtr<nsIRDFLiteral> value = do_QueryInterface(supports, &rv);
|
|
if (NS_FAILED(rv))
|
|
return NS_OK;
|
|
|
|
const PRUnichar* valueStr;
|
|
rv = value->GetValueConst(&valueStr);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
nsCOMPtr<nsIURI> url;
|
|
rv = NS_NewURI(getter_AddRefs(url), NS_LossyConvertUCS2toASCII(valueStr).get());
|
|
|
|
if (NS_FAILED(rv))
|
|
return NS_OK;
|
|
|
|
nsCOMPtr<nsISupports> sup;
|
|
sup = do_QueryInterface(url, &rv);
|
|
if (NS_FAILED(rv))
|
|
return NS_OK;
|
|
|
|
*aResult = sup;
|
|
NS_ADDREF(*aResult);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
nsChromeRegistry::nsChromeRegistry()
|
|
{
|
|
NS_INIT_REFCNT();
|
|
|
|
mInstallInitialized = PR_FALSE;
|
|
mProfileInitialized = PR_FALSE;
|
|
|
|
mUseXBLForms = PR_FALSE;
|
|
mBatchInstallFlushes = PR_FALSE;
|
|
|
|
nsCOMPtr<nsIPref> prefService(do_GetService(kPrefServiceCID));
|
|
if (prefService)
|
|
prefService->GetBoolPref(kUseXBLFormsPref, &mUseXBLForms);
|
|
|
|
mDataSourceTable = nsnull;
|
|
}
|
|
|
|
|
|
static PRBool PR_CALLBACK DatasourceEnumerator(nsHashKey *aKey, void *aData, void* closure)
|
|
{
|
|
if (!closure || !aData)
|
|
return PR_FALSE;
|
|
|
|
nsIRDFCompositeDataSource* compositeDS = (nsIRDFCompositeDataSource*) closure;
|
|
|
|
nsCOMPtr<nsISupports> supports = (nsISupports*)aData;
|
|
|
|
nsCOMPtr<nsIRDFDataSource> dataSource = do_QueryInterface(supports);
|
|
if (!dataSource)
|
|
return PR_FALSE;
|
|
|
|
nsresult rv = compositeDS->RemoveDataSource(dataSource);
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to RemoveDataSource");
|
|
return PR_TRUE;
|
|
}
|
|
|
|
|
|
nsChromeRegistry::~nsChromeRegistry()
|
|
{
|
|
if (mDataSourceTable) {
|
|
mDataSourceTable->Enumerate(DatasourceEnumerator, mChromeDataSource);
|
|
delete mDataSourceTable;
|
|
}
|
|
|
|
if (mRDFService) {
|
|
nsServiceManager::ReleaseService(kRDFServiceCID, mRDFService);
|
|
mRDFService = nsnull;
|
|
}
|
|
|
|
if (mRDFContainerUtils) {
|
|
nsServiceManager::ReleaseService(kRDFContainerUtilsCID, mRDFContainerUtils);
|
|
mRDFContainerUtils = nsnull;
|
|
}
|
|
|
|
}
|
|
|
|
NS_IMPL_THREADSAFE_ISUPPORTS3(nsChromeRegistry, nsIChromeRegistry, nsIObserver, nsISupportsWeakReference);
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// nsIChromeRegistry methods:
|
|
|
|
nsresult
|
|
nsChromeRegistry::Init()
|
|
{
|
|
nsresult rv;
|
|
rv = nsServiceManager::GetService(kRDFServiceCID,
|
|
NS_GET_IID(nsIRDFService),
|
|
(nsISupports**)&mRDFService);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = nsServiceManager::GetService(kRDFContainerUtilsCID,
|
|
NS_GET_IID(nsIRDFContainerUtils),
|
|
(nsISupports**)&mRDFContainerUtils);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = mRDFService->GetResource(kURICHROME_selectedSkin, getter_AddRefs(mSelectedSkin));
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF resource");
|
|
|
|
rv = mRDFService->GetResource(kURICHROME_selectedLocale, getter_AddRefs(mSelectedLocale));
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF resource");
|
|
|
|
rv = mRDFService->GetResource(kURICHROME_baseURL, getter_AddRefs(mBaseURL));
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF resource");
|
|
|
|
rv = mRDFService->GetResource(kURICHROME_packages, getter_AddRefs(mPackages));
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF resource");
|
|
|
|
rv = mRDFService->GetResource(kURICHROME_package, getter_AddRefs(mPackage));
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF resource");
|
|
|
|
rv = mRDFService->GetResource(kURICHROME_name, getter_AddRefs(mName));
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF resource");
|
|
|
|
rv = mRDFService->GetResource(kURICHROME_image, getter_AddRefs(mImage));
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF resource");
|
|
|
|
rv = mRDFService->GetResource(kURICHROME_locType, getter_AddRefs(mLocType));
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF resource");
|
|
|
|
rv = mRDFService->GetResource(kURICHROME_allowScripts, getter_AddRefs(mAllowScripts));
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF resource");
|
|
|
|
rv = mRDFService->GetResource(kURICHROME_skinVersion, getter_AddRefs(mSkinVersion));
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF resource");
|
|
|
|
rv = mRDFService->GetResource(kURICHROME_localeVersion, getter_AddRefs(mLocaleVersion));
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF resource");
|
|
|
|
rv = mRDFService->GetResource(kURICHROME_packageVersion, getter_AddRefs(mPackageVersion));
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF resource");
|
|
|
|
nsCOMPtr<nsIObserverService> observerService =
|
|
do_GetService("@mozilla.org/observer-service;1", &rv);
|
|
if (observerService) {
|
|
observerService->AddObserver(this, "profile-before-change", PR_TRUE);
|
|
observerService->AddObserver(this, "profile-after-change", PR_TRUE);
|
|
}
|
|
|
|
CheckForNewChrome();
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
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;
|
|
|
|
nsXPIDLCString str;
|
|
rv = aChromeURI->GetSpec(getter_Copies(str));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
if (!str.get())
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
// 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, kChromePrefix, sizeof(kChromePrefix) - 1) != 0)
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
// Cull out the "package" string; e.g., "navigator"
|
|
aPackage = str.get() + sizeof(kChromePrefix) - 1;
|
|
|
|
PRInt32 idx;
|
|
idx = aPackage.FindChar('/');
|
|
if (idx < 0)
|
|
return NS_OK;
|
|
|
|
// Cull out the "provider" string; e.g., "content"
|
|
aPackage.Right(aProvider, aPackage.Length() - (idx + 1));
|
|
aPackage.Truncate(idx);
|
|
|
|
idx = aProvider.FindChar('/');
|
|
if (idx < 0) {
|
|
// Force the provider to end with a '/'
|
|
idx = aProvider.Length();
|
|
aProvider.Append('/');
|
|
}
|
|
|
|
// Cull out the "file"; e.g., "navigator.xul"
|
|
aProvider.Right(aFile, aProvider.Length() - (idx + 1));
|
|
aProvider.Truncate(idx);
|
|
|
|
PRBool nofile = (aFile.Length() == 0);
|
|
if (nofile) {
|
|
// If there is no file, then construct the default file
|
|
aFile = aPackage;
|
|
|
|
if (aProvider.Equals("content")) {
|
|
aFile += ".xul";
|
|
}
|
|
else if (aProvider.Equals("skin")) {
|
|
aFile += ".css";
|
|
}
|
|
else if (aProvider.Equals("locale")) {
|
|
aFile += ".dtd";
|
|
}
|
|
else {
|
|
NS_ERROR("unknown provider");
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
} 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::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;
|
|
rv = SplitURL(aChromeURI, package, provider, file, &modified);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
if (!modified)
|
|
return NS_OK;
|
|
|
|
nsCAutoString canonical( kChromePrefix );
|
|
canonical += package;
|
|
canonical += "/";
|
|
canonical += provider;
|
|
canonical += "/";
|
|
canonical += file;
|
|
|
|
return aChromeURI->SetSpec(canonical.get());
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsChromeRegistry::ConvertChromeURL(nsIURI* aChromeURL, char** aResult)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
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
|
|
// aChromeURL
|
|
|
|
// 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);
|
|
#ifdef DEBUG
|
|
if (NS_FAILED(rv)) {
|
|
nsCAutoString msg("chrome: failed to get base url");
|
|
nsXPIDLCString url;
|
|
rv = aChromeURL->GetSpec(getter_Copies(url));
|
|
if (NS_SUCCEEDED(rv)) {
|
|
msg += " for ";
|
|
msg += (const char*)url;
|
|
}
|
|
msg += " -- using wacky default";
|
|
NS_WARNING(msg.get());
|
|
}
|
|
#endif
|
|
if (finalURL.IsEmpty()) {
|
|
// hard-coded fallback
|
|
if (provider.Equals("skin")) {
|
|
finalURL = "resource:/chrome/skins/classic/";
|
|
}
|
|
else if (provider.Equals("locale")) {
|
|
finalURL = "resource:/chrome/locales/en-US/";
|
|
}
|
|
else if (package.Equals("aim")) {
|
|
finalURL = "resource:/chrome/packages/aim/";
|
|
}
|
|
else if (package.Equals("messenger")) {
|
|
finalURL = "resource:/chrome/packages/messenger/";
|
|
}
|
|
else if (package.Equals("global")) {
|
|
finalURL = "resource:/chrome/packages/widget-toolkit/";
|
|
}
|
|
else {
|
|
finalURL = "resource:/chrome/packages/core/";
|
|
}
|
|
}
|
|
|
|
*aResult = ToNewCString(finalURL + remaining);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsChromeRegistry::GetBaseURL(const nsCString& aPackage, const nsCString& aProvider,
|
|
nsCString& aBaseURL)
|
|
{
|
|
nsCOMPtr<nsIRDFResource> resource;
|
|
|
|
nsCAutoString resourceStr("urn:mozilla:package:");
|
|
resourceStr += aPackage;
|
|
|
|
// Obtain the resource.
|
|
nsresult rv = NS_OK;
|
|
nsCOMPtr<nsIRDFResource> packageResource;
|
|
rv = GetResource(resourceStr, getter_AddRefs(packageResource));
|
|
if (NS_FAILED(rv)) {
|
|
NS_ERROR("Unable to obtain the package resource.");
|
|
return rv;
|
|
}
|
|
|
|
// Follow the "selectedSkin" or "selectedLocale" arc.
|
|
nsCOMPtr<nsIRDFResource> arc;
|
|
if (aProvider.Equals(nsCAutoString("skin"))) {
|
|
arc = mSelectedSkin;
|
|
}
|
|
else if (aProvider.Equals(nsCAutoString("locale"))) {
|
|
arc = mSelectedLocale;
|
|
}
|
|
else
|
|
// We're a package.
|
|
resource = packageResource;
|
|
|
|
if (arc) {
|
|
|
|
nsCOMPtr<nsIRDFNode> selectedProvider;
|
|
if (NS_FAILED(rv = mChromeDataSource->GetTarget(packageResource, arc, PR_TRUE, getter_AddRefs(selectedProvider)))) {
|
|
NS_ERROR("Unable to obtain the provider.");
|
|
return rv;
|
|
}
|
|
|
|
resource = do_QueryInterface(selectedProvider);
|
|
|
|
if (resource) {
|
|
// We found a selected provider, but now we need to verify that the version
|
|
// specified by the package and the version specified by the provider are
|
|
// one and the same. If they aren't, then we cannot use this provider.
|
|
nsCOMPtr<nsIRDFResource> versionArc;
|
|
if (arc == mSelectedSkin)
|
|
versionArc = mSkinVersion;
|
|
else // Locale arc
|
|
versionArc = mLocaleVersion;
|
|
|
|
nsCAutoString packageVersion;
|
|
nsChromeRegistry::FollowArc(mChromeDataSource, packageVersion, packageResource, versionArc);
|
|
if (!packageVersion.IsEmpty()) {
|
|
// The package only wants providers (skins) that say they can work with it. Let's find out
|
|
// if our provider (skin) can work with it.
|
|
nsCAutoString providerVersion;
|
|
nsChromeRegistry::FollowArc(mChromeDataSource, providerVersion, resource, versionArc);
|
|
if (!providerVersion.Equals(packageVersion))
|
|
selectedProvider = nsnull;
|
|
}
|
|
}
|
|
|
|
if (!selectedProvider) {
|
|
// Find provider will attempt to auto-select a version-compatible provider (skin). If none
|
|
// exist it will return nsnull in the selectedProvider variable.
|
|
FindProvider(aPackage, aProvider, arc, getter_AddRefs(selectedProvider));
|
|
resource = do_QueryInterface(selectedProvider);
|
|
}
|
|
|
|
if (!selectedProvider)
|
|
return rv;
|
|
|
|
if (!resource)
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
// From this resource, follow the "baseURL" arc.
|
|
return nsChromeRegistry::FollowArc(mChromeDataSource,
|
|
aBaseURL,
|
|
resource,
|
|
mBaseURL);
|
|
}
|
|
|
|
// locate
|
|
NS_IMETHODIMP
|
|
nsChromeRegistry::FindProvider(const nsCString& aPackage,
|
|
const nsCString& aProvider,
|
|
nsIRDFResource *aArc,
|
|
nsIRDFNode **aSelectedProvider)
|
|
{
|
|
*aSelectedProvider = nsnull;
|
|
|
|
nsCAutoString rootStr("urn:mozilla:");
|
|
nsresult rv = NS_OK;
|
|
|
|
rootStr += aProvider;
|
|
rootStr += ":root";
|
|
|
|
// obtain the provider root resource
|
|
nsCOMPtr<nsIRDFResource> resource;
|
|
rv = GetResource(rootStr, getter_AddRefs(resource));
|
|
if (NS_FAILED(rv)) {
|
|
NS_ERROR("Unable to obtain the provider root resource.");
|
|
return rv;
|
|
}
|
|
|
|
// wrap it in a container
|
|
nsCOMPtr<nsIRDFContainer> container;
|
|
rv = nsComponentManager::CreateInstance("@mozilla.org/rdf/container;1",
|
|
nsnull,
|
|
NS_GET_IID(nsIRDFContainer),
|
|
getter_AddRefs(container));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
rv = container->Init(mChromeDataSource, resource);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
// step through its (seq) arcs
|
|
nsCOMPtr<nsISimpleEnumerator> 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;
|
|
for ( ; moreElements; arcs->HasMoreElements(&moreElements)) {
|
|
|
|
// get next arc resource
|
|
nsCOMPtr<nsISupports> supports;
|
|
rv = arcs->GetNext(getter_AddRefs(supports));
|
|
if (NS_FAILED(rv)) return rv;
|
|
nsCOMPtr<nsIRDFResource> kid = do_QueryInterface(supports);
|
|
|
|
if (kid) {
|
|
// get its name
|
|
nsCAutoString providerName;
|
|
rv = nsChromeRegistry::FollowArc(mChromeDataSource, providerName, kid, mName);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
// get its package list
|
|
nsCOMPtr<nsIRDFNode> packageNode;
|
|
nsCOMPtr<nsIRDFResource> packageList;
|
|
rv = mChromeDataSource->GetTarget(kid, mPackages, PR_TRUE, getter_AddRefs(packageNode));
|
|
if (NS_SUCCEEDED(rv))
|
|
packageList = do_QueryInterface(packageNode);
|
|
if (!packageList)
|
|
continue;
|
|
|
|
// if aPackage is named in kid's package list, select it and we're done
|
|
rv = SelectPackageInProvider(packageList, aPackage, aProvider, providerName,
|
|
aArc, aSelectedProvider);
|
|
if (NS_FAILED(rv))
|
|
continue; // Don't let this be disastrous. We may find another acceptable match.
|
|
|
|
if (*aSelectedProvider)
|
|
return NS_OK;
|
|
}
|
|
}
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsChromeRegistry::SelectPackageInProvider(nsIRDFResource *aPackageList,
|
|
const nsCString& aPackage,
|
|
const nsCString& aProvider,
|
|
const nsCString& aProviderName,
|
|
nsIRDFResource *aArc,
|
|
nsIRDFNode **aSelectedProvider)
|
|
{
|
|
*aSelectedProvider = nsnull;
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
// wrap aPackageList in a container
|
|
nsCOMPtr<nsIRDFContainer> container;
|
|
rv = nsComponentManager::CreateInstance("@mozilla.org/rdf/container;1",
|
|
nsnull,
|
|
NS_GET_IID(nsIRDFContainer),
|
|
getter_AddRefs(container));
|
|
if (NS_SUCCEEDED(rv))
|
|
rv = container->Init(mChromeDataSource, aPackageList);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
// step through its (seq) arcs
|
|
nsCOMPtr<nsISimpleEnumerator> 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;
|
|
for ( ; moreElements; arcs->HasMoreElements(&moreElements)) {
|
|
|
|
// get next arc resource
|
|
nsCOMPtr<nsISupports> supports;
|
|
rv = arcs->GetNext(getter_AddRefs(supports));
|
|
if (NS_FAILED(rv)) return rv;
|
|
nsCOMPtr<nsIRDFResource> kid = do_QueryInterface(supports);
|
|
|
|
if (kid) {
|
|
// get its package resource
|
|
nsCOMPtr<nsIRDFNode> packageNode;
|
|
nsCOMPtr<nsIRDFResource> package;
|
|
rv = mChromeDataSource->GetTarget(kid, mPackage, PR_TRUE, getter_AddRefs(packageNode));
|
|
if (NS_SUCCEEDED(rv))
|
|
package = do_QueryInterface(packageNode);
|
|
if (!package)
|
|
continue;
|
|
|
|
// get its name
|
|
nsCAutoString packageName;
|
|
rv = nsChromeRegistry::FollowArc(mChromeDataSource, packageName, package, mName);
|
|
if (NS_FAILED(rv))
|
|
continue; // don't fail if package has not yet been installed
|
|
|
|
if (packageName.Equals(aPackage)) {
|
|
PRBool useProfile = !mProfileRoot.IsEmpty();
|
|
if (packageName.Equals("global") || packageName.Equals("communicator"))
|
|
useProfile = PR_FALSE; // Always force the auto-selection to be in the
|
|
// install dir for the packages required to bring up the profile UI.
|
|
rv = SelectProviderForPackage(aProvider,
|
|
NS_ConvertASCIItoUCS2(aProviderName).get(),
|
|
NS_ConvertASCIItoUCS2(packageName).get(),
|
|
aArc, useProfile, PR_TRUE);
|
|
if (NS_FAILED(rv))
|
|
return NS_ERROR_FAILURE;
|
|
|
|
*aSelectedProvider = kid;
|
|
NS_ADDREF(*aSelectedProvider);
|
|
return NS_OK;
|
|
}
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::GetDynamicDataSource(nsIURI *aChromeURL, PRBool aIsOverlay, PRBool aUseProfile,
|
|
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);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
// 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::GetStyleSheets(nsIURI *aChromeURL, nsISupportsArray **aResult)
|
|
{
|
|
*aResult = nsnull;
|
|
|
|
nsCOMPtr<nsISimpleEnumerator> sheets;
|
|
nsresult rv = GetDynamicInfo(aChromeURL, PR_FALSE, getter_AddRefs(sheets));
|
|
if (NS_FAILED(rv)) return rv;
|
|
PRBool hasMore;
|
|
rv = sheets->HasMoreElements(&hasMore);
|
|
if (NS_FAILED(rv)) return rv;
|
|
while (hasMore) {
|
|
if (!*aResult) {
|
|
rv = NS_NewISupportsArray(aResult);
|
|
if (NS_FAILED(rv)) return rv;
|
|
}
|
|
|
|
nsCOMPtr<nsISupports> supp;
|
|
rv = sheets->GetNext(getter_AddRefs(supp));
|
|
if (NS_FAILED(rv)) return rv;
|
|
nsCOMPtr<nsIURL> url(do_QueryInterface(supp));
|
|
if (url) {
|
|
nsCOMPtr<nsICSSStyleSheet> sheet;
|
|
nsXPIDLCString str;
|
|
rv = url->GetSpec(getter_Copies(str));
|
|
if (NS_FAILED(rv)) return rv;
|
|
rv = LoadStyleSheet(getter_AddRefs(sheet), nsCAutoString(str));
|
|
if (NS_FAILED(rv)) return rv;
|
|
rv = (*aResult)->AppendElement(sheet) ? NS_OK : NS_ERROR_FAILURE;
|
|
if (NS_FAILED(rv)) return rv;
|
|
}
|
|
sheets->HasMoreElements(&hasMore);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::GetOverlays(nsIURI *aChromeURL, nsISimpleEnumerator **aResult)
|
|
{
|
|
return GetDynamicInfo(aChromeURL, PR_TRUE, aResult);
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::GetDynamicInfo(nsIURI *aChromeURL, PRBool aIsOverlay, nsISimpleEnumerator **aResult)
|
|
{
|
|
*aResult = nsnull;
|
|
|
|
nsresult rv;
|
|
|
|
if (!mDataSourceTable)
|
|
return NS_OK;
|
|
|
|
nsCOMPtr<nsIRDFDataSource> installSource;
|
|
rv = GetDynamicDataSource(aChromeURL, aIsOverlay, PR_FALSE, getter_AddRefs(installSource));
|
|
if (NS_FAILED(rv)) return rv;
|
|
nsCOMPtr<nsIRDFDataSource> profileSource;
|
|
if (mProfileInitialized) {
|
|
rv = GetDynamicDataSource(aChromeURL, aIsOverlay, PR_TRUE, getter_AddRefs(profileSource));
|
|
if (NS_FAILED(rv)) return rv;
|
|
}
|
|
|
|
nsXPIDLCString lookup;
|
|
rv = aChromeURL->GetSpec(getter_Copies(lookup));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
// Get the chromeResource from this lookup string
|
|
nsCOMPtr<nsIRDFResource> chromeResource;
|
|
rv = GetResource(nsCAutoString(lookup), getter_AddRefs(chromeResource));
|
|
if (NS_FAILED(rv)) {
|
|
NS_ERROR("Unable to retrieve the resource corresponding to the chrome skin or content.");
|
|
return rv;
|
|
}
|
|
|
|
nsCOMPtr<nsISimpleEnumerator> installArcs;
|
|
nsCOMPtr<nsISimpleEnumerator> profileArcs;
|
|
|
|
if (installSource)
|
|
{
|
|
nsCOMPtr<nsIRDFContainer> container;
|
|
rv = nsComponentManager::CreateInstance("@mozilla.org/rdf/container;1",
|
|
nsnull,
|
|
NS_GET_IID(nsIRDFContainer),
|
|
getter_AddRefs(container));
|
|
if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(container->Init(installSource, chromeResource)))
|
|
rv = container->GetElements(getter_AddRefs(installArcs));
|
|
if (NS_FAILED(rv)) return rv;
|
|
}
|
|
|
|
if (profileSource)
|
|
{
|
|
nsCOMPtr<nsIRDFContainer> container;
|
|
rv = nsComponentManager::CreateInstance("@mozilla.org/rdf/container;1",
|
|
nsnull,
|
|
NS_GET_IID(nsIRDFContainer),
|
|
getter_AddRefs(container));
|
|
if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(container->Init(profileSource, chromeResource)))
|
|
rv = container->GetElements(getter_AddRefs(profileArcs));
|
|
if (NS_FAILED(rv)) return rv;
|
|
}
|
|
|
|
|
|
*aResult = new nsOverlayEnumerator(installArcs, profileArcs);
|
|
NS_ADDREF(*aResult);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP 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<nsISupports> supports =
|
|
getter_AddRefs(NS_STATIC_CAST(nsISupports*, mDataSourceTable->Get(&skey)));
|
|
|
|
if (supports)
|
|
{
|
|
nsCOMPtr<nsIRDFDataSource> dataSource = do_QueryInterface(supports);
|
|
if (dataSource)
|
|
{
|
|
*aResult = dataSource;
|
|
NS_ADDREF(*aResult);
|
|
return NS_OK;
|
|
}
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
}
|
|
|
|
nsresult rv = nsComponentManager::CreateInstance(kRDFXMLDataSourceCID,
|
|
nsnull,
|
|
NS_GET_IID(nsIRDFDataSource),
|
|
(void**) aResult);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
// Seed the datasource with the ``chrome'' namespace
|
|
nsCOMPtr<nsIRDFXMLSink> sink = do_QueryInterface(*aResult);
|
|
if (sink) {
|
|
nsCOMPtr<nsIAtom> prefix = getter_AddRefs(NS_NewAtom("c"));
|
|
sink->AddNameSpace(prefix, NS_ConvertASCIItoUCS2(CHROME_URI));
|
|
}
|
|
|
|
nsCOMPtr<nsIRDFRemoteDataSource> 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<nsISupports> supports = do_QueryInterface(remote);
|
|
nsCStringKey skey(key);
|
|
mDataSourceTable->Put(&skey, supports.get());
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
nsresult
|
|
nsChromeRegistry::GetResource(const nsCString& aURL,
|
|
nsIRDFResource** aResult)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
if (NS_FAILED(rv = mRDFService->GetResource(aURL.get(), aResult))) {
|
|
NS_ERROR("Unable to retrieve a resource for this URL.");
|
|
*aResult = nsnull;
|
|
return rv;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsChromeRegistry::FollowArc(nsIRDFDataSource *aDataSource,
|
|
nsCString& aResult,
|
|
nsIRDFResource* aChromeResource,
|
|
nsIRDFResource* aProperty)
|
|
{
|
|
if (!aDataSource)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIRDFNode> 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<nsIRDFResource> 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<nsIRDFLiteral> literal(do_QueryInterface(chromeBase));
|
|
if (literal) {
|
|
const PRUnichar *s;
|
|
rv = literal->GetValueConst(&s);
|
|
if (NS_FAILED(rv)) return rv;
|
|
aResult.AssignWithConversion(s);
|
|
}
|
|
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<nsIRDFNode> 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;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// theme stuff
|
|
|
|
|
|
static void FlushSkinBindingsForWindow(nsIDOMWindowInternal* aWindow)
|
|
{
|
|
// Get the DOM document.
|
|
nsCOMPtr<nsIDOMDocument> domDocument;
|
|
aWindow->GetDocument(getter_AddRefs(domDocument));
|
|
if (!domDocument)
|
|
return;
|
|
|
|
nsCOMPtr<nsIDocument> document = do_QueryInterface(domDocument);
|
|
if (!document)
|
|
return;
|
|
|
|
// Annihilate all XBL bindings.
|
|
nsCOMPtr<nsIBindingManager> bindingManager;
|
|
document->GetBindingManager(getter_AddRefs(bindingManager));
|
|
bindingManager->FlushSkinBindings();
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::RefreshSkins()
|
|
{
|
|
nsCOMPtr<nsIWindowMediator> windowMediator(do_GetService(kWindowMediatorCID));
|
|
if (!windowMediator)
|
|
return NS_OK;
|
|
|
|
nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
|
|
windowMediator->GetEnumerator(nsnull, getter_AddRefs(windowEnumerator));
|
|
PRBool more;
|
|
windowEnumerator->HasMoreElements(&more);
|
|
while (more) {
|
|
nsCOMPtr<nsISupports> protoWindow;
|
|
windowEnumerator->GetNext(getter_AddRefs(protoWindow));
|
|
if (protoWindow) {
|
|
nsCOMPtr<nsIDOMWindowInternal> domWindow = do_QueryInterface(protoWindow);
|
|
if (domWindow)
|
|
FlushSkinBindingsForWindow(domWindow);
|
|
}
|
|
windowEnumerator->HasMoreElements(&more);
|
|
}
|
|
|
|
FlushCaches();
|
|
|
|
windowMediator->GetEnumerator(nsnull, getter_AddRefs(windowEnumerator));
|
|
windowEnumerator->HasMoreElements(&more);
|
|
while (more) {
|
|
nsCOMPtr<nsISupports> protoWindow;
|
|
windowEnumerator->GetNext(getter_AddRefs(protoWindow));
|
|
if (protoWindow) {
|
|
nsCOMPtr<nsIDOMWindowInternal> domWindow = do_QueryInterface(protoWindow);
|
|
if (domWindow)
|
|
RefreshWindow(domWindow);
|
|
}
|
|
windowEnumerator->HasMoreElements(&more);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
nsresult nsChromeRegistry::FlushCaches()
|
|
{
|
|
nsresult rv;
|
|
|
|
// Flush the style sheet cache completely.
|
|
nsCOMPtr<nsIXULPrototypeCache> xulCache =
|
|
do_GetService("@mozilla.org/xul/xul-prototype-cache;1", &rv);
|
|
if (NS_SUCCEEDED(rv) && xulCache)
|
|
xulCache->FlushSkinFiles();
|
|
|
|
// Flush the new imagelib image chrome cache.
|
|
nsCOMPtr<imgICache> imageCache(do_GetService("@mozilla.org/image/cache;1", &rv));
|
|
if (NS_SUCCEEDED(rv) && imageCache) {
|
|
imageCache->ClearCache(PR_TRUE);
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
static PRBool IsChromeURI(nsIURI* aURI)
|
|
{
|
|
PRBool isChrome=PR_FALSE;
|
|
if (NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)) && isChrome)
|
|
return PR_TRUE;
|
|
return PR_FALSE;
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::RefreshWindow(nsIDOMWindowInternal* aWindow)
|
|
{
|
|
// Deal with our subframes first.
|
|
nsCOMPtr<nsIDOMWindowCollection> frames;
|
|
aWindow->GetFrames(getter_AddRefs(frames));
|
|
PRUint32 length;
|
|
frames->GetLength(&length);
|
|
for (PRUint32 i = 0; i < length; i++) {
|
|
nsCOMPtr<nsIDOMWindow> childWin;
|
|
frames->Item(i, getter_AddRefs(childWin));
|
|
nsCOMPtr<nsIDOMWindowInternal> childInt(do_QueryInterface(childWin));
|
|
RefreshWindow(childInt);
|
|
}
|
|
|
|
nsresult rv;
|
|
// Get the DOM document.
|
|
nsCOMPtr<nsIDOMDocument> domDocument;
|
|
aWindow->GetDocument(getter_AddRefs(domDocument));
|
|
if (!domDocument)
|
|
return NS_OK;
|
|
|
|
nsCOMPtr<nsIDocument> document = do_QueryInterface(domDocument);
|
|
if (!document)
|
|
return NS_OK;
|
|
|
|
// Deal with the agent sheets first.
|
|
PRInt32 shellCount = document->GetNumberOfShells();
|
|
for (PRInt32 k = 0; k < shellCount; k++) {
|
|
nsCOMPtr<nsIPresShell> shell;
|
|
document->GetShellAt(k, getter_AddRefs(shell));
|
|
if (shell) {
|
|
nsCOMPtr<nsIStyleSet> styleSet;
|
|
rv = shell->GetStyleSet(getter_AddRefs(styleSet));
|
|
if (NS_FAILED(rv)) return rv;
|
|
if (styleSet) {
|
|
// Reload only the chrome URL agent style sheets.
|
|
nsCOMPtr<nsISupportsArray> agents;
|
|
rv = NS_NewISupportsArray(getter_AddRefs(agents));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
nsCOMPtr<nsISupportsArray> newAgentSheets;
|
|
rv = NS_NewISupportsArray(getter_AddRefs(newAgentSheets));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
PRInt32 bc = styleSet->GetNumberOfAgentStyleSheets();
|
|
for (PRInt32 l = 0; l < bc; l++) {
|
|
nsCOMPtr<nsIStyleSheet> sheet = getter_AddRefs(styleSet->GetAgentStyleSheetAt(l));
|
|
nsCOMPtr<nsIURI> uri;
|
|
rv = sheet->GetURL(*getter_AddRefs(uri));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
if (IsChromeURI(uri)) {
|
|
// Reload the sheet.
|
|
nsCOMPtr<nsICSSStyleSheet> newSheet;
|
|
rv = LoadStyleSheetWithURL(uri, getter_AddRefs(newSheet));
|
|
if (NS_FAILED(rv)) return rv;
|
|
if (newSheet) {
|
|
rv = newAgentSheets->AppendElement(newSheet) ? NS_OK : NS_ERROR_FAILURE;
|
|
if (NS_FAILED(rv)) return rv;
|
|
}
|
|
}
|
|
else { // Just use the same sheet.
|
|
rv = newAgentSheets->AppendElement(sheet) ? NS_OK : NS_ERROR_FAILURE;
|
|
if (NS_FAILED(rv)) return rv;
|
|
}
|
|
}
|
|
|
|
styleSet->ReplaceAgentStyleSheets(newAgentSheets);
|
|
}
|
|
}
|
|
|
|
nsCOMPtr<nsIHTMLContentContainer> container = do_QueryInterface(document);
|
|
nsCOMPtr<nsICSSLoader> cssLoader;
|
|
rv = container->GetCSSLoader(*getter_AddRefs(cssLoader));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
// Build an array of nsIURIs of style sheets we need to load.
|
|
nsCOMPtr<nsISupportsArray> oldSheets;
|
|
rv = NS_NewISupportsArray(getter_AddRefs(oldSheets));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
nsCOMPtr<nsISupportsArray> newSheets;
|
|
rv = NS_NewISupportsArray(getter_AddRefs(newSheets));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
nsCOMPtr<nsIHTMLStyleSheet> attrSheet;
|
|
rv = container->GetAttributeStyleSheet(getter_AddRefs(attrSheet));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
nsCOMPtr<nsIHTMLCSSStyleSheet> inlineSheet;
|
|
rv = container->GetInlineStyleSheet(getter_AddRefs(inlineSheet));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
PRInt32 count = 0;
|
|
document->GetNumberOfStyleSheets(&count);
|
|
|
|
// Iterate over the style sheets.
|
|
PRUint32 i;
|
|
for (i = 0; i < (PRUint32)count; i++) {
|
|
// Get the style sheet
|
|
nsCOMPtr<nsIStyleSheet> styleSheet;
|
|
document->GetStyleSheetAt(i, getter_AddRefs(styleSheet));
|
|
|
|
// Make sure we aren't the special style sheets that never change. We
|
|
// want to skip those.
|
|
|
|
nsCOMPtr<nsIStyleSheet> attr = do_QueryInterface(attrSheet);
|
|
nsCOMPtr<nsIStyleSheet> inl = do_QueryInterface(inlineSheet);
|
|
if ((attr.get() != styleSheet.get()) &&
|
|
(inl.get() != styleSheet.get()))
|
|
// Add this sheet to the list of old style sheets.
|
|
oldSheets->AppendElement(styleSheet);
|
|
}
|
|
|
|
// Iterate over our old sheets and kick off a sync load of the new
|
|
// sheet if and only if it's a chrome URL.
|
|
PRUint32 oldCount;
|
|
oldSheets->Count(&oldCount);
|
|
for (i = 0; i < oldCount; i++) {
|
|
nsCOMPtr<nsISupports> supp = getter_AddRefs(oldSheets->ElementAt(i));
|
|
nsCOMPtr<nsIStyleSheet> sheet(do_QueryInterface(supp));
|
|
nsCOMPtr<nsIURI> uri;
|
|
rv = sheet->GetURL(*getter_AddRefs(uri));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
if (IsChromeURI(uri)) {
|
|
// Reload the sheet.
|
|
nsCOMPtr<nsICSSStyleSheet> newSheet;
|
|
LoadStyleSheetWithURL(uri, getter_AddRefs(newSheet));
|
|
if (newSheet)
|
|
newSheets->AppendElement(newSheet);
|
|
}
|
|
else // Just use the same sheet.
|
|
newSheets->AppendElement(sheet);
|
|
}
|
|
|
|
// Now notify the document that multiple sheets have been added and removed.
|
|
document->UpdateStyleSheets(oldSheets, newSheets);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::WriteInfoToDataSource(const char *aDocURI,
|
|
const PRUnichar *aOverlayURI,
|
|
PRBool aIsOverlay,
|
|
PRBool aUseProfile,
|
|
PRBool aRemove)
|
|
{
|
|
nsresult rv;
|
|
nsCOMPtr<nsIURI> uri;
|
|
nsCAutoString str(aDocURI);
|
|
rv = NS_NewURI(getter_AddRefs(uri), str.get());
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
nsCOMPtr<nsIRDFDataSource> dataSource;
|
|
rv = GetDynamicDataSource(uri, aIsOverlay, aUseProfile, getter_AddRefs(dataSource));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
if (!dataSource)
|
|
return NS_OK;
|
|
|
|
nsCOMPtr<nsIRDFResource> resource;
|
|
rv = GetResource(str, getter_AddRefs(resource));
|
|
|
|
if (NS_FAILED(rv))
|
|
return NS_OK;
|
|
|
|
nsCOMPtr<nsIRDFContainer> container;
|
|
rv = mRDFContainerUtils->MakeSeq(dataSource, resource, getter_AddRefs(container));
|
|
if (NS_FAILED(rv)) return rv;
|
|
if (!container) {
|
|
// Already exists. Create a container instead.
|
|
rv = nsComponentManager::CreateInstance("@mozilla.org/rdf/container;1",
|
|
nsnull,
|
|
NS_GET_IID(nsIRDFContainer),
|
|
getter_AddRefs(container));
|
|
if (NS_FAILED(rv)) return rv;
|
|
rv = container->Init(dataSource, resource);
|
|
if (NS_FAILED(rv)) return rv;
|
|
}
|
|
|
|
nsAutoString unistr(aOverlayURI);
|
|
nsCOMPtr<nsIRDFLiteral> 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<nsIRDFRemoteDataSource> remote = do_QueryInterface(dataSource, &rv);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
rv = remote->Flush();
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::UpdateDynamicDataSource(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource,
|
|
PRBool aIsOverlay, PRBool aUseProfile, PRBool aRemove)
|
|
{
|
|
nsCOMPtr<nsIRDFContainer> container;
|
|
nsresult rv;
|
|
|
|
rv = nsComponentManager::CreateInstance("@mozilla.org/rdf/container;1",
|
|
nsnull,
|
|
NS_GET_IID(nsIRDFContainer),
|
|
getter_AddRefs(container));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
rv = container->Init(aDataSource, aResource);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
nsCOMPtr<nsISimpleEnumerator> 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<nsISupports> supports;
|
|
rv = arcs->GetNext(getter_AddRefs(supports));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
nsCOMPtr<nsIRDFLiteral> 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;
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::UpdateDynamicDataSources(nsIRDFDataSource *aDataSource,
|
|
PRBool aIsOverlay, PRBool aUseProfile, PRBool aRemove)
|
|
{
|
|
nsresult rv;
|
|
nsCOMPtr<nsIRDFResource> 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<nsIRDFContainer> container(do_CreateInstance("@mozilla.org/rdf/container;1"));
|
|
if (!container)
|
|
return NS_OK;
|
|
|
|
if (NS_FAILED(container->Init(aDataSource, resource)))
|
|
return NS_OK;
|
|
|
|
nsCOMPtr<nsISimpleEnumerator> 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<nsISupports> supports;
|
|
rv = arcs->GetNext(getter_AddRefs(supports));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
nsCOMPtr<nsIRDFResource> 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;
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::SelectSkin(const PRUnichar* aSkin,
|
|
PRBool aUseProfile)
|
|
{
|
|
return SetProvider(nsCAutoString("skin"), mSelectedSkin, aSkin, aUseProfile, nsnull, PR_TRUE);
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::SelectLocale(const PRUnichar* aLocale,
|
|
PRBool aUseProfile)
|
|
{
|
|
return SetProvider(nsCAutoString("locale"), mSelectedLocale, aLocale, aUseProfile, nsnull, PR_TRUE);
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::SelectLocaleForProfile(const PRUnichar *aLocale,
|
|
const PRUnichar *aProfilePath)
|
|
{
|
|
// to be changed to use given path
|
|
return SetProvider(nsCAutoString("locale"), mSelectedLocale, aLocale, PR_TRUE, NS_ConvertUCS2toUTF8(aProfilePath).get(), PR_TRUE);
|
|
}
|
|
|
|
/* wstring getSelectedLocale (); */
|
|
NS_IMETHODIMP nsChromeRegistry::GetSelectedLocale(const PRUnichar *aPackageName,
|
|
PRUnichar **_retval)
|
|
{
|
|
// check if mChromeDataSource is null; do we need to apply this to every instance?
|
|
// is there a better way to test if the data source is ready?
|
|
if (!mChromeDataSource) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
nsString packageStr(aPackageName);
|
|
nsCAutoString resourceStr("urn:mozilla:package:");
|
|
resourceStr += NS_ConvertUCS2toUTF8(packageStr.get());
|
|
|
|
// Obtain the resource.
|
|
nsresult rv = NS_OK;
|
|
nsCOMPtr<nsIRDFResource> resource;
|
|
rv = GetResource(resourceStr, getter_AddRefs(resource));
|
|
if (NS_FAILED(rv)) {
|
|
NS_ERROR("Unable to obtain the package resource.");
|
|
return rv;
|
|
}
|
|
|
|
if (mChromeDataSource == nsnull)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
// Follow the "selectedLocale" arc.
|
|
nsCOMPtr<nsIRDFNode> selectedProvider;
|
|
if (NS_FAILED(rv = mChromeDataSource->GetTarget(resource, mSelectedLocale, PR_TRUE, getter_AddRefs(selectedProvider)))) {
|
|
NS_ERROR("Unable to obtain the provider.");
|
|
return rv;
|
|
}
|
|
|
|
if (!selectedProvider) {
|
|
rv = FindProvider(NS_ConvertUCS2toUTF8(packageStr.get()), nsCAutoString("locale"), mSelectedLocale, getter_AddRefs(selectedProvider));
|
|
if (!selectedProvider)
|
|
return rv;
|
|
}
|
|
|
|
resource = do_QueryInterface(selectedProvider);
|
|
if (!resource)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
// selectedProvider.mURI now looks like "urn:mozilla:locale:ja-JP:navigator"
|
|
const char *uri;
|
|
if (NS_FAILED(rv = resource->GetValueConst(&uri)))
|
|
return rv;
|
|
|
|
// trim down to "urn:mozilla:locale:ja-JP"
|
|
nsAutoString ustr = NS_ConvertUTF8toUCS2(uri);
|
|
|
|
packageStr.Insert(PRUnichar(':'), 0);
|
|
PRInt32 pos = ustr.RFind(packageStr);
|
|
nsString urn;
|
|
ustr.Left(urn, pos);
|
|
|
|
rv = GetResource(NS_ConvertUCS2toUTF8(urn.get()), getter_AddRefs(resource));
|
|
if (NS_FAILED(rv)) {
|
|
NS_ERROR("Unable to obtain the provider resource.");
|
|
return rv;
|
|
}
|
|
|
|
// From this resource, follow the "name" arc.
|
|
nsCAutoString lc_name; // is this i18n friendly? RDF now use UTF8 internally
|
|
rv = nsChromeRegistry::FollowArc(mChromeDataSource,
|
|
lc_name,
|
|
resource,
|
|
mName);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
// this is not i18n friendly? RDF now use UTF8 internally.
|
|
*_retval = ToNewUnicode(lc_name);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::DeselectSkin(const PRUnichar* aSkin,
|
|
PRBool aUseProfile)
|
|
{
|
|
return SetProvider(nsCAutoString("skin"), mSelectedSkin, aSkin, aUseProfile, nsnull, PR_FALSE);
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::DeselectLocale(const PRUnichar* aLocale,
|
|
PRBool aUseProfile)
|
|
{
|
|
return SetProvider(nsCAutoString("locale"), mSelectedLocale, aLocale, aUseProfile, nsnull, PR_FALSE);
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::SetProvider(const nsCString& aProvider,
|
|
nsIRDFResource* aSelectionArc,
|
|
const PRUnichar* aProviderName,
|
|
PRBool aUseProfile, const char *aProfilePath,
|
|
PRBool aIsAdding)
|
|
{
|
|
// Build the provider resource str.
|
|
// e.g., urn:mozilla:skin:aqua/1.0
|
|
nsCAutoString resourceStr( "urn:mozilla:" );
|
|
resourceStr += aProvider;
|
|
resourceStr += ":";
|
|
resourceStr.AppendWithConversion(aProviderName);
|
|
|
|
// Obtain the provider resource.
|
|
nsresult rv = NS_OK;
|
|
nsCOMPtr<nsIRDFResource> resource;
|
|
rv = GetResource(resourceStr, getter_AddRefs(resource));
|
|
if (NS_FAILED(rv)) {
|
|
NS_ERROR("Unable to obtain the package resource.");
|
|
return rv;
|
|
}
|
|
NS_ASSERTION(resource, "failed to GetResource");
|
|
|
|
// Follow the packages arc to the package resources.
|
|
nsCOMPtr<nsIRDFNode> packageList;
|
|
rv = mChromeDataSource->GetTarget(resource, mPackages, PR_TRUE, getter_AddRefs(packageList));
|
|
if (NS_FAILED(rv)) {
|
|
NS_ERROR("Unable to obtain the SEQ for the package list.");
|
|
return rv;
|
|
}
|
|
// ok for packageList to be null here -- it just means that we haven't encountered that package yet
|
|
|
|
nsCOMPtr<nsIRDFResource> packageSeq(do_QueryInterface(packageList, &rv));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
// Build an RDF container to wrap the SEQ
|
|
nsCOMPtr<nsIRDFContainer> container;
|
|
rv = nsComponentManager::CreateInstance("@mozilla.org/rdf/container;1",
|
|
nsnull,
|
|
NS_GET_IID(nsIRDFContainer),
|
|
getter_AddRefs(container));
|
|
if (NS_FAILED(rv))
|
|
return NS_OK;
|
|
|
|
if (NS_FAILED(container->Init(mChromeDataSource, packageSeq)))
|
|
return NS_OK;
|
|
|
|
nsCOMPtr<nsISimpleEnumerator> arcs;
|
|
if (NS_FAILED(container->GetElements(getter_AddRefs(arcs))))
|
|
return NS_OK;
|
|
|
|
// For each skin/package entry, follow the arcs to the real package
|
|
// resource.
|
|
PRBool more;
|
|
rv = arcs->HasMoreElements(&more);
|
|
if (NS_FAILED(rv)) return rv;
|
|
while (more) {
|
|
nsCOMPtr<nsISupports> packageSkinEntry;
|
|
rv = arcs->GetNext(getter_AddRefs(packageSkinEntry));
|
|
if (NS_SUCCEEDED(rv) && packageSkinEntry) {
|
|
nsCOMPtr<nsIRDFResource> entry = do_QueryInterface(packageSkinEntry);
|
|
if (entry) {
|
|
// Obtain the real package resource.
|
|
nsCOMPtr<nsIRDFNode> packageNode;
|
|
rv = mChromeDataSource->GetTarget(entry, mPackage, PR_TRUE, getter_AddRefs(packageNode));
|
|
if (NS_FAILED(rv)) {
|
|
NS_ERROR("Unable to obtain the package resource.");
|
|
return rv;
|
|
}
|
|
|
|
// Select the skin for this package resource.
|
|
nsCOMPtr<nsIRDFResource> packageResource(do_QueryInterface(packageNode));
|
|
if (packageResource) {
|
|
rv = SetProviderForPackage(aProvider, packageResource, entry, aSelectionArc, aUseProfile, aProfilePath, aIsAdding);
|
|
if (NS_FAILED(rv))
|
|
continue; // Well, let's set as many sub-packages as we can...
|
|
}
|
|
}
|
|
}
|
|
rv = arcs->HasMoreElements(&more);
|
|
if (NS_FAILED(rv)) return rv;
|
|
}
|
|
|
|
if (aProvider.Equals("skin") && mScrollbarSheet)
|
|
LoadStyleSheet(getter_AddRefs(mScrollbarSheet), nsCAutoString("chrome://global/skin/scrollbars.css"));
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsChromeRegistry::SetProviderForPackage(const nsCString& aProvider,
|
|
nsIRDFResource* aPackageResource,
|
|
nsIRDFResource* aProviderPackageResource,
|
|
nsIRDFResource* aSelectionArc,
|
|
PRBool aUseProfile, const char *aProfilePath,
|
|
PRBool aIsAdding)
|
|
{
|
|
nsresult rv;
|
|
|
|
// Figure out which file we're needing to modify, e.g., is it the install
|
|
// dir or the profile dir, and get the right datasource.
|
|
nsDependentCString dataSourceStr(kChromeFileName);
|
|
nsCOMPtr<nsIRDFDataSource> dataSource;
|
|
rv = LoadDataSource(dataSourceStr, getter_AddRefs(dataSource), aUseProfile, aProfilePath);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
rv = nsChromeRegistry::UpdateArc(dataSource, aPackageResource, aSelectionArc, aProviderPackageResource, !aIsAdding);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
nsCOMPtr<nsIRDFRemoteDataSource> remote = do_QueryInterface(dataSource, &rv);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
if (!mBatchInstallFlushes)
|
|
rv = remote->Flush();
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::SelectSkinForPackage(const PRUnichar *aSkin,
|
|
const PRUnichar *aPackageName,
|
|
PRBool aUseProfile)
|
|
{
|
|
nsCAutoString provider("skin");
|
|
return SelectProviderForPackage(provider, aSkin, aPackageName, mSelectedSkin, aUseProfile, PR_TRUE);
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::SelectLocaleForPackage(const PRUnichar *aLocale,
|
|
const PRUnichar *aPackageName,
|
|
PRBool aUseProfile)
|
|
{
|
|
nsCAutoString provider("locale");
|
|
return SelectProviderForPackage(provider, aLocale, aPackageName, mSelectedLocale, aUseProfile, PR_TRUE);
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::DeselectSkinForPackage(const PRUnichar *aSkin,
|
|
const PRUnichar *aPackageName,
|
|
PRBool aUseProfile)
|
|
{
|
|
nsCAutoString provider("skin");
|
|
return SelectProviderForPackage(provider, aSkin, aPackageName, mSelectedSkin, aUseProfile, PR_FALSE);
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::DeselectLocaleForPackage(const PRUnichar *aLocale,
|
|
const PRUnichar *aPackageName,
|
|
PRBool aUseProfile)
|
|
{
|
|
nsCAutoString provider("locale");
|
|
return SelectProviderForPackage(provider, aLocale, aPackageName, mSelectedLocale, aUseProfile, PR_FALSE);
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::IsSkinSelectedForPackage(const PRUnichar *aSkin,
|
|
const PRUnichar *aPackageName,
|
|
PRBool aUseProfile, PRBool* aResult)
|
|
{
|
|
nsCAutoString provider("skin");
|
|
return IsProviderSelectedForPackage(provider, aSkin, aPackageName, mSelectedSkin, aUseProfile, aResult);
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::IsLocaleSelectedForPackage(const PRUnichar *aLocale,
|
|
const PRUnichar *aPackageName,
|
|
PRBool aUseProfile, PRBool* aResult)
|
|
{
|
|
nsCAutoString provider("locale");
|
|
return IsProviderSelectedForPackage(provider, aLocale, aPackageName, mSelectedLocale, aUseProfile, aResult);
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::SelectProviderForPackage(const nsCString& aProviderType,
|
|
const PRUnichar *aProviderName,
|
|
const PRUnichar *aPackageName,
|
|
nsIRDFResource* aSelectionArc,
|
|
PRBool aUseProfile, PRBool aIsAdding)
|
|
{
|
|
nsCAutoString package( "urn:mozilla:package:" );
|
|
package.AppendWithConversion(aPackageName);
|
|
|
|
nsCAutoString provider( "urn:mozilla:" );
|
|
provider += aProviderType;
|
|
provider += ":";
|
|
provider.AppendWithConversion(aProviderName);
|
|
provider += ":";
|
|
provider.AppendWithConversion(aPackageName);
|
|
|
|
// Obtain the package resource.
|
|
nsresult rv = NS_OK;
|
|
nsCOMPtr<nsIRDFResource> packageResource;
|
|
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");
|
|
|
|
// Obtain the provider resource.
|
|
nsCOMPtr<nsIRDFResource> providerResource;
|
|
rv = GetResource(provider, getter_AddRefs(providerResource));
|
|
if (NS_FAILED(rv)) {
|
|
NS_ERROR("Unable to obtain the provider resource.");
|
|
return rv;
|
|
}
|
|
NS_ASSERTION(providerResource, "failed to get providerResource");
|
|
|
|
// Version-check before selecting. If this skin isn't a compatible version, then
|
|
// don't allow the selection.
|
|
// We found a selected provider, but now we need to verify that the version
|
|
// specified by the package and the version specified by the provider are
|
|
// one and the same. If they aren't, then we cannot use this provider.
|
|
nsCOMPtr<nsIRDFResource> versionArc;
|
|
if (aSelectionArc == mSelectedSkin)
|
|
versionArc = mSkinVersion;
|
|
else // Locale arc
|
|
versionArc = mLocaleVersion;
|
|
|
|
nsCAutoString packageVersion;
|
|
nsChromeRegistry::FollowArc(mChromeDataSource, packageVersion, packageResource, versionArc);
|
|
if (!packageVersion.IsEmpty()) {
|
|
// The package only wants providers (skins) that say they can work with it. Let's find out
|
|
// if our provider (skin) can work with it.
|
|
nsCAutoString providerVersion;
|
|
nsChromeRegistry::FollowArc(mChromeDataSource, providerVersion, providerResource, versionArc);
|
|
if (!providerVersion.Equals(packageVersion))
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
return SetProviderForPackage(aProviderType, packageResource, providerResource, aSelectionArc,
|
|
aUseProfile, nsnull, aIsAdding);
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::IsSkinSelected(const PRUnichar* aSkin,
|
|
PRBool aUseProfile, PRInt32* aResult)
|
|
{
|
|
return IsProviderSelected(nsCAutoString("skin"), aSkin, mSelectedSkin, aUseProfile, aResult);
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::IsLocaleSelected(const PRUnichar* aLocale,
|
|
PRBool aUseProfile, PRInt32* aResult)
|
|
{
|
|
return IsProviderSelected(nsCAutoString("locale"), aLocale, mSelectedLocale, aUseProfile, aResult);
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::IsProviderSelected(const nsCString& aProvider,
|
|
const PRUnichar* aProviderName,
|
|
nsIRDFResource* aSelectionArc,
|
|
PRBool aUseProfile, PRInt32* aResult)
|
|
{
|
|
// Build the provider resource str.
|
|
// e.g., urn:mozilla:skin:aqua/1.0
|
|
*aResult = NONE;
|
|
nsCAutoString resourceStr( "urn:mozilla:" );
|
|
resourceStr += aProvider;
|
|
resourceStr += ":";
|
|
resourceStr.AppendWithConversion(aProviderName);
|
|
|
|
// Obtain the provider resource.
|
|
nsresult rv = NS_OK;
|
|
nsCOMPtr<nsIRDFResource> resource;
|
|
rv = GetResource(resourceStr, getter_AddRefs(resource));
|
|
if (NS_FAILED(rv)) {
|
|
NS_ERROR("Unable to obtain the package resource.");
|
|
return rv;
|
|
}
|
|
NS_ASSERTION(resource, "failed to GetResource");
|
|
|
|
// Follow the packages arc to the package resources.
|
|
nsCOMPtr<nsIRDFNode> packageList;
|
|
rv = mChromeDataSource->GetTarget(resource, mPackages, PR_TRUE, getter_AddRefs(packageList));
|
|
if (NS_FAILED(rv)) {
|
|
NS_ERROR("Unable to obtain the SEQ for the package list.");
|
|
return rv;
|
|
}
|
|
// ok for packageList to be null here -- it just means that we haven't encountered that package yet
|
|
|
|
nsCOMPtr<nsIRDFResource> packageSeq(do_QueryInterface(packageList, &rv));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
// Build an RDF container to wrap the SEQ
|
|
nsCOMPtr<nsIRDFContainer> container(do_CreateInstance("@mozilla.org/rdf/container;1"));
|
|
if (NS_FAILED(container->Init(mChromeDataSource, packageSeq)))
|
|
return NS_OK;
|
|
|
|
nsCOMPtr<nsISimpleEnumerator> arcs;
|
|
container->GetElements(getter_AddRefs(arcs));
|
|
|
|
// For each skin/package entry, follow the arcs to the real package
|
|
// resource.
|
|
PRBool more;
|
|
rv = arcs->HasMoreElements(&more);
|
|
if (NS_FAILED(rv)) return rv;
|
|
while (more) {
|
|
nsCOMPtr<nsISupports> packageSkinEntry;
|
|
rv = arcs->GetNext(getter_AddRefs(packageSkinEntry));
|
|
if (NS_SUCCEEDED(rv) && packageSkinEntry) {
|
|
nsCOMPtr<nsIRDFResource> entry = do_QueryInterface(packageSkinEntry);
|
|
if (entry) {
|
|
// Obtain the real package resource.
|
|
nsCOMPtr<nsIRDFNode> packageNode;
|
|
rv = mChromeDataSource->GetTarget(entry, mPackage, PR_TRUE, getter_AddRefs(packageNode));
|
|
if (NS_FAILED(rv)) {
|
|
NS_ERROR("Unable to obtain the package resource.");
|
|
return rv;
|
|
}
|
|
|
|
// Select the skin for this package resource.
|
|
nsCOMPtr<nsIRDFResource> packageResource(do_QueryInterface(packageNode));
|
|
if (packageResource) {
|
|
PRBool isSet = PR_FALSE;
|
|
rv = IsProviderSetForPackage(aProvider, packageResource, entry, aSelectionArc, aUseProfile, &isSet);
|
|
if (NS_FAILED(rv)) {
|
|
NS_ERROR("Unable to set provider for package resource.");
|
|
return rv;
|
|
}
|
|
if (isSet && !*aResult)
|
|
*aResult = FULL;
|
|
else if (!isSet && *aResult) {
|
|
*aResult = PARTIAL;
|
|
return NS_OK;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
rv = arcs->HasMoreElements(&more);
|
|
if (NS_FAILED(rv)) return rv;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsChromeRegistry::IsProviderSelectedForPackage(const nsCString& aProviderType,
|
|
const PRUnichar *aProviderName,
|
|
const PRUnichar *aPackageName,
|
|
nsIRDFResource* aSelectionArc,
|
|
PRBool aUseProfile, PRBool* aResult)
|
|
{
|
|
*aResult = PR_FALSE;
|
|
nsCAutoString package( "urn:mozilla:package:" );
|
|
package.AppendWithConversion(aPackageName);
|
|
|
|
nsCAutoString provider( "urn:mozilla:" );
|
|
provider += aProviderType;
|
|
provider += ":";
|
|
provider.AppendWithConversion(aProviderName);
|
|
provider += ":";
|
|
provider.AppendWithConversion(aPackageName);
|
|
|
|
// Obtain the package resource.
|
|
nsresult rv = NS_OK;
|
|
nsCOMPtr<nsIRDFResource> packageResource;
|
|
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");
|
|
|
|
// Obtain the provider resource.
|
|
nsCOMPtr<nsIRDFResource> providerResource;
|
|
rv = GetResource(provider, getter_AddRefs(providerResource));
|
|
if (NS_FAILED(rv)) {
|
|
NS_ERROR("Unable to obtain the provider resource.");
|
|
return rv;
|
|
}
|
|
NS_ASSERTION(providerResource, "failed to get providerResource");
|
|
|
|
return IsProviderSetForPackage(aProviderType, packageResource, providerResource, aSelectionArc,
|
|
aUseProfile, aResult);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsChromeRegistry::IsProviderSetForPackage(const nsCString& aProvider,
|
|
nsIRDFResource* aPackageResource,
|
|
nsIRDFResource* aProviderPackageResource,
|
|
nsIRDFResource* aSelectionArc,
|
|
PRBool aUseProfile, PRBool* aResult)
|
|
{
|
|
nsresult rv;
|
|
// Figure out which file we're needing to modify, e.g., is it the install
|
|
// dir or the profile dir, and get the right datasource.
|
|
nsDependentCString dataSourceStr(kChromeFileName);
|
|
|
|
nsCOMPtr<nsIRDFDataSource> dataSource;
|
|
rv = LoadDataSource(dataSourceStr, getter_AddRefs(dataSource), aUseProfile, nsnull);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
nsCOMPtr<nsIRDFNode> retVal;
|
|
dataSource->GetTarget(aPackageResource, aSelectionArc, PR_TRUE, getter_AddRefs(retVal));
|
|
if (retVal) {
|
|
nsCOMPtr<nsIRDFNode> node(do_QueryInterface(aProviderPackageResource));
|
|
if (node == retVal)
|
|
*aResult = PR_TRUE;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::InstallProvider(const nsCString& aProviderType,
|
|
const nsCString& aBaseURL,
|
|
PRBool aUseProfile, PRBool aAllowScripts,
|
|
PRBool aRemove)
|
|
{
|
|
// XXX don't allow local chrome overrides of install chrome!
|
|
#ifdef DEBUG
|
|
printf("*** Chrome Registration of %s: Checking for contents.rdf at %s\n", aProviderType.get(), aBaseURL.get());
|
|
#endif
|
|
|
|
// Load the data source found at the base URL.
|
|
nsCOMPtr<nsIRDFDataSource> dataSource;
|
|
nsresult rv = nsComponentManager::CreateInstance(kRDFXMLDataSourceCID,
|
|
nsnull,
|
|
NS_GET_IID(nsIRDFDataSource),
|
|
(void**) getter_AddRefs(dataSource));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
nsCOMPtr<nsIRDFRemoteDataSource> 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(nsCAutoString("skin"), dataSource);
|
|
PRBool localeCount = GetProviderCount(nsCAutoString("locale"), dataSource);
|
|
PRBool packageCount = GetProviderCount(nsCAutoString("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_WARNING("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<nsIRDFDataSource> installSource;
|
|
nsDependentCString installStr(kChromeFileName);
|
|
rv = LoadDataSource(installStr, 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.Assign(NS_LITERAL_STRING("profile"));
|
|
else locstr.Assign(NS_LITERAL_STRING("install"));
|
|
nsCOMPtr<nsIRDFLiteral> locLiteral;
|
|
rv = mRDFService->GetLiteral(locstr.get(), getter_AddRefs(locLiteral));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
// Get the literal for our script access.
|
|
nsAutoString scriptstr;
|
|
scriptstr.Assign(NS_LITERAL_STRING("false"));
|
|
nsCOMPtr<nsIRDFLiteral> scriptLiteral;
|
|
rv = mRDFService->GetLiteral(scriptstr.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<nsISimpleEnumerator> 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<nsISupports> supports;
|
|
rv = resources->GetNext(getter_AddRefs(supports));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
nsCOMPtr<nsIRDFResource> 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<nsIRDFLiteral> 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<nsIRDFContainer> container;
|
|
rv = nsComponentManager::CreateInstance("@mozilla.org/rdf/container;1",
|
|
nsnull,
|
|
NS_GET_IID(nsIRDFContainer),
|
|
getter_AddRefs(container));
|
|
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<nsIRDFContainer> installContainer;
|
|
rv = mRDFContainerUtils->MakeSeq(installSource, resource, getter_AddRefs(installContainer));
|
|
if (NS_FAILED(rv)) return rv;
|
|
if (!installContainer) {
|
|
// Already exists. Create a container instead.
|
|
rv = nsComponentManager::CreateInstance("@mozilla.org/rdf/container;1",
|
|
nsnull,
|
|
NS_GET_IID(nsIRDFContainer),
|
|
getter_AddRefs(installContainer));
|
|
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<nsISimpleEnumerator> 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<nsISupports> supp;
|
|
rv = seqKids->GetNext(getter_AddRefs(supp));
|
|
if (NS_FAILED(rv)) return rv;
|
|
nsCOMPtr<nsIRDFNode> 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.Equals(nsCAutoString("package"))) {
|
|
PRBool doAppendPackage = appendPackage;
|
|
PRInt32 perProviderPackageCount;
|
|
container->GetCount(&perProviderPackageCount);
|
|
if (perProviderPackageCount > 1)
|
|
doAppendPackage = PR_TRUE;
|
|
|
|
// Iterate over our kids a second time.
|
|
nsCOMPtr<nsISimpleEnumerator> 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<nsISupports> supp;
|
|
rv = seqKids2->GetNext(getter_AddRefs(supp));
|
|
if (NS_FAILED(rv)) return rv;
|
|
nsCOMPtr<nsIRDFResource> 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<nsIRDFLiteral> 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.Equals(nsCAutoString("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<nsIRDFResource> 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<nsISimpleEnumerator> 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<nsISupports> supp;
|
|
rv = arcs->GetNext(getter_AddRefs(supp));
|
|
if (NS_FAILED(rv)) return rv;
|
|
nsCOMPtr<nsIRDFResource> 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<nsIRDFNode> 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<nsIRDFLiteral> 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.
|
|
nsAutoString fullURL; fullURL.AssignWithConversion(aBaseURL.get());
|
|
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<nsIRDFRemoteDataSource> 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::InstallSkin(const char* aBaseURL, PRBool aUseProfile, PRBool aAllowScripts)
|
|
{
|
|
nsCAutoString provider("skin");
|
|
return InstallProvider(provider, nsCAutoString(aBaseURL), aUseProfile, aAllowScripts, PR_FALSE);
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::InstallLocale(const char* aBaseURL, PRBool aUseProfile)
|
|
{
|
|
nsCAutoString provider("locale");
|
|
return InstallProvider(provider, nsCAutoString(aBaseURL), aUseProfile, PR_TRUE, PR_FALSE);
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::InstallPackage(const char* aBaseURL, PRBool aUseProfile)
|
|
{
|
|
nsCAutoString provider("package");
|
|
return InstallProvider(provider, nsCAutoString(aBaseURL), aUseProfile, PR_TRUE, PR_FALSE);
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::UninstallSkin(const PRUnichar* aSkinName, PRBool aUseProfile)
|
|
{
|
|
// The skin must first be deselected.
|
|
DeselectSkin(aSkinName, aUseProfile);
|
|
|
|
// Now uninstall it.
|
|
nsCAutoString provider("skin");
|
|
return UninstallProvider(provider, aSkinName, aUseProfile);
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::UninstallLocale(const PRUnichar* aLocaleName, PRBool aUseProfile)
|
|
{
|
|
// The locale must first be deselected.
|
|
DeselectLocale(aLocaleName, aUseProfile);
|
|
|
|
nsCAutoString provider("locale");
|
|
return UninstallProvider(provider, aLocaleName, aUseProfile);
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::UninstallPackage(const PRUnichar* aPackageName, PRBool aUseProfile)
|
|
{
|
|
NS_ERROR("XXX Write me!\n");
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsChromeRegistry::UninstallProvider(const nsCString& aProviderType,
|
|
const PRUnichar* 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);
|
|
nsCAutoString provName; provName.AssignWithConversion(aProviderName);
|
|
specificChild += provName;
|
|
|
|
// Instantiate the data source we wish to modify.
|
|
nsCOMPtr<nsIRDFDataSource> installSource;
|
|
nsDependentCString installStr(kChromeFileName);
|
|
rv = LoadDataSource(installStr, 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<nsIRDFContainer> container(do_CreateInstance("@mozilla.org/rdf/container;1"));
|
|
|
|
// Get the resource for the root.
|
|
nsCOMPtr<nsIRDFResource> 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<nsIRDFResource> 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<nsIRDFRemoteDataSource> remote = do_QueryInterface(installSource);
|
|
remote->Flush();
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsChromeRegistry::GetProfileRoot(nsCString& aFileURL)
|
|
{
|
|
nsresult rv;
|
|
nsCOMPtr<nsIFile> 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<nsIFile> defaultUserContentFile;
|
|
nsCOMPtr<nsIFile> 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->Append("chrome");
|
|
defaultUserContentFile->Append("userContent.css");
|
|
defaultUserChromeFile->Append("chrome");
|
|
defaultUserChromeFile->Append("userChrome.css");
|
|
|
|
// copy along
|
|
// It aint an error if these files dont exist
|
|
(void) defaultUserContentFile->CopyTo(userChromeDir, nsnull);
|
|
(void) defaultUserChromeFile->CopyTo(userChromeDir, nsnull);
|
|
}
|
|
}
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
nsXPIDLCString urlSpec;
|
|
rv = NS_GetURLSpecFromFile(userChromeDir, getter_Copies(urlSpec));
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
aFileURL = urlSpec;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsChromeRegistry::GetInstallRoot(nsCString& aFileURL)
|
|
{
|
|
nsresult rv;
|
|
nsCOMPtr<nsIFile> appChromeDir;
|
|
|
|
// Build a fileSpec that points to the destination
|
|
// (bin dir + chrome)
|
|
rv = NS_GetSpecialDirectory(NS_APP_CHROME_DIR, getter_AddRefs(appChromeDir));
|
|
if (NS_FAILED(rv) || !appChromeDir)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
nsXPIDLCString urlSpec;
|
|
rv = NS_GetURLSpecFromFile(appChromeDir, getter_Copies(urlSpec));
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
aFileURL = urlSpec;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsChromeRegistry::ReloadChrome()
|
|
{
|
|
// Do a reload of all top level windows.
|
|
nsresult rv = NS_OK;
|
|
|
|
// Flush the cache completely.
|
|
nsCOMPtr<nsIXULPrototypeCache> xulCache =
|
|
do_GetService("@mozilla.org/xul/xul-prototype-cache;1", &rv);
|
|
if (NS_SUCCEEDED(rv) && xulCache) {
|
|
rv = xulCache->Flush();
|
|
if (NS_FAILED(rv)) return rv;
|
|
}
|
|
|
|
nsCOMPtr<nsIStringBundleService> bundleService =
|
|
do_GetService(kStringBundleServiceCID, &rv);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
rv = bundleService->FlushBundles();
|
|
if (NS_FAILED(rv)) return rv;
|
|
}
|
|
|
|
// Get the window mediator
|
|
nsCOMPtr<nsIWindowMediator> windowMediator = do_GetService(kWindowMediatorCID, &rv);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
|
|
|
|
rv = windowMediator->GetEnumerator(nsnull, getter_AddRefs(windowEnumerator));
|
|
if (NS_SUCCEEDED(rv)) {
|
|
// Get each dom window
|
|
PRBool more;
|
|
rv = windowEnumerator->HasMoreElements(&more);
|
|
if (NS_FAILED(rv)) return rv;
|
|
while (more) {
|
|
nsCOMPtr<nsISupports> protoWindow;
|
|
rv = windowEnumerator->GetNext(getter_AddRefs(protoWindow));
|
|
if (NS_SUCCEEDED(rv)) {
|
|
nsCOMPtr<nsIDOMWindowInternal> domWindow =
|
|
do_QueryInterface(protoWindow);
|
|
if (domWindow) {
|
|
nsCOMPtr<nsIDOMLocation> location;
|
|
domWindow->GetLocation(getter_AddRefs(location));
|
|
if (location) {
|
|
rv = location->Reload(PR_FALSE);
|
|
if (NS_FAILED(rv)) return rv;
|
|
}
|
|
}
|
|
}
|
|
rv = windowEnumerator->HasMoreElements(&more);
|
|
if (NS_FAILED(rv)) return rv;
|
|
}
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsChromeRegistry::GetArcs(nsIRDFDataSource* aDataSource,
|
|
const nsCString& aType,
|
|
nsISimpleEnumerator** aResult)
|
|
{
|
|
nsCOMPtr<nsIRDFContainer> container;
|
|
nsresult rv = nsComponentManager::CreateInstance("@mozilla.org/rdf/container;1",
|
|
nsnull,
|
|
NS_GET_IID(nsIRDFContainer),
|
|
getter_AddRefs(container));
|
|
if (NS_FAILED(rv))
|
|
return NS_OK;
|
|
|
|
nsCAutoString lookup("chrome:");
|
|
lookup += aType;
|
|
|
|
// Get the chromeResource from this lookup string
|
|
nsCOMPtr<nsIRDFResource> 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<nsISimpleEnumerator> arcs;
|
|
if (NS_FAILED(container->GetElements(getter_AddRefs(arcs))))
|
|
return NS_OK;
|
|
|
|
*aResult = arcs;
|
|
NS_IF_ADDREF(*aResult);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsChromeRegistry::AddToCompositeDataSource(PRBool aUseProfile)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
if (!mChromeDataSource) {
|
|
rv = nsComponentManager::CreateInstance("@mozilla.org/rdf/datasource;1?name=composite-datasource",
|
|
nsnull,
|
|
NS_GET_IID(nsIRDFCompositeDataSource),
|
|
getter_AddRefs(mChromeDataSource));
|
|
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;
|
|
}
|
|
|
|
nsDependentCString name(kChromeFileName);
|
|
if (aUseProfile) {
|
|
// Profiles take precedence. Load them first.
|
|
nsCOMPtr<nsIRDFDataSource> dataSource;
|
|
LoadDataSource(name, getter_AddRefs(dataSource), PR_TRUE, nsnull);
|
|
mChromeDataSource->AddDataSource(dataSource);
|
|
}
|
|
|
|
// Always load the install dir datasources
|
|
nsCOMPtr<nsIRDFDataSource> dataSource;
|
|
LoadDataSource(name, getter_AddRefs(dataSource), PR_FALSE, nsnull);
|
|
mChromeDataSource->AddDataSource(dataSource);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsChromeRegistry::GetAgentSheets(nsIDocShell* aDocShell, nsISupportsArray **aResult)
|
|
{
|
|
nsresult rv = NS_NewISupportsArray(aResult);
|
|
|
|
// Determine the agent sheets that should be loaded.
|
|
if (!mScrollbarSheet)
|
|
LoadStyleSheet(getter_AddRefs(mScrollbarSheet), nsCAutoString("chrome://global/skin/scrollbars.css"));
|
|
|
|
if (!mFormSheet) {
|
|
nsCAutoString sheetURL;
|
|
GetFormSheetURL(sheetURL);
|
|
LoadStyleSheet(getter_AddRefs(mFormSheet), sheetURL);
|
|
}
|
|
|
|
PRBool shouldOverride = PR_FALSE;
|
|
nsCOMPtr<nsIChromeEventHandler> chromeHandler;
|
|
aDocShell->GetChromeEventHandler(getter_AddRefs(chromeHandler));
|
|
if (chromeHandler) {
|
|
nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(chromeHandler));
|
|
if (elt) {
|
|
nsAutoString sheets;
|
|
elt->GetAttribute(NS_LITERAL_STRING("usechromesheets"), sheets);
|
|
if (!sheets.IsEmpty()) {
|
|
// Construct the URIs and try to load each sheet.
|
|
nsCAutoString sheetsStr; sheetsStr.AssignWithConversion(sheets);
|
|
char* str = ToNewCString(sheets);
|
|
char* newStr;
|
|
char* token = nsCRT::strtok( str, ", ", &newStr );
|
|
while (token) {
|
|
nsCOMPtr<nsIContent> content(do_QueryInterface(elt));
|
|
nsCOMPtr<nsIDocument> doc;
|
|
content->GetDocument(*getter_AddRefs(doc));
|
|
nsCOMPtr<nsIURI> docURL;
|
|
doc->GetDocumentURL(getter_AddRefs(docURL));
|
|
nsCOMPtr<nsIURI> url;
|
|
rv = NS_NewURI(getter_AddRefs(url), token, docURL);
|
|
|
|
PRBool enabled = PR_FALSE;
|
|
nsCOMPtr<nsICSSStyleSheet> sheet;
|
|
nsCOMPtr<nsIXULPrototypeCache> cache(do_GetService("@mozilla.org/xul/xul-prototype-cache;1"));
|
|
if (cache) {
|
|
cache->GetEnabled(&enabled);
|
|
if (enabled) {
|
|
nsCOMPtr<nsICSSStyleSheet> cachedSheet;
|
|
cache->GetStyleSheet(url, getter_AddRefs(cachedSheet));
|
|
if (cachedSheet)
|
|
sheet = cachedSheet;
|
|
}
|
|
}
|
|
|
|
if (!sheet) {
|
|
LoadStyleSheetWithURL(url, getter_AddRefs(sheet));
|
|
if (sheet) {
|
|
if (enabled)
|
|
cache->PutStyleSheet(sheet);
|
|
}
|
|
}
|
|
|
|
if (sheet) {
|
|
// A sheet was loaded successfully. We will *not* use the default
|
|
// set of agent sheets (which consists solely of the scrollbar sheet).
|
|
shouldOverride = PR_TRUE;
|
|
(*aResult)->AppendElement(sheet);
|
|
}
|
|
|
|
// Advance to the next sheet URL.
|
|
token = nsCRT::strtok( newStr, ", ", &newStr );
|
|
}
|
|
nsMemory::Free(str);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (mScrollbarSheet && !shouldOverride)
|
|
(*aResult)->AppendElement(mScrollbarSheet);
|
|
|
|
if (mFormSheet)
|
|
(*aResult)->AppendElement(mFormSheet);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsChromeRegistry::GetUserSheets(PRBool aIsChrome, nsISupportsArray **aResult)
|
|
{
|
|
nsresult rv;
|
|
|
|
if ((aIsChrome && mUserChromeSheet) || (!aIsChrome && mUserContentSheet)) {
|
|
rv = NS_NewISupportsArray(aResult);
|
|
if (NS_FAILED(rv)) return rv;
|
|
if (aIsChrome && mUserChromeSheet) {
|
|
rv = (*aResult)->AppendElement(mUserChromeSheet) ? NS_OK : NS_ERROR_FAILURE;
|
|
if (NS_FAILED(rv)) return rv;
|
|
}
|
|
|
|
if (!aIsChrome && mUserContentSheet) {
|
|
rv = (*aResult)->AppendElement(mUserContentSheet) ? NS_OK : NS_ERROR_FAILURE;
|
|
if (NS_FAILED(rv)) return rv;
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult nsChromeRegistry::LoadStyleSheet(nsICSSStyleSheet** aSheet, const nsCString& aURL)
|
|
{
|
|
nsCOMPtr<nsIURI> uri;
|
|
nsresult rv = NS_NewURI(getter_AddRefs(uri), aURL.get());
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
rv = LoadStyleSheetWithURL(uri, aSheet);
|
|
return rv;
|
|
}
|
|
|
|
nsresult nsChromeRegistry::LoadStyleSheetWithURL(nsIURI* aURL, nsICSSStyleSheet** aSheet)
|
|
{
|
|
nsCOMPtr<nsICSSLoader> loader;
|
|
nsresult rv = nsComponentManager::CreateInstance(kCSSLoaderCID,
|
|
nsnull,
|
|
NS_GET_IID(nsICSSLoader),
|
|
getter_AddRefs(loader));
|
|
if (NS_FAILED(rv)) return rv;
|
|
if (loader) {
|
|
PRBool complete;
|
|
rv = loader->LoadAgentSheet(aURL, *aSheet, complete,
|
|
nsnull);
|
|
if (NS_FAILED(rv)) return rv;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult nsChromeRegistry::GetUserSheetURL(PRBool aIsChrome, nsCString & aURL)
|
|
{
|
|
aURL = mProfileRoot;
|
|
if (aIsChrome)
|
|
aURL.Append("userChrome.css");
|
|
else aURL.Append("userContent.css");
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult nsChromeRegistry::GetFormSheetURL(nsCString& aURL)
|
|
{
|
|
aURL = mUseXBLForms ? "chrome://forms/skin/forms.css" : "resource:/res/forms.css";
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult nsChromeRegistry::LoadInstallDataSource()
|
|
{
|
|
nsresult rv = GetInstallRoot(mInstallRoot);
|
|
if (NS_FAILED(rv)) return rv;
|
|
mInstallInitialized = PR_TRUE;
|
|
return AddToCompositeDataSource(PR_FALSE);
|
|
}
|
|
|
|
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;
|
|
|
|
// We have to flush the chrome cache!
|
|
rv = FlushCaches();
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
// XXX this sucks ASS. This is a temporary hack until we get
|
|
// around to fixing the skin switching bugs.
|
|
// Select and Remove skins based on a pref set in a previous session.
|
|
nsCOMPtr<nsIPref> pref(do_GetService("@mozilla.org/preferences;1"));
|
|
if (pref) {
|
|
nsXPIDLString skinToSelect;
|
|
rv = pref->CopyUnicharPref("general.skins.selectedSkin", getter_Copies(skinToSelect));
|
|
if (NS_SUCCEEDED(rv)) {
|
|
rv = SelectSkin(skinToSelect, PR_TRUE);
|
|
if (NS_SUCCEEDED(rv))
|
|
pref->DeleteBranch("general.skins.selectedSkin");
|
|
}
|
|
}
|
|
|
|
rv = LoadStyleSheet(getter_AddRefs(mScrollbarSheet), nsCAutoString("chrome://global/skin/scrollbars.css"));
|
|
// This must always be the last line of profile initialization!
|
|
|
|
nsCAutoString sheetURL;
|
|
rv = GetUserSheetURL(PR_TRUE, sheetURL);
|
|
if (NS_FAILED(rv)) return rv;
|
|
if (!sheetURL.IsEmpty()) {
|
|
(void)LoadStyleSheet(getter_AddRefs(mUserChromeSheet), sheetURL);
|
|
// it's ok to not have a user.css file
|
|
}
|
|
rv = GetUserSheetURL(PR_FALSE, sheetURL);
|
|
if (NS_FAILED(rv)) return rv;
|
|
if (!sheetURL.IsEmpty()) {
|
|
(void)LoadStyleSheet(getter_AddRefs(mUserContentSheet), sheetURL);
|
|
// it's ok not to have a userContent.css or userChrome.css file
|
|
}
|
|
rv = GetFormSheetURL(sheetURL);
|
|
if (NS_FAILED(rv)) return rv;
|
|
if (!sheetURL.IsEmpty())
|
|
(void)LoadStyleSheet(getter_AddRefs(mFormSheet), sheetURL);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::AllowScriptsForSkin(nsIURI* aChromeURI, PRBool *aResult)
|
|
{
|
|
*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;
|
|
|
|
// XXX could factor this with selectproviderforpackage
|
|
// get the selected skin resource for the package
|
|
nsCOMPtr<nsIRDFNode> selectedProvider;
|
|
|
|
nsCAutoString resourceStr("urn:mozilla:package:");
|
|
resourceStr += package;
|
|
|
|
// Obtain the resource.
|
|
nsCOMPtr<nsIRDFResource> resource;
|
|
rv = GetResource(resourceStr, getter_AddRefs(resource));
|
|
if (NS_FAILED(rv)) {
|
|
NS_ERROR("Unable to obtain the package resource.");
|
|
return rv;
|
|
}
|
|
|
|
if (NS_FAILED(rv = mChromeDataSource->GetTarget(resource, mSelectedSkin, PR_TRUE, getter_AddRefs(selectedProvider))))
|
|
return NS_OK;
|
|
|
|
if (!selectedProvider) {
|
|
rv = FindProvider(package, provider, mSelectedSkin, getter_AddRefs(selectedProvider));
|
|
if (NS_FAILED(rv)) return rv;
|
|
}
|
|
if (!selectedProvider)
|
|
return NS_OK;
|
|
|
|
resource = do_QueryInterface(selectedProvider, &rv);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
// get its script access
|
|
nsCAutoString scriptAccess;
|
|
rv = nsChromeRegistry::FollowArc(mChromeDataSource,
|
|
scriptAccess,
|
|
resource,
|
|
mAllowScripts);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
if (!scriptAccess.IsEmpty())
|
|
*aResult = PR_FALSE;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsChromeRegistry::CheckForNewChrome()
|
|
{
|
|
nsresult rv;
|
|
|
|
rv = LoadInstallDataSource();
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
// open the installed-chrome file
|
|
nsCOMPtr<nsILocalFile> listFile;
|
|
nsCOMPtr<nsIProperties> directoryService =
|
|
do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
rv = directoryService->Get(NS_APP_CHROME_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(listFile));
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
nsCOMPtr<nsIFile> chromeFile;
|
|
rv = listFile->Clone(getter_AddRefs(chromeFile));
|
|
if (NS_FAILED(rv)) return rv;
|
|
rv = chromeFile->Append(kChromeFileName);
|
|
if (NS_FAILED(rv)) return rv;
|
|
nsInt64 chromeDate;
|
|
(void)chromeFile->GetLastModifiedTime(&chromeDate.mValue);
|
|
|
|
rv = listFile->AppendRelativePath(kInstalledChromeFileName);
|
|
if (NS_FAILED(rv)) return rv;
|
|
nsInt64 listFileDate;
|
|
(void)listFile->GetLastModifiedTime(&listFileDate.mValue);
|
|
|
|
if (listFileDate < chromeDate)
|
|
return NS_OK;
|
|
|
|
PRFileDesc *file;
|
|
rv = listFile->OpenNSPRFileDesc(PR_RDONLY, 0, &file);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
// file is open.
|
|
|
|
PRFileInfo finfo;
|
|
|
|
if (PR_GetOpenFileInfo(file, &finfo) == PR_SUCCESS) {
|
|
char *dataBuffer = new char[finfo.size+1];
|
|
if (dataBuffer) {
|
|
PRInt32 bufferSize = PR_Read(file, dataBuffer, finfo.size);
|
|
if (bufferSize > 0) {
|
|
dataBuffer[bufferSize] = '\r'; // be sure to terminate in a delimiter
|
|
rv = ProcessNewChromeBuffer(dataBuffer, bufferSize);
|
|
}
|
|
delete [] dataBuffer;
|
|
}
|
|
}
|
|
PR_Close(file);
|
|
// listFile->Remove(PR_FALSE);
|
|
|
|
return rv;
|
|
}
|
|
|
|
// flaming unthreadsafe function
|
|
nsresult
|
|
nsChromeRegistry::ProcessNewChromeBuffer(char *aBuffer, PRInt32 aLength)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
char *bufferEnd = aBuffer + aLength;
|
|
char *chromeType, // "content", "locale" or "skin"
|
|
*chromeProfile, // "install" or "profile"
|
|
*chromeLocType, // type of location (local path or URL)
|
|
*chromeLocation; // base location of chrome (jar file)
|
|
PRBool isProfile;
|
|
PRBool isSelection;
|
|
|
|
nsCAutoString content("content");
|
|
nsCAutoString locale("locale");
|
|
nsCAutoString skin("skin");
|
|
nsCAutoString profile("profile");
|
|
nsCAutoString select("select");
|
|
nsCAutoString path("path");
|
|
nsCAutoString fileURL;
|
|
nsCAutoString chromeURL;
|
|
|
|
mBatchInstallFlushes = PR_TRUE;
|
|
|
|
while (aBuffer < bufferEnd) {
|
|
// parse one line of installed-chrome.txt
|
|
chromeType = aBuffer;
|
|
while (aBuffer < bufferEnd && *aBuffer != ',')
|
|
++aBuffer;
|
|
if (aBuffer >= bufferEnd)
|
|
break;
|
|
*aBuffer = '\0';
|
|
|
|
chromeProfile = ++aBuffer;
|
|
while (aBuffer < bufferEnd && *aBuffer != ',')
|
|
++aBuffer;
|
|
if (aBuffer >= bufferEnd)
|
|
break;
|
|
*aBuffer = '\0';
|
|
|
|
chromeLocType = ++aBuffer;
|
|
while (aBuffer < bufferEnd && *aBuffer != ',')
|
|
++aBuffer;
|
|
if (aBuffer >= bufferEnd)
|
|
break;
|
|
*aBuffer = '\0';
|
|
|
|
chromeLocation = ++aBuffer;
|
|
while (aBuffer < bufferEnd && (*aBuffer != '\r' && *aBuffer != '\n'))
|
|
++aBuffer;
|
|
if (aBuffer >= bufferEnd)
|
|
break;
|
|
while (*--aBuffer == ' ')
|
|
;
|
|
*++aBuffer = '\0';
|
|
|
|
// process the parsed line
|
|
isProfile = profile.Equals(chromeProfile);
|
|
isSelection = select.Equals(chromeLocType);
|
|
|
|
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<nsILocalFile> chromeFile(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv));
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
rv = chromeFile->InitWithPath(chromeLocation);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
/* xpidl strings aren't unified with strings, so this fu is necessary.
|
|
* all we want here is the canonical url
|
|
*/
|
|
nsXPIDLCString chromeURLfoopy;
|
|
rv = NS_GetURLSpecFromFile(chromeFile, getter_Copies(chromeURLfoopy));
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
chromeURL = chromeURLfoopy;
|
|
|
|
/* 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
|
|
if (skin.Equals(chromeType)) {
|
|
if (isSelection) {
|
|
nsAutoString name; name.AssignWithConversion(chromeLocation);
|
|
rv = SelectSkin(name.get(), isProfile);
|
|
#ifdef DEBUG
|
|
printf("***** Chrome Registration: Selecting skin %s as default\n", (const char*)chromeLocation);
|
|
#endif
|
|
}
|
|
else
|
|
rv = InstallSkin(chromeURL.get(), isProfile, PR_FALSE);
|
|
}
|
|
else if (content.Equals(chromeType))
|
|
rv = InstallPackage(chromeURL.get(), isProfile);
|
|
else if (locale.Equals(chromeType)) {
|
|
if (isSelection) {
|
|
nsAutoString name; name.AssignWithConversion(chromeLocation);
|
|
rv = SelectLocale(name.get(), isProfile);
|
|
#ifdef DEBUG
|
|
printf("***** Chrome Registration: Selecting locale %s as default\n", (const char*)chromeLocation);
|
|
#endif
|
|
}
|
|
else
|
|
rv = InstallLocale(chromeURL.get(), isProfile);
|
|
}
|
|
|
|
while (aBuffer < bufferEnd && (*aBuffer == '\0' || *aBuffer == ' ' || *aBuffer == '\r' || *aBuffer == '\n'))
|
|
++aBuffer;
|
|
}
|
|
|
|
mBatchInstallFlushes = PR_FALSE;
|
|
nsDependentCString dataSourceStr(kChromeFileName);
|
|
nsCOMPtr<nsIRDFDataSource> dataSource;
|
|
LoadDataSource(dataSourceStr, getter_AddRefs(dataSource), PR_FALSE, nsnull);
|
|
nsCOMPtr<nsIRDFRemoteDataSource> remote(do_QueryInterface(dataSource));
|
|
remote->Flush();
|
|
return NS_OK;
|
|
}
|
|
|
|
PRBool
|
|
nsChromeRegistry::GetProviderCount(const nsCString& aProviderType, nsIRDFDataSource* aDataSource)
|
|
{
|
|
nsresult rv;
|
|
|
|
nsCAutoString rootStr("urn:mozilla:");
|
|
rootStr += aProviderType;
|
|
rootStr += ":root";
|
|
|
|
// obtain the provider root resource
|
|
nsCOMPtr<nsIRDFResource> resource;
|
|
rv = GetResource(rootStr, getter_AddRefs(resource));
|
|
if (NS_FAILED(rv))
|
|
return 0;
|
|
|
|
// wrap it in a container
|
|
nsCOMPtr<nsIRDFContainer> container;
|
|
rv = nsComponentManager::CreateInstance("@mozilla.org/rdf/container;1",
|
|
nsnull,
|
|
NS_GET_IID(nsIRDFContainer),
|
|
getter_AddRefs(container));
|
|
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 (!nsCRT::strcmp("profile-before-change", aTopic)) {
|
|
|
|
mChromeDataSource = nsnull;
|
|
mScrollbarSheet = mFormSheet = nsnull;
|
|
mInstallInitialized = mProfileInitialized = PR_FALSE;
|
|
|
|
if (!nsCRT::strcmp("shutdown-cleanse", NS_ConvertUCS2toUTF8(someData).get())) {
|
|
nsCOMPtr<nsIFile> userChromeDir;
|
|
rv = NS_GetSpecialDirectory(NS_APP_USER_CHROME_DIR, getter_AddRefs(userChromeDir));
|
|
if (NS_SUCCEEDED(rv) && userChromeDir)
|
|
rv = userChromeDir->Remove(PR_TRUE);
|
|
}
|
|
}
|
|
else if (!nsCRT::strcmp("profile-after-change", aTopic)) {
|
|
if (!mProfileInitialized) {
|
|
nsCOMPtr<nsIPref> prefService(do_GetService(kPrefServiceCID));
|
|
if (prefService)
|
|
prefService->GetBoolPref(kUseXBLFormsPref, &mUseXBLForms);
|
|
|
|
rv = LoadProfileDataSource();
|
|
}
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::CheckThemeVersion(const PRUnichar *aSkin,
|
|
PRBool* aResult)
|
|
{
|
|
nsCAutoString provider("skin");
|
|
return CheckProviderVersion(provider, aSkin, mSkinVersion, aResult);
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::CheckLocaleVersion(const PRUnichar *aLocale,
|
|
PRBool* aResult)
|
|
{
|
|
nsCAutoString provider("locale");
|
|
return CheckProviderVersion(provider, aLocale, mLocaleVersion, aResult);
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP nsChromeRegistry::CheckProviderVersion (const nsCString& aProviderType,
|
|
const PRUnichar* aProviderName,
|
|
nsIRDFResource* aSelectionArc,
|
|
PRBool *aCompatible)
|
|
{
|
|
*aCompatible = PR_TRUE;
|
|
|
|
// Build the provider resource str.
|
|
// e.g., urn:mozilla:skin:aqua/1.0
|
|
nsCAutoString resourceStr( "urn:mozilla:" );
|
|
resourceStr += aProviderType;
|
|
resourceStr += ":";
|
|
resourceStr.AppendWithConversion(aProviderName);
|
|
|
|
// Obtain the provider resource.
|
|
nsresult rv = NS_OK;
|
|
nsCOMPtr<nsIRDFResource> resource;
|
|
rv = GetResource(resourceStr, getter_AddRefs(resource));
|
|
if (NS_FAILED(rv)) {
|
|
NS_ERROR("Unable to obtain the package resource.");
|
|
return rv;
|
|
}
|
|
|
|
// Follow the packages arc to the package resources.
|
|
nsCOMPtr<nsIRDFNode> packageList;
|
|
rv = mChromeDataSource->GetTarget(resource, mPackages, PR_TRUE, getter_AddRefs(packageList));
|
|
if (NS_FAILED(rv)) {
|
|
NS_ERROR("Unable to obtain the SEQ for the package list.");
|
|
return rv;
|
|
}
|
|
// ok for packageList to be null here -- it just means that we haven't encountered that package yet
|
|
|
|
nsCOMPtr<nsIRDFResource> packageSeq(do_QueryInterface(packageList, &rv));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
// Build an RDF container to wrap the SEQ
|
|
nsCOMPtr<nsIRDFContainer> container;
|
|
rv = nsComponentManager::CreateInstance("@mozilla.org/rdf/container;1",
|
|
nsnull,
|
|
NS_GET_IID(nsIRDFContainer),
|
|
getter_AddRefs(container));
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
rv = container->Init(mChromeDataSource, packageSeq);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
nsCOMPtr<nsISimpleEnumerator> arcs;
|
|
|
|
rv = container->GetElements(getter_AddRefs(arcs));
|
|
if (NS_FAILED(rv))
|
|
return NS_OK;
|
|
|
|
// For each skin-package entry, follow the arcs to the real package
|
|
// resource.
|
|
PRBool more;
|
|
rv = arcs->HasMoreElements(&more);
|
|
if (NS_FAILED(rv)) return rv;
|
|
while (more) {
|
|
nsCOMPtr<nsISupports> packageSkinEntry;
|
|
rv = arcs->GetNext(getter_AddRefs(packageSkinEntry));
|
|
if (NS_SUCCEEDED(rv) && packageSkinEntry) {
|
|
nsCOMPtr<nsIRDFResource> entry = do_QueryInterface(packageSkinEntry);
|
|
if (entry) {
|
|
|
|
nsCAutoString themePackageVersion;
|
|
nsChromeRegistry::FollowArc(mChromeDataSource, themePackageVersion, entry, aSelectionArc);
|
|
|
|
// Obtain the real package resource.
|
|
nsCOMPtr<nsIRDFNode> packageNode;
|
|
rv = mChromeDataSource->GetTarget(entry, mPackage, PR_TRUE, getter_AddRefs(packageNode));
|
|
if (NS_FAILED(rv)) {
|
|
NS_ERROR("Unable to obtain the package resource.");
|
|
return rv;
|
|
}
|
|
|
|
nsCOMPtr<nsIRDFResource> packageResource(do_QueryInterface(packageNode));
|
|
if (packageResource) {
|
|
|
|
nsCAutoString packageVersion;
|
|
nsChromeRegistry::FollowArc(mChromeDataSource, packageVersion, packageResource, aSelectionArc);
|
|
|
|
nsCAutoString packageName;
|
|
nsChromeRegistry::FollowArc(mChromeDataSource, packageName, packageResource, mName);
|
|
|
|
if (packageName.IsEmpty())
|
|
// the package is not represented for current version, so ignore it
|
|
*aCompatible = PR_TRUE;
|
|
else {
|
|
if (packageVersion.IsEmpty() && themePackageVersion.IsEmpty())
|
|
*aCompatible = PR_TRUE;
|
|
else {
|
|
if (!packageVersion.IsEmpty() && !themePackageVersion.IsEmpty())
|
|
*aCompatible = ( themePackageVersion.Equals(packageVersion));
|
|
else
|
|
*aCompatible = PR_FALSE;
|
|
}
|
|
}
|
|
|
|
// if just one theme package is NOT compatible, the theme will be disabled
|
|
if (!(*aCompatible))
|
|
return NS_OK;
|
|
|
|
}
|
|
}
|
|
}
|
|
rv = arcs->HasMoreElements(&more);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|