[WK2] Rename WebString to API::String
[WebKit-https.git] / Source / WebKit2 / Shared / API / Cocoa / WKRemoteObjectRegistry.mm
1 /*
2  * Copyright (C) 2013 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 "WKRemoteObjectRegistryInternal.h"
28
29 #if WK_API_ENABLED
30
31 #import "Connection.h"
32 #import "ImmutableDictionary.h"
33 #import "MutableDictionary.h"
34 #import "WKConnectionRef.h"
35 #import "WKRemoteObject.h"
36 #import "WKRemoteObjectCoder.h"
37 #import "WKRemoteObjectInterface.h"
38 #import "WKSharedAPICast.h"
39 #import "WebConnection.h"
40
41 const char* const messageName = "WKRemoteObjectRegistryMessage";
42
43 const char* const encodedInvocationKey = "encodedInvocation";
44 const char* const interfaceIdentifierKey = "interfaceIdentifier";
45
46 NSString * const invocationKey = @"invocation";
47
48 using namespace WebKit;
49
50 @implementation WKRemoteObjectRegistry {
51     RefPtr<WebConnection> _connection;
52     RetainPtr<NSMapTable> _remoteObjectProxies;
53     HashMap<String, std::pair<RetainPtr<id>, RetainPtr<WKRemoteObjectInterface>>> _exportedObjects;
54 }
55
56 - (void)registerExportedObject:(id)object interface:(WKRemoteObjectInterface *)interface
57 {
58     ASSERT(!_exportedObjects.contains(interface.identifier));
59     _exportedObjects.add(interface.identifier, std::make_pair<RetainPtr<id>, RetainPtr<WKRemoteObjectInterface>>(object, interface));
60 }
61
62 - (void)unregisterExportedObject:(id)object interface:(WKRemoteObjectInterface *)interface
63 {
64     ASSERT(_exportedObjects.get(interface.identifier).first == object);
65     ASSERT(_exportedObjects.get(interface.identifier).second == interface);
66
67     _exportedObjects.remove(interface.identifier);
68 }
69
70 - (id)remoteObjectProxyWithInterface:(WKRemoteObjectInterface *)interface
71 {
72     if (!_remoteObjectProxies)
73         _remoteObjectProxies = [NSMapTable strongToWeakObjectsMapTable];
74
75     if (id remoteObjectProxy = [_remoteObjectProxies objectForKey:interface.identifier])
76         return remoteObjectProxy;
77
78     RetainPtr<NSString> identifier = adoptNS([interface.identifier copy]);
79     RetainPtr<WKRemoteObject> remoteObject = adoptNS([[WKRemoteObject alloc] _initWithObjectRegistry:self interface:interface]);
80     [_remoteObjectProxies setObject:remoteObject.get() forKey:identifier.get()];
81
82     return [remoteObject.leakRef() autorelease];
83 }
84
85 - (void)_sendInvocation:(NSInvocation *)invocation interface:(WKRemoteObjectInterface *)interface
86 {
87     RetainPtr<WKRemoteObjectEncoder> encoder = adoptNS([[WKRemoteObjectEncoder alloc] init]);
88     [encoder encodeObject:invocation forKey:invocationKey];
89
90     RefPtr<MutableDictionary> body = MutableDictionary::create();
91     body->set(interfaceIdentifierKey, API::String::create(interface.identifier));
92     body->set(encodedInvocationKey, [encoder rootObjectDictionary]);
93
94     [self _sendMessageWithBody:body.release()];
95 }
96
97 - (void)_sendMessageWithBody:(PassRefPtr<ImmutableDictionary>)body
98 {
99     _connection->postMessage(messageName, body.get());
100 }
101
102 @end
103
104 @implementation WKRemoteObjectRegistry (WKPrivate)
105
106 - (id)_initWithConnectionRef:(WKConnectionRef)connectionRef
107 {
108     if (!(self = [super init]))
109         return nil;
110
111     _connection = toImpl(connectionRef);
112
113     return self;
114 }
115
116 - (BOOL)_handleMessageWithName:(WKStringRef)name body:(WKTypeRef)body
117 {
118     if (toImpl(name)->string() != messageName)
119         return NO;
120
121     if (!toImpl(body) || toImpl(body)->type() != API::Object::Type::Dictionary)
122         return NO;
123
124     const ImmutableDictionary* dictionary = toImpl(static_cast<WKDictionaryRef>(body));
125
126     API::String* interfaceIdentifier = dictionary->get<API::String>(interfaceIdentifierKey);
127     if (!interfaceIdentifier)
128         return NO;
129
130     const ImmutableDictionary* encodedInvocation = dictionary->get<ImmutableDictionary>(encodedInvocationKey);
131     if (!encodedInvocationKey)
132         return NO;
133
134     [self _invokeMessageWithInterfaceIdentifier:interfaceIdentifier->string() encodedInvocation:encodedInvocation];
135     return YES;
136 }
137
138 - (void)_invokeMessageWithInterfaceIdentifier:(const String&)interfaceIdentifier encodedInvocation:(const ImmutableDictionary*)encodedInvocation
139 {
140     auto interfaceAndObject = _exportedObjects.get(interfaceIdentifier);
141     if (!interfaceAndObject.second) {
142         NSLog(@"Did not find a registered object for the interface \"%@\"", (NSString *)interfaceIdentifier);
143         return;
144     }
145
146     RetainPtr<WKRemoteObjectDecoder> decoder = adoptNS([[WKRemoteObjectDecoder alloc] initWithInterface:interfaceAndObject.second.get() rootObjectDictionary:encodedInvocation]);
147
148     NSInvocation *invocation = nil;
149
150     @try {
151         invocation = [decoder decodeObjectOfClass:[NSInvocation class] forKey:invocationKey];
152     } @catch (NSException *exception) {
153         NSLog(@"Exception caught during decoding of message: %@", exception);
154     }
155
156     // FIXME: Invoke the invocation.
157 }
158
159 @end
160
161 #endif // WK_API_ENABLED