760c5e6389659803d16ee46c036ab026677c7938
[WebKit-https.git] / WebKitTools / 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 "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/JavaScriptCore.h>
44 #import <WebKit/WebFramePrivate.h>
45 #import <WebKit/WebHTMLViewPrivate.h>
46 #import <WebKit/WebKit.h>
47 #import <WebKit/WebNSURLExtras.h>
48 #import <wtf/Assertions.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 (!done && layoutTestController->dumpFrameLoadCallbacks()) {
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 (!done && layoutTestController->dumpFrameLoadCallbacks()) {
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 _updateFocusedAndActiveState];
167 }
168
169 - (void)webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
170 {
171     if (!done && layoutTestController->dumpFrameLoadCallbacks()) {
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 (!done && layoutTestController->dumpFrameLoadCallbacks()) {
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 (!done && layoutTestController->dumpFrameLoadCallbacks()) {
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 (!done && layoutTestController->dumpFrameLoadCallbacks()) {
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 (!done && layoutTestController->dumpFrameLoadCallbacks()) {
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 (!done && layoutTestController->dumpFrameLoadCallbacks()) {
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 (!done && layoutTestController->dumpFrameLoadCallbacks()) {
293         NSString *string = [NSString stringWithFormat:@"%@ - didReceiveServerRedirectForProvisionalLoadForFrame", [frame _drt_descriptionSuitableForTestResult]];
294         printf ("%s\n", [string UTF8String]);
295     }
296 }
297
298 - (void)webView:(WebView *)sender didChangeLocationWithinPageForFrame:(WebFrame *)frame
299 {
300     if (!done && layoutTestController->dumpFrameLoadCallbacks()) {
301         NSString *string = [NSString stringWithFormat:@"%@ - didChangeLocationWithinPageForFrame", [frame _drt_descriptionSuitableForTestResult]];
302         printf ("%s\n", [string UTF8String]);
303     }
304 }
305
306 - (void)webView:(WebView *)sender willPerformClientRedirectToURL:(NSURL *)URL delay:(NSTimeInterval)seconds fireDate:(NSDate *)date forFrame:(WebFrame *)frame
307 {
308     if (!done && layoutTestController->dumpFrameLoadCallbacks()) {
309         NSString *string = [NSString stringWithFormat:@"%@ - willPerformClientRedirectToURL: %@ ", [frame _drt_descriptionSuitableForTestResult], [URL _drt_descriptionSuitableForTestResult]];
310         printf ("%s\n", [string UTF8String]);
311     }
312 }
313
314 - (void)webView:(WebView *)sender didCancelClientRedirectForFrame:(WebFrame *)frame
315 {
316     if (!done && layoutTestController->dumpFrameLoadCallbacks()) {
317         NSString *string = [NSString stringWithFormat:@"%@ - didCancelClientRedirectForFrame", [frame _drt_descriptionSuitableForTestResult]];
318         printf ("%s\n", [string UTF8String]);
319     }
320 }
321
322 - (void)webView:(WebView *)sender willCloseFrame:(WebFrame *)frame;
323 {
324     if (!done && layoutTestController->dumpFrameLoadCallbacks()) {
325         NSString *string = [NSString stringWithFormat:@"%@ - willCloseFrame", [frame _drt_descriptionSuitableForTestResult]];
326         printf ("%s\n", [string UTF8String]);
327     }
328 }
329
330 - (void)webView:(WebView *)sender didFinishDocumentLoadForFrame:(WebFrame *)frame;
331 {
332     if (!done && layoutTestController->dumpFrameLoadCallbacks()) {
333         NSString *string = [NSString stringWithFormat:@"%@ - didFinishDocumentLoadForFrame", [frame _drt_descriptionSuitableForTestResult]];
334         printf ("%s\n", [string UTF8String]);
335     }
336 }
337
338 - (void)webView:(WebView *)sender didHandleOnloadEventsForFrame:(WebFrame *)frame;
339 {
340     if (!done && layoutTestController->dumpFrameLoadCallbacks()) {
341         NSString *string = [NSString stringWithFormat:@"%@ - didHandleOnloadEventsForFrame", [frame _drt_descriptionSuitableForTestResult]];
342         printf ("%s\n", [string UTF8String]);
343     }
344 }
345
346 @end