|
1 /* |
|
2 * Copyright (C) 2007 Apple Inc. All rights reserved. |
|
3 * |
|
4 * Redistribution and use in source and binary forms, with or without |
|
5 * modification, are permitted provided that the following conditions |
|
6 * are met: |
|
7 * |
|
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 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of |
|
14 * its contributors may be used to endorse or promote products derived |
|
15 * from this software without specific prior written permission. |
|
16 * |
|
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
|
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
|
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
|
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
27 */ |
|
28 |
|
29 #import "DumpRenderTree.h" |
|
30 #import "FrameLoadDelegate.h" |
|
31 |
|
32 #import "AppleScriptController.h" |
|
33 #import "EventSendingController.h" |
|
34 #import "GCController.h" |
|
35 #import "LayoutTestController.h" |
|
36 #import "NavigationController.h" |
|
37 #import "ObjCController.h" |
|
38 #import "ObjCPlugin.h" |
|
39 #import "ObjCPluginFunction.h" |
|
40 #import "TextInputController.h" |
|
41 #import "WorkQueue.h" |
|
42 #import "WorkQueueItem.h" |
|
43 #import <JavaScriptCore/Assertions.h> |
|
44 #import <JavaScriptCore/JavaScriptCore.h> |
|
45 #import <WebKit/WebFramePrivate.h> |
|
46 #import <WebKit/WebHTMLViewPrivate.h> |
|
47 #import <WebKit/WebKit.h> |
|
48 #import <WebKit/WebNSURLExtras.h> |
|
49 |
|
50 @interface NSURLRequest (PrivateThingsWeShouldntReallyUse) |
|
51 +(void)setAllowsAnyHTTPSCertificate:(BOOL)allow forHost:(NSString *)host; |
|
52 @end |
|
53 |
|
54 @interface NSURL (DRTExtras) |
|
55 - (NSString *)_drt_descriptionSuitableForTestResult; |
|
56 @end |
|
57 |
|
58 @interface NSError (DRTExtras) |
|
59 - (NSString *)_drt_descriptionSuitableForTestResult; |
|
60 @end |
|
61 |
|
62 @interface NSURLResponse (DRTExtras) |
|
63 - (NSString *)_drt_descriptionSuitableForTestResult; |
|
64 @end |
|
65 |
|
66 @interface NSURLRequest (DRTExtras) |
|
67 - (NSString *)_drt_descriptionSuitableForTestResult; |
|
68 @end |
|
69 |
|
70 @interface WebFrame (DRTExtras) |
|
71 - (NSString *)_drt_descriptionSuitableForTestResult; |
|
72 @end |
|
73 |
|
74 @implementation WebFrame (DRTExtras) |
|
75 - (NSString *)_drt_descriptionSuitableForTestResult |
|
76 { |
|
77 BOOL isMainFrame = (self == [[self webView] mainFrame]); |
|
78 NSString *name = [self name]; |
|
79 if (isMainFrame) { |
|
80 if ([name length]) |
|
81 return [NSString stringWithFormat:@"main frame \"%@\"", name]; |
|
82 else |
|
83 return @"main frame"; |
|
84 } else { |
|
85 if (name) |
|
86 return [NSString stringWithFormat:@"frame \"%@\"", name]; |
|
87 else |
|
88 return @"frame (anonymous)"; |
|
89 } |
|
90 } |
|
91 @end |
|
92 |
|
93 @implementation FrameLoadDelegate |
|
94 |
|
95 - (id)init |
|
96 { |
|
97 if ((self = [super init])) |
|
98 gcController = new GCController; |
|
99 return self; |
|
100 } |
|
101 |
|
102 - (void)dealloc |
|
103 { |
|
104 delete gcController; |
|
105 [super dealloc]; |
|
106 } |
|
107 |
|
108 // Exec messages in the work queue until they're all done, or one of them starts a new load |
|
109 - (void)processWork:(id)dummy |
|
110 { |
|
111 // quit doing work once a load is in progress |
|
112 while (WorkQueue::shared()->count() > 0 && !topLoadingFrame) { |
|
113 WorkQueueItem* item = WorkQueue::shared()->dequeue(); |
|
114 ASSERT(item); |
|
115 item->invoke(); |
|
116 delete item; |
|
117 } |
|
118 |
|
119 // if we didn't start a new load, then we finished all the commands, so we're ready to dump state |
|
120 if (!topLoadingFrame && !layoutTestController->waitToDump()) |
|
121 dump(); |
|
122 } |
|
123 |
|
124 - (void)webView:(WebView *)c locationChangeDone:(NSError *)error forDataSource:(WebDataSource *)dataSource |
|
125 { |
|
126 if ([dataSource webFrame] == topLoadingFrame) { |
|
127 topLoadingFrame = nil; |
|
128 WorkQueue::shared()->setFrozen(true); // first complete load freezes the queue for the rest of this test |
|
129 if (!layoutTestController->waitToDump()) { |
|
130 if (WorkQueue::shared()->count()) |
|
131 [self performSelector:@selector(processWork:) withObject:nil afterDelay:0]; |
|
132 else |
|
133 dump(); |
|
134 } |
|
135 } |
|
136 } |
|
137 |
|
138 - (void)webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame |
|
139 { |
|
140 if (layoutTestController->dumpFrameLoadCallbacks() && !done) { |
|
141 NSString *string = [NSString stringWithFormat:@"%@ - didStartProvisionalLoadForFrame", [frame _drt_descriptionSuitableForTestResult]]; |
|
142 printf ("%s\n", [string UTF8String]); |
|
143 } |
|
144 |
|
145 ASSERT([frame provisionalDataSource]); |
|
146 // Make sure we only set this once per test. If it gets cleared, and then set again, we might |
|
147 // end up doing two dumps for one test. |
|
148 if (!topLoadingFrame && !done) |
|
149 topLoadingFrame = frame; |
|
150 } |
|
151 |
|
152 - (void)webView:(WebView *)sender didCommitLoadForFrame:(WebFrame *)frame |
|
153 { |
|
154 if (layoutTestController->dumpFrameLoadCallbacks() && !done) { |
|
155 NSString *string = [NSString stringWithFormat:@"%@ - didCommitLoadForFrame", [frame _drt_descriptionSuitableForTestResult]]; |
|
156 printf ("%s\n", [string UTF8String]); |
|
157 } |
|
158 |
|
159 ASSERT(![frame provisionalDataSource]); |
|
160 ASSERT([frame dataSource]); |
|
161 |
|
162 layoutTestController->setWindowIsKey(true); |
|
163 NSView *documentView = [[mainFrame frameView] documentView]; |
|
164 [[[mainFrame webView] window] makeFirstResponder:documentView]; |
|
165 if ([documentView isKindOfClass:[WebHTMLView class]]) |
|
166 [(WebHTMLView *)documentView _updateActiveState]; |
|
167 } |
|
168 |
|
169 - (void)webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame |
|
170 { |
|
171 if (layoutTestController->dumpFrameLoadCallbacks() && !done) { |
|
172 NSString *string = [NSString stringWithFormat:@"%@ - didFailProvisionalLoadWithError", [frame _drt_descriptionSuitableForTestResult]]; |
|
173 printf ("%s\n", [string UTF8String]); |
|
174 } |
|
175 |
|
176 if ([error domain] == NSURLErrorDomain && [error code] == NSURLErrorServerCertificateHasUnknownRoot) { |
|
177 NSURL *failedURL = [[error userInfo] objectForKey:@"NSErrorFailingURLKey"]; |
|
178 [NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[failedURL _web_hostString]]; |
|
179 [frame loadRequest:[[[[frame provisionalDataSource] request] mutableCopy] autorelease]]; |
|
180 return; |
|
181 } |
|
182 |
|
183 ASSERT([frame provisionalDataSource]); |
|
184 [self webView:sender locationChangeDone:error forDataSource:[frame provisionalDataSource]]; |
|
185 } |
|
186 |
|
187 - (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame |
|
188 { |
|
189 ASSERT([frame dataSource]); |
|
190 ASSERT(frame == [[frame dataSource] webFrame]); |
|
191 |
|
192 if (layoutTestController->dumpFrameLoadCallbacks() && !done) { |
|
193 NSString *string = [NSString stringWithFormat:@"%@ - didFinishLoadForFrame", [frame _drt_descriptionSuitableForTestResult]]; |
|
194 printf ("%s\n", [string UTF8String]); |
|
195 } |
|
196 |
|
197 // FIXME: This call to displayIfNeeded can be removed when <rdar://problem/5092361> is fixed. |
|
198 // After that is fixed, we will reenable painting after WebCore is done loading the document, |
|
199 // and this call will no longer be needed. |
|
200 if ([[sender mainFrame] isEqual:frame]) |
|
201 [sender displayIfNeeded]; |
|
202 [self webView:sender locationChangeDone:nil forDataSource:[frame dataSource]]; |
|
203 [navigationController webView:sender didFinishLoadForFrame:frame]; |
|
204 } |
|
205 |
|
206 - (void)webView:(WebView *)sender didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame; |
|
207 { |
|
208 if (layoutTestController->dumpFrameLoadCallbacks() && !done) { |
|
209 NSString *string = [NSString stringWithFormat:@"%@ - didFailLoadWithError", [frame _drt_descriptionSuitableForTestResult]]; |
|
210 printf ("%s\n", [string UTF8String]); |
|
211 } |
|
212 |
|
213 ASSERT(![frame provisionalDataSource]); |
|
214 ASSERT([frame dataSource]); |
|
215 |
|
216 [self webView:sender locationChangeDone:error forDataSource:[frame dataSource]]; |
|
217 } |
|
218 |
|
219 - (void)webView:(WebView *)webView windowScriptObjectAvailable:(WebScriptObject *)windowScriptObject; |
|
220 { |
|
221 if (layoutTestController->dumpFrameLoadCallbacks() && !done) { |
|
222 NSString *string = [NSString stringWithFormat:@"?? - windowScriptObjectAvailable"]; |
|
223 printf ("%s\n", [string UTF8String]); |
|
224 } |
|
225 |
|
226 ASSERT_NOT_REACHED(); |
|
227 } |
|
228 |
|
229 - (void)webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)obj forFrame:(WebFrame *)frame |
|
230 { |
|
231 if (layoutTestController->dumpFrameLoadCallbacks() && !done) { |
|
232 NSString *string = [NSString stringWithFormat:@"%@ - didClearWindowObjectForFrame", [frame _drt_descriptionSuitableForTestResult]]; |
|
233 printf ("%s\n", [string UTF8String]); |
|
234 } |
|
235 |
|
236 ASSERT(obj == [frame windowObject]); |
|
237 ASSERT([obj JSObject] == JSContextGetGlobalObject([frame globalContext])); |
|
238 |
|
239 // Make New-Style LayoutTestController |
|
240 JSContextRef context = [frame globalContext]; |
|
241 JSObjectRef globalObject = JSContextGetGlobalObject(context); |
|
242 JSValueRef exception = 0; |
|
243 |
|
244 ASSERT(layoutTestController); |
|
245 layoutTestController->makeWindowObject(context, globalObject, &exception); |
|
246 ASSERT(!exception); |
|
247 |
|
248 gcController->makeWindowObject(context, globalObject, &exception); |
|
249 ASSERT(!exception); |
|
250 |
|
251 // Make Old-Style controllers |
|
252 EventSendingController *esc = [[EventSendingController alloc] init]; |
|
253 [obj setValue:esc forKey:@"eventSender"]; |
|
254 [esc release]; |
|
255 |
|
256 TextInputController *tic = [[TextInputController alloc] initWithWebView:sender]; |
|
257 [obj setValue:tic forKey:@"textInputController"]; |
|
258 [tic release]; |
|
259 |
|
260 AppleScriptController *asc = [[AppleScriptController alloc] initWithWebView:sender]; |
|
261 [obj setValue:asc forKey:@"appleScriptController"]; |
|
262 [asc release]; |
|
263 |
|
264 ObjCController *occ = [[ObjCController alloc] init]; |
|
265 [obj setValue:occ forKey:@"objCController"]; |
|
266 [occ release]; |
|
267 |
|
268 [obj setValue:navigationController forKey:@"navigationController"]; |
|
269 |
|
270 ObjCPlugin *plugin = [[ObjCPlugin alloc] init]; |
|
271 [obj setValue:plugin forKey:@"objCPlugin"]; |
|
272 [plugin release]; |
|
273 |
|
274 ObjCPluginFunction *pluginFunction = [[ObjCPluginFunction alloc] init]; |
|
275 [obj setValue:pluginFunction forKey:@"objCPluginFunction"]; |
|
276 [pluginFunction release]; |
|
277 } |
|
278 |
|
279 - (void)webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame |
|
280 { |
|
281 if (layoutTestController->dumpFrameLoadCallbacks() && !done) { |
|
282 NSString *string = [NSString stringWithFormat:@"%@ - didReceiveTitle: %@", [frame _drt_descriptionSuitableForTestResult], title]; |
|
283 printf ("%s\n", [string UTF8String]); |
|
284 } |
|
285 |
|
286 if (layoutTestController->dumpTitleChanges()) |
|
287 printf("TITLE CHANGED: %s\n", [title UTF8String]); |
|
288 } |
|
289 |
|
290 - (void)webView:(WebView *)sender didReceiveServerRedirectForProvisionalLoadForFrame:(WebFrame *)frame |
|
291 { |
|
292 if (layoutTestController->dumpFrameLoadCallbacks() && !done) { |
|
293 NSString *string = [NSString stringWithFormat:@"%@ - didReceiveServerRedirectForProvisionalLoadForFrame", [frame _drt_descriptionSuitableForTestResult]]; |
|
294 printf ("%s\n", [string UTF8String]); |
|
295 } |
|
296 } |
|
297 |
|
298 - (void)webView:(WebView *)sender didReceiveIcon:(NSImage *)image forFrame:(WebFrame *)frame |
|
299 { |
|
300 if (layoutTestController->dumpFrameLoadCallbacks() && !done) { |
|
301 NSString *string = [NSString stringWithFormat:@"%@ - didReceiveIconForFrame", [frame _drt_descriptionSuitableForTestResult]]; |
|
302 printf ("%s\n", [string UTF8String]); |
|
303 } |
|
304 } |
|
305 |
|
306 - (void)webView:(WebView *)sender didChangeLocationWithinPageForFrame:(WebFrame *)frame |
|
307 { |
|
308 if (layoutTestController->dumpFrameLoadCallbacks() && !done) { |
|
309 NSString *string = [NSString stringWithFormat:@"%@ - didChangeLocationWithinPageForFrame", [frame _drt_descriptionSuitableForTestResult]]; |
|
310 printf ("%s\n", [string UTF8String]); |
|
311 } |
|
312 } |
|
313 |
|
314 - (void)webView:(WebView *)sender willPerformClientRedirectToURL:(NSURL *)URL delay:(NSTimeInterval)seconds fireDate:(NSDate *)date forFrame:(WebFrame *)frame |
|
315 { |
|
316 if (layoutTestController->dumpFrameLoadCallbacks() && !done) { |
|
317 NSString *string = [NSString stringWithFormat:@"%@ - willPerformClientRedirectToURL: %@ ", [frame _drt_descriptionSuitableForTestResult], [URL _drt_descriptionSuitableForTestResult]]; |
|
318 printf ("%s\n", [string UTF8String]); |
|
319 } |
|
320 } |
|
321 |
|
322 - (void)webView:(WebView *)sender didCancelClientRedirectForFrame:(WebFrame *)frame |
|
323 { |
|
324 if (layoutTestController->dumpFrameLoadCallbacks() && !done) { |
|
325 NSString *string = [NSString stringWithFormat:@"%@ - didCancelClientRedirectForFrame", [frame _drt_descriptionSuitableForTestResult]]; |
|
326 printf ("%s\n", [string UTF8String]); |
|
327 } |
|
328 } |
|
329 |
|
330 - (void)webView:(WebView *)sender willCloseFrame:(WebFrame *)frame; |
|
331 { |
|
332 if (layoutTestController->dumpFrameLoadCallbacks() && !done) { |
|
333 NSString *string = [NSString stringWithFormat:@"%@ - willCloseFrame", [frame _drt_descriptionSuitableForTestResult]]; |
|
334 printf ("%s\n", [string UTF8String]); |
|
335 } |
|
336 } |
|
337 |
|
338 - (void)webView:(WebView *)sender didFinishDocumentLoadForFrame:(WebFrame *)frame; |
|
339 { |
|
340 if (layoutTestController->dumpFrameLoadCallbacks() && !done) { |
|
341 NSString *string = [NSString stringWithFormat:@"%@ - didFinishDocumentLoadForFrame", [frame _drt_descriptionSuitableForTestResult]]; |
|
342 printf ("%s\n", [string UTF8String]); |
|
343 } |
|
344 } |
|
345 |
|
346 - (void)webView:(WebView *)sender didHandleOnloadEventsForFrame:(WebFrame *)frame; |
|
347 { |
|
348 if (layoutTestController->dumpFrameLoadCallbacks() && !done) { |
|
349 NSString *string = [NSString stringWithFormat:@"%@ - didHandleOnloadEventsForFrame", [frame _drt_descriptionSuitableForTestResult]]; |
|
350 printf ("%s\n", [string UTF8String]); |
|
351 } |
|
352 } |
|
353 |
|
354 @end |