Home | History | Annotate | Download | only in mac
      1 /*
      2  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
      3  * Copyright (C) 2006 James G. Speth (speth (at) end.com)
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
     15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR
     18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25 */
     26 
     27 #import "config.h"
     28 #import "ObjCPlugin.h"
     29 
     30 #import <WebKit/WebKit.h>
     31 #import <objc/objc-runtime.h>
     32 
     33 // === NSObject category to expose almost everything to JavaScript ===
     34 
     35 // Warning: this class introduces huge security weaknesses, and should only be used
     36 // for testing inside of DumpRenderTree, and only with trusted code.  By default, it has
     37 // the same restrictive behavior as the standard WebKit setup.  However, scripts can use the
     38 // plugin's removeBridgeRestrictions: method to open up almost total access to the Cocoa
     39 // frameworks.
     40 
     41 static BOOL _allowsScriptsFullAccess = NO;
     42 
     43 @interface NSObject (ObjCScriptAccess)
     44 
     45 + (void)setAllowsScriptsFullAccess:(BOOL)value;
     46 + (BOOL)allowsScriptsFullAccess;
     47 
     48 @end
     49 
     50 @implementation NSObject (ObjCScriptAccess)
     51 
     52 + (void)setAllowsScriptsFullAccess:(BOOL)value
     53 {
     54     _allowsScriptsFullAccess = value;
     55 }
     56 
     57 + (BOOL)allowsScriptsFullAccess
     58 {
     59     return _allowsScriptsFullAccess;
     60 }
     61 
     62 + (BOOL)isSelectorExcludedFromWebScript:(SEL)selector
     63 {
     64     return !_allowsScriptsFullAccess;
     65 }
     66 
     67 + (NSString *)webScriptNameForSelector:(SEL)selector
     68 {
     69     return nil;
     70 }
     71 
     72 @end
     73 
     74 @interface JSObjC : NSObject {
     75 }
     76 
     77 // expose some useful objc functions to the scripting environment
     78 - (id)lookUpClass:(NSString *)name;
     79 - (void)log:(NSString *)message;
     80 - (id)retainObject:(id)obj;
     81 - (id)classOfObject:(id)obj;
     82 - (NSString *)classNameOfObject:(id)obj;
     83 
     84 @end
     85 
     86 @implementation JSObjC
     87 
     88 + (BOOL)isSelectorExcludedFromWebScript:(SEL)selector
     89 {
     90     return NO;
     91 }
     92 
     93 + (NSString *)webScriptNameForSelector:(SEL)selector
     94 {
     95     return nil;
     96 }
     97 
     98 - (id)invokeDefaultMethodWithArguments:(NSArray *)args
     99 {
    100     // this is a useful shortcut for accessing objective-c classes from the scripting
    101     // environment, e.g. 'var myObject = objc("NSObject").alloc().init();'
    102     if ([args count] == 1)
    103         return [self lookUpClass:[args objectAtIndex:0]];
    104     return nil;
    105 }
    106 
    107 - (id)lookUpClass:(NSString *)name
    108 {
    109     return NSClassFromString(name);
    110 }
    111 
    112 - (void)log:(NSString *)message
    113 {
    114     NSLog(@"%@", message);
    115 }
    116 
    117 - (id)retainObject:(id)obj
    118 {
    119     return [obj retain];
    120 }
    121 
    122 - (id)classOfObject:(id)obj
    123 {
    124     return (id)[obj class];
    125 }
    126 
    127 - (NSString *)classNameOfObject:(id)obj
    128 {
    129     return [obj className];
    130 }
    131 
    132 @end
    133 
    134 @implementation ObjCPlugin
    135 
    136 + (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector
    137 {
    138     if (aSelector == @selector(removeBridgeRestrictions:))
    139         return NO;
    140 
    141     if (aSelector == @selector(echo:))
    142         return NO;
    143 
    144     if (aSelector == @selector(throwIfArgumentIsNotHello:))
    145       return NO;
    146 
    147     return YES;
    148 }
    149 
    150 + (NSString *)webScriptNameForSelector:(SEL)aSelector
    151 {
    152     if (aSelector == @selector(echo:))
    153         return @"echo";
    154 
    155     if (aSelector == @selector(throwIfArgumentIsNotHello:))
    156       return @"throwIfArgumentIsNotHello";
    157 
    158     return nil;
    159 }
    160 
    161 + (NSString *)webScriptNameForKey:(const char *)key
    162 {
    163     if (strcmp(key, "throwOnDealloc") == 0)
    164       return @"throwOnDealloc";
    165 
    166     return nil;
    167 }
    168 
    169 + (BOOL)isKeyExcludedFromWebScript:(const char *)key
    170 {
    171     if (strcmp(key, "throwOnDealloc") == 0)
    172       return NO;
    173 
    174     return YES;
    175 }
    176 
    177 - (void)removeBridgeRestrictions:(id)container
    178 {
    179     // let scripts invoke any selector
    180     [NSObject setAllowsScriptsFullAccess:YES];
    181 
    182     // store a JSObjC instance into the provided container
    183     JSObjC *objc = [[JSObjC alloc] init];
    184     [container setValue:objc forKey:@"objc"];
    185     [objc release];
    186 }
    187 
    188 - (id)echo:(id)obj
    189 {
    190     return obj;
    191 }
    192 
    193 - (void)throwIfArgumentIsNotHello:(NSString *)str
    194 {
    195     if (![str isEqualToString:@"Hello"])
    196         [WebScriptObject throwException:[NSString stringWithFormat:@"%@ != Hello", str]];
    197 }
    198 
    199 - (void)dealloc
    200 {
    201     if (throwOnDealloc)
    202         [WebScriptObject throwException:@"Throwing exception on dealloc of ObjCPlugin"];
    203 
    204     [super dealloc];
    205 }
    206 
    207 @end
    208