FileSource.cpp (6450B)
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 #include "FileSource.h" 8 #include "mozilla/dom/Promise.h" 9 10 using namespace mozilla::dom; 11 12 namespace mozilla::intl { 13 14 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(L10nFileSource, mGlobal) 15 16 L10nFileSource::L10nFileSource(RefPtr<const ffi::FileSource> aRaw, 17 nsIGlobalObject* aGlobal) 18 : mGlobal(aGlobal), mRaw(std::move(aRaw)) {} 19 20 /* static */ 21 already_AddRefed<L10nFileSource> L10nFileSource::Constructor( 22 const GlobalObject& aGlobal, const nsACString& aName, 23 const nsACString& aMetaSource, const nsTArray<nsCString>& aLocales, 24 const nsACString& aPrePath, const dom::FileSourceOptions& aOptions, 25 const Optional<Sequence<nsCString>>& aIndex, ErrorResult& aRv) { 26 nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports()); 27 28 ffi::L10nFileSourceStatus status; 29 30 bool allowOverrides = aOptions.mAddResourceOptions.mAllowOverrides; 31 32 RefPtr<const ffi::FileSource> raw; 33 if (aIndex.WasPassed()) { 34 raw = dont_AddRef(ffi::l10nfilesource_new_with_index( 35 &aName, &aMetaSource, &aLocales, &aPrePath, aIndex.Value().Elements(), 36 aIndex.Value().Length(), allowOverrides, &status)); 37 } else { 38 raw = dont_AddRef(ffi::l10nfilesource_new( 39 &aName, &aMetaSource, &aLocales, &aPrePath, allowOverrides, &status)); 40 } 41 42 if (PopulateError(aRv, status)) { 43 return nullptr; 44 } 45 return MakeAndAddRef<L10nFileSource>(std::move(raw), global); 46 } 47 48 /* static */ 49 already_AddRefed<L10nFileSource> L10nFileSource::CreateMock( 50 const GlobalObject& aGlobal, const nsACString& aName, 51 const nsACString& aMetaSource, const nsTArray<nsCString>& aLocales, 52 const nsACString& aPrePath, const nsTArray<L10nFileSourceMockFile>& aFS, 53 ErrorResult& aRv) { 54 nsTArray<ffi::L10nFileSourceMockFile> fs(aFS.Length()); 55 for (const auto& file : aFS) { 56 auto f = fs.AppendElement(); 57 f->path = file.mPath; 58 f->source = file.mSource; 59 } 60 nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports()); 61 62 ffi::L10nFileSourceStatus status; 63 64 RefPtr<const ffi::FileSource> raw(dont_AddRef(ffi::l10nfilesource_new_mock( 65 &aName, &aMetaSource, &aLocales, &aPrePath, &fs, &status))); 66 67 if (PopulateError(aRv, status)) { 68 return nullptr; 69 } 70 return MakeAndAddRef<L10nFileSource>(std::move(raw), global); 71 } 72 73 JSObject* L10nFileSource::WrapObject(JSContext* aCx, 74 JS::Handle<JSObject*> aGivenProto) { 75 return L10nFileSource_Binding::Wrap(aCx, this, aGivenProto); 76 } 77 78 void L10nFileSource::GetName(nsCString& aRetVal) { 79 ffi::l10nfilesource_get_name(mRaw.get(), &aRetVal); 80 } 81 82 void L10nFileSource::GetMetaSource(nsCString& aRetVal) { 83 ffi::l10nfilesource_get_metasource(mRaw.get(), &aRetVal); 84 } 85 86 void L10nFileSource::GetLocales(nsTArray<nsCString>& aRetVal) { 87 ffi::l10nfilesource_get_locales(mRaw.get(), &aRetVal); 88 } 89 90 void L10nFileSource::GetPrePath(nsCString& aRetVal) { 91 ffi::l10nfilesource_get_prepath(mRaw.get(), &aRetVal); 92 } 93 94 void L10nFileSource::GetIndex(Nullable<nsTArray<nsCString>>& aRetVal) { 95 bool hasIndex = 96 ffi::l10nfilesource_get_index(mRaw.get(), &aRetVal.SetValue()); 97 if (!hasIndex) { 98 aRetVal.SetNull(); 99 } 100 } 101 102 L10nFileSourceHasFileStatus L10nFileSource::HasFile(const nsACString& aLocale, 103 const nsACString& aPath, 104 ErrorResult& aRv) { 105 ffi::L10nFileSourceStatus status; 106 107 bool isPresent = false; 108 bool hasValue = ffi::l10nfilesource_has_file(mRaw.get(), &aLocale, &aPath, 109 &status, &isPresent); 110 111 if (!PopulateError(aRv, status) && hasValue) { 112 if (isPresent) { 113 return L10nFileSourceHasFileStatus::Present; 114 } 115 116 return L10nFileSourceHasFileStatus::Missing; 117 } 118 return L10nFileSourceHasFileStatus::Unknown; 119 } 120 121 already_AddRefed<FluentResource> L10nFileSource::FetchFileSync( 122 const nsACString& aLocale, const nsACString& aPath, ErrorResult& aRv) { 123 ffi::L10nFileSourceStatus status; 124 125 RefPtr<const ffi::FluentResource> raw = 126 dont_AddRef(ffi::l10nfilesource_fetch_file_sync(mRaw.get(), &aLocale, 127 &aPath, &status)); 128 129 if (!PopulateError(aRv, status) && raw) { 130 return MakeAndAddRef<FluentResource>(mGlobal, raw); 131 } 132 133 return nullptr; 134 } 135 136 already_AddRefed<Promise> L10nFileSource::FetchFile(const nsACString& aLocale, 137 const nsACString& aPath, 138 ErrorResult& aRv) { 139 RefPtr<Promise> promise = Promise::Create(mGlobal, aRv); 140 if (aRv.Failed()) { 141 return nullptr; 142 } 143 144 ffi::L10nFileSourceStatus status; 145 146 ffi::l10nfilesource_fetch_file( 147 mRaw.get(), &aLocale, &aPath, promise, 148 [](const Promise* aPromise, const ffi::FluentResource* aRes) { 149 Promise* promise = const_cast<Promise*>(aPromise); 150 151 if (aRes) { 152 nsIGlobalObject* global = promise->GetGlobalObject(); 153 RefPtr<FluentResource> res = new FluentResource(global, aRes); 154 promise->MaybeResolve(res); 155 } else { 156 promise->MaybeResolve(JS::NullHandleValue); 157 } 158 }, 159 &status); 160 161 if (PopulateError(aRv, status)) { 162 return nullptr; 163 } 164 165 return promise.forget(); 166 } 167 168 /* static */ 169 bool L10nFileSource::PopulateError(ErrorResult& aError, 170 ffi::L10nFileSourceStatus& aStatus) { 171 switch (aStatus) { 172 case ffi::L10nFileSourceStatus::InvalidLocaleCode: 173 aError.ThrowTypeError("Invalid locale code"); 174 return true; 175 case ffi::L10nFileSourceStatus::EmptyName: 176 aError.ThrowTypeError("Name cannot be empty."); 177 return true; 178 case ffi::L10nFileSourceStatus::EmptyPrePath: 179 aError.ThrowTypeError("prePath cannot be empty."); 180 return true; 181 case ffi::L10nFileSourceStatus::EmptyResId: 182 aError.ThrowTypeError("resId cannot be empty."); 183 return true; 184 185 case ffi::L10nFileSourceStatus::None: 186 return false; 187 } 188 MOZ_ASSERT_UNREACHABLE("Unknown status"); 189 return false; 190 } 191 192 } // namespace mozilla::intl