123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467 |
- /*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #import "config.h"
- #import "DumpRenderTree.h"
- #import "FrameLoadDelegate.h"
- #import "AccessibilityController.h"
- #import "AppleScriptController.h"
- #import "EventSendingController.h"
- #import "Foundation/NSNotification.h"
- #import "GCController.h"
- #import "TestRunner.h"
- #import "NavigationController.h"
- #import "ObjCController.h"
- #import "ObjCPlugin.h"
- #import "ObjCPluginFunction.h"
- #import "TextInputController.h"
- #import "WebCoreTestSupport.h"
- #import "WorkQueue.h"
- #import "WorkQueueItem.h"
- #import <JavaScriptCore/JavaScriptCore.h>
- #import <WebKitSystemInterface.h>
- #import <WebKit/WebFramePrivate.h>
- #import <WebKit/WebHTMLViewPrivate.h>
- #import <WebKit/WebKit.h>
- #import <WebKit/WebNSURLExtras.h>
- #import <WebKit/WebScriptWorld.h>
- #import <WebKit/WebSecurityOriginPrivate.h>
- #import <WebKit/WebViewPrivate.h>
- #import <wtf/Assertions.h>
- #ifndef NSEC_PER_MSEC
- #define NSEC_PER_MSEC 1000000ull
- #endif
- @interface NSURL (DRTExtras)
- - (NSString *)_drt_descriptionSuitableForTestResult;
- @end
- @interface NSError (DRTExtras)
- - (NSString *)_drt_descriptionSuitableForTestResult;
- @end
- @interface NSURLResponse (DRTExtras)
- - (NSString *)_drt_descriptionSuitableForTestResult;
- @end
- @interface NSURLRequest (DRTExtras)
- - (NSString *)_drt_descriptionSuitableForTestResult;
- @end
- @interface WebFrame (DRTExtras)
- - (NSString *)_drt_descriptionSuitableForTestResult;
- @end
- @implementation WebFrame (DRTExtras)
- - (NSString *)_drt_descriptionSuitableForTestResult
- {
- BOOL isMainFrame = (self == [[self webView] mainFrame]);
- NSString *name = [self name];
- if (isMainFrame) {
- if ([name length])
- return [NSString stringWithFormat:@"main frame \"%@\"", name];
- else
- return @"main frame";
- } else {
- if (name)
- return [NSString stringWithFormat:@"frame \"%@\"", name];
- else
- return @"frame (anonymous)";
- }
- }
- - (NSString *)_drt_printFrameUserGestureStatus
- {
- BOOL isUserGesture = [[self webView] _isProcessingUserGesture];
- return [NSString stringWithFormat:@"Frame with user gesture \"%@\"", isUserGesture ? @"true" : @"false"];
- }
- @end
- @implementation FrameLoadDelegate
- - (id)init
- {
- if ((self = [super init])) {
- gcController = new GCController;
- accessibilityController = new AccessibilityController;
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(webViewProgressFinishedNotification:) name:WebViewProgressFinishedNotification object:nil];
- }
- return self;
- }
- - (void)dealloc
- {
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- delete gcController;
- delete accessibilityController;
- [super dealloc];
- }
- // Exec messages in the work queue until they're all done, or one of them starts a new load
- - (void)processWork:(id)dummy
- {
- // if another load started, then wait for it to complete.
- if (topLoadingFrame)
- return;
- // if we finish all the commands, we're ready to dump state
- if (WorkQueue::shared()->processWork() && !gTestRunner->waitToDump())
- dump();
- }
- - (void)resetToConsistentState
- {
- accessibilityController->resetToConsistentState();
- }
- - (void)webView:(WebView *)c locationChangeDone:(NSError *)error forDataSource:(WebDataSource *)dataSource
- {
- if ([dataSource webFrame] == topLoadingFrame) {
- topLoadingFrame = nil;
- WorkQueue::shared()->setFrozen(true); // first complete load freezes the queue for the rest of this test
- if (!gTestRunner->waitToDump()) {
- if (WorkQueue::shared()->count())
- [self performSelector:@selector(processWork:) withObject:nil afterDelay:0];
- else
- dump();
- }
- }
- }
- #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
- static NSString *testPathFromURL(NSURL* url)
- {
- if ([url isFileURL]) {
- NSString *filePath = [url path];
- NSRange layoutTestsRange = [filePath rangeOfString:@"/LayoutTests/"];
- if (layoutTestsRange.location == NSNotFound)
- return nil;
-
- return [filePath substringFromIndex:NSMaxRange(layoutTestsRange)];
- }
-
- // HTTP test URLs look like: http://127.0.0.1:8000/inspector/resource-tree/resource-request-content-after-loading-and-clearing-cache.html
- if (![[url scheme] isEqualToString:@"http"] && ![[url scheme] isEqualToString:@"https"])
- return nil;
- if ([[url host] isEqualToString:@"127.0.0.1"] && ([[url port] intValue] == 8000 || [[url port] intValue] == 8443))
- return [url path];
- return nil;
- }
- #endif
- - (void)webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame
- {
- ASSERT([frame provisionalDataSource]);
- #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
- if (!done && [[sender mainFrame] isEqual:frame]) {
- NSURL *provisionalLoadURL = [[[frame provisionalDataSource] initialRequest] URL];
- if (NSString *testPath = testPathFromURL(provisionalLoadURL))
- WKSetCrashReportApplicationSpecificInformation((CFStringRef)[@"CRASHING TEST: " stringByAppendingString:testPath]);
- }
- #endif
- if (!done && gTestRunner->dumpFrameLoadCallbacks()) {
- NSString *string = [NSString stringWithFormat:@"%@ - didStartProvisionalLoadForFrame", [frame _drt_descriptionSuitableForTestResult]];
- printf ("%s\n", [string UTF8String]);
- }
- if (!done && gTestRunner->dumpUserGestureInFrameLoadCallbacks()) {
- NSString *string = [NSString stringWithFormat:@"%@ - in didStartProvisionalLoadForFrame", [frame _drt_printFrameUserGestureStatus]];
- printf ("%s\n", [string UTF8String]);
- }
- // Make sure we only set this once per test. If it gets cleared, and then set again, we might
- // end up doing two dumps for one test.
- if (!topLoadingFrame && !done)
- topLoadingFrame = frame;
- if (!done && gTestRunner->stopProvisionalFrameLoads()) {
- NSString *string = [NSString stringWithFormat:@"%@ - stopping load in didStartProvisionalLoadForFrame callback", [frame _drt_descriptionSuitableForTestResult]];
- printf ("%s\n", [string UTF8String]);
- [frame stopLoading];
- }
- if (!done && gTestRunner->useDeferredFrameLoading()) {
- [sender setDefersCallbacks:YES];
- int64_t deferredWaitTime = 5 * NSEC_PER_MSEC;
- dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, deferredWaitTime);
- dispatch_after(when, dispatch_get_main_queue(), ^{
- [sender setDefersCallbacks:NO];
- });
- }
- }
- - (void)webView:(WebView *)sender didCommitLoadForFrame:(WebFrame *)frame
- {
- if (!done && gTestRunner->dumpFrameLoadCallbacks()) {
- NSString *string = [NSString stringWithFormat:@"%@ - didCommitLoadForFrame", [frame _drt_descriptionSuitableForTestResult]];
- printf ("%s\n", [string UTF8String]);
- }
- ASSERT(![frame provisionalDataSource]);
- ASSERT([frame dataSource]);
-
- gTestRunner->setWindowIsKey(true);
- NSView *documentView = [[mainFrame frameView] documentView];
- [[[mainFrame webView] window] makeFirstResponder:documentView];
- }
- - (void)webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
- {
- if (!done && gTestRunner->dumpFrameLoadCallbacks()) {
- NSString *string = [NSString stringWithFormat:@"%@ - didFailProvisionalLoadWithError", [frame _drt_descriptionSuitableForTestResult]];
- printf("%s\n", [string UTF8String]);
- }
- if ([error domain] == NSURLErrorDomain && ([error code] == NSURLErrorServerCertificateHasUnknownRoot || [error code] == NSURLErrorServerCertificateUntrusted)) {
- // <http://webkit.org/b/31200> In order to prevent extra frame load delegate logging being generated if the first test to use SSL
- // is set to log frame load delegate calls we ignore SSL certificate errors on localhost and 127.0.0.1 from within dumpRenderTree.
- // 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
- // to apply the workaround to.
- ASSERT_NOT_REACHED();
- return;
- }
- ASSERT([frame provisionalDataSource]);
- [self webView:sender locationChangeDone:error forDataSource:[frame provisionalDataSource]];
- }
- - (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame
- {
- ASSERT([frame dataSource]);
- ASSERT(frame == [[frame dataSource] webFrame]);
-
- if (!done && gTestRunner->dumpFrameLoadCallbacks()) {
- NSString *string = [NSString stringWithFormat:@"%@ - didFinishLoadForFrame", [frame _drt_descriptionSuitableForTestResult]];
- printf ("%s\n", [string UTF8String]);
- }
- // FIXME: This call to displayIfNeeded can be removed when <rdar://problem/5092361> is fixed.
- // After that is fixed, we will reenable painting after WebCore is done loading the document,
- // and this call will no longer be needed.
- if ([[sender mainFrame] isEqual:frame])
- [sender displayIfNeeded];
- [self webView:sender locationChangeDone:nil forDataSource:[frame dataSource]];
- [gNavigationController webView:sender didFinishLoadForFrame:frame];
- }
- - (void)webView:(WebView *)sender didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
- {
- if (!done && gTestRunner->dumpFrameLoadCallbacks()) {
- NSString *string = [NSString stringWithFormat:@"%@ - didFailLoadWithError", [frame _drt_descriptionSuitableForTestResult]];
- printf ("%s\n", [string UTF8String]);
- }
- ASSERT(![frame provisionalDataSource]);
- ASSERT([frame dataSource]);
-
- [self webView:sender locationChangeDone:error forDataSource:[frame dataSource]];
- }
- - (void)webView:(WebView *)webView windowScriptObjectAvailable:(WebScriptObject *)windowScriptObject
- {
- if (!done && gTestRunner->dumpFrameLoadCallbacks()) {
- NSString *string = [NSString stringWithFormat:@"?? - windowScriptObjectAvailable"];
- printf ("%s\n", [string UTF8String]);
- }
- ASSERT_NOT_REACHED();
- }
- - (void)didClearWindowObjectInStandardWorldForFrame:(WebFrame *)frame
- {
- // Make New-Style TestRunner
- JSContextRef context = [frame globalContext];
- JSObjectRef globalObject = JSContextGetGlobalObject(context);
- JSValueRef exception = 0;
- ASSERT(gTestRunner);
- gTestRunner->makeWindowObject(context, globalObject, &exception);
- ASSERT(!exception);
- gcController->makeWindowObject(context, globalObject, &exception);
- ASSERT(!exception);
- accessibilityController->makeWindowObject(context, globalObject, &exception);
- ASSERT(!exception);
- WebCoreTestSupport::injectInternalsObject(context);
- // Make Old-Style controllers
- WebView *webView = [frame webView];
- WebScriptObject *obj = [frame windowObject];
- AppleScriptController *asc = [[AppleScriptController alloc] initWithWebView:webView];
- [obj setValue:asc forKey:@"appleScriptController"];
- [asc release];
- EventSendingController *esc = [[EventSendingController alloc] init];
- [obj setValue:esc forKey:@"eventSender"];
- [esc release];
-
- [obj setValue:gNavigationController forKey:@"navigationController"];
-
- ObjCController *occ = [[ObjCController alloc] init];
- [obj setValue:occ forKey:@"objCController"];
- [occ release];
- ObjCPlugin *plugin = [[ObjCPlugin alloc] init];
- [obj setValue:plugin forKey:@"objCPlugin"];
- [plugin release];
-
- ObjCPluginFunction *pluginFunction = [[ObjCPluginFunction alloc] init];
- [obj setValue:pluginFunction forKey:@"objCPluginFunction"];
- [pluginFunction release];
- TextInputController *tic = [[TextInputController alloc] initWithWebView:webView];
- [obj setValue:tic forKey:@"textInputController"];
- [tic release];
- }
- - (void)didClearWindowObjectForFrame:(WebFrame *)frame inIsolatedWorld:(WebScriptWorld *)world
- {
- JSGlobalContextRef ctx = [frame _globalContextForScriptWorld:world];
- if (!ctx)
- return;
- JSObjectRef globalObject = JSContextGetGlobalObject(ctx);
- if (!globalObject)
- return;
- JSObjectSetProperty(ctx, globalObject, JSRetainPtr<JSStringRef>(Adopt, JSStringCreateWithUTF8CString("__worldID")).get(), JSValueMakeNumber(ctx, worldIDForWorld(world)), kJSPropertyAttributeReadOnly, 0);
- }
- - (void)webView:(WebView *)sender didClearWindowObjectForFrame:(WebFrame *)frame inScriptWorld:(WebScriptWorld *)world
- {
- if (world == [WebScriptWorld standardWorld])
- [self didClearWindowObjectInStandardWorldForFrame:frame];
- else
- [self didClearWindowObjectForFrame:frame inIsolatedWorld:world];
- }
- - (void)webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame
- {
- if (!done && gTestRunner->dumpFrameLoadCallbacks()) {
- NSString *string = [NSString stringWithFormat:@"%@ - didReceiveTitle: %@", [frame _drt_descriptionSuitableForTestResult], title];
- printf ("%s\n", [string UTF8String]);
- }
- if (gTestRunner->dumpTitleChanges())
- printf("TITLE CHANGED: '%s'\n", [title UTF8String]);
- }
- - (void)webView:(WebView *)sender didReceiveServerRedirectForProvisionalLoadForFrame:(WebFrame *)frame
- {
- if (!done && gTestRunner->dumpFrameLoadCallbacks()) {
- NSString *string = [NSString stringWithFormat:@"%@ - didReceiveServerRedirectForProvisionalLoadForFrame", [frame _drt_descriptionSuitableForTestResult]];
- printf ("%s\n", [string UTF8String]);
- }
- }
- - (void)webView:(WebView *)sender didChangeLocationWithinPageForFrame:(WebFrame *)frame
- {
- if (!done && gTestRunner->dumpFrameLoadCallbacks()) {
- NSString *string = [NSString stringWithFormat:@"%@ - didChangeLocationWithinPageForFrame", [frame _drt_descriptionSuitableForTestResult]];
- printf ("%s\n", [string UTF8String]);
- }
- }
- - (void)webView:(WebView *)sender willPerformClientRedirectToURL:(NSURL *)URL delay:(NSTimeInterval)seconds fireDate:(NSDate *)date forFrame:(WebFrame *)frame
- {
- if (!done && gTestRunner->dumpFrameLoadCallbacks()) {
- NSString *string = [NSString stringWithFormat:@"%@ - willPerformClientRedirectToURL: %@ ", [frame _drt_descriptionSuitableForTestResult], [URL _drt_descriptionSuitableForTestResult]];
- printf ("%s\n", [string UTF8String]);
- }
- if (!done && gTestRunner->dumpUserGestureInFrameLoadCallbacks()) {
- NSString *string = [NSString stringWithFormat:@"%@ - in willPerformClientRedirect", [frame _drt_printFrameUserGestureStatus]];
- printf ("%s\n", [string UTF8String]);
- }
- }
- - (void)webView:(WebView *)sender didCancelClientRedirectForFrame:(WebFrame *)frame
- {
- if (!done && gTestRunner->dumpFrameLoadCallbacks()) {
- NSString *string = [NSString stringWithFormat:@"%@ - didCancelClientRedirectForFrame", [frame _drt_descriptionSuitableForTestResult]];
- printf ("%s\n", [string UTF8String]);
- }
- }
- - (void)webView:(WebView *)sender didFinishDocumentLoadForFrame:(WebFrame *)frame
- {
- if (!done && gTestRunner->dumpFrameLoadCallbacks()) {
- NSString *string = [NSString stringWithFormat:@"%@ - didFinishDocumentLoadForFrame", [frame _drt_descriptionSuitableForTestResult]];
- printf ("%s\n", [string UTF8String]);
- } else if (!done) {
- unsigned pendingFrameUnloadEvents = [frame _pendingFrameUnloadEventCount];
- if (pendingFrameUnloadEvents) {
- NSString *string = [NSString stringWithFormat:@"%@ - has %u onunload handler(s)", [frame _drt_descriptionSuitableForTestResult], pendingFrameUnloadEvents];
- printf ("%s\n", [string UTF8String]);
- }
- }
- }
- - (void)webView:(WebView *)sender didHandleOnloadEventsForFrame:(WebFrame *)frame
- {
- if (!done && gTestRunner->dumpFrameLoadCallbacks()) {
- NSString *string = [NSString stringWithFormat:@"%@ - didHandleOnloadEventsForFrame", [frame _drt_descriptionSuitableForTestResult]];
- printf ("%s\n", [string UTF8String]);
- }
- }
- - (void)webViewDidDisplayInsecureContent:(WebView *)sender
- {
- if (!done && gTestRunner->dumpFrameLoadCallbacks())
- printf ("didDisplayInsecureContent\n");
- }
- - (void)webView:(WebView *)sender didRunInsecureContent:(WebSecurityOrigin *)origin
- {
- if (!done && gTestRunner->dumpFrameLoadCallbacks())
- printf ("didRunInsecureContent\n");
- }
- - (void)webView:(WebView *)sender didDetectXSS:(NSURL *)insecureURL
- {
- if (!done && gTestRunner->dumpFrameLoadCallbacks())
- printf ("didDetectXSS\n");
- }
- - (void)webViewProgressFinishedNotification:(NSNotification *)notification
- {
- if (!done && gTestRunner->dumpProgressFinishedCallback())
- printf ("postProgressFinishedNotification\n");
- }
- @end
|