Make nsTransferable::GetTransferData assign the out params even when it returns an error since some callers depend on it (regression fix). b=565392 r=dbaron
authorMats Palmgren <matspal@gmail.com>
Wed, 09 Jun 2010 21:08:09 +0200
changeset 43408 b3404e64afade2774aca7fcff5221bec22cac6bd
parent 43407 3b326ae18eba057b9368d75cb2dde732745476bc
child 43409 18c728e4b4c6b63fba394fd5c6d0e743344a8c29
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs565392
milestone1.9.3a5pre
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
Make nsTransferable::GetTransferData assign the out params even when it returns an error since some callers depend on it (regression fix). b=565392 r=dbaron
widget/src/xpwidgets/nsTransferable.cpp
widget/tests/Makefile.in
widget/tests/test_bug565392.html
--- a/widget/src/xpwidgets/nsTransferable.cpp
+++ b/widget/src/xpwidgets/nsTransferable.cpp
@@ -305,16 +305,17 @@ nsTransferable::GetTransferDataFlavors(n
 // accessible from JS.
 //
 NS_IMETHODIMP
 nsTransferable::GetTransferData(const char *aFlavor, nsISupports **aData, PRUint32 *aDataLen)
 {
   NS_ENSURE_ARG_POINTER(aFlavor && aData && aDataLen);
 
   nsresult rv = NS_OK;
+  nsCOMPtr<nsISupports> savedData;
   
   // first look and see if the data is present in one of the intrinsic flavors
   PRUint32 i;
   for (i = 0; i < mDataArray.Length(); ++i ) {
     DataStruct& data = mDataArray.ElementAt(i);
     if ( data.GetFlavor().Equals(aFlavor) ) {
       nsCOMPtr<nsISupports> dataBytes;
       PRUint32 len;
@@ -329,16 +330,17 @@ nsTransferable::GetTransferData(const ch
             break;    // the provider failed. fall into the converter code below.
         }
       }
       if (dataBytes && len > 0) { // XXXmats why is zero length not ok?
         *aDataLen = len;
         dataBytes.forget(aData);
         return NS_OK;
       }
+      savedData = dataBytes;  // return this if format converter fails
       break;
     }
   }
 
   PRBool found = PR_FALSE;
 
   // if not, try using a format converter to get the requested flavor
   if ( mFormatConv ) {
@@ -361,16 +363,23 @@ nsTransferable::GetTransferData(const ch
           }
         }
         mFormatConv->Convert(data.GetFlavor().get(), dataBytes, len, aFlavor, aData, aDataLen);
         found = PR_TRUE;
         break;
       }
     }
   }
+
+  // for backward compatibility
+  if (!found) {
+    savedData.forget(aData);
+    *aDataLen = 0;
+  }
+
   return found ? NS_OK : NS_ERROR_FAILURE;
 }
 
 
 //
 // GetAnyTransferData
 //
 // Returns the data of the first flavor found. Caller is responsible for deleting the
--- a/widget/tests/Makefile.in
+++ b/widget/tests/Makefile.in
@@ -92,16 +92,19 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
 ifneq ($(OS_ARCH), WINCE)
 _CHROME_FILES  += taskbar_previews.xul \
 		window_state_windows.xul \
 		taskbar_progress.xul \
 		$(NULL)
+
+_TEST_FILES +=	test_bug565392.html \
+		$(NULL)
 endif
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
 _TEST_FILES += 	plugin_scroll_invalidation.html \
 		test_plugin_scroll_invalidation.html \
 		$(NULL)
 endif
new file mode 100644
--- /dev/null
+++ b/widget/tests/test_bug565392.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=565392
+-->
+<head>
+  <title>Test for Bug 565392</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=565392">Mozilla Bug 565392</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 565392 **/
+
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  const Cc = Components.classes;
+  const Ci = Components.interfaces;
+  var ds = Cc["@mozilla.org/file/directory_service;1"]
+             .getService(Ci.nsIProperties);
+  var dir1 = ds.get("ProfD", Ci.nsIFile);
+  var clipboard = Cc["@mozilla.org/widget/clipboard;1"]
+                    .getService(Ci.nsIClipboard);
+  
+  function getTransferableFile(file) {
+    var transferable = Cc['@mozilla.org/widget/transferable;1']
+                         .createInstance(Ci.nsITransferable);
+    transferable.setTransferData("application/x-moz-file", file, 0);
+    return transferable;
+  }
+
+  function setClipboardData(transferable) {
+    clipboard.setData(transferable, null, 1);
+  }
+  
+  function getClipboardData(mime) {
+    var transferable = Cc['@mozilla.org/widget/transferable;1']
+                         .createInstance(Ci.nsITransferable);
+    transferable.addDataFlavor(mime);
+    clipboard.getData(transferable, 1);
+    var data = {};
+    transferable.getTransferData(mime, data, {}) ;
+    return data;
+  }
+
+setClipboardData(getTransferableFile(dir1))
+is(clipboard.hasDataMatchingFlavors(["application/x-moz-file"], 1,1), true);
+var data = getClipboardData("application/x-moz-file");
+var file = data.value.QueryInterface(Ci.nsIFile);
+ok(file.isDirectory(), true);
+is(file.target, dir1.target, true);
+
+</script>
+</pre>
+</body>
+</html>