Reviewed by ggaren.
[WebKit-https.git] / WebKitTools / DumpRenderTree / ObjCPlugin.m
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 "ObjCPlugin.h"
28 #import <objc/objc-runtime.h>
29 #import <WebKit/WebKit.h>
30
31
32 // === NSObject category to expose almost everything to JavaScript ===
33
34 // Warning: this class introduces huge security weaknesses, and should only be used
35 // for testing inside of DumpRenderTree, and only with trusted code.  By default, it has
36 // the same restrictive behavior as the standard WebKit setup.  However, scripts can use the
37 // plugin's removeBridgeRestrictions: method to open up almost total access to the Cocoa
38 // frameworks.
39
40 static BOOL _allowsScriptsFullAccess = NO;
41
42 @interface NSObject (ObjCScriptAccess)
43
44 + (void)setAllowsScriptsFullAccess:(BOOL)value;
45 + (BOOL)allowsScriptsFullAccess;
46
47 @end
48
49 @implementation NSObject (ObjCScriptAccess)
50
51 + (void)setAllowsScriptsFullAccess:(BOOL)value
52 {
53     _allowsScriptsFullAccess = value;
54 }
55
56 + (BOOL)allowsScriptsFullAccess
57 {
58     return _allowsScriptsFullAccess;
59 }
60
61 + (BOOL)isSelectorExcludedFromWebScript:(SEL)selector
62 {
63     return !_allowsScriptsFullAccess;
64 }
65
66 + (NSString *)webScriptNameForSelector:(SEL)selector
67 {
68     return nil;
69 }
70
71 @end
72
73 @interface JSObjC : NSObject {
74 }
75
76 // expose some useful objc functions to the scripting environment
77 - (id)lookUpClass:(NSString *)name;
78 - (void)log:(NSString *)message;
79 - (id)retainObject:(id)obj;
80 - (id)classOfObject:(id)obj;
81 - (NSString *)classNameOfObject:(id)obj;
82
83 @end
84
85 @implementation JSObjC
86
87 + (BOOL)isSelectorExcludedFromWebScript:(SEL)selector
88 {
89     return NO;
90 }
91
92 + (NSString *)webScriptNameForSelector:(SEL)selector
93 {
94     return nil;
95 }
96
97 - (id)invokeDefaultMethodWithArguments:(NSArray *)args
98 {
99     // this is a useful shortcut for accessing objective-c classes from the scripting
100     // environment, e.g. 'var myObject = objc("NSObject").alloc().init();'
101     if ([args count] == 1)
102         return [self lookUpClass:[args objectAtIndex:0]];
103     return nil;
104 }
105
106 - (id)lookUpClass:(NSString *)name
107 {
108     return NSClassFromString(name);
109 }
110
111 - (void)log:(NSString *)message
112 {
113     NSLog(message);
114 }
115
116 - (id)retainObject:(id)obj
117 {
118     return [obj retain];
119 }
120
121 - (id)classOfObject:(id)obj
122 {
123     return (id)[obj class];
124 }
125
126 - (NSString *)classNameOfObject:(id)obj
127 {
128     return [obj className];
129 }
130
131 @end
132
133 @implementation ObjCPlugin
134
135 + (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector
136 {
137     if (aSelector == @selector(removeBridgeRestrictions:))
138         return NO;
139
140     if (aSelector == @selector(echo:))
141         return NO;
142
143     if (aSelector == @selector(throwIfArgumentIsNotHello:))
144       return NO;
145
146     return YES;
147 }
148
149 + (NSString *)webScriptNameForSelector:(SEL)aSelector
150 {
151     if (aSelector == @selector(echo:))
152         return @"echo";
153
154     if (aSelector == @selector(throwIfArgumentIsNotHello:))
155       return @"throwIfArgumentIsNotHello";
156
157     return nil;
158 }
159
160 - (void)removeBridgeRestrictions:(id)container
161 {
162     // let scripts invoke any selector
163     [NSObject setAllowsScriptsFullAccess:YES];
164     
165     // store a JSObjC instance into the provided container
166     JSObjC *objc = [[JSObjC alloc] init];
167     [container setValue:objc forKey:@"objc"];
168     [objc release];
169 }
170
171 - (id)echo:(id)obj
172 {
173     return obj;
174 }
175
176 - (void)throwIfArgumentIsNotHello:(NSString *)str 
177 {
178     if (![str isEqualToString:@"Hello"]) 
179         [WebScriptObject throwException:[NSString stringWithFormat:@"%@ != Hello", str]];
180 }
181
182 @end