Bug 1281995 Support relative paths in host manifest on windows r?kmag draft
authorAndrew Swan <aswan@mozilla.com>
Mon, 27 Jun 2016 14:52:57 -0700
changeset 384145 9f9a9f1a85d082301ed3de8f3886d1f701feb2cc
parent 384060 dbb31bcad5a1f60a35b5600ea1578d9b9fa55237
child 524622 86264dbf81a4ecdef2dbc8326b8774f13ebabb58
push id22181
push useraswan@mozilla.com
push dateTue, 05 Jul 2016 17:47:13 +0000
reviewerskmag
bugs1281995
milestone50.0a1
Bug 1281995 Support relative paths in host manifest on windows r?kmag MozReview-Commit-ID: DaqYdPGQC3A
toolkit/components/extensions/NativeMessaging.jsm
toolkit/components/extensions/test/mochitest/test_chrome_ext_native_messaging.html
--- a/toolkit/components/extensions/NativeMessaging.jsm
+++ b/toolkit/components/extensions/NativeMessaging.jsm
@@ -185,20 +185,28 @@ this.NativeApp = class extends EventEmit
         if (!hostInfo) {
           throw new Error(`No such native application ${application}`);
         }
 
         if (!hostInfo.manifest.allowed_extensions.includes(extension.id)) {
           throw new Error(`This extension does not have permission to use native application ${application}`);
         }
 
+        let command = hostInfo.manifest.path;
+        if (AppConstants.platform == "win") {
+          // OS.Path.join() ignores anything before the last absolute path
+          // it sees, so if command is already absolute, it remains unchanged
+          // here.  If it is relative, we get the proper absolute path here.
+          command = OS.Path.join(OS.Path.dirname(hostInfo.path), command);
+        }
+
         let subprocessOpts = {
-          command: hostInfo.manifest.path,
+          command: command,
           arguments: [hostInfo.path],
-          workdir: OS.Path.dirname(hostInfo.manifest.path),
+          workdir: OS.Path.dirname(command),
         };
         return Subprocess.call(subprocessOpts);
       }).then(proc => {
         this.startupPromise = null;
         this.proc = proc;
         this._startRead();
         this._startWrite();
       }).catch(err => {
--- a/toolkit/components/extensions/test/mochitest/test_chrome_ext_native_messaging.html
+++ b/toolkit/components/extensions/test/mochitest/test_chrome_ext_native_messaging.html
@@ -182,16 +182,27 @@ add_task(function* setup() {
           type: "stdio",
           allowed_extensions: [ID],
         };
         let manifestPath = getPath(`${script.name}.json`);
         yield OS.File.writeAtomic(manifestPath, JSON.stringify(manifest));
 
         registry.setValue(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
                           REGKEY, script.name, manifestPath);
+
+        // Create a version of the manifest with a relative path
+        let relativeName = `relative.${script.name}`;
+        manifest.name = relativeName;
+        manifest.path = `${script.name}.bat`;
+
+        manifestPath = getPath(`${relativeName}.json`);
+        yield OS.File.writeAtomic(manifestPath, JSON.stringify(manifest));
+
+        registry.setValue(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
+                          REGKEY, relativeName, manifestPath);
       }
       break;
 
     default:
       ok(false, `Native messaing is not supported on ${AppConstants.platform}`);
   }
 });
 
@@ -266,16 +277,47 @@ add_task(function* test_happy_path() {
 
   let procCount = yield getSubprocessCount();
   is(procCount, 1, "subprocess is still running");
   let exitPromise = waitForSubprocessExit();
   yield extension.unload();
   yield exitPromise;
 });
 
+if (AppConstants.platform == "win") {
+  // "relative.echo" has a relative path in the host manifest.
+  add_task(function* test_relative_path() {
+    function background() {
+      let port = browser.runtime.connectNative("relative.echo");
+      let MSG = "test relative echo path";
+      port.onMessage.addListener(msg => {
+        browser.test.assertEq(MSG, msg, "Got expected message back");
+        browser.test.sendMessage("done");
+      });
+      port.postMessage(MSG);
+    }
+
+    let extension = ExtensionTestUtils.loadExtension({
+      background: `(${background})()`,
+      manifest: {
+        permissions: ["nativeMessaging"],
+      },
+    }, ID);
+
+    yield extension.startup();
+    yield extension.awaitMessage("done");
+
+    let procCount = yield getSubprocessCount();
+    is(procCount, 1, "subprocess is still running");
+    let exitPromise = waitForSubprocessExit();
+    yield extension.unload();
+    yield exitPromise;
+  });
+}
+
 // Test sendNativeMessage()
 add_task(function* test_sendNativeMessage() {
   function background() {
     let MSG = {test: "hello world"};
 
     // Check error handling
     browser.runtime.sendNativeMessage("nonexistent", MSG).then(() => {
       browser.test.fail("sendNativeMessage() to a nonexistent app should have failed");