| /* |
| * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. |
| * Copyright (C) 2006 James G. Speth (speth@end.com) |
| * |
| * 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 THE AUTHOR ``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 THE AUTHOR OR |
| * 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 "ObjCPlugin.h" |
| #import <objc/objc-runtime.h> |
| #import <WebKit/WebKit.h> |
| |
| |
| // === NSObject category to expose almost everything to JavaScript === |
| |
| // Warning: this class introduces huge security weaknesses, and should only be used |
| // for testing inside of DumpRenderTree, and only with trusted code. By default, it has |
| // the same restrictive behavior as the standard WebKit setup. However, scripts can use the |
| // plugin's removeBridgeRestrictions: method to open up almost total access to the Cocoa |
| // frameworks. |
| |
| static BOOL _allowsScriptsFullAccess = NO; |
| |
| @interface NSObject (ObjCScriptAccess) |
| |
| + (void)setAllowsScriptsFullAccess:(BOOL)value; |
| + (BOOL)allowsScriptsFullAccess; |
| |
| @end |
| |
| @implementation NSObject (ObjCScriptAccess) |
| |
| + (void)setAllowsScriptsFullAccess:(BOOL)value |
| { |
| _allowsScriptsFullAccess = value; |
| } |
| |
| + (BOOL)allowsScriptsFullAccess |
| { |
| return _allowsScriptsFullAccess; |
| } |
| |
| + (BOOL)isSelectorExcludedFromWebScript:(SEL)selector |
| { |
| return !_allowsScriptsFullAccess; |
| } |
| |
| + (NSString *)webScriptNameForSelector:(SEL)selector |
| { |
| return nil; |
| } |
| |
| @end |
| |
| @interface JSObjC : NSObject { |
| } |
| |
| // expose some useful objc functions to the scripting environment |
| - (id)lookUpClass:(NSString *)name; |
| - (void)log:(NSString *)message; |
| - (id)retainObject:(id)obj; |
| - (id)classOfObject:(id)obj; |
| - (NSString *)classNameOfObject:(id)obj; |
| |
| @end |
| |
| @implementation JSObjC |
| |
| + (BOOL)isSelectorExcludedFromWebScript:(SEL)selector |
| { |
| return NO; |
| } |
| |
| + (NSString *)webScriptNameForSelector:(SEL)selector |
| { |
| return nil; |
| } |
| |
| - (id)invokeDefaultMethodWithArguments:(NSArray *)args |
| { |
| // this is a useful shortcut for accessing objective-c classes from the scripting |
| // environment, e.g. 'var myObject = objc("NSObject").alloc().init();' |
| if ([args count] == 1) |
| return [self lookUpClass:[args objectAtIndex:0]]; |
| return nil; |
| } |
| |
| - (id)lookUpClass:(NSString *)name |
| { |
| return NSClassFromString(name); |
| } |
| |
| - (void)log:(NSString *)message |
| { |
| NSLog(message); |
| } |
| |
| - (id)retainObject:(id)obj |
| { |
| return [obj retain]; |
| } |
| |
| - (id)classOfObject:(id)obj |
| { |
| return (id)[obj class]; |
| } |
| |
| - (NSString *)classNameOfObject:(id)obj |
| { |
| return [obj className]; |
| } |
| |
| @end |
| |
| @implementation ObjCPlugin |
| |
| + (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector |
| { |
| if (aSelector == @selector(removeBridgeRestrictions:)) |
| return NO; |
| |
| if (aSelector == @selector(echo:)) |
| return NO; |
| |
| if (aSelector == @selector(throwIfArgumentIsNotHello:)) |
| return NO; |
| |
| return YES; |
| } |
| |
| + (NSString *)webScriptNameForSelector:(SEL)aSelector |
| { |
| if (aSelector == @selector(echo:)) |
| return @"echo"; |
| |
| if (aSelector == @selector(throwIfArgumentIsNotHello:)) |
| return @"throwIfArgumentIsNotHello"; |
| |
| return nil; |
| } |
| |
| + (NSString *)webScriptNameForKey:(const char *)key |
| { |
| if (strcmp(key, "throwOnDealloc") == 0) |
| return @"throwOnDealloc"; |
| |
| return nil; |
| } |
| |
| + (BOOL)isKeyExcludedFromWebScript:(const char *)key |
| { |
| if (strcmp(key, "throwOnDealloc") == 0) |
| return NO; |
| |
| return YES; |
| } |
| |
| - (void)removeBridgeRestrictions:(id)container |
| { |
| // let scripts invoke any selector |
| [NSObject setAllowsScriptsFullAccess:YES]; |
| |
| // store a JSObjC instance into the provided container |
| JSObjC *objc = [[JSObjC alloc] init]; |
| [container setValue:objc forKey:@"objc"]; |
| [objc release]; |
| } |
| |
| - (id)echo:(id)obj |
| { |
| return obj; |
| } |
| |
| - (void)throwIfArgumentIsNotHello:(NSString *)str |
| { |
| if (![str isEqualToString:@"Hello"]) |
| [WebScriptObject throwException:[NSString stringWithFormat:@"%@ != Hello", str]]; |
| } |
| |
| - (void)dealloc |
| { |
| if (throwOnDealloc) |
| [WebScriptObject throwException:@"Throwing exception on dealloc of ObjCPlugin"]; |
| |
| [super dealloc]; |
| } |
| |
| @end |