summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/test/xpcshell/head_native_messaging.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/extensions/test/xpcshell/head_native_messaging.js')
-rw-r--r--toolkit/components/extensions/test/xpcshell/head_native_messaging.js131
1 files changed, 131 insertions, 0 deletions
diff --git a/toolkit/components/extensions/test/xpcshell/head_native_messaging.js b/toolkit/components/extensions/test/xpcshell/head_native_messaging.js
new file mode 100644
index 000000000..f7c619b76
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/head_native_messaging.js
@@ -0,0 +1,131 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+/* globals AppConstants, FileUtils */
+/* exported getSubprocessCount, setupHosts, waitForSubprocessExit */
+
+XPCOMUtils.defineLazyModuleGetter(this, "MockRegistry",
+ "resource://testing-common/MockRegistry.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "OS",
+ "resource://gre/modules/osfile.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "setTimeout",
+ "resource://gre/modules/Timer.jsm");
+
+let {Subprocess, SubprocessImpl} = Cu.import("resource://gre/modules/Subprocess.jsm");
+
+
+// It's important that we use a space in this directory name to make sure we
+// correctly handle executing batch files with spaces in their path.
+let tmpDir = FileUtils.getDir("TmpD", ["Native Messaging"]);
+tmpDir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
+
+do_register_cleanup(() => {
+ tmpDir.remove(true);
+});
+
+function getPath(filename) {
+ return OS.Path.join(tmpDir.path, filename);
+}
+
+const ID = "native@tests.mozilla.org";
+
+
+function* setupHosts(scripts) {
+ const PERMS = {unixMode: 0o755};
+
+ const env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
+ const pythonPath = yield Subprocess.pathSearch(env.get("PYTHON"));
+
+ function* writeManifest(script, scriptPath, path) {
+ let body = `#!${pythonPath} -u\n${script.script}`;
+
+ yield OS.File.writeAtomic(scriptPath, body);
+ yield OS.File.setPermissions(scriptPath, PERMS);
+
+ let manifest = {
+ name: script.name,
+ description: script.description,
+ path,
+ type: "stdio",
+ allowed_extensions: [ID],
+ };
+
+ let manifestPath = getPath(`${script.name}.json`);
+ yield OS.File.writeAtomic(manifestPath, JSON.stringify(manifest));
+
+ return manifestPath;
+ }
+
+ switch (AppConstants.platform) {
+ case "macosx":
+ case "linux":
+ let dirProvider = {
+ getFile(property) {
+ if (property == "XREUserNativeMessaging") {
+ return tmpDir.clone();
+ } else if (property == "XRESysNativeMessaging") {
+ return tmpDir.clone();
+ }
+ return null;
+ },
+ };
+
+ Services.dirsvc.registerProvider(dirProvider);
+ do_register_cleanup(() => {
+ Services.dirsvc.unregisterProvider(dirProvider);
+ });
+
+ for (let script of scripts) {
+ let path = getPath(`${script.name}.py`);
+
+ yield writeManifest(script, path, path);
+ }
+ break;
+
+ case "win":
+ const REGKEY = String.raw`Software\Mozilla\NativeMessagingHosts`;
+
+ let registry = new MockRegistry();
+ do_register_cleanup(() => {
+ registry.shutdown();
+ });
+
+ for (let script of scripts) {
+ // It's important that we use a space in this filename. See directory
+ // name comment above.
+ let batPath = getPath(`batch ${script.name}.bat`);
+ let scriptPath = getPath(`${script.name}.py`);
+
+ let batBody = `@ECHO OFF\n${pythonPath} -u "${scriptPath}" %*\n`;
+ yield OS.File.writeAtomic(batPath, batBody);
+
+ // Create absolute and relative path versions of the entry.
+ for (let [name, path] of [[script.name, batPath],
+ [`relative.${script.name}`, OS.Path.basename(batPath)]]) {
+ script.name = name;
+ let manifestPath = yield writeManifest(script, scriptPath, path);
+
+ registry.setValue(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
+ `${REGKEY}\\${script.name}`, "", manifestPath);
+ }
+ }
+ break;
+
+ default:
+ ok(false, `Native messaging is not supported on ${AppConstants.platform}`);
+ }
+}
+
+
+function getSubprocessCount() {
+ return SubprocessImpl.Process.getWorker().call("getProcesses", [])
+ .then(result => result.size);
+}
+function waitForSubprocessExit() {
+ return SubprocessImpl.Process.getWorker().call("waitForNoProcesses", []).then(() => {
+ // Return to the main event loop to give IO handlers enough time to consume
+ // their remaining buffered input.
+ return new Promise(resolve => setTimeout(resolve, 0));
+ });
+}