Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | #include "mozilla/dom/PContentParent.h" |
michael@0 | 7 | #include "RegistryMessageUtils.h" |
michael@0 | 8 | #include "nsResProtocolHandler.h" |
michael@0 | 9 | |
michael@0 | 10 | #include "nsChromeRegistryChrome.h" |
michael@0 | 11 | |
michael@0 | 12 | #if defined(XP_WIN) |
michael@0 | 13 | #include <windows.h> |
michael@0 | 14 | #elif defined(XP_MACOSX) |
michael@0 | 15 | #include <CoreServices/CoreServices.h> |
michael@0 | 16 | #endif |
michael@0 | 17 | |
michael@0 | 18 | #include "nsArrayEnumerator.h" |
michael@0 | 19 | #include "nsComponentManager.h" |
michael@0 | 20 | #include "nsEnumeratorUtils.h" |
michael@0 | 21 | #include "nsNetUtil.h" |
michael@0 | 22 | #include "nsStringEnumerator.h" |
michael@0 | 23 | #include "nsTextFormatter.h" |
michael@0 | 24 | #include "nsXPCOMCIDInternal.h" |
michael@0 | 25 | |
michael@0 | 26 | #include "mozilla/LookAndFeel.h" |
michael@0 | 27 | |
michael@0 | 28 | #include "nsICommandLine.h" |
michael@0 | 29 | #include "nsILocaleService.h" |
michael@0 | 30 | #include "nsIObserverService.h" |
michael@0 | 31 | #include "nsIPrefBranch.h" |
michael@0 | 32 | #include "nsIPrefService.h" |
michael@0 | 33 | #include "mozilla/Preferences.h" |
michael@0 | 34 | #include "nsIResProtocolHandler.h" |
michael@0 | 35 | #include "nsIScriptError.h" |
michael@0 | 36 | #include "nsIXPConnect.h" |
michael@0 | 37 | #include "nsIXULRuntime.h" |
michael@0 | 38 | |
michael@0 | 39 | #define UILOCALE_CMD_LINE_ARG "UILocale" |
michael@0 | 40 | |
michael@0 | 41 | #define MATCH_OS_LOCALE_PREF "intl.locale.matchOS" |
michael@0 | 42 | #define SELECTED_LOCALE_PREF "general.useragent.locale" |
michael@0 | 43 | #define SELECTED_SKIN_PREF "general.skins.selectedSkin" |
michael@0 | 44 | #define PACKAGE_OVERRIDE_BRANCH "chrome.override_package." |
michael@0 | 45 | |
michael@0 | 46 | using namespace mozilla; |
michael@0 | 47 | |
michael@0 | 48 | static PLDHashOperator |
michael@0 | 49 | RemoveAll(PLDHashTable *table, PLDHashEntryHdr *entry, uint32_t number, void *arg) |
michael@0 | 50 | { |
michael@0 | 51 | return (PLDHashOperator) (PL_DHASH_NEXT | PL_DHASH_REMOVE); |
michael@0 | 52 | } |
michael@0 | 53 | |
michael@0 | 54 | // We use a "best-fit" algorithm for matching locales and themes. |
michael@0 | 55 | // 1) the exact selected locale/theme |
michael@0 | 56 | // 2) (locales only) same language, different country |
michael@0 | 57 | // e.g. en-GB is the selected locale, only en-US is available |
michael@0 | 58 | // 3) any available locale/theme |
michael@0 | 59 | |
michael@0 | 60 | /** |
michael@0 | 61 | * Match the language-part of two lang-COUNTRY codes, hopefully but |
michael@0 | 62 | * not guaranteed to be in the form ab-CD or abz-CD. "ab" should also |
michael@0 | 63 | * work, any other garbage-in will produce undefined results as long |
michael@0 | 64 | * as it does not crash. |
michael@0 | 65 | */ |
michael@0 | 66 | static bool |
michael@0 | 67 | LanguagesMatch(const nsACString& a, const nsACString& b) |
michael@0 | 68 | { |
michael@0 | 69 | if (a.Length() < 2 || b.Length() < 2) |
michael@0 | 70 | return false; |
michael@0 | 71 | |
michael@0 | 72 | nsACString::const_iterator as, ae, bs, be; |
michael@0 | 73 | a.BeginReading(as); |
michael@0 | 74 | a.EndReading(ae); |
michael@0 | 75 | b.BeginReading(bs); |
michael@0 | 76 | b.EndReading(be); |
michael@0 | 77 | |
michael@0 | 78 | while (*as == *bs) { |
michael@0 | 79 | if (*as == '-') |
michael@0 | 80 | return true; |
michael@0 | 81 | |
michael@0 | 82 | ++as; ++bs; |
michael@0 | 83 | |
michael@0 | 84 | // reached the end |
michael@0 | 85 | if (as == ae && bs == be) |
michael@0 | 86 | return true; |
michael@0 | 87 | |
michael@0 | 88 | // "a" is short |
michael@0 | 89 | if (as == ae) |
michael@0 | 90 | return (*bs == '-'); |
michael@0 | 91 | |
michael@0 | 92 | // "b" is short |
michael@0 | 93 | if (bs == be) |
michael@0 | 94 | return (*as == '-'); |
michael@0 | 95 | } |
michael@0 | 96 | |
michael@0 | 97 | return false; |
michael@0 | 98 | } |
michael@0 | 99 | |
michael@0 | 100 | nsChromeRegistryChrome::nsChromeRegistryChrome() |
michael@0 | 101 | : mProfileLoaded(false) |
michael@0 | 102 | { |
michael@0 | 103 | mPackagesHash.ops = nullptr; |
michael@0 | 104 | } |
michael@0 | 105 | |
michael@0 | 106 | nsChromeRegistryChrome::~nsChromeRegistryChrome() |
michael@0 | 107 | { |
michael@0 | 108 | if (mPackagesHash.ops) |
michael@0 | 109 | PL_DHashTableFinish(&mPackagesHash); |
michael@0 | 110 | } |
michael@0 | 111 | |
michael@0 | 112 | nsresult |
michael@0 | 113 | nsChromeRegistryChrome::Init() |
michael@0 | 114 | { |
michael@0 | 115 | nsresult rv = nsChromeRegistry::Init(); |
michael@0 | 116 | if (NS_FAILED(rv)) |
michael@0 | 117 | return rv; |
michael@0 | 118 | |
michael@0 | 119 | mSelectedLocale = NS_LITERAL_CSTRING("en-US"); |
michael@0 | 120 | mSelectedSkin = NS_LITERAL_CSTRING("classic/1.0"); |
michael@0 | 121 | |
michael@0 | 122 | PL_DHashTableInit(&mPackagesHash, &kTableOps, |
michael@0 | 123 | nullptr, sizeof(PackageEntry), 16); |
michael@0 | 124 | |
michael@0 | 125 | bool safeMode = false; |
michael@0 | 126 | nsCOMPtr<nsIXULRuntime> xulrun (do_GetService(XULAPPINFO_SERVICE_CONTRACTID)); |
michael@0 | 127 | if (xulrun) |
michael@0 | 128 | xulrun->GetInSafeMode(&safeMode); |
michael@0 | 129 | |
michael@0 | 130 | nsCOMPtr<nsIPrefService> prefserv (do_GetService(NS_PREFSERVICE_CONTRACTID)); |
michael@0 | 131 | nsCOMPtr<nsIPrefBranch> prefs; |
michael@0 | 132 | |
michael@0 | 133 | if (safeMode) |
michael@0 | 134 | prefserv->GetDefaultBranch(nullptr, getter_AddRefs(prefs)); |
michael@0 | 135 | else |
michael@0 | 136 | prefs = do_QueryInterface(prefserv); |
michael@0 | 137 | |
michael@0 | 138 | if (!prefs) { |
michael@0 | 139 | NS_WARNING("Could not get pref service!"); |
michael@0 | 140 | } |
michael@0 | 141 | else { |
michael@0 | 142 | nsXPIDLCString provider; |
michael@0 | 143 | rv = prefs->GetCharPref(SELECTED_SKIN_PREF, getter_Copies(provider)); |
michael@0 | 144 | if (NS_SUCCEEDED(rv)) |
michael@0 | 145 | mSelectedSkin = provider; |
michael@0 | 146 | |
michael@0 | 147 | SelectLocaleFromPref(prefs); |
michael@0 | 148 | |
michael@0 | 149 | rv = prefs->AddObserver(MATCH_OS_LOCALE_PREF, this, true); |
michael@0 | 150 | rv = prefs->AddObserver(SELECTED_LOCALE_PREF, this, true); |
michael@0 | 151 | rv = prefs->AddObserver(SELECTED_SKIN_PREF, this, true); |
michael@0 | 152 | } |
michael@0 | 153 | |
michael@0 | 154 | nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService(); |
michael@0 | 155 | if (obsService) { |
michael@0 | 156 | obsService->AddObserver(this, "command-line-startup", true); |
michael@0 | 157 | obsService->AddObserver(this, "profile-initial-state", true); |
michael@0 | 158 | } |
michael@0 | 159 | |
michael@0 | 160 | return NS_OK; |
michael@0 | 161 | } |
michael@0 | 162 | |
michael@0 | 163 | NS_IMETHODIMP |
michael@0 | 164 | nsChromeRegistryChrome::CheckForOSAccessibility() |
michael@0 | 165 | { |
michael@0 | 166 | int32_t useAccessibilityTheme = |
michael@0 | 167 | LookAndFeel::GetInt(LookAndFeel::eIntID_UseAccessibilityTheme, 0); |
michael@0 | 168 | |
michael@0 | 169 | if (useAccessibilityTheme) { |
michael@0 | 170 | /* Set the skin to classic and remove pref observers */ |
michael@0 | 171 | if (!mSelectedSkin.EqualsLiteral("classic/1.0")) { |
michael@0 | 172 | mSelectedSkin.AssignLiteral("classic/1.0"); |
michael@0 | 173 | RefreshSkins(); |
michael@0 | 174 | } |
michael@0 | 175 | |
michael@0 | 176 | nsCOMPtr<nsIPrefBranch> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID)); |
michael@0 | 177 | if (prefs) { |
michael@0 | 178 | prefs->RemoveObserver(SELECTED_SKIN_PREF, this); |
michael@0 | 179 | } |
michael@0 | 180 | } |
michael@0 | 181 | |
michael@0 | 182 | return NS_OK; |
michael@0 | 183 | } |
michael@0 | 184 | |
michael@0 | 185 | NS_IMETHODIMP |
michael@0 | 186 | nsChromeRegistryChrome::GetLocalesForPackage(const nsACString& aPackage, |
michael@0 | 187 | nsIUTF8StringEnumerator* *aResult) |
michael@0 | 188 | { |
michael@0 | 189 | nsCString realpackage; |
michael@0 | 190 | nsresult rv = OverrideLocalePackage(aPackage, realpackage); |
michael@0 | 191 | if (NS_FAILED(rv)) |
michael@0 | 192 | return rv; |
michael@0 | 193 | |
michael@0 | 194 | nsTArray<nsCString> *a = new nsTArray<nsCString>; |
michael@0 | 195 | if (!a) |
michael@0 | 196 | return NS_ERROR_OUT_OF_MEMORY; |
michael@0 | 197 | |
michael@0 | 198 | PackageEntry* entry = |
michael@0 | 199 | static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash, |
michael@0 | 200 | & realpackage, |
michael@0 | 201 | PL_DHASH_LOOKUP)); |
michael@0 | 202 | |
michael@0 | 203 | if (PL_DHASH_ENTRY_IS_BUSY(entry)) { |
michael@0 | 204 | entry->locales.EnumerateToArray(a); |
michael@0 | 205 | } |
michael@0 | 206 | |
michael@0 | 207 | rv = NS_NewAdoptingUTF8StringEnumerator(aResult, a); |
michael@0 | 208 | if (NS_FAILED(rv)) |
michael@0 | 209 | delete a; |
michael@0 | 210 | |
michael@0 | 211 | return rv; |
michael@0 | 212 | } |
michael@0 | 213 | |
michael@0 | 214 | static nsresult |
michael@0 | 215 | getUILangCountry(nsACString& aUILang) |
michael@0 | 216 | { |
michael@0 | 217 | nsresult rv; |
michael@0 | 218 | |
michael@0 | 219 | nsCOMPtr<nsILocaleService> localeService = do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv); |
michael@0 | 220 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 221 | |
michael@0 | 222 | nsAutoString uiLang; |
michael@0 | 223 | rv = localeService->GetLocaleComponentForUserAgent(uiLang); |
michael@0 | 224 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 225 | |
michael@0 | 226 | CopyUTF16toUTF8(uiLang, aUILang); |
michael@0 | 227 | return NS_OK; |
michael@0 | 228 | } |
michael@0 | 229 | |
michael@0 | 230 | NS_IMETHODIMP |
michael@0 | 231 | nsChromeRegistryChrome::IsLocaleRTL(const nsACString& package, bool *aResult) |
michael@0 | 232 | { |
michael@0 | 233 | *aResult = false; |
michael@0 | 234 | |
michael@0 | 235 | nsAutoCString locale; |
michael@0 | 236 | GetSelectedLocale(package, locale); |
michael@0 | 237 | if (locale.Length() < 2) |
michael@0 | 238 | return NS_OK; |
michael@0 | 239 | |
michael@0 | 240 | // first check the intl.uidirection.<locale> preference, and if that is not |
michael@0 | 241 | // set, check the same preference but with just the first two characters of |
michael@0 | 242 | // the locale. If that isn't set, default to left-to-right. |
michael@0 | 243 | nsAutoCString prefString = NS_LITERAL_CSTRING("intl.uidirection.") + locale; |
michael@0 | 244 | nsCOMPtr<nsIPrefBranch> prefBranch (do_GetService(NS_PREFSERVICE_CONTRACTID)); |
michael@0 | 245 | if (!prefBranch) |
michael@0 | 246 | return NS_OK; |
michael@0 | 247 | |
michael@0 | 248 | nsXPIDLCString dir; |
michael@0 | 249 | prefBranch->GetCharPref(prefString.get(), getter_Copies(dir)); |
michael@0 | 250 | if (dir.IsEmpty()) { |
michael@0 | 251 | int32_t hyphen = prefString.FindChar('-'); |
michael@0 | 252 | if (hyphen >= 1) { |
michael@0 | 253 | nsAutoCString shortPref(Substring(prefString, 0, hyphen)); |
michael@0 | 254 | prefBranch->GetCharPref(shortPref.get(), getter_Copies(dir)); |
michael@0 | 255 | } |
michael@0 | 256 | } |
michael@0 | 257 | *aResult = dir.EqualsLiteral("rtl"); |
michael@0 | 258 | return NS_OK; |
michael@0 | 259 | } |
michael@0 | 260 | |
michael@0 | 261 | nsresult |
michael@0 | 262 | nsChromeRegistryChrome::GetSelectedLocale(const nsACString& aPackage, |
michael@0 | 263 | nsACString& aLocale) |
michael@0 | 264 | { |
michael@0 | 265 | nsCString realpackage; |
michael@0 | 266 | nsresult rv = OverrideLocalePackage(aPackage, realpackage); |
michael@0 | 267 | if (NS_FAILED(rv)) |
michael@0 | 268 | return rv; |
michael@0 | 269 | PackageEntry* entry = |
michael@0 | 270 | static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash, |
michael@0 | 271 | & realpackage, |
michael@0 | 272 | PL_DHASH_LOOKUP)); |
michael@0 | 273 | |
michael@0 | 274 | if (PL_DHASH_ENTRY_IS_FREE(entry)) |
michael@0 | 275 | return NS_ERROR_FAILURE; |
michael@0 | 276 | |
michael@0 | 277 | aLocale = entry->locales.GetSelected(mSelectedLocale, nsProviderArray::LOCALE); |
michael@0 | 278 | if (aLocale.IsEmpty()) |
michael@0 | 279 | return NS_ERROR_FAILURE; |
michael@0 | 280 | |
michael@0 | 281 | return NS_OK; |
michael@0 | 282 | } |
michael@0 | 283 | |
michael@0 | 284 | nsresult |
michael@0 | 285 | nsChromeRegistryChrome::OverrideLocalePackage(const nsACString& aPackage, |
michael@0 | 286 | nsACString& aOverride) |
michael@0 | 287 | { |
michael@0 | 288 | const nsACString& pref = NS_LITERAL_CSTRING(PACKAGE_OVERRIDE_BRANCH) + aPackage; |
michael@0 | 289 | nsAdoptingCString override = mozilla::Preferences::GetCString(PromiseFlatCString(pref).get()); |
michael@0 | 290 | if (override) { |
michael@0 | 291 | aOverride = override; |
michael@0 | 292 | } |
michael@0 | 293 | else { |
michael@0 | 294 | aOverride = aPackage; |
michael@0 | 295 | } |
michael@0 | 296 | return NS_OK; |
michael@0 | 297 | } |
michael@0 | 298 | |
michael@0 | 299 | nsresult |
michael@0 | 300 | nsChromeRegistryChrome::SelectLocaleFromPref(nsIPrefBranch* prefs) |
michael@0 | 301 | { |
michael@0 | 302 | nsresult rv; |
michael@0 | 303 | bool matchOSLocale = false; |
michael@0 | 304 | rv = prefs->GetBoolPref(MATCH_OS_LOCALE_PREF, &matchOSLocale); |
michael@0 | 305 | |
michael@0 | 306 | if (NS_SUCCEEDED(rv) && matchOSLocale) { |
michael@0 | 307 | // compute lang and region code only when needed! |
michael@0 | 308 | nsAutoCString uiLocale; |
michael@0 | 309 | rv = getUILangCountry(uiLocale); |
michael@0 | 310 | if (NS_SUCCEEDED(rv)) |
michael@0 | 311 | mSelectedLocale = uiLocale; |
michael@0 | 312 | } |
michael@0 | 313 | else { |
michael@0 | 314 | nsXPIDLCString provider; |
michael@0 | 315 | rv = prefs->GetCharPref(SELECTED_LOCALE_PREF, getter_Copies(provider)); |
michael@0 | 316 | if (NS_SUCCEEDED(rv)) { |
michael@0 | 317 | mSelectedLocale = provider; |
michael@0 | 318 | } |
michael@0 | 319 | } |
michael@0 | 320 | |
michael@0 | 321 | if (NS_FAILED(rv)) |
michael@0 | 322 | NS_ERROR("Couldn't select locale from pref!"); |
michael@0 | 323 | |
michael@0 | 324 | return rv; |
michael@0 | 325 | } |
michael@0 | 326 | |
michael@0 | 327 | NS_IMETHODIMP |
michael@0 | 328 | nsChromeRegistryChrome::Observe(nsISupports *aSubject, const char *aTopic, |
michael@0 | 329 | const char16_t *someData) |
michael@0 | 330 | { |
michael@0 | 331 | nsresult rv = NS_OK; |
michael@0 | 332 | |
michael@0 | 333 | if (!strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic)) { |
michael@0 | 334 | nsCOMPtr<nsIPrefBranch> prefs (do_QueryInterface(aSubject)); |
michael@0 | 335 | NS_ASSERTION(prefs, "Bad observer call!"); |
michael@0 | 336 | |
michael@0 | 337 | NS_ConvertUTF16toUTF8 pref(someData); |
michael@0 | 338 | |
michael@0 | 339 | if (pref.EqualsLiteral(MATCH_OS_LOCALE_PREF) || |
michael@0 | 340 | pref.EqualsLiteral(SELECTED_LOCALE_PREF)) { |
michael@0 | 341 | rv = UpdateSelectedLocale(); |
michael@0 | 342 | if (NS_SUCCEEDED(rv) && mProfileLoaded) |
michael@0 | 343 | FlushAllCaches(); |
michael@0 | 344 | } |
michael@0 | 345 | else if (pref.EqualsLiteral(SELECTED_SKIN_PREF)) { |
michael@0 | 346 | nsXPIDLCString provider; |
michael@0 | 347 | rv = prefs->GetCharPref(pref.get(), getter_Copies(provider)); |
michael@0 | 348 | if (NS_FAILED(rv)) { |
michael@0 | 349 | NS_ERROR("Couldn't get new skin pref!"); |
michael@0 | 350 | return rv; |
michael@0 | 351 | } |
michael@0 | 352 | |
michael@0 | 353 | mSelectedSkin = provider; |
michael@0 | 354 | RefreshSkins(); |
michael@0 | 355 | } else { |
michael@0 | 356 | NS_ERROR("Unexpected pref!"); |
michael@0 | 357 | } |
michael@0 | 358 | } |
michael@0 | 359 | else if (!strcmp("command-line-startup", aTopic)) { |
michael@0 | 360 | nsCOMPtr<nsICommandLine> cmdLine (do_QueryInterface(aSubject)); |
michael@0 | 361 | if (cmdLine) { |
michael@0 | 362 | nsAutoString uiLocale; |
michael@0 | 363 | rv = cmdLine->HandleFlagWithParam(NS_LITERAL_STRING(UILOCALE_CMD_LINE_ARG), |
michael@0 | 364 | false, uiLocale); |
michael@0 | 365 | if (NS_SUCCEEDED(rv) && !uiLocale.IsEmpty()) { |
michael@0 | 366 | CopyUTF16toUTF8(uiLocale, mSelectedLocale); |
michael@0 | 367 | nsCOMPtr<nsIPrefBranch> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID)); |
michael@0 | 368 | if (prefs) { |
michael@0 | 369 | prefs->RemoveObserver(SELECTED_LOCALE_PREF, this); |
michael@0 | 370 | } |
michael@0 | 371 | } |
michael@0 | 372 | } |
michael@0 | 373 | } |
michael@0 | 374 | else if (!strcmp("profile-initial-state", aTopic)) { |
michael@0 | 375 | mProfileLoaded = true; |
michael@0 | 376 | } |
michael@0 | 377 | else { |
michael@0 | 378 | NS_ERROR("Unexpected observer topic!"); |
michael@0 | 379 | } |
michael@0 | 380 | |
michael@0 | 381 | return rv; |
michael@0 | 382 | } |
michael@0 | 383 | |
michael@0 | 384 | NS_IMETHODIMP |
michael@0 | 385 | nsChromeRegistryChrome::CheckForNewChrome() |
michael@0 | 386 | { |
michael@0 | 387 | PL_DHashTableEnumerate(&mPackagesHash, RemoveAll, nullptr); |
michael@0 | 388 | mOverlayHash.Clear(); |
michael@0 | 389 | mStyleHash.Clear(); |
michael@0 | 390 | mOverrideTable.Clear(); |
michael@0 | 391 | |
michael@0 | 392 | nsComponentManagerImpl::gComponentManager->RereadChromeManifests(); |
michael@0 | 393 | return NS_OK; |
michael@0 | 394 | } |
michael@0 | 395 | |
michael@0 | 396 | nsresult nsChromeRegistryChrome::UpdateSelectedLocale() |
michael@0 | 397 | { |
michael@0 | 398 | nsresult rv = NS_OK; |
michael@0 | 399 | nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID)); |
michael@0 | 400 | if (prefs) { |
michael@0 | 401 | rv = SelectLocaleFromPref(prefs); |
michael@0 | 402 | if (NS_SUCCEEDED(rv)) { |
michael@0 | 403 | nsCOMPtr<nsIObserverService> obsSvc = |
michael@0 | 404 | mozilla::services::GetObserverService(); |
michael@0 | 405 | NS_ASSERTION(obsSvc, "Couldn't get observer service."); |
michael@0 | 406 | obsSvc->NotifyObservers((nsIChromeRegistry*) this, |
michael@0 | 407 | "selected-locale-has-changed", nullptr); |
michael@0 | 408 | } |
michael@0 | 409 | } |
michael@0 | 410 | |
michael@0 | 411 | return rv; |
michael@0 | 412 | } |
michael@0 | 413 | |
michael@0 | 414 | static void |
michael@0 | 415 | SerializeURI(nsIURI* aURI, |
michael@0 | 416 | SerializedURI& aSerializedURI) |
michael@0 | 417 | { |
michael@0 | 418 | if (!aURI) |
michael@0 | 419 | return; |
michael@0 | 420 | |
michael@0 | 421 | aURI->GetSpec(aSerializedURI.spec); |
michael@0 | 422 | aURI->GetOriginCharset(aSerializedURI.charset); |
michael@0 | 423 | } |
michael@0 | 424 | |
michael@0 | 425 | static PLDHashOperator |
michael@0 | 426 | EnumerateOverride(nsIURI* aURIKey, |
michael@0 | 427 | nsIURI* aURI, |
michael@0 | 428 | void* aArg) |
michael@0 | 429 | { |
michael@0 | 430 | nsTArray<OverrideMapping>* overrides = |
michael@0 | 431 | static_cast<nsTArray<OverrideMapping>*>(aArg); |
michael@0 | 432 | |
michael@0 | 433 | SerializedURI chromeURI, overrideURI; |
michael@0 | 434 | |
michael@0 | 435 | SerializeURI(aURIKey, chromeURI); |
michael@0 | 436 | SerializeURI(aURI, overrideURI); |
michael@0 | 437 | |
michael@0 | 438 | OverrideMapping override = { |
michael@0 | 439 | chromeURI, overrideURI |
michael@0 | 440 | }; |
michael@0 | 441 | overrides->AppendElement(override); |
michael@0 | 442 | return (PLDHashOperator)PL_DHASH_NEXT; |
michael@0 | 443 | } |
michael@0 | 444 | |
michael@0 | 445 | struct EnumerationArgs |
michael@0 | 446 | { |
michael@0 | 447 | InfallibleTArray<ChromePackage>& packages; |
michael@0 | 448 | const nsCString& selectedLocale; |
michael@0 | 449 | const nsCString& selectedSkin; |
michael@0 | 450 | }; |
michael@0 | 451 | |
michael@0 | 452 | void |
michael@0 | 453 | nsChromeRegistryChrome::SendRegisteredChrome( |
michael@0 | 454 | mozilla::dom::PContentParent* aParent) |
michael@0 | 455 | { |
michael@0 | 456 | InfallibleTArray<ChromePackage> packages; |
michael@0 | 457 | InfallibleTArray<ResourceMapping> resources; |
michael@0 | 458 | InfallibleTArray<OverrideMapping> overrides; |
michael@0 | 459 | |
michael@0 | 460 | EnumerationArgs args = { |
michael@0 | 461 | packages, mSelectedLocale, mSelectedSkin |
michael@0 | 462 | }; |
michael@0 | 463 | PL_DHashTableEnumerate(&mPackagesHash, CollectPackages, &args); |
michael@0 | 464 | |
michael@0 | 465 | nsCOMPtr<nsIIOService> io (do_GetIOService()); |
michael@0 | 466 | NS_ENSURE_TRUE_VOID(io); |
michael@0 | 467 | |
michael@0 | 468 | nsCOMPtr<nsIProtocolHandler> ph; |
michael@0 | 469 | nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph)); |
michael@0 | 470 | NS_ENSURE_SUCCESS_VOID(rv); |
michael@0 | 471 | |
michael@0 | 472 | //FIXME: Some substitutions are set up lazily and might not exist yet |
michael@0 | 473 | nsCOMPtr<nsIResProtocolHandler> irph (do_QueryInterface(ph)); |
michael@0 | 474 | nsResProtocolHandler* rph = static_cast<nsResProtocolHandler*>(irph.get()); |
michael@0 | 475 | rph->CollectSubstitutions(resources); |
michael@0 | 476 | |
michael@0 | 477 | mOverrideTable.EnumerateRead(&EnumerateOverride, &overrides); |
michael@0 | 478 | |
michael@0 | 479 | bool success = aParent->SendRegisterChrome(packages, resources, overrides, |
michael@0 | 480 | mSelectedLocale); |
michael@0 | 481 | NS_ENSURE_TRUE_VOID(success); |
michael@0 | 482 | } |
michael@0 | 483 | |
michael@0 | 484 | PLDHashOperator |
michael@0 | 485 | nsChromeRegistryChrome::CollectPackages(PLDHashTable *table, |
michael@0 | 486 | PLDHashEntryHdr *entry, |
michael@0 | 487 | uint32_t number, |
michael@0 | 488 | void *arg) |
michael@0 | 489 | { |
michael@0 | 490 | EnumerationArgs* args = static_cast<EnumerationArgs*>(arg); |
michael@0 | 491 | PackageEntry* package = static_cast<PackageEntry*>(entry); |
michael@0 | 492 | |
michael@0 | 493 | SerializedURI contentURI, localeURI, skinURI; |
michael@0 | 494 | |
michael@0 | 495 | SerializeURI(package->baseURI, contentURI); |
michael@0 | 496 | SerializeURI(package->locales.GetBase(args->selectedLocale, |
michael@0 | 497 | nsProviderArray::LOCALE), localeURI); |
michael@0 | 498 | SerializeURI(package->skins.GetBase(args->selectedSkin, nsProviderArray::ANY), |
michael@0 | 499 | skinURI); |
michael@0 | 500 | |
michael@0 | 501 | ChromePackage chromePackage = { |
michael@0 | 502 | package->package, |
michael@0 | 503 | contentURI, |
michael@0 | 504 | localeURI, |
michael@0 | 505 | skinURI, |
michael@0 | 506 | package->flags |
michael@0 | 507 | }; |
michael@0 | 508 | args->packages.AppendElement(chromePackage); |
michael@0 | 509 | return (PLDHashOperator)PL_DHASH_NEXT; |
michael@0 | 510 | } |
michael@0 | 511 | |
michael@0 | 512 | static bool |
michael@0 | 513 | CanLoadResource(nsIURI* aResourceURI) |
michael@0 | 514 | { |
michael@0 | 515 | bool isLocalResource = false; |
michael@0 | 516 | (void)NS_URIChainHasFlags(aResourceURI, |
michael@0 | 517 | nsIProtocolHandler::URI_IS_LOCAL_RESOURCE, |
michael@0 | 518 | &isLocalResource); |
michael@0 | 519 | return isLocalResource; |
michael@0 | 520 | } |
michael@0 | 521 | |
michael@0 | 522 | nsIURI* |
michael@0 | 523 | nsChromeRegistryChrome::GetBaseURIFromPackage(const nsCString& aPackage, |
michael@0 | 524 | const nsCString& aProvider, |
michael@0 | 525 | const nsCString& aPath) |
michael@0 | 526 | { |
michael@0 | 527 | PackageEntry* entry = |
michael@0 | 528 | static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash, |
michael@0 | 529 | &aPackage, |
michael@0 | 530 | PL_DHASH_LOOKUP)); |
michael@0 | 531 | |
michael@0 | 532 | if (PL_DHASH_ENTRY_IS_FREE(entry)) { |
michael@0 | 533 | if (!mInitialized) |
michael@0 | 534 | return nullptr; |
michael@0 | 535 | |
michael@0 | 536 | LogMessage("No chrome package registered for chrome://%s/%s/%s", |
michael@0 | 537 | aPackage.get(), aProvider.get(), aPath.get()); |
michael@0 | 538 | |
michael@0 | 539 | return nullptr; |
michael@0 | 540 | } |
michael@0 | 541 | |
michael@0 | 542 | if (aProvider.EqualsLiteral("locale")) { |
michael@0 | 543 | return entry->locales.GetBase(mSelectedLocale, nsProviderArray::LOCALE); |
michael@0 | 544 | } |
michael@0 | 545 | else if (aProvider.EqualsLiteral("skin")) { |
michael@0 | 546 | return entry->skins.GetBase(mSelectedSkin, nsProviderArray::ANY); |
michael@0 | 547 | } |
michael@0 | 548 | else if (aProvider.EqualsLiteral("content")) { |
michael@0 | 549 | return entry->baseURI; |
michael@0 | 550 | } |
michael@0 | 551 | return nullptr; |
michael@0 | 552 | } |
michael@0 | 553 | |
michael@0 | 554 | nsresult |
michael@0 | 555 | nsChromeRegistryChrome::GetFlagsFromPackage(const nsCString& aPackage, |
michael@0 | 556 | uint32_t* aFlags) |
michael@0 | 557 | { |
michael@0 | 558 | PackageEntry* entry = |
michael@0 | 559 | static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash, |
michael@0 | 560 | & (nsACString&) aPackage, |
michael@0 | 561 | PL_DHASH_LOOKUP)); |
michael@0 | 562 | if (PL_DHASH_ENTRY_IS_FREE(entry)) |
michael@0 | 563 | return NS_ERROR_NOT_AVAILABLE; |
michael@0 | 564 | |
michael@0 | 565 | *aFlags = entry->flags; |
michael@0 | 566 | return NS_OK; |
michael@0 | 567 | } |
michael@0 | 568 | |
michael@0 | 569 | PLHashNumber |
michael@0 | 570 | nsChromeRegistryChrome::HashKey(PLDHashTable *table, const void *key) |
michael@0 | 571 | { |
michael@0 | 572 | const nsACString& str = *reinterpret_cast<const nsACString*>(key); |
michael@0 | 573 | return HashString(str); |
michael@0 | 574 | } |
michael@0 | 575 | |
michael@0 | 576 | bool |
michael@0 | 577 | nsChromeRegistryChrome::MatchKey(PLDHashTable *table, const PLDHashEntryHdr *entry, |
michael@0 | 578 | const void *key) |
michael@0 | 579 | { |
michael@0 | 580 | const nsACString& str = *reinterpret_cast<const nsACString*>(key); |
michael@0 | 581 | const PackageEntry* pentry = static_cast<const PackageEntry*>(entry); |
michael@0 | 582 | return str.Equals(pentry->package); |
michael@0 | 583 | } |
michael@0 | 584 | |
michael@0 | 585 | void |
michael@0 | 586 | nsChromeRegistryChrome::ClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry) |
michael@0 | 587 | { |
michael@0 | 588 | PackageEntry* pentry = static_cast<PackageEntry*>(entry); |
michael@0 | 589 | pentry->~PackageEntry(); |
michael@0 | 590 | } |
michael@0 | 591 | |
michael@0 | 592 | bool |
michael@0 | 593 | nsChromeRegistryChrome::InitEntry(PLDHashTable *table, PLDHashEntryHdr *entry, |
michael@0 | 594 | const void *key) |
michael@0 | 595 | { |
michael@0 | 596 | const nsACString& str = *reinterpret_cast<const nsACString*>(key); |
michael@0 | 597 | |
michael@0 | 598 | new (entry) PackageEntry(str); |
michael@0 | 599 | return true; |
michael@0 | 600 | } |
michael@0 | 601 | |
michael@0 | 602 | const PLDHashTableOps |
michael@0 | 603 | nsChromeRegistryChrome::kTableOps = { |
michael@0 | 604 | PL_DHashAllocTable, |
michael@0 | 605 | PL_DHashFreeTable, |
michael@0 | 606 | HashKey, |
michael@0 | 607 | MatchKey, |
michael@0 | 608 | PL_DHashMoveEntryStub, |
michael@0 | 609 | ClearEntry, |
michael@0 | 610 | PL_DHashFinalizeStub, |
michael@0 | 611 | InitEntry |
michael@0 | 612 | }; |
michael@0 | 613 | |
michael@0 | 614 | nsChromeRegistryChrome::ProviderEntry* |
michael@0 | 615 | nsChromeRegistryChrome::nsProviderArray::GetProvider(const nsACString& aPreferred, MatchType aType) |
michael@0 | 616 | { |
michael@0 | 617 | int32_t i = mArray.Count(); |
michael@0 | 618 | if (!i) |
michael@0 | 619 | return nullptr; |
michael@0 | 620 | |
michael@0 | 621 | ProviderEntry* found = nullptr; // Only set if we find a partial-match locale |
michael@0 | 622 | ProviderEntry* entry; |
michael@0 | 623 | |
michael@0 | 624 | while (i--) { |
michael@0 | 625 | entry = reinterpret_cast<ProviderEntry*>(mArray[i]); |
michael@0 | 626 | if (aPreferred.Equals(entry->provider)) |
michael@0 | 627 | return entry; |
michael@0 | 628 | |
michael@0 | 629 | if (aType != LOCALE) |
michael@0 | 630 | continue; |
michael@0 | 631 | |
michael@0 | 632 | if (LanguagesMatch(aPreferred, entry->provider)) { |
michael@0 | 633 | found = entry; |
michael@0 | 634 | continue; |
michael@0 | 635 | } |
michael@0 | 636 | |
michael@0 | 637 | if (!found && entry->provider.EqualsLiteral("en-US")) |
michael@0 | 638 | found = entry; |
michael@0 | 639 | } |
michael@0 | 640 | |
michael@0 | 641 | if (!found && aType != EXACT) |
michael@0 | 642 | return entry; |
michael@0 | 643 | |
michael@0 | 644 | return found; |
michael@0 | 645 | } |
michael@0 | 646 | |
michael@0 | 647 | nsIURI* |
michael@0 | 648 | nsChromeRegistryChrome::nsProviderArray::GetBase(const nsACString& aPreferred, MatchType aType) |
michael@0 | 649 | { |
michael@0 | 650 | ProviderEntry* provider = GetProvider(aPreferred, aType); |
michael@0 | 651 | |
michael@0 | 652 | if (!provider) |
michael@0 | 653 | return nullptr; |
michael@0 | 654 | |
michael@0 | 655 | return provider->baseURI; |
michael@0 | 656 | } |
michael@0 | 657 | |
michael@0 | 658 | const nsACString& |
michael@0 | 659 | nsChromeRegistryChrome::nsProviderArray::GetSelected(const nsACString& aPreferred, MatchType aType) |
michael@0 | 660 | { |
michael@0 | 661 | ProviderEntry* entry = GetProvider(aPreferred, aType); |
michael@0 | 662 | |
michael@0 | 663 | if (entry) |
michael@0 | 664 | return entry->provider; |
michael@0 | 665 | |
michael@0 | 666 | return EmptyCString(); |
michael@0 | 667 | } |
michael@0 | 668 | |
michael@0 | 669 | void |
michael@0 | 670 | nsChromeRegistryChrome::nsProviderArray::SetBase(const nsACString& aProvider, nsIURI* aBaseURL) |
michael@0 | 671 | { |
michael@0 | 672 | ProviderEntry* provider = GetProvider(aProvider, EXACT); |
michael@0 | 673 | |
michael@0 | 674 | if (provider) { |
michael@0 | 675 | provider->baseURI = aBaseURL; |
michael@0 | 676 | return; |
michael@0 | 677 | } |
michael@0 | 678 | |
michael@0 | 679 | // no existing entries, add a new one |
michael@0 | 680 | provider = new ProviderEntry(aProvider, aBaseURL); |
michael@0 | 681 | if (!provider) |
michael@0 | 682 | return; // It's safe to silently fail on OOM |
michael@0 | 683 | |
michael@0 | 684 | mArray.AppendElement(provider); |
michael@0 | 685 | } |
michael@0 | 686 | |
michael@0 | 687 | void |
michael@0 | 688 | nsChromeRegistryChrome::nsProviderArray::EnumerateToArray(nsTArray<nsCString> *a) |
michael@0 | 689 | { |
michael@0 | 690 | int32_t i = mArray.Count(); |
michael@0 | 691 | while (i--) { |
michael@0 | 692 | ProviderEntry *entry = reinterpret_cast<ProviderEntry*>(mArray[i]); |
michael@0 | 693 | a->AppendElement(entry->provider); |
michael@0 | 694 | } |
michael@0 | 695 | } |
michael@0 | 696 | |
michael@0 | 697 | void |
michael@0 | 698 | nsChromeRegistryChrome::nsProviderArray::Clear() |
michael@0 | 699 | { |
michael@0 | 700 | int32_t i = mArray.Count(); |
michael@0 | 701 | while (i--) { |
michael@0 | 702 | ProviderEntry* entry = reinterpret_cast<ProviderEntry*>(mArray[i]); |
michael@0 | 703 | delete entry; |
michael@0 | 704 | } |
michael@0 | 705 | |
michael@0 | 706 | mArray.Clear(); |
michael@0 | 707 | } |
michael@0 | 708 | |
michael@0 | 709 | void |
michael@0 | 710 | nsChromeRegistryChrome::OverlayListEntry::AddURI(nsIURI* aURI) |
michael@0 | 711 | { |
michael@0 | 712 | int32_t i = mArray.Count(); |
michael@0 | 713 | while (i--) { |
michael@0 | 714 | bool equals; |
michael@0 | 715 | if (NS_SUCCEEDED(aURI->Equals(mArray[i], &equals)) && equals) |
michael@0 | 716 | return; |
michael@0 | 717 | } |
michael@0 | 718 | |
michael@0 | 719 | mArray.AppendObject(aURI); |
michael@0 | 720 | } |
michael@0 | 721 | |
michael@0 | 722 | void |
michael@0 | 723 | nsChromeRegistryChrome::OverlayListHash::Add(nsIURI* aBase, nsIURI* aOverlay) |
michael@0 | 724 | { |
michael@0 | 725 | OverlayListEntry* entry = mTable.PutEntry(aBase); |
michael@0 | 726 | if (entry) |
michael@0 | 727 | entry->AddURI(aOverlay); |
michael@0 | 728 | } |
michael@0 | 729 | |
michael@0 | 730 | const nsCOMArray<nsIURI>* |
michael@0 | 731 | nsChromeRegistryChrome::OverlayListHash::GetArray(nsIURI* aBase) |
michael@0 | 732 | { |
michael@0 | 733 | OverlayListEntry* entry = mTable.GetEntry(aBase); |
michael@0 | 734 | if (!entry) |
michael@0 | 735 | return nullptr; |
michael@0 | 736 | |
michael@0 | 737 | return &entry->mArray; |
michael@0 | 738 | } |
michael@0 | 739 | |
michael@0 | 740 | #ifdef MOZ_XUL |
michael@0 | 741 | NS_IMETHODIMP |
michael@0 | 742 | nsChromeRegistryChrome::GetStyleOverlays(nsIURI *aChromeURL, |
michael@0 | 743 | nsISimpleEnumerator **aResult) |
michael@0 | 744 | { |
michael@0 | 745 | const nsCOMArray<nsIURI>* parray = mStyleHash.GetArray(aChromeURL); |
michael@0 | 746 | if (!parray) |
michael@0 | 747 | return NS_NewEmptyEnumerator(aResult); |
michael@0 | 748 | |
michael@0 | 749 | return NS_NewArrayEnumerator(aResult, *parray); |
michael@0 | 750 | } |
michael@0 | 751 | |
michael@0 | 752 | NS_IMETHODIMP |
michael@0 | 753 | nsChromeRegistryChrome::GetXULOverlays(nsIURI *aChromeURL, |
michael@0 | 754 | nsISimpleEnumerator **aResult) |
michael@0 | 755 | { |
michael@0 | 756 | const nsCOMArray<nsIURI>* parray = mOverlayHash.GetArray(aChromeURL); |
michael@0 | 757 | if (!parray) |
michael@0 | 758 | return NS_NewEmptyEnumerator(aResult); |
michael@0 | 759 | |
michael@0 | 760 | return NS_NewArrayEnumerator(aResult, *parray); |
michael@0 | 761 | } |
michael@0 | 762 | #endif // MOZ_XUL |
michael@0 | 763 | |
michael@0 | 764 | nsIURI* |
michael@0 | 765 | nsChromeRegistry::ManifestProcessingContext::GetManifestURI() |
michael@0 | 766 | { |
michael@0 | 767 | if (!mManifestURI) { |
michael@0 | 768 | nsCString uri; |
michael@0 | 769 | mFile.GetURIString(uri); |
michael@0 | 770 | NS_NewURI(getter_AddRefs(mManifestURI), uri); |
michael@0 | 771 | } |
michael@0 | 772 | return mManifestURI; |
michael@0 | 773 | } |
michael@0 | 774 | |
michael@0 | 775 | nsIXPConnect* |
michael@0 | 776 | nsChromeRegistry::ManifestProcessingContext::GetXPConnect() |
michael@0 | 777 | { |
michael@0 | 778 | if (!mXPConnect) |
michael@0 | 779 | mXPConnect = do_GetService("@mozilla.org/js/xpc/XPConnect;1"); |
michael@0 | 780 | |
michael@0 | 781 | return mXPConnect; |
michael@0 | 782 | } |
michael@0 | 783 | |
michael@0 | 784 | already_AddRefed<nsIURI> |
michael@0 | 785 | nsChromeRegistry::ManifestProcessingContext::ResolveURI(const char* uri) |
michael@0 | 786 | { |
michael@0 | 787 | nsIURI* baseuri = GetManifestURI(); |
michael@0 | 788 | if (!baseuri) |
michael@0 | 789 | return nullptr; |
michael@0 | 790 | |
michael@0 | 791 | nsCOMPtr<nsIURI> resolved; |
michael@0 | 792 | nsresult rv = NS_NewURI(getter_AddRefs(resolved), uri, baseuri); |
michael@0 | 793 | if (NS_FAILED(rv)) |
michael@0 | 794 | return nullptr; |
michael@0 | 795 | |
michael@0 | 796 | return resolved.forget(); |
michael@0 | 797 | } |
michael@0 | 798 | |
michael@0 | 799 | static void |
michael@0 | 800 | EnsureLowerCase(char *aBuf) |
michael@0 | 801 | { |
michael@0 | 802 | for (; *aBuf; ++aBuf) { |
michael@0 | 803 | char ch = *aBuf; |
michael@0 | 804 | if (ch >= 'A' && ch <= 'Z') |
michael@0 | 805 | *aBuf = ch + 'a' - 'A'; |
michael@0 | 806 | } |
michael@0 | 807 | } |
michael@0 | 808 | |
michael@0 | 809 | void |
michael@0 | 810 | nsChromeRegistryChrome::ManifestContent(ManifestProcessingContext& cx, int lineno, |
michael@0 | 811 | char *const * argv, bool platform, |
michael@0 | 812 | bool contentaccessible) |
michael@0 | 813 | { |
michael@0 | 814 | char* package = argv[0]; |
michael@0 | 815 | char* uri = argv[1]; |
michael@0 | 816 | |
michael@0 | 817 | EnsureLowerCase(package); |
michael@0 | 818 | |
michael@0 | 819 | nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri); |
michael@0 | 820 | if (!resolved) { |
michael@0 | 821 | LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, |
michael@0 | 822 | "During chrome registration, unable to create URI '%s'.", uri); |
michael@0 | 823 | return; |
michael@0 | 824 | } |
michael@0 | 825 | |
michael@0 | 826 | if (!CanLoadResource(resolved)) { |
michael@0 | 827 | LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag, |
michael@0 | 828 | "During chrome registration, cannot register non-local URI '%s' as content.", |
michael@0 | 829 | uri); |
michael@0 | 830 | return; |
michael@0 | 831 | } |
michael@0 | 832 | |
michael@0 | 833 | PackageEntry* entry = |
michael@0 | 834 | static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash, |
michael@0 | 835 | & (const nsACString&) nsDependentCString(package), |
michael@0 | 836 | PL_DHASH_ADD)); |
michael@0 | 837 | if (!entry) |
michael@0 | 838 | return; |
michael@0 | 839 | |
michael@0 | 840 | entry->baseURI = resolved; |
michael@0 | 841 | |
michael@0 | 842 | if (platform) |
michael@0 | 843 | entry->flags |= PLATFORM_PACKAGE; |
michael@0 | 844 | if (contentaccessible) |
michael@0 | 845 | entry->flags |= CONTENT_ACCESSIBLE; |
michael@0 | 846 | } |
michael@0 | 847 | |
michael@0 | 848 | void |
michael@0 | 849 | nsChromeRegistryChrome::ManifestLocale(ManifestProcessingContext& cx, int lineno, |
michael@0 | 850 | char *const * argv, bool platform, |
michael@0 | 851 | bool contentaccessible) |
michael@0 | 852 | { |
michael@0 | 853 | char* package = argv[0]; |
michael@0 | 854 | char* provider = argv[1]; |
michael@0 | 855 | char* uri = argv[2]; |
michael@0 | 856 | |
michael@0 | 857 | EnsureLowerCase(package); |
michael@0 | 858 | |
michael@0 | 859 | nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri); |
michael@0 | 860 | if (!resolved) { |
michael@0 | 861 | LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, |
michael@0 | 862 | "During chrome registration, unable to create URI '%s'.", uri); |
michael@0 | 863 | return; |
michael@0 | 864 | } |
michael@0 | 865 | |
michael@0 | 866 | if (!CanLoadResource(resolved)) { |
michael@0 | 867 | LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag, |
michael@0 | 868 | "During chrome registration, cannot register non-local URI '%s' as content.", |
michael@0 | 869 | uri); |
michael@0 | 870 | return; |
michael@0 | 871 | } |
michael@0 | 872 | |
michael@0 | 873 | PackageEntry* entry = |
michael@0 | 874 | static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash, |
michael@0 | 875 | & (const nsACString&) nsDependentCString(package), |
michael@0 | 876 | PL_DHASH_ADD)); |
michael@0 | 877 | if (!entry) |
michael@0 | 878 | return; |
michael@0 | 879 | |
michael@0 | 880 | entry->locales.SetBase(nsDependentCString(provider), resolved); |
michael@0 | 881 | } |
michael@0 | 882 | |
michael@0 | 883 | void |
michael@0 | 884 | nsChromeRegistryChrome::ManifestSkin(ManifestProcessingContext& cx, int lineno, |
michael@0 | 885 | char *const * argv, bool platform, |
michael@0 | 886 | bool contentaccessible) |
michael@0 | 887 | { |
michael@0 | 888 | char* package = argv[0]; |
michael@0 | 889 | char* provider = argv[1]; |
michael@0 | 890 | char* uri = argv[2]; |
michael@0 | 891 | |
michael@0 | 892 | EnsureLowerCase(package); |
michael@0 | 893 | |
michael@0 | 894 | nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri); |
michael@0 | 895 | if (!resolved) { |
michael@0 | 896 | LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, |
michael@0 | 897 | "During chrome registration, unable to create URI '%s'.", uri); |
michael@0 | 898 | return; |
michael@0 | 899 | } |
michael@0 | 900 | |
michael@0 | 901 | if (!CanLoadResource(resolved)) { |
michael@0 | 902 | LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag, |
michael@0 | 903 | "During chrome registration, cannot register non-local URI '%s' as content.", |
michael@0 | 904 | uri); |
michael@0 | 905 | return; |
michael@0 | 906 | } |
michael@0 | 907 | |
michael@0 | 908 | PackageEntry* entry = |
michael@0 | 909 | static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash, |
michael@0 | 910 | & (const nsACString&) nsDependentCString(package), |
michael@0 | 911 | PL_DHASH_ADD)); |
michael@0 | 912 | if (!entry) |
michael@0 | 913 | return; |
michael@0 | 914 | |
michael@0 | 915 | entry->skins.SetBase(nsDependentCString(provider), resolved); |
michael@0 | 916 | } |
michael@0 | 917 | |
michael@0 | 918 | void |
michael@0 | 919 | nsChromeRegistryChrome::ManifestOverlay(ManifestProcessingContext& cx, int lineno, |
michael@0 | 920 | char *const * argv, bool platform, |
michael@0 | 921 | bool contentaccessible) |
michael@0 | 922 | { |
michael@0 | 923 | char* base = argv[0]; |
michael@0 | 924 | char* overlay = argv[1]; |
michael@0 | 925 | |
michael@0 | 926 | nsCOMPtr<nsIURI> baseuri = cx.ResolveURI(base); |
michael@0 | 927 | nsCOMPtr<nsIURI> overlayuri = cx.ResolveURI(overlay); |
michael@0 | 928 | if (!baseuri || !overlayuri) { |
michael@0 | 929 | LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, |
michael@0 | 930 | "During chrome registration, unable to create URI."); |
michael@0 | 931 | return; |
michael@0 | 932 | } |
michael@0 | 933 | |
michael@0 | 934 | if (!CanLoadResource(overlayuri)) { |
michael@0 | 935 | LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, |
michael@0 | 936 | "Cannot register non-local URI '%s' as an overlay.", overlay); |
michael@0 | 937 | return; |
michael@0 | 938 | } |
michael@0 | 939 | |
michael@0 | 940 | mOverlayHash.Add(baseuri, overlayuri); |
michael@0 | 941 | } |
michael@0 | 942 | |
michael@0 | 943 | void |
michael@0 | 944 | nsChromeRegistryChrome::ManifestStyle(ManifestProcessingContext& cx, int lineno, |
michael@0 | 945 | char *const * argv, bool platform, |
michael@0 | 946 | bool contentaccessible) |
michael@0 | 947 | { |
michael@0 | 948 | char* base = argv[0]; |
michael@0 | 949 | char* overlay = argv[1]; |
michael@0 | 950 | |
michael@0 | 951 | nsCOMPtr<nsIURI> baseuri = cx.ResolveURI(base); |
michael@0 | 952 | nsCOMPtr<nsIURI> overlayuri = cx.ResolveURI(overlay); |
michael@0 | 953 | if (!baseuri || !overlayuri) { |
michael@0 | 954 | LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, |
michael@0 | 955 | "During chrome registration, unable to create URI."); |
michael@0 | 956 | return; |
michael@0 | 957 | } |
michael@0 | 958 | |
michael@0 | 959 | if (!CanLoadResource(overlayuri)) { |
michael@0 | 960 | LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, |
michael@0 | 961 | "Cannot register non-local URI '%s' as a style overlay.", overlay); |
michael@0 | 962 | return; |
michael@0 | 963 | } |
michael@0 | 964 | |
michael@0 | 965 | mStyleHash.Add(baseuri, overlayuri); |
michael@0 | 966 | } |
michael@0 | 967 | |
michael@0 | 968 | void |
michael@0 | 969 | nsChromeRegistryChrome::ManifestOverride(ManifestProcessingContext& cx, int lineno, |
michael@0 | 970 | char *const * argv, bool platform, |
michael@0 | 971 | bool contentaccessible) |
michael@0 | 972 | { |
michael@0 | 973 | char* chrome = argv[0]; |
michael@0 | 974 | char* resolved = argv[1]; |
michael@0 | 975 | |
michael@0 | 976 | nsCOMPtr<nsIURI> chromeuri = cx.ResolveURI(chrome); |
michael@0 | 977 | nsCOMPtr<nsIURI> resolveduri = cx.ResolveURI(resolved); |
michael@0 | 978 | if (!chromeuri || !resolveduri) { |
michael@0 | 979 | LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, |
michael@0 | 980 | "During chrome registration, unable to create URI."); |
michael@0 | 981 | return; |
michael@0 | 982 | } |
michael@0 | 983 | |
michael@0 | 984 | if (!CanLoadResource(resolveduri)) { |
michael@0 | 985 | LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, |
michael@0 | 986 | "Cannot register non-local URI '%s' for an override.", resolved); |
michael@0 | 987 | return; |
michael@0 | 988 | } |
michael@0 | 989 | mOverrideTable.Put(chromeuri, resolveduri); |
michael@0 | 990 | } |
michael@0 | 991 | |
michael@0 | 992 | void |
michael@0 | 993 | nsChromeRegistryChrome::ManifestResource(ManifestProcessingContext& cx, int lineno, |
michael@0 | 994 | char *const * argv, bool platform, |
michael@0 | 995 | bool contentaccessible) |
michael@0 | 996 | { |
michael@0 | 997 | char* package = argv[0]; |
michael@0 | 998 | char* uri = argv[1]; |
michael@0 | 999 | |
michael@0 | 1000 | EnsureLowerCase(package); |
michael@0 | 1001 | nsDependentCString host(package); |
michael@0 | 1002 | |
michael@0 | 1003 | nsCOMPtr<nsIIOService> io = mozilla::services::GetIOService(); |
michael@0 | 1004 | if (!io) { |
michael@0 | 1005 | NS_WARNING("No IO service trying to process chrome manifests"); |
michael@0 | 1006 | return; |
michael@0 | 1007 | } |
michael@0 | 1008 | |
michael@0 | 1009 | nsCOMPtr<nsIProtocolHandler> ph; |
michael@0 | 1010 | nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph)); |
michael@0 | 1011 | if (NS_FAILED(rv)) |
michael@0 | 1012 | return; |
michael@0 | 1013 | |
michael@0 | 1014 | nsCOMPtr<nsIResProtocolHandler> rph = do_QueryInterface(ph); |
michael@0 | 1015 | |
michael@0 | 1016 | bool exists = false; |
michael@0 | 1017 | rv = rph->HasSubstitution(host, &exists); |
michael@0 | 1018 | if (exists) { |
michael@0 | 1019 | LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, |
michael@0 | 1020 | "Duplicate resource declaration for '%s' ignored.", package); |
michael@0 | 1021 | return; |
michael@0 | 1022 | } |
michael@0 | 1023 | |
michael@0 | 1024 | nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri); |
michael@0 | 1025 | if (!resolved) { |
michael@0 | 1026 | LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, |
michael@0 | 1027 | "During chrome registration, unable to create URI '%s'.", uri); |
michael@0 | 1028 | return; |
michael@0 | 1029 | } |
michael@0 | 1030 | |
michael@0 | 1031 | if (!CanLoadResource(resolved)) { |
michael@0 | 1032 | LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag, |
michael@0 | 1033 | "Warning: cannot register non-local URI '%s' as a resource.", |
michael@0 | 1034 | uri); |
michael@0 | 1035 | return; |
michael@0 | 1036 | } |
michael@0 | 1037 | |
michael@0 | 1038 | rph->SetSubstitution(host, resolved); |
michael@0 | 1039 | } |