• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
3 * Copyright (C) 2006 James G. Speth (speth@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
41static 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