Use CompletionHandlers for ResourceHandleClient::didReceiveResponseAsync
[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/MainFrame.h>
47 #import <WebCore/NotImplemented.h>
48 #import <WebCore/Page.h>
49 #import <WebCore/Pasteboard.h>
50 #import <WebCore/RenderImage.h>
51 #import <WebCore/StringTruncator.h>
52 #import <WebCore/WebCoreNSURLExtras.h>
53 #import <wtf/StdLibExtras.h>
54
55 #if PLATFORM(IOS)
56 #import "UIKitSPI.h"
57 #endif
58
59 using namespace WebCore;
60 using namespace WebKit;
61
62 namespace WebKit {
63
64 #if PLATFORM(MAC)
65
66 static RefPtr<ShareableBitmap> convertImageToBitmap(NSImage *image, const IntSize& size, Frame& frame)
67 {
68     ShareableBitmap::Configuration bitmapConfiguration;
69     bitmapConfiguration.colorSpace.cgColorSpace = screenColorSpace(frame.mainFrame().view());
70     auto bitmap = ShareableBitmap::createShareable(size, bitmapConfiguration);
71     if (!bitmap)
72         return nullptr;
73
74     auto graphicsContext = bitmap->createGraphicsContext();
75
76     RetainPtr<NSGraphicsContext> savedContext = [NSGraphicsContext currentContext];
77
78 #pragma clang diagnostic push
79 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
80     [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:graphicsContext->platformContext() flipped:YES]];
81 #pragma clang diagnostic pop
82     [image drawInRect:NSMakeRect(0, 0, bitmap->size().width(), bitmap->size().height()) fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:1 respectFlipped:YES hints:nil];
83
84     [NSGraphicsContext setCurrentContext:savedContext.get()];
85
86     return bitmap;
87 }
88
89 void WebDragClient::didConcludeEditDrag()
90 {
91 }
92
93 void WebDragClient::startDrag(DragItem dragItem, DataTransfer&, Frame& frame)
94 {
95     auto& image = dragItem.image;
96     IntSize bitmapSize([image.get() size]);
97     RefPtr<ShareableBitmap> bitmap = convertImageToBitmap(image.get().get(), bitmapSize, frame);
98     ShareableBitmap::Handle handle;
99     if (!bitmap || !bitmap->createHandle(handle))
100         return;
101
102     m_page->willStartDrag();
103     m_page->send(Messages::WebPageProxy::StartDrag(dragItem, handle));
104 }
105
106 static WebCore::CachedImage* cachedImage(Element& element)
107 {
108     auto* renderer = element.renderer();
109     if (!is<WebCore::RenderImage>(renderer))
110         return nullptr;
111     WebCore::CachedImage* image = downcast<WebCore::RenderImage>(*renderer).cachedImage();
112     if (!image || image->errorOccurred()) 
113         return nullptr;
114     return image;
115 }
116
117 void WebDragClient::declareAndWriteDragImage(const String& pasteboardName, Element& element, const URL& url, const String& label, Frame*)
118 {
119 #pragma clang diagnostic push
120 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
121     ASSERT(pasteboardName == String(NSDragPboard));
122 #pragma clang diagnostic pop
123
124     WebCore::CachedImage* image = cachedImage(element);
125
126     String extension;
127     if (image) {
128         extension = image->image()->filenameExtension();
129         if (extension.isEmpty())
130             return;
131     }
132
133     String title = label;
134     if (title.isEmpty()) {
135         title = url.lastPathComponent();
136         if (title.isEmpty())
137             title = userVisibleString((NSURL *)url);
138     }
139
140     RefPtr<LegacyWebArchive> archive = LegacyWebArchive::create(element);
141
142     NSURLResponse *response = image->response().nsURLResponse();
143     
144     RefPtr<SharedBuffer> imageBuffer = image->image()->data();
145     size_t imageSize = imageBuffer->size();
146     SharedMemory::Handle imageHandle;
147     
148     RefPtr<SharedMemory> sharedMemoryBuffer = SharedMemory::allocate(imageBuffer->size());
149     if (!sharedMemoryBuffer)
150         return;
151     memcpy(sharedMemoryBuffer->data(), imageBuffer->data(), imageSize);
152     sharedMemoryBuffer->createHandle(imageHandle, SharedMemory::Protection::ReadOnly);
153     
154     RetainPtr<CFDataRef> data = archive ? archive->rawDataRepresentation() : 0;
155     SharedMemory::Handle archiveHandle;
156     size_t archiveSize = 0;
157     if (data) {
158         RefPtr<SharedBuffer> archiveBuffer = SharedBuffer::create((NSData *)data.get());
159         RefPtr<SharedMemory> archiveSharedMemoryBuffer = SharedMemory::allocate(archiveBuffer->size());
160         if (!archiveSharedMemoryBuffer)
161             return;
162         archiveSize = archiveBuffer->size();
163         memcpy(archiveSharedMemoryBuffer->data(), archiveBuffer->data(), archiveSize);
164         archiveSharedMemoryBuffer->createHandle(archiveHandle, SharedMemory::Protection::ReadOnly);
165     }
166
167     String filename = String([response suggestedFilename]);
168     if (m_page->isInspectorPage()) {
169         String downloadFilename = ResourceResponseBase::sanitizeSuggestedFilename(element.attributeWithoutSynchronization(HTMLNames::filenameAttr));
170         if (!downloadFilename.isEmpty())
171             filename = downloadFilename;
172     }
173
174     m_page->send(Messages::WebPageProxy::SetPromisedDataForImage(pasteboardName, imageHandle, imageSize, filename, extension, title, String([[response URL] absoluteString]), userVisibleString((NSURL *)url), archiveHandle, archiveSize));
175 }
176
177 #endif // PLATFORM(MAC)
178
179 #if PLATFORM(IOS)
180
181 static RefPtr<ShareableBitmap> convertCGImageToBitmap(CGImageRef image, const IntSize& size, Frame& frame)
182 {
183     ShareableBitmap::Configuration bitmapConfiguration;
184     bitmapConfiguration.colorSpace.cgColorSpace = screenColorSpace(frame.mainFrame().view());
185     auto bitmap = ShareableBitmap::createShareable(size, bitmapConfiguration);
186     if (!bitmap)
187         return nullptr;
188
189     auto graphicsContext = bitmap->createGraphicsContext();
190     UIGraphicsPushContext(graphicsContext->platformContext());
191     CGContextDrawImage(graphicsContext->platformContext(), CGRectMake(0, 0, size.width(), size.height()), image);
192     UIGraphicsPopContext();
193     return bitmap;
194 }
195
196 void WebDragClient::startDrag(DragItem dragItem, DataTransfer& dataTransfer, Frame& frame)
197 {
198     auto& image = dragItem.image;
199
200     IntSize bitmapSize(CGImageGetWidth(image.get().get()), CGImageGetHeight(image.get().get()));
201     auto bitmap = convertCGImageToBitmap(image.get().get(), bitmapSize, frame);
202     ShareableBitmap::Handle handle;
203     if (!bitmap || !bitmap->createHandle(handle))
204         return;
205
206     m_page->willStartDrag();
207     m_page->send(Messages::WebPageProxy::StartDrag(dragItem, handle));
208 }
209
210 void WebDragClient::declareAndWriteDragImage(const String& pasteboardName, Element& element, const URL& url, const String& label, Frame*)
211 {
212     if (auto frame = element.document().frame())
213         frame->editor().writeImageToPasteboard(*Pasteboard::createForDragAndDrop(), element, url, label);
214 }
215
216 void WebDragClient::didConcludeEditDrag()
217 {
218     m_page->didConcludeEditDataInteraction();
219 }
220
221 #endif // PLATFORM(IOS)
222
223 } // namespace WebKit
224
225 #endif // ENABLE(DRAG_SUPPORT)