1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 sw=2 et tw=78: */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is mozilla.org code.
18 * The Initial Developer of the Original Code is
19 * Netscape Communications Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 1998
21 * the Initial Developer. All Rights Reserved.
24 * Original Author: David W. Hyatt (hyatt@netscape.com)
25 * Gagan Saksena <gagan@netscape.com>
26 * Benjamin Smedberg <benjamin@smedbergs.us>
28 * Alternatively, the contents of this file may be used under the terms of
29 * either the GNU General Public License Version 2 or later (the "GPL"), or
30 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 * in which case the provisions of the GPL or the LGPL are applicable instead
32 * of those above. If you wish to allow use of your version of this file only
33 * under the terms of either the GPL or the LGPL, and not to allow others to
34 * use your version of this file under the terms of the MPL, indicate your
35 * decision by deleting the provisions above and replace them with the notice
36 * and other provisions required by the GPL or the LGPL. If you do not delete
37 * the provisions above, a recipient may use your version of this file under
38 * the terms of any one of the MPL, the GPL or the LGPL.
40 * ***** END LICENSE BLOCK ***** */
42 #include "nsChromeRegistry.h"
50 #elif defined(XP_MACOSX)
51 #include <Carbon/Carbon.h>
52 #elif defined(MOZ_WIDGET_GTK2)
56 #include "nsAppDirectoryServiceDefs.h"
57 #include "nsArrayEnumerator.h"
58 #include "nsStringEnumerator.h"
59 #include "nsEnumeratorUtils.h"
61 #include "nsDOMError.h"
64 #include "nsLayoutCID.h"
66 #include "nsNetUtil.h"
67 #include "nsReadableUtils.h"
68 #include "nsStaticAtom.h"
70 #include "nsUnicharUtils.h"
71 #include "nsWidgetsCID.h"
72 #include "nsXPIDLString.h"
73 #include "nsXULAppAPI.h"
74 #include "nsTextFormatter.h"
77 #include "nsICommandLine.h"
78 #include "nsICSSLoader.h"
79 #include "nsICSSStyleSheet.h"
80 #include "nsIConsoleService.h"
81 #include "nsIDirectoryService.h"
82 #include "nsIDocument.h"
83 #include "nsIDOMDocument.h"
84 #include "nsIDocShell.h"
85 #include "nsIDocumentObserver.h"
86 #include "nsIDOMElement.h"
87 #include "nsIDOMLocation.h"
88 #include "nsIDOMWindowCollection.h"
89 #include "nsIDOMWindowInternal.h"
90 #include "nsIFileChannel.h"
91 #include "nsIFileURL.h"
92 #include "nsIIOService.h"
93 #include "nsIJARProtocolHandler.h"
94 #include "nsIJARURI.h"
95 #include "nsILocalFile.h"
96 #include "nsILocaleService.h"
97 #include "nsILookAndFeel.h"
98 #include "nsIObserverService.h"
99 #include "nsIPrefService.h"
100 #include "nsIPrefBranch.h"
101 #include "nsIPrefBranch2.h"
102 #include "nsIPresShell.h"
103 #include "nsIProtocolHandler.h"
104 #include "nsIResProtocolHandler.h"
105 #include "nsIScriptError.h"
106 #include "nsIServiceManager.h"
107 #include "nsISimpleEnumerator.h"
108 #include "nsIStyleSheet.h"
109 #include "nsISupportsArray.h"
110 #include "nsIVersionComparator.h"
111 #include "nsIWindowMediator.h"
112 #include "nsIXPConnect.h"
113 #include "nsIXULAppInfo.h"
114 #include "nsIXULRuntime.h"
115 #include "nsPresShellIterator.h"
118 // keep all the RDF stuff together, in case we can remove it in the far future
120 #include "nsRDFCID.h"
121 #include "nsIRDFService.h"
122 #include "nsIRDFDataSource.h"
123 #include "nsIRDFObserver.h"
124 #include "nsIRDFRemoteDataSource.h"
125 #include "nsIRDFXMLSink.h"
126 #include "nsIRDFResource.h"
127 #include "nsIRDFDataSource.h"
128 #include "nsIRDFContainer.h"
129 #include "nsIRDFContainerUtils.h"
131 #define CHROME_URI "http://www.mozilla.org/rdf/chrome#"
133 DEFINE_RDF_VOCAB(CHROME_URI
, CHROME
, packages
);
134 DEFINE_RDF_VOCAB(CHROME_URI
, CHROME
, package
);
135 DEFINE_RDF_VOCAB(CHROME_URI
, CHROME
, name
);
136 DEFINE_RDF_VOCAB(CHROME_URI
, CHROME
, platformPackage
);
140 #define UILOCALE_CMD_LINE_ARG "UILocale"
142 #define MATCH_OS_LOCALE_PREF "intl.locale.matchOS"
143 #define SELECTED_LOCALE_PREF "general.useragent.locale"
144 #define SELECTED_SKIN_PREF "general.skins.selectedSkin"
146 static NS_DEFINE_CID(kCSSLoaderCID
, NS_CSS_LOADER_CID
);
147 static NS_DEFINE_CID(kLookAndFeelCID
, NS_LOOKANDFEEL_CID
);
149 nsChromeRegistry
* nsChromeRegistry::gChromeRegistry
;
151 ////////////////////////////////////////////////////////////////////////////////
154 LogMessage(const char* aMsg
, ...)
156 nsCOMPtr
<nsIConsoleService
> console
157 (do_GetService(NS_CONSOLESERVICE_CONTRACTID
));
162 va_start(args
, aMsg
);
163 char* formatted
= PR_vsmprintf(aMsg
, args
);
168 console
->LogStringMessage(NS_ConvertUTF8toUTF16(formatted
).get());
169 PR_smprintf_free(formatted
);
173 LogMessageWithContext(nsIURI
* aURL
, PRUint32 aLineNumber
, PRUint32 flags
,
174 const char* aMsg
, ...)
178 nsCOMPtr
<nsIConsoleService
> console
179 (do_GetService(NS_CONSOLESERVICE_CONTRACTID
));
181 nsCOMPtr
<nsIScriptError
> error
182 (do_CreateInstance(NS_SCRIPTERROR_CONTRACTID
));
183 if (!console
|| !error
)
187 va_start(args
, aMsg
);
188 char* formatted
= PR_vsmprintf(aMsg
, args
);
197 rv
= error
->Init(NS_ConvertUTF8toUTF16(formatted
).get(),
198 NS_ConvertUTF8toUTF16(spec
).get(),
200 aLineNumber
, 0, flags
, "chrome registration");
201 PR_smprintf_free(formatted
);
206 console
->LogMessage(error
);
209 // We use a "best-fit" algorithm for matching locales and themes.
210 // 1) the exact selected locale/theme
211 // 2) (locales only) same language, different country
212 // e.g. en-GB is the selected locale, only en-US is available
213 // 3) any available locale/theme
216 * Match the language-part of two lang-COUNTRY codes, hopefully but
217 * not guaranteed to be in the form ab-CD or abz-CD. "ab" should also
218 * work, any other garbage-in will produce undefined results as long
219 * as it does not crash.
222 LanguagesMatch(const nsACString
& a
, const nsACString
& b
)
224 if (a
.Length() < 2 || b
.Length() < 2)
227 nsACString::const_iterator as
, ae
, bs
, be
;
240 if (as
== ae
&& bs
== be
)
255 nsChromeRegistry::ProviderEntry
*
256 nsChromeRegistry::nsProviderArray::GetProvider(const nsACString
& aPreferred
, MatchType aType
)
258 PRInt32 i
= mArray
.Count();
262 ProviderEntry
* found
= nsnull
; // Only set if we find a partial-match locale
263 ProviderEntry
* entry
;
266 entry
= reinterpret_cast<ProviderEntry
*>(mArray
[i
]);
267 if (aPreferred
.Equals(entry
->provider
))
273 if (LanguagesMatch(aPreferred
, entry
->provider
)) {
278 if (!found
&& entry
->provider
.EqualsLiteral("en-US"))
282 if (!found
&& aType
!= EXACT
)
289 nsChromeRegistry::nsProviderArray::GetBase(const nsACString
& aPreferred
, MatchType aType
)
291 ProviderEntry
* provider
= GetProvider(aPreferred
, aType
);
296 return provider
->baseURI
;
300 nsChromeRegistry::nsProviderArray::GetSelected(const nsACString
& aPreferred
, MatchType aType
)
302 ProviderEntry
* entry
= GetProvider(aPreferred
, aType
);
305 return entry
->provider
;
307 return EmptyCString();
311 nsChromeRegistry::nsProviderArray::SetBase(const nsACString
& aProvider
, nsIURI
* aBaseURL
)
313 ProviderEntry
* provider
= GetProvider(aProvider
, EXACT
);
316 provider
->baseURI
= aBaseURL
;
320 // no existing entries, add a new one
321 provider
= new ProviderEntry(aProvider
, aBaseURL
);
323 return; // It's safe to silently fail on OOM
325 mArray
.AppendElement(provider
);
329 nsChromeRegistry::nsProviderArray::EnumerateToArray(nsCStringArray
*a
)
331 PRInt32 i
= mArray
.Count();
333 ProviderEntry
*entry
= reinterpret_cast<ProviderEntry
*>(mArray
[i
]);
334 a
->AppendCString(entry
->provider
);
339 nsChromeRegistry::nsProviderArray::Clear()
341 PRInt32 i
= mArray
.Count();
343 ProviderEntry
* entry
= reinterpret_cast<ProviderEntry
*>(mArray
[i
]);
350 nsChromeRegistry::PackageEntry::PackageEntry(const nsACString
& aPackage
) :
351 package(aPackage
), flags(0)
356 nsChromeRegistry::HashKey(PLDHashTable
*table
, const void *key
)
358 const nsACString
& str
= *reinterpret_cast<const nsACString
*>(key
);
359 return HashString(str
);
363 nsChromeRegistry::MatchKey(PLDHashTable
*table
, const PLDHashEntryHdr
*entry
,
366 const nsACString
& str
= *reinterpret_cast<const nsACString
*>(key
);
367 const PackageEntry
* pentry
= static_cast<const PackageEntry
*>(entry
);
368 return str
.Equals(pentry
->package
);
372 nsChromeRegistry::ClearEntry(PLDHashTable
*table
, PLDHashEntryHdr
*entry
)
374 PackageEntry
* pentry
= static_cast<PackageEntry
*>(entry
);
375 pentry
->~PackageEntry();
379 nsChromeRegistry::InitEntry(PLDHashTable
*table
, PLDHashEntryHdr
*entry
,
382 const nsACString
& str
= *reinterpret_cast<const nsACString
*>(key
);
384 new (entry
) PackageEntry(str
);
388 const PLDHashTableOps
389 nsChromeRegistry::kTableOps
= {
394 PL_DHashMoveEntryStub
,
396 PL_DHashFinalizeStub
,
401 nsChromeRegistry::OverlayListEntry::AddURI(nsIURI
* aURI
)
403 PRInt32 i
= mArray
.Count();
406 if (NS_SUCCEEDED(aURI
->Equals(mArray
[i
], &equals
)) && equals
)
410 mArray
.AppendObject(aURI
);
414 nsChromeRegistry::OverlayListHash::Add(nsIURI
* aBase
, nsIURI
* aOverlay
)
416 OverlayListEntry
* entry
= mTable
.PutEntry(aBase
);
418 entry
->AddURI(aOverlay
);
421 const nsCOMArray
<nsIURI
>*
422 nsChromeRegistry::OverlayListHash::GetArray(nsIURI
* aBase
)
424 OverlayListEntry
* entry
= mTable
.GetEntry(aBase
);
428 return &entry
->mArray
;
431 nsChromeRegistry::~nsChromeRegistry()
433 if (mPackagesHash
.ops
)
434 PL_DHashTableFinish(&mPackagesHash
);
435 gChromeRegistry
= nsnull
;
438 NS_INTERFACE_MAP_BEGIN(nsChromeRegistry
)
439 NS_INTERFACE_MAP_ENTRY(nsIChromeRegistry
)
440 NS_INTERFACE_MAP_ENTRY(nsIXULChromeRegistry
)
441 NS_INTERFACE_MAP_ENTRY(nsIToolkitChromeRegistry
)
443 NS_INTERFACE_MAP_ENTRY(nsIXULOverlayProvider
)
445 NS_INTERFACE_MAP_ENTRY(nsIObserver
)
446 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference
)
447 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIChromeRegistry
)
450 NS_IMPL_ADDREF(nsChromeRegistry
)
451 NS_IMPL_RELEASE(nsChromeRegistry
)
453 ////////////////////////////////////////////////////////////////////////////////
454 // nsIChromeRegistry methods:
457 getUILangCountry(nsACString
& aUILang
)
461 nsCOMPtr
<nsILocaleService
> localeService
= do_GetService(NS_LOCALESERVICE_CONTRACTID
, &rv
);
462 NS_ENSURE_SUCCESS(rv
, rv
);
465 rv
= localeService
->GetLocaleComponentForUserAgent(uiLang
);
466 NS_ENSURE_SUCCESS(rv
, rv
);
468 CopyUTF16toUTF8(uiLang
, aUILang
);
473 nsChromeRegistry::Init()
477 // these atoms appear in almost every chrome registry contents.rdf
478 // in some form or another. making static atoms prevents the atoms
479 // from constantly being created/destroyed during parsing
481 static const nsStaticAtom atoms
[] = {
482 { "chrome", nsnull
},
484 { "allowScripts", nsnull
},
485 { "package", nsnull
},
486 { "packages", nsnull
},
487 { "hasOverlays", nsnull
},
490 NS_RegisterStaticAtoms(atoms
, NS_ARRAY_LENGTH(atoms
));
492 // Check to see if necko and the JAR protocol handler are registered yet
493 // if not, somebody is doing work during XPCOM registration that they
494 // shouldn't be doing. See bug 292549, where JS components are trying
495 // to call Components.utils.import("chrome:///") early in registration
497 nsCOMPtr
<nsIIOService
> io (do_GetIOService());
498 if (!io
) return NS_ERROR_FAILURE
;
500 nsCOMPtr
<nsIProtocolHandler
> ph
;
501 rv
= io
->GetProtocolHandler("jar", getter_AddRefs(ph
));
502 NS_ENSURE_SUCCESS(rv
, rv
);
504 nsCOMPtr
<nsIJARProtocolHandler
> jph
= do_QueryInterface(ph
);
506 return NS_ERROR_NOT_INITIALIZED
;
508 if (!PL_DHashTableInit(&mPackagesHash
, &kTableOps
,
509 nsnull
, sizeof(PackageEntry
), 16))
510 return NS_ERROR_FAILURE
;
512 if (!mOverlayHash
.Init() ||
513 !mStyleHash
.Init() ||
514 !mOverrideTable
.Init())
515 return NS_ERROR_FAILURE
;
517 mSelectedLocale
= NS_LITERAL_CSTRING("en-US");
518 mSelectedSkin
= NS_LITERAL_CSTRING("classic/1.0");
520 // This initialization process is fairly complicated and may cause reentrant
521 // getservice calls to resolve chrome URIs (especially locale files). We
522 // don't want that, so we inform the protocol handler about our existence
523 // before we are actually fully initialized.
524 gChromeRegistry
= this;
526 PRBool safeMode
= PR_FALSE
;
527 nsCOMPtr
<nsIXULRuntime
> xulrun (do_GetService(XULAPPINFO_SERVICE_CONTRACTID
));
529 xulrun
->GetInSafeMode(&safeMode
);
531 nsCOMPtr
<nsIPrefService
> prefserv (do_GetService(NS_PREFSERVICE_CONTRACTID
));
532 nsCOMPtr
<nsIPrefBranch
> prefs
;
535 prefserv
->GetDefaultBranch(nsnull
, getter_AddRefs(prefs
));
537 prefs
= do_QueryInterface(prefserv
);
540 NS_WARNING("Could not get pref service!");
543 PRBool useLocalePref
= PR_TRUE
;
546 // check the pref first
547 PRBool matchOS
= PR_FALSE
;
548 rv
= prefs
->GetBoolPref(MATCH_OS_LOCALE_PREF
, &matchOS
);
551 if (NS_SUCCEEDED(rv
) && matchOS
) {
552 // compute lang and region code only when needed!
553 nsCAutoString uiLocale
;
554 rv
= getUILangCountry(uiLocale
);
555 if (NS_SUCCEEDED(rv
)) {
556 useLocalePref
= PR_FALSE
;
557 mSelectedLocale
= uiLocale
;
563 nsXPIDLCString provider
;
565 rv
= prefs
->GetCharPref(SELECTED_SKIN_PREF
, getter_Copies(provider
));
566 if (NS_SUCCEEDED(rv
))
567 mSelectedSkin
= provider
;
569 nsCOMPtr
<nsIPrefBranch2
> prefs2 (do_QueryInterface(prefs
));
572 rv
= prefs2
->AddObserver(SELECTED_SKIN_PREF
, this, PR_TRUE
);
575 rv
= prefs
->GetCharPref(SELECTED_LOCALE_PREF
, getter_Copies(provider
));
576 if (NS_SUCCEEDED(rv
))
577 mSelectedLocale
= provider
;
580 prefs2
->AddObserver(SELECTED_LOCALE_PREF
, this, PR_TRUE
);
586 mInitialized
= PR_TRUE
;
592 nsChromeRegistry::CheckForOSAccessibility()
596 nsCOMPtr
<nsILookAndFeel
> lookAndFeel (do_GetService(kLookAndFeelCID
));
598 PRInt32 useAccessibilityTheme
= 0;
600 rv
= lookAndFeel
->GetMetric(nsILookAndFeel::eMetric_UseAccessibilityTheme
,
601 useAccessibilityTheme
);
603 if (NS_SUCCEEDED(rv
) && useAccessibilityTheme
) {
604 /* Set the skin to classic and remove pref observers */
605 if (!mSelectedSkin
.EqualsLiteral("classic/1.0")) {
606 mSelectedSkin
.AssignLiteral("classic/1.0");
610 nsCOMPtr
<nsIPrefBranch2
> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID
));
612 prefs
->RemoveObserver(SELECTED_SKIN_PREF
, this);
621 nsChromeRegistry::GetProviderAndPath(nsIURL
* aChromeURL
,
622 nsACString
& aProvider
, nsACString
& aPath
)
628 aChromeURL
->SchemeIs("chrome", &isChrome
);
629 NS_ASSERTION(isChrome
, "Non-chrome URI?");
633 rv
= aChromeURL
->GetPath(path
);
634 NS_ENSURE_SUCCESS(rv
, rv
);
636 if (path
.Length() < 3) {
637 LogMessage("Invalid chrome URI: %s", path
.get());
638 return NS_ERROR_FAILURE
;
641 path
.SetLength(nsUnescapeCount(path
.BeginWriting()));
642 NS_ASSERTION(path
.First() == '/', "Path should always begin with a slash!");
644 PRInt32 slash
= path
.FindChar('/', 1);
646 LogMessage("Invalid chrome URI: %s", path
.get());
647 return NS_ERROR_FAILURE
;
654 if (slash
== (PRInt32
) path
.Length() - 1)
657 aPath
.Assign(path
.get() + slash
+ 1, path
.Length() - slash
- 1);
662 aProvider
.Assign(path
.get() + 1, slash
);
668 nsChromeRegistry::Canonify(nsIURL
* aChromeURL
)
670 NS_NAMED_LITERAL_CSTRING(kSlash
, "/");
674 nsCAutoString provider
, path
;
675 rv
= GetProviderAndPath(aChromeURL
, provider
, path
);
676 NS_ENSURE_SUCCESS(rv
, rv
);
678 if (path
.IsEmpty()) {
679 nsCAutoString package
;
680 rv
= aChromeURL
->GetHost(package
);
681 NS_ENSURE_SUCCESS(rv
, rv
);
683 // we re-use the "path" local string to build a new URL path
684 path
.Assign(kSlash
+ provider
+ kSlash
+ package
);
685 if (provider
.EqualsLiteral("content")) {
686 path
.AppendLiteral(".xul");
688 else if (provider
.EqualsLiteral("locale")) {
689 path
.AppendLiteral(".dtd");
691 else if (provider
.EqualsLiteral("skin")) {
692 path
.AppendLiteral(".css");
695 return NS_ERROR_INVALID_ARG
;
697 aChromeURL
->SetPath(path
);
700 // prevent directory traversals ("..")
701 // path is already unescaped once, but uris can get unescaped twice
702 const char* pos
= path
.BeginReading();
703 const char* end
= path
.EndReading();
707 return NS_ERROR_DOM_BAD_URI
;
710 return NS_ERROR_DOM_BAD_URI
;
713 // chrome: URIs with double-escapes are trying to trick us.
714 // watch for %2e, and %25 in case someone triple unescapes
716 ( pos
[2] == 'e' || pos
[2] == 'E' ||
718 return NS_ERROR_DOM_BAD_URI
;
733 nsChromeRegistry::ConvertChromeURL(nsIURI
* aChromeURI
, nsIURI
* *aResult
)
736 NS_ASSERTION(aChromeURI
, "null url!");
738 if (mOverrideTable
.Get(aChromeURI
, aResult
))
741 nsCOMPtr
<nsIURL
> chromeURL (do_QueryInterface(aChromeURI
));
742 NS_ENSURE_TRUE(chromeURL
, NS_NOINTERFACE
);
744 nsCAutoString package
, provider
, path
;
745 rv
= chromeURL
->GetHostPort(package
);
746 NS_ENSURE_SUCCESS(rv
, rv
);
748 rv
= GetProviderAndPath(chromeURL
, provider
, path
);
749 NS_ENSURE_SUCCESS(rv
, rv
);
751 PackageEntry
* entry
=
752 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
753 & (nsACString
&) package
,
756 if (PL_DHASH_ENTRY_IS_FREE(entry
)) {
758 return NS_ERROR_NOT_INITIALIZED
;
760 LogMessage("No chrome package registered for chrome://%s/%s/%s",
761 package
.get(), provider
.get(), path
.get());
763 return NS_ERROR_FAILURE
;
766 if (entry
->flags
& PackageEntry::PLATFORM_PACKAGE
) {
767 #if defined(XP_WIN) || defined(XP_OS2)
768 path
.Insert("win/", 0);
769 #elif defined(XP_MACOSX)
770 path
.Insert("mac/", 0);
772 path
.Insert("unix/", 0);
776 nsIURI
* baseURI
= nsnull
;
777 if (provider
.EqualsLiteral("locale")) {
778 baseURI
= entry
->locales
.GetBase(mSelectedLocale
, nsProviderArray::LOCALE
);
780 else if (provider
.EqualsLiteral("skin")) {
781 baseURI
= entry
->skins
.GetBase(mSelectedSkin
, nsProviderArray::ANY
);
783 else if (provider
.EqualsLiteral("content")) {
784 baseURI
= entry
->baseURI
;
788 LogMessage("No chrome package registered for chrome://%s/%s/%s",
789 package
.get(), provider
.get(), path
.get());
790 return NS_ERROR_FAILURE
;
793 return NS_NewURI(aResult
, path
, nsnull
, baseURI
);
797 nsChromeRegistry::GetSelectedLocale(const nsACString
& aPackage
, nsACString
& aLocale
)
799 PackageEntry
* entry
=
800 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
804 if (PL_DHASH_ENTRY_IS_FREE(entry
))
805 return NS_ERROR_FAILURE
;
807 aLocale
= entry
->locales
.GetSelected(mSelectedLocale
, nsProviderArray::LOCALE
);
808 if (aLocale
.IsEmpty())
809 return NS_ERROR_FAILURE
;
815 nsChromeRegistry::GetLocalesForPackage(const nsACString
& aPackage
,
816 nsIUTF8StringEnumerator
* *aResult
)
818 nsCStringArray
*a
= new nsCStringArray
;
820 return NS_ERROR_OUT_OF_MEMORY
;
822 PackageEntry
* entry
=
823 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
827 if (PL_DHASH_ENTRY_IS_BUSY(entry
)) {
828 entry
->locales
.EnumerateToArray(a
);
831 nsresult rv
= NS_NewAdoptingUTF8StringEnumerator(aResult
, a
);
840 nsChromeRegistry::GetStyleOverlays(nsIURI
*aChromeURL
,
841 nsISimpleEnumerator
**aResult
)
843 const nsCOMArray
<nsIURI
>* parray
= mStyleHash
.GetArray(aChromeURL
);
845 return NS_NewEmptyEnumerator(aResult
);
847 return NS_NewArrayEnumerator(aResult
, *parray
);
851 nsChromeRegistry::GetXULOverlays(nsIURI
*aChromeURL
, nsISimpleEnumerator
**aResult
)
853 const nsCOMArray
<nsIURI
>* parray
= mOverlayHash
.GetArray(aChromeURL
);
855 return NS_NewEmptyEnumerator(aResult
);
857 return NS_NewArrayEnumerator(aResult
, *parray
);
861 ////////////////////////////////////////////////////////////////////////
866 static void FlushSkinBindingsForWindow(nsIDOMWindowInternal
* aWindow
)
868 // Get the DOM document.
869 nsCOMPtr
<nsIDOMDocument
> domDocument
;
870 aWindow
->GetDocument(getter_AddRefs(domDocument
));
874 nsCOMPtr
<nsIDocument
> document
= do_QueryInterface(domDocument
);
878 // Annihilate all XBL bindings.
879 document
->FlushSkinBindings();
882 // XXXbsmedberg: move this to nsIWindowMediator
883 NS_IMETHODIMP
nsChromeRegistry::RefreshSkins()
885 nsCOMPtr
<nsICSSLoader
> cssLoader(do_CreateInstance(kCSSLoaderCID
));
889 nsCOMPtr
<nsIWindowMediator
> windowMediator
890 (do_GetService(NS_WINDOWMEDIATOR_CONTRACTID
));
894 nsCOMPtr
<nsISimpleEnumerator
> windowEnumerator
;
895 windowMediator
->GetEnumerator(nsnull
, getter_AddRefs(windowEnumerator
));
897 windowEnumerator
->HasMoreElements(&more
);
899 nsCOMPtr
<nsISupports
> protoWindow
;
900 windowEnumerator
->GetNext(getter_AddRefs(protoWindow
));
902 nsCOMPtr
<nsIDOMWindowInternal
> domWindow
= do_QueryInterface(protoWindow
);
904 FlushSkinBindingsForWindow(domWindow
);
906 windowEnumerator
->HasMoreElements(&more
);
911 windowMediator
->GetEnumerator(nsnull
, getter_AddRefs(windowEnumerator
));
912 windowEnumerator
->HasMoreElements(&more
);
914 nsCOMPtr
<nsISupports
> protoWindow
;
915 windowEnumerator
->GetNext(getter_AddRefs(protoWindow
));
917 nsCOMPtr
<nsIDOMWindowInternal
> domWindow
= do_QueryInterface(protoWindow
);
919 RefreshWindow(domWindow
, cssLoader
);
921 windowEnumerator
->HasMoreElements(&more
);
928 nsChromeRegistry::FlushSkinCaches()
930 nsCOMPtr
<nsIObserverService
> obsSvc
=
931 do_GetService("@mozilla.org/observer-service;1");
932 NS_ASSERTION(obsSvc
, "Couldn't get observer service.");
934 obsSvc
->NotifyObservers(static_cast<nsIChromeRegistry
*>(this),
935 NS_CHROME_FLUSH_SKINS_TOPIC
, nsnull
);
938 static PRBool
IsChromeURI(nsIURI
* aURI
)
940 PRBool isChrome
=PR_FALSE
;
941 if (NS_SUCCEEDED(aURI
->SchemeIs("chrome", &isChrome
)) && isChrome
)
946 // XXXbsmedberg: move this to windowmediator
947 nsresult
nsChromeRegistry::RefreshWindow(nsIDOMWindowInternal
* aWindow
,
948 nsICSSLoader
* aCSSLoader
)
950 // Deal with our subframes first.
951 nsCOMPtr
<nsIDOMWindowCollection
> frames
;
952 aWindow
->GetFrames(getter_AddRefs(frames
));
954 frames
->GetLength(&length
);
956 for (j
= 0; j
< length
; j
++) {
957 nsCOMPtr
<nsIDOMWindow
> childWin
;
958 frames
->Item(j
, getter_AddRefs(childWin
));
959 nsCOMPtr
<nsIDOMWindowInternal
> childInt(do_QueryInterface(childWin
));
960 RefreshWindow(childInt
, aCSSLoader
);
964 // Get the DOM document.
965 nsCOMPtr
<nsIDOMDocument
> domDocument
;
966 aWindow
->GetDocument(getter_AddRefs(domDocument
));
970 nsCOMPtr
<nsIDocument
> document
= do_QueryInterface(domDocument
);
974 // Deal with the agent sheets first. Have to do all the style sets by hand.
975 nsPresShellIterator
iter(document
);
976 nsCOMPtr
<nsIPresShell
> shell
;
977 while ((shell
= iter
.GetNextShell())) {
978 // Reload only the chrome URL agent style sheets.
979 nsCOMArray
<nsIStyleSheet
> agentSheets
;
980 rv
= shell
->GetAgentStyleSheets(agentSheets
);
981 NS_ENSURE_SUCCESS(rv
, rv
);
983 nsCOMArray
<nsIStyleSheet
> newAgentSheets
;
984 for (PRInt32 l
= 0; l
< agentSheets
.Count(); ++l
) {
985 nsIStyleSheet
*sheet
= agentSheets
[l
];
987 nsCOMPtr
<nsIURI
> uri
;
988 rv
= sheet
->GetSheetURI(getter_AddRefs(uri
));
989 if (NS_FAILED(rv
)) return rv
;
991 if (IsChromeURI(uri
)) {
993 nsCOMPtr
<nsICSSStyleSheet
> newSheet
;
994 rv
= aCSSLoader
->LoadSheetSync(uri
, PR_TRUE
, getter_AddRefs(newSheet
));
995 if (NS_FAILED(rv
)) return rv
;
997 rv
= newAgentSheets
.AppendObject(newSheet
) ? NS_OK
: NS_ERROR_FAILURE
;
998 if (NS_FAILED(rv
)) return rv
;
1001 else { // Just use the same sheet.
1002 rv
= newAgentSheets
.AppendObject(sheet
) ? NS_OK
: NS_ERROR_FAILURE
;
1003 if (NS_FAILED(rv
)) return rv
;
1007 rv
= shell
->SetAgentStyleSheets(newAgentSheets
);
1008 NS_ENSURE_SUCCESS(rv
, rv
);
1011 // Build an array of nsIURIs of style sheets we need to load.
1012 nsCOMArray
<nsIStyleSheet
> oldSheets
;
1013 nsCOMArray
<nsIStyleSheet
> newSheets
;
1015 PRInt32 count
= document
->GetNumberOfStyleSheets();
1017 // Iterate over the style sheets.
1019 for (i
= 0; i
< count
; i
++) {
1020 // Get the style sheet
1021 nsIStyleSheet
*styleSheet
= document
->GetStyleSheetAt(i
);
1023 if (!oldSheets
.AppendObject(styleSheet
)) {
1024 return NS_ERROR_OUT_OF_MEMORY
;
1028 // Iterate over our old sheets and kick off a sync load of the new
1029 // sheet if and only if it's a chrome URL.
1030 for (i
= 0; i
< count
; i
++) {
1031 nsCOMPtr
<nsIStyleSheet
> sheet
= oldSheets
[i
];
1032 nsCOMPtr
<nsIURI
> uri
;
1033 rv
= sheet
->GetSheetURI(getter_AddRefs(uri
));
1034 if (NS_FAILED(rv
)) return rv
;
1036 if (IsChromeURI(uri
)) {
1037 // Reload the sheet.
1039 nsCOMPtr
<nsICSSStyleSheet
> oldCSSSheet
= do_QueryInterface(sheet
);
1040 NS_ASSERTION(oldCSSSheet
, "Don't know how to reload a non-CSS sheet");
1042 nsCOMPtr
<nsICSSStyleSheet
> newSheet
;
1043 // XXX what about chrome sheets that have a title or are disabled? This
1044 // only works by sheer dumb luck.
1045 // XXXbz this should really use the document's CSSLoader!
1046 aCSSLoader
->LoadSheetSync(uri
, getter_AddRefs(newSheet
));
1047 // Even if it's null, we put in in there.
1048 newSheets
.AppendObject(newSheet
);
1051 // Just use the same sheet.
1052 newSheets
.AppendObject(sheet
);
1056 // Now notify the document that multiple sheets have been added and removed.
1057 document
->UpdateStyleSheets(oldSheets
, newSheets
);
1062 nsChromeRegistry::FlushAllCaches()
1064 nsCOMPtr
<nsIObserverService
> obsSvc
=
1065 do_GetService("@mozilla.org/observer-service;1");
1066 NS_ASSERTION(obsSvc
, "Couldn't get observer service.");
1068 obsSvc
->NotifyObservers((nsIChromeRegistry
*) this,
1069 NS_CHROME_FLUSH_TOPIC
, nsnull
);
1072 // xxxbsmedberg Move me to nsIWindowMediator
1074 nsChromeRegistry::ReloadChrome()
1077 // Do a reload of all top level windows.
1078 nsresult rv
= NS_OK
;
1080 // Get the window mediator
1081 nsCOMPtr
<nsIWindowMediator
> windowMediator
1082 (do_GetService(NS_WINDOWMEDIATOR_CONTRACTID
));
1083 if (windowMediator
) {
1084 nsCOMPtr
<nsISimpleEnumerator
> windowEnumerator
;
1086 rv
= windowMediator
->GetEnumerator(nsnull
, getter_AddRefs(windowEnumerator
));
1087 if (NS_SUCCEEDED(rv
)) {
1088 // Get each dom window
1090 rv
= windowEnumerator
->HasMoreElements(&more
);
1091 if (NS_FAILED(rv
)) return rv
;
1093 nsCOMPtr
<nsISupports
> protoWindow
;
1094 rv
= windowEnumerator
->GetNext(getter_AddRefs(protoWindow
));
1095 if (NS_SUCCEEDED(rv
)) {
1096 nsCOMPtr
<nsIDOMWindowInternal
> domWindow
=
1097 do_QueryInterface(protoWindow
);
1099 nsCOMPtr
<nsIDOMLocation
> location
;
1100 domWindow
->GetLocation(getter_AddRefs(location
));
1102 rv
= location
->Reload(PR_FALSE
);
1103 if (NS_FAILED(rv
)) return rv
;
1107 rv
= windowEnumerator
->HasMoreElements(&more
);
1108 if (NS_FAILED(rv
)) return rv
;
1116 nsChromeRegistry::AllowScriptsForPackage(nsIURI
* aChromeURI
, PRBool
*aResult
)
1119 *aResult
= PR_FALSE
;
1123 aChromeURI
->SchemeIs("chrome", &isChrome
);
1124 NS_ASSERTION(isChrome
, "Non-chrome URI passed to AllowScriptsForPackage!");
1127 nsCOMPtr
<nsIURL
> url (do_QueryInterface(aChromeURI
));
1128 NS_ENSURE_TRUE(url
, NS_NOINTERFACE
);
1130 nsCAutoString provider
, file
;
1131 rv
= GetProviderAndPath(url
, provider
, file
);
1132 NS_ENSURE_SUCCESS(rv
, rv
);
1134 if (!provider
.EqualsLiteral("skin"))
1141 nsChromeRegistry::AllowContentToAccess(nsIURI
*aURI
, PRBool
*aResult
)
1145 *aResult
= PR_FALSE
;
1149 aURI
->SchemeIs("chrome", &isChrome
);
1150 NS_ASSERTION(isChrome
, "Non-chrome URI passed to AllowContentToAccess!");
1153 nsCOMPtr
<nsIURL
> url
= do_QueryInterface(aURI
);
1155 NS_ERROR("Chrome URL doesn't implement nsIURL.");
1156 return NS_ERROR_UNEXPECTED
;
1159 nsCAutoString package
;
1160 rv
= url
->GetHostPort(package
);
1161 NS_ENSURE_SUCCESS(rv
, rv
);
1163 PackageEntry
*entry
=
1164 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
1165 & (nsACString
&) package
,
1168 if (PL_DHASH_ENTRY_IS_BUSY(entry
)) {
1169 *aResult
= !!(entry
->flags
& PackageEntry::CONTENT_ACCESSIBLE
);
1174 static PLDHashOperator
1175 RemoveAll(PLDHashTable
*table
, PLDHashEntryHdr
*entry
, PRUint32 number
, void *arg
)
1177 return (PLDHashOperator
) (PL_DHASH_NEXT
| PL_DHASH_REMOVE
);
1181 nsChromeRegistry::CheckForNewChrome()
1185 PL_DHashTableEnumerate(&mPackagesHash
, RemoveAll
, nsnull
);
1186 mOverlayHash
.Clear();
1188 mOverrideTable
.Clear();
1190 nsCOMPtr
<nsIURI
> manifestURI
;
1191 rv
= NS_NewURI(getter_AddRefs(manifestURI
),
1192 NS_LITERAL_CSTRING("resource:///chrome/app-chrome.manifest"));
1194 // this is the main manifest; if it doesn't exist we generate it from
1195 // installed-chrome.txt. When the build system learns about the new system,
1196 // this code can go away.
1198 nsCOMPtr
<nsIFileURL
> manifestFileURL (do_QueryInterface(manifestURI
));
1199 NS_ASSERTION(manifestFileURL
, "Not a nsIFileURL!");
1200 NS_ENSURE_TRUE(manifestFileURL
, NS_ERROR_UNEXPECTED
);
1202 nsCOMPtr
<nsIFile
> manifest
;
1203 manifestFileURL
->GetFile(getter_AddRefs(manifest
));
1204 NS_ENSURE_TRUE(manifest
, NS_ERROR_FAILURE
);
1207 rv
= manifest
->Exists(&exists
);
1208 NS_ENSURE_SUCCESS(rv
, rv
);
1211 // In debug builds, installed-chrome.txt may change during development;
1212 // we just rebuild it every time because we're not worried about startup
1213 // time or other bad/goodness.
1215 manifest
->Remove(PR_FALSE
);
1221 nsCOMPtr
<nsIFile
> installed
;
1222 manifest
->Clone(getter_AddRefs(installed
));
1224 return NS_ERROR_OUT_OF_MEMORY
;
1226 nsCOMPtr
<nsILocalFile
> linstalled (do_QueryInterface(installed
));
1227 NS_ENSURE_TRUE(linstalled
, NS_NOINTERFACE
);
1229 linstalled
->SetNativeLeafName(NS_LITERAL_CSTRING("installed-chrome.txt"));
1231 rv
= linstalled
->Exists(&exists
);
1232 NS_ENSURE_SUCCESS(rv
, rv
);
1234 // process installed-chrome.txt into app-chrome.manifest
1236 ProcessNewChromeFile(linstalled
, manifestURI
);
1239 nsCOMPtr
<nsIProperties
> dirSvc (do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID
));
1240 NS_ENSURE_TRUE(dirSvc
, NS_ERROR_FAILURE
);
1242 // check the extra chrome directories
1243 nsCOMPtr
<nsISimpleEnumerator
> chromeML
;
1244 rv
= dirSvc
->Get(NS_CHROME_MANIFESTS_FILE_LIST
, NS_GET_IID(nsISimpleEnumerator
),
1245 getter_AddRefs(chromeML
));
1246 if (NS_FAILED(rv
)) {
1247 // ok, then simply load all .manifest files in the app chrome dir.
1248 nsCOMPtr
<nsIFile
> chromeDir
;
1249 rv
= dirSvc
->Get(NS_APP_CHROME_DIR
, NS_GET_IID(nsIFile
),
1250 getter_AddRefs(chromeDir
));
1253 rv
= NS_NewSingletonEnumerator(getter_AddRefs(chromeML
), chromeDir
);
1258 nsCOMPtr
<nsISupports
> next
;
1259 while (NS_SUCCEEDED(chromeML
->HasMoreElements(&exists
)) && exists
) {
1260 chromeML
->GetNext(getter_AddRefs(next
));
1261 nsCOMPtr
<nsILocalFile
> lmanifest
= do_QueryInterface(next
);
1263 NS_ERROR("Directory enumerator returned a non-nsILocalFile");
1268 if (NS_SUCCEEDED(lmanifest
->IsDirectory(&isDir
)) && isDir
) {
1269 nsCOMPtr
<nsISimpleEnumerator
> entries
;
1270 rv
= lmanifest
->GetDirectoryEntries(getter_AddRefs(entries
));
1274 while (NS_SUCCEEDED(entries
->HasMoreElements(&exists
)) && exists
) {
1275 entries
->GetNext(getter_AddRefs(next
));
1276 lmanifest
= do_QueryInterface(next
);
1278 nsCAutoString leafName
;
1279 lmanifest
->GetNativeLeafName(leafName
);
1280 if (StringEndsWith(leafName
, NS_LITERAL_CSTRING(".manifest"))) {
1281 rv
= ProcessManifest(lmanifest
, PR_FALSE
);
1282 if (NS_FAILED(rv
)) {
1284 lmanifest
->GetNativePath(path
);
1285 LogMessage("Failed to process chrome manifest '%s'.",
1294 rv
= ProcessManifest(lmanifest
, PR_FALSE
);
1295 if (NS_FAILED(rv
)) {
1297 lmanifest
->GetNativePath(path
);
1298 LogMessage("Failed to process chrome manifest: '%s'.",
1304 rv
= dirSvc
->Get(NS_SKIN_MANIFESTS_FILE_LIST
, NS_GET_IID(nsISimpleEnumerator
),
1305 getter_AddRefs(chromeML
));
1309 while (NS_SUCCEEDED(chromeML
->HasMoreElements(&exists
)) && exists
) {
1310 chromeML
->GetNext(getter_AddRefs(next
));
1311 nsCOMPtr
<nsILocalFile
> lmanifest
= do_QueryInterface(next
);
1313 NS_ERROR("Directory enumerator returned a non-nsILocalFile");
1317 rv
= ProcessManifest(lmanifest
, PR_TRUE
);
1318 if (NS_FAILED(rv
)) {
1320 lmanifest
->GetNativePath(path
);
1321 LogMessage("Failed to process chrome manifest: '%s'.",
1329 NS_IMETHODIMP_(PRBool
)
1330 nsChromeRegistry::WrappersEnabled(nsIURI
*aURI
)
1332 nsCOMPtr
<nsIURL
> chromeURL (do_QueryInterface(aURI
));
1336 PRBool isChrome
= PR_FALSE
;
1337 nsresult rv
= chromeURL
->SchemeIs("chrome", &isChrome
);
1338 if (NS_FAILED(rv
) || !isChrome
)
1341 nsCAutoString package
;
1342 rv
= chromeURL
->GetHostPort(package
);
1346 PackageEntry
* entry
=
1347 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
1348 & (nsACString
&) package
,
1351 return PL_DHASH_ENTRY_IS_LIVE(entry
) &&
1352 entry
->flags
& PackageEntry::XPCNATIVEWRAPPERS
;
1356 nsChromeRegistry::ProcessNewChromeFile(nsILocalFile
*aListFile
, nsIURI
* aManifest
)
1361 rv
= aListFile
->OpenNSPRFileDesc(PR_RDONLY
, 0, &file
);
1362 NS_ENSURE_SUCCESS(rv
, rv
);
1367 size
= PR_Available(file
);
1369 rv
= NS_ERROR_UNEXPECTED
;
1373 buf
= (char *) malloc(size
+ 1);
1375 rv
= NS_ERROR_OUT_OF_MEMORY
;
1379 n
= PR_Read(file
, buf
, size
);
1381 rv
= ProcessNewChromeBuffer(buf
, size
, aManifest
);
1390 nsChromeRegistry::ProcessNewChromeBuffer(char *aBuffer
, PRInt32 aLength
,
1393 nsresult rv
= NS_OK
;
1394 char *bufferEnd
= aBuffer
+ aLength
;
1395 char *chromeType
, // "content", "locale" or "skin"
1396 *chromeProfile
, // "install" or "profile"
1397 *chromeLocType
, // type of location (local path or URL)
1398 *chromeLocation
; // base location of chrome (jar file)
1400 nsCOMPtr
<nsIURI
> baseURI
;
1402 // process chromeType, chromeProfile, chromeLocType, chromeLocation
1403 while (aBuffer
< bufferEnd
) {
1404 // parse one line of installed-chrome.txt
1405 chromeType
= aBuffer
;
1406 while (aBuffer
< bufferEnd
&& *aBuffer
!= ',')
1410 chromeProfile
= ++aBuffer
;
1411 if (aBuffer
>= bufferEnd
)
1414 while (aBuffer
< bufferEnd
&& *aBuffer
!= ',')
1418 chromeLocType
= ++aBuffer
;
1419 if (aBuffer
>= bufferEnd
)
1422 while (aBuffer
< bufferEnd
&& *aBuffer
!= ',')
1426 chromeLocation
= ++aBuffer
;
1427 if (aBuffer
>= bufferEnd
)
1430 while (aBuffer
< bufferEnd
&&
1431 (*aBuffer
!= '\r' && *aBuffer
!= '\n' && *aBuffer
!= ' '))
1436 // We don't do skin or locale selection from installed-chrome.txt since
1437 // ffox 0.9. Just ignore the "select" lines.
1438 if (strcmp(chromeLocType
,"select")) {
1439 if (!strcmp(chromeLocType
, "path")) {
1440 // location is a (full) path. convert it to an URL.
1442 /* this is some convoluted shit... this creates a file, inits it with
1443 * the path parsed above (chromeLocation), makes a url, and inits it
1444 * with the file created. the purpose of this is just to have the
1445 * canonical url of the stupid thing.
1447 nsCOMPtr
<nsILocalFile
> chromeFile
;
1448 rv
= NS_NewNativeLocalFile(nsDependentCString(chromeLocation
),
1449 PR_TRUE
, getter_AddRefs(chromeFile
));
1450 NS_ENSURE_SUCCESS(rv
, rv
);
1453 * all we want here is the canonical url
1455 rv
= NS_NewFileURI(getter_AddRefs(baseURI
), chromeFile
);
1456 if (NS_FAILED(rv
)) return rv
;
1459 rv
= NS_NewURI(getter_AddRefs(baseURI
), chromeLocation
);
1460 if (NS_FAILED(rv
)) return rv
;
1463 ProcessContentsManifest(baseURI
, aManifest
, baseURI
, PR_TRUE
,
1464 strcmp(chromeType
, "skin") == 0);
1467 while (aBuffer
< bufferEnd
&& (*aBuffer
== '\0' || *aBuffer
== ' ' || *aBuffer
== '\r' || *aBuffer
== '\n'))
1474 NS_IMETHODIMP
nsChromeRegistry::Observe(nsISupports
*aSubject
, const char *aTopic
, const PRUnichar
*someData
)
1476 nsresult rv
= NS_OK
;
1478 if (!strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID
, aTopic
)) {
1479 nsCOMPtr
<nsIPrefBranch
> prefs (do_QueryInterface(aSubject
));
1480 NS_ASSERTION(prefs
, "Bad observer call!");
1482 NS_ConvertUTF16toUTF8
pref(someData
);
1484 nsXPIDLCString provider
;
1485 rv
= prefs
->GetCharPref(pref
.get(), getter_Copies(provider
));
1486 if (NS_FAILED(rv
)) {
1487 NS_ERROR("Couldn't get new locale or skin pref!");
1491 if (pref
.EqualsLiteral(SELECTED_SKIN_PREF
)) {
1492 mSelectedSkin
= provider
;
1495 else if (pref
.EqualsLiteral(SELECTED_LOCALE_PREF
)) {
1496 mSelectedLocale
= provider
;
1499 NS_ERROR("Unexpected pref!");
1502 else if (!strcmp("command-line-startup", aTopic
)) {
1503 nsCOMPtr
<nsICommandLine
> cmdLine (do_QueryInterface(aSubject
));
1505 nsAutoString uiLocale
;
1506 rv
= cmdLine
->HandleFlagWithParam(NS_LITERAL_STRING(UILOCALE_CMD_LINE_ARG
),
1507 PR_FALSE
, uiLocale
);
1508 if (NS_SUCCEEDED(rv
) && !uiLocale
.IsEmpty()) {
1509 CopyUTF16toUTF8(uiLocale
, mSelectedLocale
);
1510 nsCOMPtr
<nsIPrefBranch2
> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID
));
1512 prefs
->RemoveObserver(SELECTED_LOCALE_PREF
, this);
1518 NS_ERROR("Unexpected observer topic!");
1526 GetContainerEnumerator(nsIRDFDataSource
* ds
, nsIRDFResource
* res
,
1527 nsISimpleEnumerator
* *aResult
, PRInt32
*aCountResult
= nsnull
)
1531 nsCOMPtr
<nsIRDFContainer
> container
1532 (do_CreateInstance("@mozilla.org/rdf/container;1"));
1533 NS_ENSURE_TRUE(container
, NS_ERROR_FAILURE
);
1535 rv
= container
->Init(ds
, res
);
1536 if (NS_FAILED(rv
)) return rv
;
1539 container
->GetCount(aCountResult
);
1541 return container
->GetElements(aResult
);
1545 FollowLiteral(nsIRDFDataSource
* ds
, nsIRDFResource
* res
,
1546 nsIRDFResource
* arc
, nsACString
& result
)
1550 nsCOMPtr
<nsIRDFNode
> node
;
1551 rv
= ds
->GetTarget(res
, arc
, PR_TRUE
, getter_AddRefs(node
));
1552 if (NS_FAILED(rv
) || !node
) {
1557 nsCOMPtr
<nsIRDFLiteral
> literal (do_QueryInterface(node
));
1559 NS_ERROR("Arc found, but doesn't point to expected literal!");
1564 const PRUnichar
* value
;
1565 literal
->GetValueConst(&value
);
1566 CopyUTF16toUTF8(value
, result
);
1570 FollowResource(nsIRDFDataSource
* ds
, nsIRDFResource
* res
, nsIRDFResource
* arc
,
1571 nsIRDFResource
* *result
)
1575 nsCOMPtr
<nsIRDFNode
> node
;
1576 rv
= ds
->GetTarget(res
, arc
, PR_TRUE
, getter_AddRefs(node
));
1577 if (NS_FAILED(rv
) || !node
) {
1582 CallQueryInterface(node
, result
);
1586 GetRelativePath(nsIURI
* base
, nsIURI
* relative
, nsACString
& result
)
1590 nsCOMPtr
<nsIJARURI
> jarrelative (do_QueryInterface(relative
));
1592 nsCOMPtr
<nsIURI
> jarbase
;
1593 jarrelative
->GetJARFile(getter_AddRefs(jarbase
));
1595 nsCAutoString relativeBase
;
1596 GetRelativePath(base
, jarbase
, relativeBase
);
1598 nsCAutoString jarEntry
;
1599 jarrelative
->GetJAREntry(jarEntry
);
1601 result
.Assign(NS_LITERAL_CSTRING("jar:"));
1602 result
.Append(relativeBase
);
1603 result
.Append(NS_LITERAL_CSTRING("!/"));
1604 result
.Append(jarEntry
);
1608 nsCOMPtr
<nsIURL
> baseURL (do_QueryInterface(base
));
1610 relative
->GetSpec(result
);
1614 rv
= baseURL
->GetRelativeSpec(relative
, result
);
1615 if (NS_FAILED(rv
)) {
1616 relative
->GetSpec(result
);
1620 static const PRInt32 kNSPR_APPEND_FLAGS
= PR_WRONLY
| PR_CREATE_FILE
| PR_APPEND
;
1621 static const PRInt32 kNSPR_TRUNCATE_FLAGS
= PR_WRONLY
| PR_CREATE_FILE
| PR_TRUNCATE
;
1624 nsChromeRegistry::ProcessContentsManifest(nsIURI
* aOldManifest
, nsIURI
* aFile
,
1625 nsIURI
* aBaseURI
, PRBool aAppend
,
1630 nsCAutoString relativePath
;
1631 GetRelativePath(aFile
, aBaseURI
, relativePath
);
1634 aOldManifest
->GetSpec(spec
);
1636 NS_ASSERTION(spec
.Last() == '/', "installed-chrome manifest URI doesn't end in a slash! It probably won't work.");
1638 spec
.AppendLiteral("contents.rdf");
1640 nsCOMPtr
<nsIRDFService
> rdfs (do_GetService("@mozilla.org/rdf/rdf-service;1"));
1641 NS_ENSURE_TRUE(rdfs
, NS_ERROR_FAILURE
);
1643 nsCOMPtr
<nsIRDFResource
> namearc
, platformarc
;
1644 rdfs
->GetResource(NS_LITERAL_CSTRING(kURICHROME_name
),
1645 getter_AddRefs(namearc
));
1646 rdfs
->GetResource(NS_LITERAL_CSTRING(kURICHROME_platformPackage
),
1647 getter_AddRefs(platformarc
));
1648 if (!(namearc
&& platformarc
))
1649 return NS_ERROR_FAILURE
;
1651 nsCOMPtr
<nsIRDFDataSource
> ds
;
1652 rv
= rdfs
->GetDataSourceBlocking(spec
.get(), getter_AddRefs(ds
));
1653 if (NS_FAILED(rv
)) {
1654 LogMessage("Failed to load old-style contents.rdf at '%s'.",
1659 nsCOMPtr
<nsIFileURL
> fileURL (do_QueryInterface(aFile
));
1660 NS_ENSURE_TRUE(fileURL
, NS_ERROR_INVALID_ARG
);
1662 nsCOMPtr
<nsIFile
> file
;
1663 rv
= fileURL
->GetFile(getter_AddRefs(file
));
1664 NS_ENSURE_SUCCESS(rv
, rv
);
1666 nsCOMPtr
<nsILocalFile
> lfile (do_QueryInterface(file
));
1667 NS_ENSURE_TRUE(lfile
, NS_ERROR_NO_INTERFACE
);
1670 rv
= lfile
->OpenNSPRFileDesc(aAppend
? kNSPR_APPEND_FLAGS
: kNSPR_TRUNCATE_FLAGS
,
1672 NS_ENSURE_SUCCESS(rv
, rv
);
1675 PR_Write(fd
, "\n", 1);
1677 nsCOMPtr
<nsIRDFResource
> root
;
1678 rv
= rdfs
->GetResource(NS_LITERAL_CSTRING("urn:mozilla:skin:root"),
1679 getter_AddRefs(root
));
1680 if (NS_SUCCEEDED(rv
))
1681 ProcessProvider(fd
, rdfs
, ds
, root
, PR_FALSE
, relativePath
);
1683 rv
= rdfs
->GetResource(NS_LITERAL_CSTRING("urn:mozilla:stylesheets"),
1684 getter_AddRefs(root
));
1685 if (NS_SUCCEEDED(rv
))
1686 ProcessOverlays(fd
, ds
, root
, NS_LITERAL_CSTRING("style"));
1689 rv
= rdfs
->GetResource(NS_LITERAL_CSTRING("urn:mozilla:locale:root"),
1690 getter_AddRefs(root
));
1691 if (NS_SUCCEEDED(rv
))
1692 ProcessProvider(fd
, rdfs
, ds
, root
, PR_TRUE
, relativePath
);
1694 rv
= rdfs
->GetResource(NS_LITERAL_CSTRING("urn:mozilla:overlays"),
1695 getter_AddRefs(root
));
1696 if (NS_SUCCEEDED(rv
))
1697 ProcessOverlays(fd
, ds
, root
, NS_LITERAL_CSTRING("overlay"));
1699 /* content packages are easier, but different */
1701 rv
= rdfs
->GetResource(NS_LITERAL_CSTRING("urn:mozilla:package:root"),
1702 getter_AddRefs(root
));
1704 nsCOMPtr
<nsISimpleEnumerator
> packages
;
1705 if (NS_SUCCEEDED(rv
))
1706 rv
= GetContainerEnumerator(ds
, root
, getter_AddRefs(packages
));
1708 if (NS_SUCCEEDED(rv
)) {
1710 nsCOMPtr
<nsISupports
> next
;
1711 nsCOMPtr
<nsIRDFResource
> package
;
1713 while (NS_SUCCEEDED(packages
->HasMoreElements(&more
)) && more
) {
1714 packages
->GetNext(getter_AddRefs(next
));
1716 package
= do_QueryInterface(next
);
1718 NS_WARNING("Arc from urn:mozilla:package:root points to non-resource node.");
1723 FollowLiteral(ds
, package
, namearc
, name
);
1727 nsCAutoString isPlatform
;
1728 FollowLiteral(ds
, package
, platformarc
, isPlatform
);
1729 name
.Insert(NS_LITERAL_CSTRING("content\t"), 0);
1731 name
.Append(relativePath
);
1732 if (!isPlatform
.IsEmpty())
1733 name
.AppendLiteral("\tplatform");
1735 name
.AppendLiteral(NS_LINEBREAK
);
1736 PR_Write(fd
, name
.get(), name
.Length());
1747 GetResourceName(nsIRDFResource
* res
, nsACString
& result
)
1749 // we need to get the provider name. Instead of doing something sane,
1750 // we munge the resource URI, looking from the right for colons.
1752 nsCAutoString providerURI
;
1753 res
->GetValueUTF8(providerURI
);
1755 PRInt32 found
= providerURI
.RFindChar(':');
1756 if (found
== kNotFound
) {
1761 result
.Assign(Substring(providerURI
, found
+ 1));
1766 nsChromeRegistry::ProcessProvider(PRFileDesc
*fd
, nsIRDFService
* aRDFs
,
1767 nsIRDFDataSource
* aDS
, nsIRDFResource
* aRoot
,
1768 PRBool aIsLocale
, const nsACString
& aBaseURL
)
1770 NS_NAMED_LITERAL_CSTRING(kSlash
, "/");
1771 NS_NAMED_LITERAL_CSTRING(kTab
, "\t");
1775 nsCOMPtr
<nsIRDFResource
> packagesarc
;
1776 aRDFs
->GetResource(NS_LITERAL_CSTRING(kURICHROME_packages
),
1777 getter_AddRefs(packagesarc
));
1778 if (!packagesarc
) return;
1780 nsCOMPtr
<nsISimpleEnumerator
> providers
;
1781 rv
= GetContainerEnumerator(aDS
, aRoot
, getter_AddRefs(providers
));
1782 if (NS_FAILED(rv
)) {
1786 nsCOMPtr
<nsISupports
> next
;
1789 while (NS_SUCCEEDED(providers
->HasMoreElements(&more
)) && more
) {
1790 providers
->GetNext(getter_AddRefs(next
));
1791 NS_ASSERTION(next
, "GetNext failed after HasMoreElements succeeded.");
1793 nsCOMPtr
<nsIRDFResource
> provider (do_QueryInterface(next
));
1795 NS_WARNING("Provider isn't a nsIRDFResource.");
1799 nsCAutoString providerName
;
1800 GetResourceName(provider
, providerName
);
1801 if (providerName
.IsEmpty()) {
1802 NS_WARNING("Couldn't calculate resource name.");
1806 nsCOMPtr
<nsIRDFResource
> packages
;
1807 FollowResource(aDS
, provider
, packagesarc
, getter_AddRefs(packages
));
1809 NS_WARNING("No chrome:packages arc found!");
1814 nsCOMPtr
<nsISimpleEnumerator
> packageList
;
1815 rv
= GetContainerEnumerator(aDS
, packages
, getter_AddRefs(packageList
), &count
);
1816 if (NS_FAILED(rv
)) {
1817 NS_WARNING("chrome:packages was not a sequence.");
1821 nsCOMPtr
<nsISupports
> nextPackage
;
1823 PRBool morePackages
;
1824 while (NS_SUCCEEDED(packageList
->HasMoreElements(&morePackages
)) &&
1826 packageList
->GetNext(getter_AddRefs(nextPackage
));
1828 nsCOMPtr
<nsIRDFResource
> packageRes (do_QueryInterface(nextPackage
));
1830 NS_WARNING("chrome:packages Seq points to a non-resource!");
1834 nsCAutoString packageName
;
1835 GetResourceName(packageRes
, packageName
);
1836 if (packageName
.IsEmpty()) {
1837 NS_WARNING("couldn't extract a package name.");
1844 line
.AppendLiteral("locale\t");
1846 line
.AppendLiteral("skin\t");
1848 line
+= packageName
+ kTab
+ providerName
+ kTab
+ aBaseURL
;
1850 line
+= packageName
+ kSlash
;
1852 line
.AppendLiteral(NS_LINEBREAK
);
1853 PR_Write(fd
, line
.get(), line
.Length());
1859 GetLiteralText(nsIRDFLiteral
* lit
, nsACString
& result
)
1861 const PRUnichar
* value
;
1862 lit
->GetValueConst(&value
);
1863 CopyUTF16toUTF8(value
, result
);
1867 nsChromeRegistry::ProcessOverlays(PRFileDesc
*fd
, nsIRDFDataSource
* aDS
,
1868 nsIRDFResource
* aRoot
,
1869 const nsCSubstring
& aType
)
1871 NS_NAMED_LITERAL_CSTRING(kTab
, "\t");
1872 NS_NAMED_LITERAL_CSTRING(kLinebreak
, NS_LINEBREAK
);
1876 nsCOMPtr
<nsISimpleEnumerator
> overlaids
;
1877 rv
= GetContainerEnumerator(aDS
, aRoot
, getter_AddRefs(overlaids
));
1878 if (NS_FAILED(rv
)) {
1882 nsCOMPtr
<nsISupports
> next
;
1884 while (NS_SUCCEEDED(overlaids
->HasMoreElements(&more
)) && more
) {
1885 overlaids
->GetNext(getter_AddRefs(next
));
1886 NS_ASSERTION(next
, "GetNext failed after HasMoreElements succeeded.");
1888 nsCOMPtr
<nsIRDFResource
> overlaid (do_QueryInterface(next
));
1890 NS_WARNING("Overlay arc is not a nsIRDFResource.");
1894 nsCAutoString overlaidName
;
1895 overlaid
->GetValueUTF8(overlaidName
);
1897 nsCOMPtr
<nsISimpleEnumerator
> overlays
;
1898 rv
= GetContainerEnumerator(aDS
, overlaid
, getter_AddRefs(overlays
));
1902 while (NS_SUCCEEDED(overlays
->HasMoreElements(&more
)) && more
) {
1903 overlays
->GetNext(getter_AddRefs(next
));
1904 NS_ASSERTION(next
, "GetNext failed after HasMoreElements succeeded.");
1906 nsCOMPtr
<nsIRDFLiteral
> overlay (do_QueryInterface(next
));
1908 NS_WARNING("Overlay was not an RDF literal.");
1912 nsCAutoString overlayName
;
1913 GetLiteralText(overlay
, overlayName
);
1915 overlayName
.Insert(aType
+ kTab
+ overlaidName
+ kTab
, 0);
1916 overlayName
.Append(kLinebreak
);
1917 PR_Write(fd
, overlayName
.get(), overlayName
.Length());
1925 nsChromeRegistry::ProcessContentsManifest(nsIURI
* aOldManifest
, nsIURI
* aFile
,
1926 nsIURI
* aBaseURI
, PRBool aAppend
,
1929 return NS_ERROR_NOT_IMPLEMENTED
;
1935 nsChromeRegistry::ProcessManifest(nsILocalFile
* aManifest
, PRBool aSkinOnly
)
1940 rv
= aManifest
->OpenNSPRFileDesc(PR_RDONLY
, 0, &fd
);
1941 NS_ENSURE_SUCCESS(rv
, rv
);
1946 size
= PR_Available(fd
);
1948 rv
= NS_ERROR_UNEXPECTED
;
1952 buf
= (char *) malloc(size
+ 1);
1954 rv
= NS_ERROR_OUT_OF_MEMORY
;
1958 n
= PR_Read(fd
, buf
, size
);
1961 rv
= ProcessManifestBuffer(buf
, size
, aManifest
, aSkinOnly
);
1970 static const char kWhitespace
[] = "\t ";
1971 static const char kNewlines
[] = "\r\n";
1974 * Check for a modifier flag of the following forms:
1975 * "flag" (same as "true")
1977 * "flag="no|false|0"
1978 * @param aFlag The flag to compare.
1979 * @param aData The tokenized data to check; this is lowercased
1980 * before being passed in.
1981 * @param aResult If the flag is found, the value is assigned here.
1982 * @return Whether the flag was handled.
1985 CheckFlag(const nsSubstring
& aFlag
, const nsSubstring
& aData
, PRBool
& aResult
)
1987 if (!StringBeginsWith(aData
, aFlag
))
1990 if (aFlag
.Length() == aData
.Length()) {
1991 // the data is simply "flag", which is the same as "flag=yes"
1996 if (aData
.CharAt(aFlag
.Length()) != '=') {
1997 // the data is "flag2=", which is not anything we care about
2001 if (aData
.Length() == aFlag
.Length() + 1) {
2006 switch (aData
.CharAt(aFlag
.Length() + 1)) {
2030 * Check for a modifier flag of the following form:
2033 * @param aFlag The flag to compare.
2034 * @param aData The tokenized data to check; this is lowercased
2035 * before being passed in.
2036 * @param aValue The value that is expected.
2037 * @param aResult If this is "ok" when passed in, this is left alone.
2038 * Otherwise if the flag is found it is set to eBad or eOK.
2039 * @return Whether the flag was handled.
2042 CheckStringFlag(const nsSubstring
& aFlag
, const nsSubstring
& aData
,
2043 const nsSubstring
& aValue
, TriState
& aResult
)
2045 if (aData
.Length() < aFlag
.Length() + 1)
2048 if (!StringBeginsWith(aData
, aFlag
))
2051 PRBool comparison
= PR_TRUE
;
2052 if (aData
[aFlag
.Length()] != '=') {
2053 if (aData
[aFlag
.Length()] == '!' &&
2054 aData
.Length() >= aFlag
.Length() + 2 &&
2055 aData
[aFlag
.Length() + 1] == '=')
2056 comparison
= PR_FALSE
;
2061 if (aResult
!= eOK
) {
2062 nsDependentSubstring testdata
= Substring(aData
, aFlag
.Length() + (comparison
? 1 : 2));
2063 if (testdata
.Equals(aValue
))
2064 aResult
= comparison
? eOK
: eBad
;
2066 aResult
= comparison
? eBad
: eOK
;
2073 * Check for a modifier flag of the following form:
2079 * @param aFlag The flag to compare.
2080 * @param aData The tokenized data to check; this is lowercased
2081 * before being passed in.
2082 * @param aValue The value that is expected. If this is empty then no
2083 * comparison will match.
2084 * @param aChecker the version checker to use. If null, aResult will always
2086 * @param aResult If this is eOK when passed in, this is left alone.
2087 * Otherwise if the flag is found it is set to eBad or eOK.
2088 * @return Whether the flag was handled.
2091 #define COMPARE_EQ 1 << 0
2092 #define COMPARE_LT 1 << 1
2093 #define COMPARE_GT 1 << 2
2096 CheckVersionFlag(const nsSubstring
& aFlag
, const nsSubstring
& aData
,
2097 const nsSubstring
& aValue
, nsIVersionComparator
* aChecker
,
2100 if (aData
.Length() < aFlag
.Length() + 2)
2103 if (!StringBeginsWith(aData
, aFlag
))
2106 if (aValue
.Length() == 0) {
2112 PRUint32 comparison
;
2113 nsAutoString testdata
;
2115 switch (aData
[aFlag
.Length()]) {
2117 comparison
= COMPARE_EQ
;
2118 testdata
= Substring(aData
, aFlag
.Length() + 1);
2122 if (aData
[aFlag
.Length() + 1] == '=') {
2123 comparison
= COMPARE_EQ
| COMPARE_LT
;
2124 testdata
= Substring(aData
, aFlag
.Length() + 2);
2127 comparison
= COMPARE_LT
;
2128 testdata
= Substring(aData
, aFlag
.Length() + 1);
2133 if (aData
[aFlag
.Length() + 1] == '=') {
2134 comparison
= COMPARE_EQ
| COMPARE_GT
;
2135 testdata
= Substring(aData
, aFlag
.Length() + 2);
2138 comparison
= COMPARE_GT
;
2139 testdata
= Substring(aData
, aFlag
.Length() + 1);
2147 if (testdata
.Length() == 0)
2150 if (aResult
!= eOK
) {
2156 nsresult rv
= aChecker
->Compare(NS_ConvertUTF16toUTF8(aValue
),
2157 NS_ConvertUTF16toUTF8(testdata
), &c
);
2158 if (NS_FAILED(rv
)) {
2162 if ((c
== 0 && comparison
& COMPARE_EQ
) ||
2163 (c
< 0 && comparison
& COMPARE_LT
) ||
2164 (c
> 0 && comparison
& COMPARE_GT
))
2176 EnsureLowerCase(char *aBuf
)
2178 for (; *aBuf
; ++aBuf
) {
2180 if (ch
>= 'A' && ch
<= 'Z')
2181 *aBuf
= ch
+ 'a' - 'A';
2186 nsChromeRegistry::ProcessManifestBuffer(char *buf
, PRInt32 length
,
2187 nsILocalFile
* aManifest
,
2192 NS_NAMED_LITERAL_STRING(kPlatform
, "platform");
2193 NS_NAMED_LITERAL_STRING(kXPCNativeWrappers
, "xpcnativewrappers");
2194 NS_NAMED_LITERAL_STRING(kContentAccessible
, "contentaccessible");
2195 NS_NAMED_LITERAL_STRING(kApplication
, "application");
2196 NS_NAMED_LITERAL_STRING(kAppVersion
, "appversion");
2197 NS_NAMED_LITERAL_STRING(kOs
, "os");
2198 NS_NAMED_LITERAL_STRING(kOsVersion
, "osversion");
2200 nsCOMPtr
<nsIIOService
> io (do_GetIOService());
2201 if (!io
) return NS_ERROR_FAILURE
;
2203 nsCOMPtr
<nsIProtocolHandler
> ph
;
2204 rv
= io
->GetProtocolHandler("resource", getter_AddRefs(ph
));
2205 NS_ENSURE_SUCCESS(rv
, rv
);
2207 nsCOMPtr
<nsIResProtocolHandler
> rph (do_QueryInterface(ph
));
2208 if (!rph
) return NS_ERROR_FAILURE
;
2210 nsCOMPtr
<nsIURI
> manifestURI
;
2211 rv
= io
->NewFileURI(aManifest
, getter_AddRefs(manifestURI
));
2212 NS_ENSURE_SUCCESS(rv
, rv
);
2214 nsCOMPtr
<nsIXPConnect
> xpc (do_GetService("@mozilla.org/js/xpc/XPConnect;1"));
2215 nsCOMPtr
<nsIVersionComparator
> vc (do_GetService("@mozilla.org/xpcom/version-comparator;1"));
2218 nsAutoString appVersion
;
2219 nsAutoString osTarget
;
2220 nsCOMPtr
<nsIXULAppInfo
> xapp (do_GetService(XULAPPINFO_SERVICE_CONTRACTID
));
2223 rv
= xapp
->GetID(s
);
2224 if (NS_SUCCEEDED(rv
))
2225 CopyUTF8toUTF16(s
, appID
);
2227 rv
= xapp
->GetVersion(s
);
2228 if (NS_SUCCEEDED(rv
))
2229 CopyUTF8toUTF16(s
, appVersion
);
2231 nsCOMPtr
<nsIXULRuntime
> xruntime (do_QueryInterface(xapp
));
2233 rv
= xruntime
->GetOS(s
);
2234 if (NS_SUCCEEDED(rv
)) {
2235 CopyUTF8toUTF16(s
, osTarget
);
2236 ToLowerCase(osTarget
);
2241 nsAutoString osVersion
;
2243 OSVERSIONINFO info
= { sizeof(OSVERSIONINFO
) };
2244 if (GetVersionEx(&info
)) {
2245 nsTextFormatter::ssprintf(osVersion
, NS_LITERAL_STRING("%ld.%ld").get(),
2246 info
.dwMajorVersion
,
2247 info
.dwMinorVersion
);
2249 #elif defined(XP_MACOSX)
2250 long majorVersion
, minorVersion
;
2251 if ((Gestalt(gestaltSystemVersionMajor
, &majorVersion
) == noErr
) &&
2252 (Gestalt(gestaltSystemVersionMinor
, &minorVersion
) == noErr
)) {
2253 nsTextFormatter::ssprintf(osVersion
, NS_LITERAL_STRING("%ld.%ld").get(),
2257 #elif defined(MOZ_WIDGET_GTK2)
2258 nsTextFormatter::ssprintf(osVersion
, NS_LITERAL_STRING("%ld.%ld").get(),
2264 char *newline
= buf
;
2267 // outer loop tokenizes by newline
2268 while (nsnull
!= (token
= nsCRT::strtok(newline
, kNewlines
, &newline
))) {
2271 if (*token
== '#') // ignore lines that begin with # as comments
2274 char *whitespace
= token
;
2275 token
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2276 if (!token
) continue;
2278 if (!strcmp(token
, "content")) {
2280 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2281 "Warning: Ignoring content registration in skin-only manifest.");
2284 char *package
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2285 char *uri
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2286 if (!package
|| !uri
) {
2287 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2288 "Warning: Malformed content registration.");
2292 EnsureLowerCase(package
);
2294 // NOTE: We check for platform and xpcnativewrappers modifiers on
2295 // content packages, but they are *applied* to content|skin|locale.
2297 PRBool platform
= PR_FALSE
;
2298 PRBool xpcNativeWrappers
= PR_TRUE
;
2299 PRBool contentAccessible
= PR_FALSE
;
2300 TriState stAppVersion
= eUnspecified
;
2301 TriState stApp
= eUnspecified
;
2302 TriState stOsVersion
= eUnspecified
;
2303 TriState stOs
= eUnspecified
;
2305 PRBool badFlag
= PR_FALSE
;
2307 while (nsnull
!= (token
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
)) &&
2309 NS_ConvertASCIItoUTF16
wtoken(token
);
2310 ToLowerCase(wtoken
);
2312 if (CheckFlag(kPlatform
, wtoken
, platform
) ||
2313 CheckFlag(kXPCNativeWrappers
, wtoken
, xpcNativeWrappers
) ||
2314 CheckFlag(kContentAccessible
, wtoken
, contentAccessible
) ||
2315 CheckStringFlag(kApplication
, wtoken
, appID
, stApp
) ||
2316 CheckStringFlag(kOs
, wtoken
, osTarget
, stOs
) ||
2317 CheckVersionFlag(kOsVersion
, wtoken
, osVersion
, vc
, stOsVersion
) ||
2318 CheckVersionFlag(kAppVersion
, wtoken
, appVersion
, vc
, stAppVersion
))
2321 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2322 "Warning: Unrecognized chrome registration modifier '%s'.",
2327 if (badFlag
|| stApp
== eBad
|| stAppVersion
== eBad
||
2328 stOs
== eBad
|| stOsVersion
== eBad
)
2331 nsCOMPtr
<nsIURI
> resolved
;
2332 rv
= io
->NewURI(nsDependentCString(uri
), nsnull
, manifestURI
,
2333 getter_AddRefs(resolved
));
2337 PackageEntry
* entry
=
2338 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
2339 & (const nsACString
&) nsDependentCString(package
),
2342 return NS_ERROR_OUT_OF_MEMORY
;
2344 entry
->baseURI
= resolved
;
2347 entry
->flags
|= PackageEntry::PLATFORM_PACKAGE
;
2348 if (xpcNativeWrappers
)
2349 entry
->flags
|= PackageEntry::XPCNATIVEWRAPPERS
;
2350 if (contentAccessible
)
2351 entry
->flags
|= PackageEntry::CONTENT_ACCESSIBLE
;
2353 nsCAutoString
urlp("chrome://");
2354 urlp
.Append(package
);
2357 rv
= xpc
->FlagSystemFilenamePrefix(urlp
.get(), xpcNativeWrappers
);
2358 NS_ENSURE_SUCCESS(rv
, rv
);
2361 else if (!strcmp(token
, "locale")) {
2363 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2364 "Warning: Ignoring locale registration in skin-only manifest.");
2367 char *package
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2368 char *provider
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2369 char *uri
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2370 if (!package
|| !provider
|| !uri
) {
2371 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2372 "Warning: Malformed locale registration.");
2376 EnsureLowerCase(package
);
2378 TriState stAppVersion
= eUnspecified
;
2379 TriState stApp
= eUnspecified
;
2380 TriState stOs
= eUnspecified
;
2381 TriState stOsVersion
= eUnspecified
;
2383 PRBool badFlag
= PR_FALSE
;
2385 while (nsnull
!= (token
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
)) &&
2387 NS_ConvertASCIItoUTF16
wtoken(token
);
2388 ToLowerCase(wtoken
);
2390 if (CheckStringFlag(kApplication
, wtoken
, appID
, stApp
) ||
2391 CheckStringFlag(kOs
, wtoken
, osTarget
, stOs
) ||
2392 CheckVersionFlag(kOsVersion
, wtoken
, osVersion
, vc
, stOsVersion
) ||
2393 CheckVersionFlag(kAppVersion
, wtoken
, appVersion
, vc
, stAppVersion
))
2396 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2397 "Warning: Unrecognized chrome registration modifier '%s'.",
2402 if (badFlag
|| stApp
== eBad
|| stAppVersion
== eBad
||
2403 stOs
== eBad
|| stOsVersion
== eBad
)
2406 nsCOMPtr
<nsIURI
> resolved
;
2407 rv
= io
->NewURI(nsDependentCString(uri
), nsnull
, manifestURI
,
2408 getter_AddRefs(resolved
));
2412 PackageEntry
* entry
=
2413 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
2414 & (const nsACString
&) nsDependentCString(package
),
2417 return NS_ERROR_OUT_OF_MEMORY
;
2419 entry
->locales
.SetBase(nsDependentCString(provider
), resolved
);
2421 else if (!strcmp(token
, "skin")) {
2422 char *package
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2423 char *provider
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2424 char *uri
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2425 if (!package
|| !provider
|| !uri
) {
2426 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2427 "Warning: Malformed skin registration.");
2431 EnsureLowerCase(package
);
2433 TriState stAppVersion
= eUnspecified
;
2434 TriState stApp
= eUnspecified
;
2435 TriState stOs
= eUnspecified
;
2436 TriState stOsVersion
= eUnspecified
;
2438 PRBool badFlag
= PR_FALSE
;
2440 while (nsnull
!= (token
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
)) &&
2442 NS_ConvertASCIItoUTF16
wtoken(token
);
2443 ToLowerCase(wtoken
);
2445 if (CheckStringFlag(kApplication
, wtoken
, appID
, stApp
) ||
2446 CheckStringFlag(kOs
, wtoken
, osTarget
, stOs
) ||
2447 CheckVersionFlag(kOsVersion
, wtoken
, osVersion
, vc
, stOsVersion
) ||
2448 CheckVersionFlag(kAppVersion
, wtoken
, appVersion
, vc
, stAppVersion
))
2451 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2452 "Warning: Unrecognized chrome registration modifier '%s'.",
2457 if (badFlag
|| stApp
== eBad
|| stAppVersion
== eBad
||
2458 stOs
== eBad
|| stOsVersion
== eBad
)
2461 nsCOMPtr
<nsIURI
> resolved
;
2462 rv
= io
->NewURI(nsDependentCString(uri
), nsnull
, manifestURI
,
2463 getter_AddRefs(resolved
));
2467 PackageEntry
* entry
=
2468 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
2469 & (const nsACString
&) nsDependentCString(package
),
2472 return NS_ERROR_OUT_OF_MEMORY
;
2474 entry
->skins
.SetBase(nsDependentCString(provider
), resolved
);
2476 else if (!strcmp(token
, "overlay")) {
2478 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2479 "Warning: Ignoring overlay registration in skin-only manifest.");
2482 char *base
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2483 char *overlay
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2484 if (!base
|| !overlay
) {
2485 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2486 "Warning: malformed chrome overlay instruction.");
2490 TriState stAppVersion
= eUnspecified
;
2491 TriState stApp
= eUnspecified
;
2492 TriState stOs
= eUnspecified
;
2493 TriState stOsVersion
= eUnspecified
;
2495 PRBool badFlag
= PR_FALSE
;
2497 while (nsnull
!= (token
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
)) &&
2499 NS_ConvertASCIItoUTF16
wtoken(token
);
2500 ToLowerCase(wtoken
);
2502 if (CheckStringFlag(kApplication
, wtoken
, appID
, stApp
) ||
2503 CheckStringFlag(kOs
, wtoken
, osTarget
, stOs
) ||
2504 CheckVersionFlag(kOsVersion
, wtoken
, osVersion
, vc
, stOsVersion
) ||
2505 CheckVersionFlag(kAppVersion
, wtoken
, appVersion
, vc
, stAppVersion
))
2508 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2509 "Warning: Unrecognized chrome registration modifier '%s'.",
2514 if (badFlag
|| stApp
== eBad
|| stAppVersion
== eBad
||
2515 stOs
== eBad
|| stOsVersion
== eBad
)
2518 nsCOMPtr
<nsIURI
> baseuri
, overlayuri
;
2519 rv
= io
->NewURI(nsDependentCString(base
), nsnull
, nsnull
,
2520 getter_AddRefs(baseuri
));
2521 rv
|= io
->NewURI(nsDependentCString(overlay
), nsnull
, nsnull
,
2522 getter_AddRefs(overlayuri
));
2523 if (NS_FAILED(rv
)) {
2524 NS_WARNING("Could not make URIs for overlay directive. Ignoring.");
2528 mOverlayHash
.Add(baseuri
, overlayuri
);
2530 else if (!strcmp(token
, "style")) {
2531 char *base
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2532 char *overlay
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2533 if (!base
|| !overlay
) {
2534 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2535 "Warning: malformed chrome style instruction.");
2539 TriState stAppVersion
= eUnspecified
;
2540 TriState stApp
= eUnspecified
;
2541 TriState stOs
= eUnspecified
;
2542 TriState stOsVersion
= eUnspecified
;
2544 PRBool badFlag
= PR_FALSE
;
2546 while (nsnull
!= (token
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
)) &&
2548 NS_ConvertASCIItoUTF16
wtoken(token
);
2549 ToLowerCase(wtoken
);
2551 if (CheckStringFlag(kApplication
, wtoken
, appID
, stApp
) ||
2552 CheckStringFlag(kOs
, wtoken
, osTarget
, stOs
) ||
2553 CheckVersionFlag(kOsVersion
, wtoken
, osVersion
, vc
, stOsVersion
) ||
2554 CheckVersionFlag(kAppVersion
, wtoken
, appVersion
, vc
, stAppVersion
))
2557 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2558 "Warning: Unrecognized chrome registration modifier '%s'.",
2563 if (badFlag
|| stApp
== eBad
|| stAppVersion
== eBad
||
2564 stOs
== eBad
|| stOsVersion
== eBad
)
2567 nsCOMPtr
<nsIURI
> baseuri
, overlayuri
;
2568 rv
= io
->NewURI(nsDependentCString(base
), nsnull
, nsnull
,
2569 getter_AddRefs(baseuri
));
2570 rv
|= io
->NewURI(nsDependentCString(overlay
), nsnull
, nsnull
,
2571 getter_AddRefs(overlayuri
));
2575 mStyleHash
.Add(baseuri
, overlayuri
);
2577 else if (!strcmp(token
, "override")) {
2579 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2580 "Warning: Ignoring override registration in skin-only manifest.");
2584 char *chrome
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2585 char *resolved
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2586 if (!chrome
|| !resolved
) {
2587 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2588 "Warning: malformed chrome override instruction.");
2592 TriState stAppVersion
= eUnspecified
;
2593 TriState stApp
= eUnspecified
;
2594 TriState stOs
= eUnspecified
;
2595 TriState stOsVersion
= eUnspecified
;
2597 PRBool badFlag
= PR_FALSE
;
2599 while (nsnull
!= (token
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
)) &&
2601 NS_ConvertASCIItoUTF16
wtoken(token
);
2602 ToLowerCase(wtoken
);
2604 if (CheckStringFlag(kApplication
, wtoken
, appID
, stApp
) ||
2605 CheckStringFlag(kOs
, wtoken
, osTarget
, stOs
) ||
2606 CheckVersionFlag(kOsVersion
, wtoken
, osVersion
, vc
, stOsVersion
) ||
2607 CheckVersionFlag(kAppVersion
, wtoken
, appVersion
, vc
, stAppVersion
))
2610 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2611 "Warning: Unrecognized chrome registration modifier '%s'.",
2616 if (badFlag
|| stApp
== eBad
|| stAppVersion
== eBad
||
2617 stOs
== eBad
|| stOsVersion
== eBad
)
2620 nsCOMPtr
<nsIURI
> chromeuri
, resolveduri
;
2621 rv
= io
->NewURI(nsDependentCString(chrome
), nsnull
, nsnull
,
2622 getter_AddRefs(chromeuri
));
2623 rv
|= io
->NewURI(nsDependentCString(resolved
), nsnull
, manifestURI
,
2624 getter_AddRefs(resolveduri
));
2628 mOverrideTable
.Put(chromeuri
, resolveduri
);
2630 else if (!strcmp(token
, "resource")) {
2632 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2633 "Warning: Ignoring resource registration in skin-only manifest.");
2637 char *package
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2638 char *uri
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2639 if (!package
|| !uri
) {
2640 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2641 "Warning: Malformed resource registration.");
2645 EnsureLowerCase(package
);
2647 TriState stAppVersion
= eUnspecified
;
2648 TriState stApp
= eUnspecified
;
2649 TriState stOsVersion
= eUnspecified
;
2650 TriState stOs
= eUnspecified
;
2652 PRBool badFlag
= PR_FALSE
;
2654 while (nsnull
!= (token
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
)) &&
2656 NS_ConvertASCIItoUTF16
wtoken(token
);
2657 ToLowerCase(wtoken
);
2659 if (CheckStringFlag(kApplication
, wtoken
, appID
, stApp
) ||
2660 CheckStringFlag(kOs
, wtoken
, osTarget
, stOs
) ||
2661 CheckVersionFlag(kOsVersion
, wtoken
, osVersion
, vc
, stOsVersion
) ||
2662 CheckVersionFlag(kAppVersion
, wtoken
, appVersion
, vc
, stAppVersion
))
2665 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2666 "Warning: Unrecognized chrome registration modifier '%s'.",
2671 if (badFlag
|| stApp
== eBad
|| stAppVersion
== eBad
||
2672 stOs
== eBad
|| stOsVersion
== eBad
)
2675 nsDependentCString
host(package
);
2678 rv
= rph
->HasSubstitution(host
, &exists
);
2679 NS_ENSURE_SUCCESS(rv
, rv
);
2681 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2682 "Warning: Duplicate resource declaration for '%s' ignored.",
2687 nsCOMPtr
<nsIURI
> resolved
;
2688 rv
= io
->NewURI(nsDependentCString(uri
), nsnull
, manifestURI
,
2689 getter_AddRefs(resolved
));
2693 rv
= rph
->SetSubstitution(host
, resolved
);
2694 NS_ENSURE_SUCCESS(rv
, rv
);
2697 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2698 "Warning: Ignoring unrecognized chrome manifest instruction.");