gecko-dev/intl/l10n/FileSource.cpp

196 lines
6.4 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "FileSource.h"
#include "mozilla/dom/Promise.h"
using namespace mozilla::dom;
namespace mozilla::intl {
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(L10nFileSource, mGlobal)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(L10nFileSource, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(L10nFileSource, Release)
L10nFileSource::L10nFileSource(RefPtr<const ffi::FileSource> aRaw,
nsIGlobalObject* aGlobal)
: mGlobal(aGlobal), mRaw(std::move(aRaw)) {}
/* static */
already_AddRefed<L10nFileSource> L10nFileSource::Constructor(
const GlobalObject& aGlobal, const nsACString& aName,
const nsACString& aMetaSource, const nsTArray<nsCString>& aLocales,
const nsACString& aPrePath, const dom::FileSourceOptions& aOptions,
const Optional<Sequence<nsCString>>& aIndex, ErrorResult& aRv) {
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
ffi::L10nFileSourceStatus status;
bool allowOverrides = aOptions.mAddResourceOptions.mAllowOverrides;
RefPtr<const ffi::FileSource> raw;
if (aIndex.WasPassed()) {
raw = dont_AddRef(ffi::l10nfilesource_new_with_index(
&aName, &aMetaSource, &aLocales, &aPrePath, aIndex.Value().Elements(),
aIndex.Value().Length(), allowOverrides, &status));
} else {
raw = dont_AddRef(ffi::l10nfilesource_new(
&aName, &aMetaSource, &aLocales, &aPrePath, allowOverrides, &status));
}
if (PopulateError(aRv, status)) {
return nullptr;
}
return MakeAndAddRef<L10nFileSource>(std::move(raw), global);
}
/* static */
already_AddRefed<L10nFileSource> L10nFileSource::CreateMock(
const GlobalObject& aGlobal, const nsACString& aName,
const nsACString& aMetaSource, const nsTArray<nsCString>& aLocales,
const nsACString& aPrePath, const nsTArray<L10nFileSourceMockFile>& aFS,
ErrorResult& aRv) {
nsTArray<ffi::L10nFileSourceMockFile> fs(aFS.Length());
for (const auto& file : aFS) {
auto f = fs.AppendElement();
f->path = file.mPath;
f->source = file.mSource;
}
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
ffi::L10nFileSourceStatus status;
RefPtr<const ffi::FileSource> raw(dont_AddRef(ffi::l10nfilesource_new_mock(
&aName, &aMetaSource, &aLocales, &aPrePath, &fs, &status)));
if (PopulateError(aRv, status)) {
return nullptr;
}
return MakeAndAddRef<L10nFileSource>(std::move(raw), global);
}
JSObject* L10nFileSource::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) {
return L10nFileSource_Binding::Wrap(aCx, this, aGivenProto);
}
void L10nFileSource::GetName(nsCString& aRetVal) {
ffi::l10nfilesource_get_name(mRaw.get(), &aRetVal);
}
void L10nFileSource::GetMetaSource(nsCString& aRetVal) {
ffi::l10nfilesource_get_metasource(mRaw.get(), &aRetVal);
}
void L10nFileSource::GetLocales(nsTArray<nsCString>& aRetVal) {
ffi::l10nfilesource_get_locales(mRaw.get(), &aRetVal);
}
void L10nFileSource::GetPrePath(nsCString& aRetVal) {
ffi::l10nfilesource_get_prepath(mRaw.get(), &aRetVal);
}
void L10nFileSource::GetIndex(Nullable<nsTArray<nsCString>>& aRetVal) {
bool hasIndex =
ffi::l10nfilesource_get_index(mRaw.get(), &aRetVal.SetValue());
if (!hasIndex) {
aRetVal.SetNull();
}
}
L10nFileSourceHasFileStatus L10nFileSource::HasFile(const nsACString& aLocale,
const nsACString& aPath,
ErrorResult& aRv) {
ffi::L10nFileSourceStatus status;
bool isPresent = false;
bool hasValue = ffi::l10nfilesource_has_file(mRaw.get(), &aLocale, &aPath,
&status, &isPresent);
if (!PopulateError(aRv, status) && hasValue) {
if (isPresent) {
return L10nFileSourceHasFileStatus::Present;
}
return L10nFileSourceHasFileStatus::Missing;
}
return L10nFileSourceHasFileStatus::Unknown;
}
already_AddRefed<FluentResource> L10nFileSource::FetchFileSync(
const nsACString& aLocale, const nsACString& aPath, ErrorResult& aRv) {
ffi::L10nFileSourceStatus status;
RefPtr<const ffi::FluentResource> raw =
dont_AddRef(ffi::l10nfilesource_fetch_file_sync(mRaw.get(), &aLocale,
&aPath, &status));
if (!PopulateError(aRv, status) && raw) {
return MakeAndAddRef<FluentResource>(mGlobal, raw);
}
return nullptr;
}
already_AddRefed<Promise> L10nFileSource::FetchFile(const nsACString& aLocale,
const nsACString& aPath,
ErrorResult& aRv) {
RefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
if (aRv.Failed()) {
return nullptr;
}
ffi::L10nFileSourceStatus status;
ffi::l10nfilesource_fetch_file(
mRaw.get(), &aLocale, &aPath, promise,
[](const Promise* aPromise, const ffi::FluentResource* aRes) {
Promise* promise = const_cast<Promise*>(aPromise);
if (aRes) {
nsIGlobalObject* global = promise->GetGlobalObject();
RefPtr<FluentResource> res = new FluentResource(global, aRes);
promise->MaybeResolve(res);
} else {
promise->MaybeResolve(JS::NullHandleValue);
}
},
&status);
if (PopulateError(aRv, status)) {
return nullptr;
}
return promise.forget();
}
/* static */
bool L10nFileSource::PopulateError(ErrorResult& aError,
ffi::L10nFileSourceStatus& aStatus) {
switch (aStatus) {
case ffi::L10nFileSourceStatus::InvalidLocaleCode:
aError.ThrowTypeError("Invalid locale code");
return true;
case ffi::L10nFileSourceStatus::EmptyName:
aError.ThrowTypeError("Name cannot be empty.");
return true;
case ffi::L10nFileSourceStatus::EmptyPrePath:
aError.ThrowTypeError("prePath cannot be empty.");
return true;
case ffi::L10nFileSourceStatus::EmptyResId:
aError.ThrowTypeError("resId cannot be empty.");
return true;
case ffi::L10nFileSourceStatus::None:
return false;
}
MOZ_ASSERT_UNREACHABLE("Unknown status");
return false;
}
} // namespace mozilla::intl