LCOV - code coverage report
Current view: top level - intl/locale - LocaleService.h (source / functions) Hit Total Coverage
Test: output.info Lines: 11 11 100.0 %
Date: 2017-07-14 16:53:18 Functions: 5 5 100.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             : #ifndef mozilla_intl_LocaleService_h__
       7             : #define mozilla_intl_LocaleService_h__
       8             : 
       9             : #include "nsIObserver.h"
      10             : #include "nsString.h"
      11             : #include "nsTArray.h"
      12             : 
      13             : #include "mozILocaleService.h"
      14             : 
      15             : namespace mozilla {
      16             : namespace intl {
      17             : 
      18             : /**
      19             :  * LocaleService is a manager of language negotiation in Gecko.
      20             :  *
      21             :  * It's intended to be the core place for collecting available and
      22             :  * requested languages and negotiating them to produce a fallback
      23             :  * chain of locales for the application.
      24             :  *
      25             :  * Client / Server
      26             :  *
      27             :  * LocaleService may operate in one of two modes:
      28             :  *
      29             :  *   server
      30             :  *     in the server mode, LocaleService is collecting and negotiating
      31             :  *     languages. It also subscribes to relevant observers.
      32             :  *     There should be at most one server per application instance.
      33             :  *
      34             :  *   client
      35             :  *     in the client mode, LocaleService is not responsible for collecting
      36             :  *     or reacting to any system changes. It still distributes information
      37             :  *     about locales, but internally, it gets information from the server instance
      38             :  *     instead of collecting it on its own.
      39             :  *     This prevents any data desynchronization and minimizes the cost
      40             :  *     of running the service.
      41             :  *
      42             :  *   In both modes, all get* methods should work the same way and all
      43             :  *   static methods are available.
      44             :  *
      45             :  *   In the server mode, other components may inform LocaleService about their
      46             :  *   status either via calls to set* methods or via observer events.
      47             :  *   In the client mode, only the process communication should provide data
      48             :  *   to the LocaleService.
      49             :  *
      50             :  *   At the moment desktop apps use the parent process in the server mode, and
      51             :  *   content processes in the client mode.
      52             :  *
      53             :  * Locale / Language
      54             :  *
      55             :  * The terms `Locale ID` and `Language ID` are used slightly differently
      56             :  * by different organizations. Mozilla uses the term `Language ID` to describe
      57             :  * a string that contains information about the language itself, script,
      58             :  * region and variant. For example "en-Latn-US-mac" is a correct Language ID.
      59             :  *
      60             :  * Locale ID contains a Language ID plus a number of extension tags that
      61             :  * contain information that go beyond language inforamation such as
      62             :  * preferred currency, date/time formatting etc.
      63             :  *
      64             :  * An example of a Locale ID is `en-Latn-US-x-hc-h12-ca-gregory`
      65             :  *
      66             :  * At the moment we do not support full extension tag system, but we
      67             :  * try to be specific when naming APIs, so the service is for locales,
      68             :  * but we negotiate between languages etc.
      69             :  */
      70             : class LocaleService : public mozILocaleService,
      71             :                       public nsIObserver
      72             : {
      73             : public:
      74             :   NS_DECL_ISUPPORTS
      75             :   NS_DECL_NSIOBSERVER
      76             :   NS_DECL_MOZILOCALESERVICE
      77             : 
      78             :   /**
      79             :    * List of available language negotiation strategies.
      80             :    *
      81             :    * See the mozILocaleService.idl for detailed description of the
      82             :    * strategies.
      83             :    */
      84             :   enum class LangNegStrategy {
      85             :     Filtering,
      86             :     Matching,
      87             :     Lookup
      88             :   };
      89             : 
      90             :   explicit LocaleService(bool aIsServer);
      91             : 
      92             :   /**
      93             :    * Create (if necessary) and return a raw pointer to the singleton instance.
      94             :    * Use this accessor in C++ code that just wants to call a method on the
      95             :    * instance, but does not need to hold a reference, as in
      96             :    *    nsAutoCString str;
      97             :    *    LocaleService::GetInstance()->GetAppLocaleAsLangTag(str);
      98             :    */
      99             :   static LocaleService* GetInstance();
     100             : 
     101             :   /**
     102             :    * Return an addRef'd pointer to the singleton instance. This is used by the
     103             :    * XPCOM constructor that exists to support usage from JS.
     104             :    */
     105           1 :   static already_AddRefed<LocaleService> GetInstanceAddRefed()
     106             :   {
     107           1 :     return RefPtr<LocaleService>(GetInstance()).forget();
     108             :   }
     109             : 
     110             :   /**
     111             :    * Returns a list of locales that the application should be localized to.
     112             :    *
     113             :    * The result is a ordered list of valid locale IDs and it should be
     114             :    * used for all APIs that accept list of locales, like ECMA402 and L10n APIs.
     115             :    *
     116             :    * This API always returns at least one locale.
     117             :    *
     118             :    * Example: ["en-US", "de", "pl", "sr-Cyrl", "zh-Hans-HK"]
     119             :    *
     120             :    * Usage:
     121             :    *   nsTArray<nsCString> appLocales;
     122             :    *   LocaleService::GetInstance()->GetAppLocalesAsLangTags(appLocales);
     123             :    *
     124             :    * (See mozILocaleService.idl for a JS-callable version of this.)
     125             :    */
     126             :   void GetAppLocalesAsLangTags(nsTArray<nsCString>& aRetVal);
     127             :   void GetAppLocalesAsBCP47(nsTArray<nsCString>& aRetVal);
     128             : 
     129             : 
     130             :   /**
     131             :    * Returns a list of locales to use for any regional specific operations
     132             :    * like date formatting, calendars, unit formatting etc.
     133             :    *
     134             :    * The result is a ordered list of valid locale IDs and it should be
     135             :    * used for all APIs that accept list of locales, like ECMA402 and L10n APIs.
     136             :    *
     137             :    * This API always returns at least one locale.
     138             :    *
     139             :    * Example: ["en-US", "de", "pl", "sr-Cyrl", "zh-Hans-HK"]
     140             :    *
     141             :    * Usage:
     142             :    *   nsTArray<nsCString> rgLocales;
     143             :    *   LocaleService::GetInstance()->GetRegionalPrefsLocales(rgLocales);
     144             :    *
     145             :    * (See mozILocaleService.idl for a JS-callable version of this.)
     146             :    */
     147             :   void GetRegionalPrefsLocales(nsTArray<nsCString>& aRetVal);
     148             : 
     149             :   /**
     150             :    * This method should only be called in the client mode.
     151             :    *
     152             :    * It replaces all the language negotiation and is supposed to be called
     153             :    * in order to bring the client LocaleService in sync with the server
     154             :    * LocaleService.
     155             :    *
     156             :    * Currently, it's called by the IPC code.
     157             :    */
     158             :   void AssignAppLocales(const nsTArray<nsCString>& aAppLocales);
     159             :   void AssignRequestedLocales(const nsTArray<nsCString>& aRequestedLocales);
     160             : 
     161             :   /**
     162             :    * Returns a list of locales that the user requested the app to be
     163             :    * localized to.
     164             :    *
     165             :    * The result is a sorted list of valid locale IDs and it should be
     166             :    * used as a requestedLocales input list for languages negotiation.
     167             :    *
     168             :    * Example: ["en-US", "de", "pl", "sr-Cyrl", "zh-Hans-HK"]
     169             :    *
     170             :    * Usage:
     171             :    *   nsTArray<nsCString> reqLocales;
     172             :    *   LocaleService::GetInstance()->GetRequestedLocales(reqLocales);
     173             :    *
     174             :    * Returns a boolean indicating if the attempt to retrieve prefs
     175             :    * was successful.
     176             :    *
     177             :    * (See mozILocaleService.idl for a JS-callable version of this.)
     178             :    */
     179             :   bool GetRequestedLocales(nsTArray<nsCString>& aRetVal);
     180             : 
     181             :   /**
     182             :    * Returns a list of available locales that can be used to
     183             :    * localize the app.
     184             :    *
     185             :    * The result is an unsorted list of valid locale IDs and it should be
     186             :    * used as a availableLocales input list for languages negotiation.
     187             :    *
     188             :    * Example: ["de", "en-US", "pl", "sr-Cyrl", "zh-Hans-HK"]
     189             :    *
     190             :    * Usage:
     191             :    *   nsTArray<nsCString> availLocales;
     192             :    *   LocaleService::GetInstance()->GetAvailableLocales(availLocales);
     193             :    *
     194             :    * Returns a boolean indicating if the attempt to retrieve at least
     195             :    * one locale was successful.
     196             :    *
     197             :    * (See mozILocaleService.idl for a JS-callable version of this.)
     198             :    */
     199             :   bool GetAvailableLocales(nsTArray<nsCString>& aRetVal);
     200             : 
     201             :   /**
     202             :    * Those three functions allow to trigger cache invalidation on one of the
     203             :    * three cached values.
     204             :    *
     205             :    * In most cases, the functions will be called by the observer in
     206             :    * LocaleService itself, but in a couple special cases, we have the
     207             :    * other component call this manually instead of sending a global event.
     208             :    *
     209             :    * If the result differs from the previous list, it will additionally
     210             :    * trigger a corresponding event
     211             :    *
     212             :    * This code should be called only in the server mode..
     213             :    */
     214             :   void OnAvailableLocalesChanged();
     215             :   void OnRequestedLocalesChanged();
     216             :   void OnLocalesChanged();
     217             : 
     218             :   /**
     219             :    * Negotiates the best locales out of an ordered list of requested locales and
     220             :    * a list of available locales.
     221             :    *
     222             :    * Internally it uses the following naming scheme:
     223             :    *
     224             :    *  Requested - locales requested by the user
     225             :    *  Available - locales for which the data is available
     226             :    *  Supported - locales negotiated by the algorithm
     227             :    *
     228             :    * Additionally, if defaultLocale is provided, it adds it to the end of the
     229             :    * result list as a "last resort" locale.
     230             :    *
     231             :    * Strategy is one of the three strategies described at the top of this file.
     232             :    *
     233             :    * The result list is ordered according to the order of the requested locales.
     234             :    *
     235             :    * (See mozILocaleService.idl for a JS-callable version of this.)
     236             :    */
     237             :   bool NegotiateLanguages(const nsTArray<nsCString>& aRequested,
     238             :                           const nsTArray<nsCString>& aAvailable,
     239             :                           const nsACString& aDefaultLocale,
     240             :                           LangNegStrategy aLangNegStrategy,
     241             :                           nsTArray<nsCString>& aRetVal);
     242             : 
     243             :   /**
     244             :    * Returns whether the current app locale is RTL.
     245             :    */
     246             :   bool IsAppLocaleRTL();
     247             : 
     248             :   static bool LanguagesMatch(const nsCString& aRequested,
     249             :                              const nsCString& aAvailable);
     250             : 
     251             :   bool IsServer();
     252             : 
     253             : private:
     254             :   /**
     255             :    * Locale object, a BCP47-style tag decomposed into subtags for
     256             :    * matching purposes.
     257             :    *
     258             :    * If constructed with aRange = true, any missing subtags will be
     259             :    * set to "*".
     260             :    */
     261           7 :   class Locale
     262             :   {
     263             :   public:
     264             :     Locale(const nsCString& aLocale, bool aRange);
     265             : 
     266             :     bool Matches(const Locale& aLocale) const;
     267             :     bool LanguageMatches(const Locale& aLocale) const;
     268             : 
     269             :     void SetVariantRange();
     270             :     void SetRegionRange();
     271             : 
     272             :     bool AddLikelySubtags(); // returns false if nothing changed
     273             : 
     274           2 :     const nsCString& AsString() const {
     275           2 :       return mLocaleStr;
     276             :     }
     277             : 
     278           2 :     bool operator== (const Locale& aOther) {
     279           2 :       const auto& cmp = nsCaseInsensitiveCStringComparator();
     280           4 :       return mLanguage.Equals(aOther.mLanguage, cmp) &&
     281           2 :              mScript.Equals(aOther.mScript, cmp) &&
     282           2 :              mRegion.Equals(aOther.mRegion, cmp) &&
     283           2 :              mVariant.Equals(aOther.mVariant, cmp);
     284             :     }
     285             : 
     286             :   private:
     287             :     const nsCString& mLocaleStr;
     288             :     nsCString mLanguage;
     289             :     nsCString mScript;
     290             :     nsCString mRegion;
     291             :     nsCString mVariant;
     292             :   };
     293             : 
     294             :   void FilterMatches(const nsTArray<nsCString>& aRequested,
     295             :                      const nsTArray<nsCString>& aAvailable,
     296             :                      LangNegStrategy aStrategy,
     297             :                      nsTArray<nsCString>& aRetVal);
     298             : 
     299             :   void NegotiateAppLocales(nsTArray<nsCString>& aRetVal);
     300             : 
     301             :   virtual ~LocaleService();
     302             : 
     303             :   nsTArray<nsCString> mAppLocales;
     304             :   nsTArray<nsCString> mRequestedLocales;
     305             :   nsTArray<nsCString> mAvailableLocales;
     306             :   const bool mIsServer;
     307             : 
     308             :   static StaticRefPtr<LocaleService> sInstance;
     309             : };
     310             : } // intl
     311             : } // namespace mozilla
     312             : 
     313             : #endif /* mozilla_intl_LocaleService_h__ */

Generated by: LCOV version 1.13