Move URL from WebCore to WTF
[WebKit-https.git] / Source / WebKit / WebProcess / WebCoreSupport / mac / WebDragClientMac.mm
1 /*
2  * Copyright (C) 2011 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "WebDragClient.h"
28
29 #if ENABLE(DRAG_SUPPORT)
30
31 #import "PasteboardTypes.h"
32 #import "ShareableBitmap.h"
33 #import "WebCoreArgumentCoders.h"
34 #import "WebPage.h"
35 #import "WebPageProxyMessages.h"
36 #import <WebCore/CachedImage.h>
37 #import <WebCore/Document.h>
38 #import <WebCore/DragController.h>
39 #import <WebCore/Editor.h>
40 #import <WebCore/Element.h>
41 #import <WebCore/Frame.h>
42 #import <WebCore/FrameDestructionObserver.h>
43 #import <WebCore/FrameView.h>
44 #import <WebCore/GraphicsContextCG.h>
45 #import <WebCore/LegacyWebArchive.h>
46 #import <WebCore/NotImplemented.h>
47 #import <WebCore/Page.h>
48 #import <WebCore/Pasteboard.h>
49 #import <WebCore/RenderImage.h>
50 #import <WebCore/StringTruncator.h>
51 #import <wtf/StdLibExtras.h>
52 #import <wtf/cocoa/NSURLExtras.h>
53
54 #if PLATFORM(IOS_FAMILY)
55 #import "UIKitSPI.h"
56 #endif
57
58 namespace WebKit {
59 using namespace WebCore;
60
61 #if PLATFORM(MAC)
62
63 static RefPtr<ShareableBitmap> convertImageToBitmap(NSImage *image, const IntSize& size, Frame& frame)
64 {
65     ShareableBitmap::Configuration bitmapConfiguration;
66     bitmapConfiguration.colorSpace.cgColorSpace = screenColorSpace(frame.mainFrame().view());
67     auto bitmap = ShareableBitmap::createShareable(size, bitmapConfiguration);
68     if (!bitmap)
69         return nullptr;
70
71     auto graphicsContext = bitmap->createGraphicsContext();
72
73     RetainPtr<NSGraphicsContext> savedContext = [NSGraphicsContext currentContext];
74
75     ALLOW_DEPRECATED_DECLARATIONS_BEGIN
76     [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:graphicsContext->platformContext() flipped:YES]];
77     ALLOW_DEPRECATED_DECLARATIONS_END
78     [image drawInRect:NSMakeRect(0, 0, bitmap->size().width(), bitmap->size().height()) fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:1 respectFlipped:YES hints:nil];
79
80     [NSGraphicsContext setCurrentContext:savedContext.get()];
81
82     return bitmap;
83 }
84
85 void WebDragClient::didConcludeEditDrag()
86 {
87 }
88
89 void WebDragClient::startDrag(DragItem dragItem, DataTransfer&, Frame& frame)
90 {
91     auto& image = dragItem.image;
92     IntSize bitmapSize([image.get() size]);
93     RefPtr<ShareableBitmap> bitmap = convertImageToBitmap(image.get().get(), bitmapSize, frame);
94     ShareableBitmap::Handle handle;
95     if (!bitmap || !bitmap->createHandle(handle))
96         return;
97
98     m_page->willStartDrag();
99     m_page->send(Messages::WebPageProxy::StartDrag(dragItem, handle));
100 }
101
102 static WebCore::CachedImage* cachedImage(Element& element)
103 {
104     auto* renderer = element.renderer();
105     if (!is<WebCore::RenderImage>(renderer))
106         return nullptr;
107     WebCore::CachedImage* image = downcast<WebCore::RenderImage>(*renderer).cachedImage();
108     if (!image || image->errorOccurred()) 
109         return nullptr;
110     return image;
111 }
112
113 void WebDragClient::declareAndWriteDragImage(const String& pasteboardName, Element& element, const URL& url, const String& label, Frame*)
114 {
115     ALLOW_DEPRECATED_DECLARATIONS_BEGIN
116     ASSERT(pasteboardName == String(NSDragPboard));
117     ALLOW_DEPRECATED_DECLARATIONS_END
118
119     WebCore::CachedImage* image = cachedImage(element);
120
121     String extension;
122     if (image) {
123         extension = image->image()->filenameExtension();
124         if (extension.isEmpty())
125             return;
126     }
127
128     String title = label;
129     if (title.isEmpty()) {
130         title = url.lastPathComponent();
131         if (title.isEmpty())
132             title = WTF::userVisibleString(url);
133     }
134
135     RefPtr<LegacyWebArchive> archive = LegacyWebArchive::create(element);
136
137     NSURLResponse *response = image->response().nsURLResponse();
138     
139     RefPtr<SharedBuffer> imageBuffer = image->image()->data();
140     size_t imageSize = imageBuffer->size();
141     SharedMemory::Handle imageHandle;
142     
143     RefPtr<SharedMemory> sharedMemoryBuffer = SharedMemory::allocate(imageBuffer->size());
144     if (!sharedMemoryBuffer)
145         return;
146     memcpy(sharedMemoryBuffer->data(), imageBuffer->data(), imageSize);
147     sharedMemoryBuffer->createHandle(imageHandle, SharedMemory::Protection::ReadOnly);
148     
149     RetainPtr<CFDataRef> data = archive ? archive->rawDataRepresentation() : 0;
150     SharedMemory::Handle archiveHandle;
151     size_t archiveSize = 0;
152     if (data) {
153         auto archiveBuffer = SharedBuffer::create((__bridge NSData *)data.get());
154         RefPtr<SharedMemory> archiveSharedMemoryBuffer = SharedMemory::allocate(archiveBuffer->size());
155         if (!archiveSharedMemoryBuffer)
156             return;
157         archiveSize = archiveBuffer->size();
158         memcpy(archiveSharedMemoryBuffer->data(), archiveBuffer->data(), archiveSize);
159         archiveSharedMemoryBuffer->createHandle(archiveHandle, SharedMemory::Protection::ReadOnly);
160     }
161
162     String filename = String([response suggestedFilename]);
163     if (m_page->isInspectorPage()) {
164         String downloadFilename = ResourceResponseBase::sanitizeSuggestedFilename(element.attributeWithoutSynchronization(HTMLNames::filenameAttr));
165         if (!downloadFilename.isEmpty())
166             filename = downloadFilename;
167     }
168
169     m_page->send(Messages::WebPageProxy::SetPromisedDataForImage(pasteboardName, imageHandle, imageSize, filename, extension, title, String([[response URL] absoluteString]), WTF::userVisibleString(url), archiveHandle, archiveSize));
170 }
171
172 #endif // PLATFORM(MAC)
173
174 #if PLATFORM(IOS_FAMILY)
175
176 static RefPtr<ShareableBitmap> convertCGImageToBitmap(CGImageRef image, const IntSize& size, Frame& frame)
177 {
178     ShareableBitmap::Configuration bitmapConfiguration;
179     bitmapConfiguration.colorSpace.cgColorSpace = screenColorSpace(frame.mainFrame().view());
180     auto bitmap = ShareableBitmap::createShareable(size, bitmapConfiguration);
181     if (!bitmap)
182         return nullptr;
183
184     auto graphicsContext = bitmap->createGraphicsContext();
185     UIGraphicsPushContext(graphicsContext->platformContext());
186     CGContextDrawImage(graphicsContext->platformContext(), CGRectMake(0, 0, size.width(), size.height()), image);
187     UIGraphicsPopContext();
188     return bitmap;
189 }
190
191 void WebDragClient::startDrag(DragItem dragItem, DataTransfer& dataTransfer, Frame& frame)
192 {
193     auto& image = dragItem.image;
194
195     IntSize bitmapSize(CGImageGetWidth(image.get().get()), CGImageGetHeight(image.get().get()));
196     auto bitmap = convertCGImageToBitmap(image.get().get(), bitmapSize, frame);
197     ShareableBitmap::Handle handle;
198     if (!bitmap || !bitmap->createHandle(handle))
199         return;
200
201     m_page->willStartDrag();
202     m_page->send(Messages::WebPageProxy::StartDrag(dragItem, handle));
203 }
204
205 void WebDragClient::declareAndWriteDragImage(const String& pasteboardName, Element& element, const URL& url, const String& label, Frame*)
206 {
207     if (auto frame = element.document().frame())
208         frame->editor().writeImageToPasteboard(*Pasteboard::createForDragAndDrop(), element, url, label);
209 }
210
211 void WebDragClient::didConcludeEditDrag()
212 {
213     m_page->didConcludeEditDataInteraction();
214 }
215
216 #endif // PLATFORM(IOS_FAMILY)
217
218 } // namespace WebKit
219
220 #endif // ENABLE(DRAG_SUPPORT)