Localization.h (6746B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_intl_l10n_Localization_h 8 #define mozilla_intl_l10n_Localization_h 9 10 #include "nsCycleCollectionParticipant.h" 11 #include "nsIObserver.h" 12 #include "nsWeakReference.h" 13 #include "nsWrapperCache.h" 14 #include "nsWeakReference.h" 15 #include "nsIScriptError.h" 16 #include "nsContentUtils.h" 17 #include "nsPIDOMWindow.h" 18 #include "mozilla/ErrorResult.h" 19 #include "mozilla/dom/Promise.h" 20 #include "mozilla/dom/BindingDeclarations.h" 21 #include "mozilla/dom/LocalizationBinding.h" 22 #include "mozilla/intl/LocalizationBindings.h" 23 #include "mozilla/intl/L10nRegistry.h" 24 25 namespace mozilla { 26 namespace intl { 27 28 // The state where the application contains incomplete localization resources 29 // is much more common than for other types of core resources. 30 // 31 // In result, our localization is designed to handle missing resources 32 // gracefully, and we need a more fine-tuned way to communicate those problems 33 // to developers. 34 // 35 // In particular, we want developers and early adopters to be able to reason 36 // about missing translations, without bothering end user in production, where 37 // the user cannot react to that. 38 // 39 // We currently differentiate between nightly/dev-edition builds or automation 40 // where we report the errors, and beta/release, where we silence them. 41 // 42 // A side effect of the conditional model of strict vs loose error handling is 43 // that we don't have a way to write integration tests for behavior we expect 44 // out of production environment. See bug 1741430. 45 [[maybe_unused]] static bool MaybeReportErrorsToGecko( 46 const nsTArray<nsCString>& aErrors, ErrorResult& aRv, 47 nsIGlobalObject* aGlobal) { 48 if (!aErrors.IsEmpty()) { 49 // See tor-browser#41285 50 #if defined(NIGHTLY_BUILD) || defined(MOZ_DEV_EDITION) || defined(DEBUG) || \ 51 defined(TOR_BROWSER_NIGHTLY_BUILD) 52 dom::Document* doc = nullptr; 53 if (aGlobal) { 54 nsPIDOMWindowInner* innerWindow = aGlobal->GetAsInnerWindow(); 55 if (innerWindow) { 56 doc = innerWindow->GetExtantDoc(); 57 } 58 } 59 60 for (const auto& error : aErrors) { 61 nsContentUtils::ReportToConsoleNonLocalized(NS_ConvertUTF8toUTF16(error), 62 nsIScriptError::warningFlag, 63 "l10n"_ns, doc); 64 printf_stderr("%s\n", error.get()); 65 } 66 #endif 67 68 if (xpc::IsInAutomation()) { 69 aRv.ThrowInvalidStateError(aErrors.ElementAt(0)); 70 return true; 71 } 72 } 73 74 return false; 75 } 76 77 class Localization : public nsIObserver, 78 public nsWrapperCache, 79 public nsSupportsWeakReference { 80 template <typename T, typename... Args> 81 friend already_AddRefed<T> mozilla::MakeAndAddRef(Args&&... aArgs); 82 83 public: 84 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 85 NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS_AMBIGUOUS(Localization, 86 nsIObserver) 87 NS_DECL_NSIOBSERVER 88 89 static bool IsAPIEnabled(JSContext* aCx, JSObject* aObject); 90 91 static already_AddRefed<Localization> Constructor( 92 const dom::GlobalObject& aGlobal, 93 const dom::Sequence<dom::OwningUTF8StringOrResourceId>& aResourceIds, 94 bool aIsSync, const dom::Optional<dom::NonNull<L10nRegistry>>& aRegistry, 95 const dom::Optional<dom::Sequence<nsCString>>& aLocales, 96 ErrorResult& aRv); 97 static already_AddRefed<Localization> Create( 98 const nsTArray<nsCString>& aResourceIds, bool aIsSync); 99 static already_AddRefed<Localization> Create( 100 const nsTArray<nsCString>& aResourceIds, bool aIsSync, 101 const nsTArray<nsCString>& aLocales); 102 static already_AddRefed<Localization> Create( 103 const nsTArray<ffi::GeckoResourceId>& aResourceIds, bool aIsSync); 104 105 JSObject* WrapObject(JSContext* aCx, 106 JS::Handle<JSObject*> aGivenProto) override; 107 nsIGlobalObject* GetParentObject() const { return mGlobal; } 108 109 void SetIsSync(bool aIsSync); 110 111 already_AddRefed<dom::Promise> FormatValue( 112 const nsACString& aId, const dom::Optional<L10nArgs>& aArgs, 113 ErrorResult& aRv); 114 115 already_AddRefed<dom::Promise> FormatValues( 116 const dom::Sequence<dom::OwningUTF8StringOrL10nIdArgs>& aKeys, 117 ErrorResult& aRv); 118 119 already_AddRefed<dom::Promise> FormatMessages( 120 const dom::Sequence<dom::OwningUTF8StringOrL10nIdArgs>& aKeys, 121 ErrorResult& aRv); 122 123 void FormatValueSync(const nsACString& aId, 124 const dom::Optional<L10nArgs>& aArgs, 125 nsACString& aRetVal, ErrorResult& aRv); 126 void FormatValuesSync( 127 const dom::Sequence<dom::OwningUTF8StringOrL10nIdArgs>& aKeys, 128 nsTArray<nsCString>& aRetVal, ErrorResult& aRv); 129 void FormatMessagesSync( 130 const dom::Sequence<dom::OwningUTF8StringOrL10nIdArgs>& aKeys, 131 nsTArray<dom::Nullable<dom::L10nMessage>>& aRetVal, ErrorResult& aRv); 132 133 void AddResourceId(const ffi::GeckoResourceId& aResourceId); 134 void AddResourceId(const nsCString& aResourceId); 135 void AddResourceId(const dom::OwningUTF8StringOrResourceId& aResourceId); 136 uint32_t RemoveResourceId(const ffi::GeckoResourceId& aResourceId); 137 uint32_t RemoveResourceId(const nsCString& aResourceId); 138 uint32_t RemoveResourceId( 139 const dom::OwningUTF8StringOrResourceId& aResourceId); 140 void AddResourceIds( 141 const nsTArray<dom::OwningUTF8StringOrResourceId>& aResourceIds); 142 uint32_t RemoveResourceIds( 143 const nsTArray<dom::OwningUTF8StringOrResourceId>& aResourceIds); 144 145 void SetAsync(); 146 bool IsSync(); 147 148 protected: 149 Localization(const nsTArray<nsCString>& aResIds, bool aIsSync); 150 Localization(const nsTArray<nsCString>& aResIds, bool aIsSync, 151 const nsTArray<nsCString>& aLocales); 152 Localization(const nsTArray<ffi::GeckoResourceId>& aResIds, bool aIsSync); 153 Localization(nsIGlobalObject* aGlobal, bool aIsSync); 154 155 Localization(nsIGlobalObject* aGlobal, const nsTArray<nsCString>& aResIds, 156 bool aIsSync); 157 158 Localization(nsIGlobalObject* aGlobal, bool aIsSync, 159 const ffi::LocalizationRc* aRaw); 160 161 Localization(nsIGlobalObject* aGlobal, bool aIsSync, 162 const nsTArray<nsCString>& aLocales); 163 164 virtual ~Localization(); 165 166 void RegisterObservers(); 167 virtual void OnChange(); 168 already_AddRefed<dom::Promise> MaybeWrapPromise(dom::Promise* aInnerPromise); 169 170 nsCOMPtr<nsIGlobalObject> mGlobal; 171 RefPtr<const ffi::LocalizationRc> mRaw; 172 }; 173 174 } // namespace intl 175 } // namespace mozilla 176 177 #endif