mirror of
https://github.com/HeyPuter/firefox.git
synced 2026-11-13 20:14:57 -10:00
Automatic update from web-platform-tests Update on-device Web Speech API with spec changes This CL updates the Web Speech API with the following spec[1] changes: - Rename "availableOnDevice" and "installOnDevice" to "available" and "install" - Update both APIs to support querying availability/installing multiple languages in a single call via a new SpeechRecognitionOptions - Replace the SpeechRecognitionMode mode with a processLocally attribute [1] https://webaudio.github.io/web-speech-api/ Bug: 40286514 Change-Id: Ib9a924a1a69bcaa9cdde219c591bcd945bbe7a86 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6599497 Commit-Queue: Evan Liu <[email protected]> Reviewed-by: Daniel Cheng <[email protected]> Reviewed-by: Frank Liberato <[email protected]> Reviewed-by: Fred Shih <[email protected]> Cr-Commit-Position: refs/heads/main@{#1468347} -- wpt-commits: 02dd61b64c13e0d6c177af9b9e6d5f6dc06a4c70 wpt-pr: 52905
301 lines
10 KiB
HTML
301 lines
10 KiB
HTML
<!DOCTYPE html>
|
|
<title>SpeechRecognition install</title>
|
|
<script src="/resources/testharness.js"></script>
|
|
<script src="/resources/testharnessreport.js"></script>
|
|
<script src="/resources/testdriver.js"></script>
|
|
<script src="/resources/testdriver-vendor.js"></script>
|
|
<script>
|
|
promise_test(async (t) => {
|
|
const validLang = "en-US";
|
|
const validLangAlternateLocale = "en-GB";
|
|
const invalidLang = "invalid language code";
|
|
window.SpeechRecognition =
|
|
window.SpeechRecognition || window.webkitSpeechRecognition;
|
|
const validOptions = { langs: [validLang], processLocally: true };
|
|
const validAlternateOptions = { langs: [validLangAlternateLocale], processLocally: true };
|
|
const invalidOptions = { langs: [invalidLang], processLocally: true };
|
|
|
|
// Check the availablility of the on-device language pack.
|
|
const initialAvailabilityPromise =
|
|
SpeechRecognition.available(validOptions);
|
|
assert_true(
|
|
initialAvailabilityPromise instanceof Promise,
|
|
"available should return a Promise."
|
|
);
|
|
|
|
const initialAvailabilityResult = await initialAvailabilityPromise;
|
|
assert_true(
|
|
typeof initialAvailabilityResult === "string",
|
|
"The resolved value of the available promise should be a string."
|
|
);
|
|
|
|
if (initialAvailabilityResult === "downloadable") {
|
|
// Attempt to call install directly, without a user gesture with a
|
|
// language that is downloadable but not installed.
|
|
const installWithoutUserGesturePromise =
|
|
SpeechRecognition.install(validOptions);
|
|
|
|
// Assert that the promise rejects with NotAllowedError.
|
|
await promise_rejects_dom(
|
|
t,
|
|
"NotAllowedError",
|
|
window.DOMException,
|
|
installWithoutUserGesturePromise, "SpeechRecognition.install() " +
|
|
"must reject with NotAllowedError if called without a user gesture for on-device."
|
|
);
|
|
|
|
// Test that it returns a promise when called with a valid language.
|
|
const validResultPromise = test_driver.bless(
|
|
"Call SpeechRecognition.install with a valid language",
|
|
() => SpeechRecognition.install(validOptions)
|
|
);
|
|
const validInstallPromise = test_driver.bless(
|
|
"Call SpeechRecognition.install with valid options for on-device",
|
|
() => SpeechRecognition.install(validOptions)
|
|
);
|
|
assert_true(
|
|
validInstallPromise instanceof Promise,
|
|
"install (with gesture, for on-device) should return a Promise."
|
|
);
|
|
|
|
// Verify the resolved value is a boolean.
|
|
const validInstallResult = await validInstallPromise;
|
|
assert_true(
|
|
typeof validInstallResult === "boolean",
|
|
"The resolved value of the install promise (on-device) should be a boolean."
|
|
);
|
|
|
|
// Verify that the method returns true when called with a supported language.
|
|
assert_equals(
|
|
validInstallResult,
|
|
true,
|
|
"install should resolve with `true` when called with " +
|
|
"supported options for on-device."
|
|
);
|
|
|
|
// Verify that the newly installed language pack is available.
|
|
const availableOnDeviceResultPromise =
|
|
SpeechRecognition.available(validOptions);
|
|
assert_true(
|
|
availableOnDeviceResultPromise instanceof Promise,
|
|
"available should return a Promise."
|
|
);
|
|
|
|
const availableOnDeviceResult = await availableOnDeviceResultPromise;
|
|
assert_true(
|
|
typeof availableOnDeviceResult === "string",
|
|
"The resolved value of the available promise should be a string."
|
|
);
|
|
|
|
assert_true(
|
|
availableOnDeviceResult === "available",
|
|
"The resolved value of the available promise (on-device) should be " +
|
|
"'available'."
|
|
);
|
|
|
|
// Verify that the newly installed language pack is available for an alternate locale.
|
|
const alternateLocaleResultPromise =
|
|
SpeechRecognition.available(validAlternateOptions);
|
|
assert_true(
|
|
alternateLocaleResultPromise instanceof Promise,
|
|
"available should return a Promise."
|
|
);
|
|
|
|
const alternateLocaleResult = await alternateLocaleResultPromise;
|
|
assert_true(
|
|
typeof alternateLocaleResult === "string",
|
|
"The resolved value of the available promise should be a string."
|
|
);
|
|
|
|
assert_true(
|
|
alternateLocaleResult === "available",
|
|
"The resolved value of the available promise (on-device, alternate locale) should be " +
|
|
"'available'."
|
|
);
|
|
|
|
// Verify that installing an already installed language resolves to true.
|
|
const secondInstallPromise = test_driver.bless(
|
|
"Call SpeechRecognition.install for an already installed on-device language",
|
|
() => SpeechRecognition.install(validOptions)
|
|
);
|
|
assert_true(
|
|
secondInstallPromise instanceof Promise,
|
|
"install (with gesture, for already installed on-device language) should " +
|
|
"return a Promise."
|
|
);
|
|
const secondInstallResult = await secondInstallPromise;
|
|
assert_true(
|
|
typeof secondInstallResult === "boolean",
|
|
"The resolved value of the second install promise (on-device) should be a " +
|
|
"boolean."
|
|
);
|
|
assert_equals(
|
|
secondInstallResult,
|
|
true,
|
|
"install should resolve with `true` if the on-device language is already " +
|
|
"installed."
|
|
);
|
|
}
|
|
|
|
// Test that it returns a promise and resolves to false for unsupported lang.
|
|
const invalidInstallPromise = test_driver.bless(
|
|
"Call SpeechRecognition.install with unsupported on-device options",
|
|
() => SpeechRecognition.install(invalidOptions)
|
|
);
|
|
assert_true(
|
|
invalidInstallPromise instanceof Promise,
|
|
"install (with gesture, for unsupported on-device options) should return " +
|
|
"a Promise."
|
|
);
|
|
const invalidInstallResult = await invalidInstallPromise;
|
|
assert_true(
|
|
typeof invalidInstallResult === "boolean",
|
|
"The resolved value of the install promise (unsupported on-device options) " +
|
|
"should be a boolean."
|
|
);
|
|
assert_equals(
|
|
invalidInstallResult,
|
|
false,
|
|
"install should resolve with `false` when called with " +
|
|
"unsupported on-device options."
|
|
);
|
|
}, "SpeechRecognition.install resolves with a boolean value for on-device " +
|
|
"(with user gesture).");
|
|
|
|
promise_test(async (t) => {
|
|
const iframe = document.createElement("iframe");
|
|
document.body.appendChild(iframe);
|
|
const frameWindow = iframe.contentWindow;
|
|
const frameDOMException = frameWindow.DOMException;
|
|
const frameSpeechRecognition =
|
|
frameWindow.SpeechRecognition || frameWindow.webkitSpeechRecognition;
|
|
const options = { langs: ["en-US"], processLocally: true };
|
|
|
|
iframe.remove();
|
|
await promise_rejects_dom(
|
|
t,
|
|
"InvalidStateError",
|
|
frameDOMException,
|
|
test_driver.bless(
|
|
"Call SpeechRecognition.install in a detached frame context for on-device",
|
|
() => {
|
|
return frameSpeechRecognition.install(options);
|
|
}
|
|
)
|
|
);
|
|
}, "SpeechRecognition.install rejects in a detached context for on-device.");
|
|
|
|
promise_test(async (t) => {
|
|
const iframe = document.createElement("iframe");
|
|
iframe.setAttribute("allow",
|
|
"on-device-speech-recognition 'none'");
|
|
document.body.appendChild(iframe);
|
|
t.add_cleanup(() => iframe.remove());
|
|
|
|
await new Promise(resolve => {
|
|
if (iframe.contentWindow &&
|
|
iframe.contentWindow.document.readyState === 'complete') {
|
|
resolve();
|
|
} else {
|
|
iframe.onload = resolve;
|
|
}
|
|
});
|
|
|
|
const frameWindow = iframe.contentWindow;
|
|
const frameSpeechRecognition = frameWindow.SpeechRecognition ||
|
|
frameWindow.webkitSpeechRecognition;
|
|
const frameDOMException = frameWindow.DOMException;
|
|
|
|
assert_true(!!frameSpeechRecognition,
|
|
"SpeechRecognition should exist in iframe.");
|
|
assert_true(!!frameSpeechRecognition.install,
|
|
"install method should exist on SpeechRecognition in iframe.");
|
|
|
|
const options = { langs: ["en-US"], processLocally: true };
|
|
await promise_rejects_dom(
|
|
t,
|
|
"NotAllowedError",
|
|
frameDOMException,
|
|
frameSpeechRecognition.install(options),
|
|
"install should reject with NotAllowedError if " +
|
|
"'install-on-device-speech-recognition' Permission Policy is " +
|
|
"disabled."
|
|
);
|
|
}, "SpeechRecognition.install rejects for on-device if " +
|
|
"'install-on-device-speech-recognition' Permission Policy is disabled.");
|
|
|
|
promise_test(async (t) => {
|
|
const html = `
|
|
<!DOCTYPE html>
|
|
<script>
|
|
window.addEventListener('message', async (event) => {
|
|
try {
|
|
const SpeechRecognition = window.SpeechRecognition ||
|
|
window.webkitSpeechRecognition;
|
|
if (!SpeechRecognition || !SpeechRecognition.install) {
|
|
parent.postMessage({
|
|
type: "rejection",
|
|
name: "NotSupportedError",
|
|
message: "API not available"
|
|
}, "*");
|
|
return;
|
|
}
|
|
|
|
const options = { langs: ["en-US"], processLocally: true };
|
|
await SpeechRecognition.install(options);
|
|
parent.postMessage({ type: "resolution", result: "success" }, "*");
|
|
} catch (err) {
|
|
parent.postMessage({
|
|
type: "rejection",
|
|
name: err.name,
|
|
message: err.message
|
|
}, "*");
|
|
}
|
|
});
|
|
<\/script>
|
|
`;
|
|
|
|
// Create a cross-origin Blob URL by fetching from remote origin
|
|
const blob = new Blob([html], { type: "text/html" });
|
|
const blobUrl = URL.createObjectURL(blob);
|
|
|
|
const iframe = document.createElement("iframe");
|
|
iframe.src = blobUrl;
|
|
iframe.setAttribute("sandbox", "allow-scripts");
|
|
document.body.appendChild(iframe);
|
|
t.add_cleanup(() => iframe.remove());
|
|
|
|
await new Promise(resolve => iframe.onload = resolve);
|
|
|
|
const testResult = await new Promise((resolve, reject) => {
|
|
const timeoutId = t.step_timeout(() => {
|
|
reject(new Error("Timed out waiting for message from iframe"));
|
|
}, 6000);
|
|
|
|
window.addEventListener("message", t.step_func((event) => {
|
|
if (event.source !== iframe.contentWindow) return;
|
|
clearTimeout(timeoutId);
|
|
resolve(event.data);
|
|
}));
|
|
|
|
iframe.contentWindow.postMessage("runTest", "*");
|
|
});
|
|
|
|
assert_equals(
|
|
testResult.type,
|
|
"rejection",
|
|
"Should reject due to cross-origin restriction"
|
|
);
|
|
assert_equals(
|
|
testResult.name,
|
|
"NotAllowedError",
|
|
"Should reject with NotAllowedError"
|
|
);
|
|
assert_true(
|
|
testResult.message.includes("cross-origin iframe") ||
|
|
testResult.message.includes("cross-site subframe"),
|
|
`Error message should reference cross-origin. Got: "${testResult.message}"`
|
|
);
|
|
}, "SpeechRecognition.install should reject for on-device in a cross-origin iframe.");
|
|
</script>
|