Diff
Modified: trunk/Source/WebCore/ChangeLog (89534 => 89535)
--- trunk/Source/WebCore/ChangeLog 2011-06-23 06:00:22 UTC (rev 89534)
+++ trunk/Source/WebCore/ChangeLog 2011-06-23 06:04:50 UTC (rev 89535)
@@ -1,3 +1,50 @@
+2011-06-22 Dimitri Glazkov <[email protected]>
+
+ Reviewed by Kent Tamura.
+
+ Move file-choosing and icon-loading management to FileInputType
+ https://bugs.webkit.org/show_bug.cgi?id=62069
+
+ 1) Moved the duties of FileChooserClient and FileIconLoaderClient from
+ RenderFileUploadControl to FileInputType, along with all of the
+ supporting functions.
+
+ 2) Moved Icon ownership to FileInputType and exposed accessor on
+ HTMInputElement to allow RenderFileUploadControl to query current icon.
+
+ As a result, RenderFileUploadControl is now completely stateless, which is
+ neat and clean.
+
+ Refactoring, covered by existing tests.
+
+ * html/FileInputType.cpp:
+ (WebCore::FileInputType::handleDOMActivateEvent): Moved logic here from RenderFileUploadControl.
+ (WebCore::FileInputType::requestIcon): Ditto.
+ (WebCore::FileInputType::filesChosen): Ditto.
+ (WebCore::FileInputType::receiveDropForDirectoryUpload): Ditto.
+ (WebCore::FileInputType::updateRendering): Ditto.
+ (WebCore::FileInputType::chrome): Ditto.
+ (WebCore::FileInputType::receiveDroppedFiles): Ditto.
+ (WebCore::FileInputType::icon): Added.
+ * html/FileInputType.h:
+ * html/HTMLInputElement.cpp:
+ (WebCore::HTMLInputElement::setValueFromRenderer): Updated comment.
+ (WebCore::HTMLInputElement::receiveDroppedFiles): Added to replace setFileListFromRenderer.
+ (WebCore::HTMLInputElement::icon): Added.
+ * html/HTMLInputElement.h:
+ * html/InputType.cpp:
+ (WebCore::InputType::receiveDroppedFiles): Added.
+ (WebCore::InputType::icon): Added.
+ * html/InputType.h:
+ * page/DragController.cpp:
+ (WebCore::DragController::concludeEditDrag): Changed to use HTMLInputElement. Ahh, nice and clean!
+ * rendering/RenderFileUploadControl.cpp:
+ (WebCore::RenderFileUploadControl::RenderFileUploadControl): Removed code that is no longer necessary.
+ (WebCore::RenderFileUploadControl::updateFromElement): Ditto.
+ (WebCore::RenderFileUploadControl::maxFilenameWidth): Changed to use HTMLInputElement icon accessor.
+ (WebCore::RenderFileUploadControl::paintObject): Ditto.
+ * rendering/RenderFileUploadControl.h:
+
2011-06-22 Pratik Solanki <[email protected]>
Reviewed by Darin Adler.
Modified: trunk/Source/WebCore/html/FileInputType.cpp (89534 => 89535)
--- trunk/Source/WebCore/html/FileInputType.cpp 2011-06-23 06:00:22 UTC (rev 89534)
+++ trunk/Source/WebCore/html/FileInputType.cpp 2011-06-23 06:04:50 UTC (rev 89535)
@@ -22,15 +22,20 @@
#include "config.h"
#include "FileInputType.h"
+#include "Chrome.h"
#include "Event.h"
#include "File.h"
#include "FileList.h"
#include "FileSystem.h"
#include "FormDataList.h"
+#include "Frame.h"
#include "HTMLInputElement.h"
#include "HTMLNames.h"
+#include "Icon.h"
#include "LocalizedStrings.h"
+#include "Page.h"
#include "RenderFileUploadControl.h"
+#include "ScriptController.h"
#include "ShadowRoot.h"
#include <wtf/PassOwnPtr.h>
#include <wtf/text/WTFString.h>
@@ -128,7 +133,24 @@
{
if (element()->disabled() || !element()->renderer())
return;
- toRenderFileUploadControl(element()->renderer())->click();
+
+ if (!ScriptController::processingUserGesture())
+ return;
+
+ if (Chrome* chrome = this->chrome()) {
+ FileChooserSettings settings;
+ HTMLInputElement* input = element();
+#if ENABLE(DIRECTORY_UPLOAD)
+ settings.allowsDirectoryUpload = input->fastHasAttribute(webkitdirectoryAttr);
+ settings.allowsMultipleFiles = settings.allowsDirectoryUpload || input->fastHasAttribute(multipleAttr);
+#else
+ settings.allowsMultipleFiles = input->fastHasAttribute(multipleAttr);
+#endif
+ settings.acceptTypes = input->accept();
+ ASSERT(input->files());
+ settings.selectedFiles = input->files()->filenames();
+ chrome->runOpenPanel(input->document()->frame(), newFileChooser(settings));
+ }
event->setDefaultHandled();
}
@@ -230,4 +252,84 @@
element()->ensureShadowRoot()->appendChild(UploadButtonElement::create(element()->document()), ec);
}
+void FileInputType::requestIcon(const Vector<String>& filenames)
+{
+ if (!filenames.size())
+ return;
+
+ if (Chrome* chrome = this->chrome())
+ chrome->loadIconForFiles(filenames, newFileIconLoader());
+}
+
+void FileInputType::filesChosen(const Vector<String>& filenames)
+{
+ HTMLInputElement* input = element();
+ setFileList(filenames);
+
+ input->setFormControlValueMatchesRenderer(true);
+ input->notifyFormStateChanged();
+ input->setNeedsValidityCheck();
+
+ requestIcon(filenames);
+
+ if (input->renderer())
+ input->renderer()->repaint();
+ // This call may cause destruction of this instance and thus must always be last in the function.
+ input->dispatchFormControlChangeEvent();
+}
+
+#if ENABLE(DIRECTORY_UPLOAD)
+void FileInputType::receiveDropForDirectoryUpload(const Vector<String>& paths)
+{
+ if (Chrome* chrome = this->chrome()) {
+ FileChooserSettings settings;
+ settings.allowsDirectoryUpload = true;
+ settings.allowsMultipleFiles = true;
+ settings.selectedFiles.append(paths[0]);
+ chrome->enumerateChosenDirectory(newFileChooser(settings));
+ }
+}
+#endif
+
+void FileInputType::updateRendering(PassRefPtr<Icon> icon)
+{
+ if (m_icon == icon)
+ return;
+
+ m_icon = icon;
+ if (element()->renderer())
+ element()->renderer()->repaint();
+}
+
+Chrome* FileInputType::chrome() const
+{
+ if (Page* page = element()->document()->page())
+ return page->chrome();
+ return 0;
+}
+
+void FileInputType::receiveDroppedFiles(const Vector<String>& paths)
+{
+ HTMLInputElement* input = element();
+#if ENABLE(DIRECTORY_UPLOAD)
+ if (input->fastHasAttribute(webkitdirectoryAttr)) {
+ receiveDropForDirectoryUpload(paths);
+ return;
+ }
+#endif
+
+ if (input->fastHasAttribute(multipleAttr))
+ filesChosen(paths);
+ else {
+ Vector<String> firstPathOnly;
+ firstPathOnly.append(paths[0]);
+ filesChosen(firstPathOnly);
+ }
+}
+
+Icon* FileInputType::icon() const
+{
+ return m_icon.get();
+}
+
} // namespace WebCore
Modified: trunk/Source/WebCore/html/FileInputType.h (89534 => 89535)
--- trunk/Source/WebCore/html/FileInputType.h 2011-06-23 06:00:22 UTC (rev 89534)
+++ trunk/Source/WebCore/html/FileInputType.h 2011-06-23 06:04:50 UTC (rev 89535)
@@ -33,13 +33,16 @@
#define FileInputType_h
#include "BaseButtonInputType.h"
+#include "FileChooser.h"
+#include "FileIconLoader.h"
#include <wtf/RefPtr.h>
namespace WebCore {
+class Chrome;
class FileList;
-class FileInputType : public BaseButtonInputType {
+class FileInputType : public BaseButtonInputType, private FileChooserClient, private FileIconLoaderClient {
public:
static PassOwnPtr<InputType> create(HTMLInputElement*);
@@ -57,11 +60,26 @@
virtual bool canSetValue(const String&);
virtual bool getTypeSpecificValue(String&); // Checked first, before internal storage or the value attribute.
virtual bool storesValueSeparateFromAttribute();
- virtual void setFileList(const Vector<String>& paths);
+ virtual void receiveDroppedFiles(const Vector<String>&);
+ virtual Icon* icon() const;
virtual bool isFileUpload() const;
virtual void createShadowSubtree();
+ // FileChooserClient implementation.
+ virtual void filesChosen(const Vector<String>&);
+
+ // FileIconLoaderClient implementation.
+ virtual void updateRendering(PassRefPtr<Icon>);
+
+ void setFileList(const Vector<String>& paths);
+#if ENABLE(DIRECTORY_UPLOAD)
+ void receiveDropForDirectoryUpload(const Vector<String>&);
+#endif
+ void requestIcon(const Vector<String>&);
+ Chrome* chrome() const;
+
RefPtr<FileList> m_fileList;
+ RefPtr<Icon> m_icon;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/html/HTMLInputElement.cpp (89534 => 89535)
--- trunk/Source/WebCore/html/HTMLInputElement.cpp 2011-06-23 06:00:22 UTC (rev 89534)
+++ trunk/Source/WebCore/html/HTMLInputElement.cpp 2011-06-23 06:04:50 UTC (rev 89535)
@@ -45,6 +45,7 @@
#include "HTMLNames.h"
#include "HTMLOptionElement.h"
#include "HTMLParserIdioms.h"
+#include "Icon.h"
#include "InputType.h"
#include "KeyboardEvent.h"
#include "LocalizedStrings.h"
@@ -1057,7 +1058,7 @@
void HTMLInputElement::setValueFromRenderer(const String& value)
{
- // File upload controls will always use setFileListFromRenderer.
+ // File upload controls will never use this.
ASSERT(!isFileUpload());
m_suggestedValue = String();
@@ -1085,15 +1086,6 @@
setAutofilled(false);
}
-void HTMLInputElement::setFileListFromRenderer(const Vector<String>& paths)
-{
- m_inputType->setFileList(paths);
-
- setFormControlValueMatchesRenderer(true);
- notifyFormStateChanged();
- setNeedsValidityCheck();
-}
-
void* HTMLInputElement::preDispatchEventHandler(Event* event)
{
if (event->type() == eventNames().textInputEvent && m_inputType->shouldSubmitImplicitly(event)) {
@@ -1275,6 +1267,16 @@
return m_inputType->files();
}
+void HTMLInputElement::receiveDroppedFiles(const Vector<String>& filenames)
+{
+ m_inputType->receiveDroppedFiles(filenames);
+}
+
+Icon* HTMLInputElement::icon() const
+{
+ return m_inputType->icon();
+}
+
String HTMLInputElement::visibleValue() const
{
return m_inputType->visibleValue();
Modified: trunk/Source/WebCore/html/HTMLInputElement.h (89534 => 89535)
--- trunk/Source/WebCore/html/HTMLInputElement.h 2011-06-23 06:00:22 UTC (rev 89534)
+++ trunk/Source/WebCore/html/HTMLInputElement.h 2011-06-23 06:04:50 UTC (rev 89535)
@@ -31,6 +31,7 @@
class FileList;
class HTMLDataListElement;
class HTMLOptionElement;
+class Icon;
class InputType;
class KURL;
@@ -163,7 +164,6 @@
String valueWithDefault() const;
void setValueFromRenderer(const String&);
- void setFileListFromRenderer(const Vector<String>&);
bool canHaveSelection() const;
@@ -202,6 +202,8 @@
void setAutofilled(bool = true);
FileList* files();
+ void receiveDroppedFiles(const Vector<String>&);
+ Icon* icon() const;
void addSearchResult();
void onSearch();
@@ -226,6 +228,7 @@
bool lastChangeWasUserEdit() const;
void cacheSelection(int start, int end);
+ void notifyFormStateChanged();
static const int maximumLength;
@@ -318,7 +321,6 @@
#if ENABLE(DATALIST)
HTMLDataListElement* dataList() const;
#endif
- void notifyFormStateChanged();
void parseMaxLengthAttribute(Attribute*);
void updateValueIfNeeded();
#if ENABLE(WCSS)
Modified: trunk/Source/WebCore/html/InputType.cpp (89534 => 89535)
--- trunk/Source/WebCore/html/InputType.cpp 2011-06-23 06:00:22 UTC (rev 89534)
+++ trunk/Source/WebCore/html/InputType.cpp 2011-06-23 06:04:50 UTC (rev 89535)
@@ -537,11 +537,17 @@
return false;
}
-void InputType::setFileList(const Vector<String>&)
+void InputType::receiveDroppedFiles(const Vector<String>&)
{
ASSERT_NOT_REACHED();
}
+Icon* InputType::icon() const
+{
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
bool InputType::shouldResetOnDocumentActivation()
{
return false;
Modified: trunk/Source/WebCore/html/InputType.h (89534 => 89535)
--- trunk/Source/WebCore/html/InputType.h 2011-06-23 06:00:22 UTC (rev 89534)
+++ trunk/Source/WebCore/html/InputType.h 2011-06-23 06:04:50 UTC (rev 89535)
@@ -48,6 +48,7 @@
class HTMLElement;
class HTMLFormElement;
class HTMLInputElement;
+class Icon;
class KeyboardEvent;
class MouseEvent;
class Node;
@@ -209,12 +210,13 @@
virtual void willMoveToNewOwnerDocument();
virtual bool shouldRespectAlignAttribute();
virtual FileList* files();
+ virtual void receiveDroppedFiles(const Vector<String>&);
+ virtual Icon* icon() const;
// Should return true if the corresponding renderer for a type can display a suggested value.
virtual bool canSetSuggestedValue();
virtual bool shouldSendChangeEventAfterCheckedChanged();
virtual bool canSetValue(const String&);
virtual bool storesValueSeparateFromAttribute();
- virtual void setFileList(const Vector<String>& paths);
virtual bool shouldResetOnDocumentActivation();
virtual bool shouldRespectListAttribute();
virtual bool shouldRespectSpeechAttribute();
Modified: trunk/Source/WebCore/page/DragController.cpp (89534 => 89535)
--- trunk/Source/WebCore/page/DragController.cpp 2011-06-23 06:00:22 UTC (rev 89534)
+++ trunk/Source/WebCore/page/DragController.cpp 2011-06-23 06:04:50 UTC (rev 89535)
@@ -420,14 +420,7 @@
if (filenames.isEmpty())
return false;
- // Ugly. For security none of the APIs available to us can set the input value
- // on file inputs. Even forcing a change in HTMLInputElement doesn't work as
- // RenderFileUploadControl clears the file when doing updateFromElement().
- RenderFileUploadControl* renderer = toRenderFileUploadControl(fileInput->renderer());
- if (!renderer)
- return false;
-
- renderer->receiveDroppedFiles(filenames);
+ fileInput->receiveDroppedFiles(filenames);
return true;
}
Modified: trunk/Source/WebCore/rendering/RenderFileUploadControl.cpp (89534 => 89535)
--- trunk/Source/WebCore/rendering/RenderFileUploadControl.cpp 2011-06-23 06:00:22 UTC (rev 89534)
+++ trunk/Source/WebCore/rendering/RenderFileUploadControl.cpp 2011-06-23 06:04:50 UTC (rev 89535)
@@ -21,24 +21,19 @@
#include "config.h"
#include "RenderFileUploadControl.h"
-#include "Chrome.h"
#include "FileList.h"
-#include "Frame.h"
-#include "FrameView.h"
#include "GraphicsContext.h"
#include "HTMLInputElement.h"
#include "HTMLNames.h"
#include "Icon.h"
#include "LocalizedStrings.h"
-#include "Page.h"
#include "PaintInfo.h"
#include "RenderButton.h"
#include "RenderText.h"
#include "RenderTheme.h"
-#include "RenderView.h"
-#include "ScriptController.h"
#include "ShadowRoot.h"
#include "TextRun.h"
+#include "VisiblePosition.h"
#include <math.h>
using namespace std;
@@ -57,106 +52,16 @@
RenderFileUploadControl::RenderFileUploadControl(HTMLInputElement* input)
: RenderBlock(input)
{
- ASSERT(input->files());
- requestIcon(input->files()->filenames());
}
RenderFileUploadControl::~RenderFileUploadControl()
{
}
-void RenderFileUploadControl::requestIcon(const Vector<String>& filenames)
-{
- if (!filenames.size())
- return;
-
- if (Chrome* chrome = this->chrome())
- chrome->loadIconForFiles(filenames, newFileIconLoader());
-}
-
-void RenderFileUploadControl::filesChosen(const Vector<String>& filenames)
-{
- HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(node());
- inputElement->setFileListFromRenderer(filenames);
- requestIcon(filenames);
-
- repaint();
- // This call may cause destruction of this instance and thus must always be last in the function.
- inputElement->dispatchFormControlChangeEvent();
-}
-
-#if ENABLE(DIRECTORY_UPLOAD)
-void RenderFileUploadControl::receiveDropForDirectoryUpload(const Vector<String>& paths)
-{
- if (Chrome* chrome = this->chrome()) {
- FileChooserSettings settings;
- settings.allowsDirectoryUpload = true;
- settings.allowsMultipleFiles = true;
- settings.selectedFiles.append(paths[0]);
- chrome->enumerateChosenDirectory(newFileChooser(settings));
- }
-}
-#endif
-
-
-void RenderFileUploadControl::updateRendering(PassRefPtr<Icon> icon)
-{
- if (m_icon == icon)
- return;
-
- m_icon = icon;
- repaint();
-}
-
-void RenderFileUploadControl::click()
-{
- if (!ScriptController::processingUserGesture())
- return;
-
- if (Chrome* chrome = this->chrome()) {
- FileChooserSettings settings;
- HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
-#if ENABLE(DIRECTORY_UPLOAD)
- settings.allowsDirectoryUpload = input->fastHasAttribute(webkitdirectoryAttr);
- settings.allowsMultipleFiles = settings.allowsDirectoryUpload || input->fastHasAttribute(multipleAttr);
-#else
- settings.allowsMultipleFiles = input->fastHasAttribute(multipleAttr);
-#endif
- settings.acceptTypes = input->accept();
- ASSERT(input->files());
- settings.selectedFiles = input->files()->filenames();
- chrome->runOpenPanel(frame(), newFileChooser(settings));
- }
-}
-
-Chrome* RenderFileUploadControl::chrome() const
-{
- Frame* frame = node()->document()->frame();
- if (!frame)
- return 0;
- Page* page = frame->page();
- if (!page)
- return 0;
- return page->chrome();
-}
-
void RenderFileUploadControl::updateFromElement()
{
- HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(node());
- ASSERT(inputElement->isFileUpload());
-
-
if (HTMLInputElement* button = uploadButton())
button->setDisabled(!theme()->isEnabled(this));
-
- // This only supports clearing out the files, but that's OK because for
- // security reasons that's the only change the DOM is allowed to make.
- FileList* files = inputElement->files();
- ASSERT(files);
- if (files && files->isEmpty() && m_icon) {
- m_icon = 0;
- repaint();
- }
}
static int nodeWidth(Node* node)
@@ -166,8 +71,9 @@
int RenderFileUploadControl::maxFilenameWidth() const
{
+ HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
return max(0, contentWidth() - nodeWidth(uploadButton()) - afterButtonSpacing
- - (m_icon ? iconWidth + iconFilenameSpacing : 0));
+ - (input->icon() ? iconWidth + iconFilenameSpacing : 0));
}
void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, const IntPoint& paintOffset)
@@ -197,9 +103,10 @@
if (!button)
return;
+ HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
int buttonWidth = nodeWidth(button);
int buttonAndIconWidth = buttonWidth + afterButtonSpacing
- + (m_icon ? iconWidth + iconFilenameSpacing : 0);
+ + (input->icon() ? iconWidth + iconFilenameSpacing : 0);
int textX;
if (style()->isLeftToRightDirection())
textX = contentLeft + buttonAndIconWidth;
@@ -216,7 +123,7 @@
// Draw the filename
paintInfo.context->drawBidiText(font, textRun, IntPoint(textX, textY));
- if (m_icon) {
+ if (input->icon()) {
// Determine where the icon should be placed
int iconY = paintOffset.y() + borderTop() + paddingTop() + (contentHeight() - iconHeight) / 2;
int iconX;
@@ -226,7 +133,7 @@
iconX = contentLeft + contentWidth() - buttonWidth - afterButtonSpacing - iconWidth;
// Draw the file icon
- m_icon->paint(paintInfo.context, IntRect(iconX, iconY, iconWidth, iconHeight));
+ input->icon()->paint(paintInfo.context, IntRect(iconX, iconY, iconWidth, iconHeight));
}
}
@@ -290,25 +197,6 @@
return buttonNode && buttonNode->isHTMLElement() && buttonNode->hasTagName(inputTag) ? static_cast<HTMLInputElement*>(buttonNode) : 0;
}
-void RenderFileUploadControl::receiveDroppedFiles(const Vector<String>& paths)
-{
- HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
-#if ENABLE(DIRECTORY_UPLOAD)
- if (input->fastHasAttribute(webkitdirectoryAttr)) {
- receiveDropForDirectoryUpload(paths);
- return;
- }
-#endif
-
- if (input->fastHasAttribute(multipleAttr))
- filesChosen(paths);
- else {
- Vector<String> firstPathOnly;
- firstPathOnly.append(paths[0]);
- filesChosen(firstPathOnly);
- }
-}
-
String RenderFileUploadControl::buttonValue()
{
if (HTMLInputElement* button = uploadButton())
Modified: trunk/Source/WebCore/rendering/RenderFileUploadControl.h (89534 => 89535)
--- trunk/Source/WebCore/rendering/RenderFileUploadControl.h 2011-06-23 06:00:22 UTC (rev 89534)
+++ trunk/Source/WebCore/rendering/RenderFileUploadControl.h 2011-06-23 06:04:50 UTC (rev 89535)
@@ -21,30 +21,23 @@
#ifndef RenderFileUploadControl_h
#define RenderFileUploadControl_h
-#include "FileChooser.h"
-#include "FileIconLoader.h"
#include "RenderBlock.h"
namespace WebCore {
-class Chrome;
class HTMLInputElement;
// Each RenderFileUploadControl contains a RenderButton (for opening the file chooser), and
// sufficient space to draw a file icon and filename. The RenderButton has a shadow node
// associated with it to receive click/hover events.
-class RenderFileUploadControl : public RenderBlock, private FileChooserClient, private FileIconLoaderClient {
+class RenderFileUploadControl : public RenderBlock {
public:
RenderFileUploadControl(HTMLInputElement*);
virtual ~RenderFileUploadControl();
virtual bool isFileUploadControl() const { return true; }
- void click();
-
- void receiveDroppedFiles(const Vector<String>&);
-
String buttonValue();
String fileTextValue() const;
@@ -57,25 +50,11 @@
virtual bool requiresForcedStyleRecalcPropagation() const { return true; }
- // FileChooserClient implementation.
- virtual void filesChosen(const Vector<String>&);
-
- // FileIconLoaderClient implementation.
- virtual void updateRendering(PassRefPtr<Icon>);
-
-#if ENABLE(DIRECTORY_UPLOAD)
- void receiveDropForDirectoryUpload(const Vector<String>&);
-#endif
-
- Chrome* chrome() const;
int maxFilenameWidth() const;
virtual VisiblePosition positionForPoint(const IntPoint&);
HTMLInputElement* uploadButton() const;
- void requestIcon(const Vector<String>&);
-
- RefPtr<Icon> m_icon;
};
inline RenderFileUploadControl* toRenderFileUploadControl(RenderObject* object)