12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/api/speech/tts_engine_manifest_handler.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/error_utils.h" 123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "extensions/common/manifest.h" 13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "extensions/common/manifest_constants.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 16d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace extensions { 17d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace keys = manifest_keys; 19d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace errors = manifest_errors; 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 23d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)struct TtsVoices : public Extension::ManifestData { 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TtsVoices() {} 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~TtsVoices() {} 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<extensions::TtsVoice> voices; 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)TtsVoice::TtsVoice() : remote(false) {} 330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TtsVoice::~TtsVoice() {} 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const std::vector<TtsVoice>* TtsVoice::GetTtsVoices( 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Extension* extension) { 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TtsVoices* info = static_cast<TtsVoices*>( 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension->GetManifestData(keys::kTtsVoices)); 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return info ? &info->voices : NULL; 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TtsEngineManifestHandler::TtsEngineManifestHandler() { 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TtsEngineManifestHandler::~TtsEngineManifestHandler() { 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool TtsEngineManifestHandler::Parse(Extension* extension, 51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16* error) { 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<TtsVoices> info(new TtsVoices); 537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::DictionaryValue* tts_dict = NULL; 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!extension->manifest()->GetDictionary(keys::kTtsEngine, &tts_dict)) { 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *error = base::ASCIIToUTF16(errors::kInvalidTts); 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!tts_dict->HasKey(keys::kTtsVoices)) 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::ListValue* tts_voices = NULL; 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!tts_dict->GetList(keys::kTtsVoices, &tts_voices)) { 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *error = base::ASCIIToUTF16(errors::kInvalidTtsVoices); 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < tts_voices->GetSize(); i++) { 697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::DictionaryValue* one_tts_voice = NULL; 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!tts_voices->GetDictionary(i, &one_tts_voice)) { 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *error = base::ASCIIToUTF16(errors::kInvalidTtsVoices); 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TtsVoice voice_data; 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (one_tts_voice->HasKey(keys::kTtsVoicesVoiceName)) { 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!one_tts_voice->GetString( 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) keys::kTtsVoicesVoiceName, &voice_data.voice_name)) { 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *error = base::ASCIIToUTF16(errors::kInvalidTtsVoicesVoiceName); 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (one_tts_voice->HasKey(keys::kTtsVoicesLang)) { 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!one_tts_voice->GetString( 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) keys::kTtsVoicesLang, &voice_data.lang) || 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !l10n_util::IsValidLocaleSyntax(voice_data.lang)) { 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *error = base::ASCIIToUTF16(errors::kInvalidTtsVoicesLang); 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (one_tts_voice->HasKey(keys::kTtsVoicesGender)) { 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!one_tts_voice->GetString( 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) keys::kTtsVoicesGender, &voice_data.gender) || 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (voice_data.gender != keys::kTtsGenderMale && 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) voice_data.gender != keys::kTtsGenderFemale)) { 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *error = base::ASCIIToUTF16(errors::kInvalidTtsVoicesGender); 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1000f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (one_tts_voice->HasKey(keys::kTtsVoicesRemote)) { 1010f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!one_tts_voice->GetBoolean( 1020f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) keys::kTtsVoicesRemote, &voice_data.remote)) { 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *error = base::ASCIIToUTF16(errors::kInvalidTtsVoicesRemote); 1040f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return false; 1050f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 1060f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (one_tts_voice->HasKey(keys::kTtsVoicesEventTypes)) { 1087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::ListValue* event_types_list; 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!one_tts_voice->GetList( 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) keys::kTtsVoicesEventTypes, 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &event_types_list)) { 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *error = base::ASCIIToUTF16( 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) errors::kInvalidTtsVoicesEventTypes); 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < event_types_list->GetSize(); i++) { 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string event_type; 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!event_types_list->GetString(i, &event_type)) { 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *error = base::ASCIIToUTF16(errors::kInvalidTtsVoicesEventTypes); 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (event_type != keys::kTtsVoicesEventTypeEnd && 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event_type != keys::kTtsVoicesEventTypeError && 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event_type != keys::kTtsVoicesEventTypeMarker && 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event_type != keys::kTtsVoicesEventTypeSentence && 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event_type != keys::kTtsVoicesEventTypeStart && 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event_type != keys::kTtsVoicesEventTypeWord) { 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *error = base::ASCIIToUTF16(errors::kInvalidTtsVoicesEventTypes); 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (voice_data.event_types.find(event_type) != 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) voice_data.event_types.end()) { 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *error = base::ASCIIToUTF16(errors::kInvalidTtsVoicesEventTypes); 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) voice_data.event_types.insert(event_type); 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) info->voices.push_back(voice_data); 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension->SetManifestData(keys::kTtsVoices, info.release()); 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const std::vector<std::string> TtsEngineManifestHandler::Keys() const { 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return SingleKey(keys::kTtsEngine); 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace extensions 152