commit 3bfc8bc8ea3a87010c2203f752af19b29bf4c0b2 Author: Neil Deakin neil@mozilla.com Date: Wed May 11 10:04:19 2016 -0400
Bug 1249522, when a file is present, only specify file type, r=smaug --- browser/base/content/test/general/browser.ini | 2 + .../test/general/browser_clipboard_pastefile.js | 59 +++++++++++++++++++++ .../content/test/general/clipboard_pastefile.html | 37 +++++++++++++ dom/events/DataTransfer.cpp | 60 +++++++++++++--------- dom/events/DataTransfer.h | 3 +- .../mochitest/chrome/test_sanityChromeUtils.xul | 4 +- 6 files changed, 139 insertions(+), 26 deletions(-)
diff --git a/browser/base/content/test/general/browser.ini b/browser/base/content/test/general/browser.ini index 44e5d15..3224ce5 100644 --- a/browser/base/content/test/general/browser.ini +++ b/browser/base/content/test/general/browser.ini @@ -25,6 +25,7 @@ support-files = bug792517.html bug792517.sjs bug839103.css + clipboard_pastefile.html discovery.html domplate_test.js download_page.html @@ -283,6 +284,7 @@ skip-if = os == 'win' || e10s # Bug 1159268 - Need a content-process safe versio [browser_canonizeURL.js] skip-if = e10s # Bug 1094510 - test hits the network in e10s mode only [browser_clipboard.js] +[browser_clipboard_pastefile.js] [browser_contentAreaClick.js] [browser_contextSearchTabPosition.js] skip-if = os == "mac" || e10s # bug 967013; e10s: bug 1094761 - test hits the network in e10s, causing next test to crash diff --git a/browser/base/content/test/general/browser_clipboard_pastefile.js b/browser/base/content/test/general/browser_clipboard_pastefile.js new file mode 100644 index 0000000..094628f --- /dev/null +++ b/browser/base/content/test/general/browser_clipboard_pastefile.js @@ -0,0 +1,59 @@ +// This test is used to check that pasting files removes all non-file data from +// event.clipboardData. + +add_task(function*() { + var searchbar = document.getElementById("searchbar"); + + searchbar.focus(); + searchbar.value = "Text"; + searchbar.select(); + + yield new Promise((resolve, reject) => { + searchbar.addEventListener("copy", function copyEvent(event) { + searchbar.removeEventListener("copy", copyEvent, true); + event.clipboardData.setData("text/plain", "Alternate"); + // For this test, it doesn't matter that the file isn't actually a file. + event.clipboardData.setData("application/x-moz-file", "Sample"); + event.preventDefault(); + resolve(); + }, true) + + EventUtils.synthesizeKey("c", { accelKey: true }); + }); + + let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, + "https://example.com/browser/browser/base/content/test/general/clipboard_past..."); + let browser = tab.linkedBrowser; + + yield ContentTask.spawn(browser, { }, function* (arg) { + content.document.getElementById("input").focus(); + }); + + yield BrowserTestUtils.synthesizeKey("v", { accelKey: true }, browser); + + let output = yield ContentTask.spawn(browser, { }, function* (arg) { + return content.document.getElementById("output").textContent; + }); + is (output, "Passed", "Paste file"); + + searchbar.focus(); + + yield new Promise((resolve, reject) => { + searchbar.addEventListener("paste", function copyEvent(event) { + searchbar.removeEventListener("paste", copyEvent, true); + + let dt = event.clipboardData; + is(dt.types.length, 3, "number of types"); + ok(dt.types.contains("text/plain"), "text/plain exists in types"); + ok(dt.mozTypesAt(0).contains("text/plain"), "text/plain exists in mozTypesAt"); + is(dt.getData("text/plain"), "Alternate", "text/plain returned in getData"); + is(dt.mozGetDataAt("text/plain", 0), "Alternate", "text/plain returned in mozGetDataAt"); + + resolve(); + }, true); + + EventUtils.synthesizeKey("v", { accelKey: true }); + }); + + yield BrowserTestUtils.removeTab(tab); +}); diff --git a/browser/base/content/test/general/clipboard_pastefile.html b/browser/base/content/test/general/clipboard_pastefile.html new file mode 100644 index 0000000..fcbf60e --- /dev/null +++ b/browser/base/content/test/general/clipboard_pastefile.html @@ -0,0 +1,37 @@ +<html><body> +<script> +function checkPaste(event) +{ + let output = document.getElementById("output"); + output.textContent = checkPasteHelper(event); +} + +function checkPasteHelper(event) +{ + let dt = event.clipboardData; + if (dt.types.length != 2) + return "Wrong number of types; got " + dt.types.length; + + for (let type of dt.types) { + if (type != "Files" && type != "application/x-moz-file") + return "Invalid type for types; got" + type; + } + + for (let type of dt.mozTypesAt(0)) { + if (type != "Files" && type != "application/x-moz-file") + return "Invalid type for mozTypesAt; got" + type; + } + + if (dt.getData("text/plain")) + return "text/plain found with getData"; + if (dt.mozGetDataAt("text/plain", 0)) + return "text/plain found with mozGetDataAt"; + + return "Passed"; +} +</script> + +<input id="input" onpaste="checkPaste(event)"> +<div id="output"></div> + +</body></html> diff --git a/dom/events/DataTransfer.cpp b/dom/events/DataTransfer.cpp index 2ad0eff..a6c9342 100644 --- a/dom/events/DataTransfer.cpp +++ b/dom/events/DataTransfer.cpp @@ -359,25 +359,8 @@ DataTransfer::GetFiles(nsIDOMFileList** aFileList) already_AddRefed<DOMStringList> DataTransfer::Types() { - RefPtr<DOMStringList> types = new DOMStringList(); - if (mItems.Length()) { - bool addFile = false; - const nsTArray<TransferItem>& item = mItems[0]; - for (uint32_t i = 0; i < item.Length(); i++) { - const nsString& format = item[i].mFormat; - types->Add(format); - if (!addFile) { - addFile = format.EqualsASCII(kFileMime) || - format.EqualsASCII("application/x-moz-file-promise"); - } - } - - if (addFile) { - types->Add(NS_LITERAL_STRING("Files")); - } - } - - return types.forget(); + ErrorResult rv; + return MozTypesAt(0, rv); }
NS_IMETHODIMP @@ -545,7 +528,7 @@ DataTransfer::GetMozSourceNode(nsIDOMNode** aSourceNode) }
already_AddRefed<DOMStringList> -DataTransfer::MozTypesAt(uint32_t aIndex, ErrorResult& aRv) +DataTransfer::MozTypesAt(uint32_t aIndex, ErrorResult& aRv) const { // Only the first item is valid for clipboard events if (aIndex > 0 && @@ -557,10 +540,28 @@ DataTransfer::MozTypesAt(uint32_t aIndex, ErrorResult& aRv)
RefPtr<DOMStringList> types = new DOMStringList(); if (aIndex < mItems.Length()) { + bool addFile = false; // note that you can retrieve the types regardless of their principal - nsTArray<TransferItem>& item = mItems[aIndex]; - for (uint32_t i = 0; i < item.Length(); i++) - types->Add(item[i].mFormat); + const nsTArray<TransferItem>& item = mItems[aIndex]; + for (uint32_t i = 0; i < item.Length(); i++) { + const nsString& format = item[i].mFormat; + types->Add(format); + if (!addFile) { + addFile = format.EqualsASCII(kFileMime); + } + } + + if (addFile) { + // If this is a content caller, and a file is in the data transfer, remove + // the non-file types. This prevents alternate text forms of the file + // from being returned. + if (!nsContentUtils::LegacyIsCallerChromeOrNativeCode()) { + types->Clear(); + types->Add(NS_LITERAL_STRING(kFileMime)); + } + + types->Add(NS_LITERAL_STRING("Files")); + } }
return types.forget(); @@ -602,12 +603,23 @@ DataTransfer::GetDataAtInternal(const nsAString& aFormat, uint32_t aIndex, return NS_ERROR_DOM_INDEX_SIZE_ERR; }
- nsAutoString format; GetRealFormat(aFormat, format);
nsTArray<TransferItem>& item = mItems[aIndex];
+ // If this is a content caller, and a file is in the data transfer, only + // return the file type. + if (!format.EqualsLiteral(kFileMime) && + !nsContentUtils::IsSystemPrincipal(aSubjectPrincipal)) { + uint32_t count = item.Length(); + for (uint32_t i = 0; i < count; i++) { + if (item[i].mFormat.EqualsLiteral(kFileMime)) { + return NS_OK; + } + } + } + // Check if the caller is allowed to access the drag data. Callers with // chrome privileges can always read the data. During the // drop event, allow retrieving the data except in the case where the diff --git a/dom/events/DataTransfer.h b/dom/events/DataTransfer.h index 2b1f90a..48fbac9 100644 --- a/dom/events/DataTransfer.h +++ b/dom/events/DataTransfer.h @@ -165,7 +165,8 @@ public: } } already_AddRefed<DOMStringList> MozTypesAt(uint32_t aIndex, - mozilla::ErrorResult& aRv); + mozilla::ErrorResult& aRv) const; + void MozClearDataAt(const nsAString& aFormat, uint32_t aIndex, mozilla::ErrorResult& aRv); void MozSetDataAt(JSContext* aCx, const nsAString& aFormat, diff --git a/testing/mochitest/chrome/test_sanityChromeUtils.xul b/testing/mochitest/chrome/test_sanityChromeUtils.xul index ca1915b..f3ac45d 100644 --- a/testing/mochitest/chrome/test_sanityChromeUtils.xul +++ b/testing/mochitest/chrome/test_sanityChromeUtils.xul @@ -65,7 +65,9 @@ var dragfile = [[ { type : "application/x-moz-file", data : testFile, - eqTest : function(actualData, expectedData) {return expectedData.equals(actualData);} } + eqTest : function(actualData, expectedData) {return expectedData.equals(actualData);} }, + { type : "Files", + data : null } ]];
function doOnDrop(aEvent) {