Bug 1289273: Resolve URLs passed to windows.create relative to the caller. r=aswan a=al,ritu
authorKris Maglione <maglione.k@gmail.com>
Wed, 05 Oct 2016 20:27:06 +0100
changeset 350631 35517b0212e4f1d2993c59b527f9e363e2518acb
parent 350630 3a88afcbfdc410d3b67e051568e53ba8bdfbf823
child 350632 52e6d3f9993db0aa688bdb91ea37e03a07d3d068
push id1230
push userjlund@mozilla.com
push dateMon, 31 Oct 2016 18:13:35 +0000
treeherdermozilla-release@5e06e3766db2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaswan, al, ritu
bugs1289273
milestone50.0
Bug 1289273: Resolve URLs passed to windows.create relative to the caller. r=aswan a=al,ritu MozReview-Commit-ID: 3TUIK6EvO3q
browser/components/extensions/schemas/windows.json
browser/components/extensions/test/browser/browser.ini
browser/components/extensions/test/browser/browser_ext_windows_create_url.js
toolkit/components/extensions/Extension.jsm
--- a/browser/components/extensions/schemas/windows.json
+++ b/browser/components/extensions/schemas/windows.json
@@ -282,20 +282,20 @@
           {
             "type": "object",
             "name": "createData",
             "properties": {
               "url": {
                 "description": "A URL or array of URLs to open as tabs in the window. Fully-qualified URLs must include a scheme (i.e. 'http://www.google.com', not 'www.google.com'). Relative URLs will be relative to the current page within the extension. Defaults to the New Tab Page.",
                 "optional": true,
                 "choices": [
-                  { "type": "string" },
+                  { "type": "string", "format": "relativeUrl" },
                   {
                     "type": "array",
-                    "items": { "type": "string" }
+                    "items": { "type": "string", "format": "relativeUrl" }
                   }
                 ]
               },
               "tabId": {
                 "type": "integer",
                 "minimum": 0,
                 "optional": true,
                 "description": "The id of the tab for which you want to adopt to the new window."
--- a/browser/components/extensions/test/browser/browser.ini
+++ b/browser/components/extensions/test/browser/browser.ini
@@ -79,13 +79,14 @@ support-files =
 [browser_ext_tabs_update_url.js]
 [browser_ext_topwindowid.js]
 [browser_ext_webNavigation_getFrames.js]
 [browser_ext_webNavigation_urlbar_transitions.js]
 [browser_ext_windows.js]
 [browser_ext_windows_create.js]
 tags = fullscreen
 [browser_ext_windows_create_tabId.js]
+[browser_ext_windows_create_url.js]
 [browser_ext_windows_events.js]
 [browser_ext_windows_size.js]
 skip-if = os == 'mac' # Fails when windows are randomly opened in fullscreen mode
 [browser_ext_windows_update.js]
 tags = fullscreen
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_windows_create_url.js
@@ -0,0 +1,84 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+add_task(function* testWindowCreate() {
+  let extension = ExtensionTestUtils.loadExtension({
+    manifest: {
+      permissions: ["tabs"],
+    },
+
+    background() {
+      const EXTENSION_URL = browser.runtime.getURL("test.html");
+      const REMOTE_URL = browser.runtime.getURL("test.html");
+
+      let windows = new class extends Map { // eslint-disable-line new-parens
+        get(id) {
+          if (!this.has(id)) {
+            let window = {
+              tabs: new Map(),
+            };
+            window.promise = new Promise(resolve => {
+              window.resolvePromise = resolve;
+            });
+
+            this.set(id, window);
+          }
+
+          return super.get(id);
+        }
+      };
+
+      browser.tabs.onUpdated.addListener((tabId, changed, tab) => {
+        if (changed.status == "complete" && tab.url !== "about:blank") {
+          let window = windows.get(tab.windowId);
+          window.tabs.set(tab.index, tab);
+
+          if (window.tabs.size === window.expectedTabs) {
+            window.resolvePromise(window);
+          }
+        }
+      });
+
+      function create(options) {
+        return browser.windows.create(options).then(window => {
+          let win = windows.get(window.id);
+
+          win.expectedTabs = Array.isArray(options.url) ? options.url.length : 1;
+
+          return win.promise;
+        });
+      }
+
+      Promise.all([
+        create({url: REMOTE_URL}),
+        create({url: "test.html"}),
+        create({url: EXTENSION_URL}),
+        create({url: [REMOTE_URL, "test.html", EXTENSION_URL]}),
+      ]).then(windows => {
+        browser.test.assertEq(REMOTE_URL, windows[0].tabs.get(0).url, "Single, absolute, remote URL");
+
+        browser.test.assertEq(REMOTE_URL, windows[1].tabs.get(0).url, "Single, relative URL");
+
+        browser.test.assertEq(REMOTE_URL, windows[2].tabs.get(0).url, "Single, absolute, extension URL");
+
+        browser.test.assertEq(REMOTE_URL, windows[3].tabs.get(0).url, "url[0]: Absolute, remote URL");
+        browser.test.assertEq(EXTENSION_URL, windows[3].tabs.get(1).url, "url[1]: Relative URL");
+        browser.test.assertEq(EXTENSION_URL, windows[3].tabs.get(2).url, "url[2]: Absolute, extension URL");
+      }).then(() => {
+        browser.test.notifyPass("window-create-url");
+      }).catch(e => {
+        browser.test.fail(`${e} :: ${e.stack}`);
+        browser.test.notifyFail("window-create-url");
+      });
+    },
+
+    files: {
+      "test.html": `<DOCTYPE html><html><head><meta charset="utf-8"></head></html>`,
+    },
+  });
+
+  yield extension.startup();
+  yield extension.awaitFinish("window-create-url");
+  yield extension.unload();
+});
--- a/toolkit/components/extensions/Extension.jsm
+++ b/toolkit/components/extensions/Extension.jsm
@@ -517,16 +517,20 @@ GlobalManager = {
 
     let schemaApi = Management.generateAPIs(extension, context, Management.schemaApis, namespaces);
 
     // Add in any extra API namespaces which do not have implementations
     // outside of their schema file.
     schemaApi.extensionTypes = {};
 
     let schemaWrapper = {
+      get url() {
+        return context.uri.spec;
+      },
+
       get principal() {
         return context.principal;
       },
 
       get cloneScope() {
         return context.cloneScope;
       },