Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(277)

Side by Side Diff: chrome/browser/extensions/extension_tts_engine_api.cc

Issue 9808024: Move TTS extension API to chrome/browser/speech/ (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix chromeos compile error, rebase Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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/browser/extensions/extension_tts_engine_api.h"
6
7 #include <string>
8
9 #include "base/json/json_writer.h"
10 #include "base/values.h"
11 #include "chrome/browser/extensions/extension_event_router.h"
12 #include "chrome/browser/extensions/extension_service.h"
13 #include "chrome/browser/extensions/extension_tts_api_constants.h"
14 #include "chrome/browser/extensions/extension_tts_api_controller.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/common/extensions/extension.h"
17
18 namespace constants = extension_tts_api_constants;
19
20 namespace events {
21 const char kOnSpeak[] = "ttsEngine.onSpeak";
22 const char kOnStop[] = "ttsEngine.onStop";
23 }; // namespace events
24
25 void GetExtensionVoices(Profile* profile, ListValue* result_voices) {
26 ExtensionService* service = profile->GetExtensionService();
27 DCHECK(service);
28 ExtensionEventRouter* event_router = profile->GetExtensionEventRouter();
29 DCHECK(event_router);
30
31 const ExtensionSet* extensions = service->extensions();
32 ExtensionSet::const_iterator iter;
33 for (iter = extensions->begin(); iter != extensions->end(); ++iter) {
34 const Extension* extension = *iter;
35
36 if (!event_router->ExtensionHasEventListener(
37 extension->id(), events::kOnSpeak) ||
38 !event_router->ExtensionHasEventListener(
39 extension->id(), events::kOnStop)) {
40 continue;
41 }
42
43 const std::vector<Extension::TtsVoice>& tts_voices =
44 extension->tts_voices();
45 for (size_t i = 0; i < tts_voices.size(); ++i) {
46 const Extension::TtsVoice& voice = tts_voices[i];
47 DictionaryValue* result_voice = new DictionaryValue();
48 if (!voice.voice_name.empty())
49 result_voice->SetString(constants::kVoiceNameKey, voice.voice_name);
50 if (!voice.lang.empty())
51 result_voice->SetString(constants::kLangKey, voice.lang);
52 if (!voice.gender.empty())
53 result_voice->SetString(constants::kGenderKey, voice.gender);
54 result_voice->SetString(constants::kExtensionIdKey, extension->id());
55
56 ListValue* event_types = new ListValue();
57 for (std::set<std::string>::const_iterator iter =
58 voice.event_types.begin();
59 iter != voice.event_types.end();
60 ++iter) {
61 event_types->Append(Value::CreateStringValue(*iter));
62 }
63 // If the extension sends end events, the controller will handle
64 // queueing and send interrupted and cancelled events.
65 if (voice.event_types.find(constants::kEventTypeEnd) !=
66 voice.event_types.end()) {
67 event_types->Append(
68 Value::CreateStringValue(constants::kEventTypeCancelled));
69 event_types->Append(Value::CreateStringValue(
70 constants::kEventTypeInterrupted));
71 }
72
73 result_voice->Set(constants::kEventTypesKey, event_types);
74 result_voices->Append(result_voice);
75 }
76 }
77 }
78
79 bool GetMatchingExtensionVoice(
80 Utterance* utterance,
81 const Extension** matching_extension,
82 size_t* voice_index) {
83 // This will only happen during unit testing. Otherwise, an utterance
84 // will always have an associated profile.
85 if (!utterance->profile())
86 return false;
87
88 ExtensionService* service = utterance->profile()->GetExtensionService();
89 DCHECK(service);
90 ExtensionEventRouter* event_router =
91 utterance->profile()->GetExtensionEventRouter();
92 DCHECK(event_router);
93
94 *matching_extension = NULL;
95 *voice_index = -1;
96 const ExtensionSet* extensions = service->extensions();
97 ExtensionSet::const_iterator iter;
98 for (iter = extensions->begin(); iter != extensions->end(); ++iter) {
99 const Extension* extension = *iter;
100
101 if (!event_router->ExtensionHasEventListener(
102 extension->id(), events::kOnSpeak) ||
103 !event_router->ExtensionHasEventListener(
104 extension->id(), events::kOnStop)) {
105 continue;
106 }
107
108 if (!utterance->extension_id().empty() &&
109 utterance->extension_id() != extension->id()) {
110 continue;
111 }
112
113 const std::vector<Extension::TtsVoice>& tts_voices =
114 extension->tts_voices();
115 for (size_t i = 0; i < tts_voices.size(); ++i) {
116 const Extension::TtsVoice& voice = tts_voices[i];
117 if (!voice.voice_name.empty() &&
118 !utterance->voice_name().empty() &&
119 voice.voice_name != utterance->voice_name()) {
120 continue;
121 }
122 if (!voice.lang.empty() &&
123 !utterance->lang().empty() &&
124 voice.lang != utterance->lang()) {
125 continue;
126 }
127 if (!voice.gender.empty() &&
128 !utterance->gender().empty() &&
129 voice.gender != utterance->gender()) {
130 continue;
131 }
132 if (utterance->required_event_types().size() > 0) {
133 bool has_all_required_event_types = true;
134 for (std::set<std::string>::const_iterator iter =
135 utterance->required_event_types().begin();
136 iter != utterance->required_event_types().end();
137 ++iter) {
138 if (voice.event_types.find(*iter) == voice.event_types.end()) {
139 has_all_required_event_types = false;
140 break;
141 }
142 }
143 if (!has_all_required_event_types)
144 continue;
145 }
146
147 *matching_extension = extension;
148 *voice_index = i;
149 return true;
150 }
151 }
152
153 return false;
154 }
155
156 void ExtensionTtsEngineSpeak(Utterance* utterance,
157 const Extension* extension,
158 size_t voice_index) {
159 // See if the engine supports the "end" event; if so, we can keep the
160 // utterance around and track it. If not, we're finished with this
161 // utterance now.
162 const std::set<std::string> event_types =
163 extension->tts_voices()[voice_index].event_types;
164 bool sends_end_event =
165 (event_types.find(constants::kEventTypeEnd) != event_types.end());
166
167 ListValue args;
168 args.Set(0, Value::CreateStringValue(utterance->text()));
169
170 // Pass through most options to the speech engine, but remove some
171 // that are handled internally.
172 DictionaryValue* options = static_cast<DictionaryValue*>(
173 utterance->options()->DeepCopy());
174 if (options->HasKey(constants::kRequiredEventTypesKey))
175 options->Remove(constants::kRequiredEventTypesKey, NULL);
176 if (options->HasKey(constants::kDesiredEventTypesKey))
177 options->Remove(constants::kDesiredEventTypesKey, NULL);
178 if (sends_end_event && options->HasKey(constants::kEnqueueKey))
179 options->Remove(constants::kEnqueueKey, NULL);
180 if (options->HasKey(constants::kSrcIdKey))
181 options->Remove(constants::kSrcIdKey, NULL);
182 if (options->HasKey(constants::kIsFinalEventKey))
183 options->Remove(constants::kIsFinalEventKey, NULL);
184
185 args.Set(1, options);
186 args.Set(2, Value::CreateIntegerValue(utterance->id()));
187 std::string json_args;
188 base::JSONWriter::Write(&args, &json_args);
189
190 utterance->profile()->GetExtensionEventRouter()->DispatchEventToExtension(
191 extension->id(),
192 events::kOnSpeak,
193 json_args,
194 utterance->profile(),
195 GURL());
196 }
197
198 void ExtensionTtsEngineStop(Utterance* utterance) {
199 utterance->profile()->GetExtensionEventRouter()->DispatchEventToExtension(
200 utterance->extension_id(),
201 events::kOnStop,
202 "[]",
203 utterance->profile(),
204 GURL());
205 }
206
207 bool ExtensionTtsEngineSendTtsEventFunction::RunImpl() {
208 int utterance_id;
209 std::string error_message;
210 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &utterance_id));
211
212 DictionaryValue* event;
213 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &event));
214
215 std::string event_type;
216 EXTENSION_FUNCTION_VALIDATE(
217 event->GetString(constants::kEventTypeKey, &event_type));
218
219 int char_index = 0;
220 if (event->HasKey(constants::kCharIndexKey)) {
221 EXTENSION_FUNCTION_VALIDATE(
222 event->GetInteger(constants::kCharIndexKey, &char_index));
223 }
224
225 // Make sure the extension has included this event type in its manifest.
226 bool event_type_allowed = false;
227 const Extension* extension = GetExtension();
228 for (size_t i = 0; i < extension->tts_voices().size(); i++) {
229 const Extension::TtsVoice& voice = extension->tts_voices()[i];
230 if (voice.event_types.find(event_type) != voice.event_types.end()) {
231 event_type_allowed = true;
232 break;
233 }
234 }
235 if (!event_type_allowed) {
236 error_ = constants::kErrorUndeclaredEventType;
237 return false;
238 }
239
240 ExtensionTtsController* controller = ExtensionTtsController::GetInstance();
241 if (event_type == constants::kEventTypeStart) {
242 controller->OnTtsEvent(
243 utterance_id, TTS_EVENT_START, char_index, std::string());
244 } else if (event_type == constants::kEventTypeEnd) {
245 controller->OnTtsEvent(
246 utterance_id, TTS_EVENT_END, char_index, std::string());
247 } else if (event_type == constants::kEventTypeWord) {
248 controller->OnTtsEvent(
249 utterance_id, TTS_EVENT_WORD, char_index, std::string());
250 } else if (event_type == constants::kEventTypeSentence) {
251 controller->OnTtsEvent(
252 utterance_id, TTS_EVENT_SENTENCE, char_index, std::string());
253 } else if (event_type == constants::kEventTypeMarker) {
254 controller->OnTtsEvent(
255 utterance_id, TTS_EVENT_MARKER, char_index, std::string());
256 } else if (event_type == constants::kEventTypeError) {
257 std::string error_message;
258 event->GetString(constants::kErrorMessageKey, &error_message);
259 controller->OnTtsEvent(
260 utterance_id, TTS_EVENT_ERROR, char_index, error_message);
261 } else {
262 EXTENSION_FUNCTION_VALIDATE(false);
263 }
264
265 return true;
266 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extension_tts_engine_api.h ('k') | chrome/browser/speech/extension_api/OWNERS » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698