diff options
Diffstat (limited to 'WebKitTools/DumpRenderTree/mac')
8 files changed, 478 insertions, 78 deletions
diff --git a/WebKitTools/DumpRenderTree/mac/AccessibilityControllerMac.mm b/WebKitTools/DumpRenderTree/mac/AccessibilityControllerMac.mm index 4d2da6e..9d7edef 100644 --- a/WebKitTools/DumpRenderTree/mac/AccessibilityControllerMac.mm +++ b/WebKitTools/DumpRenderTree/mac/AccessibilityControllerMac.mm @@ -40,6 +40,12 @@ AccessibilityController::~AccessibilityController() { } +AccessibilityUIElement AccessibilityController::elementAtPoint(int x, int y) +{ + id accessibilityObject = [[[mainFrame frameView] documentView] accessibilityHitTest:NSMakePoint(x, y)]; + return AccessibilityUIElement(accessibilityObject); +} + AccessibilityUIElement AccessibilityController::focusedElement() { // FIXME: we could do some caching here. diff --git a/WebKitTools/DumpRenderTree/mac/AccessibilityUIElementMac.mm b/WebKitTools/DumpRenderTree/mac/AccessibilityUIElementMac.mm index e9361f2..a39dabb 100644 --- a/WebKitTools/DumpRenderTree/mac/AccessibilityUIElementMac.mm +++ b/WebKitTools/DumpRenderTree/mac/AccessibilityUIElementMac.mm @@ -57,32 +57,11 @@ typedef void (*AXPostedNotificationCallback)(id element, NSString* notification, @interface NSObject (WebKitAccessibilityAdditions) - (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount; -- (void)accessibilitySetPostedNotificationCallback:(AXPostedNotificationCallback)function withContext:(void*)context; +- (void)accessibilitySetShouldRepostNotifications:(BOOL)repost; - (NSUInteger)accessibilityIndexOfChild:(id)child; +- (NSUInteger)accessibilityArrayAttributeCount:(NSString *)attribute; @end -AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element) - : m_element(element) - , m_notificationFunctionCallback(0) -{ - [m_element retain]; -} - -AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other) - : m_element(other.m_element) - , m_notificationFunctionCallback(0) -{ - [m_element retain]; -} - -AccessibilityUIElement::~AccessibilityUIElement() -{ - // Make sure that our notification callback does not stick around. - if (m_notificationFunctionCallback) - [m_element accessibilitySetPostedNotificationCallback:0 withContext:0]; - [m_element release]; -} - @interface NSString (JSStringRefAdditions) + (NSString *)stringWithJSStringRef:(JSStringRef)jsStringRef; - (JSStringRef)createJSStringRef; @@ -106,6 +85,88 @@ AccessibilityUIElement::~AccessibilityUIElement() @end +@interface AccessibilityNotificationHandler : NSObject +{ + id m_platformElement; + JSObjectRef m_notificationFunctionCallback; +} + +@end + +@implementation AccessibilityNotificationHandler + +- (id)initWithPlatformElement:(id)platformElement +{ + self = [super init]; + + m_platformElement = platformElement; + + // Once an object starts requesting notifications, it's on for the duration of the program. + // This is to avoid any race conditions between tests turning this flag on and off. Instead + // AccessibilityNotificationHandler can just listen when they want to. + [m_platformElement accessibilitySetShouldRepostNotifications:YES]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_notificationReceived:) name:@"AXDRTNotification" object:nil]; + + return self; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + JSValueUnprotect([mainFrame globalContext], m_notificationFunctionCallback); + m_notificationFunctionCallback = 0; + + [super dealloc]; +} + +- (void)_notificationReceived:(NSNotification *)notification +{ + NSString *notificationName = [[notification userInfo] objectForKey:@"notificationName"]; + if (!notificationName) + return; + + JSRetainPtr<JSStringRef> jsNotification(Adopt, [notificationName createJSStringRef]); + JSValueRef argument = JSValueMakeString([mainFrame globalContext], jsNotification.get()); + JSObjectCallAsFunction([mainFrame globalContext], m_notificationFunctionCallback, 0, 1, &argument, 0); +} + +- (void)setCallback:(JSObjectRef)callback +{ + if (!callback) + return; + + // Release the old callback. + if (m_notificationFunctionCallback) + JSValueUnprotect([mainFrame globalContext], m_notificationFunctionCallback); + + m_notificationFunctionCallback = callback; + JSValueProtect([mainFrame globalContext], m_notificationFunctionCallback); +} + +@end + +AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element) + : m_element(element) + , m_notificationHandler(0) +{ + // FIXME: ap@webkit.org says ObjC objects need to be CFRetained/CFRelease to be GC-compliant on the mac. + [m_element retain]; +} + +AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other) + : m_element(other.m_element) + , m_notificationHandler(0) +{ + [m_element retain]; +} + +AccessibilityUIElement::~AccessibilityUIElement() +{ + // The notification handler should be nil because removeNotificationListener() should have been called in the test. + ASSERT(!m_notificationHandler); + [m_element release]; +} + static NSString* descriptionOfValue(id valueObject, id focusedAccessibilityObject) { if (!valueObject) @@ -439,6 +500,12 @@ JSStringRef AccessibilityUIElement::language() return concatenateAttributeAndValue(@"AXLanguage", description); } +JSStringRef AccessibilityUIElement::helpText() const +{ + id description = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityHelpAttribute], m_element); + return concatenateAttributeAndValue(@"AXHelp", description); +} + double AccessibilityUIElement::x() { NSValue* positionValue = [m_element accessibilityAttributeValue:NSAccessibilityPositionAttribute]; @@ -676,6 +743,16 @@ JSStringRef AccessibilityUIElement::attributesOfHeader() return descriptionOfElements(headerVector); } +int AccessibilityUIElement::rowCount() +{ + return [m_element accessibilityArrayAttributeCount:NSAccessibilityRowsAttribute]; +} + +int AccessibilityUIElement::columnCount() +{ + return [m_element accessibilityArrayAttributeCount:NSAccessibilityColumnsAttribute]; +} + int AccessibilityUIElement::indexInTable() { NSNumber* indexNumber = [m_element accessibilityAttributeValue:NSAccessibilityIndexAttribute]; @@ -736,6 +813,11 @@ void AccessibilityUIElement::showMenu() [m_element accessibilityPerformAction:NSAccessibilityShowMenuAction]; } +void AccessibilityUIElement::press() +{ + [m_element accessibilityPerformAction:NSAccessibilityPressAction]; +} + JSStringRef AccessibilityUIElement::accessibilityValue() const { // FIXME: implement @@ -758,28 +840,30 @@ JSStringRef AccessibilityUIElement::url() return [[url absoluteString] createJSStringRef]; } -static void _accessibilityNotificationCallback(id element, NSString* notification, void* context) -{ - if (!context) - return; - - JSObjectRef functionCallback = static_cast<JSObjectRef>(context); - - JSRetainPtr<JSStringRef> jsNotification(Adopt, [notification createJSStringRef]); - JSValueRef argument = JSValueMakeString([mainFrame globalContext], jsNotification.get()); - JSObjectCallAsFunction([mainFrame globalContext], functionCallback, NULL, 1, &argument, NULL); -} - bool AccessibilityUIElement::addNotificationListener(JSObjectRef functionCallback) { if (!functionCallback) return false; - m_notificationFunctionCallback = functionCallback; - [platformUIElement() accessibilitySetPostedNotificationCallback:_accessibilityNotificationCallback withContext:reinterpret_cast<void*>(m_notificationFunctionCallback)]; + // Mac programmers should not be adding more than one notification listener per element. + // Other platforms may be different. + if (m_notificationHandler) + return false; + m_notificationHandler = [[AccessibilityNotificationHandler alloc] initWithPlatformElement:platformUIElement()]; + [m_notificationHandler setCallback:functionCallback]; + return true; } +void AccessibilityUIElement::removeNotificationListener() +{ + // Mac programmers should not be trying to remove a listener that's already removed. + ASSERT(m_notificationHandler); + + [m_notificationHandler release]; + m_notificationHandler = nil; +} + bool AccessibilityUIElement::isSelectable() const { // FIXME: implement @@ -812,7 +896,9 @@ bool AccessibilityUIElement::isCollapsed() const bool AccessibilityUIElement::hasPopup() const { - // FIXME: implement + id value = [m_element accessibilityAttributeValue:@"AXHasPopup"]; + if ([value isKindOfClass:[NSNumber class]]) + return [value boolValue]; return false; } diff --git a/WebKitTools/DumpRenderTree/mac/Configurations/Base.xcconfig b/WebKitTools/DumpRenderTree/mac/Configurations/Base.xcconfig index a72dd7d..5f989e0 100644 --- a/WebKitTools/DumpRenderTree/mac/Configurations/Base.xcconfig +++ b/WebKitTools/DumpRenderTree/mac/Configurations/Base.xcconfig @@ -34,3 +34,35 @@ GCC_WARN_UNUSED_VARIABLE = YES GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO WARNING_CFLAGS = -Wall -W -Wno-unused-parameter LINKER_DISPLAYS_MANGLED_NAMES = YES; + + +TARGET_MAC_OS_X_VERSION_MAJOR = $(MAC_OS_X_VERSION_MAJOR); + + +// Use GCC 4.2 with Xcode 3.1, which includes GCC 4.2 but defaults to GCC 4.0. +// Note that Xcode versions as new as 3.1.2 use XCODE_VERSION_ACTUAL for the minor version +// number. Newer versions of Xcode use XCODE_VERSION_MINOR for the minor version, and +// XCODE_VERSION_ACTUAL for the full version number. +TARGET_GCC_VERSION = $(TARGET_GCC_VERSION_$(TARGET_MAC_OS_X_VERSION_MAJOR)); +TARGET_GCC_VERSION_ = $(TARGET_GCC_VERSION_1040); +TARGET_GCC_VERSION_1040 = GCC_40; +TARGET_GCC_VERSION_1050 = $(TARGET_GCC_VERSION_1050_$(XCODE_VERSION_MINOR)); +TARGET_GCC_VERSION_1050_ = $(TARGET_GCC_VERSION_1050_$(XCODE_VERSION_ACTUAL)); +TARGET_GCC_VERSION_1050_0310 = GCC_42; +TARGET_GCC_VERSION_1050_0320 = GCC_42; +TARGET_GCC_VERSION_1060 = GCC_42; +TARGET_GCC_VERSION_1070 = LLVM_GCC_42; + +GCC_VERSION = $(GCC_VERSION_$(TARGET_GCC_VERSION)); +GCC_VERSION_GCC_40 = 4.0; +GCC_VERSION_GCC_42 = 4.2; +GCC_VERSION_LLVM_GCC_42 = com.apple.compilers.llvmgcc42; + +// If the target Mac OS X version does not match the current Mac OS X version then we'll want to build using the target version's SDK. +SDKROOT = $(SDKROOT_$(MAC_OS_X_VERSION_MAJOR)_$(TARGET_MAC_OS_X_VERSION_MAJOR)); +SDKROOT_1050_1040 = macosx10.4; +SDKROOT_1060_1040 = macosx10.4; +SDKROOT_1060_1050 = macosx10.5; +SDKROOT_1070_1040 = macosx10.4; +SDKROOT_1070_1050 = macosx10.5; +SDKROOT_1070_1060 = macosx10.6; diff --git a/WebKitTools/DumpRenderTree/mac/Configurations/DebugRelease.xcconfig b/WebKitTools/DumpRenderTree/mac/Configurations/DebugRelease.xcconfig index 96a39a9..ab3278e 100644 --- a/WebKitTools/DumpRenderTree/mac/Configurations/DebugRelease.xcconfig +++ b/WebKitTools/DumpRenderTree/mac/Configurations/DebugRelease.xcconfig @@ -23,7 +23,7 @@ #include "Base.xcconfig" -ARCHS = $(ARCHS_$(MAC_OS_X_VERSION_MAJOR)); +ARCHS = $(ARCHS_$(TARGET_MAC_OS_X_VERSION_MAJOR)); ARCHS_ = $(ARCHS_1040); ARCHS_1040 = $(NATIVE_ARCH); ARCHS_1050 = $(NATIVE_ARCH); @@ -32,7 +32,7 @@ ARCHS_1070 = $(ARCHS_STANDARD_32_64_BIT); ONLY_ACTIVE_ARCH = YES; -MACOSX_DEPLOYMENT_TARGET = $(MACOSX_DEPLOYMENT_TARGET_$(MAC_OS_X_VERSION_MAJOR)) +MACOSX_DEPLOYMENT_TARGET = $(MACOSX_DEPLOYMENT_TARGET_$(TARGET_MAC_OS_X_VERSION_MAJOR)) MACOSX_DEPLOYMENT_TARGET_ = 10.4; MACOSX_DEPLOYMENT_TARGET_1040 = 10.4; MACOSX_DEPLOYMENT_TARGET_1050 = 10.5; diff --git a/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm b/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm index c7ddf21..0210cf0 100644 --- a/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm +++ b/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm @@ -76,15 +76,21 @@ #import <WebKit/WebTypesInternal.h> #import <WebKit/WebViewPrivate.h> #import <getopt.h> -#import <mach-o/getsect.h> #import <objc/objc-runtime.h> #import <wtf/Assertions.h> #import <wtf/RetainPtr.h> #import <wtf/Threading.h> #import <wtf/OwnPtr.h> +extern "C" { +#import <mach-o/getsect.h> +} + using namespace std; +@interface DumpRenderTreeApplication : NSApplication +@end + @interface DumpRenderTreeEvent : NSEvent @end @@ -246,6 +252,7 @@ static void activateFonts() static const char* fontFileNames[] = { "AHEM____.TTF", + "ColorBits.ttf", "WebKitWeightWatcher100.ttf", "WebKitWeightWatcher200.ttf", "WebKitWeightWatcher300.ttf", @@ -355,7 +362,14 @@ void testStringByEvaluatingJavaScriptFromString() static NSString *libraryPathForDumpRenderTree() { - return [@"~/Library/Application Support/DumpRenderTree" stringByExpandingTildeInPath]; + //FIXME: This may not be sufficient to prevent interactions/crashes + //when running more than one copy of DumpRenderTree. + //See https://bugs.webkit.org/show_bug.cgi?id=10906 + char* dumpRenderTreeTemp = getenv("DUMPRENDERTREE_TEMP"); + if (dumpRenderTreeTemp) + return [[NSFileManager defaultManager] stringWithFileSystemRepresentation:dumpRenderTreeTemp length:strlen(dumpRenderTreeTemp)]; + else + return [@"~/Library/Application Support/DumpRenderTree" stringByExpandingTildeInPath]; } // Called before each test. @@ -420,7 +434,7 @@ static void resetDefaultsToConsistentValues() [preferences setOfflineWebApplicationCacheEnabled:YES]; [preferences setDeveloperExtrasEnabled:NO]; [preferences setLoadsImagesAutomatically:YES]; - [preferences setFrameSetFlatteningEnabled:NO]; + [preferences setFrameFlatteningEnabled:NO]; if (persistentUserStyleSheetLocation) { [preferences setUserStyleSheetLocation:[NSURL URLWithString:(NSString *)(persistentUserStyleSheetLocation.get())]]; [preferences setUserStyleSheetEnabled:YES]; @@ -430,20 +444,8 @@ static void resetDefaultsToConsistentValues() // The back/forward cache is causing problems due to layouts during transition from one page to another. // So, turn it off for now, but we might want to turn it back on some day. [preferences setUsesPageCache:NO]; - -#if defined(BUILDING_ON_LEOPARD) - // Disable hardware composititing to avoid timeouts and crashes from buggy CoreVideo teardown code. - // https://bugs.webkit.org/show_bug.cgi?id=28845 and rdar://problem/7228836 - SInt32 qtVersion; - OSErr err = Gestalt(gestaltQuickTimeVersion, &qtVersion); - assert(err == noErr); - // Bug 7228836 exists in at least 7.6.3 through 7.6.4, hopefully it will be fixed in 7.6.5. - // FIXME: Once we know the exact versions of QuickTime affected, we can update this check. - if (qtVersion <= 0x07648000) // 7.6.4, final release (0x8). See http://developer.apple.com/mac/library/techn - [preferences setAcceleratedCompositingEnabled:NO]; - else -#endif - [preferences setAcceleratedCompositingEnabled:YES]; + [preferences setAcceleratedCompositingEnabled:YES]; + [preferences setWebGLEnabled:NO]; [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain]; @@ -686,7 +688,7 @@ void dumpRenderTree(int argc, const char *argv[]) int main(int argc, const char *argv[]) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - [NSApplication sharedApplication]; // Force AppKit to init itself + [DumpRenderTreeApplication sharedApplication]; // Force AppKit to init itself dumpRenderTree(argc, argv); [WebCoreStatistics garbageCollectJavaScriptObjects]; [WebCoreStatistics emptyCache]; // Otherwise SVGImages trigger false positives for Frame/Node counts @@ -1139,9 +1141,15 @@ static bool shouldOpenWebInspector(const char* pathOrURL) return strstr(pathOrURL, "inspector/"); } +static bool shouldEnableDeveloperExtras(const char* pathOrURL) +{ + return shouldOpenWebInspector(pathOrURL) || strstr(pathOrURL, "inspector-enabled/"); +} + static void resetWebViewToConsistentStateBeforeTesting() { WebView *webView = [mainFrame webView]; + [webView setEditable:NO]; [(EditingDelegate *)[webView editingDelegate] setAcceptsEditing:YES]; [webView makeTextStandardSize:nil]; [webView resetPageZoom:nil]; @@ -1162,7 +1170,7 @@ static void resetWebViewToConsistentStateBeforeTesting() [[[mainFrame webView] inspector] setJavaScriptProfilingEnabled:NO]; [WebView _setUsesTestModeFocusRingColor:YES]; - [WebView _resetOriginAccessWhiteLists]; + [WebView _resetOriginAccessWhitelists]; } static void runTest(const string& testPathOrURL) @@ -1217,8 +1225,11 @@ static void runTest(const string& testPathOrURL) else [[mainFrame webView] setHistoryDelegate:nil]; - if (shouldOpenWebInspector(pathOrURL.c_str())) - gLayoutTestController->showWebInspector(); + if (shouldEnableDeveloperExtras(pathOrURL.c_str())) { + gLayoutTestController->setDeveloperExtrasEnabled(true); + if (shouldOpenWebInspector(pathOrURL.c_str())) + gLayoutTestController->showWebInspector(); + } if ([WebHistory optionalSharedHistory]) [WebHistory setOptionalSharedHistory:nil]; @@ -1238,9 +1249,10 @@ static void runTest(const string& testPathOrURL) NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [mainFrame loadRequest:[NSURLRequest requestWithURL:url]]; [pool release]; + while (!done) { pool = [[NSAutoreleasePool alloc] init]; - [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantPast]]; + [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantPast]]; [pool release]; } @@ -1268,7 +1280,8 @@ static void runTest(const string& testPathOrURL) } } - if (shouldOpenWebInspector(pathOrURL.c_str())) + // If developer extras enabled Web Inspector may have been open by the test. + if (shouldEnableDeveloperExtras(pathOrURL.c_str())) gLayoutTestController->closeWebInspector(); resetWebViewToConsistentStateBeforeTesting(); @@ -1307,3 +1320,13 @@ void displayWebView() } @end + +@implementation DumpRenderTreeApplication + +- (BOOL)isRunning +{ + // <rdar://problem/7686123> Java plug-in freezes unless NSApplication is running + return YES; +} + +@end diff --git a/WebKitTools/DumpRenderTree/mac/EventSendingController.mm b/WebKitTools/DumpRenderTree/mac/EventSendingController.mm index feaeddc..8c5cebf 100644 --- a/WebKitTools/DumpRenderTree/mac/EventSendingController.mm +++ b/WebKitTools/DumpRenderTree/mac/EventSendingController.mm @@ -134,7 +134,9 @@ BOOL replayingSavedEvents; || aSelector == @selector(textZoomIn) || aSelector == @selector(textZoomOut) || aSelector == @selector(zoomPageIn) - || aSelector == @selector(zoomPageOut)) + || aSelector == @selector(zoomPageOut) + || aSelector == @selector(mouseScrollByX:andY:) + || aSelector == @selector(continuousMouseScrollByX:andY:)) return NO; return YES; } @@ -166,6 +168,10 @@ BOOL replayingSavedEvents; return @"mouseMoveTo"; if (aSelector == @selector(setDragMode:)) return @"setDragMode"; + if (aSelector == @selector(mouseScrollByX:andY:)) + return @"mouseScrollBy"; + if (aSelector == @selector(continuousMouseScrollByX:andY:)) + return @"continuousMouseScrollBy"; return nil; } @@ -453,6 +459,39 @@ static int buildModifierFlags(const WebScriptObject* modifiers) } } +- (void)mouseScrollByX:(int)x andY:(int)y continuously:(BOOL)c +{ + // CGEventCreateScrollWheelEvent() was introduced in 10.5 +#if !defined(BUILDING_ON_TIGER) + CGScrollEventUnit unit = c?kCGScrollEventUnitPixel:kCGScrollEventUnitLine; + CGEventRef cgScrollEvent = CGEventCreateScrollWheelEvent(NULL, unit, 2, y, x); + + // CGEvent locations are in global display coordinates. + CGPoint lastGlobalMousePosition = { + lastMousePosition.x, + [[NSScreen mainScreen] frame].size.height - lastMousePosition.y + }; + CGEventSetLocation(cgScrollEvent, lastGlobalMousePosition); + + NSEvent *scrollEvent = [NSEvent eventWithCGEvent:cgScrollEvent]; + CFRelease(cgScrollEvent); + + NSView *subView = [[mainFrame webView] hitTest:[scrollEvent locationInWindow]]; + if (subView) + [subView scrollWheel:scrollEvent]; +#endif +} + +- (void)continuousMouseScrollByX:(int)x andY:(int)y +{ + [self mouseScrollByX:x andY:y continuously:YES]; +} + +- (void)mouseScrollByX:(int)x andY:(int)y +{ + [self mouseScrollByX:x andY:y continuously:NO]; +} + - (void)contextClick { [[[mainFrame frameView] documentView] layout]; @@ -507,33 +546,43 @@ static int buildModifierFlags(const WebScriptObject* modifiers) - (void)keyDown:(NSString *)character withModifiers:(WebScriptObject *)modifiers withLocation:(unsigned long)keyLocation { NSString *eventCharacter = character; + unsigned short keyCode = 0; if ([character isEqualToString:@"leftArrow"]) { const unichar ch = NSLeftArrowFunctionKey; eventCharacter = [NSString stringWithCharacters:&ch length:1]; + keyCode = 0x7B; } else if ([character isEqualToString:@"rightArrow"]) { const unichar ch = NSRightArrowFunctionKey; eventCharacter = [NSString stringWithCharacters:&ch length:1]; + keyCode = 0x7C; } else if ([character isEqualToString:@"upArrow"]) { const unichar ch = NSUpArrowFunctionKey; eventCharacter = [NSString stringWithCharacters:&ch length:1]; + keyCode = 0x7E; } else if ([character isEqualToString:@"downArrow"]) { const unichar ch = NSDownArrowFunctionKey; eventCharacter = [NSString stringWithCharacters:&ch length:1]; + keyCode = 0x7D; } else if ([character isEqualToString:@"pageUp"]) { const unichar ch = NSPageUpFunctionKey; eventCharacter = [NSString stringWithCharacters:&ch length:1]; + keyCode = 0x74; } else if ([character isEqualToString:@"pageDown"]) { const unichar ch = NSPageDownFunctionKey; eventCharacter = [NSString stringWithCharacters:&ch length:1]; + keyCode = 0x79; } else if ([character isEqualToString:@"home"]) { const unichar ch = NSHomeFunctionKey; eventCharacter = [NSString stringWithCharacters:&ch length:1]; + keyCode = 0x73; } else if ([character isEqualToString:@"end"]) { const unichar ch = NSEndFunctionKey; eventCharacter = [NSString stringWithCharacters:&ch length:1]; + keyCode = 0x77; } else if ([character isEqualToString:@"delete"]) { const unichar ch = 0x7f; eventCharacter = [NSString stringWithCharacters:&ch length:1]; + keyCode = 0x75; } // Compare the input string with the function-key names defined by the DOM spec (i.e. "F1",...,"F24"). @@ -542,9 +591,59 @@ static int buildModifierFlags(const WebScriptObject* modifiers) if ([character isEqualToString:[NSString stringWithFormat:@"F%u", i]]) { const unichar ch = NSF1FunctionKey + (i - 1); eventCharacter = [NSString stringWithCharacters:&ch length:1]; + switch (i) { + case 1: keyCode = 0x7A; break; + case 2: keyCode = 0x78; break; + case 3: keyCode = 0x63; break; + case 4: keyCode = 0x76; break; + case 5: keyCode = 0x60; break; + case 6: keyCode = 0x61; break; + case 7: keyCode = 0x62; break; + case 8: keyCode = 0x64; break; + case 9: keyCode = 0x65; break; + case 10: keyCode = 0x6D; break; + case 11: keyCode = 0x67; break; + case 12: keyCode = 0x6F; break; + case 13: keyCode = 0x69; break; + case 14: keyCode = 0x6B; break; + case 15: keyCode = 0x71; break; + case 16: keyCode = 0x6A; break; + case 17: keyCode = 0x40; break; + case 18: keyCode = 0x4F; break; + case 19: keyCode = 0x50; break; + case 20: keyCode = 0x5A; break; + } } } + // FIXME: No keyCode is set for most keys. + if ([character isEqualToString:@"\t"]) + keyCode = 0x30; + else if ([character isEqualToString:@" "]) + keyCode = 0x31; + else if ([character isEqualToString:@"\r"]) + keyCode = 0x24; + else if ([character isEqualToString:@"\n"]) + keyCode = 0x4C; + else if ([character isEqualToString:@"\x8"]) + keyCode = 0x33; + else if ([character isEqualToString:@"7"]) + keyCode = 0x1A; + else if ([character isEqualToString:@"5"]) + keyCode = 0x17; + else if ([character isEqualToString:@"9"]) + keyCode = 0x19; + else if ([character isEqualToString:@"0"]) + keyCode = 0x1D; + else if ([character isEqualToString:@"a"]) + keyCode = 0x00; + else if ([character isEqualToString:@"b"]) + keyCode = 0x0B; + else if ([character isEqualToString:@"d"]) + keyCode = 0x02; + else if ([character isEqualToString:@"e"]) + keyCode = 0x0E; + NSString *charactersIgnoringModifiers = eventCharacter; int modifierFlags = 0; @@ -570,7 +669,7 @@ static int buildModifierFlags(const WebScriptObject* modifiers) characters:eventCharacter charactersIgnoringModifiers:charactersIgnoringModifiers isARepeat:NO - keyCode:0]; + keyCode:keyCode]; [[[[mainFrame webView] window] firstResponder] keyDown:event]; @@ -583,7 +682,7 @@ static int buildModifierFlags(const WebScriptObject* modifiers) characters:eventCharacter charactersIgnoringModifiers:charactersIgnoringModifiers isARepeat:NO - keyCode:0]; + keyCode:keyCode]; [[[[mainFrame webView] window] firstResponder] keyUp:event]; } diff --git a/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm b/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm index 66ba5f0..e62e411 100644 --- a/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm +++ b/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm @@ -115,6 +115,11 @@ void LayoutTestController::addDisallowedURL(JSStringRef url) CFSetAddValue(disallowedURLs, [request URL]); } +bool LayoutTestController::callShouldCloseOnWebView() +{ + return [[mainFrame webView] shouldClose]; +} + void LayoutTestController::clearAllDatabases() { [[WebDatabaseManager sharedWebDatabaseManager] deleteAllDatabases]; @@ -176,6 +181,23 @@ void LayoutTestController::keepWebHistory() } } +JSValueRef LayoutTestController::computedStyleIncludingVisitedInfo(JSContextRef context, JSValueRef value) +{ + return [[mainFrame webView] _computedStyleIncludingVisitedInfo:context forElement:value]; +} + +JSRetainPtr<JSStringRef> LayoutTestController::layerTreeAsText() const +{ + JSRetainPtr<JSStringRef> string(Adopt, JSStringCreateWithCFString((CFStringRef)[mainFrame _layerTreeAsText])); + return string; +} + +JSRetainPtr<JSStringRef> LayoutTestController::markerTextForListItem(JSContextRef context, JSValueRef nodeObject) const +{ + // FIXME: Implement me. + return JSRetainPtr<JSStringRef>(); +} + int LayoutTestController::pageNumberForElementById(JSStringRef id, float pageWidthInPixels, float pageHeightInPixels) { RetainPtr<CFStringRef> idCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, id)); @@ -302,7 +324,7 @@ void LayoutTestController::setIconDatabaseEnabled(bool iconDatabaseEnabled) void LayoutTestController::setJavaScriptProfilingEnabled(bool profilingEnabled) { - [[[mainFrame webView] preferences] setDeveloperExtrasEnabled:profilingEnabled]; + setDeveloperExtrasEnabled(profilingEnabled); [[[mainFrame webView] inspector] setJavaScriptProfilingEnabled:profilingEnabled]; } @@ -324,9 +346,14 @@ void LayoutTestController::setXSSAuditorEnabled(bool enabled) [[[mainFrame webView] preferences] setXSSAuditorEnabled:enabled]; } -void LayoutTestController::setFrameSetFlatteningEnabled(bool enabled) +void LayoutTestController::setFrameFlatteningEnabled(bool enabled) { - [[[mainFrame webView] preferences] setFrameSetFlatteningEnabled:enabled]; + [[[mainFrame webView] preferences] setFrameFlatteningEnabled:enabled]; +} + +void LayoutTestController::setSpatialNavigationEnabled(bool enabled) +{ + // FIXME: Implement for SpatialNavigation layout tests. } void LayoutTestController::setAllowUniversalAccessFromFileURLs(bool enabled) @@ -424,7 +451,7 @@ void LayoutTestController::setSelectTrailingWhitespaceEnabled(bool flag) [[mainFrame webView] setSelectTrailingWhitespaceEnabled:flag]; } -static const CFTimeInterval waitToDumpWatchdogInterval = 15.0; +static const CFTimeInterval waitToDumpWatchdogInterval = 30.0; static void waitUntilDoneWatchdogFired(CFRunLoopTimerRef timer, void* info) { @@ -541,7 +568,7 @@ void LayoutTestController::waitForPolicyDelegate() [[mainFrame webView] setPolicyDelegate:policyDelegate]; } -void LayoutTestController::whiteListAccessFromOrigin(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains) +void LayoutTestController::addOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains) { RetainPtr<CFStringRef> sourceOriginCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, sourceOrigin)); NSString *sourceOriginNS = (NSString *)sourceOriginCF.get(); @@ -549,7 +576,23 @@ void LayoutTestController::whiteListAccessFromOrigin(JSStringRef sourceOrigin, J NSString *destinationProtocolNS = (NSString *)protocolCF.get(); RetainPtr<CFStringRef> hostCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, destinationHost)); NSString *destinationHostNS = (NSString *)hostCF.get(); - [WebView _whiteListAccessFromOrigin:sourceOriginNS destinationProtocol:destinationProtocolNS destinationHost:destinationHostNS allowDestinationSubdomains:allowDestinationSubdomains]; + [WebView _addOriginAccessWhitelistEntryWithSourceOrigin:sourceOriginNS destinationProtocol:destinationProtocolNS destinationHost:destinationHostNS allowDestinationSubdomains:allowDestinationSubdomains]; +} + +void LayoutTestController::removeOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains) +{ + RetainPtr<CFStringRef> sourceOriginCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, sourceOrigin)); + NSString *sourceOriginNS = (NSString *)sourceOriginCF.get(); + RetainPtr<CFStringRef> protocolCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, destinationProtocol)); + NSString *destinationProtocolNS = (NSString *)protocolCF.get(); + RetainPtr<CFStringRef> hostCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, destinationHost)); + NSString *destinationHostNS = (NSString *)hostCF.get(); + [WebView _removeOriginAccessWhitelistEntryWithSourceOrigin:sourceOriginNS destinationProtocol:destinationProtocolNS destinationHost:destinationHostNS allowDestinationSubdomains:allowDestinationSubdomains]; +} + +void LayoutTestController::setScrollbarPolicy(JSStringRef orientation, JSStringRef policy) +{ + // FIXME: implement } void LayoutTestController::addUserScript(JSStringRef source, bool runAtStart) @@ -566,16 +609,19 @@ void LayoutTestController::addUserStyleSheet(JSStringRef source) [WebView _addUserStyleSheetToGroup:@"org.webkit.DumpRenderTree" world:[WebScriptWorld world] source:sourceNS url:nil whitelist:nil blacklist:nil]; } +void LayoutTestController::setDeveloperExtrasEnabled(bool enabled) +{ + [[[mainFrame webView] preferences] setDeveloperExtrasEnabled:enabled]; +} + void LayoutTestController::showWebInspector() { - [[[mainFrame webView] preferences] setDeveloperExtrasEnabled:true]; [[[mainFrame webView] inspector] show:nil]; } void LayoutTestController::closeWebInspector() { [[[mainFrame webView] inspector] close:nil]; - [[[mainFrame webView] preferences] setDeveloperExtrasEnabled:false]; } void LayoutTestController::evaluateInWebInspector(long callId, JSStringRef script) @@ -686,3 +732,101 @@ void LayoutTestController::apiTestNewWindowDataLoadBaseURL(JSStringRef utf8Data, [delegate release]; [pool release]; } + +void LayoutTestController::apiTestGoToCurrentBackForwardItem() +{ + WebView *view = [mainFrame webView]; + [view goToBackForwardItem:[[view backForwardList] currentItem]]; +} + +void LayoutTestController::setWebViewEditable(bool editable) +{ + WebView *view = [mainFrame webView]; + [view setEditable:editable]; +} + +#ifndef BUILDING_ON_TIGER +static NSString *SynchronousLoaderRunLoopMode = @"DumpRenderTreeSynchronousLoaderRunLoopMode"; + +@interface SynchronousLoader : NSObject +{ + NSString *m_username; + NSString *m_password; + BOOL m_isDone; +} ++ (void)makeRequest:(NSURLRequest *)request withUsername:(NSString *)username password:(NSString *)password; +@end + +@implementation SynchronousLoader : NSObject +- (void)dealloc +{ + [m_username release]; + [m_password release]; + + [super dealloc]; +} + +- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection +{ + return YES; +} + +- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge +{ + if ([challenge previousFailureCount] == 0) { + NSURLCredential *credential = [[NSURLCredential alloc] initWithUser:m_username password:m_password persistence:NSURLCredentialPersistenceForSession]; + [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; + return; + } + [[challenge sender] cancelAuthenticationChallenge:challenge]; +} + +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error +{ + printf("SynchronousLoader failed: %s\n", [[error description] UTF8String]); + m_isDone = YES; +} + +- (void)connectionDidFinishLoading:(NSURLConnection *)connection +{ + m_isDone = YES; +} + ++ (void)makeRequest:(NSURLRequest *)request withUsername:(NSString *)username password:(NSString *)password +{ + ASSERT(![[request URL] user]); + ASSERT(![[request URL] password]); + + SynchronousLoader *delegate = [[SynchronousLoader alloc] init]; + delegate->m_username = [username copy]; + delegate->m_password = [password copy]; + + NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate startImmediately:NO]; + [connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:SynchronousLoaderRunLoopMode]; + [connection start]; + + while (!delegate->m_isDone) + [[NSRunLoop currentRunLoop] runMode:SynchronousLoaderRunLoopMode beforeDate:[NSDate distantFuture]]; + + [connection cancel]; + + [connection release]; + [delegate release]; +} + +@end +#endif + +void LayoutTestController::authenticateSession(JSStringRef url, JSStringRef username, JSStringRef password) +{ + // See <rdar://problem/7880699>. +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) + RetainPtr<CFStringRef> urlStringCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, url)); + RetainPtr<CFStringRef> usernameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, username)); + RetainPtr<CFStringRef> passwordCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, password)); + + NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:(NSString *)urlStringCF.get()]]; + + [SynchronousLoader makeRequest:request withUsername:(NSString *)usernameCF.get() password:(NSString *)passwordCF.get()]; +#endif +} diff --git a/WebKitTools/DumpRenderTree/mac/ResourceLoadDelegate.mm b/WebKitTools/DumpRenderTree/mac/ResourceLoadDelegate.mm index 6f82e01..9244110 100644 --- a/WebKitTools/DumpRenderTree/mac/ResourceLoadDelegate.mm +++ b/WebKitTools/DumpRenderTree/mac/ResourceLoadDelegate.mm @@ -35,6 +35,8 @@ #import <WebKit/WebTypesInternal.h> #import <wtf/Assertions.h> +using namespace std; + @interface NSURL (DRTExtras) - (NSString *)_drt_descriptionSuitableForTestResult; @end @@ -121,10 +123,10 @@ return @"<unknown>"; } --(NSURLRequest *)webView: (WebView *)wv resource:identifier willSendRequest: (NSURLRequest *)newRequest redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)dataSource +-(NSURLRequest *)webView: (WebView *)wv resource:identifier willSendRequest: (NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)dataSource { if (!done && gLayoutTestController->dumpResourceLoadCallbacks()) { - NSString *string = [NSString stringWithFormat:@"%@ - willSendRequest %@ redirectResponse %@", identifier, [newRequest _drt_descriptionSuitableForTestResult], + NSString *string = [NSString stringWithFormat:@"%@ - willSendRequest %@ redirectResponse %@", identifier, [request _drt_descriptionSuitableForTestResult], [redirectResponse _drt_descriptionSuitableForTestResult]]; printf("%s\n", [string UTF8String]); } @@ -137,7 +139,7 @@ return nil; } - NSURL *url = [newRequest URL]; + NSURL *url = [request URL]; NSString *host = [url host]; if (host && (NSOrderedSame == [[url scheme] caseInsensitiveCompare:@"http"] || NSOrderedSame == [[url scheme] caseInsensitiveCompare:@"https"]) @@ -151,7 +153,15 @@ if (disallowedURLs && CFSetContainsValue(disallowedURLs, url)) return nil; - return newRequest; + NSMutableURLRequest *newRequest = [request mutableCopy]; + const set<string>& clearHeaders = gLayoutTestController->willSendRequestClearHeaders(); + for (set<string>::const_iterator header = clearHeaders.begin(); header != clearHeaders.end(); ++header) { + NSString *nsHeader = [[NSString alloc] initWithUTF8String:header->c_str()]; + [newRequest setValue:nil forHTTPHeaderField:nsHeader]; + [nsHeader release]; + } + + return [newRequest autorelease]; } - (void)webView:(WebView *)wv resource:(id)identifier didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource |