diff options
Diffstat (limited to 'WebKitTools/DumpRenderTree')
47 files changed, 1562 insertions, 331 deletions
diff --git a/WebKitTools/DumpRenderTree/AccessibilityController.cpp b/WebKitTools/DumpRenderTree/AccessibilityController.cpp index d3688f4..045bc80 100644 --- a/WebKitTools/DumpRenderTree/AccessibilityController.cpp +++ b/WebKitTools/DumpRenderTree/AccessibilityController.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008, 2009, 2010 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -63,6 +63,13 @@ static JSValueRef logFocusEventsCallback(JSContextRef ctx, JSObjectRef, JSObject return JSValueMakeUndefined(ctx); } +static JSValueRef logValueChangeEventsCallback(JSContextRef ctx, JSObjectRef, JSObjectRef thisObject, size_t, const JSValueRef[], JSValueRef*) +{ + AccessibilityController* controller = static_cast<AccessibilityController*>(JSObjectGetPrivate(thisObject)); + controller->setLogValueChangeEvents(true); + return JSValueMakeUndefined(ctx); +} + static JSValueRef logScrollingStartEventsCallback(JSContextRef ctx, JSObjectRef, JSObjectRef thisObject, size_t, const JSValueRef[], JSValueRef*) { AccessibilityController* controller = static_cast<AccessibilityController*>(JSObjectGetPrivate(thisObject)); @@ -74,6 +81,7 @@ JSClassRef AccessibilityController::getJSClass() { static JSStaticFunction staticFunctions[] = { { "logFocusEvents", logFocusEventsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "logValueChangeEvents", logValueChangeEventsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "logScrollingStartEvents", logScrollingStartEventsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { 0, 0, 0 } }; @@ -95,5 +103,6 @@ JSClassRef AccessibilityController::getJSClass() void AccessibilityController::resetToConsistentState() { setLogFocusEvents(false); + setLogValueChangeEvents(false); setLogScrollingStartEvents(false); } diff --git a/WebKitTools/DumpRenderTree/AccessibilityController.h b/WebKitTools/DumpRenderTree/AccessibilityController.h index a10e8be..de58f84 100644 --- a/WebKitTools/DumpRenderTree/AccessibilityController.h +++ b/WebKitTools/DumpRenderTree/AccessibilityController.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008, 2009, 2010 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,13 +26,15 @@ #ifndef AccessibilityController_h #define AccessibilityController_h +#include "AccessibilityUIElement.h" #include <JavaScriptCore/JSObjectRef.h> +#include <string> +#include <wtf/HashMap.h> +#include <wtf/Platform.h> #if PLATFORM(WIN) #include <windows.h> #endif -class AccessibilityUIElement; - class AccessibilityController { public: AccessibilityController(); @@ -45,16 +47,24 @@ public: AccessibilityUIElement focusedElement(); void setLogFocusEvents(bool); + void setLogValueChangeEvents(bool); void setLogScrollingStartEvents(bool); void resetToConsistentState(); + void addNotificationListener(PlatformUIElement, JSObjectRef functionCallback); + void notificationReceived(PlatformUIElement, const std::string& eventName); + private: static JSClassRef getJSClass(); #if PLATFORM(WIN) HWINEVENTHOOK m_focusEventHook; + HWINEVENTHOOK m_valueChangeEventHook; HWINEVENTHOOK m_scrollingStartEventHook; + + HWINEVENTHOOK m_allEventsHook; + HashMap<PlatformUIElement, JSObjectRef> m_notificationListeners; #endif }; diff --git a/WebKitTools/DumpRenderTree/AccessibilityUIElement.cpp b/WebKitTools/DumpRenderTree/AccessibilityUIElement.cpp index 8c59252..87fe05c 100644 --- a/WebKitTools/DumpRenderTree/AccessibilityUIElement.cpp +++ b/WebKitTools/DumpRenderTree/AccessibilityUIElement.cpp @@ -152,6 +152,16 @@ static JSValueRef stringForRangeCallback(JSContextRef context, JSObjectRef funct return JSValueMakeString(context, stringDescription.get()); } +static JSValueRef indexOfChildCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + if (argumentCount != 1) + return 0; + + JSObjectRef otherElement = JSValueToObject(context, arguments[0], exception); + AccessibilityUIElement* childElement = toAXElement(otherElement); + return JSValueMakeNumber(context, (double)toAXElement(thisObject)->indexOfChild(childElement)); +} + static JSValueRef childAtIndexCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { int indexNumber = -1; @@ -254,13 +264,25 @@ static JSValueRef isActionSupportedCallback(JSContextRef context, JSObjectRef fu return result; } -static JSValueRef attributeValueCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +static JSValueRef boolAttributeValueCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { JSStringRef attribute = 0; if (argumentCount == 1) attribute = JSValueToStringCopy(context, arguments[0], exception); - JSRetainPtr<JSStringRef> attributeValue(Adopt, toAXElement(thisObject)->attributeValue(attribute)); - JSValueRef result = JSValueMakeString(context, attributeValue.get()); + bool val = toAXElement(thisObject)->boolAttributeValue(attribute); + JSValueRef result = JSValueMakeBoolean(context, val); + if (attribute) + JSStringRelease(attribute); + return result; +} + +static JSValueRef stringAttributeValueCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + JSStringRef attribute = 0; + if (argumentCount == 1) + attribute = JSValueToStringCopy(context, arguments[0], exception); + JSRetainPtr<JSStringRef> stringAttributeValue(Adopt, toAXElement(thisObject)->stringAttributeValue(attribute)); + JSValueRef result = JSValueMakeString(context, stringAttributeValue.get()); if (attribute) JSStringRelease(attribute); return result; @@ -322,6 +344,31 @@ static JSValueRef showMenuCallback(JSContextRef context, JSObjectRef function, J return JSValueMakeUndefined(context); } +static JSValueRef takeFocusCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + toAXElement(thisObject)->takeFocus(); + return JSValueMakeUndefined(context); +} + +static JSValueRef takeSelectionCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + toAXElement(thisObject)->takeSelection(); + return JSValueMakeUndefined(context); +} + +static JSValueRef addSelectionCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + toAXElement(thisObject)->addSelection(); + return JSValueMakeUndefined(context); +} + +static JSValueRef removeSelectionCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + toAXElement(thisObject)->removeSelection(); + return JSValueMakeUndefined(context); +} + + // Static Value Getters static JSValueRef getARIADropEffectsCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) @@ -470,11 +517,46 @@ static JSValueRef getIsSelectedCallback(JSContextRef context, JSObjectRef thisOb return JSValueMakeBoolean(context, toAXElement(thisObject)->isSelected()); } +static JSValueRef getIsSelectableCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef, JSValueRef*) +{ + return JSValueMakeBoolean(context, toAXElement(thisObject)->isSelectable()); +} + +static JSValueRef getIsMultiSelectableCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef, JSValueRef*) +{ + return JSValueMakeBoolean(context, toAXElement(thisObject)->isMultiSelectable()); +} + static JSValueRef getIsExpandedCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef, JSValueRef*) { return JSValueMakeBoolean(context, toAXElement(thisObject)->isExpanded()); } +static JSValueRef getIsCheckedCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef, JSValueRef*) +{ + return JSValueMakeBoolean(context, toAXElement(thisObject)->isChecked()); +} + +static JSValueRef getIsVisibleCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef, JSValueRef*) +{ + return JSValueMakeBoolean(context, toAXElement(thisObject)->isVisible()); +} + +static JSValueRef getIsOffScreenCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef, JSValueRef*) +{ + return JSValueMakeBoolean(context, toAXElement(thisObject)->isOffScreen()); +} + +static JSValueRef getIsCollapsedCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef, JSValueRef*) +{ + return JSValueMakeBoolean(context, toAXElement(thisObject)->isCollapsed()); +} + +static JSValueRef getHasPopupCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef, JSValueRef*) +{ + return JSValueMakeBoolean(context, toAXElement(thisObject)->hasPopup()); +} + static JSValueRef hierarchicalLevelCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef, JSValueRef*) { return JSValueMakeNumber(context, toAXElement(thisObject)->hierarchicalLevel()); @@ -504,6 +586,22 @@ static JSValueRef getDocumentURICallback(JSContextRef context, JSObjectRef thisO return JSValueMakeString(context, documentURI.get()); } +static JSValueRef getURLCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) +{ + JSRetainPtr<JSStringRef> url(Adopt, toAXElement(thisObject)->url()); + return JSValueMakeString(context, url.get()); +} + +static JSValueRef addNotificationListenerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + if (argumentCount != 1) + return JSValueMakeBoolean(context, false); + + JSObjectRef callback = JSValueToObject(context, arguments[0], exception); + bool succeeded = toAXElement(thisObject)->addNotificationListener(callback); + return JSValueMakeBoolean(context, succeeded); +} + // Destruction static void finalize(JSObjectRef thisObject) @@ -544,11 +642,19 @@ JSClassRef AccessibilityUIElement::getJSClass() { "isEnabled", getIsEnabledCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "isRequired", getIsRequiredCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "isSelected", getIsSelectedCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "isSelectable", getIsSelectableCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "isMultiSelectable", getIsMultiSelectableCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "isExpanded", getIsExpandedCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "isChecked", getIsCheckedCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "isVisible", getIsVisibleCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "isOffScreen", getIsOffScreenCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "isCollapsed", getIsCollapsedCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "hasPopup", getHasPopupCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "valueDescription", getValueDescriptionCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "hierarchicalLevel", hierarchicalLevelCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "documentEncoding", getDocumentEncodingCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "documentURI", getDocumentURICallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "url", getURLCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "isValid", getIsValidCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "orientation", getOrientationCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "ariaIsGrabbed", getARIAIsGrabbedCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, @@ -566,6 +672,7 @@ JSClassRef AccessibilityUIElement::getJSClass() { "boundsForRange", boundsForRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "stringForRange", stringForRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "childAtIndex", childAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "indexOfChild", indexOfChildCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "elementAtPoint", elementAtPointCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "attributesOfColumnHeaders", attributesOfColumnHeadersCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "attributesOfRowHeaders", attributesOfRowHeadersCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, @@ -579,7 +686,8 @@ JSClassRef AccessibilityUIElement::getJSClass() { "cellForColumnAndRow", cellForColumnAndRowCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "titleUIElement", titleUIElementCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setSelectedTextRange", setSelectedTextRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "attributeValue", attributeValueCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "stringAttributeValue", stringAttributeValueCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "boolAttributeValue", boolAttributeValueCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "isAttributeSupported", isAttributeSupportedCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "isAttributeSettable", isAttributeSettableCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "isActionSupported", isActionSupportedCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, @@ -593,6 +701,11 @@ JSClassRef AccessibilityUIElement::getJSClass() { "ariaFlowToElementAtIndex", ariaFlowToElementAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "selectedRowAtIndex", selectedRowAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "isEqual", isEqualCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "addNotificationListener", addNotificationListenerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "takeFocus", takeFocusCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "takeSelection", takeSelectionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "addSelection", addSelectionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "removeSelection", removeSelectionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { 0, 0, 0 } }; diff --git a/WebKitTools/DumpRenderTree/AccessibilityUIElement.h b/WebKitTools/DumpRenderTree/AccessibilityUIElement.h index 9985523..e7d3bc7 100644 --- a/WebKitTools/DumpRenderTree/AccessibilityUIElement.h +++ b/WebKitTools/DumpRenderTree/AccessibilityUIElement.h @@ -70,10 +70,16 @@ public: AccessibilityUIElement elementAtPoint(int x, int y); AccessibilityUIElement getChildAtIndex(unsigned); + unsigned indexOfChild(AccessibilityUIElement*); int childrenCount(); AccessibilityUIElement titleUIElement(); AccessibilityUIElement parentElement(); - + + void takeFocus(); + void takeSelection(); + void addSelection(); + void removeSelection(); + // Methods - platform-independent implementations JSStringRef allAttributes(); JSStringRef attributesOfLinkedUIElements(); @@ -85,7 +91,8 @@ public: void showMenu(); // Attributes - platform-independent implementations - JSStringRef attributeValue(JSStringRef attribute); + JSStringRef stringAttributeValue(JSStringRef attribute); + bool boolAttributeValue(JSStringRef attribute); bool isAttributeSupported(JSStringRef attribute); bool isAttributeSettable(JSStringRef attribute); bool isActionSupported(JSStringRef action); @@ -102,7 +109,7 @@ public: double y(); double width(); double height(); - double intValue(); + double intValue() const; double minValue(); double maxValue(); JSStringRef valueDescription(); @@ -111,12 +118,20 @@ public: bool isEnabled(); bool isRequired() const; bool isSelected() const; + bool isSelectable() const; + bool isMultiSelectable() const; bool isExpanded() const; + bool isChecked() const; + bool isVisible() const; + bool isOffScreen() const; + bool isCollapsed() const; + bool hasPopup() const; int hierarchicalLevel() const; double clickPointX(); double clickPointY(); JSStringRef documentEncoding(); JSStringRef documentURI(); + JSStringRef url(); // Table-specific attributes JSStringRef attributesOfColumnHeaders(); @@ -152,10 +167,15 @@ public: // Table-specific AccessibilityUIElement cellForColumnAndRow(unsigned column, unsigned row); + // Notifications + // Function callback should take one argument, the name of the notification. + bool addNotificationListener(JSObjectRef functionCallback); + private: static JSClassRef getJSClass(); PlatformUIElement m_element; + JSObjectRef m_notificationFunctionCallback; }; #endif // AccessibilityUIElement_h diff --git a/WebKitTools/DumpRenderTree/DumpRenderTree.h b/WebKitTools/DumpRenderTree/DumpRenderTree.h index c11c5f6..8366e89 100644 --- a/WebKitTools/DumpRenderTree/DumpRenderTree.h +++ b/WebKitTools/DumpRenderTree/DumpRenderTree.h @@ -46,7 +46,7 @@ #include <string> -#if !PLATFORM(OPENBSD) +#if !OS(OPENBSD) std::wstring urlSuitableForTestResult(const std::wstring& url); #endif diff --git a/WebKitTools/DumpRenderTree/LayoutTestController.cpp b/WebKitTools/DumpRenderTree/LayoutTestController.cpp index 572d610..e71cd29 100644 --- a/WebKitTools/DumpRenderTree/LayoutTestController.cpp +++ b/WebKitTools/DumpRenderTree/LayoutTestController.cpp @@ -66,6 +66,7 @@ LayoutTestController::LayoutTestController(const std::string& testPathOrURL, con , m_testRepaint(false) , m_testRepaintSweepHorizontally(false) , m_waitToDump(false) + , m_willSendRequestReturnsNull(false) , m_willSendRequestReturnsNullOnRedirect(false) , m_windowIsKey(true) , m_alwaysAcceptCookies(false) @@ -699,6 +700,21 @@ static JSValueRef setDatabaseQuotaCallback(JSContextRef context, JSObjectRef fun return JSValueMakeUndefined(context); } +static JSValueRef setDomainRelaxationForbiddenForURLSchemeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has Mac and Windows implementation + if (argumentCount < 2) + return JSValueMakeUndefined(context); + + LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + + bool forbidden = JSValueToBoolean(context, arguments[0]); + JSRetainPtr<JSStringRef> scheme(Adopt, JSValueToStringCopy(context, arguments[1], 0)); + controller->setDomainRelaxationForbiddenForURLScheme(forbidden, scheme.get()); + + return JSValueMakeUndefined(context); +} + static JSValueRef setMockGeolocationPositionCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { if (argumentCount < 3) @@ -911,6 +927,18 @@ static JSValueRef setUserStyleSheetLocationCallback(JSContextRef context, JSObje return JSValueMakeUndefined(context); } +static JSValueRef setWillSendRequestReturnsNullCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has cross-platform implementation + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); + controller->setWillSendRequestReturnsNull(JSValueToBoolean(context, arguments[0])); + + return JSValueMakeUndefined(context); +} + static JSValueRef setWillSendRequestReturnsNullOnRedirectCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { // Has cross-platform implementation @@ -1287,6 +1315,7 @@ JSStaticFunction* LayoutTestController::staticFunctions() { "setCloseRemainingWindowsWhenComplete", setCloseRemainingWindowsWhenCompleteCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setCustomPolicyDelegate", setCustomPolicyDelegateCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setDatabaseQuota", setDatabaseQuotaCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setDomainRelaxationForbiddenForURLScheme", setDomainRelaxationForbiddenForURLSchemeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setGeolocationPermission", setGeolocationPermissionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setHandlesAuthenticationChallenges", setHandlesAuthenticationChallengesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setPOSIXLocale", setPOSIXLocaleCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, @@ -1307,6 +1336,7 @@ JSStaticFunction* LayoutTestController::staticFunctions() { "setUseDashboardCompatibilityMode", setUseDashboardCompatibilityModeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setUserStyleSheetEnabled", setUserStyleSheetEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setUserStyleSheetLocation", setUserStyleSheetLocationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setWillSendRequestReturnsNull", setWillSendRequestReturnsNullCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setWillSendRequestReturnsNullOnRedirect", setWillSendRequestReturnsNullOnRedirectCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setWindowIsKey", setWindowIsKeyCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "showWebInspector", showWebInspectorCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, diff --git a/WebKitTools/DumpRenderTree/LayoutTestController.h b/WebKitTools/DumpRenderTree/LayoutTestController.h index 7e18dce..c8da6ab 100644 --- a/WebKitTools/DumpRenderTree/LayoutTestController.h +++ b/WebKitTools/DumpRenderTree/LayoutTestController.h @@ -72,6 +72,7 @@ public: void setCacheModel(int); void setCustomPolicyDelegate(bool setDelegate, bool permissive); void setDatabaseQuota(unsigned long long quota); + void setDomainRelaxationForbiddenForURLScheme(bool forbidden, JSStringRef scheme); void setMockGeolocationPosition(double latitude, double longitude, double accuracy); void setMockGeolocationError(int code, JSStringRef message); void setIconDatabaseEnabled(bool iconDatabaseEnabled); @@ -176,6 +177,9 @@ public: void setWaitToDump(bool waitToDump); void waitToDumpWatchdogTimerFired(); + bool willSendRequestReturnsNull() const { return m_willSendRequestReturnsNull; } + void setWillSendRequestReturnsNull(bool returnsNull) { m_willSendRequestReturnsNull = returnsNull; } + bool willSendRequestReturnsNullOnRedirect() const { return m_willSendRequestReturnsNullOnRedirect; } void setWillSendRequestReturnsNullOnRedirect(bool returnsNull) { m_willSendRequestReturnsNullOnRedirect = returnsNull; } @@ -249,6 +253,7 @@ private: bool m_testRepaint; bool m_testRepaintSweepHorizontally; bool m_waitToDump; // True if waitUntilDone() has been called, but notifyDone() has not yet been called. + bool m_willSendRequestReturnsNull; bool m_willSendRequestReturnsNullOnRedirect; bool m_windowIsKey; bool m_alwaysAcceptCookies; diff --git a/WebKitTools/DumpRenderTree/config.h b/WebKitTools/DumpRenderTree/config.h index 063eeea..33dee6d 100644 --- a/WebKitTools/DumpRenderTree/config.h +++ b/WebKitTools/DumpRenderTree/config.h @@ -32,7 +32,7 @@ #include <wtf/FastMalloc.h> #endif -#if PLATFORM(WIN_OS) && !COMPILER(GCC) +#if OS(WINDOWS) && !COMPILER(GCC) #define JS_EXPORTDATA __declspec(dllimport) #define WEBKIT_EXPORTDATA __declspec(dllimport) #else diff --git a/WebKitTools/DumpRenderTree/gtk/AccessibilityControllerGtk.cpp b/WebKitTools/DumpRenderTree/gtk/AccessibilityControllerGtk.cpp index df06cea..12653fc 100644 --- a/WebKitTools/DumpRenderTree/gtk/AccessibilityControllerGtk.cpp +++ b/WebKitTools/DumpRenderTree/gtk/AccessibilityControllerGtk.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008, 2009, 2010 Apple Inc. All Rights Reserved. * Copyright (C) 2009 Jan Michael Alonzo * * Redistribution and use in source and binary forms, with or without @@ -73,3 +73,15 @@ void AccessibilityController::setLogFocusEvents(bool) void AccessibilityController::setLogScrollingStartEvents(bool) { } + +void AccessibilityController::setLogValueChangeEvents(bool) +{ +} + +void AccessibilityController::addNotificationListener(PlatformUIElement, JSObjectRef) +{ +} + +void AccessibilityController::notificationReceived(PlatformUIElement, const std::string&) +{ +} diff --git a/WebKitTools/DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp b/WebKitTools/DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp index 13d313d..abfe115 100644 --- a/WebKitTools/DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp +++ b/WebKitTools/DumpRenderTree/gtk/AccessibilityUIElementGtk.cpp @@ -102,6 +102,12 @@ AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index) return 0; } +unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element) +{ + // FIXME: implement + return 0; +} + JSStringRef AccessibilityUIElement::allAttributes() { // FIXME: implement @@ -249,7 +255,7 @@ JSStringRef AccessibilityUIElement::orientation() const return 0; } -double AccessibilityUIElement::intValue() +double AccessibilityUIElement::intValue() const { GValue value = { 0, { { 0 } } }; @@ -359,6 +365,11 @@ bool AccessibilityUIElement::isExpanded() const return false; } +bool AccessibilityUIElement::isChecked() const +{ + return intValue(); +} + JSStringRef AccessibilityUIElement::attributesOfColumnHeaders() { // FIXME: implement @@ -448,12 +459,18 @@ void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned le // FIXME: implement } -JSStringRef AccessibilityUIElement::attributeValue(JSStringRef attribute) +JSStringRef AccessibilityUIElement::stringAttributeValue(JSStringRef attribute) { // FIXME: implement return JSStringCreateWithCharacters(0, 0); } +bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute) +{ + // FIXME: implement + return false; +} + bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute) { // FIXME: implement @@ -528,3 +545,71 @@ JSStringRef AccessibilityUIElement::documentURI() return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element), "URI")); } + +JSStringRef AccessibilityUIElement::url() +{ + // FIXME: implement + return JSStringCreateWithCharacters(0, 0); +} + +bool AccessibilityUIElement::addNotificationListener(JSObjectRef functionCallback) +{ + // FIXME: implement + return false; +} + +bool AccessibilityUIElement::isSelectable() const +{ + // FIXME: implement + return false; +} + +bool AccessibilityUIElement::isMultiSelectable() const +{ + // FIXME: implement + return false; +} + +bool AccessibilityUIElement::isVisible() const +{ + // FIXME: implement + return false; +} + +bool AccessibilityUIElement::isOffScreen() const +{ + // FIXME: implement + return false; +} + +bool AccessibilityUIElement::isCollapsed() const +{ + // FIXME: implement + return false; +} + +bool AccessibilityUIElement::hasPopup() const +{ + // FIXME: implement + return false; +} + +void AccessibilityUIElement::takeFocus() +{ + // FIXME: implement +} + +void AccessibilityUIElement::takeSelection() +{ + // FIXME: implement +} + +void AccessibilityUIElement::addSelection() +{ + // FIXME: implement +} + +void AccessibilityUIElement::removeSelection() +{ + // FIXME: implement +} diff --git a/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp b/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp index fd1e3c6..39430cf 100644 --- a/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp +++ b/WebKitTools/DumpRenderTree/gtk/DumpRenderTree.cpp @@ -333,6 +333,8 @@ static void resetDefaultsToConsistentValues() "default-font-size", 16, "default-monospace-font-size", 13, "minimum-font-size", 1, + "enable-caret-browsing", FALSE, + "enable-page-cache", FALSE, NULL); webkit_web_frame_clear_main_frame_name(mainFrame); @@ -340,6 +342,8 @@ static void resetDefaultsToConsistentValues() WebKitWebInspector* inspector = webkit_web_view_get_inspector(webView); g_object_set(G_OBJECT(inspector), "javascript-profiling-enabled", FALSE, NULL); + webkit_web_view_set_zoom_level(webView, 1.0); + webkit_reset_origin_access_white_lists(); setlocale(LC_ALL, ""); @@ -780,6 +784,11 @@ static WebKitWebView* createWebView() "signal::close-window", webInspectorCloseWindow, 0, NULL); + if (webView) { + WebKitWebSettings* settings = webkit_web_view_get_settings(webView); + webkit_web_view_set_settings(view, settings); + } + return view; } diff --git a/WebKitTools/DumpRenderTree/gtk/EventSender.cpp b/WebKitTools/DumpRenderTree/gtk/EventSender.cpp index 6268b5b..458e0ba 100644 --- a/WebKitTools/DumpRenderTree/gtk/EventSender.cpp +++ b/WebKitTools/DumpRenderTree/gtk/EventSender.cpp @@ -76,6 +76,14 @@ static unsigned startOfQueue; static const float zoomMultiplierRatio = 1.2f; +// Key event location code defined in DOM Level 3. +enum KeyLocationCode { + DOM_KEY_LOCATION_STANDARD = 0x00, + DOM_KEY_LOCATION_LEFT = 0x01, + DOM_KEY_LOCATION_RIGHT = 0x02, + DOM_KEY_LOCATION_NUMPAD = 0x03 +}; + static JSValueRef getDragModeCallback(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) { return JSValueMakeBoolean(context, dragMode); @@ -120,10 +128,10 @@ static JSValueRef contextClickCallback(JSContextRef context, JSObjectRef functio return JSValueMakeUndefined(context); } -static void updateClickCount(int /* button */) +static void updateClickCount(int button) { // FIXME: take the last clicked button number and the time of last click into account. - if (lastClickPositionX != lastMousePositionX || lastClickPositionY != lastMousePositionY) + if (lastClickPositionX != lastMousePositionX || lastClickPositionY != lastMousePositionY || currentEventButton != button) clickCount = 1; else clickCount++; @@ -180,7 +188,7 @@ static JSValueRef mouseDownCallback(JSContextRef context, JSObjectRef function, event.button.x_root = x_root; event.button.y_root = y_root; - updateClickCount(1); + updateClickCount(event.button.button); if (!msgQueue[endOfQueue].delay) { webkit_web_frame_layout(mainFrame); @@ -449,66 +457,93 @@ static JSValueRef keyDownCallback(JSContextRef context, JSObjectRef function, JS } } + // handle location argument. + int location = DOM_KEY_LOCATION_STANDARD; + if (argumentCount > 2) + location = (int)JSValueToNumber(context, arguments[2], exception); + JSStringRef character = JSValueToStringCopy(context, arguments[0], exception); g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context)); - int gdkKeySym; - if (JSStringIsEqualToUTF8CString(character, "leftArrow")) - gdkKeySym = GDK_Left; - else if (JSStringIsEqualToUTF8CString(character, "rightArrow")) - gdkKeySym = GDK_Right; - else if (JSStringIsEqualToUTF8CString(character, "upArrow")) - gdkKeySym = GDK_Up; - else if (JSStringIsEqualToUTF8CString(character, "downArrow")) - gdkKeySym = GDK_Down; - else if (JSStringIsEqualToUTF8CString(character, "pageUp")) - gdkKeySym = GDK_Page_Up; - else if (JSStringIsEqualToUTF8CString(character, "pageDown")) - gdkKeySym = GDK_Page_Down; - else if (JSStringIsEqualToUTF8CString(character, "home")) - gdkKeySym = GDK_Home; - else if (JSStringIsEqualToUTF8CString(character, "end")) - gdkKeySym = GDK_End; - else if (JSStringIsEqualToUTF8CString(character, "delete")) - gdkKeySym = GDK_BackSpace; - else if (JSStringIsEqualToUTF8CString(character, "F1")) - gdkKeySym = GDK_F1; - else if (JSStringIsEqualToUTF8CString(character, "F2")) - gdkKeySym = GDK_F2; - else if (JSStringIsEqualToUTF8CString(character, "F3")) - gdkKeySym = GDK_F3; - else if (JSStringIsEqualToUTF8CString(character, "F4")) - gdkKeySym = GDK_F4; - else if (JSStringIsEqualToUTF8CString(character, "F5")) - gdkKeySym = GDK_F5; - else if (JSStringIsEqualToUTF8CString(character, "F6")) - gdkKeySym = GDK_F6; - else if (JSStringIsEqualToUTF8CString(character, "F7")) - gdkKeySym = GDK_F7; - else if (JSStringIsEqualToUTF8CString(character, "F8")) - gdkKeySym = GDK_F8; - else if (JSStringIsEqualToUTF8CString(character, "F9")) - gdkKeySym = GDK_F9; - else if (JSStringIsEqualToUTF8CString(character, "F10")) - gdkKeySym = GDK_F10; - else if (JSStringIsEqualToUTF8CString(character, "F11")) - gdkKeySym = GDK_F11; - else if (JSStringIsEqualToUTF8CString(character, "F12")) - gdkKeySym = GDK_F12; - else { - int charCode = JSStringGetCharactersPtr(character)[0]; - if (charCode == '\n' || charCode == '\r') - gdkKeySym = GDK_Return; - else if (charCode == '\t') - gdkKeySym = GDK_Tab; - else if (charCode == '\x8') + int gdkKeySym = GDK_VoidSymbol; + if (location == DOM_KEY_LOCATION_NUMPAD) { + if (JSStringIsEqualToUTF8CString(character, "leftArrow")) + gdkKeySym = GDK_KP_Left; + else if (JSStringIsEqualToUTF8CString(character, "rightArrow")) + gdkKeySym = GDK_KP_Right; + else if (JSStringIsEqualToUTF8CString(character, "upArrow")) + gdkKeySym = GDK_KP_Up; + else if (JSStringIsEqualToUTF8CString(character, "downArrow")) + gdkKeySym = GDK_KP_Down; + else if (JSStringIsEqualToUTF8CString(character, "pageUp")) + gdkKeySym = GDK_KP_Page_Up; + else if (JSStringIsEqualToUTF8CString(character, "pageDown")) + gdkKeySym = GDK_KP_Page_Down; + else if (JSStringIsEqualToUTF8CString(character, "home")) + gdkKeySym = GDK_KP_Home; + else if (JSStringIsEqualToUTF8CString(character, "end")) + gdkKeySym = GDK_KP_End; + else + // Assume we only get arrow/pgUp/pgDn/home/end keys with + // location=NUMPAD for now. + g_assert_not_reached(); + } else { + if (JSStringIsEqualToUTF8CString(character, "leftArrow")) + gdkKeySym = GDK_Left; + else if (JSStringIsEqualToUTF8CString(character, "rightArrow")) + gdkKeySym = GDK_Right; + else if (JSStringIsEqualToUTF8CString(character, "upArrow")) + gdkKeySym = GDK_Up; + else if (JSStringIsEqualToUTF8CString(character, "downArrow")) + gdkKeySym = GDK_Down; + else if (JSStringIsEqualToUTF8CString(character, "pageUp")) + gdkKeySym = GDK_Page_Up; + else if (JSStringIsEqualToUTF8CString(character, "pageDown")) + gdkKeySym = GDK_Page_Down; + else if (JSStringIsEqualToUTF8CString(character, "home")) + gdkKeySym = GDK_Home; + else if (JSStringIsEqualToUTF8CString(character, "end")) + gdkKeySym = GDK_End; + else if (JSStringIsEqualToUTF8CString(character, "delete")) gdkKeySym = GDK_BackSpace; + else if (JSStringIsEqualToUTF8CString(character, "F1")) + gdkKeySym = GDK_F1; + else if (JSStringIsEqualToUTF8CString(character, "F2")) + gdkKeySym = GDK_F2; + else if (JSStringIsEqualToUTF8CString(character, "F3")) + gdkKeySym = GDK_F3; + else if (JSStringIsEqualToUTF8CString(character, "F4")) + gdkKeySym = GDK_F4; + else if (JSStringIsEqualToUTF8CString(character, "F5")) + gdkKeySym = GDK_F5; + else if (JSStringIsEqualToUTF8CString(character, "F6")) + gdkKeySym = GDK_F6; + else if (JSStringIsEqualToUTF8CString(character, "F7")) + gdkKeySym = GDK_F7; + else if (JSStringIsEqualToUTF8CString(character, "F8")) + gdkKeySym = GDK_F8; + else if (JSStringIsEqualToUTF8CString(character, "F9")) + gdkKeySym = GDK_F9; + else if (JSStringIsEqualToUTF8CString(character, "F10")) + gdkKeySym = GDK_F10; + else if (JSStringIsEqualToUTF8CString(character, "F11")) + gdkKeySym = GDK_F11; + else if (JSStringIsEqualToUTF8CString(character, "F12")) + gdkKeySym = GDK_F12; else { - gdkKeySym = gdk_unicode_to_keyval(charCode); - if (WTF::isASCIIUpper(charCode)) - state |= GDK_SHIFT_MASK; + int charCode = JSStringGetCharactersPtr(character)[0]; + if (charCode == '\n' || charCode == '\r') + gdkKeySym = GDK_Return; + else if (charCode == '\t') + gdkKeySym = GDK_Tab; + else if (charCode == '\x8') + gdkKeySym = GDK_BackSpace; + else { + gdkKeySym = gdk_unicode_to_keyval(charCode); + if (WTF::isASCIIUpper(charCode)) + state |= GDK_SHIFT_MASK; + } } } - JSStringRelease(character); WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); diff --git a/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp b/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp index 6e94c1c..a74f7ad 100644 --- a/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp +++ b/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp @@ -68,6 +68,8 @@ static gchar* copyWebSettingKey(gchar* preferenceKey) keyTable = g_hash_table_new(g_str_hash, g_str_equal); g_hash_table_insert(keyTable, g_strdup("WebKitJavaScriptEnabled"), g_strdup("enable-scripts")); g_hash_table_insert(keyTable, g_strdup("WebKitDefaultFontSize"), g_strdup("default-font-size")); + g_hash_table_insert(keyTable, g_strdup("WebKitEnableCaretBrowsing"), g_strdup("enable-caret-browsing")); + g_hash_table_insert(keyTable, g_strdup("WebKitUsesPageCachePreferenceKey"), g_strdup("enable-page-cache")); } return g_strdup(static_cast<gchar*>(g_hash_table_lookup(keyTable, preferenceKey))); @@ -424,6 +426,11 @@ void LayoutTestController::setDatabaseQuota(unsigned long long quota) webkit_security_origin_set_web_database_quota(origin, quota); } +void LayoutTestController::setDomainRelaxationForbiddenForURLScheme(bool, JSStringRef) +{ + // FIXME: implement +} + void LayoutTestController::setAppCacheMaximumSize(unsigned long long size) { webkit_application_cache_set_maximum_size(size); @@ -489,9 +496,12 @@ void LayoutTestController::overridePreference(JSStringRef key, JSStringRef value g_value_transform(const_cast<GValue*>(&stringValue), &propValue); g_object_set_property(G_OBJECT(settings), webSettingKey, const_cast<GValue*>(&propValue)); } else if (G_VALUE_HOLDS_BOOLEAN(&propValue)) { + char* lowered = g_utf8_strdown(strValue, -1); g_object_set(G_OBJECT(settings), webSettingKey, - g_str_equal(g_utf8_strdown(strValue, -1), "true"), + g_str_equal(lowered, "true") + || g_str_equal(strValue, "1"), NULL); + g_free(lowered); } else if (G_VALUE_HOLDS_INT(&propValue)) { std::string str(strValue); std::stringstream ss(str); diff --git a/WebKitTools/DumpRenderTree/mac/AccessibilityControllerMac.mm b/WebKitTools/DumpRenderTree/mac/AccessibilityControllerMac.mm index 67e0fa4..4d2da6e 100644 --- a/WebKitTools/DumpRenderTree/mac/AccessibilityControllerMac.mm +++ b/WebKitTools/DumpRenderTree/mac/AccessibilityControllerMac.mm @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008, 2009, 2010 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -62,3 +62,14 @@ void AccessibilityController::setLogScrollingStartEvents(bool) { } +void AccessibilityController::setLogValueChangeEvents(bool) +{ +} + +void AccessibilityController::addNotificationListener(PlatformUIElement, JSObjectRef) +{ +} + +void AccessibilityController::notificationReceived(PlatformUIElement, const std::string&) +{ +} diff --git a/WebKitTools/DumpRenderTree/mac/AccessibilityUIElementMac.mm b/WebKitTools/DumpRenderTree/mac/AccessibilityUIElementMac.mm index 948f379..e9361f2 100644 --- a/WebKitTools/DumpRenderTree/mac/AccessibilityUIElementMac.mm +++ b/WebKitTools/DumpRenderTree/mac/AccessibilityUIElementMac.mm @@ -28,6 +28,7 @@ #import "AccessibilityUIElement.h" #import <Foundation/Foundation.h> +#import <JavaScriptCore/JSRetainPtr.h> #import <JavaScriptCore/JSStringRef.h> #import <JavaScriptCore/JSStringRefCF.h> #import <WebKit/WebFrame.h> @@ -52,24 +53,33 @@ #define NSAccessibilityDropEffectsAttribute @"AXDropEffects" #endif -@interface NSObject (WebKitAccessibilityArrayCategory) +typedef void (*AXPostedNotificationCallback)(id element, NSString* notification, void* context); + +@interface NSObject (WebKitAccessibilityAdditions) - (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount; +- (void)accessibilitySetPostedNotificationCallback:(AXPostedNotificationCallback)function withContext:(void*)context; +- (NSUInteger)accessibilityIndexOfChild:(id)child; @end AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element) : m_element(element) + , m_notificationFunctionCallback(0) { [m_element retain]; } AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other) : m_element(other.m_element) + , m_notificationFunctionCallback(0) { [m_element retain]; } AccessibilityUIElement::~AccessibilityUIElement() { + // Make sure that our notification callback does not stick around. + if (m_notificationFunctionCallback) + [m_element accessibilitySetPostedNotificationCallback:0 withContext:0]; [m_element release]; } @@ -237,6 +247,11 @@ AccessibilityUIElement AccessibilityUIElement::elementAtPoint(int x, int y) return AccessibilityUIElement(element); } +unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element) +{ + return [m_element accessibilityIndexOfChild:element->platformUIElement()]; +} + AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index) { Vector<AccessibilityUIElement> children; @@ -337,7 +352,7 @@ JSStringRef AccessibilityUIElement::allAttributes() return [attributes createJSStringRef]; } -JSStringRef AccessibilityUIElement::attributeValue(JSStringRef attribute) +JSStringRef AccessibilityUIElement::stringAttributeValue(JSStringRef attribute) { id value = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]]; if (![value isKindOfClass:[NSString class]]) @@ -345,6 +360,15 @@ JSStringRef AccessibilityUIElement::attributeValue(JSStringRef attribute) return [value createJSStringRef]; } +bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute) +{ + id value = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]]; + if (![value isKindOfClass:[NSNumber class]]) + return NULL; + + return [value boolValue]; +} + bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute) { return [m_element accessibilityIsAttributeSettable:[NSString stringWithJSStringRef:attribute]]; @@ -451,7 +475,7 @@ double AccessibilityUIElement::clickPointY() return static_cast<double>([positionValue pointValue].y); } -double AccessibilityUIElement::intValue() +double AccessibilityUIElement::intValue() const { id value = [m_element accessibilityAttributeValue:NSAccessibilityValueAttribute]; if ([value isKindOfClass:[NSNumber class]]) @@ -529,6 +553,12 @@ bool AccessibilityUIElement::isExpanded() const return false; } +bool AccessibilityUIElement::isChecked() const +{ + // On the Mac, intValue()==1 if a a checkable control is checked. + return intValue() == 1; +} + int AccessibilityUIElement::hierarchicalLevel() const { id value = [m_element accessibilityAttributeValue:NSAccessibilityDisclosureLevelAttribute]; @@ -721,3 +751,87 @@ JSStringRef AccessibilityUIElement::documentURI() { return JSStringCreateWithCharacters(0, 0); } + +JSStringRef AccessibilityUIElement::url() +{ + NSURL *url = [m_element accessibilityAttributeValue:NSAccessibilityURLAttribute]; + return [[url absoluteString] createJSStringRef]; +} + +static void _accessibilityNotificationCallback(id element, NSString* notification, void* context) +{ + if (!context) + return; + + JSObjectRef functionCallback = static_cast<JSObjectRef>(context); + + JSRetainPtr<JSStringRef> jsNotification(Adopt, [notification createJSStringRef]); + JSValueRef argument = JSValueMakeString([mainFrame globalContext], jsNotification.get()); + JSObjectCallAsFunction([mainFrame globalContext], functionCallback, NULL, 1, &argument, NULL); +} + +bool AccessibilityUIElement::addNotificationListener(JSObjectRef functionCallback) +{ + if (!functionCallback) + return false; + + m_notificationFunctionCallback = functionCallback; + [platformUIElement() accessibilitySetPostedNotificationCallback:_accessibilityNotificationCallback withContext:reinterpret_cast<void*>(m_notificationFunctionCallback)]; + return true; +} + +bool AccessibilityUIElement::isSelectable() const +{ + // FIXME: implement + return false; +} + +bool AccessibilityUIElement::isMultiSelectable() const +{ + // FIXME: implement + return false; +} + +bool AccessibilityUIElement::isVisible() const +{ + // FIXME: implement + return false; +} + +bool AccessibilityUIElement::isOffScreen() const +{ + // FIXME: implement + return false; +} + +bool AccessibilityUIElement::isCollapsed() const +{ + // FIXME: implement + return false; +} + +bool AccessibilityUIElement::hasPopup() const +{ + // FIXME: implement + return false; +} + +void AccessibilityUIElement::takeFocus() +{ + // FIXME: implement +} + +void AccessibilityUIElement::takeSelection() +{ + // FIXME: implement +} + +void AccessibilityUIElement::addSelection() +{ + // FIXME: implement +} + +void AccessibilityUIElement::removeSelection() +{ + // FIXME: implement +} diff --git a/WebKitTools/DumpRenderTree/mac/CheckedMalloc.cpp b/WebKitTools/DumpRenderTree/mac/CheckedMalloc.cpp index 85d0613..faef760 100644 --- a/WebKitTools/DumpRenderTree/mac/CheckedMalloc.cpp +++ b/WebKitTools/DumpRenderTree/mac/CheckedMalloc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005, 2006, 2007 Apple, Inc. All rights reserved. + * Copyright (C) 2005, 2006, 2007, 2010 Apple Inc. All rights reserved. * (C) 2007 Graham Dennis (graham.dennis@gmail.com) * (C) 2007 Eric Seidel <eric@webkit.org> * @@ -32,6 +32,7 @@ #import "CheckedMalloc.h" #import <malloc/malloc.h> +#import <sys/mman.h> static void* (*savedMalloc)(malloc_zone_t*, size_t); static void* (*savedRealloc)(malloc_zone_t*, void*, size_t); @@ -53,8 +54,19 @@ static void* checkedRealloc(malloc_zone_t* zone, void* ptr, size_t size) void makeLargeMallocFailSilently() { malloc_zone_t* zone = malloc_default_zone(); + +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) + vm_address_t pageStart = reinterpret_cast<vm_address_t>(zone) & static_cast<vm_size_t>(~(getpagesize() - 1)); + vm_size_t len = reinterpret_cast<vm_address_t>(zone) - pageStart + sizeof(malloc_zone_t); + mprotect(reinterpret_cast<void*>(pageStart), len, PROT_READ | PROT_WRITE); +#endif + savedMalloc = zone->malloc; savedRealloc = zone->realloc; zone->malloc = checkedMalloc; zone->realloc = checkedRealloc; + +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) + mprotect(reinterpret_cast<void*>(pageStart), len, PROT_READ); +#endif } diff --git a/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm b/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm index 4ffeac3..12e1941 100644 --- a/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm +++ b/WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm @@ -80,6 +80,7 @@ #import <objc/objc-runtime.h> #import <wtf/Assertions.h> #import <wtf/RetainPtr.h> +#import <wtf/Threading.h> #import <wtf/OwnPtr.h> using namespace std; @@ -466,6 +467,31 @@ static void setDefaultsToConsistentValuesForTesting() } +static void* runThread(void* arg) +{ + static ThreadIdentifier previousId = 0; + ThreadIdentifier currentId = currentThread(); + // Verify 2 successive threads do not get the same Id. + ASSERT(previousId != currentId); + previousId = currentId; + return 0; +} + +static void testThreadIdentifierMap() +{ + // Imitate 'foreign' threads that are not created by WTF. + pthread_t pthread; + pthread_create(&pthread, 0, &runThread, 0); + pthread_join(pthread, 0); + + pthread_create(&pthread, 0, &runThread, 0); + pthread_join(pthread, 0); + + // Now create another thread using WTF. On OSX, it will have the same pthread handle + // but should get a different ThreadIdentifier. + createThread(runThread, 0, "DumpRenderTree: test"); +} + static void crashHandler(int sig) { char *signalName = strsignal(sig); @@ -614,6 +640,9 @@ void dumpRenderTree(int argc, const char *argv[]) // <rdar://problem/5222911> testStringByEvaluatingJavaScriptFromString(); + // http://webkit.org/b/32689 + testThreadIdentifierMap(); + if (threaded) startJavaScriptThreads(); @@ -1075,15 +1104,20 @@ void dump() } else printf("ERROR: nil result from %s", methodNameStringForFailedTest()); + // Stop the watchdog thread before we leave this test to make sure it doesn't + // fire in between tests causing the next test to fail. + // This is a speculative fix for: https://bugs.webkit.org/show_bug.cgi?id=32339 + invalidateAnyPreviousWaitToDumpWatchdog(); + if (printSeparators) { puts("#EOF"); // terminate the content block fputs("#EOF\n", stderr); } } - + if (dumpPixels && !dumpAsText) dumpWebViewAsPixelsAndCompareWithExpected(gLayoutTestController->expectedPixelHash()); - + puts("#EOF"); // terminate the (possibly empty) pixels block fflush(stdout); diff --git a/WebKitTools/DumpRenderTree/mac/DumpRenderTreeMac.h b/WebKitTools/DumpRenderTree/mac/DumpRenderTreeMac.h index fe1ac00..5c93ee9 100644 --- a/WebKitTools/DumpRenderTree/mac/DumpRenderTreeMac.h +++ b/WebKitTools/DumpRenderTree/mac/DumpRenderTreeMac.h @@ -36,6 +36,8 @@ #define BUILDING_ON_TIGER 1 #elif !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 #define BUILDING_ON_LEOPARD 1 +#elif !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 +#define BUILDING_ON_SNOW_LEOPARD 1 #endif @class DumpRenderTreeDraggingInfo; diff --git a/WebKitTools/DumpRenderTree/mac/EventSendingController.mm b/WebKitTools/DumpRenderTree/mac/EventSendingController.mm index 1cba53b..feaeddc 100644 --- a/WebKitTools/DumpRenderTree/mac/EventSendingController.mm +++ b/WebKitTools/DumpRenderTree/mac/EventSendingController.mm @@ -125,11 +125,11 @@ BOOL replayingSavedEvents; || aSelector == @selector(contextClick) || aSelector == @selector(enableDOMUIEventLogging:) || aSelector == @selector(fireKeyboardEventsToElement:) - || aSelector == @selector(keyDown:withModifiers:) + || aSelector == @selector(keyDown:withModifiers:withLocation:) || aSelector == @selector(leapForward:) - || aSelector == @selector(mouseDown:) + || aSelector == @selector(mouseDown:withModifiers:) || aSelector == @selector(mouseMoveToX:Y:) - || aSelector == @selector(mouseUp:) + || aSelector == @selector(mouseUp:withModifiers:) || aSelector == @selector(scheduleAsynchronousClick) || aSelector == @selector(textZoomIn) || aSelector == @selector(textZoomOut) @@ -154,13 +154,13 @@ BOOL replayingSavedEvents; return @"enableDOMUIEventLogging"; if (aSelector == @selector(fireKeyboardEventsToElement:)) return @"fireKeyboardEventsToElement"; - if (aSelector == @selector(keyDown:withModifiers:)) + if (aSelector == @selector(keyDown:withModifiers:withLocation:)) return @"keyDown"; if (aSelector == @selector(leapForward:)) return @"leapForward"; - if (aSelector == @selector(mouseDown:)) + if (aSelector == @selector(mouseDown:withModifiers:)) return @"mouseDown"; - if (aSelector == @selector(mouseUp:)) + if (aSelector == @selector(mouseUp:withModifiers:)) return @"mouseUp"; if (aSelector == @selector(mouseMoveToX:Y:)) return @"mouseMoveTo"; @@ -285,7 +285,26 @@ static NSEventType eventTypeForMouseButtonAndAction(int button, MouseAction acti clickCount++; } -- (void)mouseDown:(int)buttonNumber +static int buildModifierFlags(const WebScriptObject* modifiers) +{ + int flags = 0; + if (![modifiers isKindOfClass:[WebScriptObject class]]) + return flags; + for (unsigned i = 0; [[modifiers webScriptValueAtIndex:i] isKindOfClass:[NSString class]]; i++) { + NSString* modifierName = (NSString*)[modifiers webScriptValueAtIndex:i]; + if ([modifierName isEqual:@"ctrlKey"]) + flags |= NSControlKeyMask; + else if ([modifierName isEqual:@"shiftKey"] || [modifierName isEqual:@"rangeSelectionKey"]) + flags |= NSShiftKeyMask; + else if ([modifierName isEqual:@"altKey"]) + flags |= NSAlternateKeyMask; + else if ([modifierName isEqual:@"metaKey"] || [modifierName isEqual:@"addSelectionKey"]) + flags |= NSCommandKeyMask; + } + return flags; +} + +- (void)mouseDown:(int)buttonNumber withModifiers:(WebScriptObject*)modifiers { [[[mainFrame frameView] documentView] layout]; [self updateClickCountForButton:buttonNumber]; @@ -293,7 +312,7 @@ static NSEventType eventTypeForMouseButtonAndAction(int button, MouseAction acti NSEventType eventType = eventTypeForMouseButtonAndAction(buttonNumber, MouseDown); NSEvent *event = [NSEvent mouseEventWithType:eventType location:lastMousePosition - modifierFlags:0 + modifierFlags:buildModifierFlags(modifiers) timestamp:[self currentEventTime] windowNumber:[[[mainFrame webView] window] windowNumber] context:[NSGraphicsContext currentContext] @@ -309,6 +328,11 @@ static NSEventType eventTypeForMouseButtonAndAction(int button, MouseAction acti } } +- (void)mouseDown:(int)buttonNumber +{ + [self mouseDown:buttonNumber withModifiers:nil]; +} + - (void)textZoomIn { [[mainFrame webView] makeTextLarger:self]; @@ -329,13 +353,14 @@ static NSEventType eventTypeForMouseButtonAndAction(int button, MouseAction acti [[mainFrame webView] zoomPageOut:self]; } -- (void)mouseUp:(int)buttonNumber +- (void)mouseUp:(int)buttonNumber withModifiers:(WebScriptObject*)modifiers { if (dragMode && !replayingSavedEvents) { - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[EventSendingController instanceMethodSignatureForSelector:@selector(mouseUp:)]]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[EventSendingController instanceMethodSignatureForSelector:@selector(mouseUp:withModifiers:)]]; [invocation setTarget:self]; - [invocation setSelector:@selector(mouseUp:)]; + [invocation setSelector:@selector(mouseUp:withModifiers:)]; [invocation setArgument:&buttonNumber atIndex:2]; + [invocation setArgument:&modifiers atIndex:3]; [EventSendingController saveEvent:invocation]; [EventSendingController replaySavedEvents]; @@ -347,7 +372,7 @@ static NSEventType eventTypeForMouseButtonAndAction(int button, MouseAction acti NSEventType eventType = eventTypeForMouseButtonAndAction(buttonNumber, MouseUp); NSEvent *event = [NSEvent mouseEventWithType:eventType location:lastMousePosition - modifierFlags:0 + modifierFlags:buildModifierFlags(modifiers) timestamp:[self currentEventTime] windowNumber:[[[mainFrame webView] window] windowNumber] context:[NSGraphicsContext currentContext] @@ -383,6 +408,11 @@ static NSEventType eventTypeForMouseButtonAndAction(int button, MouseAction acti } } +- (void)mouseUp:(int)buttonNumber +{ + [self mouseUp:buttonNumber withModifiers:nil]; +} + - (void)mouseMoveToX:(int)x Y:(int)y { if (dragMode && leftMouseButtonDown && !replayingSavedEvents) { @@ -474,7 +504,7 @@ static NSEventType eventTypeForMouseButtonAndAction(int button, MouseAction acti savedMouseEvents = nil; } -- (void)keyDown:(NSString *)character withModifiers:(WebScriptObject *)modifiers +- (void)keyDown:(NSString *)character withModifiers:(WebScriptObject *)modifiers withLocation:(unsigned long)keyLocation { NSString *eventCharacter = character; if ([character isEqualToString:@"leftArrow"]) { @@ -524,19 +554,10 @@ static NSEventType eventTypeForMouseButtonAndAction(int button, MouseAction acti charactersIgnoringModifiers = [character lowercaseString]; } - if ([modifiers isKindOfClass:[WebScriptObject class]]) { - for (unsigned i = 0; [[modifiers webScriptValueAtIndex:i] isKindOfClass:[NSString class]]; i++) { - NSString *modifier = (NSString *)[modifiers webScriptValueAtIndex:i]; - if ([modifier isEqual:@"ctrlKey"]) - modifierFlags |= NSControlKeyMask; - else if ([modifier isEqual:@"shiftKey"]) - modifierFlags |= NSShiftKeyMask; - else if ([modifier isEqual:@"altKey"]) - modifierFlags |= NSAlternateKeyMask; - else if ([modifier isEqual:@"metaKey"]) - modifierFlags |= NSCommandKeyMask; - } - } + modifierFlags |= buildModifierFlags(modifiers); + + if (keyLocation == DOM_KEY_LOCATION_NUMPAD) + modifierFlags |= NSNumericPadKeyMask; [[[mainFrame frameView] documentView] layout]; diff --git a/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm b/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm index 69fe19f..5f020fa 100644 --- a/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm +++ b/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm @@ -251,6 +251,12 @@ void LayoutTestController::setDatabaseQuota(unsigned long long quota) [origin release]; } +void LayoutTestController::setDomainRelaxationForbiddenForURLScheme(bool forbidden, JSStringRef scheme) +{ + RetainPtr<CFStringRef> schemeCFString(AdoptCF, JSStringCopyCFString(kCFAllocatorDefault, scheme)); + [WebView _setDomainRelaxationForbidden:forbidden forURLScheme:(NSString *)schemeCFString.get()]; +} + void LayoutTestController::setMockGeolocationPosition(double latitude, double longitude, double accuracy) { [WebGeolocationMock setPosition:latitude:longitude:accuracy]; diff --git a/WebKitTools/DumpRenderTree/mac/ObjCController.m b/WebKitTools/DumpRenderTree/mac/ObjCController.m index e0d663e..aa9ee49 100644 --- a/WebKitTools/DumpRenderTree/mac/ObjCController.m +++ b/WebKitTools/DumpRenderTree/mac/ObjCController.m @@ -58,6 +58,7 @@ static void* runJavaScriptThread(void* arg) if (0 || aSelector == @selector(classNameOf:) || aSelector == @selector(objectOfClass:) + || aSelector == @selector(arrayOfString) || aSelector == @selector(identityIsEqual::) || aSelector == @selector(longLongRoundTrip:) || aSelector == @selector(unsignedLongLongRoundTrip:) @@ -77,6 +78,8 @@ static void* runJavaScriptThread(void* arg) return @"className"; if (aSelector == @selector(objectOfClass:)) return @"objectOfClass"; + if (aSelector == @selector(arrayOfString)) + return @"arrayOfString"; if (aSelector == @selector(identityIsEqual::)) return @"identityIsEqual"; if (aSelector == @selector(longLongRoundTrip:)) @@ -122,6 +125,16 @@ static void* runJavaScriptThread(void* arg) return nil; } +- (NSArray *)arrayOfString +{ + NSString *strings[3]; + strings[0] = @"one"; + strings[1] = @"two"; + strings[2] = @"three"; + NSArray *array = [NSArray arrayWithObjects:strings count:3]; + return array; +} + - (BOOL)identityIsEqual:(WebScriptObject *)a :(WebScriptObject *)b { if ([a isKindOfClass:[NSString class]] && [b isKindOfClass:[NSString class]]) @@ -196,10 +209,9 @@ static void* runJavaScriptThread(void* arg) { #if !ASSERT_DISABLED BOOL isWindowObject = [storedWebScriptObject isKindOfClass:[DOMAbstractView class]]; -#endif JSObjectRef jsObject = [storedWebScriptObject JSObject]; ASSERT((jsObject && isWindowObject) || (!jsObject && !isWindowObject)); - +#endif [storedWebScriptObject callWebScriptMethod:@"" withArguments:nil]; [storedWebScriptObject evaluateWebScript:@""]; [storedWebScriptObject setValue:[WebUndefined undefined] forKey:@"key"]; diff --git a/WebKitTools/DumpRenderTree/mac/ResourceLoadDelegate.mm b/WebKitTools/DumpRenderTree/mac/ResourceLoadDelegate.mm index 3aaba59..6f82e01 100644 --- a/WebKitTools/DumpRenderTree/mac/ResourceLoadDelegate.mm +++ b/WebKitTools/DumpRenderTree/mac/ResourceLoadDelegate.mm @@ -129,6 +129,9 @@ printf("%s\n", [string UTF8String]); } + if (!done && gLayoutTestController->willSendRequestReturnsNull()) + return nil; + if (!done && gLayoutTestController->willSendRequestReturnsNullOnRedirect() && redirectResponse) { printf("Returning null for this redirect\n"); return nil; diff --git a/WebKitTools/DumpRenderTree/qt/DumpRenderTree.pro b/WebKitTools/DumpRenderTree/qt/DumpRenderTree.pro index 81e929b..ad42bdd 100644 --- a/WebKitTools/DumpRenderTree/qt/DumpRenderTree.pro +++ b/WebKitTools/DumpRenderTree/qt/DumpRenderTree.pro @@ -17,29 +17,32 @@ INCLUDEPATH += ../../../JavaScriptCore/ForwardingHeaders INCLUDEPATH += $$BASEDIR DESTDIR = ../../../bin -CONFIG += link_pkgconfig -PKGCONFIG += fontconfig +!win32 { + CONFIG += link_pkgconfig + PKGCONFIG += fontconfig +} -QT = core gui network +QT = core gui network testlib macx: QT += xml HEADERS = $$BASEDIR/WorkQueue.h \ - WorkQueueItem.h \ - DumpRenderTree.h \ + DumpRenderTreeQt.h \ EventSenderQt.h \ TextInputControllerQt.h \ + WorkQueueItemQt.h \ LayoutTestControllerQt.h \ - jsobjects.h \ + GCControllerQt.h \ testplugin.h -SOURCES = $$BASEDIR/WorkQueue.cpp \ - DumpRenderTree.cpp \ +SOURCES = ../../../JavaScriptCore/wtf/Assertions.cpp \ + $$BASEDIR/WorkQueue.cpp \ + DumpRenderTreeQt.cpp \ EventSenderQt.cpp \ TextInputControllerQt.cpp \ WorkQueueItemQt.cpp \ LayoutTestControllerQt.cpp \ - main.cpp \ - jsobjects.cpp \ - testplugin.cpp + GCControllerQt.cpp \ + testplugin.cpp \ + main.cpp unix:!mac { QMAKE_RPATHDIR = $$OUTPUT_DIR/lib $$QMAKE_RPATHDIR diff --git a/WebKitTools/DumpRenderTree/qt/DumpRenderTree.cpp b/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp index 6d466bf..9916f24 100644 --- a/WebKitTools/DumpRenderTree/qt/DumpRenderTree.cpp +++ b/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.cpp @@ -31,11 +31,11 @@ #include "config.h" -#include "DumpRenderTree.h" +#include "DumpRenderTreeQt.h" #include "EventSenderQt.h" +#include "GCControllerQt.h" #include "LayoutTestControllerQt.h" #include "TextInputControllerQt.h" -#include "jsobjects.h" #include "testplugin.h" #include "WorkQueue.h" @@ -48,6 +48,7 @@ #include <QFileInfo> #include <QFocusEvent> #include <QFontDatabase> +#include <QLocale> #include <QNetworkAccessManager> #include <QNetworkReply> #include <QNetworkRequest> @@ -66,7 +67,10 @@ #include <limits.h> +#ifndef Q_OS_WIN #include <unistd.h> +#endif + #include <qdebug.h> extern void qt_drt_run(bool b); @@ -86,13 +90,13 @@ const unsigned int maxViewHeight = 600; NetworkAccessManager::NetworkAccessManager(QObject* parent) : QNetworkAccessManager(parent) { -#ifndef QT_NO_SSL +#ifndef QT_NO_OPENSSL connect(this, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError>&)), this, SLOT(sslErrorsEncountered(QNetworkReply*, const QList<QSslError>&))); #endif } -#ifndef QT_NO_SSL +#ifndef QT_NO_OPENSSL void NetworkAccessManager::sslErrorsEncountered(QNetworkReply* reply, const QList<QSslError>& errors) { if (reply->url().host() == "127.0.0.1" || reply->url().host() == "localhost") { @@ -158,7 +162,6 @@ void WebPage::resetSettings() { // After each layout test, reset the settings that may have been changed by // layoutTestController.overridePreference() or similar. - settings()->resetFontSize(QWebSettings::DefaultFontSize); settings()->resetAttribute(QWebSettings::JavascriptCanOpenWindows); settings()->resetAttribute(QWebSettings::JavascriptEnabled); @@ -166,7 +169,12 @@ void WebPage::resetSettings() settings()->resetAttribute(QWebSettings::LinksIncludedInFocusChain); settings()->resetAttribute(QWebSettings::OfflineWebApplicationCacheEnabled); settings()->resetAttribute(QWebSettings::LocalContentCanAccessRemoteUrls); + + // globalSettings must be reset explicitly. + m_drt->layoutTestController()->setXSSAuditorEnabled(false); + QWebSettings::setMaximumPagesInCache(0); // reset to default + settings()->setUserStyleSheetUrl(QUrl()); // reset to default } QWebPage *WebPage::createWindow(QWebPage::WebWindowType) @@ -305,8 +313,8 @@ QObject* WebPage::createPlugin(const QString& classId, const QUrl& url, const QS DumpRenderTree::DumpRenderTree() : m_dumpPixels(false) , m_stdin(0) - , m_notifier(0) , m_enableTextOutput(false) + , m_singleFileMode(false) { qt_drt_overwritePluginDirectories(); QWebSettings::enablePersistentStorage(); @@ -317,9 +325,12 @@ DumpRenderTree::DumpRenderTree() m_page = new WebPage(m_mainView, this); m_mainView->setPage(m_page); - // create out controllers. This has to be done before connectFrame, + // create our controllers. This has to be done before connectFrame, // as it exports there to the JavaScript DOM window. m_controller = new LayoutTestController(this); + connect(m_controller, SIGNAL(showPage()), this, SLOT(showPage())); + connect(m_controller, SIGNAL(hidePage()), this, SLOT(hidePage())); + connect(m_controller, SIGNAL(done()), this, SLOT(dump())); m_eventSender = new EventSender(m_page); m_textInputController = new TextInputController(m_page); @@ -332,6 +343,11 @@ DumpRenderTree::DumpRenderTree() connect(m_page, SIGNAL(loadFinished(bool)), m_controller, SLOT(maybeDump(bool))); + // We need to connect to loadStarted() because notifyDone should only + // dump results itself when the last page loaded in the test has finished loading. + connect(m_page, SIGNAL(loadStarted()), + m_controller, SLOT(resetLoadFinished())); + connect(m_page, SIGNAL(windowCloseRequested()), this, SLOT(windowCloseRequested())); connect(m_page->mainFrame(), SIGNAL(titleChanged(const QString&)), SLOT(titleChanged(const QString&))); @@ -350,20 +366,6 @@ DumpRenderTree::~DumpRenderTree() { delete m_mainView; delete m_stdin; - delete m_notifier; -} - -void DumpRenderTree::open() -{ - if (!m_stdin) { - m_stdin = new QFile; - m_stdin->open(stdin, QFile::ReadOnly); - } - - if (!m_notifier) { - m_notifier = new QSocketNotifier(STDIN_FILENO, QSocketNotifier::Read); - connect(m_notifier, SIGNAL(activated(int)), this, SLOT(readStdin(int))); - } } static void clearHistory(QWebPage* page) @@ -438,6 +440,7 @@ void DumpRenderTree::open(const QUrl& aurl) QFocusEvent ev(QEvent::FocusIn); m_page->event(&ev); + QWebSettings::clearMemoryCaches(); QFontDatabase::removeAllApplicationFonts(); #if defined(Q_WS_X11) initializeFonts(); @@ -448,20 +451,59 @@ void DumpRenderTree::open(const QUrl& aurl) m_page->mainFrame()->load(url); } -void DumpRenderTree::readStdin(int /* socket */) +void DumpRenderTree::readLine() +{ + if (!m_stdin) { + m_stdin = new QFile; + m_stdin->open(stdin, QFile::ReadOnly); + + if (!m_stdin->isReadable()) { + emit quit(); + return; + } + } + + QByteArray line = m_stdin->readLine().trimmed(); + + if (line.isEmpty()) { + emit quit(); + return; + } + + processLine(QString::fromLocal8Bit(line.constData(), line.length())); +} + +void DumpRenderTree::processLine(const QString &input) { - // Read incoming data from stdin... - QByteArray line = m_stdin->readLine(); - if (line.endsWith('\n')) - line.truncate(line.size()-1); - //fprintf(stderr, "\n opening %s\n", line.constData()); - if (line.isEmpty()) - quit(); + QString line = input; - if (line.startsWith("http:") || line.startsWith("https:")) + if (line.startsWith(QLatin1String("http:")) + || line.startsWith(QLatin1String("https:")) + || line.startsWith(QLatin1String("file:"))) { open(QUrl(line)); - else { + } else { QFileInfo fi(line); + + if (!fi.exists()) { + QDir currentDir = QDir::currentPath(); + + // Try to be smart about where the test is located + if (currentDir.dirName() == QLatin1String("LayoutTests")) + fi = QFileInfo(currentDir, line.replace(QRegExp(".*?LayoutTests/(.*)"), "\\1")); + else if (!line.contains(QLatin1String("LayoutTests"))) + fi = QFileInfo(currentDir, line.prepend(QLatin1String("LayoutTests/"))); + + if (!fi.exists()) { + if (isSingleFileMode()) + emit quit(); + else + emit ready(); + + return; + } + + } + open(QUrl::fromLocalFile(fi.absoluteFilePath())); } @@ -490,6 +532,18 @@ void DumpRenderTree::initJSObjects() frame->addToJavaScriptWindowObject(QLatin1String("GCController"), m_gcController); } +void DumpRenderTree::showPage() +{ + m_mainView->show(); + // we need a paint event but cannot process all the events + QPixmap pixmap(m_mainView->size()); + m_mainView->render(&pixmap); +} + +void DumpRenderTree::hidePage() +{ + m_mainView->hide(); +} QString DumpRenderTree::dumpFramesAsText(QWebFrame* frame) { @@ -602,11 +656,12 @@ static const char *methodNameStringForFailedTest(LayoutTestController *controlle void DumpRenderTree::dump() { + // Prevent any further frame load callbacks from appearing after we dump the result. + qt_dump_frame_loader(false); + QWebFrame *mainFrame = m_page->mainFrame(); - //fprintf(stderr, " Dumping\n"); - if (!m_notifier) { - // Dump markup in single file mode... + if (isSingleFileMode()) { QString markup = mainFrame->toHtml(); fprintf(stdout, "Source:\n\n%s\n", markup.toUtf8().constData()); } @@ -684,8 +739,10 @@ void DumpRenderTree::dump() fflush(stdout); fflush(stderr); - if (!m_notifier) - quit(); // Exit now in single file mode... + if (isSingleFileMode()) + emit quit(); + else + emit ready(); } void DumpRenderTree::titleChanged(const QString &s) @@ -741,15 +798,30 @@ QWebPage *DumpRenderTree::createWindow() connect(page, SIGNAL(frameCreated(QWebFrame*)), this, SLOT(connectFrame(QWebFrame*))); connectFrame(page->mainFrame()); connect(page, SIGNAL(loadFinished(bool)), m_controller, SLOT(maybeDump(bool))); + connect(page, SIGNAL(windowCloseRequested()), this, SLOT(windowCloseRequested())); return page; } +void DumpRenderTree::windowCloseRequested() +{ + QWebPage* page = qobject_cast<QWebPage*>(sender()); + QObject* container = page->parent(); + windows.removeAll(container); + container->deleteLater(); +} + int DumpRenderTree::windowCount() const { // include the main view in the count return windows.count() + 1; } +void DumpRenderTree::switchFocus(bool focused) +{ + QFocusEvent event((focused) ? QEvent::FocusIn : QEvent::FocusOut, Qt::ActiveWindowFocusReason); + QApplication::sendEvent(m_mainView, &event); +} + #if defined(Q_WS_X11) void DumpRenderTree::initializeFonts() { diff --git a/WebKitTools/DumpRenderTree/qt/DumpRenderTree.h b/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.h index ab229fe..00d7ae4 100644 --- a/WebKitTools/DumpRenderTree/qt/DumpRenderTree.h +++ b/WebKitTools/DumpRenderTree/qt/DumpRenderTreeQt.h @@ -27,8 +27,8 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef DUMPRENDERTREE_H -#define DUMPRENDERTREE_H +#ifndef DumpRenderTreeQt_h +#define DumpRenderTreeQt_h #include <QList> #include <QNetworkAccessManager> @@ -36,7 +36,7 @@ #include <QTextStream> #include <QSocketNotifier> -#ifndef QT_NO_SSL +#ifndef QT_NO_OPENSSL #include <QSslError> #endif @@ -68,15 +68,15 @@ public: DumpRenderTree(); virtual ~DumpRenderTree(); - // Initialize in multi-file mode, used by run-webkit-tests. - void open(); - // Initialize in single-file mode. void open(const QUrl& url); void setTextOutputEnabled(bool enable) { m_enableTextOutput = enable; } bool isTextOutputEnabled() { return m_enableTextOutput; } + void setSingleFileMode(bool flag) { m_singleFileMode = flag; } + bool isSingleFileMode() { return m_singleFileMode; } + void setDumpPixels(bool); void closeRemainingWindows(); @@ -89,6 +89,8 @@ public: QWebPage *createWindow(); int windowCount() const; + void switchFocus(bool focused); + WebPage *webPage() const { return m_page; } @@ -98,15 +100,24 @@ public: public Q_SLOTS: void initJSObjects(); - void readStdin(int); + + void readLine(); + void processLine(const QString&); + void dump(); void titleChanged(const QString &s); void connectFrame(QWebFrame *frame); void dumpDatabaseQuota(QWebFrame* frame, const QString& dbName); void statusBarMessage(const QString& message); + void windowCloseRequested(); Q_SIGNALS: void quit(); + void ready(); + +private Q_SLOTS: + void showPage(); + void hidePage(); private: QString dumpFramesAsText(QWebFrame* frame); @@ -124,10 +135,10 @@ private: GCController* m_gcController; QFile *m_stdin; - QSocketNotifier* m_notifier; QList<QObject*> windows; bool m_enableTextOutput; + bool m_singleFileMode; }; class NetworkAccessManager : public QNetworkAccessManager { @@ -136,7 +147,7 @@ public: NetworkAccessManager(QObject* parent); private slots: -#ifndef QT_NO_SSL +#ifndef QT_NO_OPENSSL void sslErrorsEncountered(QNetworkReply*, const QList<QSslError>&); #endif }; diff --git a/WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp b/WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp index a0da273..73a9934 100644 --- a/WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp +++ b/WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp @@ -31,6 +31,8 @@ //#include <QtDebug> +#include <QtTest/QtTest> + #define KEYCODE_DEL 127 #define KEYCODE_BACKSPACE 8 #define KEYCODE_LEFTARROW 0xf702 @@ -38,11 +40,34 @@ #define KEYCODE_UPARROW 0xf700 #define KEYCODE_DOWNARROW 0xf701 +// Ports like Gtk and Windows expose a different approach for their zooming +// API if compared to Qt: they have specific methods for zooming in and out, +// as well as a settable zoom factor, while Qt has only a 'setZoomValue' method. +// Hence Qt DRT adopts a fixed zoom-factor (1.2) for compatibility. +#define ZOOM_STEP 1.2 + +#define DRT_MESSAGE_DONE (QEvent::User + 1) + +struct DRTEventQueue { + QEvent* m_event; + int m_delay; +}; + +static DRTEventQueue eventQueue[1024]; +static unsigned endOfQueue; +static unsigned startOfQueue; EventSender::EventSender(QWebPage* parent) : QObject(parent) { m_page = parent; + m_mouseButtonPressed = false; + m_drag = false; + memset(eventQueue, 0, sizeof(eventQueue)); + endOfQueue = 0; + startOfQueue = 0; + m_eventLoop = 0; + m_page->view()->installEventFilter(this); } void EventSender::mouseDown(int button) @@ -67,9 +92,11 @@ void EventSender::mouseDown(int button) break; } + m_mouseButtons |= mouseButton; + // qDebug() << "EventSender::mouseDown" << frame; - QMouseEvent event(QEvent::MouseButtonPress, m_mousePos, mouseButton, mouseButton, Qt::NoModifier); - QApplication::sendEvent(m_page, &event); + QMouseEvent* event = new QMouseEvent(QEvent::MouseButtonPress, m_mousePos, m_mousePos, mouseButton, m_mouseButtons, Qt::NoModifier); + sendOrQueueEvent(event); } void EventSender::mouseUp(int button) @@ -94,26 +121,28 @@ void EventSender::mouseUp(int button) break; } + m_mouseButtons &= ~mouseButton; + // qDebug() << "EventSender::mouseUp" << frame; - QMouseEvent event(QEvent::MouseButtonRelease, m_mousePos, mouseButton, mouseButton, Qt::NoModifier); - QApplication::sendEvent(m_page, &event); + QMouseEvent* event = new QMouseEvent(QEvent::MouseButtonRelease, m_mousePos, m_mousePos, mouseButton, m_mouseButtons, Qt::NoModifier); + sendOrQueueEvent(event); } void EventSender::mouseMoveTo(int x, int y) { // qDebug() << "EventSender::mouseMoveTo" << x << y; m_mousePos = QPoint(x, y); - QMouseEvent event(QEvent::MouseMove, m_mousePos, Qt::NoButton, Qt::NoButton, Qt::NoModifier); - QApplication::sendEvent(m_page, &event); + QMouseEvent* event = new QMouseEvent(QEvent::MouseMove, m_mousePos, m_mousePos, Qt::NoButton, m_mouseButtons, Qt::NoModifier); + sendOrQueueEvent(event); } void EventSender::leapForward(int ms) { - m_timeLeap += ms; + eventQueue[endOfQueue].m_delay = ms; //qDebug() << "EventSender::leapForward" << ms; } -void EventSender::keyDown(const QString& string, const QStringList& modifiers) +void EventSender::keyDown(const QString& string, const QStringList& modifiers, unsigned int location) { QString s = string; Qt::KeyboardModifiers modifs = 0; @@ -128,12 +157,16 @@ void EventSender::keyDown(const QString& string, const QStringList& modifiers) else if (m == "metaKey") modifs |= Qt::MetaModifier; } + if (location == 3) + modifs |= Qt::KeypadModifier; int code = 0; if (string.length() == 1) { code = string.unicode()->unicode(); //qDebug() << ">>>>>>>>> keyDown" << code << (char)code; // map special keycodes used by the tests to something that works for Qt/X11 - if (code == '\t') { + if (code == '\r') { + code = Qt::Key_Return; + } else if (code == '\t') { code = Qt::Key_Tab; if (modifs == Qt::ShiftModifier) code = Qt::Key_Backtab; @@ -251,6 +284,131 @@ void EventSender::scheduleAsynchronousClick() QApplication::postEvent(m_page, event2); } +void EventSender::addTouchPoint(int x, int y) +{ +#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) + int id = m_touchPoints.count(); + QTouchEvent::TouchPoint point(id); + m_touchPoints.append(point); + updateTouchPoint(id, x, y); + m_touchPoints[id].setState(Qt::TouchPointPressed); +#endif +} + +void EventSender::updateTouchPoint(int index, int x, int y) +{ +#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) + if (index < 0 || index >= m_touchPoints.count()) + return; + + QTouchEvent::TouchPoint &p = m_touchPoints[index]; + p.setPos(QPointF(x, y)); + p.setState(Qt::TouchPointMoved); +#endif +} + +void EventSender::setTouchModifier(const QString &modifier, bool enable) +{ +#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) + Qt::KeyboardModifier mod = Qt::NoModifier; + if (!modifier.compare(QLatin1String("shift"), Qt::CaseInsensitive)) + mod = Qt::ShiftModifier; + else if (!modifier.compare(QLatin1String("alt"), Qt::CaseInsensitive)) + mod = Qt::AltModifier; + else if (!modifier.compare(QLatin1String("meta"), Qt::CaseInsensitive)) + mod = Qt::MetaModifier; + else if (!modifier.compare(QLatin1String("ctrl"), Qt::CaseInsensitive)) + mod = Qt::ControlModifier; + + if (enable) + m_touchModifiers |= mod; + else + m_touchModifiers &= ~mod; +#endif +} + +void EventSender::touchStart() +{ +#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) + if (!m_touchActive) { + sendTouchEvent(QEvent::TouchBegin); + m_touchActive = true; + } else + sendTouchEvent(QEvent::TouchUpdate); +#endif +} + +void EventSender::touchMove() +{ +#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) + sendTouchEvent(QEvent::TouchUpdate); +#endif +} + +void EventSender::touchEnd() +{ +#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) + for (int i = 0; i < m_touchPoints.count(); ++i) + if (m_touchPoints[i].state() != Qt::TouchPointReleased) { + sendTouchEvent(QEvent::TouchUpdate); + return; + } + sendTouchEvent(QEvent::TouchEnd); + m_touchActive = false; +#endif +} + +void EventSender::clearTouchPoints() +{ +#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) + m_touchPoints.clear(); + m_touchModifiers = Qt::KeyboardModifiers(); + m_touchActive = false; +#endif +} + +void EventSender::releaseTouchPoint(int index) +{ +#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) + if (index < 0 || index >= m_touchPoints.count()) + return; + + m_touchPoints[index].setState(Qt::TouchPointReleased); +#endif +} + +void EventSender::sendTouchEvent(QEvent::Type type) +{ +#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) + QTouchEvent event(type, QTouchEvent::TouchScreen, m_touchModifiers); + event.setTouchPoints(m_touchPoints); + QApplication::sendEvent(m_page, &event); + QList<QTouchEvent::TouchPoint>::Iterator it = m_touchPoints.begin(); + while (it != m_touchPoints.end()) { + if (it->state() == Qt::TouchPointReleased) + it = m_touchPoints.erase(it); + else { + it->setState(Qt::TouchPointStationary); + ++it; + } + } +#endif +} + +void EventSender::zoomPageIn() +{ + QWebFrame* frame = m_page->mainFrame(); + if (frame) + frame->setZoomFactor(frame->zoomFactor() * ZOOM_STEP); +} + +void EventSender::zoomPageOut() +{ + QWebFrame* frame = m_page->mainFrame(); + if (frame) + frame->setZoomFactor(frame->zoomFactor() / ZOOM_STEP); +} + QWebFrame* EventSender::frameUnderMouse() const { QWebFrame* frame = m_page->mainFrame(); @@ -267,3 +425,76 @@ redo: return frame; return 0; } + +void EventSender::sendOrQueueEvent(QEvent* event) +{ + // Mouse move events are queued if + // 1. A previous event was queued. + // 2. A delay was set-up by leapForward(). + // 3. A call to mouseMoveTo while the mouse button is pressed could initiate a drag operation, and that does not return until mouseUp is processed. + // To be safe and avoid a deadlock, this event is queued. + if (endOfQueue == startOfQueue && !eventQueue[endOfQueue].m_delay && (!(m_mouseButtonPressed && (m_eventLoop && event->type() == QEvent::MouseButtonRelease)))) { + QApplication::sendEvent(m_page->view(), event); + delete event; + return; + } + eventQueue[endOfQueue++].m_event = event; + eventQueue[endOfQueue].m_delay = 0; + replaySavedEvents(event->type() != QEvent::MouseMove); +} + +void EventSender::replaySavedEvents(bool flush) +{ + if (startOfQueue < endOfQueue) { + // First send all the events that are ready to be sent + while (!eventQueue[startOfQueue].m_delay && startOfQueue < endOfQueue) { + QEvent* ev = eventQueue[startOfQueue++].m_event; + QApplication::postEvent(m_page->view(), ev); // ev deleted by the system + } + if (startOfQueue == endOfQueue) { + // Reset the queue + startOfQueue = 0; + endOfQueue = 0; + } else { + QTest::qWait(eventQueue[startOfQueue].m_delay); + eventQueue[startOfQueue].m_delay = 0; + } + } + if (!flush) + return; + + // Send a marker event, it will tell us when it is safe to exit the new event loop + QEvent* drtEvent = new QEvent((QEvent::Type)DRT_MESSAGE_DONE); + QApplication::postEvent(m_page->view(), drtEvent); + + // Start an event loop for async handling of Drag & Drop + m_eventLoop = new QEventLoop; + m_eventLoop->exec(); + delete m_eventLoop; + m_eventLoop = 0; +} + +bool EventSender::eventFilter(QObject* watched, QEvent* event) +{ + if (watched != m_page->view()) + return false; + switch (event->type()) { + case QEvent::Leave: + return true; + case QEvent::MouseButtonPress: + m_mouseButtonPressed = true; + break; + case QEvent::MouseMove: + if (m_mouseButtonPressed) + m_drag = true; + break; + case QEvent::MouseButtonRelease: + m_mouseButtonPressed = false; + m_drag = false; + break; + case DRT_MESSAGE_DONE: + m_eventLoop->exit(); + return true; + } + return false; +} diff --git a/WebKitTools/DumpRenderTree/qt/EventSenderQt.h b/WebKitTools/DumpRenderTree/qt/EventSenderQt.h index fd74455..f6cfc7c 100644 --- a/WebKitTools/DumpRenderTree/qt/EventSenderQt.h +++ b/WebKitTools/DumpRenderTree/qt/EventSenderQt.h @@ -31,6 +31,7 @@ #include <QApplication> #include <QEvent> +#include <QEventLoop> #include <QMouseEvent> #include <QObject> #include <QPoint> @@ -40,25 +41,52 @@ #include <qwebpage.h> #include <qwebframe.h> +#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) +#include <QTouchEvent> +#endif + class EventSender : public QObject { Q_OBJECT public: EventSender(QWebPage* parent); + virtual bool eventFilter(QObject* watched, QEvent* event); public slots: void mouseDown(int button = 0); void mouseUp(int button = 0); void mouseMoveTo(int x, int y); void leapForward(int ms); - void keyDown(const QString& string, const QStringList& modifiers = QStringList()); + void keyDown(const QString& string, const QStringList& modifiers = QStringList(), unsigned int location = 0); void clearKillRing() {} void contextClick(); void scheduleAsynchronousClick(); + void addTouchPoint(int x, int y); + void updateTouchPoint(int index, int x, int y); + void setTouchModifier(const QString &modifier, bool enable); + void touchStart(); + void touchMove(); + void touchEnd(); + void zoomPageIn(); + void zoomPageOut(); + void clearTouchPoints(); + void releaseTouchPoint(int index); private: + void sendTouchEvent(QEvent::Type); + void sendOrQueueEvent(QEvent*); + void replaySavedEvents(bool flush); QPoint m_mousePos; + Qt::MouseButtons m_mouseButtons; QWebPage* m_page; int m_timeLeap; + bool m_mouseButtonPressed; + bool m_drag; + QEventLoop* m_eventLoop; QWebFrame* frameUnderMouse() const; +#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) + QList<QTouchEvent::TouchPoint> m_touchPoints; + Qt::KeyboardModifiers m_touchModifiers; + bool m_touchActive; +#endif }; #endif // EventSenderQt_h diff --git a/WebKitTools/DumpRenderTree/qt/jsobjects.cpp b/WebKitTools/DumpRenderTree/qt/GCControllerQt.cpp index af331f0..9cc3aa7 100644 --- a/WebKitTools/DumpRenderTree/qt/jsobjects.cpp +++ b/WebKitTools/DumpRenderTree/qt/GCControllerQt.cpp @@ -28,20 +28,20 @@ */ #include "config.h" -#include "jsobjects.h" +#include "GCControllerQt.h" #include <qwebpage.h> -GCController::GCController(QWebPage* parent) - : QObject(parent) -{ -} - extern int qt_drt_javaScriptObjectsCount(); extern void qt_drt_garbageCollector_collect(); extern void qt_drt_garbageCollector_collectOnAlternateThread(bool waitUntilDone); +GCController::GCController(QWebPage* parent) + : QObject(parent) +{ +} + void GCController::collect() const { qt_drt_garbageCollector_collect(); diff --git a/WebKitTools/DumpRenderTree/qt/jsobjects.h b/WebKitTools/DumpRenderTree/qt/GCControllerQt.h index 3ee566b..8f5b432 100644 --- a/WebKitTools/DumpRenderTree/qt/jsobjects.h +++ b/WebKitTools/DumpRenderTree/qt/GCControllerQt.h @@ -26,8 +26,8 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSOBJECTS_H -#define JSOBJECTS_H +#ifndef GCControllerQt_h +#define GCControllerQt_h #include <QObject> diff --git a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp index 0ea5632..9430ec7 100644 --- a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp +++ b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp @@ -29,10 +29,12 @@ #include "config.h" #include "LayoutTestControllerQt.h" -#include "DumpRenderTree.h" +#include "DumpRenderTreeQt.h" #include "WorkQueue.h" -#include "WorkQueueItem.h" +#include "WorkQueueItemQt.h" #include <QDir> +#include <QLocale> +#include <qwebsettings.h> extern void qt_dump_editing_callbacks(bool b); extern void qt_dump_resource_load_callbacks(bool b); @@ -41,9 +43,11 @@ extern bool qt_drt_pauseAnimation(QWebFrame*, const QString& name, double time, extern bool qt_drt_pauseTransitionOfProperty(QWebFrame*, const QString& name, double time, const QString& elementId); extern bool qt_drt_pauseSVGAnimation(QWebFrame*, const QString& animationId, double time, const QString& elementId); extern int qt_drt_numberOfActiveAnimations(QWebFrame*); +extern void qt_drt_setDomainRelaxationForbiddenForURLScheme(bool forbidden, const QString& scheme); extern void qt_drt_whiteListAccessFromOrigin(const QString& sourceOrigin, const QString& destinationProtocol, const QString& destinationHost, bool allowDestinationSubdomains); extern QString qt_drt_counterValueForElementById(QWebFrame* qFrame, const QString& id); +extern int qt_drt_workerThreadCount(); LayoutTestController::LayoutTestController(WebCore::DumpRenderTree* drt) : QObject() @@ -54,7 +58,8 @@ LayoutTestController::LayoutTestController(WebCore::DumpRenderTree* drt) void LayoutTestController::reset() { - m_isLoading = true; + m_hasDumped = false; + m_loadFinished = false; m_textDump = false; m_dumpBackForwardList = false; m_dumpChildrenAsText = false; @@ -67,8 +72,10 @@ void LayoutTestController::reset() m_topLoadingFrame = 0; m_waitForPolicy = false; m_handleErrorPages = false; + m_webHistory = 0; qt_dump_editing_callbacks(false); qt_dump_resource_load_callbacks(false); + emit hidePage(); } void LayoutTestController::processWork() @@ -78,32 +85,40 @@ void LayoutTestController::processWork() // if we didn't start a new load, then we finished all the commands, so we're ready to dump state if (WorkQueue::shared()->processWork() && !shouldWaitUntilDone()) { emit done(); - m_isLoading = false; + m_hasDumped = true; } } -// Called on loadFinished on mainFrame. +// Called on loadFinished on WebPage void LayoutTestController::maybeDump(bool success) { - Q_ASSERT(sender() == m_topLoadingFrame->page()); + // This can happen on any of the http/tests/security/window-events-*.html tests, where the test opens + // a new window, calls the unload and load event handlers on the window's page, and then immediately + // issues a notifyDone. Needs investigation. + if (!m_topLoadingFrame) + return; + + // It is possible that we get called by windows created from the main page that have finished + // loading, so we don't ASSERT here. At the moment we do not gather results from such windows, + // but may need to in future. + if (sender() != m_topLoadingFrame->page()) + return; + + m_loadFinished = true; // as the function is called on loadFinished, the test might // already have dumped and thus no longer be active, thus // bail out here. - if (!m_isLoading) + if (m_hasDumped) return; - m_topLoadingFrame = 0; WorkQueue::shared()->setFrozen(true); // first complete load freezes the queue for the rest of this test - - if (!shouldWaitUntilDone()) { - if (WorkQueue::shared()->count()) - QTimer::singleShot(0, this, SLOT(processWork())); - else { - if (success) - emit done(); - m_isLoading = false; - } + if (WorkQueue::shared()->count()) + QTimer::singleShot(0, this, SLOT(processWork())); + else if (!shouldWaitUntilDone()) { + if (success) + emit done(); + m_hasDumped = true; } } @@ -119,9 +134,19 @@ QString LayoutTestController::counterValueForElementById(const QString& id) return qt_drt_counterValueForElementById(m_drt->webPage()->mainFrame(), id); } +int LayoutTestController::webHistoryItemCount() +{ + if (!m_webHistory) + return -1; + + // Subtract one here as our QWebHistory::count() includes the actual page, + // which is not considered in the DRT tests. + return m_webHistory->count() - 1; +} + void LayoutTestController::keepWebHistory() { - // FIXME: implement + m_webHistory = m_drt->webPage()->history(); } void LayoutTestController::notifyDone() @@ -132,11 +157,19 @@ void LayoutTestController::notifyDone() return; m_timeoutTimer.stop(); + m_waitForDone = false; + + // If the page has not finished loading (i.e. loadFinished() has not been emitted) then + // content created by the likes of document.write() JS methods will not be available yet. + // When the page has finished loading, maybeDump above will dump the results now that we have + // just set shouldWaitUntilDone to false. + if (!m_loadFinished) + return; + emit done(); // FIXME: investigate why always resetting these result in timeouts - m_isLoading = false; - m_waitForDone = false; + m_hasDumped = true; m_waitForPolicy = false; } @@ -145,6 +178,11 @@ int LayoutTestController::windowCount() return m_drt->windowCount(); } +void LayoutTestController::display() +{ + emit showPage(); +} + void LayoutTestController::clearBackForwardList() { m_drt->webPage()->history()->clear(); @@ -153,7 +191,7 @@ void LayoutTestController::clearBackForwardList() QString LayoutTestController::pathToLocalResource(const QString& url) { // Function introduced in r28690. - return QLatin1String("file://") + QUrl(url).toLocalFile(); + return QDir::toNativeSeparators(url); } void LayoutTestController::dumpEditingCallbacks() @@ -208,7 +246,7 @@ void LayoutTestController::queueNonLoadingScript(const QString& script) void LayoutTestController::provisionalLoad() { QWebFrame* frame = qobject_cast<QWebFrame*>(sender()); - if (!m_topLoadingFrame && m_isLoading) + if (!m_topLoadingFrame && !m_hasDumped) m_topLoadingFrame = frame; } @@ -280,6 +318,26 @@ void LayoutTestController::setPOSIXLocale(const QString& locale) QLocale::setDefault(qlocale); } +void LayoutTestController::setWindowIsKey(bool isKey) +{ + m_drt->switchFocus(isKey); +} + +void LayoutTestController::setMainFrameIsFirstResponder(bool isFirst) +{ + //FIXME: only need this for the moment: https://bugs.webkit.org/show_bug.cgi?id=32990 +} + +void LayoutTestController::setXSSAuditorEnabled(bool enable) +{ + // Set XSSAuditorEnabled globally so that windows created by the test inherit it too. + // resetSettings() will call this to reset the page and global setting to false again. + // Needed by http/tests/security/xssAuditor/link-opens-new-window.html + QWebSettings* globalSettings = QWebSettings::globalSettings(); + globalSettings->setAttribute(QWebSettings::XSSAuditorEnabled, enable); + m_drt->webPage()->settings()->setAttribute(QWebSettings::XSSAuditorEnabled, enable); +} + bool LayoutTestController::pauseAnimationAtTimeOnElementWithId(const QString& animationName, double time, const QString& elementId) @@ -363,3 +421,26 @@ void LayoutTestController::overridePreference(const QString& name, const QVarian else if (name == "WebKitUsesPageCachePreferenceKey") QWebSettings::setMaximumPagesInCache(value.toInt()); } + +void LayoutTestController::setUserStyleSheetLocation(const QString& url) +{ + m_userStyleSheetLocation = QUrl(url); +} + +void LayoutTestController::setUserStyleSheetEnabled(bool enabled) +{ + if (enabled) + m_drt->webPage()->settings()->setUserStyleSheetUrl(m_userStyleSheetLocation); + else + m_drt->webPage()->settings()->setUserStyleSheetUrl(QUrl()); +} + +void LayoutTestController::setDomainRelaxationForbiddenForURLScheme(bool forbidden, const QString& scheme) +{ + qt_drt_setDomainRelaxationForbiddenForURLScheme(forbidden, scheme); +} + +int LayoutTestController::workerThreadCount() +{ + return qt_drt_workerThreadCount(); +} diff --git a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h index ac8681f..64b3a15 100644 --- a/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h +++ b/WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h @@ -51,12 +51,11 @@ namespace WebCore { } class LayoutTestController : public QObject { Q_OBJECT + Q_PROPERTY(int webHistoryItemCount READ webHistoryItemCount) + Q_PROPERTY(int workerThreadCount READ workerThreadCount) public: LayoutTestController(WebCore::DumpRenderTree* drt); - bool isLoading() const { return m_isLoading; } - void setLoading(bool loading) { m_isLoading = loading; } - bool shouldDumpAsText() const { return m_textDump; } bool shouldDumpBackForwardList() const { return m_dumpBackForwardList; } bool shouldDumpChildrenAsText() const { return m_dumpChildrenAsText; } @@ -76,6 +75,9 @@ protected: signals: void done(); + void showPage(); + void hidePage(); + public slots: void maybeDump(bool ok); void dumpAsText() { m_textDump = true; } @@ -85,6 +87,7 @@ public slots: void setCanOpenWindows() { m_canOpenWindows = true; } void waitUntilDone(); QString counterValueForElementById(const QString& id); + int webHistoryItemCount(); void keepWebHistory(); void notifyDone(); void dumpBackForwardList() { m_dumpBackForwardList = true; } @@ -100,7 +103,7 @@ public slots: void provisionalLoad(); void setCloseRemainingWindowsWhenComplete(bool = false) {} int windowCount(); - void display() {} + void display(); void clearBackForwardList(); QString pathToLocalResource(const QString& url); void dumpTitleChanges() { m_dumpTitleChanges = true; } @@ -115,6 +118,10 @@ public slots: void setPrivateBrowsingEnabled(bool enable); void setPopupBlockingEnabled(bool enable); void setPOSIXLocale(const QString& locale); + void resetLoadFinished() { m_loadFinished = false; } + void setWindowIsKey(bool isKey); + void setMainFrameIsFirstResponder(bool isFirst); + void setXSSAuditorEnabled(bool enable); bool pauseAnimationAtTimeOnElementWithId(const QString& animationName, double time, const QString& elementId); bool pauseTransitionAtTimeOnElementWithId(const QString& propertyName, double time, const QString& elementId); @@ -132,12 +139,16 @@ public slots: void waitForPolicyDelegate(); void overridePreference(const QString& name, const QVariant& value); + void setUserStyleSheetLocation(const QString& url); + void setUserStyleSheetEnabled(bool enabled); + void setDomainRelaxationForbiddenForURLScheme(bool forbidden, const QString& scheme); + int workerThreadCount(); private slots: void processWork(); private: - bool m_isLoading; + bool m_hasDumped; bool m_textDump; bool m_dumpBackForwardList; bool m_dumpChildrenAsText; @@ -148,10 +159,13 @@ private: bool m_dumpStatusCallbacks; bool m_waitForPolicy; bool m_handleErrorPages; + bool m_loadFinished; + QUrl m_userStyleSheetLocation; QBasicTimer m_timeoutTimer; QWebFrame* m_topLoadingFrame; WebCore::DumpRenderTree* m_drt; + QWebHistory* m_webHistory; }; #endif // LayoutTestControllerQt_h diff --git a/WebKitTools/DumpRenderTree/qt/WorkQueueItemQt.cpp b/WebKitTools/DumpRenderTree/qt/WorkQueueItemQt.cpp index 807a6a4..067e6aa 100644 --- a/WebKitTools/DumpRenderTree/qt/WorkQueueItemQt.cpp +++ b/WebKitTools/DumpRenderTree/qt/WorkQueueItemQt.cpp @@ -27,7 +27,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" -#include "WorkQueueItem.h" +#include "WorkQueueItemQt.h" QWebFrame* findFrameNamed(const QString& frameName, QWebFrame* frame) { diff --git a/WebKitTools/DumpRenderTree/qt/WorkQueueItem.h b/WebKitTools/DumpRenderTree/qt/WorkQueueItemQt.h index d534493..94da5e1 100644 --- a/WebKitTools/DumpRenderTree/qt/WorkQueueItem.h +++ b/WebKitTools/DumpRenderTree/qt/WorkQueueItemQt.h @@ -7,13 +7,13 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * 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. + * documentation and/or other materials provided with the distribution. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. + * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -27,8 +27,8 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WorkQueueItem_h -#define WorkQueueItem_h +#ifndef WorkQueueItemQt_h +#define WorkQueueItemQt_h #include <QPointer> #include <QString> @@ -140,4 +140,4 @@ public: } }; -#endif // !defined(WorkQueueItem_h) +#endif // !defined(WorkQueueItemQt_h) diff --git a/WebKitTools/DumpRenderTree/qt/main.cpp b/WebKitTools/DumpRenderTree/qt/main.cpp index 719315f..69d3c23 100644 --- a/WebKitTools/DumpRenderTree/qt/main.cpp +++ b/WebKitTools/DumpRenderTree/qt/main.cpp @@ -27,7 +27,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "DumpRenderTree.h" +#include "DumpRenderTreeQt.h" #include <wtf/AlwaysInline.h> @@ -40,6 +40,7 @@ #include <qwebsettings.h> #include <qwebdatabase.h> #include <qdesktopservices.h> +#include <qtimer.h> #include <qwindowsstyle.h> #ifdef Q_WS_X11 @@ -89,12 +90,14 @@ QString get_backtrace() { return s; } +#ifndef Q_OS_WIN static NO_RETURN void crashHandler(int sig) { fprintf(stderr, "%s\n", strsignal(sig)); fprintf(stderr, "%s\n", get_backtrace().toLatin1().constData()); exit(128 + sig); } +#endif int main(int argc, char* argv[]) { @@ -121,6 +124,7 @@ int main(int argc, char* argv[]) QX11Info::setAppDpiX(0, 96); #endif +#ifndef Q_OS_WIN signal(SIGILL, crashHandler); /* 4: illegal instruction (not reset when caught) */ signal(SIGTRAP, crashHandler); /* 5: trace trap (not reset when caught) */ signal(SIGFPE, crashHandler); /* 8: floating point exception */ @@ -130,41 +134,42 @@ int main(int argc, char* argv[]) signal(SIGPIPE, crashHandler); /* 13: write on a pipe with no reader */ signal(SIGXCPU, crashHandler); /* 24: exceeded CPU time limit */ signal(SIGXFSZ, crashHandler); /* 25: exceeded file size limit */ +#endif QStringList args = app.arguments(); if (args.count() < 2) { - qDebug() << "Usage: DumpRenderTree [-v] filename"; + qDebug() << "Usage: DumpRenderTree [-v|--pixel-tests] filename"; exit(0); } - // supress debug output from Qt if not started with -v + // Suppress debug output from Qt if not started with -v if (!args.contains(QLatin1String("-v"))) qInstallMsgHandler(messageHandler); WebCore::DumpRenderTree dumper; - if (args.contains("--pixel-tests")) + if (args.contains(QLatin1String("--pixel-tests"))) dumper.setDumpPixels(true); QString dbDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation) + QDir::separator() + "qtwebkitdrt"; QWebSettings::setOfflineStoragePath(dbDir); QWebDatabase::removeAllDatabases(); - if (args.last() == QLatin1String("-")) { - dumper.open(); + if (args.contains(QLatin1String("-"))) { + QObject::connect(&dumper, SIGNAL(ready()), &dumper, SLOT(readLine()), Qt::QueuedConnection); + QTimer::singleShot(0, &dumper, SLOT(readLine())); } else { - if (!args.last().startsWith("/") - && !args.last().startsWith("file:") - && !args.last().startsWith("http:") - && !args.last().startsWith("https:")) { - QString path = QDir::currentPath(); - if (!path.endsWith('/')) - path.append('/'); - args.last().prepend(path); + dumper.setSingleFileMode(true); + for (int i = 1; i < args.size(); ++i) { + if (!args.at(i).startsWith('-')) { + dumper.processLine(args.at(i)); + break; + } } - dumper.open(QUrl(args.last())); } + return app.exec(); + #ifdef Q_WS_X11 FcConfigSetCurrent(0); #endif diff --git a/WebKitTools/DumpRenderTree/win/AccessibilityControllerWin.cpp b/WebKitTools/DumpRenderTree/win/AccessibilityControllerWin.cpp index ac64efb..6b35948 100644 --- a/WebKitTools/DumpRenderTree/win/AccessibilityControllerWin.cpp +++ b/WebKitTools/DumpRenderTree/win/AccessibilityControllerWin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008, 2009, 2010 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,7 +28,10 @@ #include "AccessibilityUIElement.h" #include "DumpRenderTree.h" +#include "FrameLoadDelegate.h" #include <JavaScriptCore/Assertions.h> +#include <JavaScriptCore/JSRetainPtr.h> +#include <JavaScriptCore/JSStringRef.h> #include <WebCore/COMPtr.h> #include <WebKit/WebKit.h> #include <oleacc.h> @@ -39,12 +42,21 @@ using namespace std; AccessibilityController::AccessibilityController() : m_focusEventHook(0) , m_scrollingStartEventHook(0) + , m_valueChangeEventHook(0) + , m_allEventsHook(0) { } AccessibilityController::~AccessibilityController() { setLogFocusEvents(false); + setLogValueChangeEvents(false); + + if (m_allEventsHook) + UnhookWinEvent(m_allEventsHook); + + for (HashMap<PlatformUIElement, JSObjectRef>::iterator it = m_notificationListeners.begin(); it != m_notificationListeners.end(); ++it) + JSValueUnprotect(frame->globalContext(), it->second); } AccessibilityUIElement AccessibilityController::focusedElement() @@ -89,7 +101,7 @@ AccessibilityUIElement AccessibilityController::rootElement() return rootAccessible; } -static void CALLBACK logEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD, DWORD) +static void CALLBACK logEventProc(HWINEVENTHOOK, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD, DWORD) { // Get the accessible object for this event. COMPtr<IAccessible> parentObject; @@ -112,6 +124,17 @@ static void CALLBACK logEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND printf("Received focus event for object '%S'.\n", name.c_str()); break; + case EVENT_OBJECT_VALUECHANGE: { + BSTR valueBSTR; + hr = parentObject->get_accValue(vChild, &valueBSTR); + ASSERT(SUCCEEDED(hr)); + wstring value(valueBSTR, ::SysStringLen(valueBSTR)); + SysFreeString(valueBSTR); + + printf("Received value change event for object '%S', value '%S'.\n", name.c_str(), value.c_str()); + break; + } + case EVENT_SYSTEM_SCROLLINGSTART: printf("Received scrolling start event for object '%S'.\n", name.c_str()); break; @@ -120,6 +143,8 @@ static void CALLBACK logEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND printf("Received unknown event for object '%S'.\n", name.c_str()); break; } + + VariantClear(&vChild); } void AccessibilityController::setLogFocusEvents(bool logFocusEvents) @@ -142,6 +167,26 @@ void AccessibilityController::setLogFocusEvents(bool logFocusEvents) ASSERT(m_focusEventHook); } +void AccessibilityController::setLogValueChangeEvents(bool logValueChangeEvents) +{ + if (!!m_valueChangeEventHook == logValueChangeEvents) + return; + + if (!logValueChangeEvents) { + UnhookWinEvent(m_valueChangeEventHook); + m_valueChangeEventHook = 0; + return; + } + + // Ensure that accessibility is initialized for the WebView by querying for + // the root accessible object. + rootElement(); + + m_valueChangeEventHook = SetWinEventHook(EVENT_OBJECT_VALUECHANGE, EVENT_OBJECT_VALUECHANGE, GetModuleHandle(0), logEventProc, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT); + + ASSERT(m_valueChangeEventHook); +} + void AccessibilityController::setLogScrollingStartEvents(bool logScrollingStartEvents) { if (!!m_scrollingStartEventHook == logScrollingStartEvents) @@ -161,3 +206,83 @@ void AccessibilityController::setLogScrollingStartEvents(bool logScrollingStartE ASSERT(m_scrollingStartEventHook); } + +static string stringEvent(DWORD event) +{ + switch(event) { + case EVENT_OBJECT_VALUECHANGE: + return "value change event"; + default: + return "unknown event"; + } +} + +static void CALLBACK notificationListenerProc(HWINEVENTHOOK, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD, DWORD) +{ + // Get the accessible object for this event. + COMPtr<IAccessible> parentObject; + + VARIANT vChild; + VariantInit(&vChild); + + HRESULT hr = AccessibleObjectFromEvent(hwnd, idObject, idChild, &parentObject, &vChild); + ASSERT(SUCCEEDED(hr)); + + COMPtr<IDispatch> childDispatch; + if (FAILED(parentObject->get_accChild(vChild, &childDispatch))) { + VariantClear(&vChild); + return; + } + + COMPtr<IAccessible> childAccessible(Query, childDispatch); + + sharedFrameLoadDelegate->accessibilityController()->notificationReceived(childAccessible, stringEvent(event)); + + VariantClear(&vChild); +} + +static COMPtr<IAccessibleComparable> comparableObject(const COMPtr<IServiceProvider>& serviceProvider) +{ + COMPtr<IAccessibleComparable> comparable; + serviceProvider->QueryService(SID_AccessibleComparable, __uuidof(IAccessibleComparable), reinterpret_cast<void**>(&comparable)); + return comparable; +} + +void AccessibilityController::notificationReceived(PlatformUIElement element, const string& eventName) +{ + for (HashMap<PlatformUIElement, JSObjectRef>::iterator it = m_notificationListeners.begin(); it != m_notificationListeners.end(); ++it) { + COMPtr<IServiceProvider> thisServiceProvider(Query, it->first); + if (!thisServiceProvider) + continue; + + COMPtr<IAccessibleComparable> thisComparable = comparableObject(thisServiceProvider); + if (!thisComparable) + continue; + + COMPtr<IServiceProvider> elementServiceProvider(Query, element); + if (!elementServiceProvider) + continue; + + COMPtr<IAccessibleComparable> elementComparable = comparableObject(elementServiceProvider); + if (!elementComparable) + continue; + + BOOL isSame = FALSE; + thisComparable->isSameObject(elementComparable.get(), &isSame); + if (!isSame) + continue; + + JSRetainPtr<JSStringRef> jsNotification(Adopt, JSStringCreateWithUTF8CString(eventName.c_str())); + JSValueRef argument = JSValueMakeString(frame->globalContext(), jsNotification.get()); + JSObjectCallAsFunction(frame->globalContext(), it->second, NULL, 1, &argument, NULL); + } +} + +void AccessibilityController::addNotificationListener(PlatformUIElement element, JSObjectRef functionCallback) +{ + if (!m_allEventsHook) + m_allEventsHook = SetWinEventHook(EVENT_MIN, EVENT_MAX, GetModuleHandle(0), notificationListenerProc, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT); + + JSValueProtect(frame->globalContext(), functionCallback); + m_notificationListeners.add(element, functionCallback); +} diff --git a/WebKitTools/DumpRenderTree/win/AccessibilityUIElementWin.cpp b/WebKitTools/DumpRenderTree/win/AccessibilityUIElementWin.cpp index 163abb1..301112f 100644 --- a/WebKitTools/DumpRenderTree/win/AccessibilityUIElementWin.cpp +++ b/WebKitTools/DumpRenderTree/win/AccessibilityUIElementWin.cpp @@ -26,6 +26,9 @@ #include "config.h" #include "AccessibilityUIElement.h" +#include "AccessibilityController.h" +#include "DumpRenderTree.h" +#include "FrameLoadDelegate.h" #include <JavaScriptCore/JSStringRef.h> #include <tchar.h> #include <string> @@ -98,6 +101,12 @@ AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index) return COMPtr<IAccessible>(Query, child); } +unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element) +{ + // FIXME: implement + return 0; +} + JSStringRef AccessibilityUIElement::allAttributes() { return JSStringCreateWithCharacters(0, 0); @@ -120,7 +129,11 @@ AccessibilityUIElement AccessibilityUIElement::titleUIElement() AccessibilityUIElement AccessibilityUIElement::parentElement() { - return 0; + COMPtr<IDispatch> parent; + m_element->get_accParent(&parent); + + COMPtr<IAccessible> parentAccessible(Query, parent); + return parentAccessible; } JSStringRef AccessibilityUIElement::attributesOfChildren() @@ -257,9 +270,24 @@ JSStringRef AccessibilityUIElement::valueDescription() { return 0; } + +static DWORD accessibilityState(COMPtr<IAccessible> element) +{ + VARIANT state; + element->get_accState(self(), &state); + + ASSERT(V_VT(&state) == VT_I4); + + DWORD result = state.lVal; + VariantClear(&state); + + return result; +} + bool AccessibilityUIElement::isSelected() const { - return false; + DWORD state = accessibilityState(m_element); + return (state & STATE_SYSTEM_SELECTED) == STATE_SYSTEM_SELECTED; } int AccessibilityUIElement::hierarchicalLevel() const @@ -282,12 +310,21 @@ bool AccessibilityUIElement::isExpanded() const return false; } +bool AccessibilityUIElement::isChecked() const +{ + VARIANT vState; + if (FAILED(m_element->get_accState(self(), &vState))) + return false; + + return vState.lVal & STATE_SYSTEM_CHECKED; +} + JSStringRef AccessibilityUIElement::orientation() const { return 0; } -double AccessibilityUIElement::intValue() +double AccessibilityUIElement::intValue() const { BSTR valueBSTR; if (FAILED(m_element->get_accValue(self(), &valueBSTR)) || !valueBSTR) @@ -315,7 +352,8 @@ bool AccessibilityUIElement::isActionSupported(JSStringRef action) bool AccessibilityUIElement::isEnabled() { - return false; + DWORD state = accessibilityState(m_element); + return (state & STATE_SYSTEM_UNAVAILABLE) != STATE_SYSTEM_UNAVAILABLE; } bool AccessibilityUIElement::isRequired() const @@ -403,11 +441,18 @@ void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned le { } -JSStringRef AccessibilityUIElement::attributeValue(JSStringRef attribute) +JSStringRef AccessibilityUIElement::stringAttributeValue(JSStringRef attribute) { + // FIXME: implement return JSStringCreateWithCharacters(0, 0); } +bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute) +{ + // FIXME: implement + return false; +} + bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute) { return false; @@ -428,6 +473,8 @@ void AccessibilityUIElement::decrement() void AccessibilityUIElement::showMenu() { + ASSERT(hasPopup()); + m_element->accDoDefaultAction(self()); } AccessibilityUIElement AccessibilityUIElement::disclosedRowAtIndex(unsigned index) @@ -477,3 +524,75 @@ JSStringRef AccessibilityUIElement::documentURI() { return JSStringCreateWithCharacters(0, 0); } + +JSStringRef AccessibilityUIElement::url() +{ + // FIXME: implement + return JSStringCreateWithCharacters(0, 0); +} + +bool AccessibilityUIElement::addNotificationListener(JSObjectRef functionCallback) +{ + if (!functionCallback) + return false; + + sharedFrameLoadDelegate->accessibilityController()->addNotificationListener(m_element, functionCallback); + return true; +} + +bool AccessibilityUIElement::isSelectable() const +{ + DWORD state = accessibilityState(m_element); + return (state & STATE_SYSTEM_SELECTABLE) == STATE_SYSTEM_SELECTABLE; +} + +bool AccessibilityUIElement::isMultiSelectable() const +{ + DWORD multiSelectable = STATE_SYSTEM_EXTSELECTABLE | STATE_SYSTEM_MULTISELECTABLE; + DWORD state = accessibilityState(m_element); + return (state & multiSelectable) == multiSelectable; +} + +bool AccessibilityUIElement::isVisible() const +{ + DWORD state = accessibilityState(m_element); + return (state & STATE_SYSTEM_INVISIBLE) != STATE_SYSTEM_INVISIBLE; +} + +bool AccessibilityUIElement::isOffScreen() const +{ + DWORD state = accessibilityState(m_element); + return (state & STATE_SYSTEM_OFFSCREEN) == STATE_SYSTEM_OFFSCREEN; +} + +bool AccessibilityUIElement::isCollapsed() const +{ + DWORD state = accessibilityState(m_element); + return (state & STATE_SYSTEM_COLLAPSED) == STATE_SYSTEM_COLLAPSED; +} + +bool AccessibilityUIElement::hasPopup() const +{ + DWORD state = accessibilityState(m_element); + return (state & STATE_SYSTEM_HASPOPUP) == STATE_SYSTEM_HASPOPUP; +} + +void AccessibilityUIElement::takeFocus() +{ + m_element->accSelect(SELFLAG_TAKEFOCUS, self()); +} + +void AccessibilityUIElement::takeSelection() +{ + m_element->accSelect(SELFLAG_TAKESELECTION, self()); +} + +void AccessibilityUIElement::addSelection() +{ + m_element->accSelect(SELFLAG_ADDSELECTION, self()); +} + +void AccessibilityUIElement::removeSelection() +{ + m_element->accSelect(SELFLAG_REMOVESELECTION, self()); +} diff --git a/WebKitTools/DumpRenderTree/win/DumpRenderTree.vcproj b/WebKitTools/DumpRenderTree/win/DumpRenderTree.vcproj index 299c53c..4d2dea8 100644 --- a/WebKitTools/DumpRenderTree/win/DumpRenderTree.vcproj +++ b/WebKitTools/DumpRenderTree/win/DumpRenderTree.vcproj @@ -39,7 +39,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(ProjectDir)\.";"$(ProjectDir)\..";"$(ProjectDir)\..\cg";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\private";"$(WebKitOutputDir)\Include\DumpRenderTree\ForwardingHeaders";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitOutputDir)\Include\private\JavaScriptCore";"$(WebKitLibrariesDir)\Include";"$(WebKitLibrariesDir)\Include\private";"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitOutputDir)\Include\WebCore";"$(WebKitLibrariesDir)\Include\WebCore";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility""
+ AdditionalIncludeDirectories=""$(ProjectDir)\.";"$(ProjectDir)\..";"$(ProjectDir)\..\cg";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\private";"$(WebKitOutputDir)\Include\DumpRenderTree\ForwardingHeaders";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitOutputDir)\Include\private\JavaScriptCore";"$(WebKitLibrariesDir)\Include";"$(WebKitLibrariesDir)\Include\private";"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitOutputDir)\Include\WebCore";"$(WebKitLibrariesDir)\Include\WebCore""
PreprocessorDefinitions="_CONSOLE"
DisableSpecificWarnings="4146"
ForcedIncludeFiles="DumpRenderTreePrefix.h"
@@ -112,7 +112,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(ProjectDir)\.";"$(ProjectDir)\..";"$(ProjectDir)\..\cg";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\private";"$(WebKitOutputDir)\Include\DumpRenderTree\ForwardingHeaders";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitOutputDir)\Include\private\JavaScriptCore";"$(WebKitLibrariesDir)\Include";"$(WebKitLibrariesDir)\Include\private";"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitOutputDir)\Include\WebCore";"$(WebKitLibrariesDir)\Include\WebCore";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility""
+ AdditionalIncludeDirectories=""$(ProjectDir)\.";"$(ProjectDir)\..";"$(ProjectDir)\..\cg";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\private";"$(WebKitOutputDir)\Include\DumpRenderTree\ForwardingHeaders";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitOutputDir)\Include\private\JavaScriptCore";"$(WebKitLibrariesDir)\Include";"$(WebKitLibrariesDir)\Include\private";"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitOutputDir)\Include\WebCore";"$(WebKitLibrariesDir)\Include\WebCore""
PreprocessorDefinitions="_CONSOLE"
DisableSpecificWarnings="4146"
ForcedIncludeFiles="DumpRenderTreePrefix.h"
@@ -184,7 +184,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(ProjectDir)\.";"$(ProjectDir)\..";"$(ProjectDir)\..\cg";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\private";"$(WebKitOutputDir)\Include\DumpRenderTree\ForwardingHeaders";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitOutputDir)\Include\private\JavaScriptCore";"$(WebKitLibrariesDir)\Include";"$(WebKitLibrariesDir)\Include\private";"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitOutputDir)\Include\WebCore";"$(WebKitLibrariesDir)\Include\WebCore";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility""
+ AdditionalIncludeDirectories=""$(ProjectDir)\.";"$(ProjectDir)\..";"$(ProjectDir)\..\cg";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\private";"$(WebKitOutputDir)\Include\DumpRenderTree\ForwardingHeaders";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitOutputDir)\Include\private\JavaScriptCore";"$(WebKitLibrariesDir)\Include";"$(WebKitLibrariesDir)\Include\private";"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitOutputDir)\Include\WebCore";"$(WebKitLibrariesDir)\Include\WebCore""
PreprocessorDefinitions="_CONSOLE"
DisableSpecificWarnings="4146"
ForcedIncludeFiles="DumpRenderTreePrefix.h"
@@ -255,7 +255,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(ProjectDir)\.";"$(ProjectDir)\..";"$(ProjectDir)\..\cairo";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\include\private";"$(WebKitOutputDir)\Include\DumpRenderTree\ForwardingHeaders";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitOutputDir)\Include\private\JavaScriptCore";"$(WebKitLibrariesDir)\Include";"$(WebKitLibrariesDir)\Include\private";"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitOutputDir)\Include\WebCore";"$(WebKitLibrariesDir)\Include\WebCore";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility""
+ AdditionalIncludeDirectories=""$(ProjectDir)\.";"$(ProjectDir)\..";"$(ProjectDir)\..\cairo";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\include\private";"$(WebKitOutputDir)\Include\DumpRenderTree\ForwardingHeaders";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitOutputDir)\Include\private\JavaScriptCore";"$(WebKitLibrariesDir)\Include";"$(WebKitLibrariesDir)\Include\private";"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitOutputDir)\Include\WebCore";"$(WebKitLibrariesDir)\Include\WebCore""
PreprocessorDefinitions="_CONSOLE"
DisableSpecificWarnings="4146"
ForcedIncludeFiles="DumpRenderTreePrefix.h"
@@ -328,7 +328,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(ProjectDir)\.";"$(ProjectDir)\..";"$(ProjectDir)\..\cairo";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\private";"$(WebKitOutputDir)\Include\DumpRenderTree\ForwardingHeaders";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitOutputDir)\Include\private\JavaScriptCore";"$(WebKitLibrariesDir)\Include";"$(WebKitLibrariesDir)\Include\private";"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitOutputDir)\Include\WebCore";"$(WebKitLibrariesDir)\Include\WebCore";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility""
+ AdditionalIncludeDirectories=""$(ProjectDir)\.";"$(ProjectDir)\..";"$(ProjectDir)\..\cairo";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\private";"$(WebKitOutputDir)\Include\DumpRenderTree\ForwardingHeaders";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitOutputDir)\Include\private\JavaScriptCore";"$(WebKitLibrariesDir)\Include";"$(WebKitLibrariesDir)\Include\private";"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitOutputDir)\Include\WebCore";"$(WebKitLibrariesDir)\Include\WebCore""
PreprocessorDefinitions="_CONSOLE"
DisableSpecificWarnings="4146"
ForcedIncludeFiles="DumpRenderTreePrefix.h"
@@ -400,7 +400,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(ProjectDir)\.";"$(ProjectDir)\..";"$(ProjectDir)\..\cg";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\private";"$(WebKitOutputDir)\Include\DumpRenderTree\ForwardingHeaders";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitOutputDir)\Include\private\JavaScriptCore";"$(WebKitLibrariesDir)\Include";"$(WebKitLibrariesDir)\Include\private";"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitOutputDir)\Include\WebCore";"$(WebKitLibrariesDir)\Include\WebCore";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility""
+ AdditionalIncludeDirectories=""$(ProjectDir)\.";"$(ProjectDir)\..";"$(ProjectDir)\..\cg";"$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\private";"$(WebKitOutputDir)\Include\DumpRenderTree\ForwardingHeaders";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitOutputDir)\Include\private\JavaScriptCore";"$(WebKitLibrariesDir)\Include";"$(WebKitLibrariesDir)\Include\private";"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitOutputDir)\Include\WebCore";"$(WebKitLibrariesDir)\Include\WebCore""
PreprocessorDefinitions="_CONSOLE"
DisableSpecificWarnings="4146"
ForcedIncludeFiles="DumpRenderTreePrefix.h"
diff --git a/WebKitTools/DumpRenderTree/win/DumpRenderTreeWin.h b/WebKitTools/DumpRenderTree/win/DumpRenderTreeWin.h index 54ec87b..499c57b 100644 --- a/WebKitTools/DumpRenderTree/win/DumpRenderTreeWin.h +++ b/WebKitTools/DumpRenderTree/win/DumpRenderTreeWin.h @@ -32,6 +32,7 @@ struct IWebFrame; struct IWebScriptWorld; struct IWebView; +struct FrameLoadDelegate; struct PolicyDelegate; typedef const struct __CFString* CFStringRef; typedef struct HWND__* HWND; @@ -60,4 +61,6 @@ unsigned worldIDForWorld(IWebScriptWorld*); extern UINT_PTR waitToDumpWatchdog; +extern COMPtr<FrameLoadDelegate> sharedFrameLoadDelegate; + #endif // DumpRenderTreeWin_h diff --git a/WebKitTools/DumpRenderTree/win/EventSender.cpp b/WebKitTools/DumpRenderTree/win/EventSender.cpp index dd5bf9d..5a42b00 100644 --- a/WebKitTools/DumpRenderTree/win/EventSender.cpp +++ b/WebKitTools/DumpRenderTree/win/EventSender.cpp @@ -144,6 +144,30 @@ static JSValueRef contextClickCallback(JSContextRef context, JSObjectRef functio return JSValueMakeUndefined(context); } +static WPARAM buildModifierFlags(JSContextRef context, const JSValueRef modifiers) +{ + JSObjectRef modifiersArray = JSValueToObject(context, modifiers, 0); + if (!modifiersArray) + return 0; + + WPARAM flags = 0; + int modifiersCount = JSValueToNumber(context, JSObjectGetProperty(context, modifiersArray, JSStringCreateWithUTF8CString("length"), 0), 0); + for (int i = 0; i < modifiersCount; ++i) { + JSValueRef value = JSObjectGetPropertyAtIndex(context, modifiersArray, i, 0); + JSStringRef string = JSValueToStringCopy(context, value, 0); + if (JSStringIsEqualToUTF8CString(string, "ctrlKey") + || JSStringIsEqualToUTF8CString(string, "addSelectionKey")) + flags |= MK_CONTROL; + else if (JSStringIsEqualToUTF8CString(string, "shiftKey") + || JSStringIsEqualToUTF8CString(string, "rangeSelectionKey")) + flags |= MK_SHIFT; + // No way to specifiy altKey in a MSG. + + JSStringRelease(string); + } + return flags; +} + static JSValueRef mouseDownCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { COMPtr<IWebFramePrivate> framePrivate; @@ -152,7 +176,7 @@ static JSValueRef mouseDownCallback(JSContextRef context, JSObjectRef function, down = true; int mouseType = WM_LBUTTONDOWN; - if (argumentCount == 1) { + if (argumentCount >= 1) { int mouseNumber = JSValueToNumber(context, arguments[0], exception); switch (mouseNumber) { case 0: @@ -173,8 +197,12 @@ static JSValueRef mouseDownCallback(JSContextRef context, JSObjectRef function, break; } } + + WPARAM wparam = 0; + if (argumentCount >= 2) + wparam |= buildModifierFlags(context, arguments[1]); - MSG msg = makeMsg(webViewWindow, mouseType, 0, MAKELPARAM(lastMousePosition.x, lastMousePosition.y)); + MSG msg = makeMsg(webViewWindow, mouseType, wparam, MAKELPARAM(lastMousePosition.x, lastMousePosition.y)); if (!msgQueue[endOfQueue].delay) dispatchMessage(&msg); else { @@ -234,7 +262,7 @@ static void doMouseUp(MSG msg, HRESULT* oleDragAndDropReturnValue = 0) static JSValueRef mouseUpCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { int mouseType = WM_LBUTTONUP; - if (argumentCount == 1) { + if (argumentCount >= 1) { int mouseNumber = JSValueToNumber(context, arguments[0], exception); switch (mouseNumber) { case 0: @@ -256,7 +284,11 @@ static JSValueRef mouseUpCallback(JSContextRef context, JSObjectRef function, JS } } - MSG msg = makeMsg(webViewWindow, mouseType, 0, MAKELPARAM(lastMousePosition.x, lastMousePosition.y)); + WPARAM wparam = 0; + if (argumentCount >= 2) + wparam |= buildModifierFlags(context, arguments[1]); + + MSG msg = makeMsg(webViewWindow, mouseType, wparam, MAKELPARAM(lastMousePosition.x, lastMousePosition.y)); if ((dragMode && !replayingSavedEvents) || msgQueue[endOfQueue].delay) { msgQueue[endOfQueue++].msg = msg; @@ -462,9 +494,9 @@ static JSValueRef keyDownCallback(JSContextRef context, JSObjectRef function, JS for (int i = 0; i < modifiersCount; ++i) { JSValueRef value = JSObjectGetPropertyAtIndex(context, modifiersArray, i, 0); JSStringRef string = JSValueToStringCopy(context, value, 0); - if (JSStringIsEqualToUTF8CString(string, "ctrlKey")) + if (JSStringIsEqualToUTF8CString(string, "ctrlKey") || JSStringIsEqualToUTF8CString(string, "addSelectionKey")) newKeyState[VK_CONTROL] = 0x80; - else if (JSStringIsEqualToUTF8CString(string, "shiftKey")) + else if (JSStringIsEqualToUTF8CString(string, "shiftKey") || JSStringIsEqualToUTF8CString(string, "rangeSelectionKey")) newKeyState[VK_SHIFT] = 0x80; else if (JSStringIsEqualToUTF8CString(string, "altKey")) newKeyState[VK_MENU] = 0x80; diff --git a/WebKitTools/DumpRenderTree/win/FrameLoadDelegate.h b/WebKitTools/DumpRenderTree/win/FrameLoadDelegate.h index cc6653b..329c17f 100644 --- a/WebKitTools/DumpRenderTree/win/FrameLoadDelegate.h +++ b/WebKitTools/DumpRenderTree/win/FrameLoadDelegate.h @@ -44,6 +44,8 @@ public: void resetToConsistentState(); + AccessibilityController* accessibilityController() const { return m_accessibilityController.get(); } + // IUnknown virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject); virtual ULONG STDMETHODCALLTYPE AddRef(void); diff --git a/WebKitTools/DumpRenderTree/win/ImageDiff.vcproj b/WebKitTools/DumpRenderTree/win/ImageDiff.vcproj index d9f5225..73d541b 100644 --- a/WebKitTools/DumpRenderTree/win/ImageDiff.vcproj +++ b/WebKitTools/DumpRenderTree/win/ImageDiff.vcproj @@ -38,7 +38,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\include\private";"$(WebKitOutputDir)\include\WebCore\ForwardingHeaders";"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\private";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility""
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\include\private";"$(WebKitOutputDir)\include\WebCore\ForwardingHeaders";"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\private""
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -106,7 +106,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\include\private";"$(WebKitOutputDir)\include\WebCore\ForwardingHeaders";"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\private";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility""
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\include\private";"$(WebKitOutputDir)\include\WebCore\ForwardingHeaders";"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\private""
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -173,7 +173,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\include\private";"$(WebKitOutputDir)\include\WebCore\ForwardingHeaders";"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\private";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility""
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\include\private";"$(WebKitOutputDir)\include\WebCore\ForwardingHeaders";"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\private""
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -240,7 +240,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\include\private";"$(WebKitOutputDir)\include\WebCore\ForwardingHeaders";"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\private";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders";"$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility""
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\include\private";"$(WebKitOutputDir)\include\WebCore\ForwardingHeaders";"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\private""
/>
<Tool
Name="VCManagedResourceCompilerTool"
diff --git a/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp b/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp index 5debf16..b7a63fc 100644 --- a/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp +++ b/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp @@ -806,6 +806,17 @@ void LayoutTestController::setDatabaseQuota(unsigned long long quota) databaseManager->setQuota(TEXT("file:///"), quota); } +void LayoutTestController::setDomainRelaxationForbiddenForURLScheme(bool forbidden, JSStringRef scheme) +{ + COMPtr<IWebViewPrivate> webView; + if (FAILED(WebKitCreateInstance(__uuidof(WebView), 0, __uuidof(webView), reinterpret_cast<void**>(&webView)))) + return; + + BSTR schemeBSTR = JSStringCopyBSTR(scheme); + webView->setDomainRelaxationForbiddenForURLScheme(forbidden, schemeBSTR); + SysFreeString(schemeBSTR); +} + void LayoutTestController::setAppCacheMaximumSize(unsigned long long size) { printf("ERROR: LayoutTestController::setAppCacheMaximumSize() not implemented\n"); diff --git a/WebKitTools/DumpRenderTree/win/ResourceLoadDelegate.cpp b/WebKitTools/DumpRenderTree/win/ResourceLoadDelegate.cpp index 0edf69b..19bf84a 100644 --- a/WebKitTools/DumpRenderTree/win/ResourceLoadDelegate.cpp +++ b/WebKitTools/DumpRenderTree/win/ResourceLoadDelegate.cpp @@ -243,6 +243,11 @@ HRESULT STDMETHODCALLTYPE ResourceLoadDelegate::willSendRequest( descriptionSuitableForTestResult(redirectResponse).c_str()); } + if (!done && gLayoutTestController->willSendRequestReturnsNull()) { + *newRequest = 0; + return S_OK; + } + if (!done && gLayoutTestController->willSendRequestReturnsNullOnRedirect() && redirectResponse) { printf("Returning null for this redirect\n"); *newRequest = 0; diff --git a/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/TestNetscapePlugin.vcproj b/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/TestNetscapePlugin.vcproj index b1f2073..0177d99 100644 --- a/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/TestNetscapePlugin.vcproj +++ b/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/TestNetscapePlugin.vcproj @@ -39,7 +39,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders";"$(ProjectDir)..\..\TestNetscapePlugin.subproj";"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\CoreFoundation\OSXCompatibilityHeaders";"$(WebKitLibrariesDir)\include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility""
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders";"$(ProjectDir)..\..\TestNetscapePlugin.subproj";"$(WebKitLibrariesDir)\include""
PreprocessorDefinitions="_USRDLL;TESTNETSCAPEPLUGIN_EXPORTS;snprintf=_snprintf"
DisableSpecificWarnings="4819"
/>
@@ -109,7 +109,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders";"$(ProjectDir)..\..\TestNetscapePlugin.subproj";"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\CoreFoundation\OSXCompatibilityHeaders";"$(WebKitLibrariesDir)\include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility""
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders";"$(ProjectDir)..\..\TestNetscapePlugin.subproj";"$(WebKitLibrariesDir)\include""
PreprocessorDefinitions="_USRDLL;TESTNETSCAPEPLUGIN_EXPORTS;snprintf=_snprintf"
DisableSpecificWarnings="4819"
/>
@@ -178,7 +178,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders";"$(ProjectDir)..\..\TestNetscapePlugin.subproj";"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\CoreFoundation\OSXCompatibilityHeaders";"$(WebKitLibrariesDir)\include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility""
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders";"$(ProjectDir)..\..\TestNetscapePlugin.subproj";"$(WebKitLibrariesDir)\include""
PreprocessorDefinitions="_USRDLL;TESTNETSCAPEPLUGIN_EXPORTS;snprintf=_snprintf"
RuntimeLibrary="3"
DisableSpecificWarnings="4819"
@@ -248,7 +248,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders";"$(ProjectDir)..\..\TestNetscapePlugin.subproj";"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\CoreFoundation\OSXCompatibilityHeaders";"$(WebKitLibrariesDir)\include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility""
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders";"$(ProjectDir)..\..\TestNetscapePlugin.subproj";"$(WebKitLibrariesDir)\include""
PreprocessorDefinitions="_USRDLL;TESTNETSCAPEPLUGIN_EXPORTS;snprintf=_snprintf"
DisableSpecificWarnings="4819"
/>
@@ -317,7 +317,7 @@ />
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders";"$(ProjectDir)..\..\TestNetscapePlugin.subproj";"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\CoreFoundation\OSXCompatibilityHeaders";"$(WebKitLibrariesDir)\include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility""
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\Include";"$(WebKitOutputDir)\Include\JavaScriptCore";"$(WebKitOutputDir)\Include\WebCore\ForwardingHeaders";"$(ProjectDir)..\..\TestNetscapePlugin.subproj";"$(WebKitLibrariesDir)\include""
PreprocessorDefinitions="_USRDLL;TESTNETSCAPEPLUGIN_EXPORTS;snprintf=_snprintf"
RuntimeLibrary="3"
DisableSpecificWarnings="4819"
diff --git a/WebKitTools/DumpRenderTree/wscript b/WebKitTools/DumpRenderTree/wscript index 29eca9a..5e6c597 100644 --- a/WebKitTools/DumpRenderTree/wscript +++ b/WebKitTools/DumpRenderTree/wscript @@ -57,7 +57,7 @@ def build(bld): includes = ' '.join(include_paths), source = sources, target = 'DumpRenderTree', - uselib = 'WXWEBKIT WX ' + get_config(), + uselib = 'JSCORE ICU WXWEBKIT WX ' + get_config(), libpath = [output_dir], uselib_local = '', install_path = output_dir) diff --git a/WebKitTools/DumpRenderTree/wx/DumpRenderTree.bkl b/WebKitTools/DumpRenderTree/wx/DumpRenderTree.bkl index 22fe1f9..e69de29 100644 --- a/WebKitTools/DumpRenderTree/wx/DumpRenderTree.bkl +++ b/WebKitTools/DumpRenderTree/wx/DumpRenderTree.bkl @@ -1,69 +0,0 @@ -<?xml version="1.0" ?> -<!-- -Copyright (C) 2008 Kevin Ollivier <kevino@theolliviers.com> - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - its contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -wxWebKit sample application build file ---> - -<makefile> - <set var="WX_UNICODE">1</set> - <set var="WX_SHARED">1</set> - - <include file="../../../WebKit/wx/wxwk-settings.bkl"/> - - <!-- the WX_PYTHON option was added to presets/wx.bkl in 2.8.5, so define - it in case the presets/wx.bkl doesn't define it for us. --> - <if cond="not isdefined('WX_PYTHON')"> - <set var="WX_PYTHON">0</set> - </if> - <template id="wxwebkit"> - <lib-path>$(WKOUTPUTDIR)</lib-path> - <sys-lib>wxwebkit</sys-lib> - </template> - <exe id="DumpRenderTree" template="wxwk,xml2,iconv,xslt,icu,jscore,webcore,wxwebkit,curl,pthreads"> - <app-type>gui</app-type> - <runtime-libs>dynamic</runtime-libs> - - <include>$(WK_ROOT)/WebCore/platform/wx</include> - <include>$(WK_ROOT)/WebCore/bridge/wx</include> - <include>$(WK_ROOT)/WebCore/page/wx</include> - <include>$(WK_ROOT)/WebKit/wx</include> - <include>$(WK_ROOT)/WebKit/wx/WebKitSupport</include> - <include>$(WK_ROOT)/WebKitTools/DumpRenderTree</include> - <include>$(WK_ROOT)/WebKitTools/DumpRenderTree/wx</include> - <include>$(WK_ROOT)/WebKitBuild/Debug</include> - <sources> - DumpRenderTreeWx.cpp - LayoutTestControllerWx.cpp - WorkQueueItemWx.cpp - ../LayoutTestController.cpp - ../WorkQueue.cpp - </sources> - - </exe> - -</makefile> diff --git a/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp b/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp index 2c46950..4b811ec 100644 --- a/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp +++ b/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp @@ -216,6 +216,11 @@ void LayoutTestController::setDatabaseQuota(unsigned long long quota) // FIXME: implement } +void LayoutTestController::setDomainRelaxationForbiddenForURLScheme(bool, JSStringRef) +{ + // FIXME: implement +} + void LayoutTestController::setAppCacheMaximumSize(unsigned long long size) { // FIXME: implement @@ -352,5 +357,5 @@ void LayoutTestController::whiteListAccessFromOrigin(JSStringRef sourceOrigin, J JSRetainPtr<JSStringRef> LayoutTestController::counterValueForElementById(JSStringRef id) { - + return 0; } |