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
)
256 CanLoadResource(nsIURI
* aResourceURI
)
258 PRBool isLocalResource
= PR_FALSE
;
259 (void)NS_URIChainHasFlags(aResourceURI
,
260 nsIProtocolHandler::URI_IS_LOCAL_RESOURCE
,
262 return isLocalResource
;
265 nsChromeRegistry::ProviderEntry
*
266 nsChromeRegistry::nsProviderArray::GetProvider(const nsACString
& aPreferred
, MatchType aType
)
268 PRInt32 i
= mArray
.Count();
272 ProviderEntry
* found
= nsnull
; // Only set if we find a partial-match locale
273 ProviderEntry
* entry
;
276 entry
= reinterpret_cast<ProviderEntry
*>(mArray
[i
]);
277 if (aPreferred
.Equals(entry
->provider
))
283 if (LanguagesMatch(aPreferred
, entry
->provider
)) {
288 if (!found
&& entry
->provider
.EqualsLiteral("en-US"))
292 if (!found
&& aType
!= EXACT
)
299 nsChromeRegistry::nsProviderArray::GetBase(const nsACString
& aPreferred
, MatchType aType
)
301 ProviderEntry
* provider
= GetProvider(aPreferred
, aType
);
306 return provider
->baseURI
;
310 nsChromeRegistry::nsProviderArray::GetSelected(const nsACString
& aPreferred
, MatchType aType
)
312 ProviderEntry
* entry
= GetProvider(aPreferred
, aType
);
315 return entry
->provider
;
317 return EmptyCString();
321 nsChromeRegistry::nsProviderArray::SetBase(const nsACString
& aProvider
, nsIURI
* aBaseURL
)
323 ProviderEntry
* provider
= GetProvider(aProvider
, EXACT
);
326 provider
->baseURI
= aBaseURL
;
330 // no existing entries, add a new one
331 provider
= new ProviderEntry(aProvider
, aBaseURL
);
333 return; // It's safe to silently fail on OOM
335 mArray
.AppendElement(provider
);
339 nsChromeRegistry::nsProviderArray::EnumerateToArray(nsCStringArray
*a
)
341 PRInt32 i
= mArray
.Count();
343 ProviderEntry
*entry
= reinterpret_cast<ProviderEntry
*>(mArray
[i
]);
344 a
->AppendCString(entry
->provider
);
349 nsChromeRegistry::nsProviderArray::Clear()
351 PRInt32 i
= mArray
.Count();
353 ProviderEntry
* entry
= reinterpret_cast<ProviderEntry
*>(mArray
[i
]);
360 nsChromeRegistry::PackageEntry::PackageEntry(const nsACString
& aPackage
) :
361 package(aPackage
), flags(0)
366 nsChromeRegistry::HashKey(PLDHashTable
*table
, const void *key
)
368 const nsACString
& str
= *reinterpret_cast<const nsACString
*>(key
);
369 return HashString(str
);
373 nsChromeRegistry::MatchKey(PLDHashTable
*table
, const PLDHashEntryHdr
*entry
,
376 const nsACString
& str
= *reinterpret_cast<const nsACString
*>(key
);
377 const PackageEntry
* pentry
= static_cast<const PackageEntry
*>(entry
);
378 return str
.Equals(pentry
->package
);
382 nsChromeRegistry::ClearEntry(PLDHashTable
*table
, PLDHashEntryHdr
*entry
)
384 PackageEntry
* pentry
= static_cast<PackageEntry
*>(entry
);
385 pentry
->~PackageEntry();
389 nsChromeRegistry::InitEntry(PLDHashTable
*table
, PLDHashEntryHdr
*entry
,
392 const nsACString
& str
= *reinterpret_cast<const nsACString
*>(key
);
394 new (entry
) PackageEntry(str
);
398 const PLDHashTableOps
399 nsChromeRegistry::kTableOps
= {
404 PL_DHashMoveEntryStub
,
406 PL_DHashFinalizeStub
,
411 nsChromeRegistry::OverlayListEntry::AddURI(nsIURI
* aURI
)
413 PRInt32 i
= mArray
.Count();
416 if (NS_SUCCEEDED(aURI
->Equals(mArray
[i
], &equals
)) && equals
)
420 mArray
.AppendObject(aURI
);
424 nsChromeRegistry::OverlayListHash::Add(nsIURI
* aBase
, nsIURI
* aOverlay
)
426 OverlayListEntry
* entry
= mTable
.PutEntry(aBase
);
428 entry
->AddURI(aOverlay
);
431 const nsCOMArray
<nsIURI
>*
432 nsChromeRegistry::OverlayListHash::GetArray(nsIURI
* aBase
)
434 OverlayListEntry
* entry
= mTable
.GetEntry(aBase
);
438 return &entry
->mArray
;
441 nsChromeRegistry::~nsChromeRegistry()
443 if (mPackagesHash
.ops
)
444 PL_DHashTableFinish(&mPackagesHash
);
445 gChromeRegistry
= nsnull
;
448 NS_INTERFACE_MAP_BEGIN(nsChromeRegistry
)
449 NS_INTERFACE_MAP_ENTRY(nsIChromeRegistry
)
450 NS_INTERFACE_MAP_ENTRY(nsIXULChromeRegistry
)
451 NS_INTERFACE_MAP_ENTRY(nsIToolkitChromeRegistry
)
453 NS_INTERFACE_MAP_ENTRY(nsIXULOverlayProvider
)
455 NS_INTERFACE_MAP_ENTRY(nsIObserver
)
456 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference
)
457 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIChromeRegistry
)
460 NS_IMPL_ADDREF(nsChromeRegistry
)
461 NS_IMPL_RELEASE(nsChromeRegistry
)
463 ////////////////////////////////////////////////////////////////////////////////
464 // nsIChromeRegistry methods:
467 getUILangCountry(nsACString
& aUILang
)
471 nsCOMPtr
<nsILocaleService
> localeService
= do_GetService(NS_LOCALESERVICE_CONTRACTID
, &rv
);
472 NS_ENSURE_SUCCESS(rv
, rv
);
475 rv
= localeService
->GetLocaleComponentForUserAgent(uiLang
);
476 NS_ENSURE_SUCCESS(rv
, rv
);
478 CopyUTF16toUTF8(uiLang
, aUILang
);
483 nsChromeRegistry::Init()
487 // these atoms appear in almost every chrome registry contents.rdf
488 // in some form or another. making static atoms prevents the atoms
489 // from constantly being created/destroyed during parsing
491 static const nsStaticAtom atoms
[] = {
492 { "chrome", nsnull
},
494 { "allowScripts", nsnull
},
495 { "package", nsnull
},
496 { "packages", nsnull
},
497 { "hasOverlays", nsnull
},
500 NS_RegisterStaticAtoms(atoms
, NS_ARRAY_LENGTH(atoms
));
502 // Check to see if necko and the JAR protocol handler are registered yet
503 // if not, somebody is doing work during XPCOM registration that they
504 // shouldn't be doing. See bug 292549, where JS components are trying
505 // to call Components.utils.import("chrome:///") early in registration
507 nsCOMPtr
<nsIIOService
> io (do_GetIOService());
508 if (!io
) return NS_ERROR_FAILURE
;
510 nsCOMPtr
<nsIProtocolHandler
> ph
;
511 rv
= io
->GetProtocolHandler("jar", getter_AddRefs(ph
));
512 NS_ENSURE_SUCCESS(rv
, rv
);
514 nsCOMPtr
<nsIJARProtocolHandler
> jph
= do_QueryInterface(ph
);
516 return NS_ERROR_NOT_INITIALIZED
;
518 if (!PL_DHashTableInit(&mPackagesHash
, &kTableOps
,
519 nsnull
, sizeof(PackageEntry
), 16))
520 return NS_ERROR_FAILURE
;
522 if (!mOverlayHash
.Init() ||
523 !mStyleHash
.Init() ||
524 !mOverrideTable
.Init())
525 return NS_ERROR_FAILURE
;
527 mSelectedLocale
= NS_LITERAL_CSTRING("en-US");
528 mSelectedSkin
= NS_LITERAL_CSTRING("classic/1.0");
530 // This initialization process is fairly complicated and may cause reentrant
531 // getservice calls to resolve chrome URIs (especially locale files). We
532 // don't want that, so we inform the protocol handler about our existence
533 // before we are actually fully initialized.
534 gChromeRegistry
= this;
536 PRBool safeMode
= PR_FALSE
;
537 nsCOMPtr
<nsIXULRuntime
> xulrun (do_GetService(XULAPPINFO_SERVICE_CONTRACTID
));
539 xulrun
->GetInSafeMode(&safeMode
);
541 nsCOMPtr
<nsIPrefService
> prefserv (do_GetService(NS_PREFSERVICE_CONTRACTID
));
542 nsCOMPtr
<nsIPrefBranch
> prefs
;
545 prefserv
->GetDefaultBranch(nsnull
, getter_AddRefs(prefs
));
547 prefs
= do_QueryInterface(prefserv
);
550 NS_WARNING("Could not get pref service!");
553 PRBool useLocalePref
= PR_TRUE
;
556 // check the pref first
557 PRBool matchOS
= PR_FALSE
;
558 rv
= prefs
->GetBoolPref(MATCH_OS_LOCALE_PREF
, &matchOS
);
561 if (NS_SUCCEEDED(rv
) && matchOS
) {
562 // compute lang and region code only when needed!
563 nsCAutoString uiLocale
;
564 rv
= getUILangCountry(uiLocale
);
565 if (NS_SUCCEEDED(rv
)) {
566 useLocalePref
= PR_FALSE
;
567 mSelectedLocale
= uiLocale
;
573 nsXPIDLCString provider
;
575 rv
= prefs
->GetCharPref(SELECTED_SKIN_PREF
, getter_Copies(provider
));
576 if (NS_SUCCEEDED(rv
))
577 mSelectedSkin
= provider
;
579 nsCOMPtr
<nsIPrefBranch2
> prefs2 (do_QueryInterface(prefs
));
582 rv
= prefs2
->AddObserver(SELECTED_SKIN_PREF
, this, PR_TRUE
);
585 rv
= prefs
->GetCharPref(SELECTED_LOCALE_PREF
, getter_Copies(provider
));
586 if (NS_SUCCEEDED(rv
))
587 mSelectedLocale
= provider
;
590 prefs2
->AddObserver(SELECTED_LOCALE_PREF
, this, PR_TRUE
);
596 mInitialized
= PR_TRUE
;
602 nsChromeRegistry::CheckForOSAccessibility()
606 nsCOMPtr
<nsILookAndFeel
> lookAndFeel (do_GetService(kLookAndFeelCID
));
608 PRInt32 useAccessibilityTheme
= 0;
610 rv
= lookAndFeel
->GetMetric(nsILookAndFeel::eMetric_UseAccessibilityTheme
,
611 useAccessibilityTheme
);
613 if (NS_SUCCEEDED(rv
) && useAccessibilityTheme
) {
614 /* Set the skin to classic and remove pref observers */
615 if (!mSelectedSkin
.EqualsLiteral("classic/1.0")) {
616 mSelectedSkin
.AssignLiteral("classic/1.0");
620 nsCOMPtr
<nsIPrefBranch2
> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID
));
622 prefs
->RemoveObserver(SELECTED_SKIN_PREF
, this);
631 nsChromeRegistry::GetProviderAndPath(nsIURL
* aChromeURL
,
632 nsACString
& aProvider
, nsACString
& aPath
)
638 aChromeURL
->SchemeIs("chrome", &isChrome
);
639 NS_ASSERTION(isChrome
, "Non-chrome URI?");
643 rv
= aChromeURL
->GetPath(path
);
644 NS_ENSURE_SUCCESS(rv
, rv
);
646 if (path
.Length() < 3) {
647 LogMessage("Invalid chrome URI: %s", path
.get());
648 return NS_ERROR_FAILURE
;
651 path
.SetLength(nsUnescapeCount(path
.BeginWriting()));
652 NS_ASSERTION(path
.First() == '/', "Path should always begin with a slash!");
654 PRInt32 slash
= path
.FindChar('/', 1);
656 LogMessage("Invalid chrome URI: %s", path
.get());
657 return NS_ERROR_FAILURE
;
664 if (slash
== (PRInt32
) path
.Length() - 1)
667 aPath
.Assign(path
.get() + slash
+ 1, path
.Length() - slash
- 1);
672 aProvider
.Assign(path
.get() + 1, slash
);
678 nsChromeRegistry::Canonify(nsIURL
* aChromeURL
)
680 NS_NAMED_LITERAL_CSTRING(kSlash
, "/");
684 nsCAutoString provider
, path
;
685 rv
= GetProviderAndPath(aChromeURL
, provider
, path
);
686 NS_ENSURE_SUCCESS(rv
, rv
);
688 if (path
.IsEmpty()) {
689 nsCAutoString package
;
690 rv
= aChromeURL
->GetHost(package
);
691 NS_ENSURE_SUCCESS(rv
, rv
);
693 // we re-use the "path" local string to build a new URL path
694 path
.Assign(kSlash
+ provider
+ kSlash
+ package
);
695 if (provider
.EqualsLiteral("content")) {
696 path
.AppendLiteral(".xul");
698 else if (provider
.EqualsLiteral("locale")) {
699 path
.AppendLiteral(".dtd");
701 else if (provider
.EqualsLiteral("skin")) {
702 path
.AppendLiteral(".css");
705 return NS_ERROR_INVALID_ARG
;
707 aChromeURL
->SetPath(path
);
710 // prevent directory traversals ("..")
711 // path is already unescaped once, but uris can get unescaped twice
712 const char* pos
= path
.BeginReading();
713 const char* end
= path
.EndReading();
717 return NS_ERROR_DOM_BAD_URI
;
720 return NS_ERROR_DOM_BAD_URI
;
723 // chrome: URIs with double-escapes are trying to trick us.
724 // watch for %2e, and %25 in case someone triple unescapes
726 ( pos
[2] == 'e' || pos
[2] == 'E' ||
728 return NS_ERROR_DOM_BAD_URI
;
743 nsChromeRegistry::ConvertChromeURL(nsIURI
* aChromeURI
, nsIURI
* *aResult
)
746 NS_ASSERTION(aChromeURI
, "null url!");
748 if (mOverrideTable
.Get(aChromeURI
, aResult
))
751 nsCOMPtr
<nsIURL
> chromeURL (do_QueryInterface(aChromeURI
));
752 NS_ENSURE_TRUE(chromeURL
, NS_NOINTERFACE
);
754 nsCAutoString package
, provider
, path
;
755 rv
= chromeURL
->GetHostPort(package
);
756 NS_ENSURE_SUCCESS(rv
, rv
);
758 rv
= GetProviderAndPath(chromeURL
, provider
, path
);
759 NS_ENSURE_SUCCESS(rv
, rv
);
761 PackageEntry
* entry
=
762 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
763 & (nsACString
&) package
,
766 if (PL_DHASH_ENTRY_IS_FREE(entry
)) {
768 return NS_ERROR_NOT_INITIALIZED
;
770 LogMessage("No chrome package registered for chrome://%s/%s/%s",
771 package
.get(), provider
.get(), path
.get());
773 return NS_ERROR_FAILURE
;
776 if (entry
->flags
& PackageEntry::PLATFORM_PACKAGE
) {
777 #if defined(XP_WIN) || defined(XP_OS2)
778 path
.Insert("win/", 0);
779 #elif defined(XP_MACOSX)
780 path
.Insert("mac/", 0);
782 path
.Insert("unix/", 0);
786 nsIURI
* baseURI
= nsnull
;
787 if (provider
.EqualsLiteral("locale")) {
788 baseURI
= entry
->locales
.GetBase(mSelectedLocale
, nsProviderArray::LOCALE
);
790 else if (provider
.EqualsLiteral("skin")) {
791 baseURI
= entry
->skins
.GetBase(mSelectedSkin
, nsProviderArray::ANY
);
793 else if (provider
.EqualsLiteral("content")) {
794 baseURI
= entry
->baseURI
;
798 LogMessage("No chrome package registered for chrome://%s/%s/%s",
799 package
.get(), provider
.get(), path
.get());
800 return NS_ERROR_FAILURE
;
803 return NS_NewURI(aResult
, path
, nsnull
, baseURI
);
807 nsChromeRegistry::GetSelectedLocale(const nsACString
& aPackage
, nsACString
& aLocale
)
809 PackageEntry
* entry
=
810 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
814 if (PL_DHASH_ENTRY_IS_FREE(entry
))
815 return NS_ERROR_FAILURE
;
817 aLocale
= entry
->locales
.GetSelected(mSelectedLocale
, nsProviderArray::LOCALE
);
818 if (aLocale
.IsEmpty())
819 return NS_ERROR_FAILURE
;
825 nsChromeRegistry::GetLocalesForPackage(const nsACString
& aPackage
,
826 nsIUTF8StringEnumerator
* *aResult
)
828 nsCStringArray
*a
= new nsCStringArray
;
830 return NS_ERROR_OUT_OF_MEMORY
;
832 PackageEntry
* entry
=
833 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
837 if (PL_DHASH_ENTRY_IS_BUSY(entry
)) {
838 entry
->locales
.EnumerateToArray(a
);
841 nsresult rv
= NS_NewAdoptingUTF8StringEnumerator(aResult
, a
);
850 nsChromeRegistry::GetStyleOverlays(nsIURI
*aChromeURL
,
851 nsISimpleEnumerator
**aResult
)
853 const nsCOMArray
<nsIURI
>* parray
= mStyleHash
.GetArray(aChromeURL
);
855 return NS_NewEmptyEnumerator(aResult
);
857 return NS_NewArrayEnumerator(aResult
, *parray
);
861 nsChromeRegistry::GetXULOverlays(nsIURI
*aChromeURL
, nsISimpleEnumerator
**aResult
)
863 const nsCOMArray
<nsIURI
>* parray
= mOverlayHash
.GetArray(aChromeURL
);
865 return NS_NewEmptyEnumerator(aResult
);
867 return NS_NewArrayEnumerator(aResult
, *parray
);
871 ////////////////////////////////////////////////////////////////////////
876 static void FlushSkinBindingsForWindow(nsIDOMWindowInternal
* aWindow
)
878 // Get the DOM document.
879 nsCOMPtr
<nsIDOMDocument
> domDocument
;
880 aWindow
->GetDocument(getter_AddRefs(domDocument
));
884 nsCOMPtr
<nsIDocument
> document
= do_QueryInterface(domDocument
);
888 // Annihilate all XBL bindings.
889 document
->FlushSkinBindings();
892 // XXXbsmedberg: move this to nsIWindowMediator
893 NS_IMETHODIMP
nsChromeRegistry::RefreshSkins()
895 nsCOMPtr
<nsICSSLoader
> cssLoader(do_CreateInstance(kCSSLoaderCID
));
899 nsCOMPtr
<nsIWindowMediator
> windowMediator
900 (do_GetService(NS_WINDOWMEDIATOR_CONTRACTID
));
904 nsCOMPtr
<nsISimpleEnumerator
> windowEnumerator
;
905 windowMediator
->GetEnumerator(nsnull
, getter_AddRefs(windowEnumerator
));
907 windowEnumerator
->HasMoreElements(&more
);
909 nsCOMPtr
<nsISupports
> protoWindow
;
910 windowEnumerator
->GetNext(getter_AddRefs(protoWindow
));
912 nsCOMPtr
<nsIDOMWindowInternal
> domWindow
= do_QueryInterface(protoWindow
);
914 FlushSkinBindingsForWindow(domWindow
);
916 windowEnumerator
->HasMoreElements(&more
);
921 windowMediator
->GetEnumerator(nsnull
, getter_AddRefs(windowEnumerator
));
922 windowEnumerator
->HasMoreElements(&more
);
924 nsCOMPtr
<nsISupports
> protoWindow
;
925 windowEnumerator
->GetNext(getter_AddRefs(protoWindow
));
927 nsCOMPtr
<nsIDOMWindowInternal
> domWindow
= do_QueryInterface(protoWindow
);
929 RefreshWindow(domWindow
, cssLoader
);
931 windowEnumerator
->HasMoreElements(&more
);
938 nsChromeRegistry::FlushSkinCaches()
940 nsCOMPtr
<nsIObserverService
> obsSvc
=
941 do_GetService("@mozilla.org/observer-service;1");
942 NS_ASSERTION(obsSvc
, "Couldn't get observer service.");
944 obsSvc
->NotifyObservers(static_cast<nsIChromeRegistry
*>(this),
945 NS_CHROME_FLUSH_SKINS_TOPIC
, nsnull
);
948 static PRBool
IsChromeURI(nsIURI
* aURI
)
950 PRBool isChrome
=PR_FALSE
;
951 if (NS_SUCCEEDED(aURI
->SchemeIs("chrome", &isChrome
)) && isChrome
)
956 // XXXbsmedberg: move this to windowmediator
957 nsresult
nsChromeRegistry::RefreshWindow(nsIDOMWindowInternal
* aWindow
,
958 nsICSSLoader
* aCSSLoader
)
960 // Deal with our subframes first.
961 nsCOMPtr
<nsIDOMWindowCollection
> frames
;
962 aWindow
->GetFrames(getter_AddRefs(frames
));
964 frames
->GetLength(&length
);
966 for (j
= 0; j
< length
; j
++) {
967 nsCOMPtr
<nsIDOMWindow
> childWin
;
968 frames
->Item(j
, getter_AddRefs(childWin
));
969 nsCOMPtr
<nsIDOMWindowInternal
> childInt(do_QueryInterface(childWin
));
970 RefreshWindow(childInt
, aCSSLoader
);
974 // Get the DOM document.
975 nsCOMPtr
<nsIDOMDocument
> domDocument
;
976 aWindow
->GetDocument(getter_AddRefs(domDocument
));
980 nsCOMPtr
<nsIDocument
> document
= do_QueryInterface(domDocument
);
984 // Deal with the agent sheets first. Have to do all the style sets by hand.
985 nsPresShellIterator
iter(document
);
986 nsCOMPtr
<nsIPresShell
> shell
;
987 while ((shell
= iter
.GetNextShell())) {
988 // Reload only the chrome URL agent style sheets.
989 nsCOMArray
<nsIStyleSheet
> agentSheets
;
990 rv
= shell
->GetAgentStyleSheets(agentSheets
);
991 NS_ENSURE_SUCCESS(rv
, rv
);
993 nsCOMArray
<nsIStyleSheet
> newAgentSheets
;
994 for (PRInt32 l
= 0; l
< agentSheets
.Count(); ++l
) {
995 nsIStyleSheet
*sheet
= agentSheets
[l
];
997 nsCOMPtr
<nsIURI
> uri
;
998 rv
= sheet
->GetSheetURI(getter_AddRefs(uri
));
999 if (NS_FAILED(rv
)) return rv
;
1001 if (IsChromeURI(uri
)) {
1002 // Reload the sheet.
1003 nsCOMPtr
<nsICSSStyleSheet
> newSheet
;
1004 rv
= aCSSLoader
->LoadSheetSync(uri
, PR_TRUE
, getter_AddRefs(newSheet
));
1005 if (NS_FAILED(rv
)) return rv
;
1007 rv
= newAgentSheets
.AppendObject(newSheet
) ? NS_OK
: NS_ERROR_FAILURE
;
1008 if (NS_FAILED(rv
)) return rv
;
1011 else { // Just use the same sheet.
1012 rv
= newAgentSheets
.AppendObject(sheet
) ? NS_OK
: NS_ERROR_FAILURE
;
1013 if (NS_FAILED(rv
)) return rv
;
1017 rv
= shell
->SetAgentStyleSheets(newAgentSheets
);
1018 NS_ENSURE_SUCCESS(rv
, rv
);
1021 // Build an array of nsIURIs of style sheets we need to load.
1022 nsCOMArray
<nsIStyleSheet
> oldSheets
;
1023 nsCOMArray
<nsIStyleSheet
> newSheets
;
1025 PRInt32 count
= document
->GetNumberOfStyleSheets();
1027 // Iterate over the style sheets.
1029 for (i
= 0; i
< count
; i
++) {
1030 // Get the style sheet
1031 nsIStyleSheet
*styleSheet
= document
->GetStyleSheetAt(i
);
1033 if (!oldSheets
.AppendObject(styleSheet
)) {
1034 return NS_ERROR_OUT_OF_MEMORY
;
1038 // Iterate over our old sheets and kick off a sync load of the new
1039 // sheet if and only if it's a chrome URL.
1040 for (i
= 0; i
< count
; i
++) {
1041 nsCOMPtr
<nsIStyleSheet
> sheet
= oldSheets
[i
];
1042 nsCOMPtr
<nsIURI
> uri
;
1043 rv
= sheet
->GetSheetURI(getter_AddRefs(uri
));
1044 if (NS_FAILED(rv
)) return rv
;
1046 if (IsChromeURI(uri
)) {
1047 // Reload the sheet.
1049 nsCOMPtr
<nsICSSStyleSheet
> oldCSSSheet
= do_QueryInterface(sheet
);
1050 NS_ASSERTION(oldCSSSheet
, "Don't know how to reload a non-CSS sheet");
1052 nsCOMPtr
<nsICSSStyleSheet
> newSheet
;
1053 // XXX what about chrome sheets that have a title or are disabled? This
1054 // only works by sheer dumb luck.
1055 // XXXbz this should really use the document's CSSLoader!
1056 aCSSLoader
->LoadSheetSync(uri
, getter_AddRefs(newSheet
));
1057 // Even if it's null, we put in in there.
1058 newSheets
.AppendObject(newSheet
);
1061 // Just use the same sheet.
1062 newSheets
.AppendObject(sheet
);
1066 // Now notify the document that multiple sheets have been added and removed.
1067 document
->UpdateStyleSheets(oldSheets
, newSheets
);
1072 nsChromeRegistry::FlushAllCaches()
1074 nsCOMPtr
<nsIObserverService
> obsSvc
=
1075 do_GetService("@mozilla.org/observer-service;1");
1076 NS_ASSERTION(obsSvc
, "Couldn't get observer service.");
1078 obsSvc
->NotifyObservers((nsIChromeRegistry
*) this,
1079 NS_CHROME_FLUSH_TOPIC
, nsnull
);
1082 // xxxbsmedberg Move me to nsIWindowMediator
1084 nsChromeRegistry::ReloadChrome()
1087 // Do a reload of all top level windows.
1088 nsresult rv
= NS_OK
;
1090 // Get the window mediator
1091 nsCOMPtr
<nsIWindowMediator
> windowMediator
1092 (do_GetService(NS_WINDOWMEDIATOR_CONTRACTID
));
1093 if (windowMediator
) {
1094 nsCOMPtr
<nsISimpleEnumerator
> windowEnumerator
;
1096 rv
= windowMediator
->GetEnumerator(nsnull
, getter_AddRefs(windowEnumerator
));
1097 if (NS_SUCCEEDED(rv
)) {
1098 // Get each dom window
1100 rv
= windowEnumerator
->HasMoreElements(&more
);
1101 if (NS_FAILED(rv
)) return rv
;
1103 nsCOMPtr
<nsISupports
> protoWindow
;
1104 rv
= windowEnumerator
->GetNext(getter_AddRefs(protoWindow
));
1105 if (NS_SUCCEEDED(rv
)) {
1106 nsCOMPtr
<nsIDOMWindowInternal
> domWindow
=
1107 do_QueryInterface(protoWindow
);
1109 nsCOMPtr
<nsIDOMLocation
> location
;
1110 domWindow
->GetLocation(getter_AddRefs(location
));
1112 rv
= location
->Reload(PR_FALSE
);
1113 if (NS_FAILED(rv
)) return rv
;
1117 rv
= windowEnumerator
->HasMoreElements(&more
);
1118 if (NS_FAILED(rv
)) return rv
;
1126 nsChromeRegistry::AllowScriptsForPackage(nsIURI
* aChromeURI
, PRBool
*aResult
)
1129 *aResult
= PR_FALSE
;
1133 aChromeURI
->SchemeIs("chrome", &isChrome
);
1134 NS_ASSERTION(isChrome
, "Non-chrome URI passed to AllowScriptsForPackage!");
1137 nsCOMPtr
<nsIURL
> url (do_QueryInterface(aChromeURI
));
1138 NS_ENSURE_TRUE(url
, NS_NOINTERFACE
);
1140 nsCAutoString provider
, file
;
1141 rv
= GetProviderAndPath(url
, provider
, file
);
1142 NS_ENSURE_SUCCESS(rv
, rv
);
1144 if (!provider
.EqualsLiteral("skin"))
1151 nsChromeRegistry::AllowContentToAccess(nsIURI
*aURI
, PRBool
*aResult
)
1155 *aResult
= PR_FALSE
;
1159 aURI
->SchemeIs("chrome", &isChrome
);
1160 NS_ASSERTION(isChrome
, "Non-chrome URI passed to AllowContentToAccess!");
1163 nsCOMPtr
<nsIURL
> url
= do_QueryInterface(aURI
);
1165 NS_ERROR("Chrome URL doesn't implement nsIURL.");
1166 return NS_ERROR_UNEXPECTED
;
1169 nsCAutoString package
;
1170 rv
= url
->GetHostPort(package
);
1171 NS_ENSURE_SUCCESS(rv
, rv
);
1173 PackageEntry
*entry
=
1174 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
1175 & (nsACString
&) package
,
1178 if (PL_DHASH_ENTRY_IS_BUSY(entry
)) {
1179 *aResult
= !!(entry
->flags
& PackageEntry::CONTENT_ACCESSIBLE
);
1184 static PLDHashOperator
1185 RemoveAll(PLDHashTable
*table
, PLDHashEntryHdr
*entry
, PRUint32 number
, void *arg
)
1187 return (PLDHashOperator
) (PL_DHASH_NEXT
| PL_DHASH_REMOVE
);
1191 nsChromeRegistry::CheckForNewChrome()
1195 PL_DHashTableEnumerate(&mPackagesHash
, RemoveAll
, nsnull
);
1196 mOverlayHash
.Clear();
1198 mOverrideTable
.Clear();
1200 nsCOMPtr
<nsIURI
> manifestURI
;
1201 rv
= NS_NewURI(getter_AddRefs(manifestURI
),
1202 NS_LITERAL_CSTRING("resource:///chrome/app-chrome.manifest"));
1204 // this is the main manifest; if it doesn't exist we generate it from
1205 // installed-chrome.txt. When the build system learns about the new system,
1206 // this code can go away.
1208 nsCOMPtr
<nsIFileURL
> manifestFileURL (do_QueryInterface(manifestURI
));
1209 NS_ASSERTION(manifestFileURL
, "Not a nsIFileURL!");
1210 NS_ENSURE_TRUE(manifestFileURL
, NS_ERROR_UNEXPECTED
);
1212 nsCOMPtr
<nsIFile
> manifest
;
1213 manifestFileURL
->GetFile(getter_AddRefs(manifest
));
1214 NS_ENSURE_TRUE(manifest
, NS_ERROR_FAILURE
);
1217 rv
= manifest
->Exists(&exists
);
1218 NS_ENSURE_SUCCESS(rv
, rv
);
1221 // In debug builds, installed-chrome.txt may change during development;
1222 // we just rebuild it every time because we're not worried about startup
1223 // time or other bad/goodness.
1225 manifest
->Remove(PR_FALSE
);
1231 nsCOMPtr
<nsIFile
> installed
;
1232 manifest
->Clone(getter_AddRefs(installed
));
1234 return NS_ERROR_OUT_OF_MEMORY
;
1236 nsCOMPtr
<nsILocalFile
> linstalled (do_QueryInterface(installed
));
1237 NS_ENSURE_TRUE(linstalled
, NS_NOINTERFACE
);
1239 linstalled
->SetNativeLeafName(NS_LITERAL_CSTRING("installed-chrome.txt"));
1241 rv
= linstalled
->Exists(&exists
);
1242 NS_ENSURE_SUCCESS(rv
, rv
);
1244 // process installed-chrome.txt into app-chrome.manifest
1246 ProcessNewChromeFile(linstalled
, manifestURI
);
1249 nsCOMPtr
<nsIProperties
> dirSvc (do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID
));
1250 NS_ENSURE_TRUE(dirSvc
, NS_ERROR_FAILURE
);
1252 // check the extra chrome directories
1253 nsCOMPtr
<nsISimpleEnumerator
> chromeML
;
1254 rv
= dirSvc
->Get(NS_CHROME_MANIFESTS_FILE_LIST
, NS_GET_IID(nsISimpleEnumerator
),
1255 getter_AddRefs(chromeML
));
1256 if (NS_FAILED(rv
)) {
1257 // ok, then simply load all .manifest files in the app chrome dir.
1258 nsCOMPtr
<nsIFile
> chromeDir
;
1259 rv
= dirSvc
->Get(NS_APP_CHROME_DIR
, NS_GET_IID(nsIFile
),
1260 getter_AddRefs(chromeDir
));
1263 rv
= NS_NewSingletonEnumerator(getter_AddRefs(chromeML
), chromeDir
);
1268 nsCOMPtr
<nsISupports
> next
;
1269 while (NS_SUCCEEDED(chromeML
->HasMoreElements(&exists
)) && exists
) {
1270 chromeML
->GetNext(getter_AddRefs(next
));
1271 nsCOMPtr
<nsILocalFile
> lmanifest
= do_QueryInterface(next
);
1273 NS_ERROR("Directory enumerator returned a non-nsILocalFile");
1278 if (NS_SUCCEEDED(lmanifest
->IsDirectory(&isDir
)) && isDir
) {
1279 nsCOMPtr
<nsISimpleEnumerator
> entries
;
1280 rv
= lmanifest
->GetDirectoryEntries(getter_AddRefs(entries
));
1284 while (NS_SUCCEEDED(entries
->HasMoreElements(&exists
)) && exists
) {
1285 entries
->GetNext(getter_AddRefs(next
));
1286 lmanifest
= do_QueryInterface(next
);
1288 nsCAutoString leafName
;
1289 lmanifest
->GetNativeLeafName(leafName
);
1290 if (StringEndsWith(leafName
, NS_LITERAL_CSTRING(".manifest"))) {
1291 rv
= ProcessManifest(lmanifest
, PR_FALSE
);
1292 if (NS_FAILED(rv
)) {
1294 lmanifest
->GetNativePath(path
);
1295 LogMessage("Failed to process chrome manifest '%s'.",
1304 rv
= ProcessManifest(lmanifest
, PR_FALSE
);
1305 if (NS_FAILED(rv
)) {
1307 lmanifest
->GetNativePath(path
);
1308 LogMessage("Failed to process chrome manifest: '%s'.",
1314 rv
= dirSvc
->Get(NS_SKIN_MANIFESTS_FILE_LIST
, NS_GET_IID(nsISimpleEnumerator
),
1315 getter_AddRefs(chromeML
));
1319 while (NS_SUCCEEDED(chromeML
->HasMoreElements(&exists
)) && exists
) {
1320 chromeML
->GetNext(getter_AddRefs(next
));
1321 nsCOMPtr
<nsILocalFile
> lmanifest
= do_QueryInterface(next
);
1323 NS_ERROR("Directory enumerator returned a non-nsILocalFile");
1327 rv
= ProcessManifest(lmanifest
, PR_TRUE
);
1328 if (NS_FAILED(rv
)) {
1330 lmanifest
->GetNativePath(path
);
1331 LogMessage("Failed to process chrome manifest: '%s'.",
1339 NS_IMETHODIMP_(PRBool
)
1340 nsChromeRegistry::WrappersEnabled(nsIURI
*aURI
)
1342 nsCOMPtr
<nsIURL
> chromeURL (do_QueryInterface(aURI
));
1346 PRBool isChrome
= PR_FALSE
;
1347 nsresult rv
= chromeURL
->SchemeIs("chrome", &isChrome
);
1348 if (NS_FAILED(rv
) || !isChrome
)
1351 nsCAutoString package
;
1352 rv
= chromeURL
->GetHostPort(package
);
1356 PackageEntry
* entry
=
1357 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
1358 & (nsACString
&) package
,
1361 return PL_DHASH_ENTRY_IS_LIVE(entry
) &&
1362 entry
->flags
& PackageEntry::XPCNATIVEWRAPPERS
;
1366 nsChromeRegistry::ProcessNewChromeFile(nsILocalFile
*aListFile
, nsIURI
* aManifest
)
1371 rv
= aListFile
->OpenNSPRFileDesc(PR_RDONLY
, 0, &file
);
1372 NS_ENSURE_SUCCESS(rv
, rv
);
1377 size
= PR_Available(file
);
1379 rv
= NS_ERROR_UNEXPECTED
;
1383 buf
= (char *) malloc(size
+ 1);
1385 rv
= NS_ERROR_OUT_OF_MEMORY
;
1389 n
= PR_Read(file
, buf
, size
);
1391 rv
= ProcessNewChromeBuffer(buf
, size
, aManifest
);
1400 nsChromeRegistry::ProcessNewChromeBuffer(char *aBuffer
, PRInt32 aLength
,
1403 nsresult rv
= NS_OK
;
1404 char *bufferEnd
= aBuffer
+ aLength
;
1405 char *chromeType
, // "content", "locale" or "skin"
1406 *chromeProfile
, // "install" or "profile"
1407 *chromeLocType
, // type of location (local path or URL)
1408 *chromeLocation
; // base location of chrome (jar file)
1410 nsCOMPtr
<nsIURI
> baseURI
;
1412 // process chromeType, chromeProfile, chromeLocType, chromeLocation
1413 while (aBuffer
< bufferEnd
) {
1414 // parse one line of installed-chrome.txt
1415 chromeType
= aBuffer
;
1416 while (aBuffer
< bufferEnd
&& *aBuffer
!= ',')
1420 chromeProfile
= ++aBuffer
;
1421 if (aBuffer
>= bufferEnd
)
1424 while (aBuffer
< bufferEnd
&& *aBuffer
!= ',')
1428 chromeLocType
= ++aBuffer
;
1429 if (aBuffer
>= bufferEnd
)
1432 while (aBuffer
< bufferEnd
&& *aBuffer
!= ',')
1436 chromeLocation
= ++aBuffer
;
1437 if (aBuffer
>= bufferEnd
)
1440 while (aBuffer
< bufferEnd
&&
1441 (*aBuffer
!= '\r' && *aBuffer
!= '\n' && *aBuffer
!= ' '))
1446 // We don't do skin or locale selection from installed-chrome.txt since
1447 // ffox 0.9. Just ignore the "select" lines.
1448 if (strcmp(chromeLocType
,"select")) {
1449 if (!strcmp(chromeLocType
, "path")) {
1450 // location is a (full) path. convert it to an URL.
1452 /* this is some convoluted shit... this creates a file, inits it with
1453 * the path parsed above (chromeLocation), makes a url, and inits it
1454 * with the file created. the purpose of this is just to have the
1455 * canonical url of the stupid thing.
1457 nsCOMPtr
<nsILocalFile
> chromeFile
;
1458 rv
= NS_NewNativeLocalFile(nsDependentCString(chromeLocation
),
1459 PR_TRUE
, getter_AddRefs(chromeFile
));
1460 NS_ENSURE_SUCCESS(rv
, rv
);
1463 * all we want here is the canonical url
1465 rv
= NS_NewFileURI(getter_AddRefs(baseURI
), chromeFile
);
1466 if (NS_FAILED(rv
)) return rv
;
1469 rv
= NS_NewURI(getter_AddRefs(baseURI
), chromeLocation
);
1470 if (NS_FAILED(rv
)) return rv
;
1473 ProcessContentsManifest(baseURI
, aManifest
, baseURI
, PR_TRUE
,
1474 strcmp(chromeType
, "skin") == 0);
1477 while (aBuffer
< bufferEnd
&& (*aBuffer
== '\0' || *aBuffer
== ' ' || *aBuffer
== '\r' || *aBuffer
== '\n'))
1484 NS_IMETHODIMP
nsChromeRegistry::Observe(nsISupports
*aSubject
, const char *aTopic
, const PRUnichar
*someData
)
1486 nsresult rv
= NS_OK
;
1488 if (!strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID
, aTopic
)) {
1489 nsCOMPtr
<nsIPrefBranch
> prefs (do_QueryInterface(aSubject
));
1490 NS_ASSERTION(prefs
, "Bad observer call!");
1492 NS_ConvertUTF16toUTF8
pref(someData
);
1494 nsXPIDLCString provider
;
1495 rv
= prefs
->GetCharPref(pref
.get(), getter_Copies(provider
));
1496 if (NS_FAILED(rv
)) {
1497 NS_ERROR("Couldn't get new locale or skin pref!");
1501 if (pref
.EqualsLiteral(SELECTED_SKIN_PREF
)) {
1502 mSelectedSkin
= provider
;
1505 else if (pref
.EqualsLiteral(SELECTED_LOCALE_PREF
)) {
1506 mSelectedLocale
= provider
;
1509 NS_ERROR("Unexpected pref!");
1512 else if (!strcmp("command-line-startup", aTopic
)) {
1513 nsCOMPtr
<nsICommandLine
> cmdLine (do_QueryInterface(aSubject
));
1515 nsAutoString uiLocale
;
1516 rv
= cmdLine
->HandleFlagWithParam(NS_LITERAL_STRING(UILOCALE_CMD_LINE_ARG
),
1517 PR_FALSE
, uiLocale
);
1518 if (NS_SUCCEEDED(rv
) && !uiLocale
.IsEmpty()) {
1519 CopyUTF16toUTF8(uiLocale
, mSelectedLocale
);
1520 nsCOMPtr
<nsIPrefBranch2
> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID
));
1522 prefs
->RemoveObserver(SELECTED_LOCALE_PREF
, this);
1528 NS_ERROR("Unexpected observer topic!");
1536 GetContainerEnumerator(nsIRDFDataSource
* ds
, nsIRDFResource
* res
,
1537 nsISimpleEnumerator
* *aResult
, PRInt32
*aCountResult
= nsnull
)
1541 nsCOMPtr
<nsIRDFContainer
> container
1542 (do_CreateInstance("@mozilla.org/rdf/container;1"));
1543 NS_ENSURE_TRUE(container
, NS_ERROR_FAILURE
);
1545 rv
= container
->Init(ds
, res
);
1546 if (NS_FAILED(rv
)) return rv
;
1549 container
->GetCount(aCountResult
);
1551 return container
->GetElements(aResult
);
1555 FollowLiteral(nsIRDFDataSource
* ds
, nsIRDFResource
* res
,
1556 nsIRDFResource
* arc
, nsACString
& result
)
1560 nsCOMPtr
<nsIRDFNode
> node
;
1561 rv
= ds
->GetTarget(res
, arc
, PR_TRUE
, getter_AddRefs(node
));
1562 if (NS_FAILED(rv
) || !node
) {
1567 nsCOMPtr
<nsIRDFLiteral
> literal (do_QueryInterface(node
));
1569 NS_ERROR("Arc found, but doesn't point to expected literal!");
1574 const PRUnichar
* value
;
1575 literal
->GetValueConst(&value
);
1576 CopyUTF16toUTF8(value
, result
);
1580 FollowResource(nsIRDFDataSource
* ds
, nsIRDFResource
* res
, nsIRDFResource
* arc
,
1581 nsIRDFResource
* *result
)
1585 nsCOMPtr
<nsIRDFNode
> node
;
1586 rv
= ds
->GetTarget(res
, arc
, PR_TRUE
, getter_AddRefs(node
));
1587 if (NS_FAILED(rv
) || !node
) {
1592 CallQueryInterface(node
, result
);
1596 GetRelativePath(nsIURI
* base
, nsIURI
* relative
, nsACString
& result
)
1600 nsCOMPtr
<nsIJARURI
> jarrelative (do_QueryInterface(relative
));
1602 nsCOMPtr
<nsIURI
> jarbase
;
1603 jarrelative
->GetJARFile(getter_AddRefs(jarbase
));
1605 nsCAutoString relativeBase
;
1606 GetRelativePath(base
, jarbase
, relativeBase
);
1608 nsCAutoString jarEntry
;
1609 jarrelative
->GetJAREntry(jarEntry
);
1611 result
.Assign(NS_LITERAL_CSTRING("jar:"));
1612 result
.Append(relativeBase
);
1613 result
.Append(NS_LITERAL_CSTRING("!/"));
1614 result
.Append(jarEntry
);
1618 nsCOMPtr
<nsIURL
> baseURL (do_QueryInterface(base
));
1620 relative
->GetSpec(result
);
1624 rv
= baseURL
->GetRelativeSpec(relative
, result
);
1625 if (NS_FAILED(rv
)) {
1626 relative
->GetSpec(result
);
1630 static const PRInt32 kNSPR_APPEND_FLAGS
= PR_WRONLY
| PR_CREATE_FILE
| PR_APPEND
;
1631 static const PRInt32 kNSPR_TRUNCATE_FLAGS
= PR_WRONLY
| PR_CREATE_FILE
| PR_TRUNCATE
;
1634 nsChromeRegistry::ProcessContentsManifest(nsIURI
* aOldManifest
, nsIURI
* aFile
,
1635 nsIURI
* aBaseURI
, PRBool aAppend
,
1640 nsCAutoString relativePath
;
1641 GetRelativePath(aFile
, aBaseURI
, relativePath
);
1644 aOldManifest
->GetSpec(spec
);
1646 NS_ASSERTION(spec
.Last() == '/', "installed-chrome manifest URI doesn't end in a slash! It probably won't work.");
1648 spec
.AppendLiteral("contents.rdf");
1650 nsCOMPtr
<nsIRDFService
> rdfs (do_GetService("@mozilla.org/rdf/rdf-service;1"));
1651 NS_ENSURE_TRUE(rdfs
, NS_ERROR_FAILURE
);
1653 nsCOMPtr
<nsIRDFResource
> namearc
, platformarc
;
1654 rdfs
->GetResource(NS_LITERAL_CSTRING(kURICHROME_name
),
1655 getter_AddRefs(namearc
));
1656 rdfs
->GetResource(NS_LITERAL_CSTRING(kURICHROME_platformPackage
),
1657 getter_AddRefs(platformarc
));
1658 if (!(namearc
&& platformarc
))
1659 return NS_ERROR_FAILURE
;
1661 nsCOMPtr
<nsIRDFDataSource
> ds
;
1662 rv
= rdfs
->GetDataSourceBlocking(spec
.get(), getter_AddRefs(ds
));
1663 if (NS_FAILED(rv
)) {
1664 LogMessage("Failed to load old-style contents.rdf at '%s'.",
1669 nsCOMPtr
<nsIFileURL
> fileURL (do_QueryInterface(aFile
));
1670 NS_ENSURE_TRUE(fileURL
, NS_ERROR_INVALID_ARG
);
1672 nsCOMPtr
<nsIFile
> file
;
1673 rv
= fileURL
->GetFile(getter_AddRefs(file
));
1674 NS_ENSURE_SUCCESS(rv
, rv
);
1676 nsCOMPtr
<nsILocalFile
> lfile (do_QueryInterface(file
));
1677 NS_ENSURE_TRUE(lfile
, NS_ERROR_NO_INTERFACE
);
1680 rv
= lfile
->OpenNSPRFileDesc(aAppend
? kNSPR_APPEND_FLAGS
: kNSPR_TRUNCATE_FLAGS
,
1682 NS_ENSURE_SUCCESS(rv
, rv
);
1685 PR_Write(fd
, "\n", 1);
1687 nsCOMPtr
<nsIRDFResource
> root
;
1688 rv
= rdfs
->GetResource(NS_LITERAL_CSTRING("urn:mozilla:skin:root"),
1689 getter_AddRefs(root
));
1690 if (NS_SUCCEEDED(rv
))
1691 ProcessProvider(fd
, rdfs
, ds
, root
, PR_FALSE
, relativePath
);
1693 rv
= rdfs
->GetResource(NS_LITERAL_CSTRING("urn:mozilla:stylesheets"),
1694 getter_AddRefs(root
));
1695 if (NS_SUCCEEDED(rv
))
1696 ProcessOverlays(fd
, ds
, root
, NS_LITERAL_CSTRING("style"));
1699 rv
= rdfs
->GetResource(NS_LITERAL_CSTRING("urn:mozilla:locale:root"),
1700 getter_AddRefs(root
));
1701 if (NS_SUCCEEDED(rv
))
1702 ProcessProvider(fd
, rdfs
, ds
, root
, PR_TRUE
, relativePath
);
1704 rv
= rdfs
->GetResource(NS_LITERAL_CSTRING("urn:mozilla:overlays"),
1705 getter_AddRefs(root
));
1706 if (NS_SUCCEEDED(rv
))
1707 ProcessOverlays(fd
, ds
, root
, NS_LITERAL_CSTRING("overlay"));
1709 /* content packages are easier, but different */
1711 rv
= rdfs
->GetResource(NS_LITERAL_CSTRING("urn:mozilla:package:root"),
1712 getter_AddRefs(root
));
1714 nsCOMPtr
<nsISimpleEnumerator
> packages
;
1715 if (NS_SUCCEEDED(rv
))
1716 rv
= GetContainerEnumerator(ds
, root
, getter_AddRefs(packages
));
1718 if (NS_SUCCEEDED(rv
)) {
1720 nsCOMPtr
<nsISupports
> next
;
1721 nsCOMPtr
<nsIRDFResource
> package
;
1723 while (NS_SUCCEEDED(packages
->HasMoreElements(&more
)) && more
) {
1724 packages
->GetNext(getter_AddRefs(next
));
1726 package
= do_QueryInterface(next
);
1728 NS_WARNING("Arc from urn:mozilla:package:root points to non-resource node.");
1733 FollowLiteral(ds
, package
, namearc
, name
);
1737 nsCAutoString isPlatform
;
1738 FollowLiteral(ds
, package
, platformarc
, isPlatform
);
1739 name
.Insert(NS_LITERAL_CSTRING("content\t"), 0);
1741 name
.Append(relativePath
);
1742 if (!isPlatform
.IsEmpty())
1743 name
.AppendLiteral("\tplatform");
1745 name
.AppendLiteral(NS_LINEBREAK
);
1746 PR_Write(fd
, name
.get(), name
.Length());
1757 GetResourceName(nsIRDFResource
* res
, nsACString
& result
)
1759 // we need to get the provider name. Instead of doing something sane,
1760 // we munge the resource URI, looking from the right for colons.
1762 nsCAutoString providerURI
;
1763 res
->GetValueUTF8(providerURI
);
1765 PRInt32 found
= providerURI
.RFindChar(':');
1766 if (found
== kNotFound
) {
1771 result
.Assign(Substring(providerURI
, found
+ 1));
1776 nsChromeRegistry::ProcessProvider(PRFileDesc
*fd
, nsIRDFService
* aRDFs
,
1777 nsIRDFDataSource
* aDS
, nsIRDFResource
* aRoot
,
1778 PRBool aIsLocale
, const nsACString
& aBaseURL
)
1780 NS_NAMED_LITERAL_CSTRING(kSlash
, "/");
1781 NS_NAMED_LITERAL_CSTRING(kTab
, "\t");
1785 nsCOMPtr
<nsIRDFResource
> packagesarc
;
1786 aRDFs
->GetResource(NS_LITERAL_CSTRING(kURICHROME_packages
),
1787 getter_AddRefs(packagesarc
));
1788 if (!packagesarc
) return;
1790 nsCOMPtr
<nsISimpleEnumerator
> providers
;
1791 rv
= GetContainerEnumerator(aDS
, aRoot
, getter_AddRefs(providers
));
1792 if (NS_FAILED(rv
)) {
1796 nsCOMPtr
<nsISupports
> next
;
1799 while (NS_SUCCEEDED(providers
->HasMoreElements(&more
)) && more
) {
1800 providers
->GetNext(getter_AddRefs(next
));
1801 NS_ASSERTION(next
, "GetNext failed after HasMoreElements succeeded.");
1803 nsCOMPtr
<nsIRDFResource
> provider (do_QueryInterface(next
));
1805 NS_WARNING("Provider isn't a nsIRDFResource.");
1809 nsCAutoString providerName
;
1810 GetResourceName(provider
, providerName
);
1811 if (providerName
.IsEmpty()) {
1812 NS_WARNING("Couldn't calculate resource name.");
1816 nsCOMPtr
<nsIRDFResource
> packages
;
1817 FollowResource(aDS
, provider
, packagesarc
, getter_AddRefs(packages
));
1819 NS_WARNING("No chrome:packages arc found!");
1824 nsCOMPtr
<nsISimpleEnumerator
> packageList
;
1825 rv
= GetContainerEnumerator(aDS
, packages
, getter_AddRefs(packageList
), &count
);
1826 if (NS_FAILED(rv
)) {
1827 NS_WARNING("chrome:packages was not a sequence.");
1831 nsCOMPtr
<nsISupports
> nextPackage
;
1833 PRBool morePackages
;
1834 while (NS_SUCCEEDED(packageList
->HasMoreElements(&morePackages
)) &&
1836 packageList
->GetNext(getter_AddRefs(nextPackage
));
1838 nsCOMPtr
<nsIRDFResource
> packageRes (do_QueryInterface(nextPackage
));
1840 NS_WARNING("chrome:packages Seq points to a non-resource!");
1844 nsCAutoString packageName
;
1845 GetResourceName(packageRes
, packageName
);
1846 if (packageName
.IsEmpty()) {
1847 NS_WARNING("couldn't extract a package name.");
1854 line
.AppendLiteral("locale\t");
1856 line
.AppendLiteral("skin\t");
1858 line
+= packageName
+ kTab
+ providerName
+ kTab
+ aBaseURL
;
1860 line
+= packageName
+ kSlash
;
1862 line
.AppendLiteral(NS_LINEBREAK
);
1863 PR_Write(fd
, line
.get(), line
.Length());
1869 GetLiteralText(nsIRDFLiteral
* lit
, nsACString
& result
)
1871 const PRUnichar
* value
;
1872 lit
->GetValueConst(&value
);
1873 CopyUTF16toUTF8(value
, result
);
1877 nsChromeRegistry::ProcessOverlays(PRFileDesc
*fd
, nsIRDFDataSource
* aDS
,
1878 nsIRDFResource
* aRoot
,
1879 const nsCSubstring
& aType
)
1881 NS_NAMED_LITERAL_CSTRING(kTab
, "\t");
1882 NS_NAMED_LITERAL_CSTRING(kLinebreak
, NS_LINEBREAK
);
1886 nsCOMPtr
<nsISimpleEnumerator
> overlaids
;
1887 rv
= GetContainerEnumerator(aDS
, aRoot
, getter_AddRefs(overlaids
));
1888 if (NS_FAILED(rv
)) {
1892 nsCOMPtr
<nsISupports
> next
;
1894 while (NS_SUCCEEDED(overlaids
->HasMoreElements(&more
)) && more
) {
1895 overlaids
->GetNext(getter_AddRefs(next
));
1896 NS_ASSERTION(next
, "GetNext failed after HasMoreElements succeeded.");
1898 nsCOMPtr
<nsIRDFResource
> overlaid (do_QueryInterface(next
));
1900 NS_WARNING("Overlay arc is not a nsIRDFResource.");
1904 nsCAutoString overlaidName
;
1905 overlaid
->GetValueUTF8(overlaidName
);
1907 nsCOMPtr
<nsISimpleEnumerator
> overlays
;
1908 rv
= GetContainerEnumerator(aDS
, overlaid
, getter_AddRefs(overlays
));
1912 while (NS_SUCCEEDED(overlays
->HasMoreElements(&more
)) && more
) {
1913 overlays
->GetNext(getter_AddRefs(next
));
1914 NS_ASSERTION(next
, "GetNext failed after HasMoreElements succeeded.");
1916 nsCOMPtr
<nsIRDFLiteral
> overlay (do_QueryInterface(next
));
1918 NS_WARNING("Overlay was not an RDF literal.");
1922 nsCAutoString overlayName
;
1923 GetLiteralText(overlay
, overlayName
);
1925 overlayName
.Insert(aType
+ kTab
+ overlaidName
+ kTab
, 0);
1926 overlayName
.Append(kLinebreak
);
1927 PR_Write(fd
, overlayName
.get(), overlayName
.Length());
1935 nsChromeRegistry::ProcessContentsManifest(nsIURI
* aOldManifest
, nsIURI
* aFile
,
1936 nsIURI
* aBaseURI
, PRBool aAppend
,
1939 return NS_ERROR_NOT_IMPLEMENTED
;
1945 nsChromeRegistry::ProcessManifest(nsILocalFile
* aManifest
, PRBool aSkinOnly
)
1950 rv
= aManifest
->OpenNSPRFileDesc(PR_RDONLY
, 0, &fd
);
1951 NS_ENSURE_SUCCESS(rv
, rv
);
1956 size
= PR_Available(fd
);
1958 rv
= NS_ERROR_UNEXPECTED
;
1962 buf
= (char *) malloc(size
+ 1);
1964 rv
= NS_ERROR_OUT_OF_MEMORY
;
1968 n
= PR_Read(fd
, buf
, size
);
1971 rv
= ProcessManifestBuffer(buf
, size
, aManifest
, aSkinOnly
);
1980 static const char kWhitespace
[] = "\t ";
1981 static const char kNewlines
[] = "\r\n";
1984 * Check for a modifier flag of the following forms:
1985 * "flag" (same as "true")
1987 * "flag="no|false|0"
1988 * @param aFlag The flag to compare.
1989 * @param aData The tokenized data to check; this is lowercased
1990 * before being passed in.
1991 * @param aResult If the flag is found, the value is assigned here.
1992 * @return Whether the flag was handled.
1995 CheckFlag(const nsSubstring
& aFlag
, const nsSubstring
& aData
, PRBool
& aResult
)
1997 if (!StringBeginsWith(aData
, aFlag
))
2000 if (aFlag
.Length() == aData
.Length()) {
2001 // the data is simply "flag", which is the same as "flag=yes"
2006 if (aData
.CharAt(aFlag
.Length()) != '=') {
2007 // the data is "flag2=", which is not anything we care about
2011 if (aData
.Length() == aFlag
.Length() + 1) {
2016 switch (aData
.CharAt(aFlag
.Length() + 1)) {
2040 * Check for a modifier flag of the following form:
2043 * @param aFlag The flag to compare.
2044 * @param aData The tokenized data to check; this is lowercased
2045 * before being passed in.
2046 * @param aValue The value that is expected.
2047 * @param aResult If this is "ok" when passed in, this is left alone.
2048 * Otherwise if the flag is found it is set to eBad or eOK.
2049 * @return Whether the flag was handled.
2052 CheckStringFlag(const nsSubstring
& aFlag
, const nsSubstring
& aData
,
2053 const nsSubstring
& aValue
, TriState
& aResult
)
2055 if (aData
.Length() < aFlag
.Length() + 1)
2058 if (!StringBeginsWith(aData
, aFlag
))
2061 PRBool comparison
= PR_TRUE
;
2062 if (aData
[aFlag
.Length()] != '=') {
2063 if (aData
[aFlag
.Length()] == '!' &&
2064 aData
.Length() >= aFlag
.Length() + 2 &&
2065 aData
[aFlag
.Length() + 1] == '=')
2066 comparison
= PR_FALSE
;
2071 if (aResult
!= eOK
) {
2072 nsDependentSubstring testdata
= Substring(aData
, aFlag
.Length() + (comparison
? 1 : 2));
2073 if (testdata
.Equals(aValue
))
2074 aResult
= comparison
? eOK
: eBad
;
2076 aResult
= comparison
? eBad
: eOK
;
2083 * Check for a modifier flag of the following form:
2089 * @param aFlag The flag to compare.
2090 * @param aData The tokenized data to check; this is lowercased
2091 * before being passed in.
2092 * @param aValue The value that is expected. If this is empty then no
2093 * comparison will match.
2094 * @param aChecker the version checker to use. If null, aResult will always
2096 * @param aResult If this is eOK when passed in, this is left alone.
2097 * Otherwise if the flag is found it is set to eBad or eOK.
2098 * @return Whether the flag was handled.
2101 #define COMPARE_EQ 1 << 0
2102 #define COMPARE_LT 1 << 1
2103 #define COMPARE_GT 1 << 2
2106 CheckVersionFlag(const nsSubstring
& aFlag
, const nsSubstring
& aData
,
2107 const nsSubstring
& aValue
, nsIVersionComparator
* aChecker
,
2110 if (aData
.Length() < aFlag
.Length() + 2)
2113 if (!StringBeginsWith(aData
, aFlag
))
2116 if (aValue
.Length() == 0) {
2122 PRUint32 comparison
;
2123 nsAutoString testdata
;
2125 switch (aData
[aFlag
.Length()]) {
2127 comparison
= COMPARE_EQ
;
2128 testdata
= Substring(aData
, aFlag
.Length() + 1);
2132 if (aData
[aFlag
.Length() + 1] == '=') {
2133 comparison
= COMPARE_EQ
| COMPARE_LT
;
2134 testdata
= Substring(aData
, aFlag
.Length() + 2);
2137 comparison
= COMPARE_LT
;
2138 testdata
= Substring(aData
, aFlag
.Length() + 1);
2143 if (aData
[aFlag
.Length() + 1] == '=') {
2144 comparison
= COMPARE_EQ
| COMPARE_GT
;
2145 testdata
= Substring(aData
, aFlag
.Length() + 2);
2148 comparison
= COMPARE_GT
;
2149 testdata
= Substring(aData
, aFlag
.Length() + 1);
2157 if (testdata
.Length() == 0)
2160 if (aResult
!= eOK
) {
2166 nsresult rv
= aChecker
->Compare(NS_ConvertUTF16toUTF8(aValue
),
2167 NS_ConvertUTF16toUTF8(testdata
), &c
);
2168 if (NS_FAILED(rv
)) {
2172 if ((c
== 0 && comparison
& COMPARE_EQ
) ||
2173 (c
< 0 && comparison
& COMPARE_LT
) ||
2174 (c
> 0 && comparison
& COMPARE_GT
))
2186 EnsureLowerCase(char *aBuf
)
2188 for (; *aBuf
; ++aBuf
) {
2190 if (ch
>= 'A' && ch
<= 'Z')
2191 *aBuf
= ch
+ 'a' - 'A';
2196 nsChromeRegistry::ProcessManifestBuffer(char *buf
, PRInt32 length
,
2197 nsILocalFile
* aManifest
,
2202 NS_NAMED_LITERAL_STRING(kPlatform
, "platform");
2203 NS_NAMED_LITERAL_STRING(kXPCNativeWrappers
, "xpcnativewrappers");
2204 NS_NAMED_LITERAL_STRING(kContentAccessible
, "contentaccessible");
2205 NS_NAMED_LITERAL_STRING(kApplication
, "application");
2206 NS_NAMED_LITERAL_STRING(kAppVersion
, "appversion");
2207 NS_NAMED_LITERAL_STRING(kOs
, "os");
2208 NS_NAMED_LITERAL_STRING(kOsVersion
, "osversion");
2210 nsCOMPtr
<nsIIOService
> io (do_GetIOService());
2211 if (!io
) return NS_ERROR_FAILURE
;
2213 nsCOMPtr
<nsIProtocolHandler
> ph
;
2214 rv
= io
->GetProtocolHandler("resource", getter_AddRefs(ph
));
2215 NS_ENSURE_SUCCESS(rv
, rv
);
2217 nsCOMPtr
<nsIResProtocolHandler
> rph (do_QueryInterface(ph
));
2218 if (!rph
) return NS_ERROR_FAILURE
;
2220 nsCOMPtr
<nsIURI
> manifestURI
;
2221 rv
= io
->NewFileURI(aManifest
, getter_AddRefs(manifestURI
));
2222 NS_ENSURE_SUCCESS(rv
, rv
);
2224 nsCOMPtr
<nsIXPConnect
> xpc (do_GetService("@mozilla.org/js/xpc/XPConnect;1"));
2225 nsCOMPtr
<nsIVersionComparator
> vc (do_GetService("@mozilla.org/xpcom/version-comparator;1"));
2228 nsAutoString appVersion
;
2229 nsAutoString osTarget
;
2230 nsCOMPtr
<nsIXULAppInfo
> xapp (do_GetService(XULAPPINFO_SERVICE_CONTRACTID
));
2233 rv
= xapp
->GetID(s
);
2234 if (NS_SUCCEEDED(rv
))
2235 CopyUTF8toUTF16(s
, appID
);
2237 rv
= xapp
->GetVersion(s
);
2238 if (NS_SUCCEEDED(rv
))
2239 CopyUTF8toUTF16(s
, appVersion
);
2241 nsCOMPtr
<nsIXULRuntime
> xruntime (do_QueryInterface(xapp
));
2243 rv
= xruntime
->GetOS(s
);
2244 if (NS_SUCCEEDED(rv
)) {
2245 CopyUTF8toUTF16(s
, osTarget
);
2246 ToLowerCase(osTarget
);
2251 nsAutoString osVersion
;
2253 OSVERSIONINFO info
= { sizeof(OSVERSIONINFO
) };
2254 if (GetVersionEx(&info
)) {
2255 nsTextFormatter::ssprintf(osVersion
, NS_LITERAL_STRING("%ld.%ld").get(),
2256 info
.dwMajorVersion
,
2257 info
.dwMinorVersion
);
2259 #elif defined(XP_MACOSX)
2260 long majorVersion
, minorVersion
;
2261 if ((Gestalt(gestaltSystemVersionMajor
, &majorVersion
) == noErr
) &&
2262 (Gestalt(gestaltSystemVersionMinor
, &minorVersion
) == noErr
)) {
2263 nsTextFormatter::ssprintf(osVersion
, NS_LITERAL_STRING("%ld.%ld").get(),
2267 #elif defined(MOZ_WIDGET_GTK2)
2268 nsTextFormatter::ssprintf(osVersion
, NS_LITERAL_STRING("%ld.%ld").get(),
2274 char *newline
= buf
;
2277 // outer loop tokenizes by newline
2278 while (nsnull
!= (token
= nsCRT::strtok(newline
, kNewlines
, &newline
))) {
2281 if (*token
== '#') // ignore lines that begin with # as comments
2284 char *whitespace
= token
;
2285 token
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2286 if (!token
) continue;
2288 if (!strcmp(token
, "content")) {
2290 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2291 "Warning: Ignoring content registration in skin-only manifest.");
2294 char *package
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2295 char *uri
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2296 if (!package
|| !uri
) {
2297 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2298 "Warning: Malformed content registration.");
2302 EnsureLowerCase(package
);
2304 // NOTE: We check for platform and xpcnativewrappers modifiers on
2305 // content packages, but they are *applied* to content|skin|locale.
2307 PRBool platform
= PR_FALSE
;
2308 PRBool xpcNativeWrappers
= PR_TRUE
;
2309 PRBool contentAccessible
= PR_FALSE
;
2310 TriState stAppVersion
= eUnspecified
;
2311 TriState stApp
= eUnspecified
;
2312 TriState stOsVersion
= eUnspecified
;
2313 TriState stOs
= eUnspecified
;
2315 PRBool badFlag
= PR_FALSE
;
2317 while (nsnull
!= (token
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
)) &&
2319 NS_ConvertASCIItoUTF16
wtoken(token
);
2320 ToLowerCase(wtoken
);
2322 if (CheckFlag(kPlatform
, wtoken
, platform
) ||
2323 CheckFlag(kXPCNativeWrappers
, wtoken
, xpcNativeWrappers
) ||
2324 CheckFlag(kContentAccessible
, wtoken
, contentAccessible
) ||
2325 CheckStringFlag(kApplication
, wtoken
, appID
, stApp
) ||
2326 CheckStringFlag(kOs
, wtoken
, osTarget
, stOs
) ||
2327 CheckVersionFlag(kOsVersion
, wtoken
, osVersion
, vc
, stOsVersion
) ||
2328 CheckVersionFlag(kAppVersion
, wtoken
, appVersion
, vc
, stAppVersion
))
2331 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2332 "Warning: Unrecognized chrome registration modifier '%s'.",
2337 if (badFlag
|| stApp
== eBad
|| stAppVersion
== eBad
||
2338 stOs
== eBad
|| stOsVersion
== eBad
)
2341 nsCOMPtr
<nsIURI
> resolved
;
2342 rv
= io
->NewURI(nsDependentCString(uri
), nsnull
, manifestURI
,
2343 getter_AddRefs(resolved
));
2347 if (!CanLoadResource(resolved
)) {
2348 LogMessageWithContext(resolved
, line
, nsIScriptError::warningFlag
,
2349 "Warning: cannot register non-local URI '%s' as content.",
2354 PackageEntry
* entry
=
2355 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
2356 & (const nsACString
&) nsDependentCString(package
),
2359 return NS_ERROR_OUT_OF_MEMORY
;
2361 entry
->baseURI
= resolved
;
2364 entry
->flags
|= PackageEntry::PLATFORM_PACKAGE
;
2365 if (xpcNativeWrappers
)
2366 entry
->flags
|= PackageEntry::XPCNATIVEWRAPPERS
;
2367 if (contentAccessible
)
2368 entry
->flags
|= PackageEntry::CONTENT_ACCESSIBLE
;
2370 nsCAutoString
urlp("chrome://");
2371 urlp
.Append(package
);
2374 rv
= xpc
->FlagSystemFilenamePrefix(urlp
.get(), xpcNativeWrappers
);
2375 NS_ENSURE_SUCCESS(rv
, rv
);
2378 else if (!strcmp(token
, "locale")) {
2380 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2381 "Warning: Ignoring locale registration in skin-only manifest.");
2384 char *package
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2385 char *provider
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2386 char *uri
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2387 if (!package
|| !provider
|| !uri
) {
2388 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2389 "Warning: Malformed locale registration.");
2393 EnsureLowerCase(package
);
2395 TriState stAppVersion
= eUnspecified
;
2396 TriState stApp
= eUnspecified
;
2397 TriState stOs
= eUnspecified
;
2398 TriState stOsVersion
= eUnspecified
;
2400 PRBool badFlag
= PR_FALSE
;
2402 while (nsnull
!= (token
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
)) &&
2404 NS_ConvertASCIItoUTF16
wtoken(token
);
2405 ToLowerCase(wtoken
);
2407 if (CheckStringFlag(kApplication
, wtoken
, appID
, stApp
) ||
2408 CheckStringFlag(kOs
, wtoken
, osTarget
, stOs
) ||
2409 CheckVersionFlag(kOsVersion
, wtoken
, osVersion
, vc
, stOsVersion
) ||
2410 CheckVersionFlag(kAppVersion
, wtoken
, appVersion
, vc
, stAppVersion
))
2413 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2414 "Warning: Unrecognized chrome registration modifier '%s'.",
2419 if (badFlag
|| stApp
== eBad
|| stAppVersion
== eBad
||
2420 stOs
== eBad
|| stOsVersion
== eBad
)
2423 nsCOMPtr
<nsIURI
> resolved
;
2424 rv
= io
->NewURI(nsDependentCString(uri
), nsnull
, manifestURI
,
2425 getter_AddRefs(resolved
));
2429 if (!CanLoadResource(resolved
)) {
2430 LogMessageWithContext(resolved
, line
, nsIScriptError::warningFlag
,
2431 "Warning: cannot register non-local URI '%s' as a locale.",
2436 PackageEntry
* entry
=
2437 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
2438 & (const nsACString
&) nsDependentCString(package
),
2441 return NS_ERROR_OUT_OF_MEMORY
;
2443 entry
->locales
.SetBase(nsDependentCString(provider
), resolved
);
2445 else if (!strcmp(token
, "skin")) {
2446 char *package
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2447 char *provider
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2448 char *uri
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2449 if (!package
|| !provider
|| !uri
) {
2450 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2451 "Warning: Malformed skin registration.");
2455 EnsureLowerCase(package
);
2457 TriState stAppVersion
= eUnspecified
;
2458 TriState stApp
= eUnspecified
;
2459 TriState stOs
= eUnspecified
;
2460 TriState stOsVersion
= eUnspecified
;
2462 PRBool badFlag
= PR_FALSE
;
2464 while (nsnull
!= (token
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
)) &&
2466 NS_ConvertASCIItoUTF16
wtoken(token
);
2467 ToLowerCase(wtoken
);
2469 if (CheckStringFlag(kApplication
, wtoken
, appID
, stApp
) ||
2470 CheckStringFlag(kOs
, wtoken
, osTarget
, stOs
) ||
2471 CheckVersionFlag(kOsVersion
, wtoken
, osVersion
, vc
, stOsVersion
) ||
2472 CheckVersionFlag(kAppVersion
, wtoken
, appVersion
, vc
, stAppVersion
))
2475 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2476 "Warning: Unrecognized chrome registration modifier '%s'.",
2481 if (badFlag
|| stApp
== eBad
|| stAppVersion
== eBad
||
2482 stOs
== eBad
|| stOsVersion
== eBad
)
2485 nsCOMPtr
<nsIURI
> resolved
;
2486 rv
= io
->NewURI(nsDependentCString(uri
), nsnull
, manifestURI
,
2487 getter_AddRefs(resolved
));
2491 if (!CanLoadResource(resolved
)) {
2492 LogMessageWithContext(resolved
, line
, nsIScriptError::warningFlag
,
2493 "Warning: cannot register non-local URI '%s' as a skin.",
2498 PackageEntry
* entry
=
2499 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
2500 & (const nsACString
&) nsDependentCString(package
),
2503 return NS_ERROR_OUT_OF_MEMORY
;
2505 entry
->skins
.SetBase(nsDependentCString(provider
), resolved
);
2507 else if (!strcmp(token
, "overlay")) {
2509 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2510 "Warning: Ignoring overlay registration in skin-only manifest.");
2513 char *base
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2514 char *overlay
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2515 if (!base
|| !overlay
) {
2516 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2517 "Warning: malformed chrome overlay instruction.");
2521 TriState stAppVersion
= eUnspecified
;
2522 TriState stApp
= eUnspecified
;
2523 TriState stOs
= eUnspecified
;
2524 TriState stOsVersion
= eUnspecified
;
2526 PRBool badFlag
= PR_FALSE
;
2528 while (nsnull
!= (token
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
)) &&
2530 NS_ConvertASCIItoUTF16
wtoken(token
);
2531 ToLowerCase(wtoken
);
2533 if (CheckStringFlag(kApplication
, wtoken
, appID
, stApp
) ||
2534 CheckStringFlag(kOs
, wtoken
, osTarget
, stOs
) ||
2535 CheckVersionFlag(kOsVersion
, wtoken
, osVersion
, vc
, stOsVersion
) ||
2536 CheckVersionFlag(kAppVersion
, wtoken
, appVersion
, vc
, stAppVersion
))
2539 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2540 "Warning: Unrecognized chrome registration modifier '%s'.",
2545 if (badFlag
|| stApp
== eBad
|| stAppVersion
== eBad
||
2546 stOs
== eBad
|| stOsVersion
== eBad
)
2549 nsCOMPtr
<nsIURI
> baseuri
, overlayuri
;
2550 rv
= io
->NewURI(nsDependentCString(base
), nsnull
, nsnull
,
2551 getter_AddRefs(baseuri
));
2552 rv
|= io
->NewURI(nsDependentCString(overlay
), nsnull
, nsnull
,
2553 getter_AddRefs(overlayuri
));
2554 if (NS_FAILED(rv
)) {
2555 NS_WARNING("Could not make URIs for overlay directive. Ignoring.");
2559 if (!CanLoadResource(overlayuri
)) {
2560 LogMessageWithContext(overlayuri
, line
, nsIScriptError::warningFlag
,
2561 "Warning: cannot register non-local URI '%s' as an overlay.",
2566 mOverlayHash
.Add(baseuri
, overlayuri
);
2568 else if (!strcmp(token
, "style")) {
2569 char *base
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2570 char *overlay
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2571 if (!base
|| !overlay
) {
2572 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2573 "Warning: malformed chrome style instruction.");
2577 TriState stAppVersion
= eUnspecified
;
2578 TriState stApp
= eUnspecified
;
2579 TriState stOs
= eUnspecified
;
2580 TriState stOsVersion
= eUnspecified
;
2582 PRBool badFlag
= PR_FALSE
;
2584 while (nsnull
!= (token
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
)) &&
2586 NS_ConvertASCIItoUTF16
wtoken(token
);
2587 ToLowerCase(wtoken
);
2589 if (CheckStringFlag(kApplication
, wtoken
, appID
, stApp
) ||
2590 CheckStringFlag(kOs
, wtoken
, osTarget
, stOs
) ||
2591 CheckVersionFlag(kOsVersion
, wtoken
, osVersion
, vc
, stOsVersion
) ||
2592 CheckVersionFlag(kAppVersion
, wtoken
, appVersion
, vc
, stAppVersion
))
2595 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2596 "Warning: Unrecognized chrome registration modifier '%s'.",
2601 if (badFlag
|| stApp
== eBad
|| stAppVersion
== eBad
||
2602 stOs
== eBad
|| stOsVersion
== eBad
)
2605 nsCOMPtr
<nsIURI
> baseuri
, overlayuri
;
2606 rv
= io
->NewURI(nsDependentCString(base
), nsnull
, nsnull
,
2607 getter_AddRefs(baseuri
));
2608 rv
|= io
->NewURI(nsDependentCString(overlay
), nsnull
, nsnull
,
2609 getter_AddRefs(overlayuri
));
2613 if (!CanLoadResource(overlayuri
)) {
2614 LogMessageWithContext(overlayuri
, line
, nsIScriptError::warningFlag
,
2615 "Warning: cannot register non-local URI '%s' as a style overlay.",
2620 mStyleHash
.Add(baseuri
, overlayuri
);
2622 else if (!strcmp(token
, "override")) {
2624 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2625 "Warning: Ignoring override registration in skin-only manifest.");
2629 char *chrome
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2630 char *resolved
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2631 if (!chrome
|| !resolved
) {
2632 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2633 "Warning: malformed chrome override instruction.");
2637 TriState stAppVersion
= eUnspecified
;
2638 TriState stApp
= eUnspecified
;
2639 TriState stOs
= eUnspecified
;
2640 TriState stOsVersion
= eUnspecified
;
2642 PRBool badFlag
= PR_FALSE
;
2644 while (nsnull
!= (token
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
)) &&
2646 NS_ConvertASCIItoUTF16
wtoken(token
);
2647 ToLowerCase(wtoken
);
2649 if (CheckStringFlag(kApplication
, wtoken
, appID
, stApp
) ||
2650 CheckStringFlag(kOs
, wtoken
, osTarget
, stOs
) ||
2651 CheckVersionFlag(kOsVersion
, wtoken
, osVersion
, vc
, stOsVersion
) ||
2652 CheckVersionFlag(kAppVersion
, wtoken
, appVersion
, vc
, stAppVersion
))
2655 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2656 "Warning: Unrecognized chrome registration modifier '%s'.",
2661 if (badFlag
|| stApp
== eBad
|| stAppVersion
== eBad
||
2662 stOs
== eBad
|| stOsVersion
== eBad
)
2665 nsCOMPtr
<nsIURI
> chromeuri
, resolveduri
;
2666 rv
= io
->NewURI(nsDependentCString(chrome
), nsnull
, nsnull
,
2667 getter_AddRefs(chromeuri
));
2668 rv
|= io
->NewURI(nsDependentCString(resolved
), nsnull
, manifestURI
,
2669 getter_AddRefs(resolveduri
));
2673 if (!CanLoadResource(resolveduri
)) {
2674 LogMessageWithContext(resolveduri
, line
, nsIScriptError::warningFlag
,
2675 "Warning: cannot register non-local URI '%s' as an override.",
2680 mOverrideTable
.Put(chromeuri
, resolveduri
);
2682 else if (!strcmp(token
, "resource")) {
2684 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2685 "Warning: Ignoring resource registration in skin-only manifest.");
2689 char *package
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2690 char *uri
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2691 if (!package
|| !uri
) {
2692 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2693 "Warning: Malformed resource registration.");
2697 EnsureLowerCase(package
);
2699 TriState stAppVersion
= eUnspecified
;
2700 TriState stApp
= eUnspecified
;
2701 TriState stOsVersion
= eUnspecified
;
2702 TriState stOs
= eUnspecified
;
2704 PRBool badFlag
= PR_FALSE
;
2706 while (nsnull
!= (token
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
)) &&
2708 NS_ConvertASCIItoUTF16
wtoken(token
);
2709 ToLowerCase(wtoken
);
2711 if (CheckStringFlag(kApplication
, wtoken
, appID
, stApp
) ||
2712 CheckStringFlag(kOs
, wtoken
, osTarget
, stOs
) ||
2713 CheckVersionFlag(kOsVersion
, wtoken
, osVersion
, vc
, stOsVersion
) ||
2714 CheckVersionFlag(kAppVersion
, wtoken
, appVersion
, vc
, stAppVersion
))
2717 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2718 "Warning: Unrecognized chrome registration modifier '%s'.",
2723 if (badFlag
|| stApp
== eBad
|| stAppVersion
== eBad
||
2724 stOs
== eBad
|| stOsVersion
== eBad
)
2727 nsDependentCString
host(package
);
2730 rv
= rph
->HasSubstitution(host
, &exists
);
2731 NS_ENSURE_SUCCESS(rv
, rv
);
2733 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2734 "Warning: Duplicate resource declaration for '%s' ignored.",
2739 nsCOMPtr
<nsIURI
> resolved
;
2740 rv
= io
->NewURI(nsDependentCString(uri
), nsnull
, manifestURI
,
2741 getter_AddRefs(resolved
));
2745 if (!CanLoadResource(resolved
)) {
2746 LogMessageWithContext(resolved
, line
, nsIScriptError::warningFlag
,
2747 "Warning: cannot register non-local URI '%s' as a resource.",
2752 rv
= rph
->SetSubstitution(host
, resolved
);
2753 NS_ENSURE_SUCCESS(rv
, rv
);
2756 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2757 "Warning: Ignoring unrecognized chrome manifest instruction.");