Having a drop handler prevents navigation on drop even if event is not cancelled
[WebKit-https.git] / LayoutTests / http / tests / security / clipboard / clipboard-file-access.html
1 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
2 <html>
3 <head>
4 <script src="../../js-test-resources/js-test-pre.js"></script>
5 </head>
6 <body>
7 <p id="description"></p>
8 <div id="console"></div>
9 <script>
10 description("Tests access to event.dataTransfer.files and .types");
11
12 var dragTarget = document.createElement("div");
13 dragTarget.innerHTML = "Drag here"
14 dragTarget.style.backgroundColor = "blue";
15 dragTarget.style.width = "100px";
16 dragTarget.style.height = "100px";
17 // Important that we put this at the top of the doc so that logging does not cause it to go out of view (and be undragable)
18 document.body.insertBefore(dragTarget, document.body.firstChild);
19
20 var filesToDrag;
21 dragTarget.addEventListener("dragenter", function() {
22     debug("On dragenter:")
23     event.dataTransfer.dropEffect = "copy";
24     var shouldContainType = (filesToDrag.length > 0);
25     checkForEventTransferType(event, "Files", shouldContainType);
26     fileListShouldBe("event.dataTransfer.files", []);
27     event.preventDefault();
28 }, false);
29
30 dragTarget.addEventListener("dragover", function() {
31     debug("On dragover:")
32     event.dataTransfer.dropEffect = "copy";
33     var shouldContainType = (filesToDrag.length > 0);
34     checkForEventTransferType(event, "Files", shouldContainType);
35     fileListShouldBe("event.dataTransfer.files", []);
36     event.preventDefault();
37 }, false);
38
39 dragTarget.addEventListener("dragleave", function() {
40     debug("On dragleave:")
41     var shouldContainType = (filesToDrag.length > 0);
42     checkForEventTransferType(event, "Files", shouldContainType);
43     fileListShouldBe("event.dataTransfer.files", []);
44 }, false);
45
46 var expectedFilesOnDrop;
47 dragTarget.addEventListener("drop", function() {
48     debug("On drop:")
49     var shouldContainType = (filesToDrag.length > 0);
50     checkForEventTransferType(event, "Files", shouldContainType);
51     fileListShouldBe("event.dataTransfer.files", expectedFilesOnDrop);
52     event.preventDefault();
53 }, false);
54
55 // Some tests don't end up dropping the draggee over the drag target. Catch any
56 // leftover drop events bubbling up through the tree so they don't cause page
57 // navigation.
58 document.body.addEventListener("drop", function() {
59     event.preventDefault();
60 });
61
62 function moveMouseToCenterOfElement(element) {
63     var centerX = element.offsetLeft + element.offsetWidth / 2;
64     var centerY = element.offsetTop + element.offsetHeight / 2;
65     eventSender.mouseMoveTo(centerX, centerY);
66 }
67
68 function moveMouseToOutsideOfElement(element) {
69     var outsideX = element.offsetLeft + element.offsetWidth + 42;
70     var outsideY = element.offsetTop + element.offsetHeight + 42;
71     eventSender.mouseMoveTo(outsideX, outsideY);
72 }
73
74 function dragFilesOntoDragTarget(files, leave) {
75     filesToDrag = files;
76     eventSender.beginDragWithFiles(files);
77     moveMouseToCenterOfElement(dragTarget);
78     if (leave && leave === true)
79         moveMouseToOutsideOfElement(dragTarget);
80     eventSender.mouseUp();
81 }
82
83 function checkForEventTransferType(event, typeString, shouldContainType)
84 {
85     var passedCheck;
86     var message;
87     if (event.dataTransfer.types && event.dataTransfer.types.indexOf(typeString) != -1) {
88         passedCheck = shouldContainType;
89         message = "event.dataTransfer.types contains " + typeString + ".";
90     } else {
91         passedCheck = !shouldContainType;
92         message = "event.dataTransfer.types does not contain " + typeString + ".";
93     }
94     if (passedCheck)
95         testPassed(message);
96     else
97         testFailed(message);
98 }
99
100 function fileListShouldBe(fileListString, filesArray)
101 {
102     shouldBe(fileListString + ".length", "" + filesArray.length);
103     for (var x = 0; x < filesArray.length; x++) {
104         var fileValueString = fileListString + "[" + x + "]";
105         shouldBeEqualToString(fileValueString + ".name", filesArray[x]['name']);
106         shouldBe(fileValueString + ".size", "" + filesArray[x]['size']);
107     }
108 }
109
110 function draggingPathsShouldResultInFiles(pathsArray, filesArray, leave)
111 {
112     expectedFilesOnDrop = filesArray;
113     dragFilesOntoDragTarget(pathsArray, leave || false);
114 }
115
116 function testDraggingFiles(filesArray, leave)
117 {
118     // We could make a way to parse the filename from the path, and then only need to pass
119     // the path in the filesArray.
120     var pathsOnly = filesArray.map(function(fileSpec) { return fileSpec['path']; });
121     draggingPathsShouldResultInFiles(pathsOnly, filesArray, leave || false);
122 }
123
124 function runTest()
125 {
126     debug("Dragging no files should return an empty file list (arbitrary implementation detail):");
127     testDraggingFiles([]);
128
129     debug("Drag drop a single (non-existant) file onto an element:");
130     testDraggingFiles([
131         { 'path': 'DRTFakeFile', 'name' : 'DRTFakeFile', 'size' : 0 }
132     ]);
133
134     debug("FIXME: File.size always returns 0 for files dropped by eventSender.beginDragWithFiles from http tests:  https://bugs.webkit.org/show_bug.cgi?id=25909");
135
136     debug("Drag files over an element, leave that element and release the mouse:");   
137     testDraggingFiles([
138         { 'path': 'resources/apple.gif', 'name' : 'apple.gif', 'size' : 1476 }
139     ], true);
140
141     debug("Drag drop a real file onto an element:");
142     testDraggingFiles([
143         { 'path': 'resources/apple.gif', 'name' : 'apple.gif', 'size' : 1476 }
144     ]);
145     
146     debug("Drag drop two files onto an element:");
147     testDraggingFiles([
148         { 'path': 'resources/apple.gif', 'name' : 'apple.gif', 'size' : 1476 },
149         { 'path': 'resources/mozilla.gif', 'name' : 'mozilla.gif', 'size' : 2593 }
150     ]);
151
152     debug("Drag drop two files in reverse alphabetical order onto an element:");
153     testDraggingFiles([
154         { 'path': 'resources/mozilla.gif', 'name' : 'mozilla.gif', 'size' : 2593 },
155         { 'path': 'resources/apple.gif', 'name' : 'apple.gif', 'size' : 1476 }
156     ]);
157
158     // Directory dragging behavior is covered by https://bugs.webkit.org/show_bug.cgi?id=25852 and https://bugs.webkit.org/show_bug.cgi?id=25879
159     debug("FIXME: We should not allow element to accept drops including directories unless https://bugs.webkit.org/show_bug.cgi?id=25879 is fixed to make directory File objects useful from JavaScript.  The page is given File objects corresponding to directories, but form submission and xhr.send() will fail.");
160     debug("Drag drop a directory onto an element:");
161     draggingPathsShouldResultInFiles(['resources/directory-for-dragging'], []);
162
163     // Note: The order of selection in the Finder changes the order of file paths in the pasteboard
164     // thus it's important that we test different orders here as well (at least on the Mac)
165     // Both drops should be refused or succeed based on how https://bugs.webkit.org/show_bug.cgi?id=25879 is resolved.  Currently we expect drops to be refused.
166     debug("Drag drop a file and a directory onto an element:");
167     draggingPathsShouldResultInFiles(['resources/apple.gif', 'resources/directory-for-dragging'], []);
168
169     debug("Drag drop a directory and a file onto an element:")
170     draggingPathsShouldResultInFiles(['resources/directory-for-dragging', 'resources/apple.gif'], []);
171 }
172
173 if (window.eventSender) {
174     runTest();
175     // Clean up after ourselves
176     dragTarget.parentNode.removeChild(dragTarget);
177 } else {
178     testFailed("This test is not interactive, please run using DumpRenderTree");
179 }
180
181 var successfullyParsed = true;
182 </script>
183 <script src="../../js-test-resources/js-test-post.js"></script>
184 </body>
185 </html>