LCOV - code coverage report
Current view: top level - intl/hyphenation/glue - nsHyphenationManager.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 171 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 13 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13