Bug 1268943 - Middle mouse click on links in settings does nothing (should open in new tab). r=gijs
authorJared Wein <jwein@mozilla.com>
Fri, 13 May 2016 09:53:00 -0400
changeset 336448 a356bf6785676f4db1cc7d25eb65f7cd84203408
parent 336447 085a53f65ff321220eab2d691b970dd247917a81
child 336449 aeeab770eafee07e2f2b9330f5bf6e2f55552202
push id6249
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 13:59:36 +0000
treeherdermozilla-beta@bad9d4f5bf7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgijs
bugs1268943
milestone49.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1268943 - Middle mouse click on links in settings does nothing (should open in new tab). r=gijs MozReview-Commit-ID: D8okQLio0K8
browser/components/nsBrowserGlue.js
toolkit/content/tests/browser/browser.ini
toolkit/content/tests/browser/browser_label_textlink.js
toolkit/content/widgets/text.xml
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -378,17 +378,19 @@ BrowserGlue.prototype = {
       case "initial-migration-did-import-default-bookmarks":
         this._initPlaces(true);
         break;
       case "handle-xul-text-link":
         let linkHandled = subject.QueryInterface(Ci.nsISupportsPRBool);
         if (!linkHandled.data) {
           let win = RecentWindow.getMostRecentBrowserWindow();
           if (win) {
-            win.openUILinkIn(data, "tab");
+            data = JSON.parse(data);
+            let where = win.whereToOpenLink(data);
+            win.openUILinkIn(data.href, where);
             linkHandled.data = true;
           }
         }
         break;
       case "profile-before-change":
          // Any component depending on Places should be finalized in
          // _onPlacesShutdown.  Any component that doesn't need to act after
          // the UI has gone should be finalized in _onQuitApplicationGranted.
--- a/toolkit/content/tests/browser/browser.ini
+++ b/toolkit/content/tests/browser/browser.ini
@@ -9,16 +9,17 @@ support-files =
 [browser_bug594509.js]
 [browser_bug982298.js]
 [browser_bug1198465.js]
 [browser_contentTitle.js]
 [browser_default_image_filename.js]
 [browser_f7_caret_browsing.js]
 skip-if = e10s
 [browser_findbar.js]
+[browser_label_textlink.js]
 [browser_isSynthetic.js]
 support-files =
   empty.png
 [browser_keyevents_during_autoscrolling.js]
 [browser_save_resend_postdata.js]
 support-files =
   common/mockTransfer.js
   data/post_form_inner.sjs
new file mode 100644
--- /dev/null
+++ b/toolkit/content/tests/browser/browser_label_textlink.js
@@ -0,0 +1,38 @@
+add_task(function* () {
+  yield BrowserTestUtils.withNewTab({gBrowser, url: "about:config"}, function*(browser) {
+    let newTabURL = "http://www.example.com/";
+    yield ContentTask.spawn(browser, newTabURL, function*(newTabURL) {
+      let doc = content.document;
+      let label = doc.createElement("label");
+      label.href = newTabURL;
+      label.id = "textlink-test";
+      label.className = "text-link";
+      label.textContent = "click me";
+      doc.documentElement.append(label);
+    });
+
+    // Test that click will open tab in foreground.
+    let awaitNewTab = BrowserTestUtils.waitForNewTab(gBrowser, newTabURL);
+    yield BrowserTestUtils.synthesizeMouseAtCenter("#textlink-test", {}, browser);
+    let newTab = yield awaitNewTab;
+    is(newTab.linkedBrowser, gBrowser.selectedBrowser, "selected tab should be example page");
+    yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
+
+    // Test that ctrl+shift+click/meta+shift+click will open tab in background.
+    awaitNewTab = BrowserTestUtils.waitForNewTab(gBrowser, newTabURL);
+    yield BrowserTestUtils.synthesizeMouseAtCenter("#textlink-test",
+      {ctrlKey: true, metaKey: true, shiftKey: true},
+      browser);
+    yield awaitNewTab;
+    is(gBrowser.selectedBrowser, browser, "selected tab should be original tab");
+    yield BrowserTestUtils.removeTab(gBrowser.tabs[gBrowser.tabs.length - 1]);
+
+    // Middle-clicking should open tab in foreground.
+    awaitNewTab = BrowserTestUtils.waitForNewTab(gBrowser, newTabURL);
+    yield BrowserTestUtils.synthesizeMouseAtCenter("#textlink-test",
+      {button: 1}, browser);
+    newTab = yield awaitNewTab;
+    is(newTab.linkedBrowser, gBrowser.selectedBrowser, "selected tab should be example page");
+    yield BrowserTestUtils.removeTab(gBrowser.tabs[gBrowser.tabs.length - 1]);
+  });
+});
--- a/toolkit/content/widgets/text.xml
+++ b/toolkit/content/widgets/text.xml
@@ -351,19 +351,32 @@
           aEvent.preventDefault();
           href = uri ? uri.spec : href;
 
           // Try handing off the link to the host application, e.g. for
           // opening it in a tabbed browser.
           var linkHandled = Components.classes["@mozilla.org/supports-PRBool;1"]
                                       .createInstance(Components.interfaces.nsISupportsPRBool);
           linkHandled.data = false;
+          let {shiftKey, ctrlKey, metaKey, altKey, button} = aEvent;
+          if (!shiftKey && !altKey) {
+            // Preserve legacy behavior of non-modifier left-clicks
+            // opening in a new selected tab.
+            let {AppConstants} =
+              Components.utils.import("resource://gre/modules/AppConstants.jsm", {});
+            if (AppConstants.platform == "macosx") {
+              metaKey = true;
+            } else {
+              ctrlKey = true;
+            }
+          }
+          let data = {shiftKey, ctrlKey, metaKey, altKey, button, href};
           Components.classes["@mozilla.org/observer-service;1"]
                     .getService(Components.interfaces.nsIObserverService)
-                    .notifyObservers(linkHandled, "handle-xul-text-link", href);
+                    .notifyObservers(linkHandled, "handle-xul-text-link", JSON.stringify(data));
           if (linkHandled.data)
             return;
 
           // otherwise, fall back to opening the anchor directly
           var win = window;
           if (window instanceof Components.interfaces.nsIDOMChromeWindow) {
             while (win.opener && !win.opener.closed)
               win = win.opener;
@@ -371,13 +384,14 @@
           win.open(href);
         ]]>
         </body>
       </method>
     </implementation>
 
     <handlers>
       <handler event="click" phase="capturing" button="0" action="this.open(event)"/>
+      <handler event="click" phase="capturing" button="1" action="this.open(event)"/>
       <handler event="keypress" preventdefault="true" keycode="VK_RETURN" action="this.click()" />
     </handlers>
   </binding>
 
 </bindings>