Commit 77c48b1f authored by Katie D's avatar Katie D Committed by Commit Bot

Warns users that VoiceGender is deprecated and will be ignored in Chrome 71.

Warnings occur when loading the manifest or using a chrome.tts or
chrome.ttsEngine Javascript API with VocieGender.

Does not actually deprecate gender, but makes sure it is optional.

BUG=863999,863998

Change-Id: If850e4374cb871289af0102da18040b49f100ae7
Reviewed-on: https://chromium-review.googlesource.com/1176354
Commit-Queue: Katie Dektar <katie@chromium.org>
Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Reviewed-by: default avatarDevlin <rdevlin.cronin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#584280}
parent 461114ae
...@@ -406,7 +406,11 @@ IN_PROC_BROWSER_TEST_F(TtsApiTest, RegisterEngine) { ...@@ -406,7 +406,11 @@ IN_PROC_BROWSER_TEST_F(TtsApiTest, RegisterEngine) {
Return(true))); Return(true)));
} }
ASSERT_TRUE(RunExtensionTest("tts_engine/register_engine")) << message_; // TODO(katie): Expect the deprecated gender warning rather than ignoring
// warnings.
ASSERT_TRUE(RunExtensionTestWithFlags("tts_engine/register_engine",
kFlagIgnoreManifestWarnings))
<< message_;
} }
// https://crbug.com/709115 tracks test flakiness. // https://crbug.com/709115 tracks test flakiness.
......
...@@ -34,7 +34,9 @@ TtsVoices::~TtsVoices() {} ...@@ -34,7 +34,9 @@ TtsVoices::~TtsVoices() {}
// static // static
bool TtsVoices::Parse(const base::ListValue* tts_voices, bool TtsVoices::Parse(const base::ListValue* tts_voices,
TtsVoices* out_voices, TtsVoices* out_voices,
base::string16* error) { base::string16* error,
Extension* extension) {
bool added_gender_warning = false;
for (size_t i = 0; i < tts_voices->GetSize(); i++) { for (size_t i = 0; i < tts_voices->GetSize(); i++) {
const base::DictionaryValue* one_tts_voice = nullptr; const base::DictionaryValue* one_tts_voice = nullptr;
if (!tts_voices->GetDictionary(i, &one_tts_voice)) { if (!tts_voices->GetDictionary(i, &one_tts_voice)) {
...@@ -59,6 +61,12 @@ bool TtsVoices::Parse(const base::ListValue* tts_voices, ...@@ -59,6 +61,12 @@ bool TtsVoices::Parse(const base::ListValue* tts_voices,
} }
} }
if (one_tts_voice->HasKey(keys::kTtsVoicesGender)) { if (one_tts_voice->HasKey(keys::kTtsVoicesGender)) {
if (!added_gender_warning) {
extension->AddInstallWarning(
InstallWarning(errors::kTtsGenderIsDeprecated));
// No need to add a warning for each voice, that's noisy.
added_gender_warning = true;
}
if (!one_tts_voice->GetString( if (!one_tts_voice->GetString(
keys::kTtsVoicesGender, &voice_data.gender) || keys::kTtsVoicesGender, &voice_data.gender) ||
(voice_data.gender != keys::kTtsGenderMale && (voice_data.gender != keys::kTtsGenderMale &&
...@@ -141,7 +149,7 @@ bool TtsEngineManifestHandler::Parse(Extension* extension, ...@@ -141,7 +149,7 @@ bool TtsEngineManifestHandler::Parse(Extension* extension,
return false; return false;
} }
if (!TtsVoices::Parse(tts_voices, info.get(), error)) if (!TtsVoices::Parse(tts_voices, info.get(), error, extension))
return false; return false;
extension->SetManifestData(keys::kTtsVoices, std::move(info)); extension->SetManifestData(keys::kTtsVoices, std::move(info));
......
...@@ -32,7 +32,8 @@ struct TtsVoices : public Extension::ManifestData { ...@@ -32,7 +32,8 @@ struct TtsVoices : public Extension::ManifestData {
~TtsVoices() override; ~TtsVoices() override;
static bool Parse(const base::ListValue* tts_voices, static bool Parse(const base::ListValue* tts_voices,
TtsVoices* out_voices, TtsVoices* out_voices,
base::string16* error); base::string16* error,
Extension* extension);
std::vector<extensions::TtsVoice> voices; std::vector<extensions::TtsVoice> voices;
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
{ {
"id": "VoiceGender", "id": "VoiceGender",
"type": "string", "type": "string",
"deprecated": "Gender is deprecated and will soon be ignored.",
"enum": ["male", "female"] "enum": ["male", "female"]
}, },
{ {
...@@ -68,6 +69,7 @@ ...@@ -68,6 +69,7 @@
"gender": { "gender": {
"$ref": "VoiceGender", "$ref": "VoiceGender",
"optional": true, "optional": true,
"deprecated": "Gender is deprecated and will soon be ignored.",
"description": "This voice's gender." "description": "This voice's gender."
}, },
"remote": { "remote": {
...@@ -129,6 +131,7 @@ ...@@ -129,6 +131,7 @@
"gender": { "gender": {
"$ref": "VoiceGender", "$ref": "VoiceGender",
"optional": true, "optional": true,
"deprecated": "Gender is deprecated and will soon be ignored.",
"description": "Gender of voice for synthesized speech." "description": "Gender of voice for synthesized speech."
}, },
"rate": { "rate": {
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
{ {
"id": "VoiceGender", "id": "VoiceGender",
"type": "string", "type": "string",
"deprecated": "Gender is deprecated and will soon be ignored.",
"enum": ["male", "female"] "enum": ["male", "female"]
} }
], ],
...@@ -74,6 +75,7 @@ ...@@ -74,6 +75,7 @@
"gender": { "gender": {
"$ref": "VoiceGender", "$ref": "VoiceGender",
"optional": true, "optional": true,
"deprecated": "Gender is deprecated and will soon be ignored.",
"description": "Gender of voice for synthesized speech." "description": "Gender of voice for synthesized speech."
}, },
"rate": { "rate": {
......
...@@ -148,7 +148,7 @@ support and to still speak the underlying text.</p> ...@@ -148,7 +148,7 @@ support and to still speak the underlying text.</p>
<h2 id="choosing_voice">Choosing a voice</h2> <h2 id="choosing_voice">Choosing a voice</h2>
<p>By default, Chrome chooses the most appropriate voice for each <p>By default, Chrome chooses the most appropriate voice for each
utterance you want to speak, based on the language and gender. On most utterance you want to speak, based on the language. On most
Windows, Mac OS X, and Chrome OS systems, speech synthesis provided by Windows, Mac OS X, and Chrome OS systems, speech synthesis provided by
the operating system should be able to speak any text in at least one the operating system should be able to speak any text in at least one
language. Some users may have a variety of voices available, though, language. Some users may have a variety of voices available, though,
...@@ -166,7 +166,6 @@ argument:</p> ...@@ -166,7 +166,6 @@ argument:</p>
console.log('Voice ' + i + ':'); console.log('Voice ' + i + ':');
console.log(' name: ' + voices[i].voiceName); console.log(' name: ' + voices[i].voiceName);
console.log(' lang: ' + voices[i].lang); console.log(' lang: ' + voices[i].lang);
console.log(' gender: ' + voices[i].gender);
console.log(' extension id: ' + voices[i].extensionId); console.log(' extension id: ' + voices[i].extensionId);
console.log(' event types: ' + voices[i].eventTypes); console.log(' event types: ' + voices[i].eventTypes);
} }
......
...@@ -27,7 +27,6 @@ it provides in the extension manifest, like this:</p> ...@@ -27,7 +27,6 @@ it provides in the extension manifest, like this:</p>
{ {
"voice_name": "Alice", "voice_name": "Alice",
"lang": "en-US", "lang": "en-US",
"gender": "female",
"event_types": ["start", "marker", "end"] "event_types": ["start", "marker", "end"]
}, },
{ {
...@@ -55,10 +54,6 @@ engine used. In the unlikely event that two extensions register voices ...@@ -55,10 +54,6 @@ engine used. In the unlikely event that two extensions register voices
with the same name, a client can specify the ID of the extension that with the same name, a client can specify the ID of the extension that
should do the synthesis.</p> should do the synthesis.</p>
<p>The <code>gender</code> parameter is optional. If your voice corresponds
to a male or female voice, you can use this parameter to help clients
choose the most appropriate voice for their application.</p>
<p>The <code>lang</code> parameter is optional, but highly recommended. <p>The <code>lang</code> parameter is optional, but highly recommended.
Almost always, a voice can synthesize speech in just a single language. Almost always, a voice can synthesize speech in just a single language.
When an engine supports more than one language, it can easily register a When an engine supports more than one language, it can easily register a
......
...@@ -43,13 +43,21 @@ binding.registerCustomHook(function(api) { ...@@ -43,13 +43,21 @@ binding.registerCustomHook(function(api) {
apiFunctions.setHandleRequest('speak', function() { apiFunctions.setHandleRequest('speak', function() {
var args = $Array.from(arguments); var args = $Array.from(arguments);
if (args.length > 1 && args[1] && args[1].onEvent) { if (args.length > 1 && args[1]) {
var id = idGenerator.GetNextId(); if (args[1].onEvent) {
args[1].srcId = id; var id = idGenerator.GetNextId();
handlers[id] = args[1].onEvent; args[1].srcId = id;
// Keep the page alive until the event finishes. handlers[id] = args[1].onEvent;
// Balanced in eventHandler. // Keep the page alive until the event finishes.
lazyBG.IncrementKeepaliveCount(); // Balanced in eventHandler.
lazyBG.IncrementKeepaliveCount();
}
if (args[1].gender) {
console.warn(
'chrome.tts.speak: ' +
'Voice gender is deprecated and values will be ignored starting ' +
'in Chrome 71.');
}
} }
sendRequest('tts.speak', args, sendRequest('tts.speak', args,
bindingUtil ? undefined : this.definition.parameters, bindingUtil ? undefined : this.definition.parameters,
......
...@@ -8,6 +8,9 @@ var binding = apiBridge || require('binding').Binding.create('ttsEngine'); ...@@ -8,6 +8,9 @@ var binding = apiBridge || require('binding').Binding.create('ttsEngine');
var registerArgumentMassager = bindingUtil ? var registerArgumentMassager = bindingUtil ?
$Function.bind(bindingUtil.registerEventArgumentMassager, bindingUtil) : $Function.bind(bindingUtil.registerEventArgumentMassager, bindingUtil) :
require('event_bindings').registerArgumentMassager; require('event_bindings').registerArgumentMassager;
var sendRequest = bindingUtil ?
$Function.bind(bindingUtil.sendRequest, bindingUtil) :
require('sendRequest').sendRequest;
registerArgumentMassager('ttsEngine.onSpeak', function(args, dispatch) { registerArgumentMassager('ttsEngine.onSpeak', function(args, dispatch) {
var text = args[0]; var text = args[0];
...@@ -19,5 +22,23 @@ registerArgumentMassager('ttsEngine.onSpeak', function(args, dispatch) { ...@@ -19,5 +22,23 @@ registerArgumentMassager('ttsEngine.onSpeak', function(args, dispatch) {
dispatch([text, options, sendTtsEvent]); dispatch([text, options, sendTtsEvent]);
}); });
binding.registerCustomHook(function(api) {
// Provide a warning if deprecated parameters are used.
api.apiFunctions.setHandleRequest('updateVoices', function(voices) {
for (var i = 0; i < voices.length; i++) {
if (voices[i].gender) {
console.warn(
'chrome.ttsEngine.updateVoices: ' +
'Voice gender is deprecated and values will be ignored ' +
'starting in Chrome 71.');
break;
}
}
sendRequest(
'ttsEngine.updateVoices', [voices],
bindingUtil ? undefined : this.definition.parameters, undefined);
});
}.bind(this));
if (!apiBridge) if (!apiBridge)
exports.$set('binding', binding.generate()); exports.$set('binding', binding.generate());
...@@ -6,7 +6,6 @@ var testVoiceData = [ ...@@ -6,7 +6,6 @@ var testVoiceData = [
{ {
eventTypes: ['start'], eventTypes: ['start'],
extensionId: 'pkplfbidichfdicaijlchgnapepdginl', extensionId: 'pkplfbidichfdicaijlchgnapepdginl',
gender: 'male',
lang: 'zh-TW', lang: 'zh-TW',
remote: false, remote: false,
voiceName: 'David' voiceName: 'David'
......
...@@ -735,6 +735,9 @@ const char kReservedMessageFound[] = ...@@ -735,6 +735,9 @@ const char kReservedMessageFound[] =
"Reserved key * found in message catalog."; "Reserved key * found in message catalog.";
const char kRulesFileIsInvalid[] = const char kRulesFileIsInvalid[] =
"Invalid value for key '*.*': The provided path is invalid."; "Invalid value for key '*.*': The provided path is invalid.";
const char kTtsGenderIsDeprecated[] =
"Voice gender is deprecated and values will be ignored starting in Chrome "
"71";
const char kUnrecognizedManifestKey[] = "Unrecognized manifest key '*'."; const char kUnrecognizedManifestKey[] = "Unrecognized manifest key '*'.";
const char kUnrecognizedManifestProperty[] = const char kUnrecognizedManifestProperty[] =
"Unrecognized property '*' of manifest key '*'."; "Unrecognized property '*' of manifest key '*'.";
......
...@@ -496,6 +496,7 @@ extern const char kPermissionUnknownOrMalformed[]; ...@@ -496,6 +496,7 @@ extern const char kPermissionUnknownOrMalformed[];
extern const char kPluginsRequirementDeprecated[]; extern const char kPluginsRequirementDeprecated[];
extern const char kReservedMessageFound[]; extern const char kReservedMessageFound[];
extern const char kRulesFileIsInvalid[]; extern const char kRulesFileIsInvalid[];
extern const char kTtsGenderIsDeprecated[];
extern const char kUnrecognizedManifestKey[]; extern const char kUnrecognizedManifestKey[];
extern const char kUnrecognizedManifestProperty[]; extern const char kUnrecognizedManifestProperty[];
extern const char kUrlHandlersInHostedApps[]; extern const char kUrlHandlersInHostedApps[];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment