2 * Copyright (C) 2007 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
30 #import "DumpRenderTree.h"
31 #import "FrameLoadDelegate.h"
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"
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>
57 @interface NSURL (DRTExtras)
58 - (NSString *)_drt_descriptionSuitableForTestResult;
61 @interface NSError (DRTExtras)
62 - (NSString *)_drt_descriptionSuitableForTestResult;
65 @interface NSURLResponse (DRTExtras)
66 - (NSString *)_drt_descriptionSuitableForTestResult;
69 @interface NSURLRequest (DRTExtras)
70 - (NSString *)_drt_descriptionSuitableForTestResult;
73 @interface WebFrame (DRTExtras)
74 - (NSString *)_drt_descriptionSuitableForTestResult;
77 @implementation WebFrame (DRTExtras)
78 - (NSString *)_drt_descriptionSuitableForTestResult
80 BOOL isMainFrame = (self == [[self webView] mainFrame]);
81 NSString *name = [self name];
84 return [NSString stringWithFormat:@"main frame \"%@\"", name];
89 return [NSString stringWithFormat:@"frame \"%@\"", name];
91 return @"frame (anonymous)";
95 - (NSString *)_drt_printFrameUserGestureStatus
97 BOOL isUserGesture = [[self webView] _isProcessingUserGesture];
98 return [NSString stringWithFormat:@"Frame with user gesture \"%@\"", isUserGesture ? @"true" : @"false"];
102 @implementation FrameLoadDelegate
106 if ((self = [super init])) {
107 gcController = new GCController;
108 accessibilityController = new AccessibilityController;
116 delete accessibilityController;
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
123 // if another load started, then wait for it to complete.
127 // if we finish all the commands, we're ready to dump state
128 if (WorkQueue::shared()->processWork() && !gLayoutTestController->waitToDump())
132 - (void)resetToConsistentState
134 accessibilityController->resetToConsistentState();
137 - (void)webView:(WebView *)c locationChangeDone:(NSError *)error forDataSource:(WebDataSource *)dataSource
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];
151 - (void)webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame
153 if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
154 NSString *string = [NSString stringWithFormat:@"%@ - didStartProvisionalLoadForFrame", [frame _drt_descriptionSuitableForTestResult]];
155 printf ("%s\n", [string UTF8String]);
158 if (!done && gLayoutTestController->dumpUserGestureInFrameLoadCallbacks()) {
159 NSString *string = [NSString stringWithFormat:@"%@ - in didStartProvisionalLoadForFrame", [frame _drt_printFrameUserGestureStatus]];
160 printf ("%s\n", [string UTF8String]);
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;
169 if (!done && gLayoutTestController->stopProvisionalFrameLoads()) {
170 NSString *string = [NSString stringWithFormat:@"%@ - stopping load in didStartProvisionalLoadForFrame callback", [frame _drt_descriptionSuitableForTestResult]];
171 printf ("%s\n", [string UTF8String]);
176 - (void)webView:(WebView *)sender didCommitLoadForFrame:(WebFrame *)frame
178 if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
179 NSString *string = [NSString stringWithFormat:@"%@ - didCommitLoadForFrame", [frame _drt_descriptionSuitableForTestResult]];
180 printf ("%s\n", [string UTF8String]);
183 ASSERT(![frame provisionalDataSource]);
184 ASSERT([frame dataSource]);
186 gLayoutTestController->setWindowIsKey(true);
187 NSView *documentView = [[mainFrame frameView] documentView];
188 [[[mainFrame webView] window] makeFirstResponder:documentView];
191 - (void)webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
193 if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
194 NSString *string = [NSString stringWithFormat:@"%@ - didFailProvisionalLoadWithError", [frame _drt_descriptionSuitableForTestResult]];
195 printf("%s\n", [string UTF8String]);
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();
207 ASSERT([frame provisionalDataSource]);
208 [self webView:sender locationChangeDone:error forDataSource:[frame provisionalDataSource]];
211 - (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame
213 ASSERT([frame dataSource]);
214 ASSERT(frame == [[frame dataSource] webFrame]);
216 if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
217 NSString *string = [NSString stringWithFormat:@"%@ - didFinishLoadForFrame", [frame _drt_descriptionSuitableForTestResult]];
218 printf ("%s\n", [string UTF8String]);
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];
230 - (void)webView:(WebView *)sender didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
232 if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
233 NSString *string = [NSString stringWithFormat:@"%@ - didFailLoadWithError", [frame _drt_descriptionSuitableForTestResult]];
234 printf ("%s\n", [string UTF8String]);
237 ASSERT(![frame provisionalDataSource]);
238 ASSERT([frame dataSource]);
240 [self webView:sender locationChangeDone:error forDataSource:[frame dataSource]];
243 - (void)webView:(WebView *)webView windowScriptObjectAvailable:(WebScriptObject *)windowScriptObject
245 if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
246 NSString *string = [NSString stringWithFormat:@"?? - windowScriptObjectAvailable"];
247 printf ("%s\n", [string UTF8String]);
250 ASSERT_NOT_REACHED();
253 - (void)didClearWindowObjectInStandardWorldForFrame:(WebFrame *)frame
255 // Make New-Style LayoutTestController
256 JSContextRef context = [frame globalContext];
257 JSObjectRef globalObject = JSContextGetGlobalObject(context);
258 JSValueRef exception = 0;
260 ASSERT(gLayoutTestController);
261 gLayoutTestController->makeWindowObject(context, globalObject, &exception);
264 gcController->makeWindowObject(context, globalObject, &exception);
267 accessibilityController->makeWindowObject(context, globalObject, &exception);
270 WebCoreTestSupport::injectInternalsObject(context);
272 // Make Old-Style controllers
274 WebView *webView = [frame webView];
275 WebScriptObject *obj = [frame windowObject];
276 AppleScriptController *asc = [[AppleScriptController alloc] initWithWebView:webView];
277 [obj setValue:asc forKey:@"appleScriptController"];
280 EventSendingController *esc = [[EventSendingController alloc] init];
281 [obj setValue:esc forKey:@"eventSender"];
284 [obj setValue:gNavigationController forKey:@"navigationController"];
286 ObjCController *occ = [[ObjCController alloc] init];
287 [obj setValue:occ forKey:@"objCController"];
290 ObjCPlugin *plugin = [[ObjCPlugin alloc] init];
291 [obj setValue:plugin forKey:@"objCPlugin"];
294 ObjCPluginFunction *pluginFunction = [[ObjCPluginFunction alloc] init];
295 [obj setValue:pluginFunction forKey:@"objCPluginFunction"];
296 [pluginFunction release];
298 [obj setValue:[PlainTextController sharedPlainTextController] forKey:@"plainText"];
300 TextInputController *tic = [[TextInputController alloc] initWithWebView:webView];
301 [obj setValue:tic forKey:@"textInputController"];
305 - (void)didClearWindowObjectForFrame:(WebFrame *)frame inIsolatedWorld:(WebScriptWorld *)world
307 JSGlobalContextRef ctx = [frame _globalContextForScriptWorld:world];
311 JSObjectRef globalObject = JSContextGetGlobalObject(ctx);
315 JSObjectSetProperty(ctx, globalObject, JSRetainPtr<JSStringRef>(Adopt, JSStringCreateWithUTF8CString("__worldID")).get(), JSValueMakeNumber(ctx, worldIDForWorld(world)), kJSPropertyAttributeReadOnly, 0);
318 - (void)webView:(WebView *)sender didClearWindowObjectForFrame:(WebFrame *)frame inScriptWorld:(WebScriptWorld *)world
320 if (world == [WebScriptWorld standardWorld])
321 [self didClearWindowObjectInStandardWorldForFrame:frame];
323 [self didClearWindowObjectForFrame:frame inIsolatedWorld:world];
326 - (void)webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame
328 if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
329 NSString *string = [NSString stringWithFormat:@"%@ - didReceiveTitle: %@", [frame _drt_descriptionSuitableForTestResult], title];
330 printf ("%s\n", [string UTF8String]);
333 if (gLayoutTestController->dumpTitleChanges())
334 printf("TITLE CHANGED: %s\n", [title UTF8String]);
337 - (void)webView:(WebView *)sender didReceiveServerRedirectForProvisionalLoadForFrame:(WebFrame *)frame
339 if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
340 NSString *string = [NSString stringWithFormat:@"%@ - didReceiveServerRedirectForProvisionalLoadForFrame", [frame _drt_descriptionSuitableForTestResult]];
341 printf ("%s\n", [string UTF8String]);
345 - (void)webView:(WebView *)sender didChangeLocationWithinPageForFrame:(WebFrame *)frame
347 if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
348 NSString *string = [NSString stringWithFormat:@"%@ - didChangeLocationWithinPageForFrame", [frame _drt_descriptionSuitableForTestResult]];
349 printf ("%s\n", [string UTF8String]);
353 - (void)webView:(WebView *)sender willPerformClientRedirectToURL:(NSURL *)URL delay:(NSTimeInterval)seconds fireDate:(NSDate *)date forFrame:(WebFrame *)frame
355 if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
356 NSString *string = [NSString stringWithFormat:@"%@ - willPerformClientRedirectToURL: %@ ", [frame _drt_descriptionSuitableForTestResult], [URL _drt_descriptionSuitableForTestResult]];
357 printf ("%s\n", [string UTF8String]);
360 if (!done && gLayoutTestController->dumpUserGestureInFrameLoadCallbacks()) {
361 NSString *string = [NSString stringWithFormat:@"%@ - in willPerformClientRedirect", [frame _drt_printFrameUserGestureStatus]];
362 printf ("%s\n", [string UTF8String]);
366 - (void)webView:(WebView *)sender didCancelClientRedirectForFrame:(WebFrame *)frame
368 if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
369 NSString *string = [NSString stringWithFormat:@"%@ - didCancelClientRedirectForFrame", [frame _drt_descriptionSuitableForTestResult]];
370 printf ("%s\n", [string UTF8String]);
374 - (void)webView:(WebView *)sender didFinishDocumentLoadForFrame:(WebFrame *)frame
376 if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
377 NSString *string = [NSString stringWithFormat:@"%@ - didFinishDocumentLoadForFrame", [frame _drt_descriptionSuitableForTestResult]];
378 printf ("%s\n", [string UTF8String]);
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]);
388 - (void)webView:(WebView *)sender didHandleOnloadEventsForFrame:(WebFrame *)frame
390 if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
391 NSString *string = [NSString stringWithFormat:@"%@ - didHandleOnloadEventsForFrame", [frame _drt_descriptionSuitableForTestResult]];
392 printf ("%s\n", [string UTF8String]);
396 - (void)webViewDidDisplayInsecureContent:(WebView *)sender
398 if (!done && gLayoutTestController->dumpFrameLoadCallbacks())
399 printf ("didDisplayInsecureContent\n");
402 - (void)webView:(WebView *)sender didRunInsecureContent:(WebSecurityOrigin *)origin
404 if (!done && gLayoutTestController->dumpFrameLoadCallbacks())
405 printf ("didRunInsecureContent\n");