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 "nsXPCOMCIDInternal.h"
73 #include "nsXPIDLString.h"
74 #include "nsXULAppAPI.h"
75 #include "nsTextFormatter.h"
78 #include "nsICommandLine.h"
79 #include "nsICSSLoader.h"
80 #include "nsICSSStyleSheet.h"
81 #include "nsIConsoleService.h"
82 #include "nsIDirectoryService.h"
83 #include "nsIDocument.h"
84 #include "nsIDOMDocument.h"
85 #include "nsIDocShell.h"
86 #include "nsIDocumentObserver.h"
87 #include "nsIDOMElement.h"
88 #include "nsIDOMLocation.h"
89 #include "nsIDOMWindowCollection.h"
90 #include "nsIDOMWindowInternal.h"
91 #include "nsIFileChannel.h"
92 #include "nsIFileURL.h"
93 #include "nsIIOService.h"
94 #include "nsIJARProtocolHandler.h"
95 #include "nsIJARURI.h"
96 #include "nsILocalFile.h"
97 #include "nsILocaleService.h"
98 #include "nsILookAndFeel.h"
99 #include "nsIObserverService.h"
100 #include "nsIPrefService.h"
101 #include "nsIPrefBranch.h"
102 #include "nsIPrefBranch2.h"
103 #include "nsIPresShell.h"
104 #include "nsIProtocolHandler.h"
105 #include "nsIResProtocolHandler.h"
106 #include "nsIScriptError.h"
107 #include "nsIServiceManager.h"
108 #include "nsISimpleEnumerator.h"
109 #include "nsIStyleSheet.h"
110 #include "nsISupportsArray.h"
111 #include "nsIVersionComparator.h"
112 #include "nsIWindowMediator.h"
113 #include "nsIXPConnect.h"
114 #include "nsIXULAppInfo.h"
115 #include "nsIXULRuntime.h"
117 #define UILOCALE_CMD_LINE_ARG "UILocale"
119 #define MATCH_OS_LOCALE_PREF "intl.locale.matchOS"
120 #define SELECTED_LOCALE_PREF "general.useragent.locale"
121 #define SELECTED_SKIN_PREF "general.skins.selectedSkin"
123 static NS_DEFINE_CID(kCSSLoaderCID
, NS_CSS_LOADER_CID
);
124 static NS_DEFINE_CID(kLookAndFeelCID
, NS_LOOKANDFEEL_CID
);
126 nsChromeRegistry
* nsChromeRegistry::gChromeRegistry
;
128 ////////////////////////////////////////////////////////////////////////////////
131 LogMessage(const char* aMsg
, ...)
133 nsCOMPtr
<nsIConsoleService
> console
134 (do_GetService(NS_CONSOLESERVICE_CONTRACTID
));
139 va_start(args
, aMsg
);
140 char* formatted
= PR_vsmprintf(aMsg
, args
);
145 console
->LogStringMessage(NS_ConvertUTF8toUTF16(formatted
).get());
146 PR_smprintf_free(formatted
);
150 LogMessageWithContext(nsIURI
* aURL
, PRUint32 aLineNumber
, PRUint32 flags
,
151 const char* aMsg
, ...)
155 nsCOMPtr
<nsIConsoleService
> console
156 (do_GetService(NS_CONSOLESERVICE_CONTRACTID
));
158 nsCOMPtr
<nsIScriptError
> error
159 (do_CreateInstance(NS_SCRIPTERROR_CONTRACTID
));
160 if (!console
|| !error
)
164 va_start(args
, aMsg
);
165 char* formatted
= PR_vsmprintf(aMsg
, args
);
174 rv
= error
->Init(NS_ConvertUTF8toUTF16(formatted
).get(),
175 NS_ConvertUTF8toUTF16(spec
).get(),
177 aLineNumber
, 0, flags
, "chrome registration");
178 PR_smprintf_free(formatted
);
183 console
->LogMessage(error
);
186 // We use a "best-fit" algorithm for matching locales and themes.
187 // 1) the exact selected locale/theme
188 // 2) (locales only) same language, different country
189 // e.g. en-GB is the selected locale, only en-US is available
190 // 3) any available locale/theme
193 * Match the language-part of two lang-COUNTRY codes, hopefully but
194 * not guaranteed to be in the form ab-CD or abz-CD. "ab" should also
195 * work, any other garbage-in will produce undefined results as long
196 * as it does not crash.
199 LanguagesMatch(const nsACString
& a
, const nsACString
& b
)
201 if (a
.Length() < 2 || b
.Length() < 2)
204 nsACString::const_iterator as
, ae
, bs
, be
;
217 if (as
== ae
&& bs
== be
)
233 CanLoadResource(nsIURI
* aResourceURI
)
235 PRBool isLocalResource
= PR_FALSE
;
236 (void)NS_URIChainHasFlags(aResourceURI
,
237 nsIProtocolHandler::URI_IS_LOCAL_RESOURCE
,
239 return isLocalResource
;
242 nsChromeRegistry::ProviderEntry
*
243 nsChromeRegistry::nsProviderArray::GetProvider(const nsACString
& aPreferred
, MatchType aType
)
245 PRInt32 i
= mArray
.Count();
249 ProviderEntry
* found
= nsnull
; // Only set if we find a partial-match locale
250 ProviderEntry
* entry
;
253 entry
= reinterpret_cast<ProviderEntry
*>(mArray
[i
]);
254 if (aPreferred
.Equals(entry
->provider
))
260 if (LanguagesMatch(aPreferred
, entry
->provider
)) {
265 if (!found
&& entry
->provider
.EqualsLiteral("en-US"))
269 if (!found
&& aType
!= EXACT
)
276 nsChromeRegistry::nsProviderArray::GetBase(const nsACString
& aPreferred
, MatchType aType
)
278 ProviderEntry
* provider
= GetProvider(aPreferred
, aType
);
283 return provider
->baseURI
;
287 nsChromeRegistry::nsProviderArray::GetSelected(const nsACString
& aPreferred
, MatchType aType
)
289 ProviderEntry
* entry
= GetProvider(aPreferred
, aType
);
292 return entry
->provider
;
294 return EmptyCString();
298 nsChromeRegistry::nsProviderArray::SetBase(const nsACString
& aProvider
, nsIURI
* aBaseURL
)
300 ProviderEntry
* provider
= GetProvider(aProvider
, EXACT
);
303 provider
->baseURI
= aBaseURL
;
307 // no existing entries, add a new one
308 provider
= new ProviderEntry(aProvider
, aBaseURL
);
310 return; // It's safe to silently fail on OOM
312 mArray
.AppendElement(provider
);
316 nsChromeRegistry::nsProviderArray::EnumerateToArray(nsTArray
<nsCString
> *a
)
318 PRInt32 i
= mArray
.Count();
320 ProviderEntry
*entry
= reinterpret_cast<ProviderEntry
*>(mArray
[i
]);
321 a
->AppendElement(entry
->provider
);
326 nsChromeRegistry::nsProviderArray::Clear()
328 PRInt32 i
= mArray
.Count();
330 ProviderEntry
* entry
= reinterpret_cast<ProviderEntry
*>(mArray
[i
]);
337 nsChromeRegistry::PackageEntry::PackageEntry(const nsACString
& aPackage
) :
338 package(aPackage
), flags(0)
343 nsChromeRegistry::HashKey(PLDHashTable
*table
, const void *key
)
345 const nsACString
& str
= *reinterpret_cast<const nsACString
*>(key
);
346 return HashString(str
);
350 nsChromeRegistry::MatchKey(PLDHashTable
*table
, const PLDHashEntryHdr
*entry
,
353 const nsACString
& str
= *reinterpret_cast<const nsACString
*>(key
);
354 const PackageEntry
* pentry
= static_cast<const PackageEntry
*>(entry
);
355 return str
.Equals(pentry
->package
);
359 nsChromeRegistry::ClearEntry(PLDHashTable
*table
, PLDHashEntryHdr
*entry
)
361 PackageEntry
* pentry
= static_cast<PackageEntry
*>(entry
);
362 pentry
->~PackageEntry();
366 nsChromeRegistry::InitEntry(PLDHashTable
*table
, PLDHashEntryHdr
*entry
,
369 const nsACString
& str
= *reinterpret_cast<const nsACString
*>(key
);
371 new (entry
) PackageEntry(str
);
375 const PLDHashTableOps
376 nsChromeRegistry::kTableOps
= {
381 PL_DHashMoveEntryStub
,
383 PL_DHashFinalizeStub
,
388 nsChromeRegistry::OverlayListEntry::AddURI(nsIURI
* aURI
)
390 PRInt32 i
= mArray
.Count();
393 if (NS_SUCCEEDED(aURI
->Equals(mArray
[i
], &equals
)) && equals
)
397 mArray
.AppendObject(aURI
);
401 nsChromeRegistry::OverlayListHash::Add(nsIURI
* aBase
, nsIURI
* aOverlay
)
403 OverlayListEntry
* entry
= mTable
.PutEntry(aBase
);
405 entry
->AddURI(aOverlay
);
408 const nsCOMArray
<nsIURI
>*
409 nsChromeRegistry::OverlayListHash::GetArray(nsIURI
* aBase
)
411 OverlayListEntry
* entry
= mTable
.GetEntry(aBase
);
415 return &entry
->mArray
;
418 nsChromeRegistry::~nsChromeRegistry()
420 if (mPackagesHash
.ops
)
421 PL_DHashTableFinish(&mPackagesHash
);
422 gChromeRegistry
= nsnull
;
425 NS_INTERFACE_MAP_BEGIN(nsChromeRegistry
)
426 NS_INTERFACE_MAP_ENTRY(nsIChromeRegistry
)
427 NS_INTERFACE_MAP_ENTRY(nsIXULChromeRegistry
)
428 NS_INTERFACE_MAP_ENTRY(nsIToolkitChromeRegistry
)
430 NS_INTERFACE_MAP_ENTRY(nsIXULOverlayProvider
)
432 NS_INTERFACE_MAP_ENTRY(nsIObserver
)
433 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference
)
434 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIChromeRegistry
)
437 NS_IMPL_ADDREF(nsChromeRegistry
)
438 NS_IMPL_RELEASE(nsChromeRegistry
)
440 ////////////////////////////////////////////////////////////////////////////////
441 // nsIChromeRegistry methods:
444 getUILangCountry(nsACString
& aUILang
)
448 nsCOMPtr
<nsILocaleService
> localeService
= do_GetService(NS_LOCALESERVICE_CONTRACTID
, &rv
);
449 NS_ENSURE_SUCCESS(rv
, rv
);
452 rv
= localeService
->GetLocaleComponentForUserAgent(uiLang
);
453 NS_ENSURE_SUCCESS(rv
, rv
);
455 CopyUTF16toUTF8(uiLang
, aUILang
);
460 nsChromeRegistry::Init()
464 // Check to see if necko and the JAR protocol handler are registered yet
465 // if not, somebody is doing work during XPCOM registration that they
466 // shouldn't be doing. See bug 292549, where JS components are trying
467 // to call Components.utils.import("chrome:///") early in registration
469 nsCOMPtr
<nsIIOService
> io (do_GetIOService());
470 if (!io
) return NS_ERROR_FAILURE
;
472 nsCOMPtr
<nsIProtocolHandler
> ph
;
473 rv
= io
->GetProtocolHandler("jar", getter_AddRefs(ph
));
474 NS_ENSURE_SUCCESS(rv
, rv
);
476 nsCOMPtr
<nsIJARProtocolHandler
> jph
= do_QueryInterface(ph
);
478 return NS_ERROR_NOT_INITIALIZED
;
480 if (!PL_DHashTableInit(&mPackagesHash
, &kTableOps
,
481 nsnull
, sizeof(PackageEntry
), 16))
482 return NS_ERROR_FAILURE
;
484 if (!mOverlayHash
.Init() ||
485 !mStyleHash
.Init() ||
486 !mOverrideTable
.Init())
487 return NS_ERROR_FAILURE
;
489 mSelectedLocale
= NS_LITERAL_CSTRING("en-US");
490 mSelectedSkin
= NS_LITERAL_CSTRING("classic/1.0");
492 // This initialization process is fairly complicated and may cause reentrant
493 // getservice calls to resolve chrome URIs (especially locale files). We
494 // don't want that, so we inform the protocol handler about our existence
495 // before we are actually fully initialized.
496 gChromeRegistry
= this;
498 PRBool safeMode
= PR_FALSE
;
499 nsCOMPtr
<nsIXULRuntime
> xulrun (do_GetService(XULAPPINFO_SERVICE_CONTRACTID
));
501 xulrun
->GetInSafeMode(&safeMode
);
503 nsCOMPtr
<nsIPrefService
> prefserv (do_GetService(NS_PREFSERVICE_CONTRACTID
));
504 nsCOMPtr
<nsIPrefBranch
> prefs
;
507 prefserv
->GetDefaultBranch(nsnull
, getter_AddRefs(prefs
));
509 prefs
= do_QueryInterface(prefserv
);
512 NS_WARNING("Could not get pref service!");
515 nsXPIDLCString provider
;
516 rv
= prefs
->GetCharPref(SELECTED_SKIN_PREF
, getter_Copies(provider
));
517 if (NS_SUCCEEDED(rv
))
518 mSelectedSkin
= provider
;
520 SelectLocaleFromPref(prefs
);
522 nsCOMPtr
<nsIPrefBranch2
> prefs2 (do_QueryInterface(prefs
));
524 rv
= prefs2
->AddObserver(MATCH_OS_LOCALE_PREF
, this, PR_TRUE
);
525 rv
= prefs2
->AddObserver(SELECTED_LOCALE_PREF
, this, PR_TRUE
);
526 rv
= prefs2
->AddObserver(SELECTED_SKIN_PREF
, this, PR_TRUE
);
530 nsCOMPtr
<nsIObserverService
> obsService (do_GetService("@mozilla.org/observer-service;1"));
532 obsService
->AddObserver(this, "command-line-startup", PR_TRUE
);
533 obsService
->AddObserver(this, "profile-initial-state", PR_TRUE
);
538 mInitialized
= PR_TRUE
;
544 nsChromeRegistry::CheckForOSAccessibility()
548 nsCOMPtr
<nsILookAndFeel
> lookAndFeel (do_GetService(kLookAndFeelCID
));
550 PRInt32 useAccessibilityTheme
= 0;
552 rv
= lookAndFeel
->GetMetric(nsILookAndFeel::eMetric_UseAccessibilityTheme
,
553 useAccessibilityTheme
);
555 if (NS_SUCCEEDED(rv
) && useAccessibilityTheme
) {
556 /* Set the skin to classic and remove pref observers */
557 if (!mSelectedSkin
.EqualsLiteral("classic/1.0")) {
558 mSelectedSkin
.AssignLiteral("classic/1.0");
562 nsCOMPtr
<nsIPrefBranch2
> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID
));
564 prefs
->RemoveObserver(SELECTED_SKIN_PREF
, this);
573 nsChromeRegistry::GetProviderAndPath(nsIURL
* aChromeURL
,
574 nsACString
& aProvider
, nsACString
& aPath
)
580 aChromeURL
->SchemeIs("chrome", &isChrome
);
581 NS_ASSERTION(isChrome
, "Non-chrome URI?");
585 rv
= aChromeURL
->GetPath(path
);
586 NS_ENSURE_SUCCESS(rv
, rv
);
588 if (path
.Length() < 3) {
589 LogMessage("Invalid chrome URI: %s", path
.get());
590 return NS_ERROR_FAILURE
;
593 path
.SetLength(nsUnescapeCount(path
.BeginWriting()));
594 NS_ASSERTION(path
.First() == '/', "Path should always begin with a slash!");
596 PRInt32 slash
= path
.FindChar('/', 1);
598 LogMessage("Invalid chrome URI: %s", path
.get());
599 return NS_ERROR_FAILURE
;
606 if (slash
== (PRInt32
) path
.Length() - 1)
609 aPath
.Assign(path
.get() + slash
+ 1, path
.Length() - slash
- 1);
614 aProvider
.Assign(path
.get() + 1, slash
);
620 nsChromeRegistry::Canonify(nsIURL
* aChromeURL
)
622 NS_NAMED_LITERAL_CSTRING(kSlash
, "/");
626 nsCAutoString provider
, path
;
627 rv
= GetProviderAndPath(aChromeURL
, provider
, path
);
628 NS_ENSURE_SUCCESS(rv
, rv
);
630 if (path
.IsEmpty()) {
631 nsCAutoString package
;
632 rv
= aChromeURL
->GetHost(package
);
633 NS_ENSURE_SUCCESS(rv
, rv
);
635 // we re-use the "path" local string to build a new URL path
636 path
.Assign(kSlash
+ provider
+ kSlash
+ package
);
637 if (provider
.EqualsLiteral("content")) {
638 path
.AppendLiteral(".xul");
640 else if (provider
.EqualsLiteral("locale")) {
641 path
.AppendLiteral(".dtd");
643 else if (provider
.EqualsLiteral("skin")) {
644 path
.AppendLiteral(".css");
647 return NS_ERROR_INVALID_ARG
;
649 aChromeURL
->SetPath(path
);
652 // prevent directory traversals ("..")
653 // path is already unescaped once, but uris can get unescaped twice
654 const char* pos
= path
.BeginReading();
655 const char* end
= path
.EndReading();
659 return NS_ERROR_DOM_BAD_URI
;
662 return NS_ERROR_DOM_BAD_URI
;
665 // chrome: URIs with double-escapes are trying to trick us.
666 // watch for %2e, and %25 in case someone triple unescapes
668 ( pos
[2] == 'e' || pos
[2] == 'E' ||
670 return NS_ERROR_DOM_BAD_URI
;
685 nsChromeRegistry::ConvertChromeURL(nsIURI
* aChromeURI
, nsIURI
* *aResult
)
688 NS_ASSERTION(aChromeURI
, "null url!");
690 if (mOverrideTable
.Get(aChromeURI
, aResult
))
693 nsCOMPtr
<nsIURL
> chromeURL (do_QueryInterface(aChromeURI
));
694 NS_ENSURE_TRUE(chromeURL
, NS_NOINTERFACE
);
696 nsCAutoString package
, provider
, path
;
697 rv
= chromeURL
->GetHostPort(package
);
698 NS_ENSURE_SUCCESS(rv
, rv
);
700 rv
= GetProviderAndPath(chromeURL
, provider
, path
);
701 NS_ENSURE_SUCCESS(rv
, rv
);
703 PackageEntry
* entry
=
704 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
705 & (nsACString
&) package
,
708 if (PL_DHASH_ENTRY_IS_FREE(entry
)) {
710 return NS_ERROR_NOT_INITIALIZED
;
712 LogMessage("No chrome package registered for chrome://%s/%s/%s",
713 package
.get(), provider
.get(), path
.get());
715 return NS_ERROR_FAILURE
;
718 if (entry
->flags
& PackageEntry::PLATFORM_PACKAGE
) {
719 #if defined(XP_WIN) || defined(XP_OS2)
720 path
.Insert("win/", 0);
721 #elif defined(XP_MACOSX)
722 path
.Insert("mac/", 0);
724 path
.Insert("unix/", 0);
728 nsIURI
* baseURI
= nsnull
;
729 if (provider
.EqualsLiteral("locale")) {
730 baseURI
= entry
->locales
.GetBase(mSelectedLocale
, nsProviderArray::LOCALE
);
732 else if (provider
.EqualsLiteral("skin")) {
733 baseURI
= entry
->skins
.GetBase(mSelectedSkin
, nsProviderArray::ANY
);
735 else if (provider
.EqualsLiteral("content")) {
736 baseURI
= entry
->baseURI
;
740 LogMessage("No chrome package registered for chrome://%s/%s/%s",
741 package
.get(), provider
.get(), path
.get());
742 return NS_ERROR_FAILURE
;
745 return NS_NewURI(aResult
, path
, nsnull
, baseURI
);
749 nsChromeRegistry::GetSelectedLocale(const nsACString
& aPackage
, nsACString
& aLocale
)
751 PackageEntry
* entry
=
752 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
756 if (PL_DHASH_ENTRY_IS_FREE(entry
))
757 return NS_ERROR_FAILURE
;
759 aLocale
= entry
->locales
.GetSelected(mSelectedLocale
, nsProviderArray::LOCALE
);
760 if (aLocale
.IsEmpty())
761 return NS_ERROR_FAILURE
;
767 nsChromeRegistry::IsLocaleRTL(const nsACString
& package
, PRBool
*aResult
)
771 nsCAutoString locale
;
772 GetSelectedLocale(package
, locale
);
773 if (locale
.Length() < 2)
776 // first check the intl.uidirection.<locale> preference, and if that is not
777 // set, check the same preference but with just the first two characters of
778 // the locale. If that isn't set, default to left-to-right.
779 nsCAutoString prefString
= NS_LITERAL_CSTRING("intl.uidirection.") + locale
;
780 nsCOMPtr
<nsIPrefBranch
> prefBranch (do_GetService(NS_PREFSERVICE_CONTRACTID
));
785 prefBranch
->GetCharPref(prefString
.get(), getter_Copies(dir
));
787 PRInt32 hyphen
= prefString
.FindChar('-');
789 nsCAutoString
shortPref(Substring(prefString
, 0, hyphen
));
790 prefBranch
->GetCharPref(shortPref
.get(), getter_Copies(dir
));
793 *aResult
= dir
.EqualsLiteral("rtl");
798 nsChromeRegistry::GetLocalesForPackage(const nsACString
& aPackage
,
799 nsIUTF8StringEnumerator
* *aResult
)
801 nsTArray
<nsCString
> *a
= new nsTArray
<nsCString
>;
803 return NS_ERROR_OUT_OF_MEMORY
;
805 PackageEntry
* entry
=
806 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
810 if (PL_DHASH_ENTRY_IS_BUSY(entry
)) {
811 entry
->locales
.EnumerateToArray(a
);
814 nsresult rv
= NS_NewAdoptingUTF8StringEnumerator(aResult
, a
);
823 nsChromeRegistry::GetStyleOverlays(nsIURI
*aChromeURL
,
824 nsISimpleEnumerator
**aResult
)
826 const nsCOMArray
<nsIURI
>* parray
= mStyleHash
.GetArray(aChromeURL
);
828 return NS_NewEmptyEnumerator(aResult
);
830 return NS_NewArrayEnumerator(aResult
, *parray
);
834 nsChromeRegistry::GetXULOverlays(nsIURI
*aChromeURL
, nsISimpleEnumerator
**aResult
)
836 const nsCOMArray
<nsIURI
>* parray
= mOverlayHash
.GetArray(aChromeURL
);
838 return NS_NewEmptyEnumerator(aResult
);
840 return NS_NewArrayEnumerator(aResult
, *parray
);
844 ////////////////////////////////////////////////////////////////////////
849 static void FlushSkinBindingsForWindow(nsIDOMWindowInternal
* aWindow
)
851 // Get the DOM document.
852 nsCOMPtr
<nsIDOMDocument
> domDocument
;
853 aWindow
->GetDocument(getter_AddRefs(domDocument
));
857 nsCOMPtr
<nsIDocument
> document
= do_QueryInterface(domDocument
);
861 // Annihilate all XBL bindings.
862 document
->FlushSkinBindings();
865 // XXXbsmedberg: move this to nsIWindowMediator
866 NS_IMETHODIMP
nsChromeRegistry::RefreshSkins()
868 nsCOMPtr
<nsICSSLoader
> cssLoader(do_CreateInstance(kCSSLoaderCID
));
872 nsCOMPtr
<nsIWindowMediator
> windowMediator
873 (do_GetService(NS_WINDOWMEDIATOR_CONTRACTID
));
877 nsCOMPtr
<nsISimpleEnumerator
> windowEnumerator
;
878 windowMediator
->GetEnumerator(nsnull
, getter_AddRefs(windowEnumerator
));
880 windowEnumerator
->HasMoreElements(&more
);
882 nsCOMPtr
<nsISupports
> protoWindow
;
883 windowEnumerator
->GetNext(getter_AddRefs(protoWindow
));
885 nsCOMPtr
<nsIDOMWindowInternal
> domWindow
= do_QueryInterface(protoWindow
);
887 FlushSkinBindingsForWindow(domWindow
);
889 windowEnumerator
->HasMoreElements(&more
);
894 windowMediator
->GetEnumerator(nsnull
, getter_AddRefs(windowEnumerator
));
895 windowEnumerator
->HasMoreElements(&more
);
897 nsCOMPtr
<nsISupports
> protoWindow
;
898 windowEnumerator
->GetNext(getter_AddRefs(protoWindow
));
900 nsCOMPtr
<nsIDOMWindowInternal
> domWindow
= do_QueryInterface(protoWindow
);
902 RefreshWindow(domWindow
, cssLoader
);
904 windowEnumerator
->HasMoreElements(&more
);
911 nsChromeRegistry::FlushSkinCaches()
913 nsCOMPtr
<nsIObserverService
> obsSvc
=
914 do_GetService("@mozilla.org/observer-service;1");
915 NS_ASSERTION(obsSvc
, "Couldn't get observer service.");
917 obsSvc
->NotifyObservers(static_cast<nsIChromeRegistry
*>(this),
918 NS_CHROME_FLUSH_SKINS_TOPIC
, nsnull
);
921 static PRBool
IsChromeURI(nsIURI
* aURI
)
923 PRBool isChrome
=PR_FALSE
;
924 if (NS_SUCCEEDED(aURI
->SchemeIs("chrome", &isChrome
)) && isChrome
)
929 // XXXbsmedberg: move this to windowmediator
930 nsresult
nsChromeRegistry::RefreshWindow(nsIDOMWindowInternal
* aWindow
,
931 nsICSSLoader
* aCSSLoader
)
933 // Deal with our subframes first.
934 nsCOMPtr
<nsIDOMWindowCollection
> frames
;
935 aWindow
->GetFrames(getter_AddRefs(frames
));
937 frames
->GetLength(&length
);
939 for (j
= 0; j
< length
; j
++) {
940 nsCOMPtr
<nsIDOMWindow
> childWin
;
941 frames
->Item(j
, getter_AddRefs(childWin
));
942 nsCOMPtr
<nsIDOMWindowInternal
> childInt(do_QueryInterface(childWin
));
943 RefreshWindow(childInt
, aCSSLoader
);
947 // Get the DOM document.
948 nsCOMPtr
<nsIDOMDocument
> domDocument
;
949 aWindow
->GetDocument(getter_AddRefs(domDocument
));
953 nsCOMPtr
<nsIDocument
> document
= do_QueryInterface(domDocument
);
957 // Deal with the agent sheets first. Have to do all the style sets by hand.
958 nsCOMPtr
<nsIPresShell
> shell
= document
->GetPrimaryShell();
960 // Reload only the chrome URL agent style sheets.
961 nsCOMArray
<nsIStyleSheet
> agentSheets
;
962 rv
= shell
->GetAgentStyleSheets(agentSheets
);
963 NS_ENSURE_SUCCESS(rv
, rv
);
965 nsCOMArray
<nsIStyleSheet
> newAgentSheets
;
966 for (PRInt32 l
= 0; l
< agentSheets
.Count(); ++l
) {
967 nsIStyleSheet
*sheet
= agentSheets
[l
];
969 nsCOMPtr
<nsIURI
> uri
;
970 rv
= sheet
->GetSheetURI(getter_AddRefs(uri
));
971 if (NS_FAILED(rv
)) return rv
;
973 if (IsChromeURI(uri
)) {
975 nsCOMPtr
<nsICSSStyleSheet
> newSheet
;
976 rv
= aCSSLoader
->LoadSheetSync(uri
, PR_TRUE
, PR_TRUE
,
977 getter_AddRefs(newSheet
));
978 if (NS_FAILED(rv
)) return rv
;
980 rv
= newAgentSheets
.AppendObject(newSheet
) ? NS_OK
: NS_ERROR_FAILURE
;
981 if (NS_FAILED(rv
)) return rv
;
984 else { // Just use the same sheet.
985 rv
= newAgentSheets
.AppendObject(sheet
) ? NS_OK
: NS_ERROR_FAILURE
;
986 if (NS_FAILED(rv
)) return rv
;
990 rv
= shell
->SetAgentStyleSheets(newAgentSheets
);
991 NS_ENSURE_SUCCESS(rv
, rv
);
994 // Build an array of nsIURIs of style sheets we need to load.
995 nsCOMArray
<nsIStyleSheet
> oldSheets
;
996 nsCOMArray
<nsIStyleSheet
> newSheets
;
998 PRInt32 count
= document
->GetNumberOfStyleSheets();
1000 // Iterate over the style sheets.
1002 for (i
= 0; i
< count
; i
++) {
1003 // Get the style sheet
1004 nsIStyleSheet
*styleSheet
= document
->GetStyleSheetAt(i
);
1006 if (!oldSheets
.AppendObject(styleSheet
)) {
1007 return NS_ERROR_OUT_OF_MEMORY
;
1011 // Iterate over our old sheets and kick off a sync load of the new
1012 // sheet if and only if it's a chrome URL.
1013 for (i
= 0; i
< count
; i
++) {
1014 nsCOMPtr
<nsICSSStyleSheet
> sheet
= do_QueryInterface(oldSheets
[i
]);
1015 nsIURI
* uri
= sheet
? sheet
->GetOriginalURI() : nsnull
;
1017 if (uri
&& IsChromeURI(uri
)) {
1018 // Reload the sheet.
1019 nsCOMPtr
<nsICSSStyleSheet
> newSheet
;
1020 // XXX what about chrome sheets that have a title or are disabled? This
1021 // only works by sheer dumb luck.
1022 // XXXbz this should really use the document's CSSLoader!
1023 aCSSLoader
->LoadSheetSync(uri
, getter_AddRefs(newSheet
));
1024 // Even if it's null, we put in in there.
1025 newSheets
.AppendObject(newSheet
);
1028 // Just use the same sheet.
1029 newSheets
.AppendObject(sheet
);
1033 // Now notify the document that multiple sheets have been added and removed.
1034 document
->UpdateStyleSheets(oldSheets
, newSheets
);
1039 nsChromeRegistry::FlushAllCaches()
1041 nsCOMPtr
<nsIObserverService
> obsSvc
=
1042 do_GetService("@mozilla.org/observer-service;1");
1043 NS_ASSERTION(obsSvc
, "Couldn't get observer service.");
1045 obsSvc
->NotifyObservers((nsIChromeRegistry
*) this,
1046 NS_CHROME_FLUSH_TOPIC
, nsnull
);
1049 // xxxbsmedberg Move me to nsIWindowMediator
1051 nsChromeRegistry::ReloadChrome()
1054 // Do a reload of all top level windows.
1055 nsresult rv
= NS_OK
;
1057 // Get the window mediator
1058 nsCOMPtr
<nsIWindowMediator
> windowMediator
1059 (do_GetService(NS_WINDOWMEDIATOR_CONTRACTID
));
1060 if (windowMediator
) {
1061 nsCOMPtr
<nsISimpleEnumerator
> windowEnumerator
;
1063 rv
= windowMediator
->GetEnumerator(nsnull
, getter_AddRefs(windowEnumerator
));
1064 if (NS_SUCCEEDED(rv
)) {
1065 // Get each dom window
1067 rv
= windowEnumerator
->HasMoreElements(&more
);
1068 if (NS_FAILED(rv
)) return rv
;
1070 nsCOMPtr
<nsISupports
> protoWindow
;
1071 rv
= windowEnumerator
->GetNext(getter_AddRefs(protoWindow
));
1072 if (NS_SUCCEEDED(rv
)) {
1073 nsCOMPtr
<nsIDOMWindowInternal
> domWindow
=
1074 do_QueryInterface(protoWindow
);
1076 nsCOMPtr
<nsIDOMLocation
> location
;
1077 domWindow
->GetLocation(getter_AddRefs(location
));
1079 rv
= location
->Reload(PR_FALSE
);
1080 if (NS_FAILED(rv
)) return rv
;
1084 rv
= windowEnumerator
->HasMoreElements(&more
);
1085 if (NS_FAILED(rv
)) return rv
;
1093 nsChromeRegistry::AllowScriptsForPackage(nsIURI
* aChromeURI
, PRBool
*aResult
)
1096 *aResult
= PR_FALSE
;
1100 aChromeURI
->SchemeIs("chrome", &isChrome
);
1101 NS_ASSERTION(isChrome
, "Non-chrome URI passed to AllowScriptsForPackage!");
1104 nsCOMPtr
<nsIURL
> url (do_QueryInterface(aChromeURI
));
1105 NS_ENSURE_TRUE(url
, NS_NOINTERFACE
);
1107 nsCAutoString provider
, file
;
1108 rv
= GetProviderAndPath(url
, provider
, file
);
1109 NS_ENSURE_SUCCESS(rv
, rv
);
1111 if (!provider
.EqualsLiteral("skin"))
1118 nsChromeRegistry::AllowContentToAccess(nsIURI
*aURI
, PRBool
*aResult
)
1122 *aResult
= PR_FALSE
;
1126 aURI
->SchemeIs("chrome", &isChrome
);
1127 NS_ASSERTION(isChrome
, "Non-chrome URI passed to AllowContentToAccess!");
1130 nsCOMPtr
<nsIURL
> url
= do_QueryInterface(aURI
);
1132 NS_ERROR("Chrome URL doesn't implement nsIURL.");
1133 return NS_ERROR_UNEXPECTED
;
1136 nsCAutoString package
;
1137 rv
= url
->GetHostPort(package
);
1138 NS_ENSURE_SUCCESS(rv
, rv
);
1140 PackageEntry
*entry
=
1141 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
1142 & (nsACString
&) package
,
1145 if (PL_DHASH_ENTRY_IS_BUSY(entry
)) {
1146 *aResult
= !!(entry
->flags
& PackageEntry::CONTENT_ACCESSIBLE
);
1151 static PLDHashOperator
1152 RemoveAll(PLDHashTable
*table
, PLDHashEntryHdr
*entry
, PRUint32 number
, void *arg
)
1154 return (PLDHashOperator
) (PL_DHASH_NEXT
| PL_DHASH_REMOVE
);
1158 nsChromeRegistry::CheckForNewChrome()
1162 PL_DHashTableEnumerate(&mPackagesHash
, RemoveAll
, nsnull
);
1163 mOverlayHash
.Clear();
1165 mOverrideTable
.Clear();
1167 nsCOMPtr
<nsIProperties
> dirSvc (do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID
));
1168 NS_ENSURE_TRUE(dirSvc
, NS_ERROR_FAILURE
);
1170 // check the extra chrome directories
1171 nsCOMPtr
<nsISimpleEnumerator
> chromeML
;
1172 rv
= dirSvc
->Get(NS_CHROME_MANIFESTS_FILE_LIST
, NS_GET_IID(nsISimpleEnumerator
),
1173 getter_AddRefs(chromeML
));
1174 if (NS_FAILED(rv
)) {
1175 // ok, then simply load all .manifest files in the app chrome dir.
1176 nsCOMPtr
<nsIFile
> chromeDir
;
1177 rv
= dirSvc
->Get(NS_APP_CHROME_DIR
, NS_GET_IID(nsIFile
),
1178 getter_AddRefs(chromeDir
));
1181 rv
= NS_NewSingletonEnumerator(getter_AddRefs(chromeML
), chromeDir
);
1187 nsCOMPtr
<nsISupports
> next
;
1188 while (NS_SUCCEEDED(chromeML
->HasMoreElements(&exists
)) && exists
) {
1189 chromeML
->GetNext(getter_AddRefs(next
));
1190 nsCOMPtr
<nsILocalFile
> lmanifest
= do_QueryInterface(next
);
1192 NS_ERROR("Directory enumerator returned a non-nsILocalFile");
1197 if (NS_SUCCEEDED(lmanifest
->IsDirectory(&isDir
)) && isDir
) {
1198 nsCOMPtr
<nsISimpleEnumerator
> entries
;
1199 rv
= lmanifest
->GetDirectoryEntries(getter_AddRefs(entries
));
1203 while (NS_SUCCEEDED(entries
->HasMoreElements(&exists
)) && exists
) {
1204 entries
->GetNext(getter_AddRefs(next
));
1205 lmanifest
= do_QueryInterface(next
);
1207 nsCAutoString leafName
;
1208 lmanifest
->GetNativeLeafName(leafName
);
1209 if (StringEndsWith(leafName
, NS_LITERAL_CSTRING(".manifest"))) {
1210 rv
= ProcessManifest(lmanifest
, PR_FALSE
);
1211 if (NS_FAILED(rv
)) {
1213 lmanifest
->GetNativePath(path
);
1214 LogMessage("Failed to process chrome manifest '%s'.",
1223 rv
= ProcessManifest(lmanifest
, PR_FALSE
);
1224 if (NS_FAILED(rv
)) {
1226 lmanifest
->GetNativePath(path
);
1227 LogMessage("Failed to process chrome manifest: '%s'.",
1233 rv
= dirSvc
->Get(NS_SKIN_MANIFESTS_FILE_LIST
, NS_GET_IID(nsISimpleEnumerator
),
1234 getter_AddRefs(chromeML
));
1238 while (NS_SUCCEEDED(chromeML
->HasMoreElements(&exists
)) && exists
) {
1239 chromeML
->GetNext(getter_AddRefs(next
));
1240 nsCOMPtr
<nsILocalFile
> lmanifest
= do_QueryInterface(next
);
1242 NS_ERROR("Directory enumerator returned a non-nsILocalFile");
1246 rv
= ProcessManifest(lmanifest
, PR_TRUE
);
1247 if (NS_FAILED(rv
)) {
1249 lmanifest
->GetNativePath(path
);
1250 LogMessage("Failed to process chrome manifest: '%s'.",
1258 NS_IMETHODIMP_(PRBool
)
1259 nsChromeRegistry::WrappersEnabled(nsIURI
*aURI
)
1261 nsCOMPtr
<nsIURL
> chromeURL (do_QueryInterface(aURI
));
1265 PRBool isChrome
= PR_FALSE
;
1266 nsresult rv
= chromeURL
->SchemeIs("chrome", &isChrome
);
1267 if (NS_FAILED(rv
) || !isChrome
)
1270 nsCAutoString package
;
1271 rv
= chromeURL
->GetHostPort(package
);
1275 PackageEntry
* entry
=
1276 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
1277 & (nsACString
&) package
,
1280 return PL_DHASH_ENTRY_IS_LIVE(entry
) &&
1281 entry
->flags
& PackageEntry::XPCNATIVEWRAPPERS
;
1285 nsChromeRegistry::SelectLocaleFromPref(nsIPrefBranch
* prefs
)
1288 PRBool matchOSLocale
= PR_FALSE
, userLocaleOverride
= PR_FALSE
;
1289 prefs
->PrefHasUserValue(SELECTED_LOCALE_PREF
, &userLocaleOverride
);
1290 rv
= prefs
->GetBoolPref(MATCH_OS_LOCALE_PREF
, &matchOSLocale
);
1292 if (NS_SUCCEEDED(rv
) && matchOSLocale
&& !userLocaleOverride
) {
1293 // compute lang and region code only when needed!
1294 nsCAutoString uiLocale
;
1295 rv
= getUILangCountry(uiLocale
);
1296 if (NS_SUCCEEDED(rv
))
1297 mSelectedLocale
= uiLocale
;
1300 nsXPIDLCString provider
;
1301 rv
= prefs
->GetCharPref(SELECTED_LOCALE_PREF
, getter_Copies(provider
));
1302 if (NS_SUCCEEDED(rv
)) {
1303 mSelectedLocale
= provider
;
1310 NS_IMETHODIMP
nsChromeRegistry::Observe(nsISupports
*aSubject
, const char *aTopic
, const PRUnichar
*someData
)
1312 nsresult rv
= NS_OK
;
1314 if (!strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID
, aTopic
)) {
1315 nsCOMPtr
<nsIPrefBranch
> prefs (do_QueryInterface(aSubject
));
1316 NS_ASSERTION(prefs
, "Bad observer call!");
1318 NS_ConvertUTF16toUTF8
pref(someData
);
1320 if (pref
.EqualsLiteral(MATCH_OS_LOCALE_PREF
) ||
1321 pref
.EqualsLiteral(SELECTED_LOCALE_PREF
)) {
1322 rv
= SelectLocaleFromPref(prefs
);
1323 if (NS_SUCCEEDED(rv
) && mProfileLoaded
)
1326 else if (pref
.EqualsLiteral(SELECTED_SKIN_PREF
)) {
1327 nsXPIDLCString provider
;
1328 rv
= prefs
->GetCharPref(pref
.get(), getter_Copies(provider
));
1329 if (NS_FAILED(rv
)) {
1330 NS_ERROR("Couldn't get new locale pref!");
1334 mSelectedSkin
= provider
;
1337 NS_ERROR("Unexpected pref!");
1340 else if (!strcmp("command-line-startup", aTopic
)) {
1341 nsCOMPtr
<nsICommandLine
> cmdLine (do_QueryInterface(aSubject
));
1343 nsAutoString uiLocale
;
1344 rv
= cmdLine
->HandleFlagWithParam(NS_LITERAL_STRING(UILOCALE_CMD_LINE_ARG
),
1345 PR_FALSE
, uiLocale
);
1346 if (NS_SUCCEEDED(rv
) && !uiLocale
.IsEmpty()) {
1347 CopyUTF16toUTF8(uiLocale
, mSelectedLocale
);
1348 nsCOMPtr
<nsIPrefBranch2
> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID
));
1350 prefs
->RemoveObserver(SELECTED_LOCALE_PREF
, this);
1355 else if (!strcmp("profile-initial-state", aTopic
)) {
1356 mProfileLoaded
= PR_TRUE
;
1359 NS_ERROR("Unexpected observer topic!");
1366 nsChromeRegistry::ProcessManifest(nsILocalFile
* aManifest
, PRBool aSkinOnly
)
1371 rv
= aManifest
->OpenNSPRFileDesc(PR_RDONLY
, 0, &fd
);
1372 NS_ENSURE_SUCCESS(rv
, rv
);
1377 size
= PR_Available(fd
);
1379 rv
= NS_ERROR_UNEXPECTED
;
1383 buf
= (char *) malloc(size
+ 1);
1385 rv
= NS_ERROR_OUT_OF_MEMORY
;
1389 n
= PR_Read(fd
, buf
, size
);
1392 rv
= ProcessManifestBuffer(buf
, size
, aManifest
, aSkinOnly
);
1401 static const char kWhitespace
[] = "\t ";
1402 static const char kNewlines
[] = "\r\n";
1405 * Check for a modifier flag of the following forms:
1406 * "flag" (same as "true")
1408 * "flag="no|false|0"
1409 * @param aFlag The flag to compare.
1410 * @param aData The tokenized data to check; this is lowercased
1411 * before being passed in.
1412 * @param aResult If the flag is found, the value is assigned here.
1413 * @return Whether the flag was handled.
1416 CheckFlag(const nsSubstring
& aFlag
, const nsSubstring
& aData
, PRBool
& aResult
)
1418 if (!StringBeginsWith(aData
, aFlag
))
1421 if (aFlag
.Length() == aData
.Length()) {
1422 // the data is simply "flag", which is the same as "flag=yes"
1427 if (aData
.CharAt(aFlag
.Length()) != '=') {
1428 // the data is "flag2=", which is not anything we care about
1432 if (aData
.Length() == aFlag
.Length() + 1) {
1437 switch (aData
.CharAt(aFlag
.Length() + 1)) {
1461 * Check for a modifier flag of the following form:
1464 * @param aFlag The flag to compare.
1465 * @param aData The tokenized data to check; this is lowercased
1466 * before being passed in.
1467 * @param aValue The value that is expected.
1468 * @param aResult If this is "ok" when passed in, this is left alone.
1469 * Otherwise if the flag is found it is set to eBad or eOK.
1470 * @return Whether the flag was handled.
1473 CheckStringFlag(const nsSubstring
& aFlag
, const nsSubstring
& aData
,
1474 const nsSubstring
& aValue
, TriState
& aResult
)
1476 if (aData
.Length() < aFlag
.Length() + 1)
1479 if (!StringBeginsWith(aData
, aFlag
))
1482 PRBool comparison
= PR_TRUE
;
1483 if (aData
[aFlag
.Length()] != '=') {
1484 if (aData
[aFlag
.Length()] == '!' &&
1485 aData
.Length() >= aFlag
.Length() + 2 &&
1486 aData
[aFlag
.Length() + 1] == '=')
1487 comparison
= PR_FALSE
;
1492 if (aResult
!= eOK
) {
1493 nsDependentSubstring testdata
= Substring(aData
, aFlag
.Length() + (comparison
? 1 : 2));
1494 if (testdata
.Equals(aValue
))
1495 aResult
= comparison
? eOK
: eBad
;
1497 aResult
= comparison
? eBad
: eOK
;
1504 * Check for a modifier flag of the following form:
1510 * @param aFlag The flag to compare.
1511 * @param aData The tokenized data to check; this is lowercased
1512 * before being passed in.
1513 * @param aValue The value that is expected. If this is empty then no
1514 * comparison will match.
1515 * @param aChecker the version checker to use. If null, aResult will always
1517 * @param aResult If this is eOK when passed in, this is left alone.
1518 * Otherwise if the flag is found it is set to eBad or eOK.
1519 * @return Whether the flag was handled.
1522 #define COMPARE_EQ 1 << 0
1523 #define COMPARE_LT 1 << 1
1524 #define COMPARE_GT 1 << 2
1527 CheckVersionFlag(const nsSubstring
& aFlag
, const nsSubstring
& aData
,
1528 const nsSubstring
& aValue
, nsIVersionComparator
* aChecker
,
1531 if (aData
.Length() < aFlag
.Length() + 2)
1534 if (!StringBeginsWith(aData
, aFlag
))
1537 if (aValue
.Length() == 0) {
1543 PRUint32 comparison
;
1544 nsAutoString testdata
;
1546 switch (aData
[aFlag
.Length()]) {
1548 comparison
= COMPARE_EQ
;
1549 testdata
= Substring(aData
, aFlag
.Length() + 1);
1553 if (aData
[aFlag
.Length() + 1] == '=') {
1554 comparison
= COMPARE_EQ
| COMPARE_LT
;
1555 testdata
= Substring(aData
, aFlag
.Length() + 2);
1558 comparison
= COMPARE_LT
;
1559 testdata
= Substring(aData
, aFlag
.Length() + 1);
1564 if (aData
[aFlag
.Length() + 1] == '=') {
1565 comparison
= COMPARE_EQ
| COMPARE_GT
;
1566 testdata
= Substring(aData
, aFlag
.Length() + 2);
1569 comparison
= COMPARE_GT
;
1570 testdata
= Substring(aData
, aFlag
.Length() + 1);
1578 if (testdata
.Length() == 0)
1581 if (aResult
!= eOK
) {
1587 nsresult rv
= aChecker
->Compare(NS_ConvertUTF16toUTF8(aValue
),
1588 NS_ConvertUTF16toUTF8(testdata
), &c
);
1589 if (NS_FAILED(rv
)) {
1593 if ((c
== 0 && comparison
& COMPARE_EQ
) ||
1594 (c
< 0 && comparison
& COMPARE_LT
) ||
1595 (c
> 0 && comparison
& COMPARE_GT
))
1607 EnsureLowerCase(char *aBuf
)
1609 for (; *aBuf
; ++aBuf
) {
1611 if (ch
>= 'A' && ch
<= 'Z')
1612 *aBuf
= ch
+ 'a' - 'A';
1617 nsChromeRegistry::ProcessManifestBuffer(char *buf
, PRInt32 length
,
1618 nsILocalFile
* aManifest
,
1623 NS_NAMED_LITERAL_STRING(kPlatform
, "platform");
1624 NS_NAMED_LITERAL_STRING(kXPCNativeWrappers
, "xpcnativewrappers");
1625 NS_NAMED_LITERAL_STRING(kContentAccessible
, "contentaccessible");
1626 NS_NAMED_LITERAL_STRING(kApplication
, "application");
1627 NS_NAMED_LITERAL_STRING(kAppVersion
, "appversion");
1628 NS_NAMED_LITERAL_STRING(kOs
, "os");
1629 NS_NAMED_LITERAL_STRING(kOsVersion
, "osversion");
1631 nsCOMPtr
<nsIIOService
> io (do_GetIOService());
1632 if (!io
) return NS_ERROR_FAILURE
;
1634 nsCOMPtr
<nsIProtocolHandler
> ph
;
1635 rv
= io
->GetProtocolHandler("resource", getter_AddRefs(ph
));
1636 NS_ENSURE_SUCCESS(rv
, rv
);
1638 nsCOMPtr
<nsIResProtocolHandler
> rph (do_QueryInterface(ph
));
1639 if (!rph
) return NS_ERROR_FAILURE
;
1641 nsCOMPtr
<nsIURI
> manifestURI
;
1642 rv
= io
->NewFileURI(aManifest
, getter_AddRefs(manifestURI
));
1643 NS_ENSURE_SUCCESS(rv
, rv
);
1645 nsCOMPtr
<nsIXPConnect
> xpc (do_GetService("@mozilla.org/js/xpc/XPConnect;1"));
1646 nsCOMPtr
<nsIVersionComparator
> vc (do_GetService("@mozilla.org/xpcom/version-comparator;1"));
1649 nsAutoString appVersion
;
1650 nsAutoString osTarget
;
1651 nsCOMPtr
<nsIXULAppInfo
> xapp (do_GetService(XULAPPINFO_SERVICE_CONTRACTID
));
1654 rv
= xapp
->GetID(s
);
1655 if (NS_SUCCEEDED(rv
))
1656 CopyUTF8toUTF16(s
, appID
);
1658 rv
= xapp
->GetVersion(s
);
1659 if (NS_SUCCEEDED(rv
))
1660 CopyUTF8toUTF16(s
, appVersion
);
1662 nsCOMPtr
<nsIXULRuntime
> xruntime (do_QueryInterface(xapp
));
1664 rv
= xruntime
->GetOS(s
);
1665 if (NS_SUCCEEDED(rv
)) {
1666 CopyUTF8toUTF16(s
, osTarget
);
1667 ToLowerCase(osTarget
);
1672 nsAutoString osVersion
;
1674 OSVERSIONINFO info
= { sizeof(OSVERSIONINFO
) };
1675 if (GetVersionEx(&info
)) {
1676 nsTextFormatter::ssprintf(osVersion
, NS_LITERAL_STRING("%ld.%ld").get(),
1677 info
.dwMajorVersion
,
1678 info
.dwMinorVersion
);
1680 #elif defined(XP_MACOSX)
1681 SInt32 majorVersion
, minorVersion
;
1682 if ((Gestalt(gestaltSystemVersionMajor
, &majorVersion
) == noErr
) &&
1683 (Gestalt(gestaltSystemVersionMinor
, &minorVersion
) == noErr
)) {
1684 nsTextFormatter::ssprintf(osVersion
, NS_LITERAL_STRING("%ld.%ld").get(),
1688 #elif defined(MOZ_WIDGET_GTK2)
1689 nsTextFormatter::ssprintf(osVersion
, NS_LITERAL_STRING("%ld.%ld").get(),
1695 char *newline
= buf
;
1698 // outer loop tokenizes by newline
1699 while (nsnull
!= (token
= nsCRT::strtok(newline
, kNewlines
, &newline
))) {
1702 if (*token
== '#') // ignore lines that begin with # as comments
1705 char *whitespace
= token
;
1706 token
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
1707 if (!token
) continue;
1709 if (!strcmp(token
, "content")) {
1711 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
1712 "Warning: Ignoring content registration in skin-only manifest.");
1715 char *package
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
1716 char *uri
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
1717 if (!package
|| !uri
) {
1718 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
1719 "Warning: Malformed content registration.");
1723 EnsureLowerCase(package
);
1725 // NOTE: We check for platform and xpcnativewrappers modifiers on
1726 // content packages, but they are *applied* to content|skin|locale.
1728 PRBool platform
= PR_FALSE
;
1729 PRBool xpcNativeWrappers
= PR_TRUE
;
1730 PRBool contentAccessible
= PR_FALSE
;
1731 TriState stAppVersion
= eUnspecified
;
1732 TriState stApp
= eUnspecified
;
1733 TriState stOsVersion
= eUnspecified
;
1734 TriState stOs
= eUnspecified
;
1736 PRBool badFlag
= PR_FALSE
;
1738 while (nsnull
!= (token
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
)) &&
1740 NS_ConvertASCIItoUTF16
wtoken(token
);
1741 ToLowerCase(wtoken
);
1743 if (CheckFlag(kPlatform
, wtoken
, platform
) ||
1744 CheckFlag(kXPCNativeWrappers
, wtoken
, xpcNativeWrappers
) ||
1745 CheckFlag(kContentAccessible
, wtoken
, contentAccessible
) ||
1746 CheckStringFlag(kApplication
, wtoken
, appID
, stApp
) ||
1747 CheckStringFlag(kOs
, wtoken
, osTarget
, stOs
) ||
1748 CheckVersionFlag(kOsVersion
, wtoken
, osVersion
, vc
, stOsVersion
) ||
1749 CheckVersionFlag(kAppVersion
, wtoken
, appVersion
, vc
, stAppVersion
))
1752 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
1753 "Warning: Unrecognized chrome registration modifier '%s'.",
1758 if (badFlag
|| stApp
== eBad
|| stAppVersion
== eBad
||
1759 stOs
== eBad
|| stOsVersion
== eBad
)
1762 nsCOMPtr
<nsIURI
> resolved
;
1763 rv
= io
->NewURI(nsDependentCString(uri
), nsnull
, manifestURI
,
1764 getter_AddRefs(resolved
));
1768 if (!CanLoadResource(resolved
)) {
1769 LogMessageWithContext(resolved
, line
, nsIScriptError::warningFlag
,
1770 "Warning: cannot register non-local URI '%s' as content.",
1775 PackageEntry
* entry
=
1776 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
1777 & (const nsACString
&) nsDependentCString(package
),
1780 return NS_ERROR_OUT_OF_MEMORY
;
1782 entry
->baseURI
= resolved
;
1785 entry
->flags
|= PackageEntry::PLATFORM_PACKAGE
;
1786 if (xpcNativeWrappers
)
1787 entry
->flags
|= PackageEntry::XPCNATIVEWRAPPERS
;
1788 if (contentAccessible
)
1789 entry
->flags
|= PackageEntry::CONTENT_ACCESSIBLE
;
1791 nsCAutoString
urlp("chrome://");
1792 urlp
.Append(package
);
1795 rv
= xpc
->FlagSystemFilenamePrefix(urlp
.get(), xpcNativeWrappers
);
1796 NS_ENSURE_SUCCESS(rv
, rv
);
1799 else if (!strcmp(token
, "locale")) {
1801 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
1802 "Warning: Ignoring locale registration in skin-only manifest.");
1805 char *package
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
1806 char *provider
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
1807 char *uri
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
1808 if (!package
|| !provider
|| !uri
) {
1809 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
1810 "Warning: Malformed locale registration.");
1814 EnsureLowerCase(package
);
1816 TriState stAppVersion
= eUnspecified
;
1817 TriState stApp
= eUnspecified
;
1818 TriState stOs
= eUnspecified
;
1819 TriState stOsVersion
= eUnspecified
;
1821 PRBool badFlag
= PR_FALSE
;
1823 while (nsnull
!= (token
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
)) &&
1825 NS_ConvertASCIItoUTF16
wtoken(token
);
1826 ToLowerCase(wtoken
);
1828 if (CheckStringFlag(kApplication
, wtoken
, appID
, stApp
) ||
1829 CheckStringFlag(kOs
, wtoken
, osTarget
, stOs
) ||
1830 CheckVersionFlag(kOsVersion
, wtoken
, osVersion
, vc
, stOsVersion
) ||
1831 CheckVersionFlag(kAppVersion
, wtoken
, appVersion
, vc
, stAppVersion
))
1834 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
1835 "Warning: Unrecognized chrome registration modifier '%s'.",
1840 if (badFlag
|| stApp
== eBad
|| stAppVersion
== eBad
||
1841 stOs
== eBad
|| stOsVersion
== eBad
)
1844 nsCOMPtr
<nsIURI
> resolved
;
1845 rv
= io
->NewURI(nsDependentCString(uri
), nsnull
, manifestURI
,
1846 getter_AddRefs(resolved
));
1850 if (!CanLoadResource(resolved
)) {
1851 LogMessageWithContext(resolved
, line
, nsIScriptError::warningFlag
,
1852 "Warning: cannot register non-local URI '%s' as a locale.",
1857 PackageEntry
* entry
=
1858 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
1859 & (const nsACString
&) nsDependentCString(package
),
1862 return NS_ERROR_OUT_OF_MEMORY
;
1864 entry
->locales
.SetBase(nsDependentCString(provider
), resolved
);
1866 else if (!strcmp(token
, "skin")) {
1867 char *package
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
1868 char *provider
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
1869 char *uri
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
1870 if (!package
|| !provider
|| !uri
) {
1871 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
1872 "Warning: Malformed skin registration.");
1876 EnsureLowerCase(package
);
1878 TriState stAppVersion
= eUnspecified
;
1879 TriState stApp
= eUnspecified
;
1880 TriState stOs
= eUnspecified
;
1881 TriState stOsVersion
= eUnspecified
;
1883 PRBool badFlag
= PR_FALSE
;
1885 while (nsnull
!= (token
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
)) &&
1887 NS_ConvertASCIItoUTF16
wtoken(token
);
1888 ToLowerCase(wtoken
);
1890 if (CheckStringFlag(kApplication
, wtoken
, appID
, stApp
) ||
1891 CheckStringFlag(kOs
, wtoken
, osTarget
, stOs
) ||
1892 CheckVersionFlag(kOsVersion
, wtoken
, osVersion
, vc
, stOsVersion
) ||
1893 CheckVersionFlag(kAppVersion
, wtoken
, appVersion
, vc
, stAppVersion
))
1896 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
1897 "Warning: Unrecognized chrome registration modifier '%s'.",
1902 if (badFlag
|| stApp
== eBad
|| stAppVersion
== eBad
||
1903 stOs
== eBad
|| stOsVersion
== eBad
)
1906 nsCOMPtr
<nsIURI
> resolved
;
1907 rv
= io
->NewURI(nsDependentCString(uri
), nsnull
, manifestURI
,
1908 getter_AddRefs(resolved
));
1912 if (!CanLoadResource(resolved
)) {
1913 LogMessageWithContext(resolved
, line
, nsIScriptError::warningFlag
,
1914 "Warning: cannot register non-local URI '%s' as a skin.",
1919 PackageEntry
* entry
=
1920 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
1921 & (const nsACString
&) nsDependentCString(package
),
1924 return NS_ERROR_OUT_OF_MEMORY
;
1926 entry
->skins
.SetBase(nsDependentCString(provider
), resolved
);
1928 else if (!strcmp(token
, "overlay")) {
1930 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
1931 "Warning: Ignoring overlay registration in skin-only manifest.");
1934 char *base
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
1935 char *overlay
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
1936 if (!base
|| !overlay
) {
1937 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
1938 "Warning: malformed chrome overlay instruction.");
1942 TriState stAppVersion
= eUnspecified
;
1943 TriState stApp
= eUnspecified
;
1944 TriState stOs
= eUnspecified
;
1945 TriState stOsVersion
= eUnspecified
;
1947 PRBool badFlag
= PR_FALSE
;
1949 while (nsnull
!= (token
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
)) &&
1951 NS_ConvertASCIItoUTF16
wtoken(token
);
1952 ToLowerCase(wtoken
);
1954 if (CheckStringFlag(kApplication
, wtoken
, appID
, stApp
) ||
1955 CheckStringFlag(kOs
, wtoken
, osTarget
, stOs
) ||
1956 CheckVersionFlag(kOsVersion
, wtoken
, osVersion
, vc
, stOsVersion
) ||
1957 CheckVersionFlag(kAppVersion
, wtoken
, appVersion
, vc
, stAppVersion
))
1960 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
1961 "Warning: Unrecognized chrome registration modifier '%s'.",
1966 if (badFlag
|| stApp
== eBad
|| stAppVersion
== eBad
||
1967 stOs
== eBad
|| stOsVersion
== eBad
)
1970 nsCOMPtr
<nsIURI
> baseuri
, overlayuri
;
1971 rv
= io
->NewURI(nsDependentCString(base
), nsnull
, nsnull
,
1972 getter_AddRefs(baseuri
));
1973 rv
|= io
->NewURI(nsDependentCString(overlay
), nsnull
, nsnull
,
1974 getter_AddRefs(overlayuri
));
1975 if (NS_FAILED(rv
)) {
1976 NS_WARNING("Could not make URIs for overlay directive. Ignoring.");
1980 if (!CanLoadResource(overlayuri
)) {
1981 LogMessageWithContext(overlayuri
, line
, nsIScriptError::warningFlag
,
1982 "Warning: cannot register non-local URI '%s' as an overlay.",
1987 mOverlayHash
.Add(baseuri
, overlayuri
);
1989 else if (!strcmp(token
, "style")) {
1990 char *base
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
1991 char *overlay
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
1992 if (!base
|| !overlay
) {
1993 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
1994 "Warning: malformed chrome style instruction.");
1998 TriState stAppVersion
= eUnspecified
;
1999 TriState stApp
= eUnspecified
;
2000 TriState stOs
= eUnspecified
;
2001 TriState stOsVersion
= eUnspecified
;
2003 PRBool badFlag
= PR_FALSE
;
2005 while (nsnull
!= (token
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
)) &&
2007 NS_ConvertASCIItoUTF16
wtoken(token
);
2008 ToLowerCase(wtoken
);
2010 if (CheckStringFlag(kApplication
, wtoken
, appID
, stApp
) ||
2011 CheckStringFlag(kOs
, wtoken
, osTarget
, stOs
) ||
2012 CheckVersionFlag(kOsVersion
, wtoken
, osVersion
, vc
, stOsVersion
) ||
2013 CheckVersionFlag(kAppVersion
, wtoken
, appVersion
, vc
, stAppVersion
))
2016 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2017 "Warning: Unrecognized chrome registration modifier '%s'.",
2022 if (badFlag
|| stApp
== eBad
|| stAppVersion
== eBad
||
2023 stOs
== eBad
|| stOsVersion
== eBad
)
2026 nsCOMPtr
<nsIURI
> baseuri
, overlayuri
;
2027 rv
= io
->NewURI(nsDependentCString(base
), nsnull
, nsnull
,
2028 getter_AddRefs(baseuri
));
2029 rv
|= io
->NewURI(nsDependentCString(overlay
), nsnull
, nsnull
,
2030 getter_AddRefs(overlayuri
));
2034 if (!CanLoadResource(overlayuri
)) {
2035 LogMessageWithContext(overlayuri
, line
, nsIScriptError::warningFlag
,
2036 "Warning: cannot register non-local URI '%s' as a style overlay.",
2041 mStyleHash
.Add(baseuri
, overlayuri
);
2043 else if (!strcmp(token
, "override")) {
2045 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2046 "Warning: Ignoring override registration in skin-only manifest.");
2050 char *chrome
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2051 char *resolved
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2052 if (!chrome
|| !resolved
) {
2053 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2054 "Warning: malformed chrome override instruction.");
2058 TriState stAppVersion
= eUnspecified
;
2059 TriState stApp
= eUnspecified
;
2060 TriState stOs
= eUnspecified
;
2061 TriState stOsVersion
= eUnspecified
;
2063 PRBool badFlag
= PR_FALSE
;
2065 while (nsnull
!= (token
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
)) &&
2067 NS_ConvertASCIItoUTF16
wtoken(token
);
2068 ToLowerCase(wtoken
);
2070 if (CheckStringFlag(kApplication
, wtoken
, appID
, stApp
) ||
2071 CheckStringFlag(kOs
, wtoken
, osTarget
, stOs
) ||
2072 CheckVersionFlag(kOsVersion
, wtoken
, osVersion
, vc
, stOsVersion
) ||
2073 CheckVersionFlag(kAppVersion
, wtoken
, appVersion
, vc
, stAppVersion
))
2076 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2077 "Warning: Unrecognized chrome registration modifier '%s'.",
2082 if (badFlag
|| stApp
== eBad
|| stAppVersion
== eBad
||
2083 stOs
== eBad
|| stOsVersion
== eBad
)
2086 nsCOMPtr
<nsIURI
> chromeuri
, resolveduri
;
2087 rv
= io
->NewURI(nsDependentCString(chrome
), nsnull
, nsnull
,
2088 getter_AddRefs(chromeuri
));
2089 rv
|= io
->NewURI(nsDependentCString(resolved
), nsnull
, manifestURI
,
2090 getter_AddRefs(resolveduri
));
2094 if (!CanLoadResource(resolveduri
)) {
2095 LogMessageWithContext(resolveduri
, line
, nsIScriptError::warningFlag
,
2096 "Warning: cannot register non-local URI '%s' as an override.",
2101 mOverrideTable
.Put(chromeuri
, resolveduri
);
2103 else if (!strcmp(token
, "resource")) {
2105 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2106 "Warning: Ignoring resource registration in skin-only manifest.");
2110 char *package
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2111 char *uri
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
);
2112 if (!package
|| !uri
) {
2113 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2114 "Warning: Malformed resource registration.");
2118 EnsureLowerCase(package
);
2120 TriState stAppVersion
= eUnspecified
;
2121 TriState stApp
= eUnspecified
;
2122 TriState stOsVersion
= eUnspecified
;
2123 TriState stOs
= eUnspecified
;
2125 PRBool badFlag
= PR_FALSE
;
2127 while (nsnull
!= (token
= nsCRT::strtok(whitespace
, kWhitespace
, &whitespace
)) &&
2129 NS_ConvertASCIItoUTF16
wtoken(token
);
2130 ToLowerCase(wtoken
);
2132 if (CheckStringFlag(kApplication
, wtoken
, appID
, stApp
) ||
2133 CheckStringFlag(kOs
, wtoken
, osTarget
, stOs
) ||
2134 CheckVersionFlag(kOsVersion
, wtoken
, osVersion
, vc
, stOsVersion
) ||
2135 CheckVersionFlag(kAppVersion
, wtoken
, appVersion
, vc
, stAppVersion
))
2138 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2139 "Warning: Unrecognized chrome registration modifier '%s'.",
2144 if (badFlag
|| stApp
== eBad
|| stAppVersion
== eBad
||
2145 stOs
== eBad
|| stOsVersion
== eBad
)
2148 nsDependentCString
host(package
);
2151 rv
= rph
->HasSubstitution(host
, &exists
);
2152 NS_ENSURE_SUCCESS(rv
, rv
);
2154 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2155 "Warning: Duplicate resource declaration for '%s' ignored.",
2160 nsCOMPtr
<nsIURI
> resolved
;
2161 rv
= io
->NewURI(nsDependentCString(uri
), nsnull
, manifestURI
,
2162 getter_AddRefs(resolved
));
2166 if (!CanLoadResource(resolved
)) {
2167 LogMessageWithContext(resolved
, line
, nsIScriptError::warningFlag
,
2168 "Warning: cannot register non-local URI '%s' as a resource.",
2173 rv
= rph
->SetSubstitution(host
, resolved
);
2174 NS_ENSURE_SUCCESS(rv
, rv
);
2177 LogMessageWithContext(manifestURI
, line
, nsIScriptError::warningFlag
,
2178 "Warning: Ignoring unrecognized chrome manifest instruction.");