Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test gets skipped with pattern: os == 'win' && socketprocess_networking && fission OR os == 'mac' && socketprocess_networking && fission OR os == 'mac' && debug OR os == 'linux' && socketprocess_networking
- Manifest: toolkit/components/extensions/test/xpcshell/xpcshell-remote.toml includes toolkit/components/extensions/test/xpcshell/xpcshell-common.toml
- Manifest: toolkit/components/extensions/test/xpcshell/xpcshell.toml includes toolkit/components/extensions/test/xpcshell/xpcshell-common.toml
/* Any copyright is dedicated to the Public Domain.
"use strict";
const { ExtensionAPI } = ExtensionCommon;
const API_CLASS = class extends ExtensionAPI {
getAPI(context) {
return {
testMockAPI: {
async anAsyncAPIMethod(...args) {
const callContextDataBeforeAwait = context.callContextData;
await Promise.resolve();
const callContextDataAfterAwait = context.callContextData;
return {
args,
callContextDataBeforeAwait,
callContextDataAfterAwait,
};
},
},
};
}
};
const API_SCRIPT = `
this.testMockAPI = ${API_CLASS.toString()};
`;
const API_SCHEMA = [
{
namespace: "testMockAPI",
functions: [
{
name: "anAsyncAPIMethod",
type: "function",
async: true,
parameters: [
{
name: "param1",
type: "object",
additionalProperties: {
type: "string",
},
},
{
name: "param2",
type: "string",
},
],
},
],
},
];
const MODULE_INFO = {
testMockAPI: {
schema: `data:,${JSON.stringify(API_SCHEMA)}`,
scopes: ["addon_parent"],
paths: [["testMockAPI"]],
url: URL.createObjectURL(new Blob([API_SCRIPT])),
},
};
add_setup(async function () {
// The blob:-URL registered above in MODULE_INFO gets loaded at
Services.prefs.setBoolPref(
"security.allow_parent_unrestricted_js_loads",
true
);
registerCleanupFunction(() => {
Services.prefs.clearUserPref("security.allow_parent_unrestricted_js_loads");
});
ExtensionParent.apiManager.registerModules(MODULE_INFO);
});
add_task(
async function test_propagated_isHandlingUserInput_on_async_api_methods_calls() {
const extension = ExtensionTestUtils.loadExtension({
manifest: {
browser_specific_settings: { gecko: { id: "@test-ext" } },
},
background() {
browser.test.onMessage.addListener(async (msg, args) => {
if (msg !== "async-method-call") {
browser.test.fail(`Unexpected test message: ${msg}`);
return;
}
try {
let result = await browser.testMockAPI.anAsyncAPIMethod(...args);
browser.test.sendMessage("async-method-call:result", result);
} catch (err) {
browser.test.sendMessage("async-method-call:error", err.message);
}
});
},
});
await extension.startup();
const callArgs = [{ param1: "param1" }, "param2"];
info("Test API method called without handling user input");
extension.sendMessage("async-method-call", callArgs);
const result = await extension.awaitMessage("async-method-call:result");
Assert.deepEqual(
result?.args,
callArgs,
"Got the expected parameters when called without handling user input"
);
Assert.deepEqual(
result?.callContextDataBeforeAwait,
{ isHandlingUserInput: false },
"Got the expected callContextData before awaiting on a promise"
);
Assert.deepEqual(
result?.callContextDataAfterAwait,
null,
"context.callContextData should have been nullified after awaiting on a promise"
);
await withHandlingUserInput(extension, async () => {
extension.sendMessage("async-method-call", callArgs);
const result = await extension.awaitMessage("async-method-call:result");
Assert.deepEqual(
result?.args,
callArgs,
"Got the expected parameters when called while handling user input"
);
Assert.deepEqual(
result?.callContextDataBeforeAwait,
{ isHandlingUserInput: true },
"Got the expected callContextData before awaiting on a promise"
);
Assert.deepEqual(
result?.callContextDataAfterAwait,
null,
"context.callContextData should have been nullified after awaiting on a promise"
);
});
await extension.unload();
}
);