diff --git a/content/html/content/src/HTMLInputElement.cpp b/content/html/content/src/HTMLInputElement.cpp index cabfbf8e17e..e9b3079bc75 100644 --- a/content/html/content/src/HTMLInputElement.cpp +++ b/content/html/content/src/HTMLInputElement.cpp @@ -476,52 +476,43 @@ nsColorPickerShownCallback::Done(const nsAString& aColor) NS_IMPL_ISUPPORTS1(nsColorPickerShownCallback, nsIColorPickerShownCallback) -HTMLInputElement::AsyncClickHandler::AsyncClickHandler(HTMLInputElement* aInput) - : mInput(aInput) +bool +HTMLInputElement::IsPopupBlocked() const { - nsPIDOMWindow* win = aInput->OwnerDoc()->GetWindow(); - if (win) { - mPopupControlState = win->GetPopupControlState(); + nsCOMPtr win = OwnerDoc()->GetWindow(); + MOZ_ASSERT(win, "window should not be null"); + if (!win) { + return true; } -} -NS_IMETHODIMP -HTMLInputElement::AsyncClickHandler::Run() -{ - if (mInput->GetType() == NS_FORM_INPUT_FILE) { - return InitFilePicker(); - } else if (mInput->GetType() == NS_FORM_INPUT_COLOR) { - return InitColorPicker(); + // Check if page is allowed to open the popup + if (win->GetPopupControlState() <= openControlled) { + return false; } - return NS_ERROR_FAILURE; + + nsCOMPtr pm = do_GetService(NS_POPUPWINDOWMANAGER_CONTRACTID); + if (!pm) { + return true; + } + + uint32_t permission; + pm->TestPermission(OwnerDoc()->NodePrincipal(), &permission); + return permission == nsIPopupWindowManager::DENY_POPUP; } nsresult -HTMLInputElement::AsyncClickHandler::InitColorPicker() +HTMLInputElement::InitColorPicker() { - // Get parent nsPIDOMWindow object. - nsCOMPtr doc = mInput->OwnerDoc(); + nsCOMPtr doc = OwnerDoc(); nsCOMPtr win = doc->GetWindow(); if (!win) { return NS_ERROR_FAILURE; } - // Check if page is allowed to open the popup - if (mPopupControlState > openControlled) { - nsCOMPtr pm = - do_GetService(NS_POPUPWINDOWMANAGER_CONTRACTID); - - if (!pm) { - return NS_OK; - } - - uint32_t permission; - pm->TestPermission(doc->NodePrincipal(), &permission); - if (permission == nsIPopupWindowManager::DENY_POPUP) { - nsGlobalWindow::FirePopupBlockedEvent(doc, win, nullptr, EmptyString(), EmptyString()); - return NS_OK; - } + if (IsPopupBlocked()) { + nsGlobalWindow::FirePopupBlockedEvent(doc, win, nullptr, EmptyString(), EmptyString()); + return NS_OK; } // Get Loc title @@ -535,42 +526,30 @@ HTMLInputElement::AsyncClickHandler::InitColorPicker() } nsAutoString initialValue; - mInput->GetValueInternal(initialValue); + GetValueInternal(initialValue); nsresult rv = colorPicker->Init(win, title, initialValue); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr callback = - new nsColorPickerShownCallback(mInput, colorPicker); + new nsColorPickerShownCallback(this, colorPicker); return colorPicker->Open(callback); } nsresult -HTMLInputElement::AsyncClickHandler::InitFilePicker() +HTMLInputElement::InitFilePicker() { // Get parent nsPIDOMWindow object. - nsCOMPtr doc = mInput->OwnerDoc(); + nsCOMPtr doc = OwnerDoc(); - nsPIDOMWindow* win = doc->GetWindow(); + nsCOMPtr win = doc->GetWindow(); if (!win) { return NS_ERROR_FAILURE; } - // Check if page is allowed to open the popup - if (mPopupControlState > openControlled) { - nsCOMPtr pm = - do_GetService(NS_POPUPWINDOWMANAGER_CONTRACTID); - - if (!pm) { - return NS_OK; - } - - uint32_t permission; - pm->TestPermission(doc->NodePrincipal(), &permission); - if (permission == nsIPopupWindowManager::DENY_POPUP) { - nsGlobalWindow::FirePopupBlockedEvent(doc, win, nullptr, EmptyString(), EmptyString()); - return NS_OK; - } + if (IsPopupBlocked()) { + nsGlobalWindow::FirePopupBlockedEvent(doc, win, nullptr, EmptyString(), EmptyString()); + return NS_OK; } // Get Loc title @@ -582,7 +561,7 @@ HTMLInputElement::AsyncClickHandler::InitFilePicker() if (!filePicker) return NS_ERROR_FAILURE; - bool multi = mInput->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple); + bool multi = HasAttr(kNameSpaceID_None, nsGkAtoms::multiple); nsresult rv = filePicker->Init(win, title, multi @@ -590,8 +569,8 @@ HTMLInputElement::AsyncClickHandler::InitFilePicker() : static_cast(nsIFilePicker::modeOpen)); NS_ENSURE_SUCCESS(rv, rv); - if (mInput->HasAttr(kNameSpaceID_None, nsGkAtoms::accept)) { - mInput->SetFilePickerFiltersFromAccept(filePicker); + if (HasAttr(kNameSpaceID_None, nsGkAtoms::accept)) { + SetFilePickerFiltersFromAccept(filePicker); } else { filePicker->AppendFilters(nsIFilePicker::filterAll); } @@ -599,10 +578,10 @@ HTMLInputElement::AsyncClickHandler::InitFilePicker() // Set default directry and filename nsAutoString defaultName; - const nsCOMArray& oldFiles = mInput->GetFilesInternal(); + const nsCOMArray& oldFiles = GetFilesInternal(); nsCOMPtr callback = - new HTMLInputElement::nsFilePickerShownCallback(mInput, filePicker, multi); + new HTMLInputElement::nsFilePickerShownCallback(this, filePicker, multi); if (oldFiles.Count()) { nsString path; @@ -2596,13 +2575,6 @@ HTMLInputElement::SelectAll(nsPresContext* aPresContext) } } -NS_IMETHODIMP -HTMLInputElement::FireAsyncClickHandler() -{ - nsCOMPtr event = new AsyncClickHandler(this); - return NS_DispatchToMainThread(event); -} - bool HTMLInputElement::NeedToInitializeEditorForEvent(nsEventChainPreVisitor& aVisitor) const { @@ -2906,8 +2878,8 @@ HTMLInputElement::ShouldPreventDOMActivateDispatch(EventTarget* aOriginalTarget) nsGkAtoms::button, eCaseMatters); } -void -HTMLInputElement::MaybeFireAsyncClickHandler(nsEventChainPostVisitor& aVisitor) +nsresult +HTMLInputElement::MaybeInitPickers(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 . @@ -2915,12 +2887,17 @@ HTMLInputElement::MaybeFireAsyncClickHandler(nsEventChainPostVisitor& aVisitor) // - 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) && + // .click(). However, the pickers will follow the rules of popup-blocking. + if (NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent) && !aVisitor.mEvent->mFlags.mDefaultPrevented) { - FireAsyncClickHandler(); + if (mType == NS_FORM_INPUT_FILE) { + return InitFilePicker(); + } + if (mType == NS_FORM_INPUT_COLOR) { + return InitColorPicker(); + } } + return NS_OK; } nsresult @@ -2928,9 +2905,8 @@ 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; + // in document, try to init picker even without PresContext. + return MaybeInitPickers(aVisitor); } if (aVisitor.mEvent->message == NS_FOCUS_CONTENT || @@ -3333,9 +3309,7 @@ HTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor) PostHandleEventForRangeThumb(aVisitor); } - MaybeFireAsyncClickHandler(aVisitor); - - return rv; + return MaybeInitPickers(aVisitor); } void diff --git a/content/html/content/src/HTMLInputElement.h b/content/html/content/src/HTMLInputElement.h index 3645c9ba4b2..eae3e805d5d 100644 --- a/content/html/content/src/HTMLInputElement.h +++ b/content/html/content/src/HTMLInputElement.h @@ -222,9 +222,6 @@ 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, nsGenericHTMLFormElementWithState) @@ -1083,6 +1080,25 @@ protected: */ bool ShouldPreventDOMActivateDispatch(EventTarget* aOriginalTarget); + /** + * Some input type (color and file) let user choose a value using a picker: + * this function checks if it is needed, and if so, open the corresponding + * picker (color picker or file picker). + */ + nsresult MaybeInitPickers(nsEventChainPostVisitor& aVisitor); + + nsresult InitFilePicker(); + nsresult InitColorPicker(); + + /** + * Use this function before trying to open a picker. + * It checks if the page is allowed to open a new pop-up. + * If it returns true, you should not create the picker. + * + * @return true if popup should be blocked, false otherwise + */ + bool IsPopupBlocked() const; + nsCOMPtr mControllers; /* @@ -1230,21 +1246,6 @@ private: bool mIsTrusted; }; - class AsyncClickHandler - : public nsRunnable - { - public: - AsyncClickHandler(HTMLInputElement* aInput); - NS_IMETHOD Run() MOZ_OVERRIDE; - - protected: - nsresult InitFilePicker(); - nsresult InitColorPicker(); - - nsRefPtr mInput; - PopupControlState mPopupControlState; - }; - class nsFilePickerShownCallback : public nsIFilePickerShownCallback {