Add and deploy WK_API_ENABLED guards
[WebKit-https.git] / Source / WebKit2 / Shared / mac / ObjCObjectGraphCoders.mm
1 /*
2  * Copyright (C) 2012 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 "ObjCObjectGraphCoders.h"
28
29 #import "ArgumentCodersMac.h"
30 #import "WKTypeRefWrapper.h"
31
32 // For UIProcess side encoding/decoding
33 #import "WKAPICast.h"
34 #import "WKBrowsingContextControllerInternal.h"
35 #import "WKBrowsingContextControllerPrivate.h"
36 #import "WebContextUserMessageCoders.h"
37 #import "WebPageProxy.h"
38 #import "WebProcessProxy.h"
39
40 // For WebProcess side encoding/decoding
41 #import "InjectedBundleUserMessageCoders.h"
42 #import "WKBundleAPICast.h"
43 #import "WKWebProcessPlugInBrowserContextControllerInternal.h"
44 #import "WKWebProcessPlugInBrowserContextControllerPrivate.h"
45 #import "WKWebProcessPlugInInternal.h"
46 #import "WebPage.h"
47 #import "WebProcess.h"
48
49 namespace WebKit {
50
51 enum WebKitNSType {
52     NullType,
53     NSDictionaryType,
54     NSArrayType,
55     NSStringType,
56     NSNumberType,
57     NSDateType,
58     NSDataType,
59 #if WK_API_ENABLED
60     WKBrowsingContextControllerType,
61     WKTypeRefWrapperType,
62 #endif
63     UnknownType,
64 };
65
66 static WebKitNSType typeFromObject(id object)
67 {
68     ASSERT(object);
69
70     if ([object isKindOfClass:[NSDictionary class]])
71         return NSDictionaryType;
72     if ([object isKindOfClass:[NSString class]])
73         return NSStringType;
74     if ([object isKindOfClass:[NSArray class]])
75         return NSArrayType;
76     if ([object isKindOfClass:[NSNumber class]])
77         return NSNumberType;
78     if ([object isKindOfClass:[NSDate class]])
79         return NSDateType;
80     if ([object isKindOfClass:[NSData class]])
81         return NSDataType;
82 #if WK_API_ENABLED
83     if ([object isKindOfClass:[WKBrowsingContextController class]] || [object isKindOfClass:[WKWebProcessPlugInBrowserContextController class]])
84         return WKBrowsingContextControllerType;
85     if ([object isKindOfClass:[WKTypeRefWrapper class]])
86         return WKTypeRefWrapperType;
87 #endif
88
89     return UnknownType;
90 }
91
92 template<typename Owner>
93 class ObjCObjectGraphEncoder {
94 public:
95     bool baseEncode(CoreIPC::ArgumentEncoder& encoder, WebKitNSType& type) const
96     {
97         if (!m_root) {
98             encoder << static_cast<uint32_t>(NullType);
99             return true;
100         }
101
102         type = typeFromObject(m_root);
103         if (type == UnknownType) {
104             [NSException raise:NSInvalidArgumentException format:@"Can not encode objects of class type '%@'", static_cast<NSString *>(NSStringFromClass([m_root class]))];
105         }
106
107         encoder << static_cast<uint32_t>(type);
108
109         switch (type) {
110         case NSStringType: {
111             CoreIPC::encode(encoder, static_cast<NSString *>(m_root));
112             return true;
113         }
114         case NSArrayType: {
115             NSArray *array = static_cast<NSArray *>(m_root);
116
117             NSUInteger size = [array count];
118             encoder << static_cast<uint64_t>(size);
119
120             for (NSUInteger i = 0; i < size; ++i)
121                 encoder << Owner([array objectAtIndex:i]);
122             return true;
123         }
124         case NSDictionaryType: {
125             NSDictionary* dictionary = static_cast<NSDictionary *>(m_root);
126
127             NSUInteger size = [dictionary count];
128             encoder << static_cast<uint64_t>(size);
129
130             NSArray *keys = [dictionary allKeys];
131             NSArray *values = [dictionary allValues];
132             for (NSUInteger i = 0; i < size; ++i) {
133                 encoder << Owner([keys objectAtIndex:i]);
134                 encoder << Owner([values objectAtIndex:i]);
135             }
136
137             return true;
138         }
139         case NSNumberType: {
140             CoreIPC::encode(encoder, static_cast<NSNumber *>(m_root));
141             return true;
142         }
143         case NSDateType: {
144             CoreIPC::encode(encoder, static_cast<NSDate *>(m_root));
145             return true;
146         }
147         case NSDataType: {
148             CoreIPC::encode(encoder, static_cast<NSData *>(m_root));
149             return true;
150         }
151         default:
152             break;
153         }
154
155         return false;
156     }
157
158 protected:
159     ObjCObjectGraphEncoder(id root)
160         : m_root(root)
161     {
162     }
163
164     id m_root;
165 };
166
167 template<typename Owner>
168 class ObjCObjectGraphDecoder {
169 public:
170     static bool baseDecode(CoreIPC::ArgumentDecoder& decoder, Owner& coder, WebKitNSType& type)
171     {
172         uint32_t typeAsUInt32;
173         if (!decoder.decode(typeAsUInt32))
174             return false;
175
176         type = static_cast<WebKitNSType>(typeAsUInt32);
177
178         switch (type) {
179         case NSStringType: {
180             RetainPtr<NSString> string;
181             if (!CoreIPC::decode(decoder, string))
182                 return false;
183             coder.m_root = string;
184             break;
185         }
186         case NSArrayType: {
187             uint64_t size;
188             if (!decoder.decode(size))
189                 return false;
190
191             RetainPtr<NSMutableArray> array = adoptNS([[NSMutableArray alloc] initWithCapacity:size]);
192             for (uint64_t i = 0; i < size; ++i) {
193                 RetainPtr<id> value;
194                 Owner messageCoder(coder, value);
195                 if (!decoder.decode(messageCoder))
196                     return false;
197
198                 [array.get() addObject:value.get()];
199             }
200
201             coder.m_root = array;
202             break;
203         }
204         case NSDictionaryType: {
205             uint64_t size;
206             if (!decoder.decode(size))
207                 return false;
208
209             RetainPtr<NSMutableDictionary> dictionary = adoptNS([[NSMutableDictionary alloc] initWithCapacity:size]);
210             for (uint64_t i = 0; i < size; ++i) {
211                 // Try to decode the key name.
212                 RetainPtr<id> key;
213                 Owner keyMessageCoder(coder, key);
214                 if (!decoder.decode(keyMessageCoder))
215                     return false;
216
217                 RetainPtr<id> value;
218                 Owner valueMessageCoder(coder, value);
219                 if (!decoder.decode(valueMessageCoder))
220                     return false;
221
222                 [dictionary.get() setObject:value.get() forKey:key.get()];
223             }
224
225             coder.m_root = dictionary;
226             break;
227         }
228         case NSNumberType: {
229             RetainPtr<NSNumber> number;
230             if (!CoreIPC::decode(decoder, number))
231                 return false;
232             coder.m_root = number;
233             break;
234         }
235         case NSDateType: {
236             RetainPtr<NSDate> date;
237             if (!CoreIPC::decode(decoder, date))
238                 return false;
239             coder.m_root = date;
240             break;
241         }
242         case NSDataType: {
243             RetainPtr<NSData> data;
244             if (!CoreIPC::decode(decoder, data))
245                 return false;
246             coder.m_root = data;
247             break;
248         }
249         default:
250             break;
251         }
252
253         return true;
254     }
255
256 protected:
257     ObjCObjectGraphDecoder(RetainPtr<id>& root)
258         : m_root(root)
259     {
260     }
261
262     RetainPtr<id>& m_root;
263 };
264
265
266 // WebContext Additions
267
268 class WebContextObjCObjectGraphEncoderImpl : public ObjCObjectGraphEncoder<WebContextObjCObjectGraphEncoderImpl> {
269 public:
270     typedef ObjCObjectGraphEncoder<WebContextObjCObjectGraphEncoderImpl> Base;
271
272     explicit WebContextObjCObjectGraphEncoderImpl(id root)
273         : Base(root)
274     {
275     }
276
277     void encode(CoreIPC::ArgumentEncoder& encoder) const
278     {
279         WebKitNSType type = NullType;
280         if (baseEncode(encoder, type))
281             return;
282
283         switch (type) {
284 #if WK_API_ENABLED
285         case WKBrowsingContextControllerType: {
286             WKBrowsingContextController *browsingContextController = static_cast<WKBrowsingContextController *>(m_root);
287
288             encoder << toImpl(browsingContextController._pageRef)->pageID();
289             break;
290         }
291         case WKTypeRefWrapperType: {
292             WKTypeRefWrapper *wrapper = static_cast<WKTypeRefWrapper *>(m_root);
293             encoder << WebContextUserMessageEncoder(toImpl(wrapper.object));
294             break;
295         }
296 #endif
297         default:
298             ASSERT_NOT_REACHED();
299             break;
300         }
301     }
302 };
303
304
305 class WebContextObjCObjectGraphDecoderImpl : public ObjCObjectGraphDecoder<WebContextObjCObjectGraphDecoderImpl> {
306 public:
307     typedef ObjCObjectGraphDecoder<WebContextObjCObjectGraphDecoderImpl> Base;
308
309     WebContextObjCObjectGraphDecoderImpl(RetainPtr<id>& root, WebProcessProxy* process)
310         : Base(root)
311         , m_process(process)
312     {
313     }
314
315     WebContextObjCObjectGraphDecoderImpl(WebContextObjCObjectGraphDecoderImpl& userMessageDecoder, RetainPtr<id>& root)
316         : Base(root)
317         , m_process(userMessageDecoder.m_process)
318     {
319     }
320
321     static bool decode(CoreIPC::ArgumentDecoder& decoder, WebContextObjCObjectGraphDecoderImpl& coder)
322     {
323         WebKitNSType type = NullType;
324         if (!Base::baseDecode(decoder, coder, type))
325             return false;
326
327         if (coder.m_root)
328             return true;
329
330         if (type == NullType || type == UnknownType) {
331             coder.m_root = [NSNull null];
332             return true;
333         }
334
335         switch (type) {
336 #if WK_API_ENABLED
337         case WKBrowsingContextControllerType: {
338             uint64_t pageID;
339             if (!decoder.decode(pageID))
340                 return false;
341
342             WebPageProxy* webPage = coder.m_process->webPage(pageID);
343             if (!webPage)
344                 coder.m_root = [NSNull null];
345             else 
346                 coder.m_root = [WKBrowsingContextController _browsingContextControllerForPageRef:toAPI(webPage)];
347             break;
348         }
349         case WKTypeRefWrapperType: {
350             RefPtr<APIObject> object;
351             WebContextUserMessageDecoder objectDecoder(object, coder.m_process);
352             if (!decoder.decode(objectDecoder))
353                 return false;
354             coder.m_root = adoptNS([[WKTypeRefWrapper alloc] initWithObject:toAPI(object.get())]);
355             break;
356         }
357 #endif
358         default:
359             return false;
360         }
361
362         return true;
363     }
364
365 private:
366     WebProcessProxy* m_process;
367 };
368
369
370 // InjectedBundle Additions
371
372 class InjectedBundleObjCObjectGraphEncoderImpl : public ObjCObjectGraphEncoder<InjectedBundleObjCObjectGraphEncoderImpl> {
373 public:
374     typedef ObjCObjectGraphEncoder<InjectedBundleObjCObjectGraphEncoderImpl> Base;
375
376     explicit InjectedBundleObjCObjectGraphEncoderImpl(id root)
377         : Base(root)
378     {
379     }
380
381     void encode(CoreIPC::ArgumentEncoder& encoder) const
382     {
383         WebKitNSType type = NullType;
384         if (baseEncode(encoder, type))
385             return;
386
387         switch (type) {
388 #if WK_API_ENABLED
389         case WKBrowsingContextControllerType: {
390             WKWebProcessPlugInBrowserContextController *browserContextController = static_cast<WKWebProcessPlugInBrowserContextController *>(m_root);
391
392             encoder << toImpl(browserContextController._bundlePageRef)->pageID();
393             break;
394         }
395         case WKTypeRefWrapperType: {
396             WKTypeRefWrapper *wrapper = static_cast<WKTypeRefWrapper *>(m_root);
397             encoder << InjectedBundleUserMessageEncoder(toImpl(wrapper.object));
398         }
399 #endif
400         default:
401             ASSERT_NOT_REACHED();
402             break;
403         }
404     }
405 };
406
407 class InjectedBundleObjCObjectGraphDecoderImpl : public ObjCObjectGraphDecoder<InjectedBundleObjCObjectGraphDecoderImpl> {
408 public:
409     typedef ObjCObjectGraphDecoder<InjectedBundleObjCObjectGraphDecoderImpl> Base;
410
411     InjectedBundleObjCObjectGraphDecoderImpl(RetainPtr<id>& root, WebProcess* process)
412         : Base(root)
413         , m_process(process)
414     {
415     }
416
417     InjectedBundleObjCObjectGraphDecoderImpl(InjectedBundleObjCObjectGraphDecoderImpl& userMessageDecoder, RetainPtr<id>& root)
418         : Base(root)
419         , m_process(userMessageDecoder.m_process)
420     {
421     }
422
423     static bool decode(CoreIPC::ArgumentDecoder& decoder, InjectedBundleObjCObjectGraphDecoderImpl& coder)
424     {
425         WebKitNSType type = NullType;
426         if (!Base::baseDecode(decoder, coder, type))
427             return false;
428
429         if (coder.m_root)
430             return true;
431
432         if (type == NullType || type == UnknownType) {
433             coder.m_root = [NSNull null];
434             return true;
435         }
436
437         switch (type) {
438 #if WK_API_ENABLED
439         case WKBrowsingContextControllerType: {
440             uint64_t pageID;
441             if (!decoder.decode(pageID))
442                 return false;
443
444             WebPage* webPage = coder.m_process->webPage(pageID);
445             if (!webPage)
446                 coder.m_root = [NSNull null];
447             else 
448                 coder.m_root = [[WKWebProcessPlugInController _shared] _browserContextControllerForBundlePageRef:toAPI(webPage)];
449             break;
450         }
451         case WKTypeRefWrapperType: {
452             RefPtr<APIObject> object;
453             InjectedBundleUserMessageDecoder objectDecoder(object);
454             if (!decoder.decode(objectDecoder))
455                 return false;
456             coder.m_root = adoptNS([[WKTypeRefWrapper alloc] initWithObject:toAPI(object.get())]);
457             break;
458         }
459 #endif
460         default:
461             return false;
462         }
463
464         return true;
465     }
466
467 private:
468     WebProcess* m_process;
469 };
470
471
472 // Adaptors
473
474 WebContextObjCObjectGraphEncoder::WebContextObjCObjectGraphEncoder(ObjCObjectGraph* objectGraph)
475     : m_objectGraph(objectGraph)
476 {
477 }
478
479 void WebContextObjCObjectGraphEncoder::encode(CoreIPC::ArgumentEncoder& encoder) const
480 {
481     encoder << WebContextObjCObjectGraphEncoderImpl(m_objectGraph->rootObject());
482 }
483
484 WebContextObjCObjectGraphDecoder::WebContextObjCObjectGraphDecoder(RefPtr<ObjCObjectGraph>& objectGraph, WebProcessProxy* process)
485     : m_objectGraph(objectGraph)
486     , m_process(process)
487 {
488 }
489
490 bool WebContextObjCObjectGraphDecoder::decode(CoreIPC::ArgumentDecoder& decoder, WebContextObjCObjectGraphDecoder& coder)
491 {
492     RetainPtr<id> root;
493     WebContextObjCObjectGraphDecoderImpl coderImpl(root, coder.m_process);
494     if (!decoder.decode(coderImpl))
495         return false;
496
497     coder.m_objectGraph = ObjCObjectGraph::create(root.get());
498     return true;
499 }
500
501 InjectedBundleObjCObjectGraphEncoder::InjectedBundleObjCObjectGraphEncoder(ObjCObjectGraph* objectGraph)
502     : m_objectGraph(objectGraph)
503 {
504 }
505
506 void InjectedBundleObjCObjectGraphEncoder::encode(CoreIPC::ArgumentEncoder& encoder) const
507 {
508     encoder << InjectedBundleObjCObjectGraphEncoderImpl(m_objectGraph->rootObject());
509 }
510
511 InjectedBundleObjCObjectGraphDecoder::InjectedBundleObjCObjectGraphDecoder(RefPtr<ObjCObjectGraph>& objectGraph, WebProcess* process)
512     : m_objectGraph(objectGraph)
513     , m_process(process)
514 {
515 }
516
517 bool InjectedBundleObjCObjectGraphDecoder::decode(CoreIPC::ArgumentDecoder& decoder, InjectedBundleObjCObjectGraphDecoder& coder)
518 {
519     RetainPtr<id> root;
520     InjectedBundleObjCObjectGraphDecoderImpl coderImpl(root, coder.m_process);
521     if (!decoder.decode(coderImpl))
522         return false;
523
524     coder.m_objectGraph = ObjCObjectGraph::create(root.get());
525     return true;
526 }
527
528 } // namespace WebKit