1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/common/extensions/api/speech/tts_engine_manifest_handler.h"
6
7#include "base/memory/scoped_ptr.h"
8#include "base/strings/string_number_conversions.h"
9#include "base/strings/utf_string_conversions.h"
10#include "base/values.h"
11#include "extensions/common/error_utils.h"
12#include "extensions/common/manifest.h"
13#include "extensions/common/manifest_constants.h"
14#include "ui/base/l10n/l10n_util.h"
15
16namespace extensions {
17
18namespace keys = manifest_keys;
19namespace errors = manifest_errors;
20
21namespace {
22
23struct TtsVoices : public Extension::ManifestData {
24  TtsVoices() {}
25  virtual ~TtsVoices() {}
26
27  std::vector<extensions::TtsVoice> voices;
28};
29
30}  // namespace
31
32TtsVoice::TtsVoice() : remote(false) {}
33
34TtsVoice::~TtsVoice() {}
35
36// static
37const std::vector<TtsVoice>* TtsVoice::GetTtsVoices(
38    const Extension* extension) {
39  TtsVoices* info = static_cast<TtsVoices*>(
40      extension->GetManifestData(keys::kTtsVoices));
41  return info ? &info->voices : NULL;
42}
43
44TtsEngineManifestHandler::TtsEngineManifestHandler() {
45}
46
47TtsEngineManifestHandler::~TtsEngineManifestHandler() {
48}
49
50bool TtsEngineManifestHandler::Parse(Extension* extension,
51                                     base::string16* error) {
52  scoped_ptr<TtsVoices> info(new TtsVoices);
53  const base::DictionaryValue* tts_dict = NULL;
54  if (!extension->manifest()->GetDictionary(keys::kTtsEngine, &tts_dict)) {
55    *error = base::ASCIIToUTF16(errors::kInvalidTts);
56    return false;
57  }
58
59  if (!tts_dict->HasKey(keys::kTtsVoices))
60    return true;
61
62  const base::ListValue* tts_voices = NULL;
63  if (!tts_dict->GetList(keys::kTtsVoices, &tts_voices)) {
64    *error = base::ASCIIToUTF16(errors::kInvalidTtsVoices);
65    return false;
66  }
67
68  for (size_t i = 0; i < tts_voices->GetSize(); i++) {
69    const base::DictionaryValue* one_tts_voice = NULL;
70    if (!tts_voices->GetDictionary(i, &one_tts_voice)) {
71      *error = base::ASCIIToUTF16(errors::kInvalidTtsVoices);
72      return false;
73    }
74
75    TtsVoice voice_data;
76    if (one_tts_voice->HasKey(keys::kTtsVoicesVoiceName)) {
77      if (!one_tts_voice->GetString(
78              keys::kTtsVoicesVoiceName, &voice_data.voice_name)) {
79        *error = base::ASCIIToUTF16(errors::kInvalidTtsVoicesVoiceName);
80        return false;
81      }
82    }
83    if (one_tts_voice->HasKey(keys::kTtsVoicesLang)) {
84      if (!one_tts_voice->GetString(
85              keys::kTtsVoicesLang, &voice_data.lang) ||
86          !l10n_util::IsValidLocaleSyntax(voice_data.lang)) {
87        *error = base::ASCIIToUTF16(errors::kInvalidTtsVoicesLang);
88        return false;
89      }
90    }
91    if (one_tts_voice->HasKey(keys::kTtsVoicesGender)) {
92      if (!one_tts_voice->GetString(
93              keys::kTtsVoicesGender, &voice_data.gender) ||
94          (voice_data.gender != keys::kTtsGenderMale &&
95           voice_data.gender != keys::kTtsGenderFemale)) {
96        *error = base::ASCIIToUTF16(errors::kInvalidTtsVoicesGender);
97        return false;
98      }
99    }
100    if (one_tts_voice->HasKey(keys::kTtsVoicesRemote)) {
101      if (!one_tts_voice->GetBoolean(
102              keys::kTtsVoicesRemote, &voice_data.remote)) {
103        *error = base::ASCIIToUTF16(errors::kInvalidTtsVoicesRemote);
104        return false;
105      }
106    }
107    if (one_tts_voice->HasKey(keys::kTtsVoicesEventTypes)) {
108      const base::ListValue* event_types_list;
109      if (!one_tts_voice->GetList(
110              keys::kTtsVoicesEventTypes,
111              &event_types_list)) {
112        *error = base::ASCIIToUTF16(
113            errors::kInvalidTtsVoicesEventTypes);
114        return false;
115      }
116      for (size_t i = 0; i < event_types_list->GetSize(); i++) {
117        std::string event_type;
118        if (!event_types_list->GetString(i, &event_type)) {
119          *error = base::ASCIIToUTF16(errors::kInvalidTtsVoicesEventTypes);
120          return false;
121        }
122        if (event_type != keys::kTtsVoicesEventTypeEnd &&
123            event_type != keys::kTtsVoicesEventTypeError &&
124            event_type != keys::kTtsVoicesEventTypeMarker &&
125            event_type != keys::kTtsVoicesEventTypeSentence &&
126            event_type != keys::kTtsVoicesEventTypeStart &&
127            event_type != keys::kTtsVoicesEventTypeWord) {
128          *error = base::ASCIIToUTF16(errors::kInvalidTtsVoicesEventTypes);
129          return false;
130        }
131        if (voice_data.event_types.find(event_type) !=
132            voice_data.event_types.end()) {
133          *error = base::ASCIIToUTF16(errors::kInvalidTtsVoicesEventTypes);
134          return false;
135        }
136        voice_data.event_types.insert(event_type);
137      }
138    }
139
140    info->voices.push_back(voice_data);
141  }
142
143  extension->SetManifestData(keys::kTtsVoices, info.release());
144  return true;
145}
146
147const std::vector<std::string> TtsEngineManifestHandler::Keys() const {
148  return SingleKey(keys::kTtsEngine);
149}
150
151}  // namespace extensions
152