- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / speech / extension_api / tts_engine_extension_api.cc
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/speech/extension_api/tts_engine_extension_api.h"
6
7 #include <string>
8
9 #include "base/json/json_writer.h"
10 #include "base/values.h"
11 #include "chrome/browser/extensions/event_router.h"
12 #include "chrome/browser/extensions/extension_host.h"
13 #include "chrome/browser/extensions/extension_process_manager.h"
14 #include "chrome/browser/extensions/extension_service.h"
15 #include "chrome/browser/extensions/extension_system.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/speech/extension_api/tts_extension_api.h"
18 #include "chrome/browser/speech/extension_api/tts_extension_api_constants.h"
19 #include "chrome/browser/speech/tts_controller.h"
20 #include "chrome/common/extensions/api/speech/tts_engine_manifest_handler.h"
21 #include "chrome/common/extensions/extension.h"
22 #include "chrome/common/extensions/extension_messages.h"
23 #include "content/public/browser/render_process_host.h"
24 #include "content/public/browser/render_view_host.h"
25 #include "content/public/common/console_message_level.h"
26
27 using extensions::EventRouter;
28 using extensions::Extension;
29 using extensions::ExtensionSystem;
30
31 namespace constants = tts_extension_api_constants;
32
33 namespace tts_engine_events {
34 const char kOnSpeak[] = "ttsEngine.onSpeak";
35 const char kOnStop[] = "ttsEngine.onStop";
36 const char kOnPause[] = "ttsEngine.onPause";
37 const char kOnResume[] = "ttsEngine.onResume";
38 };  // namespace tts_engine_events
39
40 namespace {
41 void WarnIfMissingPauseOrResumeListener(
42     Profile* profile, EventRouter* event_router, std::string extension_id) {
43   bool has_onpause = event_router->ExtensionHasEventListener(
44       extension_id, tts_engine_events::kOnPause);
45   bool has_onresume = event_router->ExtensionHasEventListener(
46       extension_id, tts_engine_events::kOnResume);
47   if (has_onpause == has_onresume)
48     return;
49
50   ExtensionProcessManager* process_manager =
51       ExtensionSystem::Get(profile)->process_manager();
52   extensions::ExtensionHost* host =
53       process_manager->GetBackgroundHostForExtension(extension_id);
54   host->render_process_host()->Send(new ExtensionMsg_AddMessageToConsole(
55       host->render_view_host()->GetRoutingID(),
56       content::CONSOLE_MESSAGE_LEVEL_WARNING,
57       constants::kErrorMissingPauseOrResume));
58 };
59 }  // anonymous namespace
60
61 void GetExtensionVoices(Profile* profile, std::vector<VoiceData>* out_voices) {
62   ExtensionService* service = profile->GetExtensionService();
63   DCHECK(service);
64   EventRouter* event_router =
65       ExtensionSystem::Get(profile)->event_router();
66   DCHECK(event_router);
67
68   const ExtensionSet* extensions = service->extensions();
69   ExtensionSet::const_iterator iter;
70   for (iter = extensions->begin(); iter != extensions->end(); ++iter) {
71     const Extension* extension = iter->get();
72
73     if (!event_router->ExtensionHasEventListener(
74             extension->id(), tts_engine_events::kOnSpeak) ||
75         !event_router->ExtensionHasEventListener(
76             extension->id(), tts_engine_events::kOnStop)) {
77       continue;
78     }
79
80     const std::vector<extensions::TtsVoice>* tts_voices =
81         extensions::TtsVoice::GetTtsVoices(extension);
82     if (!tts_voices)
83       continue;
84
85     for (size_t i = 0; i < tts_voices->size(); ++i) {
86       const extensions::TtsVoice& voice = tts_voices->at(i);
87
88       out_voices->push_back(VoiceData());
89       VoiceData& result_voice = out_voices->back();
90
91       result_voice.native = false;
92       result_voice.name = voice.voice_name;
93       result_voice.lang = voice.lang;
94       result_voice.remote = voice.remote;
95       result_voice.extension_id = extension->id();
96       if (voice.gender == constants::kGenderMale)
97         result_voice.gender = TTS_GENDER_MALE;
98       else if (voice.gender == constants::kGenderFemale)
99         result_voice.gender = TTS_GENDER_FEMALE;
100       else
101         result_voice.gender = TTS_GENDER_NONE;
102
103       for (std::set<std::string>::const_iterator iter =
104                voice.event_types.begin();
105            iter != voice.event_types.end();
106            ++iter) {
107         result_voice.events.insert(TtsEventTypeFromString(*iter));
108       }
109
110       // If the extension sends end events, the controller will handle
111       // queueing and send interrupted and cancelled events.
112       if (voice.event_types.find(constants::kEventTypeEnd) !=
113           voice.event_types.end()) {
114         result_voice.events.insert(TTS_EVENT_CANCELLED);
115         result_voice.events.insert(TTS_EVENT_INTERRUPTED);
116       }
117     }
118   }
119 }
120
121 void ExtensionTtsEngineSpeak(Utterance* utterance, const VoiceData& voice) {
122   // See if the engine supports the "end" event; if so, we can keep the
123   // utterance around and track it. If not, we're finished with this
124   // utterance now.
125   bool sends_end_event = voice.events.find(TTS_EVENT_END) != voice.events.end();
126
127   scoped_ptr<ListValue> args(new ListValue());
128   args->Set(0, Value::CreateStringValue(utterance->text()));
129
130   // Pass through most options to the speech engine, but remove some
131   // that are handled internally.
132   scoped_ptr<DictionaryValue> options(static_cast<DictionaryValue*>(
133       utterance->options()->DeepCopy()));
134   if (options->HasKey(constants::kRequiredEventTypesKey))
135     options->Remove(constants::kRequiredEventTypesKey, NULL);
136   if (options->HasKey(constants::kDesiredEventTypesKey))
137     options->Remove(constants::kDesiredEventTypesKey, NULL);
138   if (sends_end_event && options->HasKey(constants::kEnqueueKey))
139     options->Remove(constants::kEnqueueKey, NULL);
140   if (options->HasKey(constants::kSrcIdKey))
141     options->Remove(constants::kSrcIdKey, NULL);
142   if (options->HasKey(constants::kIsFinalEventKey))
143     options->Remove(constants::kIsFinalEventKey, NULL);
144   if (options->HasKey(constants::kOnEventKey))
145     options->Remove(constants::kOnEventKey, NULL);
146
147   args->Set(1, options.release());
148   args->Set(2, Value::CreateIntegerValue(utterance->id()));
149
150   scoped_ptr<extensions::Event> event(new extensions::Event(
151       tts_engine_events::kOnSpeak, args.Pass()));
152   event->restrict_to_profile = utterance->profile();
153   ExtensionSystem::Get(utterance->profile())->event_router()->
154       DispatchEventToExtension(utterance->extension_id(), event.Pass());
155 }
156
157 void ExtensionTtsEngineStop(Utterance* utterance) {
158   scoped_ptr<ListValue> args(new ListValue());
159   scoped_ptr<extensions::Event> event(new extensions::Event(
160       tts_engine_events::kOnStop, args.Pass()));
161   event->restrict_to_profile = utterance->profile();
162   ExtensionSystem::Get(utterance->profile())->event_router()->
163       DispatchEventToExtension(utterance->extension_id(), event.Pass());
164 }
165
166 void ExtensionTtsEnginePause(Utterance* utterance) {
167   scoped_ptr<ListValue> args(new ListValue());
168   scoped_ptr<extensions::Event> event(new extensions::Event(
169       tts_engine_events::kOnPause, args.Pass()));
170   Profile* profile = utterance->profile();
171   event->restrict_to_profile = profile;
172   EventRouter* event_router = ExtensionSystem::Get(profile)->event_router();
173   std::string id = utterance->extension_id();
174   event_router->DispatchEventToExtension(id, event.Pass());
175   WarnIfMissingPauseOrResumeListener(profile, event_router, id);
176 }
177
178 void ExtensionTtsEngineResume(Utterance* utterance) {
179   scoped_ptr<ListValue> args(new ListValue());
180   scoped_ptr<extensions::Event> event(new extensions::Event(
181       tts_engine_events::kOnResume, args.Pass()));
182   Profile* profile = utterance->profile();
183   event->restrict_to_profile = profile;
184   EventRouter* event_router = ExtensionSystem::Get(profile)->event_router();
185   std::string id = utterance->extension_id();
186   event_router->DispatchEventToExtension(id, event.Pass());
187   WarnIfMissingPauseOrResumeListener(profile, event_router, id);
188 }
189
190 bool ExtensionTtsEngineSendTtsEventFunction::RunImpl() {
191   int utterance_id;
192   EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &utterance_id));
193
194   DictionaryValue* event;
195   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &event));
196
197   std::string event_type;
198   EXTENSION_FUNCTION_VALIDATE(
199       event->GetString(constants::kEventTypeKey, &event_type));
200
201   int char_index = 0;
202   if (event->HasKey(constants::kCharIndexKey)) {
203     EXTENSION_FUNCTION_VALIDATE(
204         event->GetInteger(constants::kCharIndexKey, &char_index));
205   }
206
207   // Make sure the extension has included this event type in its manifest.
208   bool event_type_allowed = false;
209   const Extension* extension = GetExtension();
210   const std::vector<extensions::TtsVoice>* tts_voices =
211       extensions::TtsVoice::GetTtsVoices(extension);
212   if (!tts_voices) {
213     error_ = constants::kErrorUndeclaredEventType;
214     return false;
215   }
216
217   for (size_t i = 0; i < tts_voices->size(); i++) {
218     const extensions::TtsVoice& voice = tts_voices->at(i);
219     if (voice.event_types.find(event_type) != voice.event_types.end()) {
220       event_type_allowed = true;
221       break;
222     }
223   }
224   if (!event_type_allowed) {
225     error_ = constants::kErrorUndeclaredEventType;
226     return false;
227   }
228
229   TtsController* controller = TtsController::GetInstance();
230   if (event_type == constants::kEventTypeStart) {
231     controller->OnTtsEvent(
232         utterance_id, TTS_EVENT_START, char_index, std::string());
233   } else if (event_type == constants::kEventTypeEnd) {
234     controller->OnTtsEvent(
235         utterance_id, TTS_EVENT_END, char_index, std::string());
236   } else if (event_type == constants::kEventTypeWord) {
237     controller->OnTtsEvent(
238         utterance_id, TTS_EVENT_WORD, char_index, std::string());
239   } else if (event_type == constants::kEventTypeSentence) {
240     controller->OnTtsEvent(
241         utterance_id, TTS_EVENT_SENTENCE, char_index, std::string());
242   } else if (event_type == constants::kEventTypeMarker) {
243     controller->OnTtsEvent(
244         utterance_id, TTS_EVENT_MARKER, char_index, std::string());
245   } else if (event_type == constants::kEventTypeError) {
246     std::string error_message;
247     event->GetString(constants::kErrorMessageKey, &error_message);
248     controller->OnTtsEvent(
249         utterance_id, TTS_EVENT_ERROR, char_index, error_message);
250   } else if (event_type == constants::kEventTypePause) {
251     controller->OnTtsEvent(
252         utterance_id, TTS_EVENT_PAUSE, char_index, std::string());
253   } else if (event_type == constants::kEventTypeResume) {
254     controller->OnTtsEvent(
255         utterance_id, TTS_EVENT_RESUME, char_index, std::string());
256   } else {
257     EXTENSION_FUNCTION_VALIDATE(false);
258   }
259
260   return true;
261 }