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.
5 #include "chrome/browser/speech/extension_api/tts_extension_api.h"
9 #include "base/lazy_instance.h"
10 #include "base/values.h"
11 #include "chrome/browser/extensions/extension_function_registry.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/speech/extension_api/tts_engine_extension_api.h"
14 #include "chrome/browser/speech/extension_api/tts_extension_api_constants.h"
15 #include "chrome/browser/speech/tts_controller.h"
16 #include "chrome/common/extensions/api/speech/tts_engine_manifest_handler.h"
17 #include "ui/base/l10n/l10n_util.h"
19 namespace constants
= tts_extension_api_constants
;
21 namespace extensions
{
23 bool TtsSpeakFunction::RunImpl() {
25 EXTENSION_FUNCTION_VALIDATE(args_
->GetString(0, &text
));
26 if (text
.size() > 32768) {
27 error_
= constants::kErrorUtteranceTooLong
;
31 scoped_ptr
<DictionaryValue
> options(new DictionaryValue());
32 if (args_
->GetSize() >= 2) {
33 DictionaryValue
* temp_options
= NULL
;
34 if (args_
->GetDictionary(1, &temp_options
))
35 options
.reset(temp_options
->DeepCopy());
38 std::string voice_name
;
39 if (options
->HasKey(constants::kVoiceNameKey
)) {
40 EXTENSION_FUNCTION_VALIDATE(
41 options
->GetString(constants::kVoiceNameKey
, &voice_name
));
45 if (options
->HasKey(constants::kLangKey
))
46 EXTENSION_FUNCTION_VALIDATE(options
->GetString(constants::kLangKey
, &lang
));
47 if (!lang
.empty() && !l10n_util::IsValidLocaleSyntax(lang
)) {
48 error_
= constants::kErrorInvalidLang
;
53 if (options
->HasKey(constants::kGenderKey
))
54 EXTENSION_FUNCTION_VALIDATE(
55 options
->GetString(constants::kGenderKey
, &gender
));
56 if (!gender
.empty() &&
57 gender
!= constants::kGenderFemale
&&
58 gender
!= constants::kGenderMale
) {
59 error_
= constants::kErrorInvalidGender
;
64 if (options
->HasKey(constants::kRateKey
)) {
65 EXTENSION_FUNCTION_VALIDATE(
66 options
->GetDouble(constants::kRateKey
, &rate
));
67 if (rate
< 0.1 || rate
> 10.0) {
68 error_
= constants::kErrorInvalidRate
;
74 if (options
->HasKey(constants::kPitchKey
)) {
75 EXTENSION_FUNCTION_VALIDATE(
76 options
->GetDouble(constants::kPitchKey
, &pitch
));
77 if (pitch
< 0.0 || pitch
> 2.0) {
78 error_
= constants::kErrorInvalidPitch
;
84 if (options
->HasKey(constants::kVolumeKey
)) {
85 EXTENSION_FUNCTION_VALIDATE(
86 options
->GetDouble(constants::kVolumeKey
, &volume
));
87 if (volume
< 0.0 || volume
> 1.0) {
88 error_
= constants::kErrorInvalidVolume
;
93 bool can_enqueue
= false;
94 if (options
->HasKey(constants::kEnqueueKey
)) {
95 EXTENSION_FUNCTION_VALIDATE(
96 options
->GetBoolean(constants::kEnqueueKey
, &can_enqueue
));
99 std::set
<std::string
> required_event_types
;
100 if (options
->HasKey(constants::kRequiredEventTypesKey
)) {
102 EXTENSION_FUNCTION_VALIDATE(
103 options
->GetList(constants::kRequiredEventTypesKey
, &list
));
104 for (size_t i
= 0; i
< list
->GetSize(); i
++) {
105 std::string event_type
;
106 if (!list
->GetString(i
, &event_type
))
107 required_event_types
.insert(event_type
);
111 std::set
<std::string
> desired_event_types
;
112 if (options
->HasKey(constants::kDesiredEventTypesKey
)) {
114 EXTENSION_FUNCTION_VALIDATE(
115 options
->GetList(constants::kDesiredEventTypesKey
, &list
));
116 for (size_t i
= 0; i
< list
->GetSize(); i
++) {
117 std::string event_type
;
118 if (!list
->GetString(i
, &event_type
))
119 desired_event_types
.insert(event_type
);
123 std::string voice_extension_id
;
124 if (options
->HasKey(constants::kExtensionIdKey
)) {
125 EXTENSION_FUNCTION_VALIDATE(
126 options
->GetString(constants::kExtensionIdKey
, &voice_extension_id
));
130 if (options
->HasKey(constants::kSrcIdKey
)) {
131 EXTENSION_FUNCTION_VALIDATE(
132 options
->GetInteger(constants::kSrcIdKey
, &src_id
));
135 // If we got this far, the arguments were all in the valid format, so
136 // send the success response to the callback now - this ensures that
137 // the callback response always arrives before events, which makes
138 // the behavior more predictable and easier to write unit tests for too.
141 UtteranceContinuousParameters continuous_params
;
142 continuous_params
.rate
= rate
;
143 continuous_params
.pitch
= pitch
;
144 continuous_params
.volume
= volume
;
146 Utterance
* utterance
= new Utterance(profile());
147 utterance
->set_text(text
);
148 utterance
->set_voice_name(voice_name
);
149 utterance
->set_src_extension_id(extension_id());
150 utterance
->set_src_id(src_id
);
151 utterance
->set_src_url(source_url());
152 utterance
->set_lang(lang
);
153 utterance
->set_gender(gender
);
154 utterance
->set_continuous_parameters(continuous_params
);
155 utterance
->set_can_enqueue(can_enqueue
);
156 utterance
->set_required_event_types(required_event_types
);
157 utterance
->set_desired_event_types(desired_event_types
);
158 utterance
->set_extension_id(voice_extension_id
);
159 utterance
->set_options(options
.get());
161 TtsController
* controller
= TtsController::GetInstance();
162 controller
->SpeakOrEnqueue(utterance
);
166 bool TtsStopSpeakingFunction::RunImpl() {
167 TtsController::GetInstance()->Stop();
171 bool TtsIsSpeakingFunction::RunImpl() {
172 SetResult(Value::CreateBooleanValue(
173 TtsController::GetInstance()->IsSpeaking()));
177 bool TtsGetVoicesFunction::RunImpl() {
178 SetResult(TtsController::GetInstance()->GetVoices(profile()));
183 TtsAPI
* TtsAPI::Get(Profile
* profile
) {
184 return ProfileKeyedAPIFactory
<TtsAPI
>::GetForProfile(profile
);
187 TtsAPI::TtsAPI(Profile
* profile
) {
188 (new TtsEngineManifestHandler
)->Register();
189 ExtensionFunctionRegistry
* registry
=
190 ExtensionFunctionRegistry::GetInstance();
191 registry
->RegisterFunction
<ExtensionTtsEngineSendTtsEventFunction
>();
192 registry
->RegisterFunction
<TtsGetVoicesFunction
>();
193 registry
->RegisterFunction
<TtsIsSpeakingFunction
>();
194 registry
->RegisterFunction
<TtsSpeakFunction
>();
195 registry
->RegisterFunction
<TtsStopSpeakingFunction
>();
201 static base::LazyInstance
<ProfileKeyedAPIFactory
<TtsAPI
> >
202 g_factory
= LAZY_INSTANCE_INITIALIZER
;
204 ProfileKeyedAPIFactory
<TtsAPI
>* TtsAPI::GetFactoryInstance() {
205 return &g_factory
.Get();
208 } // namespace extensions