1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * the Mozilla Foundation.
19 * Portions created by the Initial Developer are Copyright (C) 2010
20 * the Initial Developer. All Rights Reserved.
23 * Josh Matthews <josh@joshmatthews.net> (Initial Developer)
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
40 #include "mozilla/dom/PContentParent.h"
41 #include "RegistryMessageUtils.h"
42 #include "nsResProtocolHandler.h"
45 #include "nsChromeRegistryChrome.h"
49 #elif defined(XP_MACOSX)
50 #include <CoreServices/CoreServices.h>
51 #elif defined(MOZ_WIDGET_GTK2)
55 #include "nsArrayEnumerator.h"
56 #include "nsAppDirectoryServiceDefs.h"
57 #include "nsComponentManager.h"
58 #include "nsEnumeratorUtils.h"
59 #include "nsNetUtil.h"
60 #include "nsStringEnumerator.h"
61 #include "nsTextFormatter.h"
62 #include "nsUnicharUtils.h"
63 #include "nsWidgetsCID.h"
64 #include "nsXPCOMCIDInternal.h"
65 #include "nsZipArchive.h"
67 #include "nsICommandLine.h"
68 #include "nsILocaleService.h"
69 #include "nsILocalFile.h"
70 #include "nsILookAndFeel.h"
71 #include "nsIObserverService.h"
72 #include "nsIPrefBranch2.h"
73 #include "nsIPrefService.h"
74 #include "nsIResProtocolHandler.h"
75 #include "nsIScriptError.h"
76 #include "nsIVersionComparator.h"
77 #include "nsIXPConnect.h"
78 #include "nsIXULAppInfo.h"
79 #include "nsIXULRuntime.h"
81 #define UILOCALE_CMD_LINE_ARG "UILocale"
83 #define MATCH_OS_LOCALE_PREF "intl.locale.matchOS"
84 #define SELECTED_LOCALE_PREF "general.useragent.locale"
85 #define SELECTED_SKIN_PREF "general.skins.selectedSkin"
87 static NS_DEFINE_CID(kLookAndFeelCID
, NS_LOOKANDFEEL_CID
);
89 static PLDHashOperator
90 RemoveAll(PLDHashTable
*table
, PLDHashEntryHdr
*entry
, PRUint32 number
, void *arg
)
92 return (PLDHashOperator
) (PL_DHASH_NEXT
| PL_DHASH_REMOVE
);
95 // We use a "best-fit" algorithm for matching locales and themes.
96 // 1) the exact selected locale/theme
97 // 2) (locales only) same language, different country
98 // e.g. en-GB is the selected locale, only en-US is available
99 // 3) any available locale/theme
102 * Match the language-part of two lang-COUNTRY codes, hopefully but
103 * not guaranteed to be in the form ab-CD or abz-CD. "ab" should also
104 * work, any other garbage-in will produce undefined results as long
105 * as it does not crash.
108 LanguagesMatch(const nsACString
& a
, const nsACString
& b
)
110 if (a
.Length() < 2 || b
.Length() < 2)
113 nsACString::const_iterator as
, ae
, bs
, be
;
126 if (as
== ae
&& bs
== be
)
141 nsChromeRegistryChrome::nsChromeRegistryChrome()
142 : mProfileLoaded(PR_FALSE
)
144 mPackagesHash
.ops
= nsnull
;
147 nsChromeRegistryChrome::~nsChromeRegistryChrome()
149 if (mPackagesHash
.ops
)
150 PL_DHashTableFinish(&mPackagesHash
);
154 nsChromeRegistryChrome::Init()
156 nsresult rv
= nsChromeRegistry::Init();
160 if (!mOverlayHash
.Init() ||
162 return NS_ERROR_FAILURE
;
164 mSelectedLocale
= NS_LITERAL_CSTRING("en-US");
165 mSelectedSkin
= NS_LITERAL_CSTRING("classic/1.0");
167 if (!PL_DHashTableInit(&mPackagesHash
, &kTableOps
,
168 nsnull
, sizeof(PackageEntry
), 16))
169 return NS_ERROR_FAILURE
;
171 PRBool safeMode
= PR_FALSE
;
172 nsCOMPtr
<nsIXULRuntime
> xulrun (do_GetService(XULAPPINFO_SERVICE_CONTRACTID
));
174 xulrun
->GetInSafeMode(&safeMode
);
176 nsCOMPtr
<nsIPrefService
> prefserv (do_GetService(NS_PREFSERVICE_CONTRACTID
));
177 nsCOMPtr
<nsIPrefBranch
> prefs
;
180 prefserv
->GetDefaultBranch(nsnull
, getter_AddRefs(prefs
));
182 prefs
= do_QueryInterface(prefserv
);
185 NS_WARNING("Could not get pref service!");
188 nsXPIDLCString provider
;
189 rv
= prefs
->GetCharPref(SELECTED_SKIN_PREF
, getter_Copies(provider
));
190 if (NS_SUCCEEDED(rv
))
191 mSelectedSkin
= provider
;
193 SelectLocaleFromPref(prefs
);
195 nsCOMPtr
<nsIPrefBranch2
> prefs2 (do_QueryInterface(prefs
));
197 rv
= prefs2
->AddObserver(MATCH_OS_LOCALE_PREF
, this, PR_TRUE
);
198 rv
= prefs2
->AddObserver(SELECTED_LOCALE_PREF
, this, PR_TRUE
);
199 rv
= prefs2
->AddObserver(SELECTED_SKIN_PREF
, this, PR_TRUE
);
203 nsCOMPtr
<nsIObserverService
> obsService
= mozilla::services::GetObserverService();
205 obsService
->AddObserver(this, "command-line-startup", PR_TRUE
);
206 obsService
->AddObserver(this, "profile-initial-state", PR_TRUE
);
213 nsChromeRegistryChrome::CheckForOSAccessibility()
217 nsCOMPtr
<nsILookAndFeel
> lookAndFeel (do_GetService(kLookAndFeelCID
));
219 PRInt32 useAccessibilityTheme
= 0;
221 rv
= lookAndFeel
->GetMetric(nsILookAndFeel::eMetric_UseAccessibilityTheme
,
222 useAccessibilityTheme
);
224 if (NS_SUCCEEDED(rv
) && useAccessibilityTheme
) {
225 /* Set the skin to classic and remove pref observers */
226 if (!mSelectedSkin
.EqualsLiteral("classic/1.0")) {
227 mSelectedSkin
.AssignLiteral("classic/1.0");
231 nsCOMPtr
<nsIPrefBranch2
> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID
));
233 prefs
->RemoveObserver(SELECTED_SKIN_PREF
, this);
242 nsChromeRegistryChrome::GetLocalesForPackage(const nsACString
& aPackage
,
243 nsIUTF8StringEnumerator
* *aResult
)
245 nsTArray
<nsCString
> *a
= new nsTArray
<nsCString
>;
247 return NS_ERROR_OUT_OF_MEMORY
;
249 PackageEntry
* entry
=
250 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
254 if (PL_DHASH_ENTRY_IS_BUSY(entry
)) {
255 entry
->locales
.EnumerateToArray(a
);
258 nsresult rv
= NS_NewAdoptingUTF8StringEnumerator(aResult
, a
);
266 getUILangCountry(nsACString
& aUILang
)
270 nsCOMPtr
<nsILocaleService
> localeService
= do_GetService(NS_LOCALESERVICE_CONTRACTID
, &rv
);
271 NS_ENSURE_SUCCESS(rv
, rv
);
274 rv
= localeService
->GetLocaleComponentForUserAgent(uiLang
);
275 NS_ENSURE_SUCCESS(rv
, rv
);
277 CopyUTF16toUTF8(uiLang
, aUILang
);
282 nsChromeRegistryChrome::IsLocaleRTL(const nsACString
& package
, PRBool
*aResult
)
286 nsCAutoString locale
;
287 GetSelectedLocale(package
, locale
);
288 if (locale
.Length() < 2)
291 // first check the intl.uidirection.<locale> preference, and if that is not
292 // set, check the same preference but with just the first two characters of
293 // the locale. If that isn't set, default to left-to-right.
294 nsCAutoString prefString
= NS_LITERAL_CSTRING("intl.uidirection.") + locale
;
295 nsCOMPtr
<nsIPrefBranch
> prefBranch (do_GetService(NS_PREFSERVICE_CONTRACTID
));
300 prefBranch
->GetCharPref(prefString
.get(), getter_Copies(dir
));
302 PRInt32 hyphen
= prefString
.FindChar('-');
304 nsCAutoString
shortPref(Substring(prefString
, 0, hyphen
));
305 prefBranch
->GetCharPref(shortPref
.get(), getter_Copies(dir
));
308 *aResult
= dir
.EqualsLiteral("rtl");
313 nsChromeRegistryChrome::GetSelectedLocale(const nsACString
& aPackage
,
316 PackageEntry
* entry
=
317 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
321 if (PL_DHASH_ENTRY_IS_FREE(entry
))
322 return NS_ERROR_FAILURE
;
324 aLocale
= entry
->locales
.GetSelected(mSelectedLocale
, nsProviderArray::LOCALE
);
325 if (aLocale
.IsEmpty())
326 return NS_ERROR_FAILURE
;
332 nsChromeRegistryChrome::SelectLocaleFromPref(nsIPrefBranch
* prefs
)
335 PRBool matchOSLocale
= PR_FALSE
;
336 rv
= prefs
->GetBoolPref(MATCH_OS_LOCALE_PREF
, &matchOSLocale
);
338 if (NS_SUCCEEDED(rv
) && matchOSLocale
) {
339 // compute lang and region code only when needed!
340 nsCAutoString uiLocale
;
341 rv
= getUILangCountry(uiLocale
);
342 if (NS_SUCCEEDED(rv
))
343 mSelectedLocale
= uiLocale
;
346 nsXPIDLCString provider
;
347 rv
= prefs
->GetCharPref(SELECTED_LOCALE_PREF
, getter_Copies(provider
));
348 if (NS_SUCCEEDED(rv
)) {
349 mSelectedLocale
= provider
;
354 NS_ERROR("Couldn't select locale from pref!");
360 nsChromeRegistryChrome::Observe(nsISupports
*aSubject
, const char *aTopic
,
361 const PRUnichar
*someData
)
365 if (!strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID
, aTopic
)) {
366 nsCOMPtr
<nsIPrefBranch
> prefs (do_QueryInterface(aSubject
));
367 NS_ASSERTION(prefs
, "Bad observer call!");
369 NS_ConvertUTF16toUTF8
pref(someData
);
371 if (pref
.EqualsLiteral(MATCH_OS_LOCALE_PREF
) ||
372 pref
.EqualsLiteral(SELECTED_LOCALE_PREF
)) {
373 if (!mProfileLoaded
) {
374 rv
= SelectLocaleFromPref(prefs
);
380 else if (pref
.EqualsLiteral(SELECTED_SKIN_PREF
)) {
381 nsXPIDLCString provider
;
382 rv
= prefs
->GetCharPref(pref
.get(), getter_Copies(provider
));
384 NS_ERROR("Couldn't get new skin pref!");
388 mSelectedSkin
= provider
;
391 NS_ERROR("Unexpected pref!");
394 else if (!strcmp("command-line-startup", aTopic
)) {
395 nsCOMPtr
<nsICommandLine
> cmdLine (do_QueryInterface(aSubject
));
397 nsAutoString uiLocale
;
398 rv
= cmdLine
->HandleFlagWithParam(NS_LITERAL_STRING(UILOCALE_CMD_LINE_ARG
),
400 if (NS_SUCCEEDED(rv
) && !uiLocale
.IsEmpty()) {
401 CopyUTF16toUTF8(uiLocale
, mSelectedLocale
);
402 nsCOMPtr
<nsIPrefBranch2
> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID
));
404 prefs
->RemoveObserver(SELECTED_LOCALE_PREF
, this);
409 else if (!strcmp("profile-initial-state", aTopic
)) {
410 mProfileLoaded
= PR_TRUE
;
413 NS_ERROR("Unexpected observer topic!");
420 nsChromeRegistryChrome::CheckForNewChrome()
422 PL_DHashTableEnumerate(&mPackagesHash
, RemoveAll
, nsnull
);
423 mOverlayHash
.Clear();
425 mOverrideTable
.Clear();
427 nsComponentManagerImpl::gComponentManager
->RereadChromeManifests();
431 void nsChromeRegistryChrome::UpdateSelectedLocale()
433 nsCOMPtr
<nsIPrefBranch
> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID
));
435 nsresult rv
= SelectLocaleFromPref(prefs
);
436 if (NS_SUCCEEDED(rv
)) {
437 nsCOMPtr
<nsIObserverService
> obsSvc
=
438 mozilla::services::GetObserverService();
439 NS_ASSERTION(obsSvc
, "Couldn't get observer service.");
440 obsSvc
->NotifyObservers((nsIChromeRegistry
*) this,
441 "selected-locale-has-changed", nsnull
);
448 SerializeURI(nsIURI
* aURI
,
449 SerializedURI
& aSerializedURI
)
454 aURI
->GetSpec(aSerializedURI
.spec
);
455 aURI
->GetOriginCharset(aSerializedURI
.charset
);
458 static PLDHashOperator
459 EnumerateOverride(nsIURI
* aURIKey
,
463 nsTArray
<OverrideMapping
>* overrides
=
464 static_cast<nsTArray
<OverrideMapping
>*>(aArg
);
466 SerializedURI chromeURI
, overrideURI
;
468 SerializeURI(aURIKey
, chromeURI
);
469 SerializeURI(aURI
, overrideURI
);
471 OverrideMapping override
= {
472 chromeURI
, overrideURI
474 overrides
->AppendElement(override
);
475 return (PLDHashOperator
)PL_DHASH_NEXT
;
478 struct EnumerationArgs
480 InfallibleTArray
<ChromePackage
>& packages
;
481 const nsCString
& selectedLocale
;
482 const nsCString
& selectedSkin
;
486 nsChromeRegistryChrome::SendRegisteredChrome(
487 mozilla::dom::PContentParent
* aParent
)
489 InfallibleTArray
<ChromePackage
> packages
;
490 InfallibleTArray
<ResourceMapping
> resources
;
491 InfallibleTArray
<OverrideMapping
> overrides
;
493 EnumerationArgs args
= {
494 packages
, mSelectedLocale
, mSelectedSkin
496 PL_DHashTableEnumerate(&mPackagesHash
, CollectPackages
, &args
);
498 nsCOMPtr
<nsIIOService
> io (do_GetIOService());
499 NS_ENSURE_TRUE(io
, );
501 nsCOMPtr
<nsIProtocolHandler
> ph
;
502 nsresult rv
= io
->GetProtocolHandler("resource", getter_AddRefs(ph
));
503 NS_ENSURE_SUCCESS(rv
, );
505 //FIXME: Some substitutions are set up lazily and might not exist yet
506 nsCOMPtr
<nsIResProtocolHandler
> irph (do_QueryInterface(ph
));
507 nsResProtocolHandler
* rph
= static_cast<nsResProtocolHandler
*>(irph
.get());
508 rph
->CollectSubstitutions(resources
);
510 mOverrideTable
.EnumerateRead(&EnumerateOverride
, &overrides
);
512 bool success
= aParent
->SendRegisterChrome(packages
, resources
, overrides
,
514 NS_ENSURE_TRUE(success
, );
518 nsChromeRegistryChrome::CollectPackages(PLDHashTable
*table
,
519 PLDHashEntryHdr
*entry
,
523 EnumerationArgs
* args
= static_cast<EnumerationArgs
*>(arg
);
524 PackageEntry
* package
= static_cast<PackageEntry
*>(entry
);
526 SerializedURI contentURI
, localeURI
, skinURI
;
528 SerializeURI(package
->baseURI
, contentURI
);
529 SerializeURI(package
->locales
.GetBase(args
->selectedLocale
,
530 nsProviderArray::LOCALE
), localeURI
);
531 SerializeURI(package
->skins
.GetBase(args
->selectedSkin
, nsProviderArray::ANY
),
534 ChromePackage chromePackage
= {
541 args
->packages
.AppendElement(chromePackage
);
542 return (PLDHashOperator
)PL_DHASH_NEXT
;
547 CanLoadResource(nsIURI
* aResourceURI
)
549 PRBool isLocalResource
= PR_FALSE
;
550 (void)NS_URIChainHasFlags(aResourceURI
,
551 nsIProtocolHandler::URI_IS_LOCAL_RESOURCE
,
553 return isLocalResource
;
557 nsChromeRegistryChrome::GetBaseURIFromPackage(const nsCString
& aPackage
,
558 const nsCString
& aProvider
,
559 const nsCString
& aPath
)
561 PackageEntry
* entry
=
562 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
566 if (PL_DHASH_ENTRY_IS_FREE(entry
)) {
570 LogMessage("No chrome package registered for chrome://%s/%s/%s",
571 aPackage
.get(), aProvider
.get(), aPath
.get());
576 if (aProvider
.EqualsLiteral("locale")) {
577 return entry
->locales
.GetBase(mSelectedLocale
, nsProviderArray::LOCALE
);
579 else if (aProvider
.EqualsLiteral("skin")) {
580 return entry
->skins
.GetBase(mSelectedSkin
, nsProviderArray::ANY
);
582 else if (aProvider
.EqualsLiteral("content")) {
583 return entry
->baseURI
;
589 nsChromeRegistryChrome::GetFlagsFromPackage(const nsCString
& aPackage
,
592 PackageEntry
* entry
=
593 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
594 & (nsACString
&) aPackage
,
596 if (PL_DHASH_ENTRY_IS_FREE(entry
))
597 return NS_ERROR_NOT_AVAILABLE
;
599 *aFlags
= entry
->flags
;
604 nsChromeRegistryChrome::HashKey(PLDHashTable
*table
, const void *key
)
606 const nsACString
& str
= *reinterpret_cast<const nsACString
*>(key
);
607 return HashString(str
);
611 nsChromeRegistryChrome::MatchKey(PLDHashTable
*table
, const PLDHashEntryHdr
*entry
,
614 const nsACString
& str
= *reinterpret_cast<const nsACString
*>(key
);
615 const PackageEntry
* pentry
= static_cast<const PackageEntry
*>(entry
);
616 return str
.Equals(pentry
->package
);
620 nsChromeRegistryChrome::ClearEntry(PLDHashTable
*table
, PLDHashEntryHdr
*entry
)
622 PackageEntry
* pentry
= static_cast<PackageEntry
*>(entry
);
623 pentry
->~PackageEntry();
627 nsChromeRegistryChrome::InitEntry(PLDHashTable
*table
, PLDHashEntryHdr
*entry
,
630 const nsACString
& str
= *reinterpret_cast<const nsACString
*>(key
);
632 new (entry
) PackageEntry(str
);
636 const PLDHashTableOps
637 nsChromeRegistryChrome::kTableOps
= {
642 PL_DHashMoveEntryStub
,
644 PL_DHashFinalizeStub
,
648 nsChromeRegistryChrome::ProviderEntry
*
649 nsChromeRegistryChrome::nsProviderArray::GetProvider(const nsACString
& aPreferred
, MatchType aType
)
651 PRInt32 i
= mArray
.Count();
655 ProviderEntry
* found
= nsnull
; // Only set if we find a partial-match locale
656 ProviderEntry
* entry
;
659 entry
= reinterpret_cast<ProviderEntry
*>(mArray
[i
]);
660 if (aPreferred
.Equals(entry
->provider
))
666 if (LanguagesMatch(aPreferred
, entry
->provider
)) {
671 if (!found
&& entry
->provider
.EqualsLiteral("en-US"))
675 if (!found
&& aType
!= EXACT
)
682 nsChromeRegistryChrome::nsProviderArray::GetBase(const nsACString
& aPreferred
, MatchType aType
)
684 ProviderEntry
* provider
= GetProvider(aPreferred
, aType
);
689 return provider
->baseURI
;
693 nsChromeRegistryChrome::nsProviderArray::GetSelected(const nsACString
& aPreferred
, MatchType aType
)
695 ProviderEntry
* entry
= GetProvider(aPreferred
, aType
);
698 return entry
->provider
;
700 return EmptyCString();
704 nsChromeRegistryChrome::nsProviderArray::SetBase(const nsACString
& aProvider
, nsIURI
* aBaseURL
)
706 ProviderEntry
* provider
= GetProvider(aProvider
, EXACT
);
709 provider
->baseURI
= aBaseURL
;
713 // no existing entries, add a new one
714 provider
= new ProviderEntry(aProvider
, aBaseURL
);
716 return; // It's safe to silently fail on OOM
718 mArray
.AppendElement(provider
);
722 nsChromeRegistryChrome::nsProviderArray::EnumerateToArray(nsTArray
<nsCString
> *a
)
724 PRInt32 i
= mArray
.Count();
726 ProviderEntry
*entry
= reinterpret_cast<ProviderEntry
*>(mArray
[i
]);
727 a
->AppendElement(entry
->provider
);
732 nsChromeRegistryChrome::nsProviderArray::Clear()
734 PRInt32 i
= mArray
.Count();
736 ProviderEntry
* entry
= reinterpret_cast<ProviderEntry
*>(mArray
[i
]);
744 nsChromeRegistryChrome::OverlayListEntry::AddURI(nsIURI
* aURI
)
746 PRInt32 i
= mArray
.Count();
749 if (NS_SUCCEEDED(aURI
->Equals(mArray
[i
], &equals
)) && equals
)
753 mArray
.AppendObject(aURI
);
757 nsChromeRegistryChrome::OverlayListHash::Add(nsIURI
* aBase
, nsIURI
* aOverlay
)
759 OverlayListEntry
* entry
= mTable
.PutEntry(aBase
);
761 entry
->AddURI(aOverlay
);
764 const nsCOMArray
<nsIURI
>*
765 nsChromeRegistryChrome::OverlayListHash::GetArray(nsIURI
* aBase
)
767 OverlayListEntry
* entry
= mTable
.GetEntry(aBase
);
771 return &entry
->mArray
;
776 nsChromeRegistryChrome::GetStyleOverlays(nsIURI
*aChromeURL
,
777 nsISimpleEnumerator
**aResult
)
779 const nsCOMArray
<nsIURI
>* parray
= mStyleHash
.GetArray(aChromeURL
);
781 return NS_NewEmptyEnumerator(aResult
);
783 return NS_NewArrayEnumerator(aResult
, *parray
);
787 nsChromeRegistryChrome::GetXULOverlays(nsIURI
*aChromeURL
,
788 nsISimpleEnumerator
**aResult
)
790 const nsCOMArray
<nsIURI
>* parray
= mOverlayHash
.GetArray(aChromeURL
);
792 return NS_NewEmptyEnumerator(aResult
);
794 return NS_NewArrayEnumerator(aResult
, *parray
);
799 nsChromeRegistry::ManifestProcessingContext::GetManifestURI()
802 nsCOMPtr
<nsIIOService
> io
= mozilla::services::GetIOService();
804 NS_WARNING("No IO service trying to process chrome manifests");
809 nsCOMPtr
<nsIURI
> fileURI
;
810 io
->NewFileURI(mFile
, getter_AddRefs(fileURI
));
813 fileURI
->GetSpec(spec
);
814 spec
.Insert(NS_LITERAL_CSTRING("jar:"), 0);
815 spec
.AppendLiteral("!/");
818 NS_NewURI(getter_AddRefs(mManifestURI
), spec
, NULL
, NULL
, io
);
821 io
->NewFileURI(mFile
, getter_AddRefs(mManifestURI
));
828 nsChromeRegistry::ManifestProcessingContext::GetXPConnect()
831 mXPConnect
= do_GetService("@mozilla.org/js/xpc/XPConnect;1");
836 already_AddRefed
<nsIURI
>
837 nsChromeRegistry::ManifestProcessingContext::ResolveURI(const char* uri
)
839 nsIURI
* baseuri
= GetManifestURI();
843 nsCOMPtr
<nsIURI
> resolved
;
844 nsresult rv
= NS_NewURI(getter_AddRefs(resolved
), uri
, baseuri
);
848 return resolved
.forget();
852 EnsureLowerCase(char *aBuf
)
854 for (; *aBuf
; ++aBuf
) {
856 if (ch
>= 'A' && ch
<= 'Z')
857 *aBuf
= ch
+ 'a' - 'A';
862 nsChromeRegistryChrome::ManifestContent(ManifestProcessingContext
& cx
, int lineno
,
863 char *const * argv
, bool platform
,
864 bool contentaccessible
)
866 char* package
= argv
[0];
869 EnsureLowerCase(package
);
871 nsCOMPtr
<nsIURI
> resolved
= cx
.ResolveURI(uri
);
873 LogMessageWithContext(cx
.GetManifestURI(), lineno
, nsIScriptError::warningFlag
,
874 "During chrome registration, unable to create URI '%s'.", uri
);
878 if (!CanLoadResource(resolved
)) {
879 LogMessageWithContext(resolved
, lineno
, nsIScriptError::warningFlag
,
880 "During chrome registration, cannot register non-local URI '%s' as content.",
885 PackageEntry
* entry
=
886 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
887 & (const nsACString
&) nsDependentCString(package
),
892 entry
->baseURI
= resolved
;
895 entry
->flags
|= PLATFORM_PACKAGE
;
896 if (contentaccessible
)
897 entry
->flags
|= CONTENT_ACCESSIBLE
;
898 if (cx
.GetXPConnect()) {
899 nsCAutoString
urlp("chrome://");
900 urlp
.Append(package
);
903 cx
.GetXPConnect()->FlagSystemFilenamePrefix(urlp
.get(), true);
908 nsChromeRegistryChrome::ManifestLocale(ManifestProcessingContext
& cx
, int lineno
,
909 char *const * argv
, bool platform
,
910 bool contentaccessible
)
912 char* package
= argv
[0];
913 char* provider
= argv
[1];
916 EnsureLowerCase(package
);
918 nsCOMPtr
<nsIURI
> resolved
= cx
.ResolveURI(uri
);
920 LogMessageWithContext(cx
.GetManifestURI(), lineno
, nsIScriptError::warningFlag
,
921 "During chrome registration, unable to create URI '%s'.", uri
);
925 if (!CanLoadResource(resolved
)) {
926 LogMessageWithContext(resolved
, lineno
, nsIScriptError::warningFlag
,
927 "During chrome registration, cannot register non-local URI '%s' as content.",
932 PackageEntry
* entry
=
933 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
934 & (const nsACString
&) nsDependentCString(package
),
939 entry
->locales
.SetBase(nsDependentCString(provider
), resolved
);
943 nsChromeRegistryChrome::ManifestSkin(ManifestProcessingContext
& cx
, int lineno
,
944 char *const * argv
, bool platform
,
945 bool contentaccessible
)
947 char* package
= argv
[0];
948 char* provider
= argv
[1];
951 EnsureLowerCase(package
);
953 nsCOMPtr
<nsIURI
> resolved
= cx
.ResolveURI(uri
);
955 LogMessageWithContext(cx
.GetManifestURI(), lineno
, nsIScriptError::warningFlag
,
956 "During chrome registration, unable to create URI '%s'.", uri
);
960 if (!CanLoadResource(resolved
)) {
961 LogMessageWithContext(resolved
, lineno
, nsIScriptError::warningFlag
,
962 "During chrome registration, cannot register non-local URI '%s' as content.",
967 PackageEntry
* entry
=
968 static_cast<PackageEntry
*>(PL_DHashTableOperate(&mPackagesHash
,
969 & (const nsACString
&) nsDependentCString(package
),
974 entry
->skins
.SetBase(nsDependentCString(provider
), resolved
);
978 nsChromeRegistryChrome::ManifestOverlay(ManifestProcessingContext
& cx
, int lineno
,
979 char *const * argv
, bool platform
,
980 bool contentaccessible
)
982 char* base
= argv
[0];
983 char* overlay
= argv
[1];
985 nsCOMPtr
<nsIURI
> baseuri
= cx
.ResolveURI(base
);
986 nsCOMPtr
<nsIURI
> overlayuri
= cx
.ResolveURI(overlay
);
987 if (!baseuri
|| !overlayuri
) {
988 LogMessageWithContext(cx
.GetManifestURI(), lineno
, nsIScriptError::warningFlag
,
989 "During chrome registration, unable to create URI.");
993 if (!CanLoadResource(overlayuri
)) {
994 LogMessageWithContext(cx
.GetManifestURI(), lineno
, nsIScriptError::warningFlag
,
995 "Cannot register non-local URI '%s' as an overlay.", overlay
);
999 mOverlayHash
.Add(baseuri
, overlayuri
);
1003 nsChromeRegistryChrome::ManifestStyle(ManifestProcessingContext
& cx
, int lineno
,
1004 char *const * argv
, bool platform
,
1005 bool contentaccessible
)
1007 char* base
= argv
[0];
1008 char* overlay
= argv
[1];
1010 nsCOMPtr
<nsIURI
> baseuri
= cx
.ResolveURI(base
);
1011 nsCOMPtr
<nsIURI
> overlayuri
= cx
.ResolveURI(overlay
);
1012 if (!baseuri
|| !overlayuri
) {
1013 LogMessageWithContext(cx
.GetManifestURI(), lineno
, nsIScriptError::warningFlag
,
1014 "During chrome registration, unable to create URI.");
1018 if (!CanLoadResource(overlayuri
)) {
1019 LogMessageWithContext(cx
.GetManifestURI(), lineno
, nsIScriptError::warningFlag
,
1020 "Cannot register non-local URI '%s' as a style overlay.", overlay
);
1024 mStyleHash
.Add(baseuri
, overlayuri
);
1028 nsChromeRegistryChrome::ManifestOverride(ManifestProcessingContext
& cx
, int lineno
,
1029 char *const * argv
, bool platform
,
1030 bool contentaccessible
)
1032 char* chrome
= argv
[0];
1033 char* resolved
= argv
[1];
1035 nsCOMPtr
<nsIURI
> chromeuri
= cx
.ResolveURI(chrome
);
1036 nsCOMPtr
<nsIURI
> resolveduri
= cx
.ResolveURI(resolved
);
1037 if (!chromeuri
|| !resolveduri
) {
1038 LogMessageWithContext(cx
.GetManifestURI(), lineno
, nsIScriptError::warningFlag
,
1039 "During chrome registration, unable to create URI.");
1043 if (!CanLoadResource(resolveduri
)) {
1044 LogMessageWithContext(cx
.GetManifestURI(), lineno
, nsIScriptError::warningFlag
,
1045 "Cannot register non-local URI '%s' for an override.", resolved
);
1048 mOverrideTable
.Put(chromeuri
, resolveduri
);
1052 nsChromeRegistryChrome::ManifestResource(ManifestProcessingContext
& cx
, int lineno
,
1053 char *const * argv
, bool platform
,
1054 bool contentaccessible
)
1056 char* package
= argv
[0];
1057 char* uri
= argv
[1];
1059 EnsureLowerCase(package
);
1060 nsDependentCString
host(package
);
1062 nsCOMPtr
<nsIIOService
> io
= mozilla::services::GetIOService();
1064 NS_WARNING("No IO service trying to process chrome manifests");
1068 nsCOMPtr
<nsIProtocolHandler
> ph
;
1069 nsresult rv
= io
->GetProtocolHandler("resource", getter_AddRefs(ph
));
1073 nsCOMPtr
<nsIResProtocolHandler
> rph
= do_QueryInterface(ph
);
1075 PRBool exists
= PR_FALSE
;
1076 rv
= rph
->HasSubstitution(host
, &exists
);
1078 LogMessageWithContext(cx
.GetManifestURI(), lineno
, nsIScriptError::warningFlag
,
1079 "Duplicate resource declaration for '%s' ignored.", package
);
1083 nsCOMPtr
<nsIURI
> resolved
= cx
.ResolveURI(uri
);
1085 LogMessageWithContext(cx
.GetManifestURI(), lineno
, nsIScriptError::warningFlag
,
1086 "During chrome registration, unable to create URI '%s'.", uri
);
1090 if (!CanLoadResource(resolved
)) {
1091 LogMessageWithContext(cx
.GetManifestURI(), lineno
, nsIScriptError::warningFlag
,
1092 "Warning: cannot register non-local URI '%s' as a resource.",
1097 rph
->SetSubstitution(host
, resolved
);