initial import
[vuplus_webkit] / Tools / DumpRenderTree / mac / FrameLoadDelegate.mm
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 "config.h"
30 #import "DumpRenderTree.h"
31 #import "FrameLoadDelegate.h"
32
33 #import "AccessibilityController.h"
34 #import "AppleScriptController.h"
35 #import "EventSendingController.h"
36 #import "GCController.h"
37 #import "LayoutTestController.h"
38 #import "NavigationController.h"
39 #import "ObjCController.h"
40 #import "ObjCPlugin.h"
41 #import "ObjCPluginFunction.h"
42 #import "PlainTextController.h"
43 #import "TextInputController.h"
44 #import "WebCoreTestSupport.h"
45 #import "WorkQueue.h"
46 #import "WorkQueueItem.h"
47 #import <JavaScriptCore/JavaScriptCore.h>
48 #import <WebKit/WebFramePrivate.h>
49 #import <WebKit/WebHTMLViewPrivate.h>
50 #import <WebKit/WebKit.h>
51 #import <WebKit/WebNSURLExtras.h>
52 #import <WebKit/WebScriptWorld.h>
53 #import <WebKit/WebSecurityOriginPrivate.h>
54 #import <WebKit/WebViewPrivate.h>
55 #import <wtf/Assertions.h>
56
57 @interface NSURL (DRTExtras)
58 - (NSString *)_drt_descriptionSuitableForTestResult;
59 @end
60
61 @interface NSError (DRTExtras)
62 - (NSString *)_drt_descriptionSuitableForTestResult;
63 @end
64
65 @interface NSURLResponse (DRTExtras)
66 - (NSString *)_drt_descriptionSuitableForTestResult;
67 @end
68
69 @interface NSURLRequest (DRTExtras)
70 - (NSString *)_drt_descriptionSuitableForTestResult;
71 @end
72
73 @interface WebFrame (DRTExtras)
74 - (NSString *)_drt_descriptionSuitableForTestResult;
75 @end
76
77 @implementation WebFrame (DRTExtras)
78 - (NSString *)_drt_descriptionSuitableForTestResult
79 {
80     BOOL isMainFrame = (self == [[self webView] mainFrame]);
81     NSString *name = [self name];
82     if (isMainFrame) {
83         if ([name length])
84             return [NSString stringWithFormat:@"main frame \"%@\"", name];
85         else
86             return @"main frame";
87     } else {
88         if (name)
89             return [NSString stringWithFormat:@"frame \"%@\"", name];
90         else
91             return @"frame (anonymous)";
92     }
93 }
94
95 - (NSString *)_drt_printFrameUserGestureStatus
96 {
97     BOOL isUserGesture = [[self webView] _isProcessingUserGesture];
98     return [NSString stringWithFormat:@"Frame with user gesture \"%@\"", isUserGesture ? @"true" : @"false"];
99 }
100 @end
101
102 @implementation FrameLoadDelegate
103
104 - (id)init
105 {
106     if ((self = [super init])) {
107         gcController = new GCController;
108         accessibilityController = new AccessibilityController;
109     }
110     return self;
111 }
112
113 - (void)dealloc
114 {
115     delete gcController;
116     delete accessibilityController;
117     [super dealloc];
118 }
119
120 // Exec messages in the work queue until they're all done, or one of them starts a new load
121 - (void)processWork:(id)dummy
122 {
123     // if another load started, then wait for it to complete.
124     if (topLoadingFrame)
125         return;
126
127     // if we finish all the commands, we're ready to dump state
128     if (WorkQueue::shared()->processWork() && !gLayoutTestController->waitToDump())
129         dump();
130 }
131
132 - (void)resetToConsistentState
133 {
134     accessibilityController->resetToConsistentState();
135 }
136
137 - (void)webView:(WebView *)c locationChangeDone:(NSError *)error forDataSource:(WebDataSource *)dataSource
138 {
139     if ([dataSource webFrame] == topLoadingFrame) {
140         topLoadingFrame = nil;
141         WorkQueue::shared()->setFrozen(true); // first complete load freezes the queue for the rest of this test
142         if (!gLayoutTestController->waitToDump()) {
143             if (WorkQueue::shared()->count())
144                 [self performSelector:@selector(processWork:) withObject:nil afterDelay:0];
145             else
146                 dump();
147         }
148     }
149 }
150
151 - (void)webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame
152 {
153     if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
154         NSString *string = [NSString stringWithFormat:@"%@ - didStartProvisionalLoadForFrame", [frame _drt_descriptionSuitableForTestResult]];
155         printf ("%s\n", [string UTF8String]);
156     }
157
158     if (!done && gLayoutTestController->dumpUserGestureInFrameLoadCallbacks()) {
159         NSString *string = [NSString stringWithFormat:@"%@ - in didStartProvisionalLoadForFrame", [frame _drt_printFrameUserGestureStatus]];
160         printf ("%s\n", [string UTF8String]);
161     }
162
163     ASSERT([frame provisionalDataSource]);
164     // Make sure we only set this once per test.  If it gets cleared, and then set again, we might
165     // end up doing two dumps for one test.
166     if (!topLoadingFrame && !done)
167         topLoadingFrame = frame;
168
169     if (!done && gLayoutTestController->stopProvisionalFrameLoads()) {
170         NSString *string = [NSString stringWithFormat:@"%@ - stopping load in didStartProvisionalLoadForFrame callback", [frame _drt_descriptionSuitableForTestResult]];
171         printf ("%s\n", [string UTF8String]);
172         [frame stopLoading];
173     }
174 }
175
176 - (void)webView:(WebView *)sender didCommitLoadForFrame:(WebFrame *)frame
177 {
178     if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
179         NSString *string = [NSString stringWithFormat:@"%@ - didCommitLoadForFrame", [frame _drt_descriptionSuitableForTestResult]];
180         printf ("%s\n", [string UTF8String]);
181     }
182
183     ASSERT(![frame provisionalDataSource]);
184     ASSERT([frame dataSource]);
185     
186     gLayoutTestController->setWindowIsKey(true);
187     NSView *documentView = [[mainFrame frameView] documentView];
188     [[[mainFrame webView] window] makeFirstResponder:documentView];
189 }
190
191 - (void)webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
192 {
193     if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
194         NSString *string = [NSString stringWithFormat:@"%@ - didFailProvisionalLoadWithError", [frame _drt_descriptionSuitableForTestResult]];
195         printf("%s\n", [string UTF8String]);
196     }
197
198     if ([error domain] == NSURLErrorDomain && ([error code] == NSURLErrorServerCertificateHasUnknownRoot || [error code] == NSURLErrorServerCertificateUntrusted)) {
199         // <http://webkit.org/b/31200> In order to prevent extra frame load delegate logging being generated if the first test to use SSL
200         // is set to log frame load delegate calls we ignore SSL certificate errors on localhost and 127.0.0.1 from within dumpRenderTree.
201         // Those are the only hosts that we use SSL with at present.  If we hit this code path then we've found another host that we need
202         // to apply the workaround to.
203         ASSERT_NOT_REACHED();
204         return;
205     }
206
207     ASSERT([frame provisionalDataSource]);
208     [self webView:sender locationChangeDone:error forDataSource:[frame provisionalDataSource]];
209 }
210
211 - (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame
212 {
213     ASSERT([frame dataSource]);
214     ASSERT(frame == [[frame dataSource] webFrame]);
215     
216     if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
217         NSString *string = [NSString stringWithFormat:@"%@ - didFinishLoadForFrame", [frame _drt_descriptionSuitableForTestResult]];
218         printf ("%s\n", [string UTF8String]);
219     }
220
221     // FIXME: This call to displayIfNeeded can be removed when <rdar://problem/5092361> is fixed.
222     // After that is fixed, we will reenable painting after WebCore is done loading the document, 
223     // and this call will no longer be needed.
224     if ([[sender mainFrame] isEqual:frame])
225         [sender displayIfNeeded];
226     [self webView:sender locationChangeDone:nil forDataSource:[frame dataSource]];
227     [gNavigationController webView:sender didFinishLoadForFrame:frame];
228 }
229
230 - (void)webView:(WebView *)sender didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
231 {
232     if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
233         NSString *string = [NSString stringWithFormat:@"%@ - didFailLoadWithError", [frame _drt_descriptionSuitableForTestResult]];
234         printf ("%s\n", [string UTF8String]);
235     }
236
237     ASSERT(![frame provisionalDataSource]);
238     ASSERT([frame dataSource]);
239     
240     [self webView:sender locationChangeDone:error forDataSource:[frame dataSource]];    
241 }
242
243 - (void)webView:(WebView *)webView windowScriptObjectAvailable:(WebScriptObject *)windowScriptObject
244 {
245     if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
246         NSString *string = [NSString stringWithFormat:@"?? - windowScriptObjectAvailable"];
247         printf ("%s\n", [string UTF8String]);
248     }
249
250     ASSERT_NOT_REACHED();
251 }
252
253 - (void)didClearWindowObjectInStandardWorldForFrame:(WebFrame *)frame
254 {
255     // Make New-Style LayoutTestController
256     JSContextRef context = [frame globalContext];
257     JSObjectRef globalObject = JSContextGetGlobalObject(context);
258     JSValueRef exception = 0;
259
260     ASSERT(gLayoutTestController);
261     gLayoutTestController->makeWindowObject(context, globalObject, &exception);
262     ASSERT(!exception);
263
264     gcController->makeWindowObject(context, globalObject, &exception);
265     ASSERT(!exception);
266
267     accessibilityController->makeWindowObject(context, globalObject, &exception);
268     ASSERT(!exception);
269
270     WebCoreTestSupport::injectInternalsObject(context);
271
272     // Make Old-Style controllers
273
274     WebView *webView = [frame webView];
275     WebScriptObject *obj = [frame windowObject];
276     AppleScriptController *asc = [[AppleScriptController alloc] initWithWebView:webView];
277     [obj setValue:asc forKey:@"appleScriptController"];
278     [asc release];
279
280     EventSendingController *esc = [[EventSendingController alloc] init];
281     [obj setValue:esc forKey:@"eventSender"];
282     [esc release];
283     
284     [obj setValue:gNavigationController forKey:@"navigationController"];
285     
286     ObjCController *occ = [[ObjCController alloc] init];
287     [obj setValue:occ forKey:@"objCController"];
288     [occ release];
289
290     ObjCPlugin *plugin = [[ObjCPlugin alloc] init];
291     [obj setValue:plugin forKey:@"objCPlugin"];
292     [plugin release];
293     
294     ObjCPluginFunction *pluginFunction = [[ObjCPluginFunction alloc] init];
295     [obj setValue:pluginFunction forKey:@"objCPluginFunction"];
296     [pluginFunction release];
297
298     [obj setValue:[PlainTextController sharedPlainTextController] forKey:@"plainText"];
299
300     TextInputController *tic = [[TextInputController alloc] initWithWebView:webView];
301     [obj setValue:tic forKey:@"textInputController"];
302     [tic release];
303 }
304
305 - (void)didClearWindowObjectForFrame:(WebFrame *)frame inIsolatedWorld:(WebScriptWorld *)world
306 {
307     JSGlobalContextRef ctx = [frame _globalContextForScriptWorld:world];
308     if (!ctx)
309         return;
310
311     JSObjectRef globalObject = JSContextGetGlobalObject(ctx);
312     if (!globalObject)
313         return;
314
315     JSObjectSetProperty(ctx, globalObject, JSRetainPtr<JSStringRef>(Adopt, JSStringCreateWithUTF8CString("__worldID")).get(), JSValueMakeNumber(ctx, worldIDForWorld(world)), kJSPropertyAttributeReadOnly, 0);
316 }
317
318 - (void)webView:(WebView *)sender didClearWindowObjectForFrame:(WebFrame *)frame inScriptWorld:(WebScriptWorld *)world
319 {
320     if (world == [WebScriptWorld standardWorld])
321         [self didClearWindowObjectInStandardWorldForFrame:frame];
322     else
323         [self didClearWindowObjectForFrame:frame inIsolatedWorld:world];
324 }
325
326 - (void)webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame
327 {
328     if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
329         NSString *string = [NSString stringWithFormat:@"%@ - didReceiveTitle: %@", [frame _drt_descriptionSuitableForTestResult], title];
330         printf ("%s\n", [string UTF8String]);
331     }
332
333     if (gLayoutTestController->dumpTitleChanges())
334         printf("TITLE CHANGED: %s\n", [title UTF8String]);
335 }
336
337 - (void)webView:(WebView *)sender didReceiveServerRedirectForProvisionalLoadForFrame:(WebFrame *)frame
338 {
339     if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
340         NSString *string = [NSString stringWithFormat:@"%@ - didReceiveServerRedirectForProvisionalLoadForFrame", [frame _drt_descriptionSuitableForTestResult]];
341         printf ("%s\n", [string UTF8String]);
342     }
343 }
344
345 - (void)webView:(WebView *)sender didChangeLocationWithinPageForFrame:(WebFrame *)frame
346 {
347     if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
348         NSString *string = [NSString stringWithFormat:@"%@ - didChangeLocationWithinPageForFrame", [frame _drt_descriptionSuitableForTestResult]];
349         printf ("%s\n", [string UTF8String]);
350     }
351 }
352
353 - (void)webView:(WebView *)sender willPerformClientRedirectToURL:(NSURL *)URL delay:(NSTimeInterval)seconds fireDate:(NSDate *)date forFrame:(WebFrame *)frame
354 {
355     if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
356         NSString *string = [NSString stringWithFormat:@"%@ - willPerformClientRedirectToURL: %@ ", [frame _drt_descriptionSuitableForTestResult], [URL _drt_descriptionSuitableForTestResult]];
357         printf ("%s\n", [string UTF8String]);
358     }
359
360     if (!done && gLayoutTestController->dumpUserGestureInFrameLoadCallbacks()) {
361         NSString *string = [NSString stringWithFormat:@"%@ - in willPerformClientRedirect", [frame _drt_printFrameUserGestureStatus]];
362         printf ("%s\n", [string UTF8String]);
363     }
364 }
365
366 - (void)webView:(WebView *)sender didCancelClientRedirectForFrame:(WebFrame *)frame
367 {
368     if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
369         NSString *string = [NSString stringWithFormat:@"%@ - didCancelClientRedirectForFrame", [frame _drt_descriptionSuitableForTestResult]];
370         printf ("%s\n", [string UTF8String]);
371     }
372 }
373
374 - (void)webView:(WebView *)sender didFinishDocumentLoadForFrame:(WebFrame *)frame
375 {
376     if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
377         NSString *string = [NSString stringWithFormat:@"%@ - didFinishDocumentLoadForFrame", [frame _drt_descriptionSuitableForTestResult]];
378         printf ("%s\n", [string UTF8String]);
379     } else if (!done) {
380         unsigned pendingFrameUnloadEvents = [frame _pendingFrameUnloadEventCount];
381         if (pendingFrameUnloadEvents) {
382             NSString *string = [NSString stringWithFormat:@"%@ - has %u onunload handler(s)", [frame _drt_descriptionSuitableForTestResult], pendingFrameUnloadEvents];
383             printf ("%s\n", [string UTF8String]);
384         }
385     }
386 }
387
388 - (void)webView:(WebView *)sender didHandleOnloadEventsForFrame:(WebFrame *)frame
389 {
390     if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
391         NSString *string = [NSString stringWithFormat:@"%@ - didHandleOnloadEventsForFrame", [frame _drt_descriptionSuitableForTestResult]];
392         printf ("%s\n", [string UTF8String]);
393     }
394 }
395
396 - (void)webViewDidDisplayInsecureContent:(WebView *)sender
397 {
398     if (!done && gLayoutTestController->dumpFrameLoadCallbacks())
399         printf ("didDisplayInsecureContent\n");
400 }
401
402 - (void)webView:(WebView *)sender didRunInsecureContent:(WebSecurityOrigin *)origin
403 {
404     if (!done && gLayoutTestController->dumpFrameLoadCallbacks())
405         printf ("didRunInsecureContent\n");
406 }
407
408 @end