From 75215be2aad56f76c9e5036a67e216bf32be7b40 Mon Sep 17 00:00:00 2001 From: Olli Pettay Date: Tue, 4 Jun 2013 00:40:41 +0300 Subject: [PATCH] Bug 875252, make type=file click() to work (again) even when the element isn't in the DOM, r=jst --HG-- extra : rebase_source : e8fecce550d5fe91a524f1b47a8429165354ac90 --- content/html/content/src/HTMLInputElement.cpp | 33 ++++++++++++------- content/html/content/src/HTMLInputElement.h | 1 + .../test/forms/test_input_file_picker.html | 17 ++++++++-- 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/content/html/content/src/HTMLInputElement.cpp b/content/html/content/src/HTMLInputElement.cpp index ccfc735feac4..588673d0b1d3 100644 --- a/content/html/content/src/HTMLInputElement.cpp +++ b/content/html/content/src/HTMLInputElement.cpp @@ -2761,10 +2761,30 @@ HTMLInputElement::ShouldPreventDOMActivateDispatch(EventTarget* aOriginalTarget) nsGkAtoms::button, eCaseMatters); } +void +HTMLInputElement::MaybeFireAsyncClickHandler(nsEventChainPostVisitor& aVisitor) +{ + // Open a file picker when we receive a click on a , or + // open a color picker when we receive a click on a . + // A click is handled in the following cases: + // - preventDefault() has not been called (or something similar); + // - it's the left mouse button. + // We do not prevent non-trusted click because authors can already use + // .click(). However, the file picker will follow the rules of popup-blocking. + if ((mType == NS_FORM_INPUT_FILE || mType == NS_FORM_INPUT_COLOR) && + NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent) && + !aVisitor.mEvent->mFlags.mDefaultPrevented) { + FireAsyncClickHandler(); + } +} + nsresult HTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor) { if (!aVisitor.mPresContext) { + // Hack alert! In order to open file picker even in case the element isn't + // in document, fire click handler even without PresContext. + MaybeFireAsyncClickHandler(aVisitor); return NS_OK; } @@ -3168,18 +3188,7 @@ HTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor) PostHandleEventForRangeThumb(aVisitor); } - // Open a file picker when we receive a click on a , or - // open a color picker when we receive a click on a . - // A click is handled in the following cases: - // - preventDefault() has not been called (or something similar); - // - it's the left mouse button. - // We do not prevent non-trusted click because authors can already use - // .click(). However, the file picker will follow the rules of popup-blocking. - if ((mType == NS_FORM_INPUT_FILE || mType == NS_FORM_INPUT_COLOR) && - NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent) && - !aVisitor.mEvent->mFlags.mDefaultPrevented) { - return FireAsyncClickHandler(); - } + MaybeFireAsyncClickHandler(aVisitor); return rv; } diff --git a/content/html/content/src/HTMLInputElement.h b/content/html/content/src/HTMLInputElement.h index 3f938e314582..7fc763639b2d 100644 --- a/content/html/content/src/HTMLInputElement.h +++ b/content/html/content/src/HTMLInputElement.h @@ -223,6 +223,7 @@ public: virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE; + void MaybeFireAsyncClickHandler(nsEventChainPostVisitor& aVisitor); NS_IMETHOD FireAsyncClickHandler(); NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLInputElement, diff --git a/content/html/content/test/forms/test_input_file_picker.html b/content/html/content/test/forms/test_input_file_picker.html index 44ad47c652f2..63b4858307e9 100644 --- a/content/html/content/test/forms/test_input_file_picker.html +++ b/content/html/content/test/forms/test_input_file_picker.html @@ -193,8 +193,7 @@ function runTests() { "File picker should show the correct filter index (" + testName + ")"); if (++currentTest == testData.length) { - MockFilePicker.cleanup(); - SimpleTest.finish(); + setTimeout(testDisconnectedElement, 0); } else { launchNextTest(); } @@ -204,6 +203,20 @@ function runTests() { launchNextTest(); } +function testDisconnectedElement() { + MockFilePicker.shown = false; + MockFilePicker.showCallback = function(filepicker) { + ok(MockFilePicker.shown, "FilePicker should be open!"); + MockFilePicker.shown = false; + MockFilePicker.cleanup(); + SimpleTest.finish(); + } + var f = document.createElement("input"); + f.setAttribute("type", "file"); + f.click(); + ok(!MockFilePicker.shown, "FilePicker should open asynchronously!"); +} +