1/* 2 * Copyright (C) 2011 Igalia S.L. 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#include "config.h" 27#include "ArgumentCodersGtk.h" 28 29#include "DataReference.h" 30#include "ShareableBitmap.h" 31#include "WebCoreArgumentCoders.h" 32#include <WebCore/DataObjectGtk.h> 33#include <WebCore/DragData.h> 34#include <WebCore/GraphicsContext.h> 35#include <WebCore/GtkVersioning.h> 36#include <WebCore/PlatformContextCairo.h> 37#include <wtf/gobject/GUniquePtr.h> 38 39using namespace WebCore; 40using namespace WebKit; 41 42namespace IPC { 43 44static void encodeImage(ArgumentEncoder& encoder, const GdkPixbuf* pixbuf) 45{ 46 IntSize imageSize(gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf)); 47 RefPtr<ShareableBitmap> bitmap = ShareableBitmap::createShareable(imageSize, ShareableBitmap::SupportsAlpha); 48 auto graphicsContext = bitmap->createGraphicsContext(); 49 50 cairo_t* cr = graphicsContext->platformContext()->cr(); 51 gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0); 52 cairo_paint(cr); 53 54 ShareableBitmap::Handle handle; 55 bitmap->createHandle(handle); 56 57 encoder << handle; 58} 59 60static bool decodeImage(ArgumentDecoder& decoder, GRefPtr<GdkPixbuf>& pixbuf) 61{ 62 ShareableBitmap::Handle handle; 63 if (!decoder.decode(handle)) 64 return false; 65 66 RefPtr<ShareableBitmap> bitmap = ShareableBitmap::create(handle); 67 if (!bitmap) 68 return false; 69 70 RefPtr<Image> image = bitmap->createImage(); 71 if (!image) 72 return false; 73 74 RefPtr<cairo_surface_t> surface = image->nativeImageForCurrentFrame(); 75 if (!surface) 76 return false; 77 78 pixbuf = adoptGRef(gdk_pixbuf_get_from_surface(surface.get(), 0, 0, cairo_image_surface_get_width(surface.get()), cairo_image_surface_get_height(surface.get()))); 79 if (!pixbuf) 80 return false; 81 82 return true; 83} 84 85static void encodeDataObject(ArgumentEncoder& encoder, const DataObjectGtk* dataObject) 86{ 87 bool hasText = dataObject->hasText(); 88 encoder << hasText; 89 if (hasText) 90 encoder << dataObject->text(); 91 92 bool hasMarkup = dataObject->hasMarkup(); 93 encoder << hasMarkup; 94 if (hasMarkup) 95 encoder << dataObject->markup(); 96 97 bool hasURL = dataObject->hasURL(); 98 encoder << hasURL; 99 if (hasURL) 100 encoder << dataObject->url().string(); 101 102 bool hasURIList = dataObject->hasURIList(); 103 encoder << hasURIList; 104 if (hasURIList) 105 encoder << dataObject->uriList(); 106 107 bool hasImage = dataObject->hasImage(); 108 encoder << hasImage; 109 if (hasImage) 110 encodeImage(encoder, dataObject->image()); 111 112 bool hasUnknownTypeData = dataObject->hasUnknownTypeData(); 113 encoder << hasUnknownTypeData; 114 if (hasUnknownTypeData) 115 encoder << dataObject->unknownTypes(); 116} 117 118static bool decodeDataObject(ArgumentDecoder& decoder, RefPtr<DataObjectGtk>& dataObject) 119{ 120 RefPtr<DataObjectGtk> data = DataObjectGtk::create(); 121 122 bool hasText; 123 if (!decoder.decode(hasText)) 124 return false; 125 if (hasText) { 126 String text; 127 if (!decoder.decode(text)) 128 return false; 129 data->setText(text); 130 } 131 132 bool hasMarkup; 133 if (!decoder.decode(hasMarkup)) 134 return false; 135 if (hasMarkup) { 136 String markup; 137 if (!decoder.decode(markup)) 138 return false; 139 data->setMarkup(markup); 140 } 141 142 bool hasURL; 143 if (!decoder.decode(hasURL)) 144 return false; 145 if (hasURL) { 146 String url; 147 if (!decoder.decode(url)) 148 return false; 149 data->setURL(URL(URL(), url), String()); 150 } 151 152 bool hasURIList; 153 if (!decoder.decode(hasURIList)) 154 return false; 155 if (hasURIList) { 156 String uriList; 157 if (!decoder.decode(uriList)) 158 return false; 159 data->setURIList(uriList); 160 } 161 162 bool hasImage; 163 if (!decoder.decode(hasImage)) 164 return false; 165 if (hasImage) { 166 GRefPtr<GdkPixbuf> image; 167 if (!decodeImage(decoder, image)) 168 return false; 169 data->setImage(image.get()); 170 } 171 172 bool hasUnknownTypeData; 173 if (!decoder.decode(hasUnknownTypeData)) 174 return false; 175 if (hasUnknownTypeData) { 176 HashMap<String, String> unknownTypes; 177 if (!decoder.decode(unknownTypes)) 178 return false; 179 180 auto end = unknownTypes.end(); 181 for (auto it = unknownTypes.begin(); it != end; ++it) 182 data->setUnknownTypeData(it->key, it->value); 183 } 184 185 dataObject = data; 186 187 return true; 188} 189 190void ArgumentCoder<DragData>::encode(ArgumentEncoder& encoder, const DragData& dragData) 191{ 192 encoder << dragData.clientPosition(); 193 encoder << dragData.globalPosition(); 194 encoder << static_cast<uint64_t>(dragData.draggingSourceOperationMask()); 195 encoder << static_cast<uint64_t>(dragData.flags()); 196 197 DataObjectGtk* platformData = dragData.platformData(); 198 encoder << static_cast<bool>(platformData); 199 if (platformData) 200 encodeDataObject(encoder, platformData); 201} 202 203bool ArgumentCoder<DragData>::decode(ArgumentDecoder& decoder, DragData& dragData) 204{ 205 IntPoint clientPosition; 206 if (!decoder.decode(clientPosition)) 207 return false; 208 209 IntPoint globalPosition; 210 if (!decoder.decode(globalPosition)) 211 return false; 212 213 uint64_t sourceOperationMask; 214 if (!decoder.decode(sourceOperationMask)) 215 return false; 216 217 uint64_t flags; 218 if (!decoder.decode(flags)) 219 return false; 220 221 bool hasPlatformData; 222 if (!decoder.decode(hasPlatformData)) 223 return false; 224 225 RefPtr<DataObjectGtk> platformData; 226 if (hasPlatformData) { 227 if (!decodeDataObject(decoder, platformData)) 228 return false; 229 } 230 231 dragData = DragData(platformData.release().leakRef(), clientPosition, globalPosition, static_cast<DragOperation>(sourceOperationMask), 232 static_cast<DragApplicationFlags>(flags)); 233 234 return true; 235} 236 237static void encodeGKeyFile(ArgumentEncoder& encoder, GKeyFile* keyFile) 238{ 239 gsize dataSize; 240 GUniquePtr<char> data(g_key_file_to_data(keyFile, &dataSize, 0)); 241 encoder << DataReference(reinterpret_cast<uint8_t*>(data.get()), dataSize); 242} 243 244static bool decodeGKeyFile(ArgumentDecoder& decoder, GUniquePtr<GKeyFile>& keyFile) 245{ 246 DataReference dataReference; 247 if (!decoder.decode(dataReference)) 248 return false; 249 250 if (!dataReference.size()) 251 return true; 252 253 keyFile.reset(g_key_file_new()); 254 if (!g_key_file_load_from_data(keyFile.get(), reinterpret_cast<const gchar*>(dataReference.data()), dataReference.size(), G_KEY_FILE_NONE, 0)) { 255 keyFile.reset(); 256 return false; 257 } 258 259 return true; 260} 261 262void encode(ArgumentEncoder& encoder, GtkPrintSettings* printSettings) 263{ 264 GUniquePtr<GKeyFile> keyFile(g_key_file_new()); 265 gtk_print_settings_to_key_file(printSettings, keyFile.get(), "Print Settings"); 266 encodeGKeyFile(encoder, keyFile.get()); 267} 268 269bool decode(ArgumentDecoder& decoder, GRefPtr<GtkPrintSettings>& printSettings) 270{ 271 GUniquePtr<GKeyFile> keyFile; 272 if (!decodeGKeyFile(decoder, keyFile)) 273 return false; 274 275 printSettings = adoptGRef(gtk_print_settings_new()); 276 if (!keyFile) 277 return true; 278 279 if (!gtk_print_settings_load_key_file(printSettings.get(), keyFile.get(), "Print Settings", 0)) 280 printSettings = 0; 281 282 return printSettings; 283} 284 285void encode(ArgumentEncoder& encoder, GtkPageSetup* pageSetup) 286{ 287 GUniquePtr<GKeyFile> keyFile(g_key_file_new()); 288 gtk_page_setup_to_key_file(pageSetup, keyFile.get(), "Page Setup"); 289 encodeGKeyFile(encoder, keyFile.get()); 290} 291 292bool decode(ArgumentDecoder& decoder, GRefPtr<GtkPageSetup>& pageSetup) 293{ 294 GUniquePtr<GKeyFile> keyFile; 295 if (!decodeGKeyFile(decoder, keyFile)) 296 return false; 297 298 pageSetup = adoptGRef(gtk_page_setup_new()); 299 if (!keyFile) 300 return true; 301 302 if (!gtk_page_setup_load_key_file(pageSetup.get(), keyFile.get(), "Page Setup", 0)) 303 pageSetup = 0; 304 305 return pageSetup; 306} 307 308} 309