Commit 52e744de authored by oliver's avatar oliver

2007-05-12 Oliver Hunt <oliver@apple.com>

LayoutTests:

        Reviewed by Hyatt.
        
        Add test to verify files can be dragged to <input type="file">

        * fast/forms/dragging-to-file-input-expected.txt: Added.
        * fast/forms/dragging-to-file-input.html: Added.

WebCore:

        Reviewed by Hyatt.

        <rdar://problem/4728842> Can't drag-and-drop files onto <input type="file">
        
        This patch allows a file to be dropped on to a file input field.  There
        are a few changes for data handling and a  few to allow the data to be
        threaded to the appropriate places.

        * page/DragController.cpp:
        (WebCore::asFileInput):
           When dropping a file onto a file input we may mouse over either 
           the element itself, or the contained button element.  This method
           returns the base element for the file input in either of these
           cases.
        (WebCore::DragController::tryDocumentDrag):
           Don't try to set the drag caret to a file input.
        (WebCore::DragController::concludeDrag):
           Handle dropping onto a file input element.
        (WebCore::DragController::canProcessDrag):
           We can now process a file being dragged onto a file input element.
           
        * platform/DragData.h:
           New accessors
           
        * platform/gdk/DragDataGdk.cpp:
        (WebCore::DragData::containsFiles):
        (WebCore::DragData::asFilenames):
           Link stubs.
           
        * platform/mac/DragDataMac.mm:
        (WebCore::DragData::containsFiles):
        (WebCore::DragData::asFilenames):
           Implement new accessors
        (WebCore::DragData::containsCompatibleContent):
           Update containsCompatibleContent to allow standalone files.
          
        * platform/qt/DragDataQt.cpp:
        (WebCore::DragData::containsFiles):
        (WebCore::DragData::asFilenames):
           Link stubs
                      
        * rendering/RenderFileUploadControl.cpp:
        (WebCore::RenderFileUploadControl::receiveDroppedFile):
        * rendering/RenderFileUploadControl.h:
           For security reasons we don't have an api to allow us to set 
           a value directly on a file input -- attempts to do so are
           blocked.  By adding a method to set the target through the 
           render we bypass such restrictions, and ensure the renderer
           is updated correctly.

WebKitTools:

        Reviewed by Hyatt.
        
        Add new api to DRT to allow us to test a file being dragged 
        onto <input type="file">

        * DumpRenderTree/DumpRenderTree.h:
        * DumpRenderTree/DumpRenderTree.m:
        (+[LayoutTestController isSelectorExcludedFromWebScript:]):
        (-[LayoutTestController addFileToPasteboardOnDrag]):
        (runTest):
        * DumpRenderTree/UIDelegate.m:
        (-[UIDelegate webView:dragImage:at:offset:event:pasteboard:source:slideBack:forView:]):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@21437 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent d7ffcdc4
2007-05-12 Oliver Hunt <oliver@apple.com>
Reviewed by Hyatt.
Add test to verify files can be dragged to <input type="file">
* fast/forms/dragging-to-file-input-expected.txt: Added.
* fast/forms/dragging-to-file-input.html: Added.
2007-05-12 Mitz Pettel <mitz@webkit.org>
Reviewed by Hyatt.
This tests the ability to drag a file onto <input type="file">
To test manually you need to attempt to drag a file onto the file input below
PASS: Successfully dropped file on to file input
PASS: Finished test
<p>This tests the ability to drag a file onto &lt;input type="file"&gt;</p>
<p>To test manually you need to attempt to drag a file onto the file input below</p>
<input id="target" type="file"/><br />
<input id="dragStart" type="text" value="This input field is only present to allow DRT to initiate a drag"></input><br />
<pre id="console"></pre>
<script>
function debug(str) {
var c = document.getElementById('console')
c.appendChild(document.createTextNode(str + '\n'));
}
function runTest() {
var dragStart = document.getElementById("dragStart");
var x = dragStart.offsetLeft + dragStart.offsetWidth / 2;
var y = dragStart.offsetTop + dragStart.offsetHeight / 2;
var target = document.getElementById("target");
var tx = target.offsetLeft + target.offsetWidth / 2;
var ty = target.offsetTop + target.offsetHeight / 2;
dragStart.select();
var initialValue = target.value;
eventSender.mouseMoveTo(x, y);
eventSender.mouseDown();
eventSender.leapForward(400);
eventSender.mouseMoveTo(tx, ty);
eventSender.mouseUp();
var finalValue = target.value;
if (initialValue == finalValue || finalValue != "DRTFakeFile")
debug("FAIL: Could not drop file on to file input");
else
debug("PASS: Successfully dropped file on to file input");
debug("PASS: Finished test");
}
if (window.layoutTestController) {
layoutTestController.addFileToPasteboardOnDrag();
layoutTestController.dumpAsText();
runTest();
}
// remove drag source
var dragStart = document.getElementById("dragStart");
dragStart.parentNode.removeChild(dragStart);
</script>
\ No newline at end of file
2007-05-12 Oliver Hunt <oliver@apple.com>
Reviewed by Hyatt.
<rdar://problem/4728842> Can't drag-and-drop files onto <input type="file">
This patch allows a file to be dropped on to a file input field. There
are a few changes for data handling and a few to allow the data to be
threaded to the appropriate places.
* page/DragController.cpp:
(WebCore::asFileInput):
When dropping a file onto a file input we may mouse over either
the element itself, or the contained button element. This method
returns the base element for the file input in either of these
cases.
(WebCore::DragController::tryDocumentDrag):
Don't try to set the drag caret to a file input.
(WebCore::DragController::concludeDrag):
Handle dropping onto a file input element.
(WebCore::DragController::canProcessDrag):
We can now process a file being dragged onto a file input element.
* platform/DragData.h:
New accessors
* platform/gdk/DragDataGdk.cpp:
(WebCore::DragData::containsFiles):
(WebCore::DragData::asFilenames):
Link stubs.
* platform/mac/DragDataMac.mm:
(WebCore::DragData::containsFiles):
(WebCore::DragData::asFilenames):
Implement new accessors
(WebCore::DragData::containsCompatibleContent):
Update containsCompatibleContent to allow standalone files.
* platform/qt/DragDataQt.cpp:
(WebCore::DragData::containsFiles):
(WebCore::DragData::asFilenames):
Link stubs
* rendering/RenderFileUploadControl.cpp:
(WebCore::RenderFileUploadControl::receiveDroppedFile):
* rendering/RenderFileUploadControl.h:
For security reasons we don't have an api to allow us to set
a value directly on a file input -- attempts to do so are
blocked. By adding a method to set the target through the
render we bypass such restrictions, and ensure the renderer
is updated correctly.
2007-05-12 Mitz Pettel <mitz@webkit.org>
Reviewed by Hyatt.
......@@ -44,12 +44,15 @@
#include "FrameLoader.h"
#include "FrameView.h"
#include "HTMLAnchorElement.h"
#include "HTMLInputElement.h"
#include "HTMLNames.h"
#include "Image.h"
#include "markup.h"
#include "MoveSelectionCommand.h"
#include "Node.h"
#include "Page.h"
#include "PlugInInfoStore.h"
#include "RenderFileUploadControl.h"
#include "RenderImage.h"
#include "ReplaceSelectionCommand.h"
#include "ResourceRequest.h"
......@@ -248,6 +251,26 @@ DragOperation DragController::dragEnteredOrUpdated(DragData* dragData)
return operation;
}
static HTMLInputElement* asFileInput(Node* node)
{
ASSERT(node);
// The button for a FILE input is a sub element with no set input type
// In order to get around this problem we assume any non-FILE input element
// is this internal button, and try querying the shadow parent node.
if (node->hasTagName(HTMLNames::inputTag) && node->isShadowNode() && static_cast<HTMLInputElement*>(node)->inputType() != HTMLInputElement::FILE)
node = node->shadowParentNode();
if (!node || !node->hasTagName(HTMLNames::inputTag))
return 0;
HTMLInputElement* inputElem = static_cast<HTMLInputElement*>(node);
if (inputElem->inputType() == HTMLInputElement::FILE)
return inputElem;
return 0;
}
DragOperation DragController::tryDocumentDrag(DragData* dragData, DragDestinationAction actionMask)
{
......@@ -271,12 +294,15 @@ DragOperation DragController::tryDocumentDrag(DragData* dragData, DragDestinatio
IntPoint dragPos = dragData->clientPosition();
IntPoint point = frameView->windowToContents(dragPos);
Selection dragCaret(visiblePositionForPoint(m_document->frame(), point));
m_page->dragCaretController()->setSelection(dragCaret);
Element* element = m_document->elementFromPoint(point.x(), point.y());
ASSERT(element);
Frame* innerFrame = element->document()->frame();
ASSERT(innerFrame);
if (!asFileInput(element)) {
Selection dragCaret(visiblePositionForPoint(m_document->frame(), point));
m_page->dragCaretController()->setSelection(dragCaret);
}
return dragIsMove(innerFrame->selectionController(), dragData) ? DragOperationMove : DragOperationCopy;
}
......@@ -341,11 +367,33 @@ bool DragController::concludeDrag(DragData* dragData, DragDestinationAction acti
innerFrame->editor()->applyStyle(style.get(), EditActionSetColor);
return true;
}
if (!m_page->dragController()->canProcessDrag(dragData)) {
m_page->dragCaretController()->clear();
return false;
}
if (HTMLInputElement* fileInput = asFileInput(element)) {
if (!dragData->containsFiles())
return false;
Vector<String> filenames;
dragData->asFilenames(filenames);
if (filenames.isEmpty())
return false;
// Ugly. For security none of the API's available to us to 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 = static_cast<RenderFileUploadControl*>(fileInput->renderer());
if (!renderer)
return false;
// Only take the first filename as <input type="file" /> can only accept one
renderer->receiveDroppedFile(filenames[0]);
return true;
}
Selection dragCaret(m_page->dragCaretController()->selection());
m_page->dragCaretController()->clear();
......@@ -400,9 +448,16 @@ bool DragController::canProcessDrag(DragData* dragData)
return false;
result = m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(point, true);
if (!result.innerNonSharedNode() || !result.innerNonSharedNode()->isContentEditable())
if (!result.innerNonSharedNode())
return false;
if (dragData->containsFiles() && asFileInput(result.innerNonSharedNode()))
return true;
if (!result.innerNonSharedNode()->isContentEditable())
return false;
if (m_didInitiateDrag && m_document == m_dragInitiator && result.isSelected())
return false;
......
......@@ -32,6 +32,7 @@
#include "IntPoint.h"
#include <wtf/Forward.h>
#include <wtf/Vector.h>
#if PLATFORM(MAC)
#ifdef __OBJC__
......@@ -85,11 +86,12 @@ namespace WebCore {
bool containsCompatibleContent() const;
String asURL(String* title = 0) const;
String asPlainText() const;
void asFilenames(Vector<String>&) const;
Color asColor() const;
PassRefPtr<DocumentFragment> asFragment(Document*) const;
bool canSmartReplace() const;
bool containsColor() const;
bool containsFiles() const;
private:
IntPoint m_clientPosition;
IntPoint m_globalPosition;
......
......@@ -41,6 +41,15 @@ bool DragData::containsColor() const
return false;
}
bool DragData::containsFiles() const
{
return false;
}
void DragData::asFilenames(Vector<String>& result) const
{
}
bool DragData::containsPlainText() const
{
return false;
......
......@@ -55,12 +55,26 @@ bool DragData::canSmartReplace() const
Pasteboard::generalPasteboard();
return [[[m_platformDragData draggingPasteboard] types] containsObject:WebSmartPastePboardType];
}
bool DragData::containsColor() const
{
return [[[m_platformDragData draggingPasteboard] types] containsObject:NSColorPboardType];
}
bool DragData::containsFiles() const
{
return [[[m_platformDragData draggingPasteboard] types] containsObject:NSFilenamesPboardType];
}
void DragData::asFilenames(Vector<String>& result) const
{
NSArray *filenames = [[m_platformDragData draggingPasteboard] propertyListForType:NSFilenamesPboardType];
NSEnumerator *fileEnumerator = [filenames objectEnumerator];
while (NSString *filename = [fileEnumerator nextObject])
result.append(filename);
}
bool DragData::containsPlainText() const
{
NSPasteboard *pasteboard = [m_platformDragData draggingPasteboard];
......@@ -90,28 +104,13 @@ Clipboard* DragData::createClipboard(ClipboardAccessPolicy policy) const
return new ClipboardMac(true, [m_platformDragData draggingPasteboard], policy);
}
static bool imageExistsAtPaths(NSArray* paths)
{
NSEnumerator *enumerator = [paths objectEnumerator];
NSString *path;
while ((path = [enumerator nextObject]) != nil)
if (MimeTypeRegistry::isSupportedImageResourceMIMEType(MimeTypeRegistry::getMIMETypeForExtension([path pathExtension])))
return true;
return false;
}
bool DragData::containsCompatibleContent() const
{
NSPasteboard *pasteboard = [m_platformDragData draggingPasteboard];
NSMutableSet *types = [NSMutableSet setWithArray:[pasteboard types]];
[types intersectSet:[NSSet setWithArray:m_pasteboardHelper->insertablePasteboardTypes()]];
if ([types count] == 0)
return false;
return !([types count] == 1 && [types containsObject:NSFilenamesPboardType] &&
!imageExistsAtPaths([pasteboard propertyListForType:NSFilenamesPboardType]));
return [types count] != 0;
}
bool DragData::containsURL() const
......
......@@ -50,6 +50,16 @@ bool DragData::containsColor() const
return false;
}
bool DragData::containsFiles() const
{
notImplemented();
return false;
}
void DragData::asFilenames(Vector<String>& result) const
{
}
bool DragData::containsPlainText() const
{
return m_platformDragData->hasText() || m_platformDragData->hasUrls();
......
......@@ -266,6 +266,11 @@ void RenderFileUploadControl::calcPrefWidths()
setPrefWidthsDirty(false);
}
void RenderFileUploadControl::receiveDroppedFile(const String& filename)
{
m_fileChooser->chooseFile(filename);
}
HTMLFileUploadInnerButtonElement::HTMLFileUploadInnerButtonElement(Document* doc, Node* shadowParent)
: HTMLInputElement(doc)
, m_shadowParent(shadowParent)
......
......@@ -47,6 +47,8 @@ public:
void click();
void valueChanged();
void receiveDroppedFile(const String&);
private:
int maxFilenameWidth() const;
......
2007-05-12 Oliver Hunt <oliver@apple.com>
Reviewed by Hyatt.
Add new api to DRT to allow us to test a file being dragged
onto <input type="file">
* DumpRenderTree/DumpRenderTree.h:
* DumpRenderTree/DumpRenderTree.m:
(+[LayoutTestController isSelectorExcludedFromWebScript:]):
(-[LayoutTestController addFileToPasteboardOnDrag]):
(runTest):
* DumpRenderTree/UIDelegate.m:
(-[UIDelegate webView:dragImage:at:offset:event:pasteboard:source:slideBack:forView:]):
2007-05-11 Holger Hans Peter Freyther <zecke@selfish.org>
Reviewed by Maciej.
......
......@@ -39,5 +39,6 @@ extern NSMutableSet *disallowedURLs;
extern BOOL waitToDump;
extern BOOL canOpenWindows;
extern BOOL closeWebViews;
extern BOOL addFileToPasteboardOnDrag;
WebView *createWebView();
......@@ -110,6 +110,7 @@ @interface LocalPasteboard : NSPasteboard
BOOL canOpenWindows;
BOOL closeWebViews;
BOOL closeRemainingWindowsWhenComplete = YES;
BOOL addFileToPasteboardOnDrag = NO;
static void runTest(const char *pathOrURL);
static NSString *md5HashStringForBitmap(CGImageRef bitmap);
......@@ -1068,8 +1069,9 @@ + (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector
|| aSelector == @selector(setCanOpenWindows)
|| aSelector == @selector(setCallCloseOnWebViews:)
|| aSelector == @selector(setCloseRemainingWindowsWhenComplete:)
|| aSelector == @selector(setUseDashboardCompatibilityMode:))
return NO;
|| aSelector == @selector(setUseDashboardCompatibilityMode:)
|| aSelector == @selector(addFileToPasteboardOnDrag))
return NO;
return YES;
}
......@@ -1178,6 +1180,11 @@ - (void)dumpAsText
dumpAsText = YES;
}
- (void)addFileToPasteboardOnDrag
{
addFileToPasteboardOnDrag = YES;
}
- (void)addDisallowedURL:(NSString *)urlString
{
if (!disallowedURLs)
......@@ -1468,7 +1475,7 @@ static void runTest(const char *pathOrURL)
fprintf(stderr, "can't parse filename as UTF-8\n");
return;
}
CFURLRef URL;
if (CFStringHasPrefix(pathOrURLString, CFSTR("http://")))
URL = CFURLCreateWithString(NULL, pathOrURLString, NULL);
......@@ -1498,6 +1505,7 @@ static void runTest(const char *pathOrURL)
readFromWindow = NO;
canOpenWindows = NO;
closeWebViews = YES;
addFileToPasteboardOnDrag = NO;
[[frame webView] _setDashboardBehavior:WebDashboardBehaviorUseBackwardCompatibilityMode to:NO];
testRepaint = testRepaintDefault;
repaintSweepHorizontally = repaintSweepHorizontallyDefault;
......
......@@ -56,6 +56,10 @@ - (void)webView:(WebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *
- (void)webView:(WebView *)sender dragImage:(NSImage *)anImage at:(NSPoint)viewLocation offset:(NSSize)initialOffset event:(NSEvent *)event pasteboard:(NSPasteboard *)pboard source:(id)sourceObj slideBack:(BOOL)slideFlag forView:(NSView *)view
{
assert(!draggingInfo);
if (addFileToPasteboardOnDrag) {
[pboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType] owner:nil];
[pboard setPropertyList:[NSArray arrayWithObject:@"DRTFakeFile"] forType:NSFilenamesPboardType];
}
draggingInfo = [[DumpRenderTreeDraggingInfo alloc] initWithImage:anImage offset:initialOffset pasteboard:pboard source:sourceObj];
[EventSendingController replaySavedEvents];
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment