From 9bedd9a6bd33ab119a8f1cf6a6ac3ad9ece6a668 Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Mon, 8 Jul 2013 15:12:18 -0400 Subject: [PATCH] Bug 885996 - 1/2 - Interaction between nsIColorPicker and content. r=smaug --- content/html/content/src/HTMLInputElement.cpp | 145 +++++++++++++++++- content/html/content/src/HTMLInputElement.h | 1 - .../en-US/chrome/layout/HtmlForm.properties | 1 + 3 files changed, 144 insertions(+), 3 deletions(-) diff --git a/content/html/content/src/HTMLInputElement.cpp b/content/html/content/src/HTMLInputElement.cpp index 16174f83b84..d755cd29a95 100644 --- a/content/html/content/src/HTMLInputElement.cpp +++ b/content/html/content/src/HTMLInputElement.cpp @@ -96,6 +96,8 @@ #include +#include "nsIColorPicker.h" + // input type=date #include "js/Date.h" @@ -377,6 +379,103 @@ HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult) NS_IMPL_ISUPPORTS1(HTMLInputElement::nsFilePickerShownCallback, nsIFilePickerShownCallback) +class nsColorPickerShownCallback MOZ_FINAL + : public nsIColorPickerShownCallback +{ +public: + nsColorPickerShownCallback(HTMLInputElement* aInput, + nsIColorPicker* aColorPicker) + : mInput(aInput) + , mColorPicker(aColorPicker) + , mValueChanged(false) + {} + + NS_DECL_ISUPPORTS + + NS_IMETHOD Update(const nsAString& aColor) MOZ_OVERRIDE; + NS_IMETHOD Done(const nsAString& aColor) MOZ_OVERRIDE; + +private: + /** + * Updates the internals of the object using aColor as the new value. + * If aTrustedUpdate is true, it will consider that aColor is a new value. + * Otherwise, it will check that aColor is different from the current value. + */ + nsresult UpdateInternal(const nsAString& aColor, bool aTrustedUpdate); + + nsRefPtr mInput; + nsCOMPtr mColorPicker; + bool mValueChanged; +}; + +nsresult +nsColorPickerShownCallback::UpdateInternal(const nsAString& aColor, + bool aTrustedUpdate) +{ + bool valueChanged = false; + + nsAutoString oldValue; + if (aTrustedUpdate) { + valueChanged = true; + } else { + mInput->GetValue(oldValue); + } + + mInput->SetValue(aColor); + + if (!aTrustedUpdate) { + nsAutoString newValue; + mInput->GetValue(newValue); + if (!oldValue.Equals(newValue)) { + valueChanged = true; + } + } + + if (valueChanged) { + mValueChanged = true; + return nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(), + static_cast(mInput.get()), + NS_LITERAL_STRING("input"), true, + false); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsColorPickerShownCallback::Update(const nsAString& aColor) +{ + return UpdateInternal(aColor, true); +} + +NS_IMETHODIMP +nsColorPickerShownCallback::Done(const nsAString& aColor) +{ + /** + * When Done() is called, we might be at the end of a serie of Update() calls + * in which case mValueChanged is set to true and a change event will have to + * be fired but we might also be in a one shot Done() call situation in which + * case we should fire a change event iif the value actually changed. + * UpdateInternal(bool) is taking care of that logic for us. + */ + nsresult rv = NS_OK; + + if (!aColor.IsEmpty()) { + UpdateInternal(aColor, false); + } + + if (mValueChanged) { + rv = nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(), + static_cast(mInput.get()), + NS_LITERAL_STRING("change"), true, + false); + } + + return rv; +} + +NS_IMPL_ISUPPORTS1(nsColorPickerShownCallback, nsIColorPickerShownCallback) + HTMLInputElement::AsyncClickHandler::AsyncClickHandler(HTMLInputElement* aInput) : mInput(aInput) { @@ -400,8 +499,50 @@ HTMLInputElement::AsyncClickHandler::Run() nsresult HTMLInputElement::AsyncClickHandler::InitColorPicker() { - // TODO - return NS_OK; + // Get parent nsPIDOMWindow object. + nsCOMPtr doc = mInput->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; + } + } + + // Get Loc title + nsXPIDLString title; + nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES, + "ColorPicker", title); + + nsCOMPtr colorPicker = do_CreateInstance("@mozilla.org/colorpicker;1"); + if (!colorPicker) { + return NS_ERROR_FAILURE; + } + + nsAutoString initialValue; + mInput->GetValueInternal(initialValue); + nsresult rv = colorPicker->Init(win, title, initialValue); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr callback = + new nsColorPickerShownCallback(mInput, colorPicker); + + return colorPicker->Open(callback); } nsresult diff --git a/content/html/content/src/HTMLInputElement.h b/content/html/content/src/HTMLInputElement.h index db67772681b..632511d57d9 100644 --- a/content/html/content/src/HTMLInputElement.h +++ b/content/html/content/src/HTMLInputElement.h @@ -24,7 +24,6 @@ #include "mozilla/Decimal.h" class nsDOMFileList; -class nsIFilePicker; class nsIRadioGroupContainer; class nsIRadioGroupVisitor; class nsIRadioVisitor; diff --git a/dom/locales/en-US/chrome/layout/HtmlForm.properties b/dom/locales/en-US/chrome/layout/HtmlForm.properties index cba568a85df..1a9910ebe2e 100644 --- a/dom/locales/en-US/chrome/layout/HtmlForm.properties +++ b/dom/locales/en-US/chrome/layout/HtmlForm.properties @@ -27,3 +27,4 @@ NoFilesSelected=No files selected. # when there are more than one selected file. # %S will be a number greater or equal to 2. XFilesSelected=%S files selected. +ColorPicker=Choose a color \ No newline at end of file