blob: f947c4c86a9df5ffb45a8fcf0deac9b3d56684f9 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/common/extensions/api/speech/tts_engine_manifest_handler.h"
#include <stddef.h>
#include <memory>
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/manifest.h"
#include "extensions/common/manifest_constants.h"
#include "ui/base/l10n/l10n_util.h"
namespace extensions {
namespace keys = manifest_keys;
namespace errors = manifest_errors;
TtsVoice::TtsVoice() : remote(false) {}
TtsVoice::TtsVoice(const TtsVoice& other) = default;
TtsVoice::~TtsVoice() {}
TtsVoices::TtsVoices() {}
TtsVoices::~TtsVoices() {}
// static
bool TtsVoices::Parse(const base::ListValue* tts_voices,
TtsVoices* out_voices,
base::string16* error,
Extension* extension) {
bool added_gender_warning = false;
for (size_t i = 0; i < tts_voices->GetSize(); i++) {
const base::DictionaryValue* one_tts_voice = nullptr;
if (!tts_voices->GetDictionary(i, &one_tts_voice)) {
*error = base::ASCIIToUTF16(errors::kInvalidTtsVoices);
return false;
}
TtsVoice voice_data;
if (one_tts_voice->HasKey(keys::kTtsVoicesVoiceName)) {
if (!one_tts_voice->GetString(
keys::kTtsVoicesVoiceName, &voice_data.voice_name)) {
*error = base::ASCIIToUTF16(errors::kInvalidTtsVoicesVoiceName);
return false;
}
}
if (one_tts_voice->HasKey(keys::kTtsVoicesLang)) {
if (!one_tts_voice->GetString(
keys::kTtsVoicesLang, &voice_data.lang) ||
!l10n_util::IsValidLocaleSyntax(voice_data.lang)) {
*error = base::ASCIIToUTF16(errors::kInvalidTtsVoicesLang);
return false;
}
}
// TODO(katie): After M73, consider deprecating this installation warning,
// since the warning landed in M70 and gender was deprecated in M71.
if (one_tts_voice->HasKey(keys::kTtsVoicesGender) &&
!added_gender_warning) {
extension->AddInstallWarning(
InstallWarning(errors::kTtsGenderIsDeprecated));
// No need to add a warning for each voice, that's noisy.
added_gender_warning = true;
}
if (one_tts_voice->HasKey(keys::kTtsVoicesRemote)) {
if (!one_tts_voice->GetBoolean(
keys::kTtsVoicesRemote, &voice_data.remote)) {
*error = base::ASCIIToUTF16(errors::kInvalidTtsVoicesRemote);
return false;
}
}
if (one_tts_voice->HasKey(keys::kTtsVoicesEventTypes)) {
const base::ListValue* event_types_list;
if (!one_tts_voice->GetList(
keys::kTtsVoicesEventTypes,
&event_types_list)) {
*error = base::ASCIIToUTF16(
errors::kInvalidTtsVoicesEventTypes);
return false;
}
for (size_t i = 0; i < event_types_list->GetSize(); i++) {
std::string event_type;
if (!event_types_list->GetString(i, &event_type)) {
*error = base::ASCIIToUTF16(errors::kInvalidTtsVoicesEventTypes);
return false;
}
if (event_type != keys::kTtsVoicesEventTypeEnd &&
event_type != keys::kTtsVoicesEventTypeError &&
event_type != keys::kTtsVoicesEventTypeMarker &&
event_type != keys::kTtsVoicesEventTypeSentence &&
event_type != keys::kTtsVoicesEventTypeStart &&
event_type != keys::kTtsVoicesEventTypeWord) {
*error = base::ASCIIToUTF16(errors::kInvalidTtsVoicesEventTypes);
return false;
}
if (voice_data.event_types.find(event_type) !=
voice_data.event_types.end()) {
*error = base::ASCIIToUTF16(errors::kInvalidTtsVoicesEventTypes);
return false;
}
voice_data.event_types.insert(event_type);
}
}
out_voices->voices.push_back(voice_data);
}
return true;
}
// static
const std::vector<TtsVoice>* TtsVoices::GetTtsVoices(
const Extension* extension) {
TtsVoices* info =
static_cast<TtsVoices*>(extension->GetManifestData(keys::kTtsVoices));
return info ? &info->voices : nullptr;
}
TtsEngineManifestHandler::TtsEngineManifestHandler() {}
TtsEngineManifestHandler::~TtsEngineManifestHandler() {}
bool TtsEngineManifestHandler::Parse(Extension* extension,
base::string16* error) {
auto info = std::make_unique<TtsVoices>();
const base::DictionaryValue* tts_dict = nullptr;
if (!extension->manifest()->GetDictionary(keys::kTtsEngine, &tts_dict)) {
*error = base::ASCIIToUTF16(errors::kInvalidTts);
return false;
}
if (!tts_dict->HasKey(keys::kTtsVoices))
return true;
const base::ListValue* tts_voices = nullptr;
if (!tts_dict->GetList(keys::kTtsVoices, &tts_voices)) {
*error = base::ASCIIToUTF16(errors::kInvalidTtsVoices);
return false;
}
if (!TtsVoices::Parse(tts_voices, info.get(), error, extension))
return false;
extension->SetManifestData(keys::kTtsVoices, std::move(info));
return true;
}
base::span<const char* const> TtsEngineManifestHandler::Keys() const {
static constexpr const char* kKeys[] = {keys::kTtsEngine};
return kKeys;
}
} // namespace extensions