Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; 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 "nsHyphenationManager.h" |
michael@0 | 7 | #include "nsHyphenator.h" |
michael@0 | 8 | #include "nsIAtom.h" |
michael@0 | 9 | #include "nsIFile.h" |
michael@0 | 10 | #include "nsIURI.h" |
michael@0 | 11 | #include "nsIProperties.h" |
michael@0 | 12 | #include "nsISimpleEnumerator.h" |
michael@0 | 13 | #include "nsIDirectoryEnumerator.h" |
michael@0 | 14 | #include "nsDirectoryServiceDefs.h" |
michael@0 | 15 | #include "nsNetUtil.h" |
michael@0 | 16 | #include "nsUnicharUtils.h" |
michael@0 | 17 | #include "mozilla/Preferences.h" |
michael@0 | 18 | #include "nsZipArchive.h" |
michael@0 | 19 | #include "mozilla/Services.h" |
michael@0 | 20 | #include "nsIObserverService.h" |
michael@0 | 21 | #include "nsCRT.h" |
michael@0 | 22 | |
michael@0 | 23 | using namespace mozilla; |
michael@0 | 24 | |
michael@0 | 25 | static const char kIntlHyphenationAliasPrefix[] = "intl.hyphenation-alias."; |
michael@0 | 26 | static const char kMemoryPressureNotification[] = "memory-pressure"; |
michael@0 | 27 | |
michael@0 | 28 | nsHyphenationManager *nsHyphenationManager::sInstance = nullptr; |
michael@0 | 29 | |
michael@0 | 30 | NS_IMPL_ISUPPORTS(nsHyphenationManager::MemoryPressureObserver, |
michael@0 | 31 | nsIObserver) |
michael@0 | 32 | |
michael@0 | 33 | NS_IMETHODIMP |
michael@0 | 34 | nsHyphenationManager::MemoryPressureObserver::Observe(nsISupports *aSubject, |
michael@0 | 35 | const char *aTopic, |
michael@0 | 36 | const char16_t *aData) |
michael@0 | 37 | { |
michael@0 | 38 | if (!nsCRT::strcmp(aTopic, kMemoryPressureNotification)) { |
michael@0 | 39 | // We don't call Instance() here, as we don't want to create a hyphenation |
michael@0 | 40 | // manager if there isn't already one in existence. |
michael@0 | 41 | // (This observer class is local to the hyphenation manager, so it can use |
michael@0 | 42 | // the protected members directly.) |
michael@0 | 43 | if (nsHyphenationManager::sInstance) { |
michael@0 | 44 | nsHyphenationManager::sInstance->mHyphenators.Clear(); |
michael@0 | 45 | } |
michael@0 | 46 | } |
michael@0 | 47 | return NS_OK; |
michael@0 | 48 | } |
michael@0 | 49 | |
michael@0 | 50 | nsHyphenationManager* |
michael@0 | 51 | nsHyphenationManager::Instance() |
michael@0 | 52 | { |
michael@0 | 53 | if (sInstance == nullptr) { |
michael@0 | 54 | sInstance = new nsHyphenationManager(); |
michael@0 | 55 | |
michael@0 | 56 | nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); |
michael@0 | 57 | if (obs) { |
michael@0 | 58 | obs->AddObserver(new MemoryPressureObserver, |
michael@0 | 59 | kMemoryPressureNotification, false); |
michael@0 | 60 | } |
michael@0 | 61 | } |
michael@0 | 62 | return sInstance; |
michael@0 | 63 | } |
michael@0 | 64 | |
michael@0 | 65 | void |
michael@0 | 66 | nsHyphenationManager::Shutdown() |
michael@0 | 67 | { |
michael@0 | 68 | delete sInstance; |
michael@0 | 69 | sInstance = nullptr; |
michael@0 | 70 | } |
michael@0 | 71 | |
michael@0 | 72 | nsHyphenationManager::nsHyphenationManager() |
michael@0 | 73 | { |
michael@0 | 74 | LoadPatternList(); |
michael@0 | 75 | LoadAliases(); |
michael@0 | 76 | } |
michael@0 | 77 | |
michael@0 | 78 | nsHyphenationManager::~nsHyphenationManager() |
michael@0 | 79 | { |
michael@0 | 80 | sInstance = nullptr; |
michael@0 | 81 | } |
michael@0 | 82 | |
michael@0 | 83 | already_AddRefed<nsHyphenator> |
michael@0 | 84 | nsHyphenationManager::GetHyphenator(nsIAtom *aLocale) |
michael@0 | 85 | { |
michael@0 | 86 | nsRefPtr<nsHyphenator> hyph; |
michael@0 | 87 | mHyphenators.Get(aLocale, getter_AddRefs(hyph)); |
michael@0 | 88 | if (hyph) { |
michael@0 | 89 | return hyph.forget(); |
michael@0 | 90 | } |
michael@0 | 91 | nsCOMPtr<nsIURI> uri = mPatternFiles.Get(aLocale); |
michael@0 | 92 | if (!uri) { |
michael@0 | 93 | nsCOMPtr<nsIAtom> alias = mHyphAliases.Get(aLocale); |
michael@0 | 94 | if (alias) { |
michael@0 | 95 | mHyphenators.Get(alias, getter_AddRefs(hyph)); |
michael@0 | 96 | if (hyph) { |
michael@0 | 97 | return hyph.forget(); |
michael@0 | 98 | } |
michael@0 | 99 | uri = mPatternFiles.Get(alias); |
michael@0 | 100 | if (uri) { |
michael@0 | 101 | aLocale = alias; |
michael@0 | 102 | } |
michael@0 | 103 | } |
michael@0 | 104 | if (!uri) { |
michael@0 | 105 | // In the case of a locale such as "de-DE-1996", we try replacing |
michael@0 | 106 | // successive trailing subtags with "-*" to find fallback patterns, |
michael@0 | 107 | // so "de-DE-1996" -> "de-DE-*" (and then recursively -> "de-*") |
michael@0 | 108 | nsAtomCString localeStr(aLocale); |
michael@0 | 109 | if (StringEndsWith(localeStr, NS_LITERAL_CSTRING("-*"))) { |
michael@0 | 110 | localeStr.Truncate(localeStr.Length() - 2); |
michael@0 | 111 | } |
michael@0 | 112 | int32_t i = localeStr.RFindChar('-'); |
michael@0 | 113 | if (i > 1) { |
michael@0 | 114 | localeStr.Replace(i, localeStr.Length() - i, "-*"); |
michael@0 | 115 | nsCOMPtr<nsIAtom> fuzzyLocale = do_GetAtom(localeStr); |
michael@0 | 116 | return GetHyphenator(fuzzyLocale); |
michael@0 | 117 | } else { |
michael@0 | 118 | return nullptr; |
michael@0 | 119 | } |
michael@0 | 120 | } |
michael@0 | 121 | } |
michael@0 | 122 | hyph = new nsHyphenator(uri); |
michael@0 | 123 | if (hyph->IsValid()) { |
michael@0 | 124 | mHyphenators.Put(aLocale, hyph); |
michael@0 | 125 | return hyph.forget(); |
michael@0 | 126 | } |
michael@0 | 127 | #ifdef DEBUG |
michael@0 | 128 | nsCString msg; |
michael@0 | 129 | uri->GetSpec(msg); |
michael@0 | 130 | msg.Insert("failed to load patterns from ", 0); |
michael@0 | 131 | NS_WARNING(msg.get()); |
michael@0 | 132 | #endif |
michael@0 | 133 | mPatternFiles.Remove(aLocale); |
michael@0 | 134 | return nullptr; |
michael@0 | 135 | } |
michael@0 | 136 | |
michael@0 | 137 | void |
michael@0 | 138 | nsHyphenationManager::LoadPatternList() |
michael@0 | 139 | { |
michael@0 | 140 | mPatternFiles.Clear(); |
michael@0 | 141 | mHyphenators.Clear(); |
michael@0 | 142 | |
michael@0 | 143 | LoadPatternListFromOmnijar(Omnijar::GRE); |
michael@0 | 144 | LoadPatternListFromOmnijar(Omnijar::APP); |
michael@0 | 145 | |
michael@0 | 146 | nsCOMPtr<nsIProperties> dirSvc = |
michael@0 | 147 | do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID); |
michael@0 | 148 | if (!dirSvc) { |
michael@0 | 149 | return; |
michael@0 | 150 | } |
michael@0 | 151 | |
michael@0 | 152 | nsresult rv; |
michael@0 | 153 | nsCOMPtr<nsIFile> greDir; |
michael@0 | 154 | rv = dirSvc->Get(NS_GRE_DIR, |
michael@0 | 155 | NS_GET_IID(nsIFile), getter_AddRefs(greDir)); |
michael@0 | 156 | if (NS_SUCCEEDED(rv)) { |
michael@0 | 157 | greDir->AppendNative(NS_LITERAL_CSTRING("hyphenation")); |
michael@0 | 158 | LoadPatternListFromDir(greDir); |
michael@0 | 159 | } |
michael@0 | 160 | |
michael@0 | 161 | nsCOMPtr<nsIFile> appDir; |
michael@0 | 162 | rv = dirSvc->Get(NS_XPCOM_CURRENT_PROCESS_DIR, |
michael@0 | 163 | NS_GET_IID(nsIFile), getter_AddRefs(appDir)); |
michael@0 | 164 | if (NS_SUCCEEDED(rv)) { |
michael@0 | 165 | appDir->AppendNative(NS_LITERAL_CSTRING("hyphenation")); |
michael@0 | 166 | bool equals; |
michael@0 | 167 | if (NS_SUCCEEDED(appDir->Equals(greDir, &equals)) && !equals) { |
michael@0 | 168 | LoadPatternListFromDir(appDir); |
michael@0 | 169 | } |
michael@0 | 170 | } |
michael@0 | 171 | } |
michael@0 | 172 | |
michael@0 | 173 | void |
michael@0 | 174 | nsHyphenationManager::LoadPatternListFromOmnijar(Omnijar::Type aType) |
michael@0 | 175 | { |
michael@0 | 176 | nsCString base; |
michael@0 | 177 | nsresult rv = Omnijar::GetURIString(aType, base); |
michael@0 | 178 | if (NS_FAILED(rv)) { |
michael@0 | 179 | return; |
michael@0 | 180 | } |
michael@0 | 181 | |
michael@0 | 182 | nsRefPtr<nsZipArchive> zip = Omnijar::GetReader(aType); |
michael@0 | 183 | if (!zip) { |
michael@0 | 184 | return; |
michael@0 | 185 | } |
michael@0 | 186 | |
michael@0 | 187 | nsZipFind *find; |
michael@0 | 188 | zip->FindInit("hyphenation/hyph_*.dic", &find); |
michael@0 | 189 | if (!find) { |
michael@0 | 190 | return; |
michael@0 | 191 | } |
michael@0 | 192 | |
michael@0 | 193 | const char *result; |
michael@0 | 194 | uint16_t len; |
michael@0 | 195 | while (NS_SUCCEEDED(find->FindNext(&result, &len))) { |
michael@0 | 196 | nsCString uriString(base); |
michael@0 | 197 | uriString.Append(result, len); |
michael@0 | 198 | nsCOMPtr<nsIURI> uri; |
michael@0 | 199 | rv = NS_NewURI(getter_AddRefs(uri), uriString); |
michael@0 | 200 | if (NS_FAILED(rv)) { |
michael@0 | 201 | continue; |
michael@0 | 202 | } |
michael@0 | 203 | nsCString locale; |
michael@0 | 204 | rv = uri->GetPath(locale); |
michael@0 | 205 | if (NS_FAILED(rv)) { |
michael@0 | 206 | continue; |
michael@0 | 207 | } |
michael@0 | 208 | ToLowerCase(locale); |
michael@0 | 209 | locale.SetLength(locale.Length() - 4); // strip ".dic" |
michael@0 | 210 | locale.Cut(0, locale.RFindChar('/') + 1); // strip directory |
michael@0 | 211 | if (StringBeginsWith(locale, NS_LITERAL_CSTRING("hyph_"))) { |
michael@0 | 212 | locale.Cut(0, 5); |
michael@0 | 213 | } |
michael@0 | 214 | for (uint32_t i = 0; i < locale.Length(); ++i) { |
michael@0 | 215 | if (locale[i] == '_') { |
michael@0 | 216 | locale.Replace(i, 1, '-'); |
michael@0 | 217 | } |
michael@0 | 218 | } |
michael@0 | 219 | nsCOMPtr<nsIAtom> localeAtom = do_GetAtom(locale); |
michael@0 | 220 | if (NS_SUCCEEDED(rv)) { |
michael@0 | 221 | mPatternFiles.Put(localeAtom, uri); |
michael@0 | 222 | } |
michael@0 | 223 | } |
michael@0 | 224 | |
michael@0 | 225 | delete find; |
michael@0 | 226 | } |
michael@0 | 227 | |
michael@0 | 228 | void |
michael@0 | 229 | nsHyphenationManager::LoadPatternListFromDir(nsIFile *aDir) |
michael@0 | 230 | { |
michael@0 | 231 | nsresult rv; |
michael@0 | 232 | |
michael@0 | 233 | bool check = false; |
michael@0 | 234 | rv = aDir->Exists(&check); |
michael@0 | 235 | if (NS_FAILED(rv) || !check) { |
michael@0 | 236 | return; |
michael@0 | 237 | } |
michael@0 | 238 | |
michael@0 | 239 | rv = aDir->IsDirectory(&check); |
michael@0 | 240 | if (NS_FAILED(rv) || !check) { |
michael@0 | 241 | return; |
michael@0 | 242 | } |
michael@0 | 243 | |
michael@0 | 244 | nsCOMPtr<nsISimpleEnumerator> e; |
michael@0 | 245 | rv = aDir->GetDirectoryEntries(getter_AddRefs(e)); |
michael@0 | 246 | if (NS_FAILED(rv)) { |
michael@0 | 247 | return; |
michael@0 | 248 | } |
michael@0 | 249 | |
michael@0 | 250 | nsCOMPtr<nsIDirectoryEnumerator> files(do_QueryInterface(e)); |
michael@0 | 251 | if (!files) { |
michael@0 | 252 | return; |
michael@0 | 253 | } |
michael@0 | 254 | |
michael@0 | 255 | nsCOMPtr<nsIFile> file; |
michael@0 | 256 | while (NS_SUCCEEDED(files->GetNextFile(getter_AddRefs(file))) && file){ |
michael@0 | 257 | nsAutoString dictName; |
michael@0 | 258 | file->GetLeafName(dictName); |
michael@0 | 259 | NS_ConvertUTF16toUTF8 locale(dictName); |
michael@0 | 260 | ToLowerCase(locale); |
michael@0 | 261 | if (!StringEndsWith(locale, NS_LITERAL_CSTRING(".dic"))) { |
michael@0 | 262 | continue; |
michael@0 | 263 | } |
michael@0 | 264 | if (StringBeginsWith(locale, NS_LITERAL_CSTRING("hyph_"))) { |
michael@0 | 265 | locale.Cut(0, 5); |
michael@0 | 266 | } |
michael@0 | 267 | locale.SetLength(locale.Length() - 4); // strip ".dic" |
michael@0 | 268 | for (uint32_t i = 0; i < locale.Length(); ++i) { |
michael@0 | 269 | if (locale[i] == '_') { |
michael@0 | 270 | locale.Replace(i, 1, '-'); |
michael@0 | 271 | } |
michael@0 | 272 | } |
michael@0 | 273 | #ifdef DEBUG_hyph |
michael@0 | 274 | printf("adding hyphenation patterns for %s: %s\n", locale.get(), |
michael@0 | 275 | NS_ConvertUTF16toUTF8(dictName).get()); |
michael@0 | 276 | #endif |
michael@0 | 277 | nsCOMPtr<nsIAtom> localeAtom = do_GetAtom(locale); |
michael@0 | 278 | nsCOMPtr<nsIURI> uri; |
michael@0 | 279 | nsresult rv = NS_NewFileURI(getter_AddRefs(uri), file); |
michael@0 | 280 | if (NS_SUCCEEDED(rv)) { |
michael@0 | 281 | mPatternFiles.Put(localeAtom, uri); |
michael@0 | 282 | } |
michael@0 | 283 | } |
michael@0 | 284 | } |
michael@0 | 285 | |
michael@0 | 286 | void |
michael@0 | 287 | nsHyphenationManager::LoadAliases() |
michael@0 | 288 | { |
michael@0 | 289 | nsIPrefBranch* prefRootBranch = Preferences::GetRootBranch(); |
michael@0 | 290 | if (!prefRootBranch) { |
michael@0 | 291 | return; |
michael@0 | 292 | } |
michael@0 | 293 | uint32_t prefCount; |
michael@0 | 294 | char **prefNames; |
michael@0 | 295 | nsresult rv = prefRootBranch->GetChildList(kIntlHyphenationAliasPrefix, |
michael@0 | 296 | &prefCount, &prefNames); |
michael@0 | 297 | if (NS_SUCCEEDED(rv) && prefCount > 0) { |
michael@0 | 298 | for (uint32_t i = 0; i < prefCount; ++i) { |
michael@0 | 299 | nsAdoptingCString value = Preferences::GetCString(prefNames[i]); |
michael@0 | 300 | if (value) { |
michael@0 | 301 | nsAutoCString alias(prefNames[i]); |
michael@0 | 302 | alias.Cut(0, sizeof(kIntlHyphenationAliasPrefix) - 1); |
michael@0 | 303 | ToLowerCase(alias); |
michael@0 | 304 | ToLowerCase(value); |
michael@0 | 305 | nsCOMPtr<nsIAtom> aliasAtom = do_GetAtom(alias); |
michael@0 | 306 | nsCOMPtr<nsIAtom> valueAtom = do_GetAtom(value); |
michael@0 | 307 | mHyphAliases.Put(aliasAtom, valueAtom); |
michael@0 | 308 | } |
michael@0 | 309 | } |
michael@0 | 310 | NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(prefCount, prefNames); |
michael@0 | 311 | } |
michael@0 | 312 | } |