diff options
Diffstat (limited to 'WebKitTools/DumpRenderTree/mac')
21 files changed, 1264 insertions, 313 deletions
diff --git a/WebKitTools/DumpRenderTree/mac/AccessibilityControllerMac.mm b/WebKitTools/DumpRenderTree/mac/AccessibilityControllerMac.mm new file mode 100644 index 0000000..482c4f3 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/AccessibilityControllerMac.mm @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2008 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR + * 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 "DumpRenderTree.h" +#import "AccessibilityController.h" + +#import "AccessibilityUIElement.h" +#import <Foundation/Foundation.h> +#import <WebKit/WebFrame.h> +#import <WebKit/WebHTMLView.h> + +AccessibilityController::AccessibilityController() +{ +} + +AccessibilityController::~AccessibilityController() +{ +} + +AccessibilityUIElement AccessibilityController::focusedElement() +{ + // FIXME: we could do some caching here. + id accessibilityObject = [[[mainFrame frameView] documentView] accessibilityFocusedUIElement]; + return AccessibilityUIElement(accessibilityObject); +} + +AccessibilityUIElement AccessibilityController::rootElement() +{ + // FIXME: we could do some caching here. + id accessibilityObject = [[mainFrame frameView] documentView]; + return AccessibilityUIElement(accessibilityObject); +} diff --git a/WebKitTools/DumpRenderTree/mac/AccessibilityUIElementMac.mm b/WebKitTools/DumpRenderTree/mac/AccessibilityUIElementMac.mm new file mode 100644 index 0000000..81edd99 --- /dev/null +++ b/WebKitTools/DumpRenderTree/mac/AccessibilityUIElementMac.mm @@ -0,0 +1,425 @@ +/* + * Copyright (C) 2008 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR + * 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 "DumpRenderTree.h" +#import "AccessibilityUIElement.h" + +#import <Foundation/Foundation.h> +#import <JavaScriptCore/JSStringRef.h> +#import <JavaScriptCore/JSStringRefCF.h> +#import <WebKit/WebFrame.h> +#import <WebKit/WebHTMLView.h> +#import <WebKit/WebTypesInternal.h> +#import <wtf/RetainPtr.h> +#import <wtf/Vector.h> + +AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element) + : m_element(element) +{ + [m_element retain]; +} + +AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other) + : m_element(other.m_element) +{ + [m_element retain]; +} + +AccessibilityUIElement::~AccessibilityUIElement() +{ + [m_element release]; +} + +@interface NSString (JSStringRefAdditions) +- (JSStringRef)createJSStringRef; +@end + +@implementation NSString (JSStringRefAdditions) + +- (JSStringRef)createJSStringRef +{ + return JSStringCreateWithCFString((CFStringRef)self); +} + +@end + +static NSString* descriptionOfValue(id valueObject, id focusedAccessibilityObject) +{ + if (!valueObject) + return NULL; + + if ([valueObject isKindOfClass:[NSArray class]]) + return [NSString stringWithFormat:@"<array of size %d>", [(NSArray*)valueObject count]]; + + if ([valueObject isKindOfClass:[NSNumber class]]) + return [(NSNumber*)valueObject stringValue]; + + if ([valueObject isKindOfClass:[NSValue class]]) { + NSString* type = [NSString stringWithCString:[valueObject objCType] encoding:NSASCIIStringEncoding]; + NSValue* value = (NSValue*)valueObject; + if ([type rangeOfString:@"NSRect"].length > 0) + return [NSString stringWithFormat:@"NSRect: %@", NSStringFromRect([value rectValue])]; + if ([type rangeOfString:@"NSPoint"].length > 0) + return [NSString stringWithFormat:@"NSPoint: %@", NSStringFromPoint([value pointValue])]; + if ([type rangeOfString:@"NSSize"].length > 0) + return [NSString stringWithFormat:@"NSSize: %@", NSStringFromSize([value sizeValue])]; + if ([type rangeOfString:@"NSRange"].length > 0) + return [NSString stringWithFormat:@"NSRange: %@", NSStringFromRange([value rangeValue])]; + } + + // Strip absolute URL paths + NSString* description = [valueObject description]; + NSRange range = [description rangeOfString:@"LayoutTests"]; + if (range.length) + return [description substringFromIndex:range.location]; + + // Strip pointer locations + if ([description rangeOfString:@"0x"].length) { + NSString* role = [focusedAccessibilityObject accessibilityAttributeValue:@"AXRole"]; + NSString* title = [focusedAccessibilityObject accessibilityAttributeValue:@"AXTitle"]; + if ([title length]) + return [NSString stringWithFormat:@"<%@: '%@'>", role, title]; + return [NSString stringWithFormat:@"<%@>", role]; + } + + return [valueObject description]; +} + +static NSString* attributesOfElement(id accessibilityObject) +{ + NSArray* supportedAttributes = [accessibilityObject accessibilityAttributeNames]; + + NSMutableString* attributesString = [NSMutableString string]; + for (NSUInteger i = 0; i < [supportedAttributes count]; ++i) { + NSString* attribute = [supportedAttributes objectAtIndex:i]; + + // Right now, position provides useless and screen-specific information, so we do not + // want to include it for the sake of universally passing tests. + if ([attribute isEqualToString:@"AXPosition"]) + continue; + + id valueObject = [accessibilityObject accessibilityAttributeValue:attribute]; + NSString* value = descriptionOfValue(valueObject, accessibilityObject); + [attributesString appendFormat:@"%@: %@\n", attribute, value]; + } + + return attributesString; +} + +static JSStringRef concatenateAttributeAndValue(NSString* attribute, NSString* value) +{ + Vector<UniChar> buffer([attribute length]); + [attribute getCharacters:buffer.data()]; + buffer.append(':'); + buffer.append(' '); + + Vector<UniChar> valueBuffer([value length]); + [value getCharacters:valueBuffer.data()]; + buffer.append(valueBuffer); + + return JSStringCreateWithCharacters(buffer.data(), buffer.size()); +} + +static void convertNSArrayToVector(NSArray* array, Vector<AccessibilityUIElement>& elementVector) +{ + NSUInteger count = [array count]; + for (NSUInteger i = 0; i < count; ++i) + elementVector.append(AccessibilityUIElement([array objectAtIndex:i])); +} + +static JSStringRef descriptionOfElements(Vector<AccessibilityUIElement>& elementVector) +{ + NSMutableString* allElementString = [NSMutableString string]; + size_t size = elementVector.size(); + for (size_t i = 0; i < size; ++i) { + NSString* attributes = attributesOfElement(elementVector[i].platformUIElement()); + [allElementString appendFormat:@"%@\n------------\n", attributes]; + } + + return [allElementString createJSStringRef]; +} + +void AccessibilityUIElement::getLinkedUIElements(Vector<AccessibilityUIElement>& elementVector) +{ + NSArray* linkedElements = [m_element accessibilityAttributeValue:NSAccessibilityLinkedUIElementsAttribute]; + convertNSArrayToVector(linkedElements, elementVector); +} + +void AccessibilityUIElement::getDocumentLinks(Vector<AccessibilityUIElement>& elementVector) +{ + NSArray* linkElements = [m_element accessibilityAttributeValue:@"AXLinkUIElements"]; + convertNSArrayToVector(linkElements, elementVector); +} + +void AccessibilityUIElement::getChildren(Vector<AccessibilityUIElement>& elementVector) +{ + NSArray* children = [m_element accessibilityAttributeValue:NSAccessibilityChildrenAttribute]; + convertNSArrayToVector(children, elementVector); +} + +AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index) +{ + Vector<AccessibilityUIElement> children; + getChildren(children); + + if (index < children.size()) + return children[index]; + return nil; +} + +AccessibilityUIElement AccessibilityUIElement::titleUIElement() +{ + id accessibilityObject = [m_element accessibilityAttributeValue:NSAccessibilityTitleUIElementAttribute]; + if (accessibilityObject) + return AccessibilityUIElement(accessibilityObject); + + return nil; +} + +JSStringRef AccessibilityUIElement::attributesOfLinkedUIElements() +{ + Vector<AccessibilityUIElement> linkedElements; + getLinkedUIElements(linkedElements); + return descriptionOfElements(linkedElements); +} + +JSStringRef AccessibilityUIElement::attributesOfDocumentLinks() +{ + Vector<AccessibilityUIElement> linkElements; + getDocumentLinks(linkElements); + return descriptionOfElements(linkElements); +} + +JSStringRef AccessibilityUIElement::attributesOfChildren() +{ + Vector<AccessibilityUIElement> children; + getChildren(children); + return descriptionOfElements(children); +} + +JSStringRef AccessibilityUIElement::allAttributes() +{ + NSString* attributes = attributesOfElement(m_element); + return [attributes createJSStringRef]; +} + +JSStringRef AccessibilityUIElement::parameterizedAttributeNames() +{ + NSArray* supportedParameterizedAttributes = [m_element accessibilityParameterizedAttributeNames]; + + NSMutableString* attributesString = [NSMutableString string]; + for (NSUInteger i = 0; i < [supportedParameterizedAttributes count]; ++i) { + [attributesString appendFormat:@"%@\n", [supportedParameterizedAttributes objectAtIndex:i]]; + } + + return [attributesString createJSStringRef]; +} + +JSStringRef AccessibilityUIElement::role() +{ + NSString* role = descriptionOfValue([m_element accessibilityAttributeValue:@"AXRole"], m_element); + return concatenateAttributeAndValue(@"AXRole", role); +} + +JSStringRef AccessibilityUIElement::title() +{ + NSString* title = descriptionOfValue([m_element accessibilityAttributeValue:@"AXTitle"], m_element); + return concatenateAttributeAndValue(@"AXTitle", title); +} + +JSStringRef AccessibilityUIElement::description() +{ + id description = descriptionOfValue([m_element accessibilityAttributeValue:@"AXDescription"], m_element); + return concatenateAttributeAndValue(@"AXDescription", description); +} + +double AccessibilityUIElement::width() +{ + NSValue* sizeValue = [m_element accessibilityAttributeValue:@"AXSize"]; + return static_cast<double>([sizeValue sizeValue].width); +} + +double AccessibilityUIElement::height() +{ + NSValue* sizeValue = [m_element accessibilityAttributeValue:@"AXSize"]; + return static_cast<double>([sizeValue sizeValue].height); +} + +double AccessibilityUIElement::intValue() +{ + id value = [m_element accessibilityAttributeValue:@"AXValue"]; + if ([value isKindOfClass:[NSNumber class]]) + return [(NSNumber*)value doubleValue]; + return 0.0f; +} + +double AccessibilityUIElement::minValue() +{ + id value = [m_element accessibilityAttributeValue:@"AXMinValue"]; + if ([value isKindOfClass:[NSNumber class]]) + return [(NSNumber*)value doubleValue]; + return 0.0f; +} + +double AccessibilityUIElement::maxValue() +{ + id value = [m_element accessibilityAttributeValue:@"AXMaxValue"]; + if ([value isKindOfClass:[NSNumber class]]) + return [(NSNumber*)value doubleValue]; + return 0.0; +} + +int AccessibilityUIElement::insertionPointLineNumber() +{ + id value = [m_element accessibilityAttributeValue:@"AXInsertionPointLineNumber"]; + if ([value isKindOfClass:[NSNumber class]]) + return [(NSNumber *)value intValue]; + return -1; +} + +bool AccessibilityUIElement::supportsPressAction() +{ + NSArray* actions = [m_element accessibilityActionNames]; + return [actions containsObject:@"AXPress"]; +} + +// parameterized attributes +int AccessibilityUIElement::lineForIndex(int index) +{ + id value = [m_element accessibilityAttributeValue:@"AXLineForIndex" forParameter:[NSNumber numberWithInt:index]]; + if ([value isKindOfClass:[NSNumber class]]) + return [(NSNumber *)value intValue]; + return -1; +} + +JSStringRef AccessibilityUIElement::boundsForRange(unsigned location, unsigned length) +{ + NSRange range = NSMakeRange(location, length); + id value = [m_element accessibilityAttributeValue:NSAccessibilityBoundsForRangeParameterizedAttribute forParameter:[NSValue valueWithRange:range]]; + NSRect rect = NSMakeRect(0,0,0,0); + if ([value isKindOfClass:[NSValue class]]) + rect = [value rectValue]; + + // don't return position information because it is platform dependent + NSMutableString* boundsDescription = [NSMutableString stringWithFormat:@"{{%f, %f}, {%f, %f}}",-1.0f,-1.0f,rect.size.width,rect.size.height]; + return [boundsDescription createJSStringRef]; +} + +JSStringRef AccessibilityUIElement::attributesOfColumnHeaders() +{ + // not yet defined in AppKit... odd + NSArray* columnHeadersArray = [m_element accessibilityAttributeValue:@"AXColumnHeaderUIElements"]; + Vector<AccessibilityUIElement> columnHeadersVector; + convertNSArrayToVector(columnHeadersArray, columnHeadersVector); + return descriptionOfElements(columnHeadersVector); +} + +JSStringRef AccessibilityUIElement::attributesOfRowHeaders() +{ + NSArray* rowHeadersArray = [m_element accessibilityAttributeValue:@"AXRowHeaderUIElements"]; + Vector<AccessibilityUIElement> rowHeadersVector; + convertNSArrayToVector(rowHeadersArray, rowHeadersVector); + return descriptionOfElements(rowHeadersVector); +} + +JSStringRef AccessibilityUIElement::attributesOfColumns() +{ + NSArray* columnsArray = [m_element accessibilityAttributeValue:NSAccessibilityColumnsAttribute]; + Vector<AccessibilityUIElement> columnsVector; + convertNSArrayToVector(columnsArray, columnsVector); + return descriptionOfElements(columnsVector); +} + +JSStringRef AccessibilityUIElement::attributesOfRows() +{ + NSArray* rowsArray = [m_element accessibilityAttributeValue:NSAccessibilityRowsAttribute]; + Vector<AccessibilityUIElement> rowsVector; + convertNSArrayToVector(rowsArray, rowsVector); + return descriptionOfElements(rowsVector); +} + +JSStringRef AccessibilityUIElement::attributesOfVisibleCells() +{ + NSArray* cellsArray = [m_element accessibilityAttributeValue:@"AXVisibleCells"]; + Vector<AccessibilityUIElement> cellsVector; + convertNSArrayToVector(cellsArray, cellsVector); + return descriptionOfElements(cellsVector); +} + +JSStringRef AccessibilityUIElement::attributesOfHeader() +{ + id headerObject = [m_element accessibilityAttributeValue:NSAccessibilityHeaderAttribute]; + if (!headerObject) + return [@"" createJSStringRef]; + + Vector<AccessibilityUIElement> headerVector; + headerVector.append(headerObject); + return descriptionOfElements(headerVector); +} + +int AccessibilityUIElement::indexInTable() +{ + NSNumber* indexNumber = [m_element accessibilityAttributeValue:NSAccessibilityIndexAttribute]; + if (!indexNumber) + return -1; + return [indexNumber intValue]; +} + +JSStringRef AccessibilityUIElement::rowIndexRange() +{ + NSValue* indexRange = [m_element accessibilityAttributeValue:@"AXRowIndexRange"]; + NSRange range = indexRange ? [indexRange rangeValue] : NSMakeRange(0,0); + NSMutableString* rangeDescription = [NSMutableString stringWithFormat:@"{%d, %d}",range.location, range.length]; + return [rangeDescription createJSStringRef]; +} + +JSStringRef AccessibilityUIElement::columnIndexRange() +{ + NSNumber* indexRange = [m_element accessibilityAttributeValue:@"AXColumnIndexRange"]; + NSRange range = indexRange ? [indexRange rangeValue] : NSMakeRange(0,0); + NSMutableString* rangeDescription = [NSMutableString stringWithFormat:@"{%d, %d}",range.location, range.length]; + return [rangeDescription createJSStringRef]; +} + +AccessibilityUIElement AccessibilityUIElement::cellForColumnAndRow(unsigned col, unsigned row) +{ + NSArray *colRowArray = [NSArray arrayWithObjects:[NSNumber numberWithUnsignedInt:col], [NSNumber numberWithUnsignedInt:row], nil]; + return [m_element accessibilityAttributeValue:@"AXCellForColumnAndRow" forParameter:colRowArray]; +} + +JSStringRef AccessibilityUIElement::selectedTextRange() +{ + NSNumber *indexRange = [m_element accessibilityAttributeValue:NSAccessibilitySelectedTextRangeAttribute]; + NSRange range = indexRange ? [indexRange rangeValue] : NSMakeRange(0,0); + NSMutableString *rangeDescription = [NSMutableString stringWithFormat:@"{%d, %d}",range.location, range.length]; + return [rangeDescription createJSStringRef]; +} + +void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length) +{ + NSRange textRange = NSMakeRange(location, length); + NSValue *textRangeValue = [NSValue valueWithRange:textRange]; + [m_element accessibilitySetValue:textRangeValue forAttribute:NSAccessibilitySelectedTextRangeAttribute]; +} diff --git a/WebKitTools/DumpRenderTree/mac/Configurations/Base.xcconfig b/WebKitTools/DumpRenderTree/mac/Configurations/Base.xcconfig index bd5b1e0..de9d67f 100644 --- a/WebKitTools/DumpRenderTree/mac/Configurations/Base.xcconfig +++ b/WebKitTools/DumpRenderTree/mac/Configurations/Base.xcconfig @@ -3,6 +3,8 @@ FRAMEWORK_SEARCH_PATHS = $(FRAMEWORK_SEARCH_PATHS_$(MAC_OS_X_VERSION_MAJOR)); FRAMEWORK_SEARCH_PATHS_ = $(SYSTEM_LIBRARY_DIR)/Frameworks/Quartz.framework/Frameworks $(SYSTEM_LIBRARY_DIR)/Frameworks/ApplicationServices.framework/Frameworks FRAMEWORK_SEARCH_PATHS_1040 = $(SYSTEM_LIBRARY_DIR)/Frameworks/Quartz.framework/Frameworks $(SYSTEM_LIBRARY_DIR)/Frameworks/ApplicationServices.framework/Frameworks FRAMEWORK_SEARCH_PATHS_1050 = $(SYSTEM_LIBRARY_DIR)/Frameworks/Quartz.framework/Frameworks $(SYSTEM_LIBRARY_DIR)/Frameworks/ApplicationServices.framework/Frameworks $(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks +FRAMEWORK_SEARCH_PATHS_1060 = $(SYSTEM_LIBRARY_DIR)/Frameworks/Quartz.framework/Frameworks $(SYSTEM_LIBRARY_DIR)/Frameworks/ApplicationServices.framework/Frameworks $(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks +GCC_PREPROCESSOR_DEFINITIONS = ENABLE_DASHBOARD_SUPPORT; DEBUG_INFORMATION_FORMAT = dwarf PREBINDING = NO GCC_C_LANGUAGE_STANDARD = gnu99 @@ -12,4 +14,4 @@ GCC_WARN_UNUSED_FUNCTION = YES GCC_WARN_UNUSED_VARIABLE = YES GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO WARNING_CFLAGS = -Wall -W -Wno-unused-parameter -VALID_ARCHS = ppc7400 ppc970 i386 ppc +LINKER_DISPLAYS_MANGLED_NAMES = YES; diff --git a/WebKitTools/DumpRenderTree/mac/Configurations/DebugRelease.xcconfig b/WebKitTools/DumpRenderTree/mac/Configurations/DebugRelease.xcconfig index e17439e..e272da2 100644 --- a/WebKitTools/DumpRenderTree/mac/Configurations/DebugRelease.xcconfig +++ b/WebKitTools/DumpRenderTree/mac/Configurations/DebugRelease.xcconfig @@ -1,4 +1,6 @@ #include "Base.xcconfig" +ARCHS = $(NATIVE_ARCH); + MACOSX_DEPLOYMENT_TARGET = $(MACOSX_DEPLOYMENT_TARGET_$(MAC_OS_X_VERSION_MAJOR)) MACOSX_DEPLOYMENT_TARGET_ = 10.4 MACOSX_DEPLOYMENT_TARGET_1040 = 10.4 diff --git a/WebKitTools/DumpRenderTree/mac/Configurations/DumpRenderTree.xcconfig b/WebKitTools/DumpRenderTree/mac/Configurations/DumpRenderTree.xcconfig index c8a7bdc..b977225 100644 --- a/WebKitTools/DumpRenderTree/mac/Configurations/DumpRenderTree.xcconfig +++ b/WebKitTools/DumpRenderTree/mac/Configurations/DumpRenderTree.xcconfig @@ -1,4 +1,4 @@ -OTHER_LDFLAGS = -sectcreate __DATA Ahem qt/fonts/AHEM____.TTF +OTHER_LDFLAGS = -sectcreate __DATA Ahem qt/fonts/AHEM____.TTF -sectcreate __DATA WeightWatcher100 fonts/WebKitWeightWatcher100.ttf -sectcreate __DATA WeightWatcher200 fonts/WebKitWeightWatcher200.ttf -sectcreate __DATA WeightWatcher300 fonts/WebKitWeightWatcher300.ttf -sectcreate __DATA WeightWatcher400 fonts/WebKitWeightWatcher400.ttf -sectcreate __DATA WeightWatcher500 fonts/WebKitWeightWatcher500.ttf -sectcreate __DATA WeightWatcher600 fonts/WebKitWeightWatcher600.ttf -sectcreate __DATA WeightWatcher700 fonts/WebKitWeightWatcher700.ttf -sectcreate __DATA WeightWatcher800 fonts/WebKitWeightWatcher800.ttf -sectcreate __DATA WeightWatcher900 fonts/WebKitWeightWatcher900.ttf PRODUCT_NAME = DumpRenderTree GCC_ENABLE_OBJC_EXCEPTIONS = YES GCC_PREFIX_HEADER = DumpRenderTreePrefix.h diff --git a/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm b/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm index 6df150d..203c6b2 100644 --- a/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm +++ b/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm @@ -29,6 +29,7 @@ #import "DumpRenderTree.h" +#import "AccessibilityController.h" #import "CheckedMalloc.h" #import "DumpRenderTreePasteboard.h" #import "DumpRenderTreeWindow.h" @@ -46,34 +47,42 @@ #import "UIDelegate.h" #import "WorkQueue.h" #import "WorkQueueItem.h" +#import <Carbon/Carbon.h> #import <CoreFoundation/CoreFoundation.h> #import <WebKit/DOMElementPrivate.h> #import <WebKit/DOMExtensions.h> #import <WebKit/DOMRange.h> #import <WebKit/WebBackForwardList.h> +#import <WebKit/WebCache.h> #import <WebKit/WebCoreStatistics.h> -#import <WebKit/WebDatabaseManagerPrivate.h> #import <WebKit/WebDataSourcePrivate.h> +#import <WebKit/WebDatabaseManagerPrivate.h> #import <WebKit/WebDocumentPrivate.h> #import <WebKit/WebEditingDelegate.h> #import <WebKit/WebFrameView.h> +#import <WebKit/WebHTMLRepresentationInternal.h> #import <WebKit/WebHistory.h> #import <WebKit/WebHistoryItemPrivate.h> +#import <WebKit/WebInspector.h> #import <WebKit/WebPluginDatabase.h> #import <WebKit/WebPreferences.h> #import <WebKit/WebPreferencesPrivate.h> #import <WebKit/WebResourceLoadDelegate.h> +#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/OwnPtr.h> + +using namespace std; @interface DumpRenderTreeEvent : NSEvent @end -static void runTest(const char *pathOrURL); +static void runTest(const string& testPathOrURL); // Deciding when it's OK to dump out the state is a bit tricky. All these must be true: // - There is no load in progress @@ -84,8 +93,8 @@ static void runTest(const char *pathOrURL); volatile bool done; -NavigationController* navigationController = 0; -LayoutTestController* layoutTestController = 0; +NavigationController* gNavigationController = 0; +LayoutTestController* gLayoutTestController = 0; WebFrame *mainFrame = 0; // This is the topmost frame that is loading, during a given load, or nil when no load is @@ -106,13 +115,10 @@ static ResourceLoadDelegate *resourceLoadDelegate; PolicyDelegate *policyDelegate; static int dumpPixels; -static int dumpAllPixels; static int threaded; -static int testRepaintDefault; -static int repaintSweepHorizontallyDefault; static int dumpTree = YES; +static int forceComplexText; static BOOL printSeparators; -static NSString *currentTest = nil; static RetainPtr<CFStringRef> persistentUserStyleSheetLocation; static WebHistoryItem *prevTestBFItem = nil; // current b/f item at the end of the previous test @@ -120,43 +126,109 @@ static WebHistoryItem *prevTestBFItem = nil; // current b/f item at the end of const unsigned maxViewHeight = 600; const unsigned maxViewWidth = 800; +#if __OBJC2__ +static void swizzleAllMethods(Class imposter, Class original) +{ + unsigned int imposterMethodCount; + Method* imposterMethods = class_copyMethodList(imposter, &imposterMethodCount); + + unsigned int originalMethodCount; + Method* originalMethods = class_copyMethodList(original, &originalMethodCount); + + for (unsigned int i = 0; i < imposterMethodCount; i++) { + SEL imposterMethodName = method_getName(imposterMethods[i]); + + // Attempt to add the method to the original class. If it fails, the method already exists and we should + // instead exchange the implementations. + if (class_addMethod(original, imposterMethodName, method_getImplementation(originalMethods[i]), method_getTypeEncoding(originalMethods[i]))) + continue; + + unsigned int j = 0; + for (; j < originalMethodCount; j++) { + SEL originalMethodName = method_getName(originalMethods[j]); + if (sel_isEqual(imposterMethodName, originalMethodName)) + break; + } + + // If class_addMethod failed above then the method must exist on the original class. + ASSERT(j < originalMethodCount); + method_exchangeImplementations(imposterMethods[i], originalMethods[j]); + } + + free(imposterMethods); + free(originalMethods); +} +#endif + +static void poseAsClass(const char* imposter, const char* original) +{ + Class imposterClass = objc_getClass(imposter); + Class originalClass = objc_getClass(original); + +#if !__OBJC2__ + class_poseAs(imposterClass, originalClass); +#else + + // Swizzle instance methods + swizzleAllMethods(imposterClass, originalClass); + // and then class methods + swizzleAllMethods(object_getClass(imposterClass), object_getClass(originalClass)); +#endif +} + void setPersistentUserStyleSheetLocation(CFStringRef url) { persistentUserStyleSheetLocation = url; } -static BOOL shouldIgnoreWebCoreNodeLeaks(CFStringRef URLString) +static bool shouldIgnoreWebCoreNodeLeaks(const string& URLString) { - static CFStringRef const ignoreSet[] = { + static char* const ignoreSet[] = { // Keeping this infrastructure around in case we ever need it again. }; - static const int ignoreSetCount = sizeof(ignoreSet) / sizeof(CFStringRef); + static const int ignoreSetCount = sizeof(ignoreSet) / sizeof(char*); for (int i = 0; i < ignoreSetCount; i++) { - CFStringRef ignoreString = ignoreSet[i]; - CFRange range = CFRangeMake(0, CFStringGetLength(URLString)); - CFOptionFlags flags = kCFCompareAnchored | kCFCompareBackwards | kCFCompareCaseInsensitive; - if (CFStringFindWithOptions(URLString, ignoreString, range, flags, NULL)) - return YES; + // FIXME: ignore case + string curIgnore(ignoreSet[i]); + // Match at the end of the URLString + if (!URLString.compare(URLString.length() - curIgnore.length(), curIgnore.length(), curIgnore)) + return true; } - return NO; + return false; } -static void activateAhemFont() -{ - unsigned long fontDataLength; - char* fontData = getsectdata("__DATA", "Ahem", &fontDataLength); - if (!fontData) { - fprintf(stderr, "Failed to locate the Ahem font.\n"); - exit(1); - } +static void activateFonts() +{ + static const char* fontSectionNames[] = { + "Ahem", + "WeightWatcher100", + "WeightWatcher200", + "WeightWatcher300", + "WeightWatcher400", + "WeightWatcher500", + "WeightWatcher600", + "WeightWatcher700", + "WeightWatcher800", + "WeightWatcher900", + 0 + }; + + for (unsigned i = 0; fontSectionNames[i]; ++i) { + unsigned long fontDataLength; + char* fontData = getsectdata("__DATA", fontSectionNames[i], &fontDataLength); + if (!fontData) { + fprintf(stderr, "Failed to locate the %s font.\n", fontSectionNames[i]); + exit(1); + } - ATSFontContainerRef fontContainer; - OSStatus status = ATSFontActivateFromMemory(fontData, fontDataLength, kATSFontContextLocal, kATSFontFormatUnspecified, NULL, kATSOptionFlagsDefault, &fontContainer); + ATSFontContainerRef fontContainer; + OSStatus status = ATSFontActivateFromMemory(fontData, fontDataLength, kATSFontContextLocal, kATSFontFormatUnspecified, NULL, kATSOptionFlagsDefault, &fontContainer); - if (status != noErr) { - fprintf(stderr, "Failed to activate the Ahem font.\n"); - exit(1); + if (status != noErr) { + fprintf(stderr, "Failed to activate the %s font.\n", fontSectionNames[i]); + exit(1); + } } } @@ -235,18 +307,26 @@ void testStringByEvaluatingJavaScriptFromString() static void setDefaultsToConsistentValuesForTesting() { // Give some clear to undocumented defaults values - static const int MediumFontSmoothing = 2; + static const int NoFontSmoothing = 0; static const int BlueTintedAppearance = 1; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - [defaults setObject:@"DoubleMax" forKey:@"AppleScrollBarVariant"]; [defaults setInteger:4 forKey:@"AppleAntiAliasingThreshold"]; // smallest font size to CG should perform antialiasing on - [defaults setInteger:MediumFontSmoothing forKey:@"AppleFontSmoothing"]; + [defaults setInteger:NoFontSmoothing forKey:@"AppleFontSmoothing"]; [defaults setInteger:BlueTintedAppearance forKey:@"AppleAquaColorVariant"]; [defaults setObject:@"0.709800 0.835300 1.000000" forKey:@"AppleHighlightColor"]; [defaults setObject:@"0.500000 0.500000 0.500000" forKey:@"AppleOtherHighlightColor"]; [defaults setObject:[NSArray arrayWithObject:@"en"] forKey:@"AppleLanguages"]; + // Scrollbars are drawn either using AppKit (which uses NSUserDefaults) or using HIToolbox (which uses CFPreferences / kCFPreferencesAnyApplication / kCFPreferencesCurrentUser / kCFPreferencesAnyHost) + [defaults setObject:@"DoubleMax" forKey:@"AppleScrollBarVariant"]; + RetainPtr<CFTypeRef> initialValue = CFPreferencesCopyValue(CFSTR("AppleScrollBarVariant"), kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); + CFPreferencesSetValue(CFSTR("AppleScrollBarVariant"), CFSTR("DoubleMax"), kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); + ThemeScrollBarArrowStyle style; + GetThemeScrollBarArrowStyle(&style); // Force HIToolbox to read from CFPreferences + if (initialValue) + CFPreferencesSetValue(CFSTR("AppleScrollBarVariant"), initialValue.get(), kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); + NSString *libraryPath = [@"~/Library/Application Support/DumpRenderTree" stringByExpandingTildeInPath]; [defaults setObject:[libraryPath stringByAppendingPathComponent:@"Databases"] forKey:WebDatabaseDirectoryDefaultsKey]; @@ -265,6 +345,8 @@ static void setDefaultsToConsistentValuesForTesting() [preferences setEditableLinkBehavior:WebKitEditableLinkOnlyLiveWithShiftKey]; [preferences setTabsToLinks:NO]; [preferences setDOMPasteAllowed:YES]; + [preferences setFullDocumentTeardownEnabled:YES]; + [preferences setShouldPrintBackgrounds:YES]; // 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. @@ -273,8 +355,10 @@ static void setDefaultsToConsistentValuesForTesting() static void crashHandler(int sig) { - fprintf(stderr, "%s\n", strsignal(sig)); - restoreColorSpace(0); + char *signalName = strsignal(sig); + write(STDERR_FILENO, signalName, strlen(signalName)); + write(STDERR_FILENO, "\n", 1); + restoreMainDisplayColorProfile(0); exit(128 + sig); } @@ -295,7 +379,7 @@ static void installSignalHandlers() static void allocateGlobalControllers() { // FIXME: We should remove these and move to the ObjC standard [Foo sharedInstance] model - navigationController = [[NavigationController alloc] init]; + gNavigationController = [[NavigationController alloc] init]; frameLoadDelegate = [[FrameLoadDelegate alloc] init]; uiDelegate = [[UIDelegate alloc] init]; editingDelegate = [[EditingDelegate alloc] init]; @@ -312,7 +396,7 @@ static inline void releaseAndZero(NSObject** object) static void releaseGlobalControllers() { - releaseAndZero(&navigationController); + releaseAndZero(&gNavigationController); releaseAndZero(&frameLoadDelegate); releaseAndZero(&editingDelegate); releaseAndZero(&resourceLoadDelegate); @@ -323,13 +407,11 @@ static void releaseGlobalControllers() static void initializeGlobalsFromCommandLineOptions(int argc, const char *argv[]) { struct option options[] = { - {"dump-all-pixels", no_argument, &dumpAllPixels, YES}, - {"horizontal-sweep", no_argument, &repaintSweepHorizontallyDefault, YES}, {"notree", no_argument, &dumpTree, NO}, {"pixel-tests", no_argument, &dumpPixels, YES}, - {"repaint", no_argument, &testRepaintDefault, YES}, {"tree", no_argument, &dumpTree, YES}, {"threaded", no_argument, &threaded, YES}, + {"complex-text", no_argument, &forceComplexText, YES}, {NULL, 0, NULL, 0} }; @@ -376,14 +458,14 @@ static void runTestingServerLoop() static void prepareConsistentTestingEnvironment() { - class_poseAs(objc_getClass("DumpRenderTreePasteboard"), objc_getClass("NSPasteboard")); - class_poseAs(objc_getClass("DumpRenderTreeEvent"), objc_getClass("NSEvent")); + poseAsClass("DumpRenderTreePasteboard", "NSPasteboard"); + poseAsClass("DumpRenderTreeEvent", "NSEvent"); setDefaultsToConsistentValuesForTesting(); - activateAhemFont(); + activateFonts(); if (dumpPixels) - initializeColorSpaceAndScreeBufferForPixelTests(); + setupMainDisplayColorProfile(); allocateGlobalControllers(); makeLargeMallocFailSilently(); @@ -396,12 +478,17 @@ void dumpRenderTree(int argc, const char *argv[]) addTestPluginsToPluginSearchPath(argv[0]); if (dumpPixels) installSignalHandlers(); - + + if (forceComplexText) + [WebView _setAlwaysUsesComplexTextCodePath:YES]; + WebView *webView = createWebViewAndOffscreenWindow(); mainFrame = [webView mainFrame]; [[NSURLCache sharedURLCache] removeAllCachedResponses]; + [WebCache empty]; + // <rdar://problem/5222911> testStringByEvaluatingJavaScriptFromString(); @@ -420,7 +507,6 @@ void dumpRenderTree(int argc, const char *argv[]) if (threaded) stopJavaScriptThreads(); - [WebCoreStatistics emptyCache]; // Otherwise SVGImages trigger false positives for Frame/Node counts [webView close]; mainFrame = nil; @@ -445,7 +531,7 @@ void dumpRenderTree(int argc, const char *argv[]) } if (dumpPixels) - restoreColorSpace(0); + restoreMainDisplayColorProfile(0); } int main(int argc, const char *argv[]) @@ -454,11 +540,12 @@ int main(int argc, const char *argv[]) [NSApplication sharedApplication]; // Force AppKit to init itself dumpRenderTree(argc, argv); [WebCoreStatistics garbageCollectJavaScriptObjects]; + [WebCoreStatistics emptyCache]; // Otherwise SVGImages trigger false positives for Frame/Node counts [pool release]; return 0; } -static int compareHistoryItems(id item1, id item2, void *context) +static NSInteger compareHistoryItems(id item1, id item2, void *context) { return [[item1 target] caseInsensitiveCompare:[item2 target]]; } @@ -497,7 +584,7 @@ static void dumpFrameScrollPosition(WebFrame *f) printf("scrolled to %.f,%.f\n", scrollPosition.x, scrollPosition.y); } - if (layoutTestController->dumpChildFrameScrollPositions()) { + if (gLayoutTestController->dumpChildFrameScrollPositions()) { NSArray *kids = [f childFrames]; if (kids) for (unsigned i = 0; i < [kids count]; i++) @@ -521,7 +608,7 @@ static NSString *dumpFramesAsText(WebFrame *frame) [result appendFormat:@"%@\n", [documentElement innerText]]; - if (layoutTestController->dumpChildFramesAsText()) { + if (gLayoutTestController->dumpChildFramesAsText()) { NSArray *kids = [frame childFrames]; if (kids) { for (unsigned i = 0; i < [kids count]; i++) @@ -532,8 +619,47 @@ static NSString *dumpFramesAsText(WebFrame *frame) return result; } +static NSData *dumpFrameAsPDF(WebFrame *frame) +{ + if (!frame) + return nil; + + // Sadly we have to dump to a file and then read from that file again + // +[NSPrintOperation PDFOperationWithView:insideRect:] requires a rect and prints to a single page + // likewise +[NSView dataWithPDFInsideRect:] also prints to a single continuous page + // The goal of this function is to test "real" printing across multiple pages. + // FIXME: It's possible there might be printing SPI to let us print a multi-page PDF to an NSData object + NSString *path = @"/tmp/test.pdf"; + + NSMutableDictionary *printInfoDict = [NSMutableDictionary dictionaryWithDictionary:[[NSPrintInfo sharedPrintInfo] dictionary]]; + [printInfoDict setObject:NSPrintSaveJob forKey:NSPrintJobDisposition]; + [printInfoDict setObject:path forKey:NSPrintSavePath]; + + NSPrintInfo *printInfo = [[NSPrintInfo alloc] initWithDictionary:printInfoDict]; + [printInfo setHorizontalPagination:NSAutoPagination]; + [printInfo setVerticalPagination:NSAutoPagination]; + [printInfo setVerticallyCentered:NO]; + + NSPrintOperation *printOperation = [NSPrintOperation printOperationWithView:[frame frameView] printInfo:printInfo]; + [printOperation setShowPanels:NO]; + [printOperation runOperation]; + + [printInfo release]; + + NSData *pdfData = [NSData dataWithContentsOfFile:path]; + [[NSFileManager defaultManager] removeFileAtPath:path handler:nil]; + + return pdfData; +} + static void convertMIMEType(NSMutableString *mimeType) { +#ifdef BUILDING_ON_LEOPARD + // Workaround for <rdar://problem/5539824> on Leopard + if ([mimeType isEqualToString:@"text/xml"]) + [mimeType setString:@"application/xml"]; +#endif + // Workaround for <rdar://problem/6234318> with Dashcode 2.0 if ([mimeType isEqualToString:@"application/x-javascript"]) [mimeType setString:@"text/javascript"]; } @@ -543,22 +669,24 @@ static void convertWebResourceDataToString(NSMutableDictionary *resource) NSMutableString *mimeType = [resource objectForKey:@"WebResourceMIMEType"]; convertMIMEType(mimeType); - if ([mimeType hasPrefix:@"text/"]) { + if ([mimeType hasPrefix:@"text/"] || [[WebHTMLRepresentation supportedNonImageMIMETypes] containsObject:mimeType]) { NSData *data = [resource objectForKey:@"WebResourceData"]; NSString *dataAsString = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]; [resource setObject:dataAsString forKey:@"WebResourceData"]; } } -static void normalizeWebResourceURL(NSMutableString *webResourceURL, NSString *oldURLBase) +static void normalizeWebResourceURL(NSMutableString *webResourceURL) { - [webResourceURL replaceOccurrencesOfString:oldURLBase - withString:@"file://" - options:NSLiteralSearch - range:NSMakeRange(0, [webResourceURL length])]; + static int fileUrlLength = [(NSString *)@"file://" length]; + NSRange layoutTestsWebArchivePathRange = [webResourceURL rangeOfString:@"/LayoutTests/" options:NSBackwardsSearch]; + if (layoutTestsWebArchivePathRange.location == NSNotFound) + return; + NSRange currentWorkingDirectoryRange = NSMakeRange(fileUrlLength, layoutTestsWebArchivePathRange.location - fileUrlLength); + [webResourceURL replaceCharactersInRange:currentWorkingDirectoryRange withString:@""]; } -static void convertWebResourceResponseToDictionary(NSMutableDictionary *propertyList, NSString *oldURLBase) +static void convertWebResourceResponseToDictionary(NSMutableDictionary *propertyList) { NSURLResponse *response = nil; NSData *responseData = [propertyList objectForKey:@"WebResourceResponse"]; // WebResourceResponseKey in WebResource.m @@ -573,7 +701,7 @@ static void convertWebResourceResponseToDictionary(NSMutableDictionary *property NSMutableDictionary *responseDictionary = [[NSMutableDictionary alloc] init]; NSMutableString *urlString = [[[response URL] description] mutableCopy]; - normalizeWebResourceURL(urlString, oldURLBase); + normalizeWebResourceURL(urlString); [responseDictionary setObject:urlString forKey:@"URL"]; [urlString release]; @@ -598,6 +726,14 @@ static void convertWebResourceResponseToDictionary(NSMutableDictionary *property [responseDictionary release]; } +static NSInteger compareResourceURLs(id resource1, id resource2, void *context) +{ + NSString *url1 = [resource1 objectForKey:@"WebResourceURL"]; + NSString *url2 = [resource2 objectForKey:@"WebResourceURL"]; + + return [url1 compare:url2]; +} + static NSString *serializeWebArchiveToXML(WebArchive *webArchive) { NSString *errorString; @@ -608,9 +744,6 @@ static NSString *serializeWebArchiveToXML(WebArchive *webArchive) if (!propertyList) return errorString; - // Normalize WebResourceResponse and WebResourceURL values in plist for testing - NSString *cwdURL = [@"file://" stringByAppendingString:[[[NSFileManager defaultManager] currentDirectoryPath] stringByExpandingTildeInPath]]; - NSMutableArray *resources = [NSMutableArray arrayWithCapacity:1]; [resources addObject:propertyList]; @@ -619,7 +752,7 @@ static NSString *serializeWebArchiveToXML(WebArchive *webArchive) [resources removeObjectAtIndex:0]; NSMutableDictionary *mainResource = [resourcePropertyList objectForKey:@"WebMainResource"]; - normalizeWebResourceURL([mainResource objectForKey:@"WebResourceURL"], cwdURL); + normalizeWebResourceURL([mainResource objectForKey:@"WebResourceURL"]); convertWebResourceDataToString(mainResource); // Add subframeArchives to list for processing @@ -631,10 +764,14 @@ static NSString *serializeWebArchiveToXML(WebArchive *webArchive) NSEnumerator *enumerator = [subresources objectEnumerator]; NSMutableDictionary *subresourcePropertyList; while ((subresourcePropertyList = [enumerator nextObject])) { - normalizeWebResourceURL([subresourcePropertyList objectForKey:@"WebResourceURL"], cwdURL); - convertWebResourceResponseToDictionary(subresourcePropertyList, cwdURL); + normalizeWebResourceURL([subresourcePropertyList objectForKey:@"WebResourceURL"]); + convertWebResourceResponseToDictionary(subresourcePropertyList); convertWebResourceDataToString(subresourcePropertyList); } + + // Sort the subresources so they're always in a predictable order for the dump + if (NSArray *sortedSubresources = [subresources sortedArrayUsingFunction:compareResourceURLs context:nil]) + [resourcePropertyList setObject:sortedSubresources forKey:@"WebSubresources"]; } NSData *xmlData = [NSPropertyListSerialization dataFromPropertyList:propertyList @@ -689,7 +826,7 @@ static void dumpBackForwardListForWebView(WebView *view) static void sizeWebViewForCurrentTest() { // W3C SVG tests expect to be 480x360 - bool isSVGW3CTest = ([currentTest rangeOfString:@"svg/W3C-SVG-1.1"].length); + bool isSVGW3CTest = (gLayoutTestController->testPathOrURL().find("svg/W3C-SVG-1.1") != string::npos); if (isSVGW3CTest) [[mainFrame webView] setFrameSize:NSMakeSize(480, 360)]; else @@ -699,11 +836,11 @@ static void sizeWebViewForCurrentTest() static const char *methodNameStringForFailedTest() { const char *errorMessage; - if (layoutTestController->dumpAsText()) + if (gLayoutTestController->dumpAsText()) errorMessage = "[documentElement innerText]"; - else if (layoutTestController->dumpDOMAsWebArchive()) + else if (gLayoutTestController->dumpDOMAsWebArchive()) errorMessage = "[[mainFrame DOMDocument] webArchive]"; - else if (layoutTestController->dumpSourceAsWebArchive()) + else if (gLayoutTestController->dumpSourceAsWebArchive()) errorMessage = "[[mainFrame dataSource] webArchive]"; else errorMessage = "[mainFrame renderTreeAsExternalRepresentation]"; @@ -735,21 +872,27 @@ void dump() { invalidateAnyPreviousWaitToDumpWatchdog(); + bool dumpAsText = gLayoutTestController->dumpAsText(); if (dumpTree) { NSString *resultString = nil; NSData *resultData = nil; + NSString *resultMimeType = @"text/plain"; - bool dumpAsText = layoutTestController->dumpAsText(); dumpAsText |= [[[mainFrame dataSource] _responseMIMEType] isEqualToString:@"text/plain"]; - layoutTestController->setDumpAsText(dumpAsText); - if (layoutTestController->dumpAsText()) { + gLayoutTestController->setDumpAsText(dumpAsText); + if (gLayoutTestController->dumpAsText()) { resultString = dumpFramesAsText(mainFrame); - } else if (layoutTestController->dumpDOMAsWebArchive()) { + } else if (gLayoutTestController->dumpAsPDF()) { + resultData = dumpFrameAsPDF(mainFrame); + resultMimeType = @"application/pdf"; + } else if (gLayoutTestController->dumpDOMAsWebArchive()) { WebArchive *webArchive = [[mainFrame DOMDocument] webArchive]; resultString = serializeWebArchiveToXML(webArchive); - } else if (layoutTestController->dumpSourceAsWebArchive()) { + resultMimeType = @"application/x-webarchive"; + } else if (gLayoutTestController->dumpSourceAsWebArchive()) { WebArchive *webArchive = [[mainFrame dataSource] webArchive]; resultString = serializeWebArchiveToXML(webArchive); + resultMimeType = @"application/x-webarchive"; } else { sizeWebViewForCurrentTest(); resultString = [mainFrame renderTreeAsExternalRepresentation]; @@ -758,25 +901,32 @@ void dump() if (resultString && !resultData) resultData = [resultString dataUsingEncoding:NSUTF8StringEncoding]; + printf("Content-Type: %s\n", [resultMimeType UTF8String]); + if (resultData) { fwrite([resultData bytes], 1, [resultData length], stdout); - if (!layoutTestController->dumpAsText() && !layoutTestController->dumpDOMAsWebArchive() && !layoutTestController->dumpSourceAsWebArchive()) + if (!gLayoutTestController->dumpAsText() && !gLayoutTestController->dumpDOMAsWebArchive() && !gLayoutTestController->dumpSourceAsWebArchive()) dumpFrameScrollPosition(mainFrame); - if (layoutTestController->dumpBackForwardList()) + if (gLayoutTestController->dumpBackForwardList()) dumpBackForwardListForAllWindows(); } else printf("ERROR: nil result from %s", methodNameStringForFailedTest()); - if (printSeparators) - puts("#EOF"); + if (printSeparators) { + puts("#EOF"); // terminate the content block + fputs("#EOF\n", stderr); + } } - if (dumpPixels) - dumpWebViewAsPixelsAndCompareWithExpected([currentTest UTF8String], dumpAllPixels); + if (dumpPixels && !dumpAsText) + dumpWebViewAsPixelsAndCompareWithExpected(gLayoutTestController->expectedPixelHash()); + + puts("#EOF"); // terminate the (possibly empty) pixels block fflush(stdout); + fflush(stderr); done = YES; } @@ -786,29 +936,24 @@ static bool shouldLogFrameLoadDelegates(const char *pathOrURL) return strstr(pathOrURL, "loading/"); } -static CFURLRef createCFURLFromPathOrURL(CFStringRef pathOrURLString) -{ - CFURLRef URL; - if (CFStringHasPrefix(pathOrURLString, CFSTR("http://")) || CFStringHasPrefix(pathOrURLString, CFSTR("https://"))) - URL = CFURLCreateWithString(NULL, pathOrURLString, NULL); - else - URL = CFURLCreateWithFileSystemPath(NULL, pathOrURLString, kCFURLPOSIXPathStyle, FALSE); - return URL; -} - static void resetWebViewToConsistentStateBeforeTesting() { WebView *webView = [mainFrame webView]; [(EditingDelegate *)[webView editingDelegate] setAcceptsEditing:YES]; [webView makeTextStandardSize:nil]; - [webView setTabKeyCyclesThroughElements: YES]; + [webView resetPageZoom:nil]; + [webView setTabKeyCyclesThroughElements:YES]; [webView setPolicyDelegate:nil]; [webView _setDashboardBehavior:WebDashboardBehaviorUseBackwardCompatibilityMode to:NO]; + [webView _clearMainFrameName]; WebPreferences *preferences = [webView preferences]; [preferences setPrivateBrowsingEnabled:NO]; [preferences setAuthorAndUserStylesEnabled:YES]; [preferences setJavaScriptCanOpenWindowsAutomatically:YES]; + [preferences setOfflineWebApplicationCacheEnabled:YES]; + [preferences setFullDocumentTeardownEnabled:YES]; + [preferences setDeveloperExtrasEnabled:NO]; if (persistentUserStyleSheetLocation) { [preferences setUserStyleSheetLocation:[NSURL URLWithString:(NSString *)(persistentUserStyleSheetLocation.get())]]; @@ -816,56 +961,72 @@ static void resetWebViewToConsistentStateBeforeTesting() } else [preferences setUserStyleSheetEnabled:NO]; + [[mainFrame webView] setSmartInsertDeleteEnabled:YES]; + [[[mainFrame webView] inspector] setJavaScriptProfilingEnabled:NO]; + [WebView _setUsesTestModeFocusRingColor:YES]; } -static void runTest(const char *pathOrURL) +static void runTest(const string& testPathOrURL) { - CFStringRef pathOrURLString = CFStringCreateWithCString(NULL, pathOrURL, kCFStringEncodingUTF8); + ASSERT(!testPathOrURL.empty()); + + // Look for "'" as a separator between the path or URL, and the pixel dump hash that follows. + string pathOrURL(testPathOrURL); + string expectedPixelHash; + + size_t separatorPos = pathOrURL.find("'"); + if (separatorPos != string::npos) { + pathOrURL = string(testPathOrURL, 0, separatorPos); + expectedPixelHash = string(testPathOrURL, separatorPos + 1); + } + + NSString *pathOrURLString = [NSString stringWithUTF8String:pathOrURL.c_str()]; if (!pathOrURLString) { - fprintf(stderr, "Failed to parse filename as UTF-8: %s\n", pathOrURL); + fprintf(stderr, "Failed to parse \"%s\" as UTF-8\n", pathOrURL.c_str()); return; } - CFURLRef URL = createCFURLFromPathOrURL(pathOrURLString); - if (!URL) { - CFRelease(pathOrURLString); - fprintf(stderr, "Can't turn %s into a CFURL\n", pathOrURL); + NSURL *url; + if ([pathOrURLString hasPrefix:@"http://"] || [pathOrURLString hasPrefix:@"https://"]) + url = [NSURL URLWithString:pathOrURLString]; + else + url = [NSURL fileURLWithPath:pathOrURLString]; + if (!url) { + fprintf(stderr, "Failed to parse \"%s\" as a URL\n", pathOrURL.c_str()); return; } + const string testURL([[url absoluteString] UTF8String]); + resetWebViewToConsistentStateBeforeTesting(); - layoutTestController = new LayoutTestController(testRepaintDefault, repaintSweepHorizontallyDefault); + gLayoutTestController = new LayoutTestController(testURL, expectedPixelHash); topLoadingFrame = nil; done = NO; if (disallowedURLs) CFSetRemoveAllValues(disallowedURLs); - if (shouldLogFrameLoadDelegates(pathOrURL)) - layoutTestController->setDumpFrameLoadCallbacks(true); + if (shouldLogFrameLoadDelegates(pathOrURL.c_str())) + gLayoutTestController->setDumpFrameLoadCallbacks(true); if ([WebHistory optionalSharedHistory]) [WebHistory setOptionalSharedHistory:nil]; lastMousePosition = NSZeroPoint; lastClickPosition = NSZeroPoint; - if (currentTest != nil) - CFRelease(currentTest); - currentTest = (NSString *)pathOrURLString; [prevTestBFItem release]; prevTestBFItem = [[[[mainFrame webView] backForwardList] currentItem] retain]; WorkQueue::shared()->clear(); WorkQueue::shared()->setFrozen(false); - BOOL _shouldIgnoreWebCoreNodeLeaks = shouldIgnoreWebCoreNodeLeaks(CFURLGetString(URL)); - if (_shouldIgnoreWebCoreNodeLeaks) + bool ignoreWebCoreNodeLeaks = shouldIgnoreWebCoreNodeLeaks(testURL); + if (ignoreWebCoreNodeLeaks) [WebCoreStatistics startIgnoringWebCoreNodeLeaks]; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - [mainFrame loadRequest:[NSURLRequest requestWithURL:(NSURL *)URL]]; - CFRelease(URL); + [mainFrame loadRequest:[NSURLRequest requestWithURL:url]]; [pool release]; while (!done) { pool = [[NSAutoreleasePool alloc] init]; @@ -878,7 +1039,7 @@ static void runTest(const char *pathOrURL) WorkQueue::shared()->clear(); - if (layoutTestController->closeRemainingWindowsWhenComplete()) { + if (gLayoutTestController->closeRemainingWindowsWhenComplete()) { NSArray* array = [DumpRenderTreeWindow openWindows]; unsigned count = [array count]; @@ -905,10 +1066,10 @@ static void runTest(const char *pathOrURL) ASSERT(CFArrayGetCount(openWindowsRef) == 1); ASSERT(CFArrayGetValueAtIndex(openWindowsRef, 0) == [[mainFrame webView] window]); - delete layoutTestController; - layoutTestController = 0; + gLayoutTestController->deref(); + gLayoutTestController = 0; - if (_shouldIgnoreWebCoreNodeLeaks) + if (ignoreWebCoreNodeLeaks) [WebCoreStatistics stopIgnoringWebCoreNodeLeaks]; } diff --git a/WebKitTools/DumpRenderTree/mac/DumpRenderTreeMac.h b/WebKitTools/DumpRenderTree/mac/DumpRenderTreeMac.h index c4c7573..03d354d 100644 --- a/WebKitTools/DumpRenderTree/mac/DumpRenderTreeMac.h +++ b/WebKitTools/DumpRenderTree/mac/DumpRenderTreeMac.h @@ -32,6 +32,12 @@ // FIXME: we should add a config.h file for DumpRenderTree. #define WTF_PLATFORM_CF 1 +#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4 +#define BUILDING_ON_TIGER 1 +#elif MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 +#define BUILDING_ON_LEOPARD 1 +#endif + @class DumpRenderTreeDraggingInfo; @class NavigationController; @class PolicyDelegate; @@ -45,7 +51,7 @@ extern CFMutableSetRef disallowedURLs; extern WebFrame* mainFrame; extern WebFrame* topLoadingFrame; extern DumpRenderTreeDraggingInfo *draggingInfo; -extern NavigationController* navigationController; +extern NavigationController* gNavigationController; extern PolicyDelegate* policyDelegate; extern const unsigned maxViewHeight; diff --git a/WebKitTools/DumpRenderTree/mac/DumpRenderTreePasteboard.h b/WebKitTools/DumpRenderTree/mac/DumpRenderTreePasteboard.h index 6a01a42..ba2754b 100644 --- a/WebKitTools/DumpRenderTree/mac/DumpRenderTreePasteboard.h +++ b/WebKitTools/DumpRenderTree/mac/DumpRenderTreePasteboard.h @@ -29,9 +29,10 @@ */ #import <AppKit/AppKit.h> +#import <WebKit/WebTypesInternal.h> @interface DumpRenderTreePasteboard : NSPasteboard -- (int)declareType:(NSString *)type owner:(id)newOwner; +- (NSInteger)declareType:(NSString *)type owner:(id)newOwner; + (void)releaseLocalPasteboards; @end diff --git a/WebKitTools/DumpRenderTree/mac/DumpRenderTreePasteboard.m b/WebKitTools/DumpRenderTree/mac/DumpRenderTreePasteboard.m index b5a9b7a..a797b5c 100644 --- a/WebKitTools/DumpRenderTree/mac/DumpRenderTreePasteboard.m +++ b/WebKitTools/DumpRenderTree/mac/DumpRenderTreePasteboard.m @@ -28,14 +28,17 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#import "DumpRenderTreeMac.h" #import "DumpRenderTreePasteboard.h" +#import <WebKit/WebTypesInternal.h> + @interface LocalPasteboard : NSPasteboard { NSMutableArray *typesArray; NSMutableSet *typesSet; NSMutableDictionary *dataByType; - int changeCount; + NSInteger changeCount; } @end @@ -68,7 +71,7 @@ static NSMutableDictionary *localPasteboards; // Convenience method for JS so that it doesn't have to try and create a NSArray on the objc side instead // of the usual WebScriptObject that is passed around -- (int)declareType:(NSString *)type owner:(id)newOwner +- (NSInteger)declareType:(NSString *)type owner:(id)newOwner { return [self declareTypes:[NSArray arrayWithObject:type] owner:newOwner]; } @@ -107,7 +110,7 @@ static NSMutableDictionary *localPasteboards; { } -- (int)declareTypes:(NSArray *)newTypes owner:(id)newOwner +- (NSInteger)declareTypes:(NSArray *)newTypes owner:(id)newOwner { [typesArray removeAllObjects]; [typesSet removeAllObjects]; @@ -115,7 +118,7 @@ static NSMutableDictionary *localPasteboards; return [self addTypes:newTypes owner:newOwner]; } -- (int)addTypes:(NSArray *)newTypes owner:(id)newOwner +- (NSInteger)addTypes:(NSArray *)newTypes owner:(id)newOwner { unsigned count = [newTypes count]; unsigned i; @@ -134,7 +137,7 @@ static NSMutableDictionary *localPasteboards; return ++changeCount; } -- (int)changeCount +- (NSInteger)changeCount { return changeCount; } diff --git a/WebKitTools/DumpRenderTree/mac/DumpRenderTreeWindow.mm b/WebKitTools/DumpRenderTree/mac/DumpRenderTreeWindow.mm index 9e5e104..b3fc5a7 100644 --- a/WebKitTools/DumpRenderTree/mac/DumpRenderTreeWindow.mm +++ b/WebKitTools/DumpRenderTree/mac/DumpRenderTreeWindow.mm @@ -34,6 +34,7 @@ // FIXME: This file is ObjC++ only because of this include. :( #import "LayoutTestController.h" +#import <WebKit/WebTypesInternal.h> CFMutableArrayRef openWindowsRef = 0; @@ -52,7 +53,7 @@ static CFArrayCallBacks NonRetainingArrayCallbacks = { return [[(NSArray *)openWindowsRef copy] autorelease]; } -- (id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)styleMask backing:(NSBackingStoreType)bufferingType defer:(BOOL)deferCreation +- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)bufferingType defer:(BOOL)deferCreation { if (!openWindowsRef) openWindowsRef = CFArrayCreateMutable(NULL, 0, &NonRetainingArrayCallbacks); @@ -73,7 +74,7 @@ static CFArrayCallBacks NonRetainingArrayCallbacks = { - (BOOL)isKeyWindow { - return layoutTestController ? layoutTestController->windowIsKey() : YES; + return gLayoutTestController ? gLayoutTestController->windowIsKey() : YES; } - (void)keyDown:(id)sender diff --git a/WebKitTools/DumpRenderTree/mac/EditingDelegate.mm b/WebKitTools/DumpRenderTree/mac/EditingDelegate.mm index a8f0815..cf4026b 100644 --- a/WebKitTools/DumpRenderTree/mac/EditingDelegate.mm +++ b/WebKitTools/DumpRenderTree/mac/EditingDelegate.mm @@ -73,14 +73,14 @@ - (BOOL)webView:(WebView *)webView shouldBeginEditingInDOMRange:(DOMRange *)range { - if (!done && layoutTestController->dumpEditingCallbacks()) + if (!done && gLayoutTestController->dumpEditingCallbacks()) printf("EDITING DELEGATE: shouldBeginEditingInDOMRange:%s\n", [[range dump] UTF8String]); return acceptsEditing; } - (BOOL)webView:(WebView *)webView shouldEndEditingInDOMRange:(DOMRange *)range { - if (!done && layoutTestController->dumpEditingCallbacks()) + if (!done && gLayoutTestController->dumpEditingCallbacks()) printf("EDITING DELEGATE: shouldEndEditingInDOMRange:%s\n", [[range dump] UTF8String]); return acceptsEditing; } @@ -93,7 +93,7 @@ "WebViewInsertActionDropped", }; - if (!done && layoutTestController->dumpEditingCallbacks()) + if (!done && gLayoutTestController->dumpEditingCallbacks()) printf("EDITING DELEGATE: shouldInsertNode:%s replacingDOMRange:%s givenAction:%s\n", [[node dumpPath] UTF8String], [[range dump] UTF8String], insertactionstring[action]); return acceptsEditing; } @@ -106,14 +106,14 @@ "WebViewInsertActionDropped", }; - if (!done && layoutTestController->dumpEditingCallbacks()) + if (!done && gLayoutTestController->dumpEditingCallbacks()) printf("EDITING DELEGATE: shouldInsertText:%s replacingDOMRange:%s givenAction:%s\n", [[text description] UTF8String], [[range dump] UTF8String], insertactionstring[action]); return acceptsEditing; } - (BOOL)webView:(WebView *)webView shouldDeleteDOMRange:(DOMRange *)range { - if (!done && layoutTestController->dumpEditingCallbacks()) + if (!done && gLayoutTestController->dumpEditingCallbacks()) printf("EDITING DELEGATE: shouldDeleteDOMRange:%s\n", [[range dump] UTF8String]); return acceptsEditing; } @@ -134,52 +134,52 @@ "TRUE" }; - if (!done && layoutTestController->dumpEditingCallbacks()) + if (!done && gLayoutTestController->dumpEditingCallbacks()) printf("EDITING DELEGATE: shouldChangeSelectedDOMRange:%s toDOMRange:%s affinity:%s stillSelecting:%s\n", [[currentRange dump] UTF8String], [[proposedRange dump] UTF8String], affinitystring[selectionAffinity], boolstring[flag]); return acceptsEditing; } - (BOOL)webView:(WebView *)webView shouldApplyStyle:(DOMCSSStyleDeclaration *)style toElementsInDOMRange:(DOMRange *)range { - if (!done && layoutTestController->dumpEditingCallbacks()) + if (!done && gLayoutTestController->dumpEditingCallbacks()) printf("EDITING DELEGATE: shouldApplyStyle:%s toElementsInDOMRange:%s\n", [[style description] UTF8String], [[range dump] UTF8String]); return acceptsEditing; } - (BOOL)webView:(WebView *)webView shouldChangeTypingStyle:(DOMCSSStyleDeclaration *)currentStyle toStyle:(DOMCSSStyleDeclaration *)proposedStyle { - if (!done && layoutTestController->dumpEditingCallbacks()) + if (!done && gLayoutTestController->dumpEditingCallbacks()) printf("EDITING DELEGATE: shouldChangeTypingStyle:%s toStyle:%s\n", [[currentStyle description] UTF8String], [[proposedStyle description] UTF8String]); return acceptsEditing; } - (void)webViewDidBeginEditing:(NSNotification *)notification { - if (!done && layoutTestController->dumpEditingCallbacks()) + if (!done && gLayoutTestController->dumpEditingCallbacks()) printf("EDITING DELEGATE: webViewDidBeginEditing:%s\n", [[notification name] UTF8String]); } - (void)webViewDidChange:(NSNotification *)notification { - if (!done && layoutTestController->dumpEditingCallbacks()) + if (!done && gLayoutTestController->dumpEditingCallbacks()) printf("EDITING DELEGATE: webViewDidChange:%s\n", [[notification name] UTF8String]); } - (void)webViewDidEndEditing:(NSNotification *)notification { - if (!done && layoutTestController->dumpEditingCallbacks()) + if (!done && gLayoutTestController->dumpEditingCallbacks()) printf("EDITING DELEGATE: webViewDidEndEditing:%s\n", [[notification name] UTF8String]); } - (void)webViewDidChangeTypingStyle:(NSNotification *)notification { - if (!done && layoutTestController->dumpEditingCallbacks()) + if (!done && gLayoutTestController->dumpEditingCallbacks()) printf("EDITING DELEGATE: webViewDidChangeTypingStyle:%s\n", [[notification name] UTF8String]); } - (void)webViewDidChangeSelection:(NSNotification *)notification { - if (!done && layoutTestController->dumpEditingCallbacks()) + if (!done && gLayoutTestController->dumpEditingCallbacks()) printf("EDITING DELEGATE: webViewDidChangeSelection:%s\n", [[notification name] UTF8String]); } diff --git a/WebKitTools/DumpRenderTree/mac/EventSendingController.h b/WebKitTools/DumpRenderTree/mac/EventSendingController.h index 28d0385..deee848 100644 --- a/WebKitTools/DumpRenderTree/mac/EventSendingController.h +++ b/WebKitTools/DumpRenderTree/mac/EventSendingController.h @@ -31,7 +31,7 @@ @interface EventSendingController : NSObject <DOMEventListener> { - BOOL down; + BOOL leftMouseButtonDown; BOOL dragMode; int clickCount; NSTimeInterval lastClick; diff --git a/WebKitTools/DumpRenderTree/mac/EventSendingController.mm b/WebKitTools/DumpRenderTree/mac/EventSendingController.mm index 8e9be38..8be05e7 100644 --- a/WebKitTools/DumpRenderTree/mac/EventSendingController.mm +++ b/WebKitTools/DumpRenderTree/mac/EventSendingController.mm @@ -35,13 +35,29 @@ #import "DumpRenderTreeDraggingInfo.h" #import <Carbon/Carbon.h> // for GetCurrentEventTime() -#import <WebKit/WebKit.h> #import <WebKit/DOMPrivate.h> +#import <WebKit/WebKit.h> +#import <WebKit/WebViewPrivate.h> extern "C" void _NSNewKillRingSequence(); +enum MouseAction { + MouseDown, + MouseUp, + MouseDragged +}; + +// Match the DOM spec (sadly the DOM spec does not provide an enum) +enum MouseButton { + LeftMouseButton = 0, + MiddleMouseButton = 1, + RightMouseButton = 2, + NoMouseButton = -1 +}; + NSPoint lastMousePosition; NSPoint lastClickPosition; +int lastClickButton = NoMouseButton; NSArray *webkitDomEventNames; NSMutableArray *savedMouseEvents; // mouse events sent between mouseDown and mouseUp are stored here, and then executed at once. BOOL replayingSavedEvents; @@ -102,8 +118,8 @@ BOOL replayingSavedEvents; + (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector { - if (aSelector == @selector(mouseDown) - || aSelector == @selector(mouseUp) + if (aSelector == @selector(mouseDown:) + || aSelector == @selector(mouseUp:) || aSelector == @selector(contextClick) || aSelector == @selector(mouseMoveToX:Y:) || aSelector == @selector(leapForward:) @@ -112,7 +128,9 @@ BOOL replayingSavedEvents; || aSelector == @selector(fireKeyboardEventsToElement:) || aSelector == @selector(clearKillRing) || aSelector == @selector(textZoomIn) - || aSelector == @selector(textZoomOut)) + || aSelector == @selector(textZoomOut) + || aSelector == @selector(zoomPageIn) + || aSelector == @selector(zoomPageOut)) return NO; return YES; } @@ -126,6 +144,10 @@ BOOL replayingSavedEvents; + (NSString *)webScriptNameForSelector:(SEL)aSelector { + if (aSelector == @selector(mouseDown:)) + return @"mouseDown"; + if (aSelector == @selector(mouseUp:)) + return @"mouseUp"; if (aSelector == @selector(mouseMoveToX:Y:)) return @"mouseMoveTo"; if (aSelector == @selector(leapForward:)) @@ -161,7 +183,7 @@ BOOL replayingSavedEvents; - (void)leapForward:(int)milliseconds { - if (dragMode && down && !replayingSavedEvents) { + if (dragMode && leftMouseButtonDown && !replayingSavedEvents) { NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[EventSendingController instanceMethodSignatureForSelector:@selector(leapForward:)]]; [invocation setTarget:self]; [invocation setSelector:@selector(leapForward:)]; @@ -180,15 +202,59 @@ BOOL replayingSavedEvents; _NSNewKillRingSequence(); } -- (void)mouseDown +static NSEventType eventTypeForMouseButtonAndAction(int button, MouseAction action) +{ + switch (button) { + case LeftMouseButton: + switch (action) { + case MouseDown: + return NSLeftMouseDown; + case MouseUp: + return NSLeftMouseUp; + case MouseDragged: + return NSLeftMouseDragged; + } + case RightMouseButton: + switch (action) { + case MouseDown: + return NSRightMouseDown; + case MouseUp: + return NSRightMouseUp; + case MouseDragged: + return NSRightMouseDragged; + } + default: + switch (action) { + case MouseDown: + return NSOtherMouseDown; + case MouseUp: + return NSOtherMouseUp; + case MouseDragged: + return NSOtherMouseDragged; + } + } + assert(0); + return static_cast<NSEventType>(0); +} + +- (void)updateClickCountForButton:(int)buttonNumber { - [[[mainFrame frameView] documentView] layout]; if (([self currentEventTime] - lastClick >= 1) || - !NSEqualPoints(lastMousePosition, lastClickPosition)) + !NSEqualPoints(lastMousePosition, lastClickPosition) || + lastClickButton != buttonNumber) { clickCount = 1; - else + lastClickButton = buttonNumber; + } else clickCount++; - NSEvent *event = [NSEvent mouseEventWithType:NSLeftMouseDown +} + +- (void)mouseDown:(int)buttonNumber +{ + [[[mainFrame frameView] documentView] layout]; + [self updateClickCountForButton:buttonNumber]; + + NSEventType eventType = eventTypeForMouseButtonAndAction(buttonNumber, MouseDown); + NSEvent *event = [NSEvent mouseEventWithType:eventType location:lastMousePosition modifierFlags:0 timestamp:[self currentEventTime] @@ -201,7 +267,8 @@ BOOL replayingSavedEvents; NSView *subView = [[mainFrame webView] hitTest:[event locationInWindow]]; if (subView) { [subView mouseDown:event]; - down = YES; + if (buttonNumber == LeftMouseButton) + leftMouseButtonDown = YES; } } @@ -215,12 +282,23 @@ BOOL replayingSavedEvents; [[mainFrame webView] makeTextSmaller:self]; } -- (void)mouseUp +- (void)zoomPageIn +{ + [[mainFrame webView] zoomPageIn:self]; +} + +- (void)zoomPageOut +{ + [[mainFrame webView] zoomPageOut:self]; +} + +- (void)mouseUp:(int)buttonNumber { if (dragMode && !replayingSavedEvents) { - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[EventSendingController instanceMethodSignatureForSelector:@selector(mouseUp)]]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[EventSendingController instanceMethodSignatureForSelector:@selector(mouseUp:)]]; [invocation setTarget:self]; - [invocation setSelector:@selector(mouseUp)]; + [invocation setSelector:@selector(mouseUp:)]; + [invocation setArgument:&buttonNumber atIndex:2]; [EventSendingController saveEvent:invocation]; [EventSendingController replaySavedEvents]; @@ -229,7 +307,8 @@ BOOL replayingSavedEvents; } [[[mainFrame frameView] documentView] layout]; - NSEvent *event = [NSEvent mouseEventWithType:NSLeftMouseUp + NSEventType eventType = eventTypeForMouseButtonAndAction(buttonNumber, MouseUp); + NSEvent *event = [NSEvent mouseEventWithType:eventType location:lastMousePosition modifierFlags:0 timestamp:[self currentEventTime] @@ -246,7 +325,8 @@ BOOL replayingSavedEvents; targetView = targetView ? targetView : [[mainFrame frameView] documentView]; assert(targetView); [targetView mouseUp:event]; - down = NO; + if (buttonNumber == LeftMouseButton) + leftMouseButtonDown = NO; lastClick = [event timestamp]; lastClickPosition = lastMousePosition; if (draggingInfo) { @@ -266,7 +346,7 @@ BOOL replayingSavedEvents; - (void)mouseMoveToX:(int)x Y:(int)y { - if (dragMode && down && !replayingSavedEvents) { + if (dragMode && leftMouseButtonDown && !replayingSavedEvents) { NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[EventSendingController instanceMethodSignatureForSelector:@selector(mouseMoveToX:Y:)]]; [invocation setTarget:self]; [invocation setSelector:@selector(mouseMoveToX:Y:)]; @@ -280,19 +360,19 @@ BOOL replayingSavedEvents; NSView *view = [mainFrame webView]; lastMousePosition = [view convertPoint:NSMakePoint(x, [view frame].size.height - y) toView:nil]; - NSEvent *event = [NSEvent mouseEventWithType:(down ? NSLeftMouseDragged : NSMouseMoved) + NSEvent *event = [NSEvent mouseEventWithType:(leftMouseButtonDown ? NSLeftMouseDragged : NSMouseMoved) location:lastMousePosition modifierFlags:0 timestamp:[self currentEventTime] windowNumber:[[view window] windowNumber] context:[NSGraphicsContext currentContext] eventNumber:++eventNumber - clickCount:(down ? clickCount : 0) + clickCount:(leftMouseButtonDown ? clickCount : 0) pressure:0.0]; NSView *subView = [[mainFrame webView] hitTest:[event locationInWindow]]; if (subView) { - if (down) { + if (leftMouseButtonDown) { [subView mouseDragged:event]; if (draggingInfo) { [[draggingInfo draggingSource] draggedImage:[draggingInfo draggedImage] movedTo:lastMousePosition]; @@ -306,11 +386,9 @@ BOOL replayingSavedEvents; - (void)contextClick { [[[mainFrame frameView] documentView] layout]; - if ([self currentEventTime] - lastClick >= 1) - clickCount = 1; - else - clickCount++; - NSEvent *event = [NSEvent mouseEventWithType:NSRightMouseDown + [self updateClickCountForButton:RightMouseButton]; + + NSEvent *event = [NSEvent mouseEventWithType:NSRightMouseDown location:lastMousePosition modifierFlags:0 timestamp:[self currentEventTime] diff --git a/WebKitTools/DumpRenderTree/mac/FrameLoadDelegate.h b/WebKitTools/DumpRenderTree/mac/FrameLoadDelegate.h index 3b86fdf..6c3cbdb 100644 --- a/WebKitTools/DumpRenderTree/mac/FrameLoadDelegate.h +++ b/WebKitTools/DumpRenderTree/mac/FrameLoadDelegate.h @@ -28,10 +28,12 @@ #import <Foundation/Foundation.h> +class AccessibilityController; class GCController; @interface FrameLoadDelegate : NSObject { + AccessibilityController* accessibilityController; GCController* gcController; } @end diff --git a/WebKitTools/DumpRenderTree/mac/FrameLoadDelegate.mm b/WebKitTools/DumpRenderTree/mac/FrameLoadDelegate.mm index 98b6bac..3d7f8b4 100644 --- a/WebKitTools/DumpRenderTree/mac/FrameLoadDelegate.mm +++ b/WebKitTools/DumpRenderTree/mac/FrameLoadDelegate.mm @@ -29,6 +29,7 @@ #import "DumpRenderTree.h" #import "FrameLoadDelegate.h" +#import "AccessibilityController.h" #import "AppleScriptController.h" #import "EventSendingController.h" #import "GCController.h" @@ -94,8 +95,10 @@ - (id)init { - if ((self = [super init])) + if ((self = [super init])) { gcController = new GCController; + accessibilityController = new AccessibilityController; + } return self; } @@ -117,7 +120,7 @@ } // if we didn't start a new load, then we finished all the commands, so we're ready to dump state - if (!topLoadingFrame && !layoutTestController->waitToDump()) + if (!topLoadingFrame && !gLayoutTestController->waitToDump()) dump(); } @@ -126,7 +129,7 @@ if ([dataSource webFrame] == topLoadingFrame) { topLoadingFrame = nil; WorkQueue::shared()->setFrozen(true); // first complete load freezes the queue for the rest of this test - if (!layoutTestController->waitToDump()) { + if (!gLayoutTestController->waitToDump()) { if (WorkQueue::shared()->count()) [self performSelector:@selector(processWork:) withObject:nil afterDelay:0]; else @@ -137,7 +140,7 @@ - (void)webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame { - if (!done && layoutTestController->dumpFrameLoadCallbacks()) { + if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) { NSString *string = [NSString stringWithFormat:@"%@ - didStartProvisionalLoadForFrame", [frame _drt_descriptionSuitableForTestResult]]; printf ("%s\n", [string UTF8String]); } @@ -147,11 +150,17 @@ // end up doing two dumps for one test. if (!topLoadingFrame && !done) topLoadingFrame = frame; + + if (!done && gLayoutTestController->stopProvisionalFrameLoads()) { + NSString *string = [NSString stringWithFormat:@"%@ - stopping load in didStartProvisionalLoadForFrame callback", [frame _drt_descriptionSuitableForTestResult]]; + printf ("%s\n", [string UTF8String]); + [frame stopLoading]; + } } - (void)webView:(WebView *)sender didCommitLoadForFrame:(WebFrame *)frame { - if (!done && layoutTestController->dumpFrameLoadCallbacks()) { + if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) { NSString *string = [NSString stringWithFormat:@"%@ - didCommitLoadForFrame", [frame _drt_descriptionSuitableForTestResult]]; printf ("%s\n", [string UTF8String]); } @@ -159,7 +168,7 @@ ASSERT(![frame provisionalDataSource]); ASSERT([frame dataSource]); - layoutTestController->setWindowIsKey(true); + gLayoutTestController->setWindowIsKey(true); NSView *documentView = [[mainFrame frameView] documentView]; [[[mainFrame webView] window] makeFirstResponder:documentView]; if ([documentView isKindOfClass:[WebHTMLView class]]) @@ -168,7 +177,7 @@ - (void)webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame { - if (!done && layoutTestController->dumpFrameLoadCallbacks()) { + if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) { NSString *string = [NSString stringWithFormat:@"%@ - didFailProvisionalLoadWithError", [frame _drt_descriptionSuitableForTestResult]]; printf ("%s\n", [string UTF8String]); } @@ -189,7 +198,7 @@ ASSERT([frame dataSource]); ASSERT(frame == [[frame dataSource] webFrame]); - if (!done && layoutTestController->dumpFrameLoadCallbacks()) { + if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) { NSString *string = [NSString stringWithFormat:@"%@ - didFinishLoadForFrame", [frame _drt_descriptionSuitableForTestResult]]; printf ("%s\n", [string UTF8String]); } @@ -200,12 +209,12 @@ if ([[sender mainFrame] isEqual:frame]) [sender displayIfNeeded]; [self webView:sender locationChangeDone:nil forDataSource:[frame dataSource]]; - [navigationController webView:sender didFinishLoadForFrame:frame]; + [gNavigationController webView:sender didFinishLoadForFrame:frame]; } - (void)webView:(WebView *)sender didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame; { - if (!done && layoutTestController->dumpFrameLoadCallbacks()) { + if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) { NSString *string = [NSString stringWithFormat:@"%@ - didFailLoadWithError", [frame _drt_descriptionSuitableForTestResult]]; printf ("%s\n", [string UTF8String]); } @@ -218,7 +227,7 @@ - (void)webView:(WebView *)webView windowScriptObjectAvailable:(WebScriptObject *)windowScriptObject; { - if (!done && layoutTestController->dumpFrameLoadCallbacks()) { + if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) { NSString *string = [NSString stringWithFormat:@"?? - windowScriptObjectAvailable"]; printf ("%s\n", [string UTF8String]); } @@ -236,13 +245,16 @@ JSObjectRef globalObject = JSContextGetGlobalObject(context); JSValueRef exception = 0; - ASSERT(layoutTestController); - layoutTestController->makeWindowObject(context, globalObject, &exception); + ASSERT(gLayoutTestController); + gLayoutTestController->makeWindowObject(context, globalObject, &exception); ASSERT(!exception); gcController->makeWindowObject(context, globalObject, &exception); ASSERT(!exception); + accessibilityController->makeWindowObject(context, globalObject, &exception); + ASSERT(!exception); + // Make Old-Style controllers EventSendingController *esc = [[EventSendingController alloc] init]; [obj setValue:esc forKey:@"eventSender"]; @@ -260,7 +272,7 @@ [obj setValue:occ forKey:@"objCController"]; [occ release]; - [obj setValue:navigationController forKey:@"navigationController"]; + [obj setValue:gNavigationController forKey:@"navigationController"]; ObjCPlugin *plugin = [[ObjCPlugin alloc] init]; [obj setValue:plugin forKey:@"objCPlugin"]; @@ -273,18 +285,18 @@ - (void)webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame { - if (!done && layoutTestController->dumpFrameLoadCallbacks()) { + if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) { NSString *string = [NSString stringWithFormat:@"%@ - didReceiveTitle: %@", [frame _drt_descriptionSuitableForTestResult], title]; printf ("%s\n", [string UTF8String]); } - if (layoutTestController->dumpTitleChanges()) + if (gLayoutTestController->dumpTitleChanges()) printf("TITLE CHANGED: %s\n", [title UTF8String]); } - (void)webView:(WebView *)sender didReceiveServerRedirectForProvisionalLoadForFrame:(WebFrame *)frame { - if (!done && layoutTestController->dumpFrameLoadCallbacks()) { + if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) { NSString *string = [NSString stringWithFormat:@"%@ - didReceiveServerRedirectForProvisionalLoadForFrame", [frame _drt_descriptionSuitableForTestResult]]; printf ("%s\n", [string UTF8String]); } @@ -292,7 +304,7 @@ - (void)webView:(WebView *)sender didChangeLocationWithinPageForFrame:(WebFrame *)frame { - if (!done && layoutTestController->dumpFrameLoadCallbacks()) { + if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) { NSString *string = [NSString stringWithFormat:@"%@ - didChangeLocationWithinPageForFrame", [frame _drt_descriptionSuitableForTestResult]]; printf ("%s\n", [string UTF8String]); } @@ -300,7 +312,7 @@ - (void)webView:(WebView *)sender willPerformClientRedirectToURL:(NSURL *)URL delay:(NSTimeInterval)seconds fireDate:(NSDate *)date forFrame:(WebFrame *)frame { - if (!done && layoutTestController->dumpFrameLoadCallbacks()) { + if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) { NSString *string = [NSString stringWithFormat:@"%@ - willPerformClientRedirectToURL: %@ ", [frame _drt_descriptionSuitableForTestResult], [URL _drt_descriptionSuitableForTestResult]]; printf ("%s\n", [string UTF8String]); } @@ -308,7 +320,7 @@ - (void)webView:(WebView *)sender didCancelClientRedirectForFrame:(WebFrame *)frame { - if (!done && layoutTestController->dumpFrameLoadCallbacks()) { + if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) { NSString *string = [NSString stringWithFormat:@"%@ - didCancelClientRedirectForFrame", [frame _drt_descriptionSuitableForTestResult]]; printf ("%s\n", [string UTF8String]); } @@ -316,15 +328,21 @@ - (void)webView:(WebView *)sender didFinishDocumentLoadForFrame:(WebFrame *)frame; { - if (!done && layoutTestController->dumpFrameLoadCallbacks()) { + if (!done && gLayoutTestController->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 && layoutTestController->dumpFrameLoadCallbacks()) { + if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) { NSString *string = [NSString stringWithFormat:@"%@ - didHandleOnloadEventsForFrame", [frame _drt_descriptionSuitableForTestResult]]; printf ("%s\n", [string UTF8String]); } diff --git a/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm b/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm index b321319..2200c27 100644 --- a/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm +++ b/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm @@ -36,13 +36,19 @@ #import <JavaScriptCore/JSRetainPtr.h> #import <JavaScriptCore/JSStringRef.h> #import <JavaScriptCore/JSStringRefCF.h> +#import <WebKit/DOMDocument.h> #import <WebKit/WebBackForwardList.h> +#import <WebKit/WebDatabaseManagerPrivate.h> +#import <WebKit/WebDataSource.h> #import <WebKit/WebFrame.h> +#import <WebKit/WebHTMLRepresentation.h> #import <WebKit/WebHTMLViewPrivate.h> #import <WebKit/WebHistory.h> +#import <WebKit/WebInspector.h> #import <WebKit/WebNSURLExtras.h> #import <WebKit/WebPreferences.h> #import <WebKit/WebPreferencesPrivate.h> +#import <WebKit/WebSecurityOriginPrivate.h> #import <WebKit/WebView.h> #import <WebKit/WebViewPrivate.h> #import <wtf/RetainPtr.h> @@ -65,6 +71,11 @@ void LayoutTestController::addDisallowedURL(JSStringRef url) CFSetAddValue(disallowedURLs, [request URL]); } +void LayoutTestController::clearAllDatabases() +{ + [[WebDatabaseManager sharedWebDatabaseManager] deleteAllDatabases]; +} + void LayoutTestController::clearBackForwardList() { WebBackForwardList *backForwardList = [[mainFrame webView] backForwardList]; @@ -170,6 +181,13 @@ void LayoutTestController::setCustomPolicyDelegate(bool setDelegate) [[mainFrame webView] setPolicyDelegate:nil]; } +void LayoutTestController::setDatabaseQuota(unsigned long long quota) +{ + WebSecurityOrigin *origin = [[WebSecurityOrigin alloc] initWithURL:[NSURL URLWithString:@"file:///"]]; + [origin setQuota:quota]; + [origin release]; +} + void LayoutTestController::setMainFrameIsFirstResponder(bool flag) { NSView *documentView = [[mainFrame frameView] documentView]; @@ -232,13 +250,24 @@ void LayoutTestController::setWindowIsKey(bool windowIsKey) [(WebHTMLView *)documentView _updateFocusedAndActiveState]; } +void LayoutTestController::setSmartInsertDeleteEnabled(bool flag) +{ + [[mainFrame webView] setSmartInsertDeleteEnabled:flag]; +} + +void LayoutTestController::setJavaScriptProfilingEnabled(bool profilingEnabled) +{ + [[[mainFrame webView] preferences] setDeveloperExtrasEnabled:profilingEnabled]; + [[[mainFrame webView] inspector] setJavaScriptProfilingEnabled:profilingEnabled]; +} + static const CFTimeInterval waitToDumpWatchdogInterval = 10.0; static void waitUntilDoneWatchdogFired(CFRunLoopTimerRef timer, void* info) { const char* message = "FAIL: Timed out waiting for notifyDone to be called\n"; - fprintf(stderr, message); - fprintf(stdout, message); + fprintf(stderr, "%s", message); + fprintf(stdout, "%s", message); dump(); } @@ -256,6 +285,20 @@ int LayoutTestController::windowCount() return CFArrayGetCount(openWindowsRef); } +bool LayoutTestController::elementDoesAutoCompleteForElementWithId(JSStringRef id) +{ + RetainPtr<CFStringRef> idCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, id)); + NSString *idNS = (NSString *)idCF.get(); + + DOMElement *element = [[mainFrame DOMDocument] getElementById:idNS]; + id rep = [[mainFrame dataSource] representation]; + + if ([rep class] == [WebHTMLRepresentation class]) + return [(WebHTMLRepresentation *)rep elementDoesAutoComplete:element]; + + return false; +} + void LayoutTestController::execCommand(JSStringRef name, JSStringRef value) { RetainPtr<CFStringRef> nameCF(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, name)); diff --git a/WebKitTools/DumpRenderTree/mac/ObjCController.m b/WebKitTools/DumpRenderTree/mac/ObjCController.m index 1b9abb7..ec1ed38 100644 --- a/WebKitTools/DumpRenderTree/mac/ObjCController.m +++ b/WebKitTools/DumpRenderTree/mac/ObjCController.m @@ -28,11 +28,28 @@ #import "ObjCController.h" +#import <JavaScriptCore/JavaScriptCore.h> #import <WebKit/DOMAbstractView.h> #import <WebKit/WebScriptObject.h> #import <WebKit/WebView.h> +#import <pthread.h> #import <wtf/Assertions.h> +static void* runJavaScriptThread(void* arg) +{ + JSGlobalContextRef ctx = JSGlobalContextCreate(0); + JSStringRef scriptRef = JSStringCreateWithUTF8CString("'Hello World!'"); + + JSValueRef exception = 0; + JSEvaluateScript(ctx, scriptRef, 0, 0, 1, &exception); + ASSERT(!exception); + + JSGlobalContextRelease(ctx); + JSStringRelease(scriptRef); + + return 0; +} + @implementation ObjCController + (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector @@ -46,6 +63,8 @@ || aSelector == @selector(testWrapperRoundTripping:) || aSelector == @selector(accessStoredWebScriptObject) || aSelector == @selector(storeWebScriptObject:) + || aSelector == @selector(testValueForKey) + || aSelector == @selector(testArray) ) return NO; return YES; @@ -67,6 +86,10 @@ return @"testWrapperRoundTripping"; if (aSelector == @selector(storeWebScriptObject:)) return @"storeWebScriptObject"; + if (aSelector == @selector(testValueForKey)) + return @"testValueForKey"; + if (aSelector == @selector(testArray)) + return @"testArray"; return nil; } @@ -115,6 +138,20 @@ return num; } +- (void)testValueForKey +{ + ASSERT(storedWebScriptObject); + + @try { + [storedWebScriptObject valueForKey:@"ThisKeyDoesNotExist"]; + } @catch (NSException *e) { + } + + pthread_t pthread; + pthread_create(&pthread, 0, &runJavaScriptThread, 0); + pthread_join(pthread, 0); +} + - (BOOL)testWrapperRoundTripping:(WebScriptObject *)webScriptObject { JSObjectRef jsObject = [webScriptObject JSObject]; @@ -182,6 +219,11 @@ storedWebScriptObject = [webScriptObject retain]; } +- (NSArray *)testArray +{ + return [NSArray array]; +} + - (void)dealloc { [storedWebScriptObject release]; diff --git a/WebKitTools/DumpRenderTree/mac/ObjCPlugin.m b/WebKitTools/DumpRenderTree/mac/ObjCPlugin.m index 18b174c..3ec3e74 100644 --- a/WebKitTools/DumpRenderTree/mac/ObjCPlugin.m +++ b/WebKitTools/DumpRenderTree/mac/ObjCPlugin.m @@ -110,7 +110,7 @@ static BOOL _allowsScriptsFullAccess = NO; - (void)log:(NSString *)message { - NSLog(message); + NSLog(@"%@", message); } - (id)retainObject:(id)obj diff --git a/WebKitTools/DumpRenderTree/mac/PixelDumpSupportMac.mm b/WebKitTools/DumpRenderTree/mac/PixelDumpSupportMac.mm index 5a19164..f4191e5 100644 --- a/WebKitTools/DumpRenderTree/mac/PixelDumpSupportMac.mm +++ b/WebKitTools/DumpRenderTree/mac/PixelDumpSupportMac.mm @@ -34,129 +34,208 @@ #include "LayoutTestController.h" #include <CoreGraphics/CGBitmapContext.h> +#ifndef BUILDING_ON_LEOPARD +#include <OpenGL/OpenGL.h> +#include <OpenGL/CGLMacro.h> +#endif #include <wtf/Assertions.h> -#include <wtf/RetainPtr.h> +#include <wtf/RefPtr.h> #import <WebKit/WebDocumentPrivate.h> #import <WebKit/WebKit.h> -static unsigned char* screenCaptureBuffer; +// To ensure pixel tests consistency, we need to always render in the same colorspace. +// Unfortunately, because of AppKit / WebKit constraints, we can't render directly in the colorspace of our choice. +// This implies we have to temporarily change the profile of the main display to the colorspace we want to render into. +// We also need to make sure the CGBitmapContext we return is in that same colorspace. -static CMProfileRef currentColorProfile = 0; -static CGColorSpaceRef sharedColorSpace; +#define PROFILE_PATH "/System/Library/ColorSync/Profiles/Generic RGB Profile.icc" // FIXME: This cannot be more than CS_MAX_PATH (256 characters) -void restoreColorSpace(int ignored) +static CMProfileLocation sInitialProfileLocation; // The locType field is initialized to 0 which is the same as cmNoProfileBase + +void restoreMainDisplayColorProfile(int ignored) { // This is used as a signal handler, and thus the calls into ColorSync are unsafe // But we might as well try to restore the user's color profile, we're going down anyway... - if (currentColorProfile) { - // This call is deprecated in Leopard, but there appears to be no replacement. - int error = CMSetDefaultProfileByUse(cmDisplayUse, currentColorProfile); + if (sInitialProfileLocation.locType != cmNoProfileBase) { + const CMDeviceScope scope = { kCFPreferencesCurrentUser, kCFPreferencesCurrentHost }; + int error = CMSetDeviceProfile(cmDisplayDeviceClass, (CMDeviceID)kCGDirectMainDisplay, &scope, cmDefaultProfileID, &sInitialProfileLocation); if (error) - fprintf(stderr, "Failed to retore previous color profile! You may need to open System Preferences : Displays : Color and manually restore your color settings. (Error: %i)", error); - currentColorProfile = 0; + fprintf(stderr, "Failed to restore initial color profile for main display! Open System Preferences > Displays > Color and manually re-select the profile. (Error: %i)", error); + sInitialProfileLocation.locType = cmNoProfileBase; } } -static void setDefaultColorProfileToRGB() +void setupMainDisplayColorProfile() { - CMProfileRef genericProfile = (CMProfileRef)[[NSColorSpace genericRGBColorSpace] colorSyncProfile]; - CMProfileRef previousProfile; - int error = CMGetDefaultProfileByUse(cmDisplayUse, &previousProfile); + const CMDeviceScope scope = { kCFPreferencesCurrentUser, kCFPreferencesCurrentHost }; + int error; + + CMProfileRef profile = 0; + error = CMGetProfileByAVID((CMDisplayIDType)kCGDirectMainDisplay, &profile); + if (!error) { + UInt32 size = sizeof(CMProfileLocation); + error = NCMGetProfileLocation(profile, &sInitialProfileLocation, &size); + CMCloseProfile(profile); + } if (error) { - fprintf(stderr, "Failed to get current color profile. I will not be able to restore your current profile, thus I'm not changing it. Many pixel tests may fail as a result. (Error: %i)\n", error); + fprintf(stderr, "Failed to retrieve current color profile for main display, thus it won't be changed. Many pixel tests may fail as a result. (Error: %i)", error); + sInitialProfileLocation.locType = cmNoProfileBase; return; } - if (previousProfile == genericProfile) - return; - CFStringRef previousProfileName; - CFStringRef genericProfileName; - char previousProfileNameString[1024]; - char genericProfileNameString[1024]; - CMCopyProfileDescriptionString(previousProfile, &previousProfileName); - CMCopyProfileDescriptionString(genericProfile, &genericProfileName); - CFStringGetCString(previousProfileName, previousProfileNameString, sizeof(previousProfileNameString), kCFStringEncodingUTF8); - CFStringGetCString(genericProfileName, genericProfileNameString, sizeof(previousProfileNameString), kCFStringEncodingUTF8); - CFRelease(previousProfileName); - CFRelease(genericProfileName); - - fprintf(stderr, "\n\nWARNING: Temporarily changing your system color profile from \"%s\" to \"%s\".\n", previousProfileNameString, genericProfileNameString); - fprintf(stderr, "This allows the WebKit pixel-based regression tests to have consistent color values across all machines.\n"); - fprintf(stderr, "The colors on your screen will change for the duration of the testing.\n\n"); - if ((error = CMSetDefaultProfileByUse(cmDisplayUse, genericProfile))) { - fprintf(stderr, "Failed to set color profile to \"%s\"! Many pixel tests will fail as a result. (Error: %i)", - genericProfileNameString, error); - } else { - currentColorProfile = previousProfile; - signal(SIGINT, restoreColorSpace); - signal(SIGHUP, restoreColorSpace); - signal(SIGTERM, restoreColorSpace); + CMProfileLocation location; + location.locType = cmPathBasedProfile; + strcpy(location.u.pathLoc.path, PROFILE_PATH); + error = CMSetDeviceProfile(cmDisplayDeviceClass, (CMDeviceID)kCGDirectMainDisplay, &scope, cmDefaultProfileID, &location); + if (error) { + fprintf(stderr, "Failed to set color profile for main display! Many pixel tests may fail as a result. (Error: %i)", error); + sInitialProfileLocation.locType = cmNoProfileBase; + return; } + + // Other signals are handled in installSignalHandlers() which also calls restoreMainDisplayColorProfile() + signal(SIGINT, restoreMainDisplayColorProfile); + signal(SIGHUP, restoreMainDisplayColorProfile); + signal(SIGTERM, restoreMainDisplayColorProfile); + + fprintf(stderr, "\n\nWARNING: Temporarily changing the main display color profile to \"%s\": the colors on your screen will change for the duration of the testing.\n", PROFILE_PATH); + fprintf(stderr, "This allows the WebKit pixel-based regression tests to have consistent color values across all machines.\n"); } -void initializeColorSpaceAndScreeBufferForPixelTests() -{ - setDefaultColorProfileToRGB(); - screenCaptureBuffer = (unsigned char *)malloc(maxViewHeight * maxViewWidth * 4); - sharedColorSpace = CGColorSpaceCreateDeviceRGB(); -} - -// Declared in PixelDumpSupportCG.h - -RetainPtr<CGContextRef> getBitmapContextFromWebView() -{ - NSSize webViewSize = [[mainFrame webView] frame].size; - return RetainPtr<CGContextRef>(AdoptCF, CGBitmapContextCreate(screenCaptureBuffer, static_cast<size_t>(webViewSize.width), static_cast<size_t>(webViewSize.height), 8, static_cast<size_t>(webViewSize.width) * 4, sharedColorSpace, kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedLast)); -} - -void paintWebView(CGContextRef context) +PassRefPtr<BitmapContext> createBitmapContextFromWebView(bool onscreen, bool incrementalRepaint, bool sweepHorizontally, bool drawSelectionRect) { - RetainPtr<NSGraphicsContext> savedContext = [NSGraphicsContext currentContext]; - - NSGraphicsContext* nsContext = [NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:NO]; - [NSGraphicsContext setCurrentContext:nsContext]; - WebView* view = [mainFrame webView]; - [view displayIfNeeded]; - [view lockFocus]; - NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:[view frame]]; - [view unlockFocus]; - [imageRep draw]; - [imageRep release]; - - [NSGraphicsContext setCurrentContext:savedContext.get()]; -} - -void repaintWebView(CGContextRef context, bool horizontal) -{ - RetainPtr<NSGraphicsContext> savedContext = [NSGraphicsContext currentContext]; - - NSGraphicsContext* nsContext = [NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:NO]; - [NSGraphicsContext setCurrentContext:nsContext]; - - WebView *view = [mainFrame webView]; NSSize webViewSize = [view frame].size; + size_t pixelsWide = static_cast<size_t>(webViewSize.width); + size_t pixelsHigh = static_cast<size_t>(webViewSize.height); + size_t rowBytes = (4 * pixelsWide + 63) & ~63; // Use a multiple of 64 bytes to improve CG performance - if (horizontal) { - for (NSRect column = NSMakeRect(0, 0, 1, webViewSize.height); column.origin.x < webViewSize.width; column.origin.x++) - [view displayRectIgnoringOpacity:column inContext:nsContext]; - } else { - for (NSRect line = NSMakeRect(0, 0, webViewSize.width, 1); line.origin.y < webViewSize.height; line.origin.y++) - [view displayRectIgnoringOpacity:line inContext:nsContext]; + void *buffer = calloc(pixelsHigh, rowBytes); + if (!buffer) + return 0; + + static CGColorSpaceRef colorSpace = 0; + if (!colorSpace) { + CMProfileLocation location; + location.locType = cmPathBasedProfile; + strcpy(location.u.pathLoc.path, PROFILE_PATH); + CMProfileRef profile; + if (CMOpenProfile(&profile, &location) == noErr) { + colorSpace = CGColorSpaceCreateWithPlatformColorSpace(profile); + CMCloseProfile(profile); + } + } + + CGContextRef context = CGBitmapContextCreate(buffer, pixelsWide, pixelsHigh, 8, rowBytes, colorSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host); // Use ARGB8 on PPC or BGRA8 on X86 to improve CG performance + if (!context) { + free(buffer); + return 0; } - [NSGraphicsContext setCurrentContext:savedContext.get()]; -} + // The BitmapContext keeps the CGContextRef and the pixel buffer alive + RefPtr<BitmapContext> bitmapContext = BitmapContext::createByAdoptingBitmapAndContext(buffer, context); + + NSGraphicsContext *nsContext = [NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:NO]; + ASSERT(nsContext); + + if (incrementalRepaint) { + if (sweepHorizontally) { + for (NSRect column = NSMakeRect(0, 0, 1, webViewSize.height); column.origin.x < webViewSize.width; column.origin.x++) + [view displayRectIgnoringOpacity:column inContext:nsContext]; + } else { + for (NSRect line = NSMakeRect(0, 0, webViewSize.width, 1); line.origin.y < webViewSize.height; line.origin.y++) + [view displayRectIgnoringOpacity:line inContext:nsContext]; + } + } else { + if (onscreen) { +#ifdef BUILDING_ON_LEOPARD + // Ask the window server to provide us a composited version of the *real* window content including surfaces (i.e. OpenGL content) + // Note that the returned image might differ very slightly from the window backing because of dithering artifacts in the window server compositor + + CGImageRef image = CGWindowListCreateImage(CGRectNull, kCGWindowListOptionIncludingWindow, [[view window] windowNumber], kCGWindowImageBoundsIgnoreFraming | kCGWindowImageShouldBeOpaque); + CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)), image); + CGImageRelease(image); +#else + // On 10.4 and earlier, we have to move the window temporarily "onscreen" and read directly from the display framebuffer using OpenGL + // In this code path, we need to ensure the window is above any other window or captured result will be corrupted + + NSWindow *window = [view window]; + int oldLevel = [window level]; + NSRect oldFrame = [window frame]; + + NSRect newFrame = [[[NSScreen screens] objectAtIndex:0] frame]; + newFrame = NSMakeRect(newFrame.origin.x + (newFrame.size.width - oldFrame.size.width) / 2, newFrame.origin.y + (newFrame.size.height - oldFrame.size.height) / 2, oldFrame.size.width, oldFrame.size.height); + [window setLevel:NSScreenSaverWindowLevel]; + [window setFrame:newFrame display:NO animate:NO]; + + CGRect rect = CGRectMake(newFrame.origin.x, newFrame.origin.y, webViewSize.width, webViewSize.height); + CGDirectDisplayID displayID; + CGDisplayCount count; + if (CGGetDisplaysWithRect(rect, 1, &displayID, &count) == kCGErrorSuccess) { + CGRect bounds = CGDisplayBounds(displayID); + rect.origin.x -= bounds.origin.x; + rect.origin.y -= bounds.origin.y; + + CGLPixelFormatAttribute attributes[] = {kCGLPFAAccelerated, kCGLPFANoRecovery, kCGLPFAFullScreen, kCGLPFADisplayMask, (CGLPixelFormatAttribute)CGDisplayIDToOpenGLDisplayMask(displayID), (CGLPixelFormatAttribute)0}; + CGLPixelFormatObj pixelFormat; + GLint num; + if (CGLChoosePixelFormat(attributes, &pixelFormat, &num) == kCGLNoError) { + CGLContextObj cgl_ctx; + if (CGLCreateContext(pixelFormat, 0, &cgl_ctx) == kCGLNoError) { + if (CGLSetFullScreen(cgl_ctx) == kCGLNoError) { + void *flipBuffer = calloc(pixelsHigh, rowBytes); + if (flipBuffer) { + glPixelStorei(GL_PACK_ROW_LENGTH, rowBytes / 4); + glPixelStorei(GL_PACK_ALIGNMENT, 4); +#if __BIG_ENDIAN__ + glReadPixels(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, flipBuffer); +#else + glReadPixels(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, flipBuffer); +#endif + if (!glGetError()) { + for(size_t i = 0; i < pixelsHigh; ++i) + bcopy((char*)flipBuffer + rowBytes * i, (char*)buffer + rowBytes * (pixelsHigh - i - 1), pixelsWide * 4); + } + + free(flipBuffer); + } + } + CGLDestroyContext(cgl_ctx); + } + CGLDestroyPixelFormat(pixelFormat); + } + } + + [window setFrame:oldFrame display:NO animate:NO]; + [window setLevel:oldLevel]; +#endif + } else { + // Grab directly the contents of the window backing buffer (this ignores any surfaces on the window) + // FIXME: This path is suboptimal: data is read from window backing store, converted to RGB8 then drawn again into an RGBA8 bitmap + + [view displayIfNeeded]; + [view lockFocus]; + NSBitmapImageRep *imageRep = [[[NSBitmapImageRep alloc] initWithFocusedViewRect:[view frame]] autorelease]; + [view unlockFocus]; + + RetainPtr<NSGraphicsContext> savedContext = [NSGraphicsContext currentContext]; + [NSGraphicsContext setCurrentContext:nsContext]; + [imageRep draw]; + [NSGraphicsContext setCurrentContext:savedContext.get()]; + } + } -CGRect getSelectionRect() -{ - NSView *documentView = [[mainFrame frameView] documentView]; - if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)]) { + if (drawSelectionRect) { + NSView *documentView = [[mainFrame frameView] documentView]; + ASSERT([documentView conformsToProtocol:@protocol(WebDocumentSelection)]); NSRect rect = [documentView convertRect:[(id <WebDocumentSelection>)documentView selectionRect] fromView:nil]; - return CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); + CGContextSaveGState(context); + CGContextSetLineWidth(context, 1.0); + CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0); + CGContextStrokeRect(context, CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height)); + CGContextRestoreGState(context); } - - ASSERT_NOT_REACHED(); - return CGRectZero; + + return bitmapContext.release(); } diff --git a/WebKitTools/DumpRenderTree/mac/ResourceLoadDelegate.mm b/WebKitTools/DumpRenderTree/mac/ResourceLoadDelegate.mm index cc0eb4a..5d2e2b4 100644 --- a/WebKitTools/DumpRenderTree/mac/ResourceLoadDelegate.mm +++ b/WebKitTools/DumpRenderTree/mac/ResourceLoadDelegate.mm @@ -31,6 +31,7 @@ #import "DumpRenderTree.h" #import "LayoutTestController.h" #import <WebKit/WebKit.h> +#import <WebKit/WebTypesInternal.h> #import <wtf/Assertions.h> @interface NSURL (DRTExtras) @@ -54,12 +55,12 @@ { NSString *str = [NSString stringWithFormat:@"<NSError domain %@, code %d", [self domain], [self code]]; NSURL *failingURL; - + if ((failingURL = [[self userInfo] objectForKey:@"NSErrorFailingURLKey"])) str = [str stringByAppendingFormat:@", failing URL \"%@\"", [failingURL _drt_descriptionSuitableForTestResult]]; - + str = [str stringByAppendingFormat:@">"]; - + return str; } @@ -75,9 +76,9 @@ WebDataSource *dataSource = [mainFrame dataSource]; if (!dataSource) dataSource = [mainFrame provisionalDataSource]; - + NSString *basePath = [[[[dataSource request] URL] path] stringByDeletingLastPathComponent]; - + return [[self path] substringFromIndex:[basePath length] + 1]; } @@ -106,24 +107,35 @@ - webView: (WebView *)wv identifierForInitialRequest: (NSURLRequest *)request fromDataSource: (WebDataSource *)dataSource { ASSERT([[dataSource webFrame] dataSource] || [[dataSource webFrame] provisionalDataSource]); - - if (!done && layoutTestController->dumpResourceLoadCallbacks()) + + if (!done && gLayoutTestController->dumpResourceLoadCallbacks()) return [[request URL] _drt_descriptionSuitableForTestResult]; - + return @"<unknown>"; } -(NSURLRequest *)webView: (WebView *)wv resource:identifier willSendRequest: (NSURLRequest *)newRequest redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)dataSource { - if (!done && layoutTestController->dumpResourceLoadCallbacks()) { + if (!done && gLayoutTestController->dumpResourceLoadCallbacks()) { NSString *string = [NSString stringWithFormat:@"%@ - willSendRequest %@ redirectResponse %@", identifier, [newRequest _drt_descriptionSuitableForTestResult], [redirectResponse _drt_descriptionSuitableForTestResult]]; - printf ("%s\n", [string UTF8String]); - } - - if (disallowedURLs && CFSetContainsValue(disallowedURLs, [newRequest URL])) + printf("%s\n", [string UTF8String]); + } + + NSURL *url = [newRequest URL]; + NSString *host = [url host]; + if (host + && (NSOrderedSame == [[url scheme] caseInsensitiveCompare:@"http"] || NSOrderedSame == [[url scheme] caseInsensitiveCompare:@"https"]) + && NSOrderedSame != [host compare:@"127.0.0.1"] + && NSOrderedSame != [host compare:@"255.255.255.255"] // used in some tests that expect to get back an error + && NSOrderedSame != [host caseInsensitiveCompare:@"localhost"]) { + printf("Blocked access to external URL %s\n", [[url absoluteString] cStringUsingEncoding:NSUTF8StringEncoding]); return nil; - + } + + if (disallowedURLs && CFSetContainsValue(disallowedURLs, url)) + return nil; + return newRequest; } @@ -137,41 +149,44 @@ -(void)webView: (WebView *)wv resource:identifier didReceiveResponse: (NSURLResponse *)response fromDataSource:(WebDataSource *)dataSource { - if (!done && layoutTestController->dumpResourceLoadCallbacks()) { + if (!done && gLayoutTestController->dumpResourceLoadCallbacks()) { NSString *string = [NSString stringWithFormat:@"%@ - didReceiveResponse %@", identifier, [response _drt_descriptionSuitableForTestResult]]; - printf ("%s\n", [string UTF8String]); - } + printf("%s\n", [string UTF8String]); + } } --(void)webView: (WebView *)wv resource:identifier didReceiveContentLength: (unsigned)length fromDataSource:(WebDataSource *)dataSource +-(void)webView: (WebView *)wv resource:identifier didReceiveContentLength: (NSInteger)length fromDataSource:(WebDataSource *)dataSource { } -(void)webView: (WebView *)wv resource:identifier didFinishLoadingFromDataSource:(WebDataSource *)dataSource { - if (!done && layoutTestController->dumpResourceLoadCallbacks()) { + if (!done && gLayoutTestController->dumpResourceLoadCallbacks()) { NSString *string = [NSString stringWithFormat:@"%@ - didFinishLoading", identifier]; - printf ("%s\n", [string UTF8String]); + printf("%s\n", [string UTF8String]); } } -(void)webView: (WebView *)wv resource:identifier didFailLoadingWithError:(NSError *)error fromDataSource:(WebDataSource *)dataSource { - if (!done && layoutTestController->dumpResourceLoadCallbacks()) { + if (!done && gLayoutTestController->dumpResourceLoadCallbacks()) { NSString *string = [NSString stringWithFormat:@"%@ - didFailLoadingWithError: %@", identifier, [error _drt_descriptionSuitableForTestResult]]; - printf ("%s\n", [string UTF8String]); + printf("%s\n", [string UTF8String]); } } - (void)webView: (WebView *)wv plugInFailedWithError:(NSError *)error dataSource:(WebDataSource *)dataSource { + // The call to -display here simulates the "Plug-in not found" sheet that Safari shows. + // It is used for platform/mac/plugins/update-widget-from-style-recalc.html + [wv display]; } -(NSCachedURLResponse *) webView: (WebView *)wv resource:(id)identifier willCacheResponse:(NSCachedURLResponse *)response fromDataSource:(WebDataSource *)dataSource { - if (!done && layoutTestController->dumpResourceLoadCallbacks()) { + if (!done && gLayoutTestController->dumpResourceLoadCallbacks()) { NSString *string = [NSString stringWithFormat:@"%@ - willCacheResponse: called", identifier]; - printf ("%s\n", [string UTF8String]); + printf("%s\n", [string UTF8String]); } return response; } diff --git a/WebKitTools/DumpRenderTree/mac/UIDelegate.mm b/WebKitTools/DumpRenderTree/mac/UIDelegate.mm index 29f3ddd..0c5a93c 100644 --- a/WebKitTools/DumpRenderTree/mac/UIDelegate.mm +++ b/WebKitTools/DumpRenderTree/mac/UIDelegate.mm @@ -84,10 +84,18 @@ DumpRenderTreeDraggingInfo *draggingInfo = nil; return defaultText; } +- (BOOL)webView:(WebView *)c runBeforeUnloadConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame +{ + if (!done) + printf("CONFIRM NAVIGATION: %s\n", [message UTF8String]); + return YES; +} + + - (void)webView:(WebView *)sender dragImage:(NSImage *)anImage at:(NSPoint)viewLocation offset:(NSSize)initialOffset event:(NSEvent *)event pasteboard:(NSPasteboard *)pboard source:(id)sourceObj slideBack:(BOOL)slideFlag forView:(NSView *)view { assert(!draggingInfo); - if (layoutTestController->addFileToPasteboardOnDrag()) { + if (gLayoutTestController->addFileToPasteboardOnDrag()) { [pboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType] owner:nil]; [pboard setPropertyList:[NSArray arrayWithObject:@"DRTFakeFile"] forType:NSFilenamesPboardType]; } @@ -97,19 +105,21 @@ DumpRenderTreeDraggingInfo *draggingInfo = nil; - (void)webViewFocus:(WebView *)webView { - layoutTestController->setWindowIsKey(true); - NSView *documentView = [[mainFrame frameView] documentView]; - if ([documentView isKindOfClass:[WebHTMLView class]]) - [(WebHTMLView *)documentView _updateFocusedAndActiveState]; + gLayoutTestController->setWindowIsKey(true); +} + +- (void)webViewUnfocus:(WebView *)webView +{ + gLayoutTestController->setWindowIsKey(false); } - (WebView *)webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request { - if (!layoutTestController->canOpenWindows()) + if (!gLayoutTestController->canOpenWindows()) return nil; // Make sure that waitUntilDone has been called. - ASSERT(layoutTestController->waitToDump()); + ASSERT(gLayoutTestController->waitToDump()); WebView *webView = createWebViewAndOffscreenWindow(); @@ -120,7 +130,7 @@ DumpRenderTreeDraggingInfo *draggingInfo = nil; { NSWindow* window = [sender window]; - if (layoutTestController->callCloseOnWebViews()) + if (gLayoutTestController->callCloseOnWebViews()) [sender close]; [window close]; @@ -128,10 +138,19 @@ DumpRenderTreeDraggingInfo *draggingInfo = nil; - (void)webView:(WebView *)sender frame:(WebFrame *)frame exceededDatabaseQuotaForSecurityOrigin:(WebSecurityOrigin *)origin database:(NSString *)databaseIdentifier { - static const unsigned long long defaultQuota = 5 * 1024 * 1024; + if (!done && gLayoutTestController->dumpDatabaseCallbacks()) + printf("UI DELEGATE DATABASE CALLBACK: exceededDatabaseQuotaForSecurityOrigin:{%s, %s, %i} database:%s\n", [[origin protocol] UTF8String], [[origin host] UTF8String], + [origin port], [databaseIdentifier UTF8String]); + + static const unsigned long long defaultQuota = 5 * 1024 * 1024; [origin setQuota:defaultQuota]; } +- (void)webView:(WebView *)sender setStatusText:(NSString *)text +{ + if (gLayoutTestController->dumpStatusCallbacks()) + printf("UI DELEGATE STATUS CALLBACK: setStatusText:%s\n", [text UTF8String]); +} - (void)dealloc { |