Bug 724161: simplify some javascript:/data: drop checks, r=dao, a=akeybl
authorGavin Sharp <gavin@gavinsharp.com>
Tue, 14 Feb 2012 15:08:35 -0800
changeset 87220 b740b95280281e90cdd5d8941b675581cff066b3
parent 87219 6ff957842178637b56f1303907cb97b77f3d607b
child 87221 c00445fcd26d3d99b76328b0382a1248bc4c10d0
push id879
push usergsharp@mozilla.com
push dateTue, 21 Feb 2012 18:20:25 +0000
treeherdermozilla-aurora@b740b9528028 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdao, akeybl
bugs724161
milestone12.0a2
Bug 724161: simplify some javascript:/data: drop checks, r=dao, a=akeybl
browser/base/content/tabbrowser.xml
browser/base/content/test/Makefile.in
browser/base/content/test/browser_tabDrop.js
toolkit/content/tests/browser/Makefile.in
toolkit/content/tests/browser/browser_browserDrop.js
toolkit/content/widgets/browser.xml
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -3527,22 +3527,24 @@
 
           this.tabbrowser.swapBrowsersAndCloseOther(newTab, draggedTab);
 
           // We need to select the tab after we've done
           // swapBrowsersAndCloseOther, so that the updateCurrentBrowser
           // it triggers will correctly update our URL bar.
           this.tabbrowser.selectedTab = newTab;
         } else {
-          let url = browserDragAndDrop.drop(event, { });
+          // Pass true to disallow dropping javascript: or data: urls
+          let url;
+          try {
+            url = browserDragAndDrop.drop(event, { }, true);
+          } catch (ex) {}
 
           // valid urls don't contain spaces ' '; if we have a space it isn't a valid url.
-          // Also disallow dropping javascript: or data: urls--bail out
-          if (!url || !url.length || url.indexOf(" ", 0) != -1 ||
-              /^\s*(javascript|data):/.test(url))
+          if (!url || url.indexOf(" ") != -1)
             return;
 
           let bgLoad = Services.prefs.getBoolPref("browser.tabs.loadInBackground");
 
           if (event.shiftKey)
             bgLoad = !bgLoad;
 
           let tab = this._getDragTargetTab(event);
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -262,16 +262,17 @@ endif
                  test_bug628179.html \
                  browser_wyciwyg_urlbarCopying.js \
                  test_wyciwyg_copying.html \
                  authenticate.sjs \
                  browser_minimize.js \
                  browser_aboutSyncProgress.js \
                  browser_middleMouse_inherit.js \
                  redirect_bug623155.sjs \
+                 browser_tabDrop.js \
                  $(NULL)
 
 ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 _BROWSER_FILES += \
 		browser_bug462289.js \
 		$(NULL)
 else
 _BROWSER_FILES += \
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_tabDrop.js
@@ -0,0 +1,71 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test() {
+  waitForExplicitFinish();
+
+  let newTab = gBrowser.selectedTab = gBrowser.addTab("about:blank", {skipAnimation: true});
+  registerCleanupFunction(function () {
+    gBrowser.removeTab(newTab);
+  });
+
+  let scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
+                     getService(Ci.mozIJSSubScriptLoader);
+  let chromeUtils = {};
+  scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/ChromeUtils.js", chromeUtils);
+
+  let tabContainer = gBrowser.tabContainer;
+  var receivedDropCount = 0;
+  function dropListener() {
+    receivedDropCount++;
+    if (receivedDropCount == triggeredDropCount) {
+      is(openedTabs, validDropCount, "correct number of tabs were opened");
+      executeSoon(finish);
+    }
+  }
+  tabContainer.addEventListener("drop", dropListener, false);
+  registerCleanupFunction(function () {
+    tabContainer.removeEventListener("drop", dropListener, false);
+  });
+
+  var openedTabs = 0;
+  function tabOpenListener(e) {
+    openedTabs++;
+    let tab = e.target;
+    executeSoon(function () {
+      gBrowser.removeTab(tab);
+    });
+  }
+
+  tabContainer.addEventListener("TabOpen", tabOpenListener, false);
+  registerCleanupFunction(function () {
+    tabContainer.removeEventListener("TabOpen", tabOpenListener, false);
+  });
+
+  var triggeredDropCount = 0;
+  var validDropCount = 0;
+  function drop(text, valid) {
+    triggeredDropCount++;
+    if (valid)
+      validDropCount++;
+    executeSoon(function () {
+      // A drop type of "link" onto an existing tab would normally trigger a
+      // load in that same tab, but tabbrowser code in _getDragTargetTab treats
+      // drops on the outer edges of a tab differently (loading a new tab
+      // instead). The events created by synthesizeDrop have all of their
+      // coordinates set to 0 (screenX/screenY), so they're treated as drops
+      // on the outer edge of the tab, thus they open new tabs.
+      chromeUtils.synthesizeDrop(newTab, newTab, [[{type: "text/plain", data: text}]], "link", window, EventUtils);
+    });
+  }
+
+  // Begin and end with valid drops to make sure we wait for all drops before
+  // ending the test
+  drop("mochi.test/first", true);
+  drop("javascript:'bad'");
+  drop("jAvascript:'bad'");
+  drop("space bad");
+  drop("mochi.test/second", true);
+  drop("data:text/html,bad");
+  drop("mochi.test/third", true);
+}
--- a/toolkit/content/tests/browser/Makefile.in
+++ b/toolkit/content/tests/browser/Makefile.in
@@ -51,13 +51,14 @@ DIRS = \
 include $(topsrcdir)/config/rules.mk
 
 _BROWSER_TEST_FILES = \
   browser_keyevents_during_autoscrolling.js \
   browser_bug295977_autoscroll_overflow.js \
   browser_bug594509.js \
   browser_Geometry.js \
   browser_save_resend_postdata.js \
+  browser_browserDrop.js \
   browser_Services.js \
   $(NULL)
 
 libs:: $(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/toolkit/content/tests/browser/browser_browserDrop.js
@@ -0,0 +1,61 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test() {
+  waitForExplicitFinish();
+
+  let newTab = gBrowser.selectedTab = gBrowser.addTab();
+  registerCleanupFunction(function () {
+    gBrowser.removeTab(newTab);
+  });
+
+  let scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
+                     getService(Ci.mozIJSSubScriptLoader);
+  let chromeUtils = {};
+  scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/ChromeUtils.js", chromeUtils);
+
+  let browser = gBrowser.selectedBrowser;
+
+  var linkHandlerActivated = 0;
+  // Don't worry about clobbering the droppedLinkHandler, since we're closing
+  // this tab after the test anyways
+  browser.droppedLinkHandler = function dlh(e, url, name) {
+    linkHandlerActivated++;
+    ok(!/(javascript|data)/i.test(url), "javascript link should not be dropped");
+  }
+
+  var receivedDropCount = 0;
+  function dropListener() {
+    receivedDropCount++;
+    if (receivedDropCount == triggeredDropCount) {
+      // Wait for the browser's system-phase event handler to run.
+      executeSoon(function () {
+        is(linkHandlerActivated, validDropCount,
+           "link handler was called correct number of times");
+        finish();
+      })
+    }
+  }
+  browser.addEventListener("drop", dropListener, false);
+  registerCleanupFunction(function () {
+    browser.removeEventListener("drop", dropListener, false);
+  });
+
+  var triggeredDropCount = 0;
+  var validDropCount = 0;
+  function drop(text, valid) {
+    triggeredDropCount++;
+    if (valid)
+      validDropCount++;
+    executeSoon(function () {
+      chromeUtils.synthesizeDrop(browser, browser, [[{type: "text/plain", data: text}]], "copy", window, EventUtils);
+    });
+  }
+
+  drop("mochi.test/first", true);
+  drop("javascript:'bad'");
+  drop("jAvascript:'also bad'");
+  drop("mochi.test/second", true);
+  drop("data:text/html,bad");
+  drop("mochi.test/third", true);
+}
--- a/toolkit/content/widgets/browser.xml
+++ b/toolkit/content/widgets/browser.xml
@@ -1294,25 +1294,22 @@
       <![CDATA[
         if (!this.droppedLinkHandler || event.defaultPrevented)
           return;
 
         let name = { };
         let linkHandler = Components.classes["@mozilla.org/content/dropped-link-handler;1"].
                             getService(Components.interfaces.nsIDroppedLinkHandler);
         try {
-          var uri = linkHandler.dropLink(event, name);
+          // Pass true to prevent the dropping of javascript:/data: URIs
+          var uri = linkHandler.dropLink(event, name, true);
         } catch (ex) {
           return;
         }
 
-        // don't allow dropping javascript or data urls
-        if (/^\s*(javascript|data):/.test(uri))
-          return;
-
         if (uri) {
           this.droppedLinkHandler(event, uri, name.value);
         }
       ]]>
       </handler>
     </handlers>
 
   </binding>