Skip to content
Permalink
Browse files
Begin work on decoding invocations
https://bugs.webkit.org/show_bug.cgi?id=123838

Reviewed by Dan Bernstein.

* Shared/API/Cocoa/WKRemoteObjectCoder.mm:
(encodeInvocation):
Declare the type string and selector keys as constants.

(encodeObject):
Make sure to encode the class name for NSInvocations as well.

(decodeInvocation):
Figure out the local and remove method signatures and make sure that they are equal.

* Shared/API/Cocoa/WKRemoteObjectInterface.mm:
(methodArgumentTypeEncodingForSelector):
Helper function that returns the type encoding for a given selector.

(-[WKRemoteObjectInterface _methodSignatureForSelector:]):
Helper function that returns a method signature for the method with the name referred to by selector.

* Shared/API/Cocoa/WKRemoteObjectInterfaceInternal.h: Added.
Add internal header.

* Shared/API/Cocoa/WKRemoteObjectRegistry.mm:
(-[WKRemoteObjectRegistry _invokeMessageWithInterfaceIdentifier:encodedInvocation:]):
Pass the right object to the WKRemoteObjectDecoder initializer and decode the invocation.

* WebKit2.xcodeproj/project.pbxproj:
Add internal header.

Canonical link: https://commits.webkit.org/142027@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@158700 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
Anders Carlsson committed Nov 6, 2013
1 parent d286984 commit 05935d4510f96136efcf65d492d334bb3788c002
Showing 6 changed files with 140 additions and 14 deletions.
@@ -1,3 +1,37 @@
2013-11-05 Anders Carlsson <andersca@apple.com>

Begin work on decoding invocations
https://bugs.webkit.org/show_bug.cgi?id=123838

Reviewed by Dan Bernstein.

* Shared/API/Cocoa/WKRemoteObjectCoder.mm:
(encodeInvocation):
Declare the type string and selector keys as constants.

(encodeObject):
Make sure to encode the class name for NSInvocations as well.

(decodeInvocation):
Figure out the local and remove method signatures and make sure that they are equal.

* Shared/API/Cocoa/WKRemoteObjectInterface.mm:
(methodArgumentTypeEncodingForSelector):
Helper function that returns the type encoding for a given selector.

(-[WKRemoteObjectInterface _methodSignatureForSelector:]):
Helper function that returns a method signature for the method with the name referred to by selector.

* Shared/API/Cocoa/WKRemoteObjectInterfaceInternal.h: Added.
Add internal header.

* Shared/API/Cocoa/WKRemoteObjectRegistry.mm:
(-[WKRemoteObjectRegistry _invokeMessageWithInterfaceIdentifier:encodedInvocation:]):
Pass the right object to the WKRemoteObjectDecoder initializer and decode the invocation.

* WebKit2.xcodeproj/project.pbxproj:
Add internal header.

2013-11-05 Anders Carlsson <andersca@apple.com>

WKRemoteObjectDecoder should know which interface it's decoding for
@@ -28,6 +28,7 @@

#import "MutableArray.h"
#import "MutableDictionary.h"
#import "WKRemoteObjectInterfaceInternal.h"
#import "WebData.h"
#import "WebNumber.h"
#import "WebString.h"
@@ -38,8 +39,11 @@

#if WK_API_ENABLED

const char* const classNameKey = "$class";
const char* const objectStreamKey = "$objectStream";
static const char* const classNameKey = "$class";
static const char* const objectStreamKey = "$objectStream";

static NSString * const selectorKey = @"selector";
static NSString * const typeStringKey = @"typeString";

using namespace WebKit;

@@ -120,8 +124,8 @@ static void encodeToObjectStream(WKRemoteObjectEncoder *encoder, id value)
static void encodeInvocation(WKRemoteObjectEncoder *encoder, NSInvocation *invocation)
{
NSMethodSignature *methodSignature = invocation.methodSignature;
[encoder encodeObject:methodSignature._typeString forKey:@"typeString"];
[encoder encodeObject:NSStringFromSelector(invocation.selector) forKey:@"selector"];
[encoder encodeObject:methodSignature._typeString forKey:typeStringKey];
[encoder encodeObject:NSStringFromSelector(invocation.selector) forKey:selectorKey];

NSUInteger argumentCount = methodSignature.numberOfArguments;

@@ -169,14 +173,8 @@ static void encodeInvocation(WKRemoteObjectEncoder *encoder, NSInvocation *invoc
static void encodeObject(WKRemoteObjectEncoder *encoder, id object)
{
ASSERT(object);

if ([object isKindOfClass:[NSInvocation class]]) {
// We have to special case NSInvocation since we don't want to encode the target.
encodeInvocation(encoder, object);
return;
}

if (![object conformsToProtocol:@protocol(NSSecureCoding)])
if (![object conformsToProtocol:@protocol(NSSecureCoding)] && ![object isKindOfClass:[NSInvocation class]])
[NSException raise:NSInvalidArgumentException format:@"%@ does not conform to NSSecureCoding", object];

if (class_isMetaClass(object_getClass(object)))
@@ -187,6 +185,13 @@ static void encodeObject(WKRemoteObjectEncoder *encoder, id object)
[NSException raise:NSInvalidArgumentException format:@"-classForCoder returned nil for %@", object];

encoder->_currentDictionary->set(classNameKey, WebString::create(class_getName(objectClass)));

if ([object isKindOfClass:[NSInvocation class]]) {
// We have to special case NSInvocation since we don't want to encode the target.
encodeInvocation(encoder, object);
return;
}

[object encodeWithCoder:encoder];
}

@@ -336,7 +341,26 @@ static void validateClass(WKRemoteObjectDecoder *decoder, Class objectClass)

static NSInvocation *decodeInvocation(WKRemoteObjectDecoder *decoder)
{
// FIXME: Implement this.
NSString *selectorString = [decoder decodeObjectOfClass:[NSString class] forKey:selectorKey];
if (!selectorString)
[NSException raise:NSInvalidUnarchiveOperationException format:@"Invocation had no selector"];

SEL selector = NSSelectorFromString(selectorString);
ASSERT(selector);

NSMethodSignature *localMethodSignature = [decoder->_interface _methodSignatureForSelector:selector];
if (!localMethodSignature)
[NSException raise:NSInvalidUnarchiveOperationException format:@"Selector \"%@\" is not defined in the local interface", selectorString];

NSString *typeSignature = [decoder decodeObjectOfClass:[NSString class] forKey:typeStringKey];
if (!typeSignature)
[NSException raise:NSInvalidUnarchiveOperationException format:@"Invocation had no type signature"];

NSMethodSignature *remoteMethodSignature = [NSMethodSignature signatureWithObjCTypes:typeSignature.UTF8String];
if (![localMethodSignature isEqualTo:remoteMethodSignature])
[NSException raise:NSInvalidUnarchiveOperationException format:@"Local and remote method signatures are not equal for method \"%@\"", selectorString];

// FIXME: Handle arguments.
return nil;
}

@@ -26,6 +26,8 @@
#import "config.h"
#import "WKRemoteObjectInterface.h"

#import <objc/runtime.h>

#if WK_API_ENABLED

@implementation WKRemoteObjectInterface
@@ -46,6 +48,30 @@ + (instancetype)remoteObjectInterfaceWithProtocol:(Protocol *)protocol
return [[[self alloc] initWithProtocol:protocol identifier:NSStringFromProtocol(protocol)] autorelease];
}

static const char* methodArgumentTypeEncodingForSelector(Protocol *protocol, SEL selector)
{
// First look at required methods.
struct objc_method_description method = protocol_getMethodDescription(protocol, selector, YES, YES);
if (method.name)
return method.types;

// Then look at optional methods.
method = protocol_getMethodDescription(protocol, selector, NO, YES);
if (method.name)
return method.types;

return nullptr;
}

- (NSMethodSignature *)_methodSignatureForSelector:(SEL)selector
{
const char* types = methodArgumentTypeEncodingForSelector(_protocol, selector);
if (!types)
return nil;

return [NSMethodSignature signatureWithObjCTypes:types];
}

@end

#endif // WK_API_ENABLED
@@ -0,0 +1,36 @@
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/

#import "WKRemoteObjectInterface.h"

#if WK_API_ENABLED

@interface WKRemoteObjectInterface ()

- (NSMethodSignature *)_methodSignatureForSelector:(SEL)selector;

@end

#endif // WK_API_ENABLED
@@ -143,10 +143,12 @@ - (void)_invokeMessageWithInterfaceIdentifier:(const String&)interfaceIdentifier
return;
}

RetainPtr<WKRemoteObjectDecoder> decoder = adoptNS([[WKRemoteObjectDecoder alloc] initWithInterface:interfaceAndObject.first.get() rootObjectDictionary:encodedInvocation]);
RetainPtr<WKRemoteObjectDecoder> decoder = adoptNS([[WKRemoteObjectDecoder alloc] initWithInterface:interfaceAndObject.second.get() rootObjectDictionary:encodedInvocation]);

NSInvocation *invocation = nil;

@try {
// FIXME: Decode the invocation.
invocation = [decoder decodeObjectOfClass:[NSInvocation class] forKey:invocationKey];
} @catch (NSException *exception) {
NSLog(@"Exception caught during decoding of message: %@", exception);
}
@@ -230,6 +230,7 @@
1AA5889311EE70400061B882 /* NetscapePluginStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AA5889111EE70400061B882 /* NetscapePluginStream.cpp */; };
1AAB4A8D1296F0A20023952F /* SandboxExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AAB4A8C1296F0A20023952F /* SandboxExtension.h */; };
1AAB4AAA1296F1540023952F /* SandboxExtensionMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1AAB4AA91296F1540023952F /* SandboxExtensionMac.mm */; };
1AABFE3A1829C1ED005B070E /* WKRemoteObjectInterfaceInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AABFE391829C1ED005B070E /* WKRemoteObjectInterfaceInternal.h */; };
1AAF0C4A12B16334008E49E2 /* ArgumentCodersCF.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AAF0C4812B16334008E49E2 /* ArgumentCodersCF.h */; };
1AAF0C4B12B16334008E49E2 /* ArgumentCodersCF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AAF0C4912B16334008E49E2 /* ArgumentCodersCF.cpp */; };
1AAF263814687C39004A1E8A /* TiledCoreAnimationDrawingArea.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1AAF263614687C39004A1E8A /* TiledCoreAnimationDrawingArea.mm */; };
@@ -1702,6 +1703,7 @@
1AA5889111EE70400061B882 /* NetscapePluginStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetscapePluginStream.cpp; sourceTree = "<group>"; };
1AAB4A8C1296F0A20023952F /* SandboxExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SandboxExtension.h; sourceTree = "<group>"; };
1AAB4AA91296F1540023952F /* SandboxExtensionMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SandboxExtensionMac.mm; sourceTree = "<group>"; };
1AABFE391829C1ED005B070E /* WKRemoteObjectInterfaceInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKRemoteObjectInterfaceInternal.h; sourceTree = "<group>"; };
1AADE6FE10D855FC00D3D63D /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = System/Library/Frameworks/ApplicationServices.framework; sourceTree = SDKROOT; };
1AAF0C4812B16334008E49E2 /* ArgumentCodersCF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArgumentCodersCF.h; sourceTree = "<group>"; };
1AAF0C4912B16334008E49E2 /* ArgumentCodersCF.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; path = ArgumentCodersCF.cpp; sourceTree = "<group>"; };
@@ -3721,6 +3723,7 @@
1A9E329C1822FEDD00F5D04C /* WKRemoteObjectCoder.mm */,
1A9E328B182165A900F5D04C /* WKRemoteObjectInterface.h */,
1A9E328C182165A900F5D04C /* WKRemoteObjectInterface.mm */,
1AABFE391829C1ED005B070E /* WKRemoteObjectInterfaceInternal.h */,
1A9E32871821636900F5D04C /* WKRemoteObjectRegistry.h */,
1A9E32881821636900F5D04C /* WKRemoteObjectRegistry.mm */,
1A9E32A01823018900F5D04C /* WKRemoteObjectRegistryInternal.h */,
@@ -5907,6 +5910,7 @@
BC017D0B16260FF4007054F5 /* WKDOMInternals.h in Headers */,
BC017D0D16260FF4007054F5 /* WKDOMNode.h in Headers */,
BC5D24C216CD706D007D5461 /* WKDOMNodePrivate.h in Headers */,
1AABFE3A1829C1ED005B070E /* WKRemoteObjectInterfaceInternal.h in Headers */,
BC39C4361626366F008BC689 /* WKDOMRange.h in Headers */,
BC5D24C516CD7088007D5461 /* WKDOMRangePrivate.h in Headers */,
1A9E328D182165A900F5D04C /* WKRemoteObjectInterface.h in Headers */,

0 comments on commit 05935d4

Please sign in to comment.