Bug 992691 - don't allow dropping multiple files on non-multiple file input, r=smaug
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Tue, 18 Nov 2014 15:58:08 +0000
changeset 240813 b8919fcbf6b2246428024d72b938ed9a5f8e9c92
parent 240812 a3f7920495b416acdd7310374c141e004ee152fa
child 240814 f8863cbd49cbabec9baf8749e0ee2cad4c108657
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs992691
milestone36.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 992691 - don't allow dropping multiple files on non-multiple file input, r=smaug
layout/forms/nsFileControlFrame.cpp
layout/forms/nsFileControlFrame.h
--- a/layout/forms/nsFileControlFrame.cpp
+++ b/layout/forms/nsFileControlFrame.cpp
@@ -182,66 +182,92 @@ nsFileControlFrame::DnDListener::HandleE
 
   bool defaultPrevented = false;
   aEvent->GetDefaultPrevented(&defaultPrevented);
   if (defaultPrevented) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIDOMDragEvent> dragEvent = do_QueryInterface(aEvent);
-  if (!dragEvent || !IsValidDropData(dragEvent)) {
+  if (!dragEvent) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIDOMDataTransfer> dataTransfer;
+  dragEvent->GetDataTransfer(getter_AddRefs(dataTransfer));
+  if (!IsValidDropData(dataTransfer)) {
+    return NS_OK;
+  }
+
+
+  nsIContent* content = mFrame->GetContent();
+  bool supportsMultiple = content && content->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple);
+  if (!CanDropTheseFiles(dataTransfer, supportsMultiple)) {
+    dataTransfer->SetDropEffect(NS_LITERAL_STRING("none"));
+    aEvent->StopPropagation();
     return NS_OK;
   }
 
   nsAutoString eventType;
   aEvent->GetType(eventType);
   if (eventType.EqualsLiteral("dragover")) {
     // Prevent default if we can accept this drag data
     aEvent->PreventDefault();
     return NS_OK;
   }
 
   if (eventType.EqualsLiteral("drop")) {
     aEvent->StopPropagation();
     aEvent->PreventDefault();
 
-    nsIContent* content = mFrame->GetContent();
     NS_ASSERTION(content, "The frame has no content???");
 
     HTMLInputElement* inputElement = HTMLInputElement::FromContent(content);
     NS_ASSERTION(inputElement, "No input element for this file upload control frame!");
 
-    nsCOMPtr<nsIDOMDataTransfer> dataTransfer;
-    dragEvent->GetDataTransfer(getter_AddRefs(dataTransfer));
-
     nsCOMPtr<nsIDOMFileList> fileList;
     dataTransfer->GetFiles(getter_AddRefs(fileList));
 
     inputElement->SetFiles(fileList, true);
     nsContentUtils::DispatchTrustedEvent(content->OwnerDoc(), content,
                                          NS_LITERAL_STRING("change"), true,
                                          false);
   }
 
   return NS_OK;
 }
 
 /* static */ bool
-nsFileControlFrame::DnDListener::IsValidDropData(nsIDOMDragEvent* aEvent)
+nsFileControlFrame::DnDListener::IsValidDropData(nsIDOMDataTransfer* aDOMDataTransfer)
 {
-  nsCOMPtr<nsIDOMDataTransfer> domDataTransfer;
-  aEvent->GetDataTransfer(getter_AddRefs(domDataTransfer));
-  nsCOMPtr<DataTransfer> dataTransfer = do_QueryInterface(domDataTransfer);
+  nsCOMPtr<DataTransfer> dataTransfer = do_QueryInterface(aDOMDataTransfer);
   NS_ENSURE_TRUE(dataTransfer, false);
 
   // We only support dropping files onto a file upload control
   nsRefPtr<DOMStringList> types = dataTransfer->Types();
   return types->Contains(NS_LITERAL_STRING("Files"));
 }
 
+/* static */ bool
+nsFileControlFrame::DnDListener::CanDropTheseFiles(nsIDOMDataTransfer* aDOMDataTransfer,
+                                                   bool aSupportsMultiple)
+{
+  nsCOMPtr<DataTransfer> dataTransfer = do_QueryInterface(aDOMDataTransfer);
+  NS_ENSURE_TRUE(dataTransfer, false);
+
+  nsCOMPtr<nsIDOMFileList> fileList;
+  dataTransfer->GetFiles(getter_AddRefs(fileList));
+
+  uint32_t listLength = 0;
+  if (fileList) {
+    fileList->GetLength(&listLength);
+  }
+  return listLength <= 1 || aSupportsMultiple;
+}
+
 nscoord
 nsFileControlFrame::GetMinISize(nsRenderingContext *aRenderingContext)
 {
   nscoord result;
   DISPLAY_MIN_WIDTH(this, result);
 
   // Our min width is our pref width
   result = GetPrefISize(aRenderingContext);
--- a/layout/forms/nsFileControlFrame.h
+++ b/layout/forms/nsFileControlFrame.h
@@ -9,17 +9,17 @@
 #include "mozilla/Attributes.h"
 #include "nsBlockFrame.h"
 #include "nsIFormControlFrame.h"
 #include "nsIDOMEventListener.h"
 #include "nsIAnonymousContentCreator.h"
 #include "nsCOMPtr.h"
 
 class nsTextControlFrame;
-class nsIDOMDragEvent;
+class nsIDOMDataTransfer;
 
 class nsFileControlFrame : public nsBlockFrame,
                            public nsIFormControlFrame,
                            public nsIAnonymousContentCreator
 {
 public:
   explicit nsFileControlFrame(nsStyleContext* aContext);
 
@@ -112,17 +112,18 @@ protected:
   class DnDListener: public MouseListener {
   public:
     explicit DnDListener(nsFileControlFrame* aFrame)
       : MouseListener(aFrame)
     {}
 
     NS_DECL_NSIDOMEVENTLISTENER
 
-    static bool IsValidDropData(nsIDOMDragEvent* aEvent);
+    static bool IsValidDropData(nsIDOMDataTransfer* aDOMDataTransfer);
+    static bool CanDropTheseFiles(nsIDOMDataTransfer* aDOMDataTransfer, bool aSupportsMultiple);
   };
 
   virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE
   {
     return nsBlockFrame::IsFrameOfType(aFlags &
       ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
   }