diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Tools/DumpRenderTree | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Tools/DumpRenderTree')
66 files changed, 2534 insertions, 7108 deletions
diff --git a/Tools/DumpRenderTree/AccessibilityController.cpp b/Tools/DumpRenderTree/AccessibilityController.cpp index dd9996be8..d035dea99 100644 --- a/Tools/DumpRenderTree/AccessibilityController.cpp +++ b/Tools/DumpRenderTree/AccessibilityController.cpp @@ -130,6 +130,20 @@ static JSValueRef removeNotificationListenerCallback(JSContextRef context, JSObj return JSValueMakeUndefined(context); } +static JSValueRef enableEnhancedAccessibilityCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + AccessibilityController* controller = static_cast<AccessibilityController*>(JSObjectGetPrivate(thisObject)); + if (argumentCount == 1) + controller->enableEnhancedAccessibility(JSValueToBoolean(context, arguments[0])); + return JSValueMakeUndefined(context); +} + +static JSValueRef getEnhancedAccessibilityEnabledCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) +{ + AccessibilityController* controller = static_cast<AccessibilityController*>(JSObjectGetPrivate(thisObject)); + return JSValueMakeBoolean(context, controller->enhancedAccessibilityEnabled()); +} + static JSValueRef getPlatformNameCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) { AccessibilityController* controller = static_cast<AccessibilityController*>(JSObjectGetPrivate(thisObject)); @@ -150,12 +164,14 @@ JSClassRef AccessibilityController::getJSClass() { "accessibleElementById", getAccessibleElementByIdCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "addNotificationListener", addNotificationListenerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "removeNotificationListener", removeNotificationListenerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "enableEnhancedAccessibility", enableEnhancedAccessibilityCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { 0, 0, 0 } }; static JSStaticValue staticValues[] = { { "focusedElement", getFocusedElementCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "rootElement", getRootElementCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "enhancedAccessibilityEnabled", getEnhancedAccessibilityEnabledCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "platformName", getPlatformNameCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { 0, 0, 0, 0 } }; diff --git a/Tools/DumpRenderTree/AccessibilityController.h b/Tools/DumpRenderTree/AccessibilityController.h index 2f4f6ae9e..9f66dd6ee 100644 --- a/Tools/DumpRenderTree/AccessibilityController.h +++ b/Tools/DumpRenderTree/AccessibilityController.h @@ -64,6 +64,10 @@ public: bool addNotificationListener(JSObjectRef functionCallback); void removeNotificationListener(); + // Enhanced accessibility. + void enableEnhancedAccessibility(bool); + bool enhancedAccessibilityEnabled(); + JSRetainPtr<JSStringRef> platformName() const; #if PLATFORM(WIN) @@ -89,7 +93,7 @@ private: HashMap<PlatformUIElement, JSObjectRef> m_notificationListeners; #endif -#if PLATFORM(MAC) +#if PLATFORM(COCOA) || PLATFORM(IOS) RetainPtr<NotificationHandler> m_globalNotificationHandler; #endif diff --git a/Tools/DumpRenderTree/AccessibilityTextMarker.h b/Tools/DumpRenderTree/AccessibilityTextMarker.h index b890e28a9..7809ea459 100644 --- a/Tools/DumpRenderTree/AccessibilityTextMarker.h +++ b/Tools/DumpRenderTree/AccessibilityTextMarker.h @@ -28,13 +28,13 @@ #include <JavaScriptCore/JSObjectRef.h> -#if PLATFORM(MAC) && !PLATFORM(IOS) +#if PLATFORM(MAC) || PLATFORM(IOS) #define SUPPORTS_AX_TEXTMARKERS 1 #else #define SUPPORTS_AX_TEXTMARKERS 0 #endif -#if PLATFORM(MAC) +#if PLATFORM(COCOA) #include <wtf/RetainPtr.h> typedef CFTypeRef PlatformTextMarker; typedef CFTypeRef PlatformTextMarkerRange; @@ -58,7 +58,7 @@ public: private: static JSClassRef getJSClass(); -#if SUPPORTS_AX_TEXTMARKERS +#if SUPPORTS_AX_TEXTMARKERS && PLATFORM(MAC) RetainPtr<PlatformTextMarker> m_textMarker; #else PlatformTextMarker m_textMarker; @@ -78,7 +78,7 @@ public: private: static JSClassRef getJSClass(); -#if SUPPORTS_AX_TEXTMARKERS +#if SUPPORTS_AX_TEXTMARKERS && PLATFORM(MAC) RetainPtr<PlatformTextMarkerRange> m_textMarkerRange; #else PlatformTextMarkerRange m_textMarkerRange; diff --git a/Tools/DumpRenderTree/AccessibilityUIElement.cpp b/Tools/DumpRenderTree/AccessibilityUIElement.cpp index 793b3103d..1d77d7717 100644 --- a/Tools/DumpRenderTree/AccessibilityUIElement.cpp +++ b/Tools/DumpRenderTree/AccessibilityUIElement.cpp @@ -209,7 +209,8 @@ static JSValueRef uiElementCountForSearchPredicateCallback(JSContextRef context, JSValueRef searchKey = nullptr; JSRetainPtr<JSStringRef> searchText = nullptr; bool visibleOnly = false; - if (argumentCount == 5) { + bool immediateDescendantsOnly = false; + if (argumentCount >= 5 && argumentCount <= 6) { if (JSValueIsObject(context, arguments[0])) startElement = toAXElement(JSValueToObject(context, arguments[0], exception)); @@ -221,9 +222,12 @@ static JSValueRef uiElementCountForSearchPredicateCallback(JSContextRef context, searchText.adopt(JSValueToStringCopy(context, arguments[3], exception)); visibleOnly = JSValueToBoolean(context, arguments[4]); + + if (argumentCount == 6) + immediateDescendantsOnly = JSValueToBoolean(context, arguments[5]); } - return JSValueMakeNumber(context, toAXElement(thisObject)->uiElementCountForSearchPredicate(context, startElement, isDirectionNext, searchKey, searchText.get(), visibleOnly)); + return JSValueMakeNumber(context, toAXElement(thisObject)->uiElementCountForSearchPredicate(context, startElement, isDirectionNext, searchKey, searchText.get(), visibleOnly, immediateDescendantsOnly)); } static JSValueRef uiElementForSearchPredicateCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) @@ -233,7 +237,8 @@ static JSValueRef uiElementForSearchPredicateCallback(JSContextRef context, JSOb JSValueRef searchKey = nullptr; JSRetainPtr<JSStringRef> searchText = nullptr; bool visibleOnly = false; - if (argumentCount == 5) { + bool immediateDescendantsOnly = false; + if (argumentCount >= 5 && argumentCount <= 6) { if (JSValueIsObject(context, arguments[0])) startElement = toAXElement(JSValueToObject(context, arguments[0], exception)); @@ -245,9 +250,34 @@ static JSValueRef uiElementForSearchPredicateCallback(JSContextRef context, JSOb searchText.adopt(JSValueToStringCopy(context, arguments[3], exception)); visibleOnly = JSValueToBoolean(context, arguments[4]); + + if (argumentCount == 6) + immediateDescendantsOnly = JSValueToBoolean(context, arguments[5]); } - return AccessibilityUIElement::makeJSAccessibilityUIElement(context, toAXElement(thisObject)->uiElementForSearchPredicate(context, startElement, isDirectionNext, searchKey, searchText.get(), visibleOnly)); + return AccessibilityUIElement::makeJSAccessibilityUIElement(context, toAXElement(thisObject)->uiElementForSearchPredicate(context, startElement, isDirectionNext, searchKey, searchText.get(), visibleOnly, immediateDescendantsOnly)); +} + +static JSValueRef selectTextWithCriteriaCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + if (argumentCount < 2 || argumentCount > 4) + return JSValueMakeUndefined(context); + + JSRetainPtr<JSStringRef> ambiguityResolution(Adopt, JSValueToStringCopy(context, arguments[0], exception)); + JSValueRef searchStrings = arguments[1]; + JSStringRef replacementString = nullptr; + if (argumentCount == 3) + replacementString = JSValueToStringCopy(context, arguments[2], exception); + JSStringRef activityString = nullptr; + if (argumentCount == 4) + activityString = JSValueToStringCopy(context, arguments[3], exception); + + JSRetainPtr<JSStringRef> result(Adopt, toAXElement(thisObject)->selectTextWithCriteria(context, ambiguityResolution.get(), searchStrings, replacementString, activityString)); + if (replacementString) + JSStringRelease(replacementString); + if (activityString) + JSStringRelease(activityString); + return JSValueMakeString(context, result.get()); } static JSValueRef indexOfChildCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) @@ -287,12 +317,13 @@ static JSValueRef elementsForRangeCallback(JSContextRef context, JSObjectRef fun Vector<AccessibilityUIElement> elements; toAXElement(thisObject)->elementsForRange(location, length, elements); + JSValueRef arrayResult = JSObjectMakeArray(context, 0, 0, 0); + JSObjectRef arrayObj = JSValueToObject(context, arrayResult, 0); unsigned elementsSize = elements.size(); - JSValueRef valueElements[elementsSize]; for (unsigned k = 0; k < elementsSize; ++k) - valueElements[k] = AccessibilityUIElement::makeJSAccessibilityUIElement(context, elements[k]); + JSObjectSetPropertyAtIndex(context, arrayObj, k, AccessibilityUIElement::makeJSAccessibilityUIElement(context, elements[k]), 0); - return JSObjectMakeArray(context, elementsSize, valueElements, 0); + return arrayResult; } static JSValueRef increaseTextSelectionCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) @@ -301,6 +332,26 @@ static JSValueRef increaseTextSelectionCallback(JSContextRef context, JSObjectRe return JSValueMakeUndefined(context); } +static JSValueRef scrollPageUpCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + return JSValueMakeBoolean(context, toAXElement(thisObject)->scrollPageUp()); +} + +static JSValueRef scrollPageDownCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + return JSValueMakeBoolean(context, toAXElement(thisObject)->scrollPageDown()); +} + +static JSValueRef scrollPageLeftCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + return JSValueMakeBoolean(context, toAXElement(thisObject)->scrollPageLeft()); +} + +static JSValueRef scrollPageRightCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + return JSValueMakeBoolean(context, toAXElement(thisObject)->scrollPageRight()); +} + static JSValueRef decreaseTextSelectionCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { toAXElement(thisObject)->decreaseTextSelection(); @@ -313,6 +364,11 @@ static JSValueRef assistiveTechnologySimulatedFocusCallback(JSContextRef context return JSValueMakeUndefined(context); } +static JSValueRef fieldsetAncestorElementCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + return AccessibilityUIElement::makeJSAccessibilityUIElement(context, toAXElement(thisObject)->fieldsetAncestorElement()); +} + #endif static JSValueRef childAtIndexCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) @@ -369,6 +425,15 @@ static JSValueRef ariaFlowToElementAtIndexCallback(JSContextRef context, JSObjec return AccessibilityUIElement::makeJSAccessibilityUIElement(context, toAXElement(thisObject)->ariaFlowToElementAtIndex(indexNumber)); } +static JSValueRef ariaControlsElementAtIndexCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + int indexNumber = 0; + if (argumentCount == 1) + indexNumber = JSValueToNumber(context, arguments[0], exception); + + return AccessibilityUIElement::makeJSAccessibilityUIElement(context, toAXElement(thisObject)->ariaControlsElementAtIndex(indexNumber)); +} + static JSValueRef selectedRowAtIndexCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { int indexNumber = 0; @@ -398,6 +463,19 @@ static JSValueRef isEqualCallback(JSContextRef context, JSObjectRef function, JS return JSValueMakeBoolean(context, toAXElement(thisObject)->isEqual(toAXElement(otherElement))); } +static JSValueRef setValueCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + JSRetainPtr<JSStringRef> valueText = 0; + if (argumentCount == 1) { + if (JSValueIsString(context, arguments[0])) + valueText.adopt(JSValueToStringCopy(context, arguments[0], exception)); + } + + toAXElement(thisObject)->setValue(valueText.get()); + + return JSValueMakeUndefined(context); +} + static JSValueRef setSelectedChildCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { JSObjectRef element = 0; @@ -409,6 +487,24 @@ static JSValueRef setSelectedChildCallback(JSContextRef context, JSObjectRef fun return JSValueMakeUndefined(context); } +static JSValueRef setSelectedChildAtIndexCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + if (argumentCount == 1) { + unsigned indexNumber = JSValueToNumber(context, arguments[0], exception); + toAXElement(thisObject)->setSelectedChildAtIndex(indexNumber); + } + return JSValueMakeUndefined(context); +} + +static JSValueRef removeSelectionAtIndexCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + if (argumentCount == 1) { + unsigned indexNumber = JSValueToNumber(context, arguments[0], exception); + toAXElement(thisObject)->removeSelectionAtIndex(indexNumber); + } + return JSValueMakeUndefined(context); +} + static JSValueRef elementAtPointCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { int x = 0; @@ -470,6 +566,20 @@ static JSValueRef boolAttributeValueCallback(JSContextRef context, JSObjectRef f return result; } +static JSValueRef setBoolAttributeValueCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + JSStringRef attribute = nullptr; + bool value = false; + if (argumentCount == 2) { + attribute = JSValueToStringCopy(context, arguments[0], exception); + value = JSValueToBoolean(context, arguments[1]); + } + toAXElement(thisObject)->setBoolAttributeValue(attribute, value); + if (attribute) + JSStringRelease(attribute); + return JSValueMakeUndefined(context); +} + static JSValueRef stringAttributeValueCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { JSStringRef attribute = 0; @@ -484,12 +594,14 @@ static JSValueRef stringAttributeValueCallback(JSContextRef context, JSObjectRef static JSValueRef convertElementsToObjectArray(JSContextRef context, Vector<AccessibilityUIElement>& elements, JSValueRef* exception) { + JSValueRef arrayResult = JSObjectMakeArray(context, 0, 0, 0); + JSObjectRef arrayObj = JSValueToObject(context, arrayResult, 0); + size_t elementCount = elements.size(); - auto valueElements = std::make_unique<JSValueRef[]>(elementCount); for (size_t i = 0; i < elementCount; ++i) - valueElements[i] = AccessibilityUIElement::makeJSAccessibilityUIElement(context, elements[i]); - - return JSObjectMakeArray(context, elementCount, valueElements.get(), exception); + JSObjectSetPropertyAtIndex(context, arrayObj, i, AccessibilityUIElement::makeJSAccessibilityUIElement(context, elements[i]), 0); + + return arrayResult; } static JSValueRef columnHeadersCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) @@ -601,6 +713,36 @@ static JSValueRef pressCallback(JSContextRef context, JSObjectRef function, JSOb return JSValueMakeUndefined(context); } +static JSValueRef scrollToMakeVisibleWithSubFocusCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + unsigned x = 0; + unsigned y = 0; + unsigned width = 0; + unsigned height = 0; + if (argumentCount == 4) { + x = JSValueToNumber(context, arguments[0], exception); + y = JSValueToNumber(context, arguments[1], exception); + width = JSValueToNumber(context, arguments[2], exception); + height = JSValueToNumber(context, arguments[3], exception); + } + + toAXElement(thisObject)->scrollToMakeVisibleWithSubFocus(x, y, width, height); + return JSValueMakeUndefined(context); +} + +static JSValueRef scrollToGlobalPointCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + unsigned x = 0; + unsigned y = 0; + if (argumentCount == 2) { + x = JSValueToNumber(context, arguments[0], exception); + y = JSValueToNumber(context, arguments[1], exception); + } + + toAXElement(thisObject)->scrollToGlobalPoint(x, y); + return JSValueMakeUndefined(context); +} + static JSValueRef scrollToMakeVisibleCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { toAXElement(thisObject)->scrollToMakeVisible(); @@ -631,6 +773,14 @@ static JSValueRef removeSelectionCallback(JSContextRef context, JSObjectRef func return JSValueMakeUndefined(context); } +static JSValueRef lineTextMarkerRangeForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + AccessibilityTextMarker* textMarker = nullptr; + if (argumentCount == 1) + textMarker = toTextMarker(JSValueToObject(context, arguments[0], exception)); + return AccessibilityTextMarkerRange::makeJSAccessibilityTextMarkerRange(context, toAXElement(thisObject)->lineTextMarkerRangeForTextMarker(textMarker)); +} + static JSValueRef textMarkerRangeForElementCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { AccessibilityUIElement* uiElement = 0; @@ -640,6 +790,17 @@ static JSValueRef textMarkerRangeForElementCallback(JSContextRef context, JSObje return AccessibilityTextMarkerRange::makeJSAccessibilityTextMarkerRange(context, toAXElement(thisObject)->textMarkerRangeForElement(uiElement)); } +static JSValueRef selectedTextMarkerRangeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + return AccessibilityTextMarkerRange::makeJSAccessibilityTextMarkerRange(context, toAXElement(thisObject)->selectedTextMarkerRange()); +} + +static JSValueRef resetSelectedTextMarkerRangeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + toAXElement(thisObject)->resetSelectedTextMarkerRange(); + return JSValueMakeUndefined(context); +} + static JSValueRef attributedStringForTextMarkerRangeContainsAttributeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { AccessibilityTextMarkerRange* markerRange = 0; @@ -813,6 +974,109 @@ static JSValueRef endTextMarkerCallback(JSContextRef context, JSObjectRef thisOb return AccessibilityTextMarker::makeJSAccessibilityTextMarker(context, toAXElement(thisObject)->endTextMarker()); } +static JSValueRef leftWordTextMarkerRangeForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + AccessibilityTextMarker* marker = nullptr; + if (argumentCount == 1) + marker = toTextMarker(JSValueToObject(context, arguments[0], exception)); + + return AccessibilityTextMarkerRange::makeJSAccessibilityTextMarkerRange(context, toAXElement(thisObject)->leftWordTextMarkerRangeForTextMarker(marker)); +} + +static JSValueRef rightWordTextMarkerRangeForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + AccessibilityTextMarker* marker = nullptr; + if (argumentCount == 1) + marker = toTextMarker(JSValueToObject(context, arguments[0], exception)); + + return AccessibilityTextMarkerRange::makeJSAccessibilityTextMarkerRange(context, toAXElement(thisObject)->rightWordTextMarkerRangeForTextMarker(marker)); +} + +static JSValueRef previousWordStartTextMarkerForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + AccessibilityTextMarker* marker = nullptr; + if (argumentCount == 1) + marker = toTextMarker(JSValueToObject(context, arguments[0], exception)); + + return AccessibilityTextMarker::makeJSAccessibilityTextMarker(context, toAXElement(thisObject)->previousWordStartTextMarkerForTextMarker(marker)); +} + +static JSValueRef nextWordEndTextMarkerForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + AccessibilityTextMarker* marker = nullptr; + if (argumentCount == 1) + marker = toTextMarker(JSValueToObject(context, arguments[0], exception)); + + return AccessibilityTextMarker::makeJSAccessibilityTextMarker(context, toAXElement(thisObject)->nextWordEndTextMarkerForTextMarker(marker)); +} + +static JSValueRef paragraphTextMarkerRangeForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + AccessibilityTextMarker* marker = nullptr; + if (argumentCount == 1) + marker = toTextMarker(JSValueToObject(context, arguments[0], exception)); + + return AccessibilityTextMarkerRange::makeJSAccessibilityTextMarkerRange(context, toAXElement(thisObject)->paragraphTextMarkerRangeForTextMarker(marker)); +} + +static JSValueRef previousParagraphStartTextMarkerForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + AccessibilityTextMarker* marker = nullptr; + if (argumentCount == 1) + marker = toTextMarker(JSValueToObject(context, arguments[0], exception)); + + return AccessibilityTextMarker::makeJSAccessibilityTextMarker(context, toAXElement(thisObject)->previousParagraphStartTextMarkerForTextMarker(marker)); +} + +static JSValueRef nextParagraphEndTextMarkerForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + AccessibilityTextMarker* marker = nullptr; + if (argumentCount == 1) + marker = toTextMarker(JSValueToObject(context, arguments[0], exception)); + + return AccessibilityTextMarker::makeJSAccessibilityTextMarker(context, toAXElement(thisObject)->nextParagraphEndTextMarkerForTextMarker(marker)); +} + +static JSValueRef sentenceTextMarkerRangeForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + AccessibilityTextMarker* marker = nullptr; + if (argumentCount == 1) + marker = toTextMarker(JSValueToObject(context, arguments[0], exception)); + + return AccessibilityTextMarkerRange::makeJSAccessibilityTextMarkerRange(context, toAXElement(thisObject)->sentenceTextMarkerRangeForTextMarker(marker)); +} + +static JSValueRef previousSentenceStartTextMarkerForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + AccessibilityTextMarker* marker = nullptr; + if (argumentCount == 1) + marker = toTextMarker(JSValueToObject(context, arguments[0], exception)); + + return AccessibilityTextMarker::makeJSAccessibilityTextMarker(context, toAXElement(thisObject)->previousSentenceStartTextMarkerForTextMarker(marker)); +} + +static JSValueRef nextSentenceEndTextMarkerForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + AccessibilityTextMarker* marker = nullptr; + if (argumentCount == 1) + marker = toTextMarker(JSValueToObject(context, arguments[0], exception)); + + return AccessibilityTextMarker::makeJSAccessibilityTextMarker(context, toAXElement(thisObject)->nextSentenceEndTextMarkerForTextMarker(marker)); +} + +static JSValueRef setSelectedVisibleTextRangeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + AccessibilityUIElement* uiElement = toAXElement(thisObject); + AccessibilityTextMarkerRange* textMarkerRange = nullptr; + if (argumentCount == 1) + textMarkerRange = toTextMarkerRange(JSValueToObject(context, arguments[0], exception)); + + if (uiElement) + return JSValueMakeBoolean(context, uiElement->setSelectedVisibleTextRange(textMarkerRange)); + + return JSValueMakeBoolean(context, false); +} + // Static Value Getters static JSValueRef getARIADropEffectsCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) @@ -861,6 +1125,12 @@ static JSValueRef getRoleDescriptionCallback(JSContextRef context, JSObjectRef t return JSValueMakeString(context, roleDesc.get()); } +static JSValueRef getComputedRoleStringCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) +{ + JSRetainPtr<JSStringRef> compRole(Adopt, toAXElement(thisObject)->computedRoleString()); + return JSValueMakeString(context, compRole.get()); +} + static JSValueRef getTitleCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) { JSRetainPtr<JSStringRef> title(Adopt, toAXElement(thisObject)->title()); @@ -1169,56 +1439,48 @@ static JSValueRef sentenceAtOffsetCallback(JSContextRef context, JSObjectRef fun #elif PLATFORM(IOS) -static JSValueRef stringForSelectionCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) +static JSValueRef getIsSearchFieldCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) { - JSRetainPtr<JSStringRef> labelString(Adopt, toAXElement(thisObject)->stringForSelection()); - return JSValueMakeString(context, labelString.get()); -} - -static JSValueRef getIPhoneLabelCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) -{ - JSRetainPtr<JSStringRef> labelString(Adopt, toAXElement(thisObject)->iphoneLabel()); - return JSValueMakeString(context, labelString.get()); + return JSValueMakeBoolean(context, toAXElement(thisObject)->isSearchField()); } -static JSValueRef getIPhoneHintCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) +static JSValueRef getIsTextAreaCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) { - JSRetainPtr<JSStringRef> hintString(Adopt, toAXElement(thisObject)->iphoneHint()); - return JSValueMakeString(context, hintString.get()); + return JSValueMakeBoolean(context, toAXElement(thisObject)->isTextArea()); } -static JSValueRef getIPhoneValueCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) +static JSValueRef stringForSelectionCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) { - JSRetainPtr<JSStringRef> valueString(Adopt, toAXElement(thisObject)->iphoneValue()); - return JSValueMakeString(context, valueString.get()); + JSRetainPtr<JSStringRef> labelString(Adopt, toAXElement(thisObject)->stringForSelection()); + return JSValueMakeString(context, labelString.get()); } -static JSValueRef getIPhoneIdentifierCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) +static JSValueRef getIdentifierCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) { - JSRetainPtr<JSStringRef> valueString(Adopt, toAXElement(thisObject)->iphoneIdentifier()); + JSRetainPtr<JSStringRef> valueString(Adopt, toAXElement(thisObject)->identifier()); return JSValueMakeString(context, valueString.get()); } -static JSValueRef getIPhoneTraitsCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) +static JSValueRef getTraitsCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) { - JSRetainPtr<JSStringRef> valueString(Adopt, toAXElement(thisObject)->iphoneTraits()); + JSRetainPtr<JSStringRef> valueString(Adopt, toAXElement(thisObject)->traits()); return JSValueMakeString(context, valueString.get()); } -static JSValueRef getIPhoneIsElementCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) +static JSValueRef getElementTextPositionCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) { - return JSValueMakeBoolean(context, toAXElement(thisObject)->iphoneIsElement()); + return JSValueMakeNumber(context, toAXElement(thisObject)->elementTextPosition()); } -static JSValueRef getIPhoneElementTextPositionCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) +static JSValueRef getElementTextLengthCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) { - return JSValueMakeNumber(context, toAXElement(thisObject)->iphoneElementTextPosition()); + return JSValueMakeNumber(context, toAXElement(thisObject)->elementTextLength()); } -static JSValueRef getIPhoneElementTextLengthCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) +static JSValueRef hasContainedByFieldsetTraitCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef, JSValueRef*) { - return JSValueMakeNumber(context, toAXElement(thisObject)->iphoneElementTextLength()); + return JSValueMakeBoolean(context, toAXElement(thisObject)->hasContainedByFieldsetTrait()); } #endif // PLATFORM(IOS) @@ -1252,8 +1514,8 @@ JSStringRef AccessibilityUIElement::speak() { return 0; } JSStringRef AccessibilityUIElement::rangeForLine(int line) { return 0; } JSStringRef AccessibilityUIElement::rangeForPosition(int, int) { return 0; } void AccessibilityUIElement::setSelectedChild(AccessibilityUIElement*) const { } -unsigned AccessibilityUIElement::selectedChildrenCount() const { return 0; } -AccessibilityUIElement AccessibilityUIElement::selectedChildAtIndex(unsigned) const { return 0; } +void AccessibilityUIElement::setSelectedChildAtIndex(unsigned) const { } +void AccessibilityUIElement::removeSelectionAtIndex(unsigned) const { } AccessibilityUIElement AccessibilityUIElement::horizontalScrollbar() const { return 0; } AccessibilityUIElement AccessibilityUIElement::verticalScrollbar() const { return 0; } AccessibilityUIElement AccessibilityUIElement::uiElementAttributeValue(JSStringRef) const { return 0; } @@ -1261,12 +1523,11 @@ AccessibilityUIElement AccessibilityUIElement::uiElementAttributeValue(JSStringR #if !PLATFORM(MAC) && !PLATFORM(IOS) JSStringRef AccessibilityUIElement::pathDescription() const { return 0; } +void AccessibilityUIElement::setValue(JSStringRef) { } #endif -#if !PLATFORM(MAC) +#if !PLATFORM(COCOA) void AccessibilityUIElement::uiElementArrayAttributeValue(JSStringRef, Vector<AccessibilityUIElement>&) const { } -void AccessibilityUIElement::columnHeaders(Vector<AccessibilityUIElement>&) const { } -void AccessibilityUIElement::rowHeaders(Vector<AccessibilityUIElement>&) const { } #endif #if !PLATFORM(WIN) @@ -1278,13 +1539,31 @@ bool AccessibilityUIElement::isEqual(AccessibilityUIElement* otherElement) } #endif +#if !PLATFORM(MAC) +void AccessibilityUIElement::setBoolAttributeValue(JSStringRef, bool) { } +#endif + #if !SUPPORTS_AX_TEXTMARKERS +AccessibilityTextMarkerRange AccessibilityUIElement::lineTextMarkerRangeForTextMarker(AccessibilityTextMarker*) +{ + return nullptr; +} + AccessibilityTextMarkerRange AccessibilityUIElement::textMarkerRangeForElement(AccessibilityUIElement*) { return 0; } +AccessibilityTextMarkerRange AccessibilityUIElement::selectedTextMarkerRange() +{ + return nullptr; +} + +void AccessibilityUIElement::resetSelectedTextMarkerRange() +{ +} + int AccessibilityUIElement::textMarkerRangeLength(AccessibilityTextMarkerRange*) { return 0; @@ -1370,6 +1649,61 @@ AccessibilityTextMarker AccessibilityUIElement::endTextMarker() return nullptr; } +bool AccessibilityUIElement::setSelectedVisibleTextRange(AccessibilityTextMarkerRange*) +{ + return false; +} + +AccessibilityTextMarkerRange AccessibilityUIElement::leftWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*) +{ + return nullptr; +} + +AccessibilityTextMarkerRange AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*) +{ + return nullptr; +} + +AccessibilityTextMarker AccessibilityUIElement::previousWordStartTextMarkerForTextMarker(AccessibilityTextMarker*) +{ + return nullptr; +} + +AccessibilityTextMarker AccessibilityUIElement::nextWordEndTextMarkerForTextMarker(AccessibilityTextMarker*) +{ + return nullptr; +} + +AccessibilityTextMarkerRange AccessibilityUIElement::paragraphTextMarkerRangeForTextMarker(AccessibilityTextMarker*) +{ + return nullptr; +} + +AccessibilityTextMarker AccessibilityUIElement::previousParagraphStartTextMarkerForTextMarker(AccessibilityTextMarker*) +{ + return nullptr; +} + +AccessibilityTextMarker AccessibilityUIElement::nextParagraphEndTextMarkerForTextMarker(AccessibilityTextMarker*) +{ + return nullptr; +} + +AccessibilityTextMarkerRange AccessibilityUIElement::sentenceTextMarkerRangeForTextMarker(AccessibilityTextMarker*) +{ + return nullptr; +} + +AccessibilityTextMarker AccessibilityUIElement::previousSentenceStartTextMarkerForTextMarker(AccessibilityTextMarker*) +{ + return nullptr; +} + +AccessibilityTextMarker AccessibilityUIElement::nextSentenceEndTextMarkerForTextMarker(AccessibilityTextMarker*) +{ + return nullptr; +} + #endif // Destruction @@ -1396,6 +1730,7 @@ JSClassRef AccessibilityUIElement::getJSClass() { "role", getRoleCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "subrole", getSubroleCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "roleDescription", getRoleDescriptionCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "computedRoleString", getComputedRoleStringCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "title", getTitleCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "description", getDescriptionCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "language", getLanguageCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, @@ -1449,15 +1784,14 @@ JSClassRef AccessibilityUIElement::getJSClass() { "startTextMarker", startTextMarkerCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "endTextMarker", endTextMarkerCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, #if PLATFORM(IOS) - { "iphoneLabel", getIPhoneLabelCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "iphoneHint", getIPhoneHintCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "iphoneValue", getIPhoneValueCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "iphoneIdentifier", getIPhoneIdentifierCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "iphoneTraits", getIPhoneTraitsCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "iphoneIsElement", getIPhoneIsElementCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "iphoneElementTextPosition", getIPhoneElementTextPositionCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "iphoneElementTextLength", getIPhoneElementTextLengthCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "identifier", getIdentifierCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "traits", getTraitsCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "elementTextPosition", getElementTextPositionCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "elementTextLength", getElementTextLengthCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "stringForSelection", stringForSelectionCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "hasContainedByFieldsetTrait", hasContainedByFieldsetTraitCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "isSearchField", getIsSearchFieldCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "isTextArea", getIsTextAreaCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, #endif // PLATFORM(IOS) #if PLATFORM(MAC) && !PLATFORM(IOS) { "supportedActions", supportedActionsCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, @@ -1480,8 +1814,9 @@ JSClassRef AccessibilityUIElement::getJSClass() { "stringForRange", stringForRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "attributedStringForRange", attributedStringForRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "attributedStringRangeIsMisspelled", attributedStringRangeIsMisspelledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "uiElementCountForSearchPredicate", uiElementCountForSearchPredicateCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeReadOnly }, + { "uiElementCountForSearchPredicate", uiElementCountForSearchPredicateCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "uiElementForSearchPredicate", uiElementForSearchPredicateCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "selectTextWithCriteria", selectTextWithCriteriaCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "childAtIndex", childAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "linkedUIElementAtIndex", linkedUIElementAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "indexOfChild", indexOfChildCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, @@ -1505,6 +1840,7 @@ JSClassRef AccessibilityUIElement::getJSClass() { "uiElementAttributeValue", uiElementAttributeValueCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "numberAttributeValue", numberAttributeValueCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "boolAttributeValue", boolAttributeValueCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setBoolAttributeValue", setBoolAttributeValueCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "isAttributeSupported", isAttributeSupportedCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "isAttributeSettable", isAttributeSettableCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "isPressActionSupported", isPressActionSupportedCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, @@ -1519,6 +1855,7 @@ JSClassRef AccessibilityUIElement::getJSClass() { "disclosedRowAtIndex", disclosedRowAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "ariaOwnsElementAtIndex", ariaOwnsElementAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "ariaFlowToElementAtIndex", ariaFlowToElementAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "ariaControlsElementAtIndex", ariaControlsElementAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "selectedRowAtIndex", selectedRowAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "rowAtIndex", rowAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "isEqual", isEqualCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, @@ -1528,7 +1865,10 @@ JSClassRef AccessibilityUIElement::getJSClass() { "takeSelection", takeSelectionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "addSelection", addSelectionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "removeSelection", removeSelectionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "lineTextMarkerRangeForTextMarker", lineTextMarkerRangeForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "textMarkerRangeForElement", textMarkerRangeForElementCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "selectedTextMarkerRange", selectedTextMarkerRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "resetSelectedTextMarkerRange", resetSelectedTextMarkerRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "attributedStringForTextMarkerRangeContainsAttribute", attributedStringForTextMarkerRangeContainsAttributeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "indexForTextMarker", indexForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "isTextMarkerValid", isTextMarkerValidCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, @@ -1544,9 +1884,25 @@ JSClassRef AccessibilityUIElement::getJSClass() { "nextTextMarker", nextTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "previousTextMarker", previousTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "stringForTextMarkerRange", stringForTextMarkerRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "leftWordTextMarkerRangeForTextMarker", leftWordTextMarkerRangeForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "rightWordTextMarkerRangeForTextMarker", rightWordTextMarkerRangeForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "previousWordStartTextMarkerForTextMarker", previousWordStartTextMarkerForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "nextWordEndTextMarkerForTextMarker", nextWordEndTextMarkerForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "paragraphTextMarkerRangeForTextMarker", paragraphTextMarkerRangeForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "previousParagraphStartTextMarkerForTextMarker", previousParagraphStartTextMarkerForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "nextParagraphEndTextMarkerForTextMarker", nextParagraphEndTextMarkerForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "sentenceTextMarkerRangeForTextMarker", sentenceTextMarkerRangeForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "previousSentenceStartTextMarkerForTextMarker", previousSentenceStartTextMarkerForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "nextSentenceEndTextMarkerForTextMarker", nextSentenceEndTextMarkerForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setSelectedChild", setSelectedChildCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setSelectedChildAtIndex", setSelectedChildAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "removeSelectionAtIndex", removeSelectionAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setValue", setValueCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setSelectedVisibleTextRange", setSelectedVisibleTextRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "selectedChildAtIndex", selectedChildAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "scrollToMakeVisible", scrollToMakeVisibleCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "scrollToGlobalPoint", scrollToGlobalPointCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "scrollToMakeVisibleWithSubFocus", scrollToMakeVisibleWithSubFocusCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, #if PLATFORM(GTK) || PLATFORM(EFL) { "characterAtOffset", characterAtOffsetCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "wordAtOffset", wordAtOffsetCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, @@ -1558,8 +1914,12 @@ JSClassRef AccessibilityUIElement::getJSClass() { "elementsForRange", elementsForRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "increaseTextSelection", increaseTextSelectionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "decreaseTextSelection", decreaseTextSelectionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "scrollPageUp", scrollPageUpCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "scrollPageDown", scrollPageDownCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "scrollPageLeft", scrollPageLeftCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "scrollPageRight", scrollPageRightCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "assistiveTechnologySimulatedFocus", assistiveTechnologySimulatedFocusCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - + { "fieldsetAncestorElement", fieldsetAncestorElementCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, #endif { 0, 0, 0 } }; diff --git a/Tools/DumpRenderTree/AccessibilityUIElement.h b/Tools/DumpRenderTree/AccessibilityUIElement.h index f1f21b69b..349e40976 100644 --- a/Tools/DumpRenderTree/AccessibilityUIElement.h +++ b/Tools/DumpRenderTree/AccessibilityUIElement.h @@ -31,7 +31,7 @@ #include <wtf/Platform.h> #include <wtf/Vector.h> -#if PLATFORM(MAC) +#if PLATFORM(COCOA) #ifdef __OBJC__ typedef id PlatformUIElement; #else @@ -53,7 +53,7 @@ typedef AtkObject* PlatformUIElement; typedef void* PlatformUIElement; #endif -#if PLATFORM(MAC) +#if PLATFORM(COCOA) #ifdef __OBJC__ typedef id NotificationHandler; #else @@ -109,6 +109,7 @@ public: void uiElementArrayAttributeValue(JSStringRef attribute, Vector<AccessibilityUIElement>& elements) const; AccessibilityUIElement uiElementAttributeValue(JSStringRef attribute) const; bool boolAttributeValue(JSStringRef attribute); + void setBoolAttributeValue(JSStringRef attribute, bool value); bool isAttributeSupported(JSStringRef attribute); bool isAttributeSettable(JSStringRef attribute); bool isPressActionSupported(); @@ -117,11 +118,13 @@ public: JSStringRef role(); JSStringRef subrole(); JSStringRef roleDescription(); + JSStringRef computedRoleString(); JSStringRef title(); JSStringRef description(); JSStringRef language(); JSStringRef stringValue(); JSStringRef accessibilityValue() const; + void setValue(JSStringRef); JSStringRef helpText() const; JSStringRef orientation() const; double x(); @@ -147,6 +150,9 @@ public: void setSelectedChild(AccessibilityUIElement*) const; unsigned selectedChildrenCount() const; AccessibilityUIElement selectedChildAtIndex(unsigned) const; + void setSelectedChildAtIndex(unsigned) const; + void removeSelectionAtIndex(unsigned) const; + void clearSelectedChildren() const; bool isExpanded() const; bool isChecked() const; @@ -154,6 +160,8 @@ public: bool isOffScreen() const; bool isCollapsed() const; bool isIgnored() const; + bool isSingleLine() const; + bool isMultiLine() const; bool isIndeterminate() const; bool hasPopup() const; int hierarchicalLevel() const; @@ -191,6 +199,7 @@ public: // ARIA specific AccessibilityUIElement ariaOwnsElementAtIndex(unsigned); AccessibilityUIElement ariaFlowToElementAtIndex(unsigned); + AccessibilityUIElement ariaControlsElementAtIndex(unsigned); // ARIA Drag and Drop bool ariaIsGrabbed() const; @@ -206,14 +215,23 @@ public: JSStringRef stringForRange(unsigned location, unsigned length); JSStringRef attributedStringForRange(unsigned location, unsigned length); bool attributedStringRangeIsMisspelled(unsigned location, unsigned length); - unsigned uiElementCountForSearchPredicate(JSContextRef, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly); - AccessibilityUIElement uiElementForSearchPredicate(JSContextRef, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly); + unsigned uiElementCountForSearchPredicate(JSContextRef, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly, bool immediateDescendantsOnly); + AccessibilityUIElement uiElementForSearchPredicate(JSContextRef, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly, bool immediateDescendantsOnly); + JSStringRef selectTextWithCriteria(JSContextRef, JSStringRef ambiguityResolution, JSValueRef searchStrings, JSStringRef replacementString, JSStringRef activity); #if PLATFORM(IOS) void elementsForRange(unsigned location, unsigned length, Vector<AccessibilityUIElement>& elements); JSStringRef stringForSelection(); void increaseTextSelection(); void decreaseTextSelection(); AccessibilityUIElement linkedElement(); + + bool scrollPageUp(); + bool scrollPageDown(); + bool scrollPageLeft(); + bool scrollPageRight(); + + bool hasContainedByFieldsetTrait(); + AccessibilityUIElement fieldsetAncestorElement(); #endif #if PLATFORM(GTK) || PLATFORM(EFL) @@ -232,6 +250,7 @@ public: AccessibilityUIElement verticalScrollbar() const; // Text markers. + AccessibilityTextMarkerRange lineTextMarkerRangeForTextMarker(AccessibilityTextMarker*); AccessibilityTextMarkerRange textMarkerRangeForElement(AccessibilityUIElement*); AccessibilityTextMarkerRange textMarkerRangeForMarkers(AccessibilityTextMarker* startMarker, AccessibilityTextMarker* endMarker); AccessibilityTextMarker startTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange*); @@ -244,6 +263,19 @@ public: AccessibilityUIElement accessibilityElementForTextMarker(AccessibilityTextMarker*); AccessibilityTextMarker startTextMarker(); AccessibilityTextMarker endTextMarker(); + AccessibilityTextMarkerRange leftWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*); + AccessibilityTextMarkerRange rightWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*); + AccessibilityTextMarker previousWordStartTextMarkerForTextMarker(AccessibilityTextMarker*); + AccessibilityTextMarker nextWordEndTextMarkerForTextMarker(AccessibilityTextMarker*); + AccessibilityTextMarkerRange paragraphTextMarkerRangeForTextMarker(AccessibilityTextMarker*); + AccessibilityTextMarker previousParagraphStartTextMarkerForTextMarker(AccessibilityTextMarker*); + AccessibilityTextMarker nextParagraphEndTextMarkerForTextMarker(AccessibilityTextMarker*); + AccessibilityTextMarkerRange sentenceTextMarkerRangeForTextMarker(AccessibilityTextMarker*); + AccessibilityTextMarker previousSentenceStartTextMarkerForTextMarker(AccessibilityTextMarker*); + AccessibilityTextMarker nextSentenceEndTextMarkerForTextMarker(AccessibilityTextMarker*); + AccessibilityTextMarkerRange selectedTextMarkerRange(); + void resetSelectedTextMarkerRange(); + bool setSelectedVisibleTextRange(AccessibilityTextMarkerRange*); JSStringRef stringForTextMarkerRange(AccessibilityTextMarkerRange*); int textMarkerRangeLength(AccessibilityTextMarkerRange*); @@ -263,17 +295,17 @@ public: void removeNotificationListener(); #if PLATFORM(IOS) - JSStringRef iphoneLabel(); - JSStringRef iphoneValue(); - JSStringRef iphoneTraits(); - JSStringRef iphoneHint(); - JSStringRef iphoneIdentifier(); - bool iphoneIsElement(); - int iphoneElementTextPosition(); - int iphoneElementTextLength(); + JSStringRef traits(); + JSStringRef identifier(); + int elementTextPosition(); + int elementTextLength(); AccessibilityUIElement headerElementAtIndex(unsigned); // This will simulate the accessibilityDidBecomeFocused API in UIKit. void assistiveTechnologySimulatedFocus(); + + bool isTextArea() const; + bool isSearchField() const; + #endif // PLATFORM(IOS) #if PLATFORM(MAC) && !PLATFORM(IOS) @@ -289,9 +321,7 @@ private: static JSClassRef getJSClass(); PlatformUIElement m_element; -#if PLATFORM(IOS) - JSObjectRef m_notificationFunctionCallback; -#elif PLATFORM(MAC) +#if PLATFORM(COCOA) // A retained, platform specific object used to help manage notifications for this object. NotificationHandler m_notificationHandler; #endif diff --git a/Tools/DumpRenderTree/Bindings/CodeGeneratorDumpRenderTree.pm b/Tools/DumpRenderTree/Bindings/CodeGeneratorDumpRenderTree.pm new file mode 100644 index 000000000..d39d68a0f --- /dev/null +++ b/Tools/DumpRenderTree/Bindings/CodeGeneratorDumpRenderTree.pm @@ -0,0 +1,563 @@ +# Copyright (C) 2016 Apple Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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. + +use strict; +use warnings; +use File::Spec; + +package CodeGeneratorDumpRenderTree; + +sub new +{ + my ($class, $codeGenerator, $writeDependencies, $verbose, $idlFilePath) = @_; + + my $reference = { + codeGenerator => $codeGenerator, + idlFilePath => $idlFilePath, + }; + + bless($reference, $class); + return $reference; +} + +sub GenerateInterface +{ +} + +sub WriteData +{ + my ($self, $interface, $outputDir) = @_; + + foreach my $file ($self->_generateHeaderFile($interface), $self->_generateImplementationFile($interface)) { + $$self{codeGenerator}->UpdateFile(File::Spec->catfile($outputDir, $$file{name}), join("", @{$$file{contents}})); + } +} + +sub _className +{ + my ($type) = @_; + + return "JS" . _implementationClassName($type); +} + +sub _classRefGetter +{ + my ($self, $type) = @_; + + return $$self{codeGenerator}->WK_lcfirst(_implementationClassName($type)) . "Class"; +} + +sub _parseLicenseBlock +{ + my ($fileHandle) = @_; + + my ($copyright, $readCount, $buffer, $currentCharacter, $previousCharacter); + my $startSentinel = "/*"; + my $lengthOfStartSentinel = length($startSentinel); + $readCount = read($fileHandle, $buffer, $lengthOfStartSentinel); + return "" if ($readCount < $lengthOfStartSentinel || $buffer ne $startSentinel); + $copyright = $buffer; + + while ($readCount = read($fileHandle, $currentCharacter, 1)) { + $copyright .= $currentCharacter; + return $copyright if $currentCharacter eq "/" && $previousCharacter eq "*"; + $previousCharacter = $currentCharacter; + } + + return ""; +} + +sub _parseLicenseBlockFromFile +{ + my ($path) = @_; + open my $fileHandle, "<", $path or die "Failed to open $path for reading: $!"; + my $licenseBlock = _parseLicenseBlock($fileHandle); + close($fileHandle); + return $licenseBlock; +} + +sub _defaultLicenseBlock +{ + return <<EOF; +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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. + */ +EOF +} + +sub _licenseBlock +{ + my ($self) = @_; + return $self->{licenseBlock} if $self->{licenseBlock}; + + my $licenseBlock = _parseLicenseBlockFromFile($self->{idlFilePath}) || _defaultLicenseBlock(); + $self->{licenseBlock} = $licenseBlock; + return $licenseBlock; +} + +sub _generateHeaderFile +{ + my ($self, $interface) = @_; + + my @contents = (); + + my $type = $interface->type; + my $className = _className($type); + my $implementationClassName = _implementationClassName($type); + my $filename = $className . ".h"; + + push(@contents, $self->_licenseBlock()); + + my $parentClassName = _parentClassName($interface); + + push(@contents, <<EOF); + +#ifndef ${className}_h +#define ${className}_h + +#include "${parentClassName}.h" +EOF + push(@contents, <<EOF); + +namespace WTR { + +class ${implementationClassName}; + +class ${className} : public ${parentClassName} { +public: + static JSClassRef @{[$self->_classRefGetter($type)]}(); + +private: + static const JSStaticFunction* staticFunctions(); + static const JSStaticValue* staticValues(); +EOF + + if (my @functions = @{$interface->functions}) { + push(@contents, "\n // Functions\n\n"); + foreach my $function (@functions) { + push(@contents, " static JSValueRef @{[$function->name]}(JSContextRef, JSObjectRef, JSObjectRef, size_t, const JSValueRef[], JSValueRef*);\n"); + } + } + + if (my @attributes = @{$interface->attributes}) { + push(@contents, "\n // Attributes\n\n"); + foreach my $attribute (@attributes) { + push(@contents, " static JSValueRef @{[$self->_getterName($attribute)]}(JSContextRef, JSObjectRef, JSStringRef, JSValueRef*);\n"); + push(@contents, " static bool @{[$self->_setterName($attribute)]}(JSContextRef, JSObjectRef, JSStringRef, JSValueRef, JSValueRef*);\n") unless $attribute->isReadOnly; + } + } + + push(@contents, <<EOF); +}; + +${implementationClassName}* to${implementationClassName}(JSContextRef, JSValueRef); + +} // namespace WTR + +#endif // ${className}_h +EOF + + return { name => $filename, contents => \@contents }; +} + +sub _generateImplementationFile +{ + my ($self, $interface) = @_; + + my @contentsPrefix = (); + my %contentsIncludes = (); + my @contents = (); + + my $type = $interface->type; + my $className = _className($type); + my $implementationClassName = _implementationClassName($type); + my $filename = $className . ".cpp"; + + push(@contentsPrefix, $self->_licenseBlock()); + + my $classRefGetter = $self->_classRefGetter($type); + my $parentClassName = _parentClassName($interface); + + $contentsIncludes{"${className}.h"} = 1; + $contentsIncludes{"${implementationClassName}.h"} = 1; + + push(@contentsPrefix, <<EOF); + +EOF + + push(@contents, <<EOF); +#include <JavaScriptCore/JSRetainPtr.h> +#include <wtf/GetPtr.h> + +namespace WTR { + +${implementationClassName}* to${implementationClassName}(JSContextRef context, JSValueRef value) +{ + if (!context || !value || !${className}::${classRefGetter}() || !JSValueIsObjectOfClass(context, value, ${className}::${classRefGetter}())) + return 0; + return static_cast<${implementationClassName}*>(JSWrapper::unwrap(context, value)); +} + +JSClassRef ${className}::${classRefGetter}() +{ + static JSClassRef jsClass; + if (!jsClass) { + JSClassDefinition definition = kJSClassDefinitionEmpty; + definition.className = "@{[$type->name]}"; + definition.parentClass = @{[$self->_parentClassRefGetterExpression($interface)]}; + definition.staticValues = staticValues(); + definition.staticFunctions = staticFunctions(); +EOF + + push(@contents, " definition.initialize = initialize;\n") unless _parentInterface($interface); + push(@contents, " definition.finalize = finalize;\n") unless _parentInterface($interface); + + push(@contents, <<EOF); + jsClass = JSClassCreate(&definition); + } + return jsClass; +} + +EOF + + push(@contents, $self->_staticFunctionsGetterImplementation($interface), "\n"); + push(@contents, $self->_staticValuesGetterImplementation($interface)); + + if (my @functions = @{$interface->functions}) { + push(@contents, "\n// Functions\n"); + + foreach my $function (@functions) { + push(@contents, <<EOF); + +JSValueRef ${className}::@{[$function->name]}(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + ${implementationClassName}* impl = to${implementationClassName}(context, thisObject); + if (!impl) + return JSValueMakeUndefined(context); + +EOF + my $functionCall; + if ($function->extendedAttributes->{"CustomArgumentHandling"}) { + $functionCall = "impl->" . $function->name . "(context, argumentCount, arguments, exception)"; + } else { + my @arguments = (); + my @specifiedArguments = @{$function->arguments}; + + $self->_includeHeaders(\%contentsIncludes, $function->type); + + if ($function->extendedAttributes->{"PassContext"}) { + push(@arguments, "context"); + } + + foreach my $i (0..$#specifiedArguments) { + my $argument = $specifiedArguments[$i]; + + $self->_includeHeaders(\%contentsIncludes, $type); + + push(@contents, " " . $self->_platformTypeVariableDeclaration($argument->type, $argument->name, "arguments[$i]", "argumentCount > $i") . "\n"); + + push(@arguments, $self->_argumentExpression($argument)); + } + + $functionCall = "impl->" . $function->name . "(" . join(", ", @arguments) . ")"; + } + + push(@contents, " ${functionCall};\n\n") if $function->type->name eq "void"; + push(@contents, " return " . $self->_returnExpression($function->type, $functionCall) . ";\n}\n"); + } + } + + if (my @attributes = @{$interface->attributes}) { + push(@contents, "\n// Attributes\n"); + foreach my $attribute (@attributes) { + $self->_includeHeaders(\%contentsIncludes, $attribute->type); + + my $getterName = $self->_getterName($attribute); + my $getterExpression = "impl->${getterName}()"; + + push(@contents, <<EOF); + +JSValueRef ${className}::${getterName}(JSContextRef context, JSObjectRef object, JSStringRef, JSValueRef* exception) +{ + ${implementationClassName}* impl = to${implementationClassName}(context, object); + if (!impl) + return JSValueMakeUndefined(context); + + return @{[$self->_returnExpression($attribute->type, $getterExpression)]}; +} +EOF + + unless ($attribute->isReadOnly) { + push(@contents, <<EOF); + +bool ${className}::@{[$self->_setterName($attribute)]}(JSContextRef context, JSObjectRef object, JSStringRef, JSValueRef value, JSValueRef* exception) +{ + ${implementationClassName}* impl = to${implementationClassName}(context, object); + if (!impl) + return false; + +EOF + + my $platformValue = $self->_platformTypeConstructor($attribute->type, "value"); + + push(@contents, <<EOF); + impl->@{[$self->_setterName($attribute)]}(${platformValue}); + + return true; +} +EOF + } + } + } + + push(@contents, <<EOF); + +} // namespace WTR + +EOF + + unshift(@contents, map { "#include \"$_\"\n" } sort keys(%contentsIncludes)); + unshift(@contents, "#include \"config.h\"\n"); + unshift(@contents, @contentsPrefix); + + return { name => $filename, contents => \@contents }; +} + +sub _getterName +{ + my ($self, $attribute) = @_; + + return $attribute->name; +} + +sub _includeHeaders +{ + my ($self, $headers, $type) = @_; + + return unless defined $type; + return if $type->name eq "boolean"; + return if $type->name eq "object"; + return if $$self{codeGenerator}->IsNonPointerType($type); + return if $$self{codeGenerator}->IsStringType($type); + + $$headers{_className($type) . ".h"} = 1; + $$headers{_implementationClassName($type) . ".h"} = 1; +} + +sub _implementationClassName +{ + my ($type) = @_; + + return $type->name; +} + +sub _parentClassName +{ + my ($interface) = @_; + + my $parentInterface = _parentInterface($interface); + return $parentInterface ? _className($parentInterface) : "JSWrapper"; +} + +sub _parentClassRefGetterExpression +{ + my ($self, $interface) = @_; + + my $parentInterface = _parentInterface($interface); + return $parentInterface ? $self->_classRefGetter($parentInterface) . "()" : "0"; +} + +sub _parentInterface +{ + my ($interface) = @_; + return $interface->parentType; +} + +sub _platformType +{ + my ($self, $type) = @_; + + return undef unless defined $type; + + return "bool" if $type->name eq "boolean"; + return "JSValueRef" if $type->name eq "object"; + return "JSRetainPtr<JSStringRef>" if $$self{codeGenerator}->IsStringType($type); + return "double" if $$self{codeGenerator}->IsNonPointerType($type); + return _implementationClassName($type); +} + +sub _platformTypeConstructor +{ + my ($self, $type, $argumentName) = @_; + + return "JSValueToNullableBoolean(context, $argumentName)" if $type->name eq "boolean" && $type->isNullable; + return "JSValueToBoolean(context, $argumentName)" if $type->name eq "boolean"; + return "$argumentName" if $type->name eq "object"; + return "JSRetainPtr<JSStringRef>(Adopt, JSValueToStringCopy(context, $argumentName, 0))" if $$self{codeGenerator}->IsStringType($type); + return "JSValueToNumber(context, $argumentName, 0)" if $$self{codeGenerator}->IsNonPointerType($type); + return "to" . _implementationClassName($type) . "(context, $argumentName)"; +} + +sub _platformTypeVariableDeclaration +{ + my ($self, $type, $variableName, $argumentName, $condition) = @_; + + my $platformType = $self->_platformType($type); + my $constructor = $self->_platformTypeConstructor($type, $argumentName); + + my %nonPointerTypes = ( + "bool" => 1, + "double" => 1, + "JSRetainPtr<JSStringRef>" => 1, + "JSValueRef" => 1, + ); + + my $nullValue = "0"; + if ($platformType eq "JSValueRef") { + $nullValue = "JSValueMakeUndefined(context)"; + } elsif (defined $nonPointerTypes{$platformType} && $platformType ne "double") { + $nullValue = "$platformType()"; + } + + $platformType .= "*" unless defined $nonPointerTypes{$platformType}; + + return "$platformType $variableName = $condition && $constructor;" if $condition && $platformType eq "bool"; + return "$platformType $variableName = $condition ? $constructor : $nullValue;" if $condition; + return "$platformType $variableName = $constructor;"; +} + +sub _returnExpression +{ + my ($self, $returnType, $expression) = @_; + + return "JSValueMakeUndefined(context)" if $returnType->name eq "void"; + return "JSValueMakeBooleanOrNull(context, ${expression})" if $returnType->name eq "boolean" && $returnType->isNullable; + return "JSValueMakeBoolean(context, ${expression})" if $returnType->name eq "boolean"; + return "${expression}" if $returnType->name eq "object"; + return "JSValueMakeNumber(context, ${expression})" if $$self{codeGenerator}->IsNonPointerType($returnType); + return "JSValueMakeStringOrNull(context, ${expression}.get())" if $$self{codeGenerator}->IsStringType($returnType); + return "toJS(context, WTF::getPtr(${expression}))"; +} + +sub _argumentExpression +{ + my ($self, $argument) = @_; + + my $type = $argument->type; + my $name = $argument->name; + + return "${name}.get()" if $$self{codeGenerator}->IsStringType($type); + return $name; +} + +sub _setterName +{ + my ($self, $attribute) = @_; + + my $name = $attribute->name; + + return "set" . $$self{codeGenerator}->WK_ucfirst($name); +} + +sub _staticFunctionsGetterImplementation +{ + my ($self, $interface) = @_; + + my $mapFunction = sub { + my $name = $_->name; + my @attributes = qw(kJSPropertyAttributeDontDelete kJSPropertyAttributeReadOnly); + push(@attributes, "kJSPropertyAttributeDontEnum") if $_->extendedAttributes->{"DontEnum"}; + + return "{ \"$name\", $name, " . join(" | ", @attributes) . " }"; + }; + + return $self->_staticFunctionsOrValuesGetterImplementation($interface, "function", "{ 0, 0, 0 }", $mapFunction, $interface->functions); +} + +sub _staticFunctionsOrValuesGetterImplementation +{ + my ($self, $interface, $functionOrValue, $arrayTerminator, $mapFunction, $functionsOrAttributes) = @_; + + my $className = _className($interface->type); + my $uppercaseFunctionOrValue = $$self{codeGenerator}->WK_ucfirst($functionOrValue); + + my $result = <<EOF; +const JSStatic${uppercaseFunctionOrValue}* ${className}::static${uppercaseFunctionOrValue}s() +{ +EOF + + my @initializers = map(&$mapFunction, @{$functionsOrAttributes}); + return $result . " return 0;\n}\n" unless @initializers; + + $result .= <<EOF + static const JSStatic${uppercaseFunctionOrValue} ${functionOrValue}s[] = { + @{[join(",\n ", @initializers)]}, + ${arrayTerminator} + }; + return ${functionOrValue}s; +} +EOF +} + +sub _staticValuesGetterImplementation +{ + my ($self, $interface) = @_; + + my $mapFunction = sub { + return if $_->extendedAttributes->{"NoImplementation"}; + + my $attributeName = $_->name; + my $getterName = $self->_getterName($_); + my $setterName = $_->isReadOnly ? "0" : $self->_setterName($_); + my @attributes = qw(kJSPropertyAttributeDontDelete); + push(@attributes, "kJSPropertyAttributeReadOnly") if $_->isReadOnly; + push(@attributes, "kJSPropertyAttributeDontEnum") if $_->extendedAttributes->{"DontEnum"}; + + return "{ \"$attributeName\", $getterName, $setterName, " . join(" | ", @attributes) . " }"; + }; + + return $self->_staticFunctionsOrValuesGetterImplementation($interface, "value", "{ 0, 0, 0, 0 }", $mapFunction, $interface->attributes); +} + +1; diff --git a/Tools/DumpRenderTree/CMakeLists.txt b/Tools/DumpRenderTree/CMakeLists.txt new file mode 100644 index 000000000..a34ba0a44 --- /dev/null +++ b/Tools/DumpRenderTree/CMakeLists.txt @@ -0,0 +1,100 @@ +set(WEBKIT_TESTRUNNER_SHARED_DIR "${TOOLS_DIR}/TestRunnerShared/") +set(WEBKIT_TESTRUNNER_UISCRIPTCONTEXT_DIR "${TOOLS_DIR}/TestRunnerShared/UIScriptContext") +set(DUMP_RENDER_TREE_BINDINGS_DIR "${TOOLS_DIR}/DumpRenderTree/Bindings") + +file(MAKE_DIRECTORY ${DERIVED_SOURCES_DIR}/DumpRenderTree) + +set(DumpRenderTree_SOURCES + AccessibilityController.cpp + AccessibilityTextMarker.cpp + AccessibilityUIElement.cpp + CyclicRedundancyCheck.cpp + DumpRenderTreeCommon.cpp + GCController.cpp + JavaScriptThreading.cpp + PixelDumpSupport.cpp + TestRunner.cpp + WorkQueue.cpp + ${WEBKIT_TESTRUNNER_UISCRIPTCONTEXT_DIR}/UIScriptContext.cpp + ${WEBKIT_TESTRUNNER_UISCRIPTCONTEXT_DIR}/UIScriptController.cpp + ${WEBKIT_TESTRUNNER_SHARED_DIR}/Bindings/JSWrapper.cpp +) + +set(DumpRenderTree_LIBRARIES + WebCoreTestSupport + JavaScriptCore +) + +set(DumpRenderTree_INCLUDE_DIRECTORIES + ${DERIVED_SOURCES_DIR}/DumpRenderTree + ${WEBKIT_TESTRUNNER_UISCRIPTCONTEXT_DIR} + ${WEBKIT_TESTRUNNER_SHARED_DIR}/Bindings + ${TOOLS_DIR}/DumpRenderTree + ${CMAKE_SOURCE_DIR}/Source + ${WEBCORE_DIR}/testing/js +) + +set(TestNetscapePlugIn_SOURCES + TestNetscapePlugIn/PluginObject.cpp + TestNetscapePlugIn/PluginTest.cpp + TestNetscapePlugIn/TestObject.cpp + TestNetscapePlugIn/main.cpp + + TestNetscapePlugIn/Tests/DocumentOpenInDestroyStream.cpp + TestNetscapePlugIn/Tests/EvaluateJSAfterRemovingPluginElement.cpp + TestNetscapePlugIn/Tests/FormValue.cpp + TestNetscapePlugIn/Tests/GetURLNotifyWithURLThatFailsToLoad.cpp + TestNetscapePlugIn/Tests/GetURLWithJavaScriptURL.cpp + TestNetscapePlugIn/Tests/GetURLWithJavaScriptURLDestroyingPlugin.cpp + TestNetscapePlugIn/Tests/GetUserAgentWithNullNPPFromNPPNew.cpp + TestNetscapePlugIn/Tests/LogNPPSetWindow.cpp + TestNetscapePlugIn/Tests/NPDeallocateCalledBeforeNPShutdown.cpp + TestNetscapePlugIn/Tests/NPPNewFails.cpp + TestNetscapePlugIn/Tests/NPPSetWindowCalledDuringDestruction.cpp + TestNetscapePlugIn/Tests/NPRuntimeCallsWithNullNPP.cpp + TestNetscapePlugIn/Tests/NPRuntimeObjectFromDestroyedPlugin.cpp + TestNetscapePlugIn/Tests/NPRuntimeRemoveProperty.cpp + TestNetscapePlugIn/Tests/NullNPPGetValuePointer.cpp + TestNetscapePlugIn/Tests/PassDifferentNPPStruct.cpp + TestNetscapePlugIn/Tests/PluginScriptableNPObjectInvokeDefault.cpp + TestNetscapePlugIn/Tests/PluginScriptableObjectOverridesAllProperties.cpp + TestNetscapePlugIn/Tests/PrivateBrowsing.cpp + TestNetscapePlugIn/Tests/ToStringAndValueOfObject.cpp + TestNetscapePlugIn/Tests/URLRedirect.cpp +) + +set(TestNetscapePlugIn_LIBRARIES + JavaScriptCore + WTF + WebCoreTestSupport +) + +set(DumpRenderTree_IDL_FILES + "${WEBKIT_TESTRUNNER_UISCRIPTCONTEXT_DIR}/Bindings/UIScriptController.idl" +) + +GENERATE_BINDINGS(DumpRenderTreeBindings + OUTPUT_SOURCE DumpRenderTree_SOURCES + INPUT_FILES ${DumpRenderTree_IDL_FILES} + BASE_DIR ${DUMP_RENDER_TREE_BINDINGS_DIR} + IDL_INCLUDES Bindings + FEATURES ${FEATURE_DEFINES_WITH_SPACE_SEPARATOR} + DESTINATION ${DERIVED_SOURCES_DIR}/DumpRenderTree + GENERATOR DumpRenderTree) + +WEBKIT_INCLUDE_CONFIG_FILES_IF_EXISTS() + +include_directories(${DumpRenderTree_INCLUDE_DIRECTORIES}) + +add_executable(DumpRenderTree ${DumpRenderTree_SOURCES}) +target_link_libraries(DumpRenderTree ${DumpRenderTree_LIBRARIES}) +add_dependencies(DumpRenderTree DumpRenderTreeBindings) + +if (ENABLE_NETSCAPE_PLUGIN_API) + add_library(TestNetscapePlugIn SHARED ${TestNetscapePlugIn_SOURCES}) + target_link_libraries(TestNetscapePlugIn ${TestNetscapePlugIn_LIBRARIES}) +endif () + +if (WIN32) + add_dependencies(DumpRenderTree DumpRenderTreeLib) +endif () diff --git a/Tools/DumpRenderTree/DefaultPolicyDelegate.h b/Tools/DumpRenderTree/DefaultPolicyDelegate.h new file mode 100644 index 000000000..6ff5becca --- /dev/null +++ b/Tools/DumpRenderTree/DefaultPolicyDelegate.h @@ -0,0 +1,13 @@ +// +// DefaultPolicyDelegate.h +// DumpRenderTree +// +// Created by Anders Carlsson on 7/9/13. +// +// + +#import <WebKit/WebDefaultPolicyDelegate.h> + +@interface DefaultPolicyDelegate : WebDefaultPolicyDelegate + +@end diff --git a/Tools/DumpRenderTree/DerivedSources.make b/Tools/DumpRenderTree/DerivedSources.make new file mode 100644 index 000000000..05bffef75 --- /dev/null +++ b/Tools/DumpRenderTree/DerivedSources.make @@ -0,0 +1,50 @@ +# Copyright (C) 2016 Apple Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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. + +UISCRIPTCONTEXT_DIR = $(DumpRenderTree)/../TestRunnerShared/UIScriptContext/Bindings + +VPATH = \ + $(UISCRIPTCONTEXT_DIR) \ +# + +UICONTEXT_INTERFACES = \ + UIScriptController \ +# + +SCRIPTS = \ + $(WebCoreScripts)/CodeGenerator.pm \ + $(DumpRenderTree)/Bindings/CodeGeneratorDumpRenderTree.pm \ + $(WebCoreScripts)/IDLParser.pm \ + $(WebCoreScripts)/generate-bindings.pl \ +# + +.PHONY : all + +JS%.h JS%.cpp : %.idl $(SCRIPTS) + @echo Generating bindings for $*... + @perl -I $(WebCoreScripts) -I $(UISCRIPTCONTEXT_DIR) -I $(DumpRenderTree)/Bindings $(WebCoreScripts)/generate-bindings.pl --defines "" --include $(UISCRIPTCONTEXT_DIR) --outputDir . --generator DumpRenderTree $< + +all : \ + $(UICONTEXT_INTERFACES:%=JS%.h) \ + $(UICONTEXT_INTERFACES:%=JS%.cpp) \ +# diff --git a/Tools/DumpRenderTree/DumpRenderTree.h b/Tools/DumpRenderTree/DumpRenderTree.h index 3e6323525..743e68255 100644 --- a/Tools/DumpRenderTree/DumpRenderTree.h +++ b/Tools/DumpRenderTree/DumpRenderTree.h @@ -10,7 +10,7 @@ * 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 + * 3. Neither the name of Apple 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. * @@ -26,15 +26,9 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef DumpRenderTree_h -#define DumpRenderTree_h +#pragma once -// FIXME: Remove this when all platforms are using config.h -#ifndef Config_H -#include <wtf/Platform.h> -#endif - -#if PLATFORM(MAC) +#if PLATFORM(COCOA) #include "DumpRenderTreeMac.h" #elif PLATFORM(WIN) #include "DumpRenderTreeWin.h" @@ -45,6 +39,7 @@ #endif #include <string> +#include <wtf/Platform.h> #include <wtf/RefPtr.h> #if !OS(OPENBSD) @@ -62,14 +57,12 @@ void dump(); void displayWebView(); struct TestCommand { - TestCommand() : shouldDumpPixels(false), timeout(30000) { } - std::string pathOrURL; - bool shouldDumpPixels; + std::string absolutePath; + bool shouldDumpPixels { false }; std::string expectedPixelHash; - int timeout; // in ms + int timeout { 30000 }; // in ms + bool dumpJSConsoleLogInStdErr { false }; }; TestCommand parseInputLine(const std::string&); - -#endif // DumpRenderTree_h diff --git a/Tools/DumpRenderTree/DumpRenderTreeCommon.cpp b/Tools/DumpRenderTree/DumpRenderTreeCommon.cpp index 3cb97ebfd..3c7aa61e8 100644 --- a/Tools/DumpRenderTree/DumpRenderTreeCommon.cpp +++ b/Tools/DumpRenderTree/DumpRenderTreeCommon.cpp @@ -1,3 +1,28 @@ +/* + * Copyright (C) 2016 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #include "config.h" #include "DumpRenderTree.h" @@ -70,14 +95,18 @@ TestCommand parseInputLine(const std::string& inputLine) result.pathOrURL = arg; while (tokenizer.hasNext()) { arg = tokenizer.next(); - if (arg == std::string("--timeout")) { + if (arg == "--timeout") { std::string timeoutToken = tokenizer.next(); result.timeout = atoi(timeoutToken.c_str()); - } else if (arg == std::string("-p") || arg == std::string("--pixel-test")) { + } else if (arg == "-p" || arg == "--pixel-test") { result.shouldDumpPixels = true; if (tokenizer.hasNext()) result.expectedPixelHash = tokenizer.next(); - } else + } else if (arg == "--dump-jsconsolelog-in-stderr") + result.dumpJSConsoleLogInStdErr = true; + else if (arg == std::string("--absolutePath")) + result.absolutePath = tokenizer.next(); + else die(inputLine); } diff --git a/Tools/DumpRenderTree/DumpRenderTreeFileDraggingSource.h b/Tools/DumpRenderTree/DumpRenderTreeFileDraggingSource.h new file mode 100644 index 000000000..1d42a474c --- /dev/null +++ b/Tools/DumpRenderTree/DumpRenderTreeFileDraggingSource.h @@ -0,0 +1,43 @@ +// Copyright (c) 2009, Google Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if !PLATFORM(IOS) + +#import <Cocoa/Cocoa.h> + +// An implementation of NSDraggingSource for use with DumpRenderTreeDraggingInfo when dragging files +// Used by -[EventSendingController beginDragWithFiles:] + +@interface DumpRenderTreeFileDraggingSource : NSObject { +} + +- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)flag; + +@end + +#endif diff --git a/Tools/DumpRenderTree/DumpRenderTreePrefix.h b/Tools/DumpRenderTree/DumpRenderTreePrefix.h index 64eae0704..105b54356 100644 --- a/Tools/DumpRenderTree/DumpRenderTreePrefix.h +++ b/Tools/DumpRenderTree/DumpRenderTreePrefix.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2005 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,7 +10,7 @@ * 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 + * 3. Neither the name of Apple 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. * @@ -26,8 +26,17 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H && defined(BUILDING_WITH_CMAKE) +#include "cmakeconfig.h" +#endif + #include <wtf/Platform.h> #ifdef __OBJC__ #import <Foundation/Foundation.h> #endif + +#if OS(WINDOWS) +#undef WEBCORE_EXPORT +#define WEBCORE_EXPORT WTF_IMPORT_DECLARATION +#endif diff --git a/Tools/DumpRenderTree/ForwardingHeaders/runtime/ArrayBufferView.h b/Tools/DumpRenderTree/ForwardingHeaders/runtime/ArrayBufferView.h new file mode 100644 index 000000000..7731671c8 --- /dev/null +++ b/Tools/DumpRenderTree/ForwardingHeaders/runtime/ArrayBufferView.h @@ -0,0 +1 @@ +#include <JavaScriptCore/ArrayBufferView.h> diff --git a/Tools/DumpRenderTree/ForwardingHeaders/runtime/JSArrayBufferView.h b/Tools/DumpRenderTree/ForwardingHeaders/runtime/JSArrayBufferView.h new file mode 100644 index 000000000..e38a8040f --- /dev/null +++ b/Tools/DumpRenderTree/ForwardingHeaders/runtime/JSArrayBufferView.h @@ -0,0 +1 @@ +#include <JavaScriptCore/JSArrayBufferView.h> diff --git a/Tools/DumpRenderTree/ForwardingHeaders/runtime/JSExportMacros.h b/Tools/DumpRenderTree/ForwardingHeaders/runtime/JSExportMacros.h new file mode 100644 index 000000000..4c5dcb983 --- /dev/null +++ b/Tools/DumpRenderTree/ForwardingHeaders/runtime/JSExportMacros.h @@ -0,0 +1 @@ +#include <JavaScriptCore/JSExportMacros.h>
\ No newline at end of file diff --git a/Tools/DumpRenderTree/ForwardingHeaders/runtime/TypedArrayInlines.h b/Tools/DumpRenderTree/ForwardingHeaders/runtime/TypedArrayInlines.h new file mode 100644 index 000000000..6a61945ea --- /dev/null +++ b/Tools/DumpRenderTree/ForwardingHeaders/runtime/TypedArrayInlines.h @@ -0,0 +1 @@ +#include <JavaScriptCore/TypedArrayInlines.h> diff --git a/Tools/DumpRenderTree/GCController.cpp b/Tools/DumpRenderTree/GCController.cpp index 06a04fbca..781a828eb 100644 --- a/Tools/DumpRenderTree/GCController.cpp +++ b/Tools/DumpRenderTree/GCController.cpp @@ -10,7 +10,7 @@ * 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 + * 3. Neither the name of Apple 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. * diff --git a/Tools/DumpRenderTree/GCController.h b/Tools/DumpRenderTree/GCController.h index afc1de087..79ceafc9f 100644 --- a/Tools/DumpRenderTree/GCController.h +++ b/Tools/DumpRenderTree/GCController.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,7 +10,7 @@ * 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 + * 3. Neither the name of Apple 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. * diff --git a/Tools/DumpRenderTree/JavaScriptThreading.cpp b/Tools/DumpRenderTree/JavaScriptThreading.cpp new file mode 100644 index 000000000..e2f9bade6 --- /dev/null +++ b/Tools/DumpRenderTree/JavaScriptThreading.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved. + * (C) 2007 Graham Dennis (graham.dennis@gmail.com) + * (C) 2007 Eric Seidel <eric@webkit.org> + * (C) 2012 Patrick Ganstere <paroga@paroga.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 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. + */ + +#include "config.h" +#include "JavaScriptThreading.h" + +#include <JavaScriptCore/JavaScriptCore.h> +#include <stdlib.h> +#include <wtf/Assertions.h> +#include <wtf/HashSet.h> +#include <wtf/Lock.h> +#include <wtf/Threading.h> +#include <wtf/ThreadingPrimitives.h> +#include <wtf/Vector.h> + +static const size_t javaScriptThreadsCount = 4; +static bool javaScriptThreadsShouldTerminate; +static JSContextGroupRef javaScriptThreadsGroup; + +static Lock& javaScriptThreadsMutex() +{ + DEPRECATED_DEFINE_STATIC_LOCAL(Lock, staticMutex, ()); + return staticMutex; +} + +typedef HashSet<ThreadIdentifier> ThreadSet; +static ThreadSet& javaScriptThreads() +{ + DEPRECATED_DEFINE_STATIC_LOCAL(ThreadSet, staticJavaScriptThreads, ()); + ASSERT(!javaScriptThreadsMutex().tryLock()); + return staticJavaScriptThreads; +} + +// This function exercises JSC in a loop until javaScriptThreadsShouldTerminate +// becomes true or it probabilistically decides to spawn a replacement thread and exit. +void runJavaScriptThread(void*) +{ + static const char* const script = + "var array = [];" + "for (var i = 0; i < 1024; i++) {" + " array.push(String(i));" + "}"; + + JSGlobalContextRef ctx; + { + LockHolder locker(javaScriptThreadsMutex()); + ctx = JSGlobalContextCreateInGroup(javaScriptThreadsGroup, 0); + } + + JSStringRef scriptRef; + { + LockHolder locker(javaScriptThreadsMutex()); + scriptRef = JSStringCreateWithUTF8CString(script); + } + + while (true) { + { + LockHolder locker(javaScriptThreadsMutex()); + JSValueRef exception = 0; + JSEvaluateScript(ctx, scriptRef, 0, 0, 1, &exception); + ASSERT(!exception); + } + + { + LockHolder locker(javaScriptThreadsMutex()); + const size_t valuesCount = 1024; + JSValueRef values[valuesCount]; + for (size_t i = 0; i < valuesCount; ++i) + values[i] = JSObjectMake(ctx, 0, 0); + } + + { + LockHolder locker(javaScriptThreadsMutex()); + if (javaScriptThreadsShouldTerminate) + break; + } + + // Respawn probabilistically. + if (rand() % 5) + continue; + + LockHolder locker(javaScriptThreadsMutex()); + ThreadIdentifier thread = currentThread(); + detachThread(thread); + javaScriptThreads().remove(thread); + javaScriptThreads().add(createThread(&runJavaScriptThread, 0, 0)); + break; + } + + LockHolder locker(javaScriptThreadsMutex()); + JSStringRelease(scriptRef); + JSGarbageCollect(ctx); + JSGlobalContextRelease(ctx); +} + +void startJavaScriptThreads() +{ + javaScriptThreadsGroup = JSContextGroupCreate(); + + LockHolder locker(javaScriptThreadsMutex()); + + for (size_t i = 0; i < javaScriptThreadsCount; ++i) + javaScriptThreads().add(createThread(&runJavaScriptThread, 0, 0)); +} + +void stopJavaScriptThreads() +{ + { + LockHolder locker(javaScriptThreadsMutex()); + javaScriptThreadsShouldTerminate = true; + } + + Vector<ThreadIdentifier, javaScriptThreadsCount> threads; + { + LockHolder locker(javaScriptThreadsMutex()); + copyToVector(javaScriptThreads(), threads); + ASSERT(threads.size() == javaScriptThreadsCount); + } + + for (size_t i = 0; i < javaScriptThreadsCount; ++i) + waitForThreadCompletion(threads[i]); + + { + LockHolder locker(javaScriptThreadsMutex()); + javaScriptThreads().clear(); + } + + JSContextGroupRelease(javaScriptThreadsGroup); +} diff --git a/Tools/DumpRenderTree/JavaScriptThreading.h b/Tools/DumpRenderTree/JavaScriptThreading.h index 43795a1a2..5bbe9cafe 100644 --- a/Tools/DumpRenderTree/JavaScriptThreading.h +++ b/Tools/DumpRenderTree/JavaScriptThreading.h @@ -12,7 +12,7 @@ * 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 + * 3. Neither the name of Apple 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. * diff --git a/Tools/DumpRenderTree/PixelDumpSupport.cpp b/Tools/DumpRenderTree/PixelDumpSupport.cpp index ba619bbea..5160444bf 100644 --- a/Tools/DumpRenderTree/PixelDumpSupport.cpp +++ b/Tools/DumpRenderTree/PixelDumpSupport.cpp @@ -10,7 +10,7 @@ * 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 + * 3. Neither the name of Apple 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. * @@ -43,7 +43,6 @@ #include "PixelDumpSupportCairo.h" #endif -#if !PLATFORM(IOS) void dumpWebViewAsPixelsAndCompareWithExpected(const std::string& expectedHash) { RefPtr<BitmapContext> context; @@ -58,14 +57,14 @@ void dumpWebViewAsPixelsAndCompareWithExpected(const std::string& expectedHash) // Compute the hash of the bitmap context pixels char actualHash[33]; computeMD5HashStringForBitmapContext(context.get(), actualHash); - printf("\nActualHash: %s\n", actualHash); // FIXME: No need for the leading newline. + fprintf(testResult, "\nActualHash: %s\n", actualHash); // FIXME: No need for the leading newline. // Check the computed hash against the expected one and dump image on mismatch bool dumpImage = true; if (expectedHash.length() > 0) { ASSERT(expectedHash.length() == 32); - printf("\nExpectedHash: %s\n", expectedHash.c_str()); // FIXME: No need for the leading newline. + fprintf(testResult, "\nExpectedHash: %s\n", expectedHash.c_str()); // FIXME: No need for the leading newline. if (expectedHash == actualHash) // FIXME: do case insensitive compare dumpImage = false; @@ -74,7 +73,6 @@ void dumpWebViewAsPixelsAndCompareWithExpected(const std::string& expectedHash) if (dumpImage) dumpBitmap(context.get(), actualHash); } -#endif static void appendIntToVector(unsigned number, Vector<unsigned char>& vector) { @@ -116,20 +114,20 @@ void printPNG(const unsigned char* data, const size_t dataLength, const char* ch Vector<unsigned char> bytesToAdd; convertChecksumToPNGComment(checksum, bytesToAdd); - printf("Content-Type: %s\n", "image/png"); - printf("Content-Length: %lu\n", static_cast<unsigned long>(dataLength + bytesToAdd.size())); + fprintf(testResult, "Content-Type: image/png\n"); + fprintf(testResult, "Content-Length: %lu\n", static_cast<unsigned long>(dataLength + bytesToAdd.size())); size_t insertOffset = offsetAfterIHDRChunk(data, dataLength); - fwrite(data, 1, insertOffset, stdout); - fwrite(bytesToAdd.data(), 1, bytesToAdd.size(), stdout); + fwrite(data, 1, insertOffset, testResult); + fwrite(bytesToAdd.data(), 1, bytesToAdd.size(), testResult); const size_t bytesToWriteInOneChunk = 1 << 15; data += insertOffset; size_t dataRemainingToWrite = dataLength - insertOffset; while (dataRemainingToWrite) { size_t bytesToWriteInThisChunk = std::min(dataRemainingToWrite, bytesToWriteInOneChunk); - size_t bytesWritten = fwrite(data, 1, bytesToWriteInThisChunk, stdout); + size_t bytesWritten = fwrite(data, 1, bytesToWriteInThisChunk, testResult); if (bytesWritten != bytesToWriteInThisChunk) break; dataRemainingToWrite -= bytesWritten; diff --git a/Tools/DumpRenderTree/PixelDumpSupport.h b/Tools/DumpRenderTree/PixelDumpSupport.h index 3bd8820c7..1885b3569 100644 --- a/Tools/DumpRenderTree/PixelDumpSupport.h +++ b/Tools/DumpRenderTree/PixelDumpSupport.h @@ -10,7 +10,7 @@ * 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 + * 3. Neither the name of Apple 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. * @@ -26,20 +26,16 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef PixelDumpSupport_h -#define PixelDumpSupport_h +#pragma once #include <string> - -#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> class BitmapContext; void computeMD5HashStringForBitmapContext(BitmapContext*, char hashString[33]); -PassRefPtr<BitmapContext> createPagedBitmapContext(); -PassRefPtr<BitmapContext> createBitmapContextFromWebView(bool onscreen, bool incrementalRepaint, bool sweepHorizontally, bool drawSelectionRect); +RefPtr<BitmapContext> createPagedBitmapContext(); +RefPtr<BitmapContext> createBitmapContextFromWebView(bool onscreen, bool incrementalRepaint, bool sweepHorizontally, bool drawSelectionRect); void dumpBitmap(BitmapContext*, const char* checksum); void dumpWebViewAsPixelsAndCompareWithExpected(const std::string& expectedHash); void printPNG(const unsigned char* data, const size_t dataLength, const char* checksum); - -#endif // PixelDumpSupport_h diff --git a/Tools/DumpRenderTree/TestNetscapePlugIn/CMakeLists.txt b/Tools/DumpRenderTree/TestNetscapePlugIn/CMakeLists.txt new file mode 100644 index 000000000..a5391b534 --- /dev/null +++ b/Tools/DumpRenderTree/TestNetscapePlugIn/CMakeLists.txt @@ -0,0 +1,61 @@ +set(WEBKIT_TESTNETSCAPEPLUGIN_DIR "${TOOLS_DIR}/DumpRenderTree/TestNetscapePlugIn") + +set(WebKitTestNetscapePlugIn_SOURCES + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/PluginObject.cpp + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/PluginTest.cpp + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/TestObject.cpp + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/main.cpp + + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/DocumentOpenInDestroyStream.cpp + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/EvaluateJSAfterRemovingPluginElement.cpp + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/FormValue.cpp + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/GetURLNotifyWithURLThatFailsToLoad.cpp + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/GetURLWithJavaScriptURL.cpp + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/GetURLWithJavaScriptURLDestroyingPlugin.cpp + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/GetUserAgentWithNullNPPFromNPPNew.cpp + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/LogNPPSetWindow.cpp + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/NPDeallocateCalledBeforeNPShutdown.cpp + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/NPPNewFails.cpp + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/NPPSetWindowCalledDuringDestruction.cpp + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/NPRuntimeCallsWithNullNPP.cpp + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/NPRuntimeObjectFromDestroyedPlugin.cpp + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/NPRuntimeRemoveProperty.cpp + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/NullNPPGetValuePointer.cpp + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/PassDifferentNPPStruct.cpp + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/PluginScriptableNPObjectInvokeDefault.cpp + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/PluginScriptableObjectOverridesAllProperties.cpp + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/PrivateBrowsing.cpp + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/ToStringAndValueOfObject.cpp + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/URLRedirect.cpp + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/x11/CallInvalidateRectWithNullNPPArgument.cpp +) + +set(WebKitTestNetscapePlugIn_INCLUDE_DIRECTORIES + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR} + ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/ForwardingHeaders + ${WEBCORE_DIR} + ${WTF_DIR} +) + +set(WebKitTestNetscapePlugIn_SYSTEM_INCLUDE_DIRECTORIES + ${X11_INCLUDE_DIR} +) + +include_directories(${WebKitTestNetscapePlugIn_INCLUDE_DIRECTORIES}) +include_directories(SYSTEM ${WebKitTestNetscapePlugIn_SYSTEM_INCLUDE_DIRECTORIES}) + +set(WebKitTestNetscapePlugIn_LIBRARIES + ${X11_LIBRARIES} +) + +if (WTF_OS_UNIX) + add_definitions(-DXP_UNIX) +endif () + +add_library(TestNetscapePlugIn SHARED ${WebKitTestNetscapePlugIn_SOURCES}) +target_link_libraries(TestNetscapePlugIn ${WebKitTestNetscapePlugIn_LIBRARIES}) +set_target_properties(TestNetscapePlugIn PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/plugins) +WEBKIT_SET_EXTRA_COMPILER_FLAGS(TestNetscapePlugIn) + +# Suppress unused parameter warnings for sources in WebKit2. +ADD_TARGET_PROPERTIES(TestNetscapePlugIn COMPILE_FLAGS "-Wno-unused-parameter") diff --git a/Tools/DumpRenderTree/TestNetscapePlugIn/unix/ForwardingHeaders/WebKit/npapi.h b/Tools/DumpRenderTree/TestNetscapePlugIn/ForwardingHeaders/WebKit/npapi.h index 627bc97a9..627bc97a9 100644 --- a/Tools/DumpRenderTree/TestNetscapePlugIn/unix/ForwardingHeaders/WebKit/npapi.h +++ b/Tools/DumpRenderTree/TestNetscapePlugIn/ForwardingHeaders/WebKit/npapi.h diff --git a/Tools/DumpRenderTree/TestNetscapePlugIn/unix/ForwardingHeaders/WebKit/npfunctions.h b/Tools/DumpRenderTree/TestNetscapePlugIn/ForwardingHeaders/WebKit/npfunctions.h index 54a603dbb..54a603dbb 100644 --- a/Tools/DumpRenderTree/TestNetscapePlugIn/unix/ForwardingHeaders/WebKit/npfunctions.h +++ b/Tools/DumpRenderTree/TestNetscapePlugIn/ForwardingHeaders/WebKit/npfunctions.h diff --git a/Tools/DumpRenderTree/TestNetscapePlugIn/unix/ForwardingHeaders/WebKit/npruntime.h b/Tools/DumpRenderTree/TestNetscapePlugIn/ForwardingHeaders/WebKit/npruntime.h index e435ae2ab..e435ae2ab 100644 --- a/Tools/DumpRenderTree/TestNetscapePlugIn/unix/ForwardingHeaders/WebKit/npruntime.h +++ b/Tools/DumpRenderTree/TestNetscapePlugIn/ForwardingHeaders/WebKit/npruntime.h diff --git a/Tools/DumpRenderTree/TestNetscapePlugIn/PluginObject.cpp b/Tools/DumpRenderTree/TestNetscapePlugIn/PluginObject.cpp index 75631842f..982452b68 100644 --- a/Tools/DumpRenderTree/TestNetscapePlugIn/PluginObject.cpp +++ b/Tools/DumpRenderTree/TestNetscapePlugIn/PluginObject.cpp @@ -30,10 +30,14 @@ #include "PluginTest.h" #include "TestObject.h" #include <assert.h> +#include <memory> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <wtf/Platform.h> +#include <wtf/ExportMacros.h> +#include <wtf/Assertions.h> // Helper function which takes in the plugin window object for logging to the console object. static void pluginLogWithWindowObject(NPObject* windowObject, NPP instance, const char* message) @@ -60,6 +64,7 @@ static void pluginLogWithWindowObject(NPObject* windowObject, NPP instance, cons browser->releaseobject(consoleObject); } +WTF_ATTRIBUTE_PRINTF(2, 0) void pluginLogWithArguments(NPP instance, const char* format, va_list args) { const size_t messageBufferSize = 2048; @@ -80,6 +85,7 @@ void pluginLogWithArguments(NPP instance, const char* format, va_list args) } // Helper function to log to the console object. +WTF_ATTRIBUTE_PRINTF(2, 3) void pluginLog(NPP instance, const char* format, ...) { va_list args; @@ -770,11 +776,15 @@ static bool testGetPropertyReturnValue(PluginObject* obj, const NPVariant* args, return true; } -static char* toCString(const NPString& string) +static std::unique_ptr<char[]> toCString(const NPString& string) { - char* result = static_cast<char*>(malloc(string.UTF8Length + 1)); - memcpy(result, string.UTF8Characters, string.UTF8Length); - result[string.UTF8Length] = '\0'; + size_t length = string.UTF8Length; + std::unique_ptr<char[]> result(new char[length + 1]); + if (!result) + return result; + + memcpy(result.get(), string.UTF8Characters, length); + result[length] = '\0'; return result; } @@ -785,30 +795,27 @@ static bool testPostURLFile(PluginObject* obj, const NPVariant* args, uint32_t a return false; NPString urlString = NPVARIANT_TO_STRING(args[0]); - char* url = toCString(urlString); + auto url = toCString(urlString); NPString targetString = NPVARIANT_TO_STRING(args[1]); - char* target = toCString(targetString); + auto target = toCString(targetString); NPString pathString = NPVARIANT_TO_STRING(args[2]); - char* path = toCString(pathString); + auto path = toCString(pathString); NPString contentsString = NPVARIANT_TO_STRING(args[3]); - FILE* tempFile = fopen(path, "w"); + FILE* tempFile = fopen(path.get(), "w"); if (!tempFile) return false; - if (!fwrite(contentsString.UTF8Characters, contentsString.UTF8Length, 1, tempFile)) - return false; - + size_t count = fwrite(contentsString.UTF8Characters, contentsString.UTF8Length, 1, tempFile); fclose(tempFile); - NPError error = browser->posturl(obj->npp, url, target, pathString.UTF8Length, path, TRUE); + if (!count) + return false; - free(path); - free(target); - free(url); + NPError error = browser->posturl(obj->npp, url.get(), target.get(), pathString.UTF8Length, path.get(), TRUE); BOOLEAN_TO_NPVARIANT(error == NPERR_NO_ERROR, *result); return true; @@ -967,15 +974,14 @@ bool testWindowOpen(NPP npp) static bool testSetStatus(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result) { - char* message = 0; + std::unique_ptr<char[]> message; if (argCount && NPVARIANT_IS_STRING(args[0])) { NPString statusString = NPVARIANT_TO_STRING(args[0]); message = toCString(statusString); } - - browser->status(obj->npp, message); - free(message); + browser->status(obj->npp, message.get()); + return true; } diff --git a/Tools/DumpRenderTree/TestNetscapePlugIn/PluginTest.cpp b/Tools/DumpRenderTree/TestNetscapePlugIn/PluginTest.cpp index c2195c5b1..da78148d4 100644 --- a/Tools/DumpRenderTree/TestNetscapePlugIn/PluginTest.cpp +++ b/Tools/DumpRenderTree/TestNetscapePlugIn/PluginTest.cpp @@ -28,6 +28,9 @@ #include "PluginObject.h" #include <assert.h> #include <string.h> +#include <wtf/Platform.h> +#include <wtf/ExportMacros.h> +#include <wtf/Assertions.h> #if defined(XP_UNIX) || defined(ANDROID) #include <unistd.h> @@ -133,6 +136,11 @@ bool PluginTest::NPP_URLNotify(const char* url, NPReason, void* notifyData) return false; } +void PluginTest::NPP_URLRedirectNotify(const char*, int32_t, void* notifyData) +{ + NPN_URLRedirectResponse(notifyData, true); +} + NPError PluginTest::NPP_GetValue(NPPVariable variable, void *value) { // We don't know anything about plug-in values so just return NPERR_GENERIC_ERROR. @@ -156,6 +164,11 @@ NPError PluginTest::NPN_GetURLNotify(const char *url, const char *target, void * return browser->geturlnotify(m_npp, url, target, notifyData); } +NPError PluginTest::NPN_PostURLNotify(const char *url, const char *target, uint32_t len, const char* buf, NPBool file, void *notifyData) +{ + return browser->posturlnotify(m_npp, url, target, len, buf, file, notifyData); +} + NPError PluginTest::NPN_GetValue(NPNVariable variable, void* value) { return browser->getvalue(m_npp, variable, value); @@ -228,6 +241,11 @@ void PluginTest::NPN_ReleaseVariantValue(NPVariant* variant) browser->releasevariantvalue(variant); } +void PluginTest::NPN_URLRedirectResponse(void* notifyData, NPBool allow) +{ + browser->urlredirectresponse(m_npp, notifyData, allow); +} + #ifdef XP_MACOSX bool PluginTest::NPN_ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace) { @@ -254,6 +272,7 @@ void PluginTest::executeScript(const char* script) browser->releasevariantvalue(&browserResult); } +WTF_ATTRIBUTE_PRINTF(2, 3) void PluginTest::log(const char* format, ...) { va_list args; diff --git a/Tools/DumpRenderTree/TestNetscapePlugIn/PluginTest.h b/Tools/DumpRenderTree/TestNetscapePlugIn/PluginTest.h index f8a9aaee3..d7a5163ff 100644 --- a/Tools/DumpRenderTree/TestNetscapePlugIn/PluginTest.h +++ b/Tools/DumpRenderTree/TestNetscapePlugIn/PluginTest.h @@ -31,6 +31,10 @@ #include <map> #include <string> +#if defined(_MSC_VER) && _MSC_VER < 1900 +#define snprintf _snprintf +#endif + // Helper classes for implementing has_member typedef char (&no_tag)[1]; typedef char (&yes_tag)[2]; @@ -68,12 +72,14 @@ public: virtual int16_t NPP_HandleEvent(void* event); virtual bool NPP_URLNotify(const char* url, NPReason, void* notifyData); + virtual void NPP_URLRedirectNotify(const char* url, int32_t status, void* notifyData); virtual NPError NPP_GetValue(NPPVariable, void* value); virtual NPError NPP_SetValue(NPNVariable, void *value); // NPN functions. NPError NPN_GetURL(const char* url, const char* target); NPError NPN_GetURLNotify(const char* url, const char* target, void* notifyData); + NPError NPN_PostURLNotify(const char *url, const char *target, uint32_t len, const char* buf, NPBool file, void *notifyData); NPError NPN_GetValue(NPNVariable, void* value); void NPN_InvalidateRect(NPRect* invalidRect); bool NPN_Invoke(NPObject *, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result); @@ -91,6 +97,7 @@ public: void NPN_ReleaseObject(NPObject*); bool NPN_RemoveProperty(NPObject*, NPIdentifier propertyName); void NPN_ReleaseVariantValue(NPVariant*); + void NPN_URLRedirectResponse(void* notifyData, NPBool allow); #ifdef XP_MACOSX bool NPN_ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace); diff --git a/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/EvaluateJSWithinNPP_New.cpp b/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/EvaluateJSWithinNPP_New.cpp new file mode 100644 index 000000000..c066db59f --- /dev/null +++ b/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/EvaluateJSWithinNPP_New.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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. + */ + +#include "PluginTest.h" + +#include "PluginObject.h" + +using namespace std; + +// Executing JS within NPP_New when initializing asynchronously should not be able to deadlock with the WebProcess + +class EvaluteJSWithinNPP_New : public PluginTest { +public: + EvaluteJSWithinNPP_New(NPP, const string& identifier); + +private: + virtual NPError NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData *); + +}; + +EvaluteJSWithinNPP_New::EvaluteJSWithinNPP_New(NPP npp, const string& identifier) + : PluginTest(npp, identifier) +{ +} + +NPError EvaluteJSWithinNPP_New::NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData *saved) +{ + // Give the WebProcess enough time to be deadlocked waiting for the PluginProcess. + usleep(15000); + executeScript("var theLocation = window.location;"); + return NPERR_NO_ERROR; +} + +static PluginTest::Register<EvaluteJSWithinNPP_New> registrar("evalute-js-within-npp-new"); diff --git a/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/InvokeDestroysPluginWithinNPP_New.cpp b/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/InvokeDestroysPluginWithinNPP_New.cpp new file mode 100644 index 000000000..0e2dbdce7 --- /dev/null +++ b/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/InvokeDestroysPluginWithinNPP_New.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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. + */ + +#include "PluginTest.h" + +#include "PluginObject.h" + +using namespace std; + +// Executing JS within NPP_New when initializing asynchronously should not be able to deadlock with the WebProcess + +class InvokeDestroysPluginWithinNPP_New : public PluginTest { +public: + InvokeDestroysPluginWithinNPP_New(NPP, const string& identifier); + +private: + virtual NPError NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData *); + +}; + +InvokeDestroysPluginWithinNPP_New::InvokeDestroysPluginWithinNPP_New(NPP npp, const string& identifier) + : PluginTest(npp, identifier) +{ +} + +NPError InvokeDestroysPluginWithinNPP_New::NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData *saved) +{ + // Give the WebProcess enough time to be deadlocked waiting for the PluginProcess if things aren't working correctly. + usleep(15000); + + NPObject* windowObject = 0; + if (NPN_GetValue(NPNVWindowNPObject, &windowObject) != NPERR_NO_ERROR) + return NPERR_GENERIC_ERROR; + + if (!windowObject) + return NPERR_GENERIC_ERROR; + + NPVariant result; + if (!NPN_Invoke(windowObject, NPN_GetStringIdentifier("removePluginElement"), 0, 0, &result)) + return NPERR_GENERIC_ERROR; + + return NPERR_NO_ERROR; +} + +static PluginTest::Register<InvokeDestroysPluginWithinNPP_New> registrar("invoke-destroys-plugin-within-npp-new"); diff --git a/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/PluginScriptableObjectOverridesAllProperties.cpp b/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/PluginScriptableObjectOverridesAllProperties.cpp new file mode 100644 index 000000000..ca399a816 --- /dev/null +++ b/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/PluginScriptableObjectOverridesAllProperties.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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. + */ + +#include "PluginTest.h" + +#include <string.h> + +using namespace std; + +class PluginScriptableObjectOverridesAllProperties : public PluginTest { +public: + PluginScriptableObjectOverridesAllProperties(NPP npp, const string& identifier) + : PluginTest(npp, identifier) + { + } + +private: + class PluginObject : public Object<PluginObject> { + public: + PluginObject() + { + } + + ~PluginObject() + { + } + + bool hasProperty(NPIdentifier propertyName) + { + return true; + } + + bool getProperty(NPIdentifier propertyName, NPVariant* result) + { + static const char* message = "My name is "; + char* propertyString = pluginTest()->NPN_UTF8FromIdentifier(propertyName); + + int bufferLength = strlen(propertyString) + strlen(message) + 1; + char* resultBuffer = static_cast<char*>(pluginTest()->NPN_MemAlloc(bufferLength)); + snprintf(resultBuffer, bufferLength, "%s%s", message, propertyString); + + STRINGZ_TO_NPVARIANT(resultBuffer, *result); + + return true; + } + }; + + virtual NPError NPP_GetValue(NPPVariable variable, void *value) + { + if (variable != NPPVpluginScriptableNPObject) + return NPERR_GENERIC_ERROR; + + *(NPObject**)value = PluginObject::create(this); + + return NPERR_NO_ERROR; + } + +}; + +static PluginTest::Register<PluginScriptableObjectOverridesAllProperties> pluginScriptableObjectOverridesAllProperties("plugin-scriptable-object-overrides-all-properties"); diff --git a/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/SlowNPPNew.cpp b/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/SlowNPPNew.cpp new file mode 100644 index 000000000..8c80d55a5 --- /dev/null +++ b/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/SlowNPPNew.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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. + */ + +#include "PluginTest.h" + +#include <string.h> + +using namespace std; + +class SlowNPPNew : public PluginTest { +public: + SlowNPPNew(NPP npp, const string& identifier) + : PluginTest(npp, identifier) + { + } + +private: + class PluginObject : public Object<PluginObject> { + public: + PluginObject() + { + } + + ~PluginObject() + { + } + + bool hasProperty(NPIdentifier propertyName) + { + return true; + } + + bool getProperty(NPIdentifier propertyName, NPVariant* result) + { + static const char* message = "My name is "; + char* propertyString = pluginTest()->NPN_UTF8FromIdentifier(propertyName); + + int bufferLength = strlen(propertyString) + strlen(message) + 1; + char* resultBuffer = static_cast<char*>(pluginTest()->NPN_MemAlloc(bufferLength)); + snprintf(resultBuffer, bufferLength, "%s%s", message, propertyString); + + STRINGZ_TO_NPVARIANT(resultBuffer, *result); + + return true; + } + }; + + virtual NPError NPP_GetValue(NPPVariable variable, void *value) + { + if (variable != NPPVpluginScriptableNPObject) + return NPERR_GENERIC_ERROR; + + *(NPObject**)value = PluginObject::create(this); + + return NPERR_NO_ERROR; + } + + virtual NPError NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData *saved) + { + usleep(550000); + return NPERR_NO_ERROR; + } +}; + +static PluginTest::Register<SlowNPPNew> slowNPPNew("slow-npp-new"); diff --git a/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/URLRedirect.cpp b/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/URLRedirect.cpp new file mode 100644 index 000000000..b834703da --- /dev/null +++ b/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/URLRedirect.cpp @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2014 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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. + */ + +#include "PluginTest.h" + +#include <string.h> + +using namespace std; + +class URLRedirect : public PluginTest { +public: + URLRedirect(NPP npp, const string& identifier) + : PluginTest(npp, identifier) + { + } + + struct Redirect { + int redirectsRemaining; + bool async; + bool hasFired; + }; + + std::map<void*, Redirect> redirects; + +private: + // This is the test object. + class TestObject : public Object<TestObject> { }; + + // This is the scriptable object. It has a single "testObject" property and an "evaluate" function. + class ScriptableObject : public Object<ScriptableObject> { + public: + bool hasMethod(NPIdentifier methodName) + { + return identifierIs(methodName, "get") || identifierIs(methodName, "getAsync") || identifierIs(methodName, "serviceAsync"); + } + + bool get(const NPVariant* args, uint32_t argCount, NPVariant* result, bool async) + { + if (argCount != 3 || !NPVARIANT_IS_STRING(args[0]) || !(NPVARIANT_IS_BOOLEAN(args[1]) || NPVARIANT_IS_DOUBLE(args[1]) || NPVARIANT_IS_INT32(args[1])) || !NPVARIANT_IS_STRING(args[2])) + return false; + + const NPString* notifyString = &NPVARIANT_TO_STRING(args[2]); + basic_string<NPUTF8> notify(notifyString->UTF8Characters, notifyString->UTF8Length); + NPIdentifier notifyMethod = pluginTest()->NPN_GetStringIdentifier(notify.c_str()); + + Redirect& redirect = static_cast<URLRedirect*>(pluginTest())->redirects[reinterpret_cast<void*>(notifyMethod)]; + if (NPVARIANT_IS_DOUBLE(args[1])) + redirect.redirectsRemaining = NPVARIANT_TO_DOUBLE(args[1]); + else if (NPVARIANT_IS_INT32(args[1])) + redirect.redirectsRemaining = NPVARIANT_TO_INT32(args[1]); + else if (NPVARIANT_IS_BOOLEAN(args[1])) + redirect.redirectsRemaining = NPVARIANT_TO_BOOLEAN(args[1]); + redirect.async = async; + redirect.hasFired = true; + + const NPString* urlString = &NPVARIANT_TO_STRING(args[0]); + basic_string<NPUTF8> url(urlString->UTF8Characters, urlString->UTF8Length); + + pluginTest()->NPN_GetURLNotify(url.c_str(), 0, reinterpret_cast<void*>(notifyMethod)); + + VOID_TO_NPVARIANT(*result); + return true; + } + + bool serviceAsync(const NPVariant* args, uint32_t argCount, NPVariant* result) + { + if (argCount) + return false; + + NPBool seen = 0; + URLRedirect* plugin = static_cast<URLRedirect*>(pluginTest()); + for (auto& redirect : plugin->redirects) { + if (redirect.second.hasFired) + continue; + redirect.second.hasFired = true; + plugin->NPN_URLRedirectResponse(redirect.first, redirect.second.redirectsRemaining); + if (redirect.second.redirectsRemaining) + --redirect.second.redirectsRemaining; + seen = 1; + } + + BOOLEAN_TO_NPVARIANT(seen, *result); + return true; + } + + bool invoke(NPIdentifier methodName, const NPVariant* args, uint32_t argCount, NPVariant* result) + { + if (identifierIs(methodName, "get")) + return get(args, argCount, result, false); + + if (identifierIs(methodName, "getAsync")) + return get(args, argCount, result, true); + + if (identifierIs(methodName, "serviceAsync")) + return serviceAsync(args, argCount, result); + + return false; + } + }; + + virtual NPError NPP_GetValue(NPPVariable variable, void *value) + { + if (variable != NPPVpluginScriptableNPObject) + return NPERR_GENERIC_ERROR; + + *(NPObject**)value = ScriptableObject::create(this); + + return NPERR_NO_ERROR; + } + + virtual bool NPP_URLNotify(const char* url, NPReason reason, void* notifyData) + { + NPVariant args[2]; + + NPObject* windowScriptObject; + NPN_GetValue(NPNVWindowNPObject, &windowScriptObject); + + NPIdentifier callbackIdentifier = notifyData; + + INT32_TO_NPVARIANT(reason, args[0]); + STRINGZ_TO_NPVARIANT(url, args[1]); + + NPVariant browserResult; + if (NPN_Invoke(windowScriptObject, callbackIdentifier, args, 2, &browserResult)) + NPN_ReleaseVariantValue(&browserResult); + + return true; + } + + virtual void NPP_URLRedirectNotify(const char*, int32_t, void* notifyData) + { + Redirect& redirect = redirects[notifyData]; + if (redirect.async) { + redirect.hasFired = false; + return; + } + + NPN_URLRedirectResponse(notifyData, redirect.redirectsRemaining); + if (redirect.redirectsRemaining) + --redirect.redirectsRemaining; + } +}; + +static PluginTest::Register<URLRedirect> urlRedirect("url-redirect"); + diff --git a/Tools/DumpRenderTree/TestNetscapePlugIn/main.cpp b/Tools/DumpRenderTree/TestNetscapePlugIn/main.cpp index 85cd41d2c..ca9cec8ef 100644 --- a/Tools/DumpRenderTree/TestNetscapePlugIn/main.cpp +++ b/Tools/DumpRenderTree/TestNetscapePlugIn/main.cpp @@ -41,10 +41,17 @@ extern "C" void GlobalToLocal(Point*); using namespace std; +#if defined(__GNUC__) +#define CRASH() do { \ + *(int *)(uintptr_t)0xbbadbeef = 0; \ + __builtin_trap(); /* More reliable, but doesn't say BBADBEEF. */ \ +} while (false) +#else #define CRASH() do { \ *(int *)(uintptr_t)0xbbadbeef = 0; \ ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \ -} while(false) +} while (false) +#endif static bool getEntryPointsWasCalled; static bool initializeWasCalled; @@ -116,6 +123,7 @@ NPError STDCALL NP_GetEntryPoints(NPPluginFuncs *pluginFuncs) pluginFuncs->print = NPP_Print; pluginFuncs->event = NPP_HandleEvent; pluginFuncs->urlnotify = NPP_URLNotify; + pluginFuncs->urlredirectnotify = NPP_URLRedirectNotify; pluginFuncs->getvalue = NPP_GetValue; pluginFuncs->setvalue = NPP_SetValue; @@ -256,6 +264,8 @@ NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc #endif } else if (!strcasecmp(argn[i], "src") && strstr(argv[i], "plugin-document-has-focus.pl")) obj->testKeyboardFocusForPlugins = TRUE; + else if (!strcasecmp(argn[i], "src") && strstr(argv[i], "plugin-document-alert-and-notify-done.pl")) + executeScript(obj, "alert('Plugin Loaded!'); testRunner.notifyDone();"); else if (!strcasecmp(argn[i], "evaluatescript")) { char* script = argv[i]; if (script == strstr(script, "mouse::")) { @@ -348,29 +358,30 @@ NPError NPP_SetWindow(NPP instance, NPWindow *window) { PluginObject* obj = static_cast<PluginObject*>(instance->pdata); - if (obj) { - obj->lastWindow = *window; + if (!obj) + return NPERR_GENERIC_ERROR; - if (obj->logSetWindow) { - pluginLog(instance, "NPP_SetWindow: %d %d", (int)window->width, (int)window->height); - obj->logSetWindow = FALSE; - executeScript(obj, "testRunner.notifyDone();"); - } + obj->lastWindow = *window; - if (obj->onSetWindow) - executeScript(obj, obj->onSetWindow); + if (obj->logSetWindow) { + pluginLog(instance, "NPP_SetWindow: %d %d", (int)window->width, (int)window->height); + obj->logSetWindow = FALSE; + executeScript(obj, "testRunner.notifyDone();"); + } - if (obj->testWindowOpen) { - testWindowOpen(instance); - obj->testWindowOpen = FALSE; - } + if (obj->onSetWindow) + executeScript(obj, obj->onSetWindow); - if (obj->testKeyboardFocusForPlugins) { - obj->eventLogging = true; - executeScript(obj, "eventSender.keyDown('A');"); - } + if (obj->testWindowOpen) { + testWindowOpen(instance); + obj->testWindowOpen = FALSE; } - + + if (obj->testKeyboardFocusForPlugins) { + obj->eventLogging = true; + executeScript(obj, "eventSender.keyDown('A');"); + } + return obj->pluginTest->NPP_SetWindow(window); } @@ -799,6 +810,12 @@ void NPP_URLNotify(NPP instance, const char *url, NPReason reason, void *notifyD handleCallback(obj, url, reason, notifyData); } +void NPP_URLRedirectNotify(NPP instance, const char *url, int32_t status, void *notifyData) +{ + PluginObject* obj = static_cast<PluginObject*>(instance->pdata); + obj->pluginTest->NPP_URLRedirectNotify(url, status, notifyData); +} + NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) { #ifdef XP_UNIX diff --git a/Tools/DumpRenderTree/TestOptions.h b/Tools/DumpRenderTree/TestOptions.h new file mode 100644 index 000000000..0aeb02210 --- /dev/null +++ b/Tools/DumpRenderTree/TestOptions.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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. + */ + +#pragma once +#include "DumpRenderTree.h" + +@class NSURL; + +struct TestOptions { + bool enableIntersectionObserver { false }; + bool enableModernMediaControls { true }; + bool enablePointerLock { false }; + + TestOptions(NSURL*, const TestCommand&); +}; diff --git a/Tools/DumpRenderTree/TestRunner.cpp b/Tools/DumpRenderTree/TestRunner.cpp index 7b249770e..46b8df45e 100644 --- a/Tools/DumpRenderTree/TestRunner.cpp +++ b/Tools/DumpRenderTree/TestRunner.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008, 2009, 2011, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2007-2016 Apple Inc. All rights reserved. * Copyright (C) 2010 Joone Hur <joone@kldp.org> * * Redistribution and use in source and binary forms, with or without @@ -11,7 +11,7 @@ * 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 + * 3. Neither the name of Apple 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. * @@ -30,36 +30,50 @@ #include "config.h" #include "TestRunner.h" +#include "WebCoreTestSupport.h" #include "WorkQueue.h" #include "WorkQueueItem.h" #include <JavaScriptCore/APICast.h> -#include <JavaScriptCore/JSContextRef.h> +#include <JavaScriptCore/ArrayBufferView.h> +#include <JavaScriptCore/HeapInlines.h> +#include <JavaScriptCore/JSArrayBufferView.h> #include <JavaScriptCore/JSCTestRunnerUtils.h> +#include <JavaScriptCore/JSContextRef.h> #include <JavaScriptCore/JSObjectRef.h> #include <JavaScriptCore/JSRetainPtr.h> +#include <JavaScriptCore/TypedArrayInlines.h> +#include <JavaScriptCore/VMInlines.h> +#include <WebCore/LogInitialization.h> #include <cstring> #include <locale.h> -#include <runtime/ArrayBufferView.h> -#include <runtime/JSArrayBufferView.h> -#include <runtime/TypedArrayInlines.h> #include <stdio.h> #include <wtf/Assertions.h> #include <wtf/CurrentTime.h> +#include <wtf/LoggingAccumulator.h> #include <wtf/MathExtras.h> #include <wtf/RefPtr.h> +#include <wtf/RunLoop.h> #include <wtf/StdLibExtras.h> +#include <wtf/text/WTFString.h> + +#if PLATFORM(IOS) +#include <WebCore/WebCoreThreadRun.h> +#include <wtf/BlockPtr.h> +#endif #if PLATFORM(MAC) && !PLATFORM(IOS) #include <Carbon/Carbon.h> #endif +FILE* testResult = stdout; + const unsigned TestRunner::viewWidth = 800; const unsigned TestRunner::viewHeight = 600; const unsigned TestRunner::w3cSVGViewWidth = 480; const unsigned TestRunner::w3cSVGViewHeight = 360; -TestRunner::TestRunner(const std::string& testPathOrURL, const std::string& expectedPixelHash) +TestRunner::TestRunner(const std::string& testURL, const std::string& expectedPixelHash) : m_disallowIncreaseForApplicationCacheQuota(false) , m_dumpApplicationCacheDelegateCallbacks(false) , m_dumpAsAudio(false) @@ -81,7 +95,6 @@ TestRunner::TestRunner(const std::string& testPathOrURL, const std::string& expe , m_dumpSourceAsWebArchive(false) , m_dumpStatusCallbacks(false) , m_dumpTitleChanges(false) - , m_dumpIconChanges(false) , m_dumpVisitedLinksCallback(false) , m_dumpWillCacheResponse(false) , m_generatePixelResults(true) @@ -101,9 +114,9 @@ TestRunner::TestRunner(const std::string& testPathOrURL, const std::string& expe , m_globalFlag(false) , m_isGeolocationPermissionSet(false) , m_geolocationPermission(false) + , m_rejectsProtectionSpaceAndContinueForAuthenticationChallenges(false) , m_handlesAuthenticationChallenges(false) , m_isPrinting(false) - , m_deferMainResourceDataLoad(true) , m_useDeferredFrameLoading(false) , m_shouldPaintBrokenImage(true) , m_shouldStayOnPageAfterHandlingBeforeUnload(false) @@ -112,15 +125,16 @@ TestRunner::TestRunner(const std::string& testPathOrURL, const std::string& expe , m_hasPendingWebNotificationClick(false) , m_databaseDefaultQuota(-1) , m_databaseMaxQuota(-1) - , m_testPathOrURL(testPathOrURL) + , m_testURL(testURL) , m_expectedPixelHash(expectedPixelHash) , m_titleTextDirection("ltr") + , m_timeout(0) { } -PassRefPtr<TestRunner> TestRunner::create(const std::string& testPathOrURL, const std::string& expectedPixelHash) +Ref<TestRunner> TestRunner::create(const std::string& testURL, const std::string& expectedPixelHash) { - return adoptRef(new TestRunner(testPathOrURL, expectedPixelHash)); + return adoptRef(*new TestRunner(testURL, expectedPixelHash)); } // Static Functions @@ -262,13 +276,6 @@ static JSValueRef dumpTitleChangesCallback(JSContextRef context, JSObjectRef fun return JSValueMakeUndefined(context); } -static JSValueRef dumpIconChangesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); - controller->setDumpIconChanges(true); - return JSValueMakeUndefined(context); -} - static JSValueRef dumpWillCacheResponseCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); @@ -340,9 +347,12 @@ static JSValueRef setAudioResultCallback(JSContextRef context, JSObjectRef funct return JSValueMakeUndefined(context); // FIXME (123058): Use a JSC API to get buffer contents once such is exposed. - JSC::JSArrayBufferView* jsBufferView = JSC::jsDynamicCast<JSC::JSArrayBufferView*>(toJS(toJS(context), arguments[0])); + JSC::VM& vm = toJS(context)->vm(); + JSC::JSLockHolder lock(vm); + + JSC::JSArrayBufferView* jsBufferView = JSC::jsDynamicCast<JSC::JSArrayBufferView*>(vm, toJS(toJS(context), arguments[0])); ASSERT(jsBufferView); - RefPtr<JSC::ArrayBufferView> bufferView = jsBufferView->impl(); + RefPtr<JSC::ArrayBufferView> bufferView = jsBufferView->unsharedImpl(); const char* buffer = static_cast<const char*>(bufferView->baseAddress()); std::vector<char> audioData(buffer, buffer + bufferView->byteLength()); @@ -466,73 +476,6 @@ static JSValueRef clearAllDatabasesCallback(JSContextRef context, JSObjectRef fu return JSValueMakeUndefined(context); } -static JSValueRef syncLocalStorageCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); - - controller->syncLocalStorage(); - - return JSValueMakeUndefined(context); -} - -static JSValueRef observeStorageTrackerNotificationsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); - - if (argumentCount < 1) - return JSValueMakeUndefined(context); - - unsigned numNotifications = JSValueToNumber(context, arguments[0], exception); - - ASSERT(!*exception); - - controller->observeStorageTrackerNotifications(numNotifications); - - return JSValueMakeUndefined(context); -} - -static JSValueRef deleteAllLocalStorageCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); - controller->deleteAllLocalStorage(); - - return JSValueMakeUndefined(context); -} - -static JSValueRef deleteLocalStorageForOriginCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); - - if (argumentCount < 1) - return JSValueMakeUndefined(context); - - JSRetainPtr<JSStringRef> url(Adopt, JSValueToStringCopy(context, arguments[0], exception)); - ASSERT(!*exception); - - controller->deleteLocalStorageForOrigin(url.get()); - - return JSValueMakeUndefined(context); -} - -static JSValueRef localStorageDiskUsageForOriginCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); - - if (argumentCount < 1) - return JSValueMakeUndefined(context); - - JSRetainPtr<JSStringRef> originURL(Adopt, JSValueToStringCopy(context, arguments[0], exception)); - ASSERT(!*exception); - - return JSValueMakeNumber(context, controller->localStorageDiskUsageForOrigin(originURL.get())); -} - -static JSValueRef originsWithLocalStorageCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); - return controller->originsWithLocalStorage(context); -} - static JSValueRef clearBackForwardListCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { // Has mac & windows implementation @@ -712,6 +655,12 @@ static JSValueRef numberOfPendingGeolocationPermissionRequestsCallback(JSContext return JSValueMakeNumber(context, controller->numberOfPendingGeolocationPermissionRequests()); } +static JSValueRef isGeolocationProviderActiveCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); + return JSValueMakeBoolean(context, controller->isGeolocationProviderActive()); +} + static JSValueRef queueBackNavigationCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { // Has mac & windows implementation @@ -977,18 +926,6 @@ static JSValueRef setDatabaseQuotaCallback(JSContextRef context, JSObjectRef fun return JSValueMakeUndefined(context); } -static JSValueRef setDeferMainResourceDataLoadCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - // Has Mac and Windows implementation - if (argumentCount < 1) - return JSValueMakeUndefined(context); - - TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); - controller->setDeferMainResourceDataLoad(JSValueToBoolean(context, arguments[0])); - - return JSValueMakeUndefined(context); -} - static JSValueRef setDefersLoadingCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { if (argumentCount < 1) @@ -1104,38 +1041,6 @@ static JSValueRef setMockGeolocationPositionUnavailableErrorCallback(JSContextRe return JSValueMakeUndefined(context); } -static JSValueRef addMockSpeechInputResultCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - if (argumentCount < 3) - return JSValueMakeUndefined(context); - - JSRetainPtr<JSStringRef> result(Adopt, JSValueToStringCopy(context, arguments[0], exception)); - ASSERT(!*exception); - - double confidence = JSValueToNumber(context, arguments[1], exception); - - JSRetainPtr<JSStringRef> language(Adopt, JSValueToStringCopy(context, arguments[2], exception)); - ASSERT(!*exception); - - TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); - controller->addMockSpeechInputResult(result.get(), confidence, language.get()); - - return JSValueMakeUndefined(context); -} - -static JSValueRef setMockSpeechInputDumpRectCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - if (argumentCount < 1) - return JSValueMakeUndefined(context); - - bool dumpRect = JSValueToBoolean(context, arguments[0]); - - TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); - controller->setMockSpeechInputDumpRect(dumpRect); - - return JSValueMakeUndefined(context); -} - static JSValueRef setNewWindowsCopyBackForwardListCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { // Has mac implementation @@ -1160,6 +1065,18 @@ static JSValueRef setGeolocationPermissionCallback(JSContextRef context, JSObjec return JSValueMakeUndefined(context); } +static JSValueRef setRejectsProtectionSpaceAndContinueForAuthenticationChallengesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac & windows implementation + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); + controller->setRejectsProtectionSpaceAndContinueForAuthenticationChallenges(JSValueToBoolean(context, arguments[0])); + + return JSValueMakeUndefined(context); +} + static JSValueRef setHandlesAuthenticationChallengesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { // Has mac & windows implementation @@ -1279,6 +1196,15 @@ static JSValueRef setPrintingCallback(JSContextRef context, JSObjectRef function return JSValueMakeUndefined(context); } +static JSValueRef setAllowsAnySSLCertificateCallback(JSContextRef context, JSObjectRef, JSObjectRef, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + bool allowAnyCertificate = false; + if (argumentCount == 1) + allowAnyCertificate = JSValueToBoolean(context, arguments[0]); + + TestRunner::setAllowsAnySSLCertificate(allowAnyCertificate); + return JSValueMakeUndefined(context); +} static JSValueRef setAllowUniversalAccessFromFileURLsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { @@ -1304,6 +1230,18 @@ static JSValueRef setAllowFileAccessFromFileURLsCallback(JSContextRef context, J return JSValueMakeUndefined(context); } +static JSValueRef setNeedsStorageAccessFromFileURLsQuirkCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac & windows implementation + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); + controller->setNeedsStorageAccessFromFileURLsQuirk(JSValueToBoolean(context, arguments[0])); + + return JSValueMakeUndefined(context); +} + static JSValueRef setTabKeyCyclesThroughElementsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { // Has mac & windows implementation @@ -1340,19 +1278,6 @@ static JSValueRef setPagePausedCallback(JSContextRef context, JSObjectRef functi } #endif -#if ENABLE(IOS_TEXT_AUTOSIZING) -static JSValueRef setTextAutosizingEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - if (argumentCount < 1) - return JSValueMakeUndefined(context); - - TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); - controller->setTextAutosizingEnabled(JSValueToBoolean(context, arguments[0])); - - return JSValueMakeUndefined(context); -} -#endif - static JSValueRef setUseDashboardCompatibilityModeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { // Has mac implementation @@ -1477,6 +1402,22 @@ static JSValueRef setWindowIsKeyCallback(JSContextRef context, JSObjectRef funct return JSValueMakeUndefined(context); } +static JSValueRef setViewSizeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + if (argumentCount < 2) + return JSValueMakeUndefined(context); + + double width = JSValueToNumber(context, arguments[0], exception); + ASSERT(!*exception); + double height = JSValueToNumber(context, arguments[1], exception); + ASSERT(!*exception); + + TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); + controller->setViewSize(width, height); + + return JSValueMakeUndefined(context); +} + static JSValueRef waitUntilDoneCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { // Has mac & windows implementation @@ -1579,12 +1520,10 @@ static JSValueRef closeWebInspectorCallback(JSContextRef context, JSObjectRef fu static JSValueRef evaluateInWebInspectorCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); - double callId = JSValueToNumber(context, arguments[0], exception); - ASSERT(!*exception); - JSRetainPtr<JSStringRef> script(Adopt, JSValueToStringCopy(context, arguments[1], exception)); + JSRetainPtr<JSStringRef> script(Adopt, JSValueToStringCopy(context, arguments[0], exception)); ASSERT(!*exception); - controller->evaluateInWebInspector(static_cast<long>(callId), script.get()); + controller->evaluateInWebInspector(script.get()); return JSValueMakeUndefined(context); } @@ -1842,8 +1781,31 @@ static JSValueRef preciseTimeCallback(JSContextRef context, JSObjectRef, JSObjec return JSValueMakeNumber(context, WTF::currentTime()); } +static JSValueRef imageCountInGeneralPasteboardCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + // Has mac & windows implementation + TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); + + return JSValueMakeNumber(context, controller->imageCountInGeneralPasteboard()); +} + +static JSValueRef setSpellCheckerLoggingEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + if (argumentCount < 1) + return JSValueMakeUndefined(context); + TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); + controller->setSpellCheckerLoggingEnabled(JSValueToBoolean(context, arguments[0])); + return JSValueMakeUndefined(context); +} + // Static Values +static JSValueRef getTimeoutCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) +{ + TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); + return JSValueMakeNumber(context, controller->timeout()); +} + static JSValueRef getGlobalFlagCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) { TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); @@ -1884,6 +1846,13 @@ static JSValueRef getTitleTextDirectionCallback(JSContextRef context, JSObjectRe return JSValueMakeString(context, titleDirection.get()); } +static JSValueRef getInspectorTestStubURLCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) +{ + TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); + JSRetainPtr<JSStringRef> url(Adopt, controller->inspectorTestStubURL()); + return JSValueMakeString(context, url.get()); +} + static bool setGlobalFlagCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef value, JSValueRef* exception) { TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); @@ -2020,11 +1989,16 @@ static JSValueRef simulateWebNotificationClickCallback(JSContextRef context, JSO return JSValueMakeUndefined(context); } -static JSValueRef numberOfDFGCompiles(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +static JSValueRef failNextNewCodeBlock(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { if (argumentCount < 1) return JSValueMakeUndefined(context); + return JSC::failNextNewCodeBlock(context); +} + +static JSValueRef numberOfDFGCompiles(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ return JSC::numberOfDFGCompiles(context, arguments[0]); } @@ -2036,6 +2010,34 @@ static JSValueRef neverInlineFunction(JSContextRef context, JSObjectRef function return JSC::setNeverInline(context, arguments[0]); } +static JSValueRef accummulateLogsForChannel(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + JSRetainPtr<JSStringRef> channel(Adopt, JSValueToStringCopy(context, arguments[0], exception)); + ASSERT(!*exception); + + TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); + controller->setAccummulateLogsForChannel(channel.get()); + + return JSValueMakeUndefined(context); +} + +static JSValueRef runUIScriptCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + if (argumentCount < 1) + return JSValueMakeUndefined(context); + + JSRetainPtr<JSStringRef> script = argumentCount > 0 ? JSRetainPtr<JSStringRef>(Adopt, JSValueToStringCopy(context, arguments[0], 0)) : JSRetainPtr<JSStringRef>(); + JSValueRef callback = argumentCount > 1 ? arguments[1] : JSValueMakeUndefined(context); + + TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject)); + controller->runUIScript(context, script.get(), callback); + + return JSValueMakeUndefined(context); +} + static void testRunnerObjectFinalize(JSObjectRef object) { TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(object)); @@ -2071,12 +2073,14 @@ JSClassRef TestRunner::getJSClass() JSStaticValue* TestRunner::staticValues() { static JSStaticValue staticValues[] = { + { "timeout", getTimeoutCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "globalFlag", getGlobalFlagCallback, setGlobalFlagCallback, kJSPropertyAttributeNone }, { "webHistoryItemCount", getWebHistoryItemCountCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "secureEventInputIsEnabled", getSecureEventInputIsEnabledCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "titleTextDirection", getTitleTextDirectionCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "databaseDefaultQuota", getDatabaseDefaultQuotaCallback, setDatabaseDefaultQuotaCallback, kJSPropertyAttributeNone }, { "databaseMaxQuota", getDatabaseMaxQuotaCallback, setDatabaseMaxQuotaCallback, kJSPropertyAttributeNone }, + { "inspectorTestStubURL", getInspectorTestStubURLCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { 0, 0, 0, 0 } }; return staticValues; @@ -2122,7 +2126,6 @@ JSStaticFunction* TestRunner::staticFunctions() { "dumpSourceAsWebArchive", dumpSourceAsWebArchiveCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "dumpStatusCallbacks", dumpStatusCallbacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "dumpTitleChanges", dumpTitleChangesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "dumpIconChanges", dumpIconChangesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "dumpWillCacheResponse", dumpWillCacheResponseCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "encodeHostName", encodeHostNameCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "evaluateInWebInspector", evaluateInWebInspectorCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, @@ -2133,6 +2136,7 @@ JSStaticFunction* TestRunner::staticFunctions() { "originsWithApplicationCache", originsWithApplicationCacheCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "goBack", goBackCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "ignoreLegacyWebNotificationPermissionRequests", ignoreLegacyWebNotificationPermissionRequestsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "isGeolocationProviderActive", isGeolocationProviderActiveCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "isCommandEnabled", isCommandEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "keepWebHistory", keepWebHistoryCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "numberOfPendingGeolocationPermissionRequests", numberOfPendingGeolocationPermissionRequestsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, @@ -2154,6 +2158,8 @@ JSStaticFunction* TestRunner::staticFunctions() { "setAcceptsEditing", setAcceptsEditingCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setAllowUniversalAccessFromFileURLs", setAllowUniversalAccessFromFileURLsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setAllowFileAccessFromFileURLs", setAllowFileAccessFromFileURLsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setNeedsStorageAccessFromFileURLsQuirk", setNeedsStorageAccessFromFileURLsQuirkCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setAllowsAnySSLCertificate", setAllowsAnySSLCertificateCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setAlwaysAcceptCookies", setAlwaysAcceptCookiesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setAppCacheMaximumSize", setAppCacheMaximumSizeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setAudioResult", setAudioResultCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, @@ -2166,11 +2172,11 @@ JSStaticFunction* TestRunner::staticFunctions() { "setCloseRemainingWindowsWhenComplete", setCloseRemainingWindowsWhenCompleteCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setCustomPolicyDelegate", setCustomPolicyDelegateCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setDatabaseQuota", setDatabaseQuotaCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "setDeferMainResourceDataLoad", setDeferMainResourceDataLoadCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setDefersLoading", setDefersLoadingCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setUseDeferredFrameLoading", setUseDeferredFrameLoadingCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setDomainRelaxationForbiddenForURLScheme", setDomainRelaxationForbiddenForURLSchemeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setGeolocationPermission", setGeolocationPermissionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setRejectsProtectionSpaceAndContinueForAuthenticationChallenges", setRejectsProtectionSpaceAndContinueForAuthenticationChallengesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setHandlesAuthenticationChallenges", setHandlesAuthenticationChallengesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setIconDatabaseEnabled", setIconDatabaseEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setAutomaticLinkDetectionEnabled", setAutomaticLinkDetectionEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, @@ -2178,8 +2184,6 @@ JSStaticFunction* TestRunner::staticFunctions() { "setMockDeviceOrientation", setMockDeviceOrientationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setMockGeolocationPositionUnavailableError", setMockGeolocationPositionUnavailableErrorCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setMockGeolocationPosition", setMockGeolocationPositionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "addMockSpeechInputResult", addMockSpeechInputResultCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "setMockSpeechInputDumpRect", setMockSpeechInputDumpRectCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setNewWindowsCopyBackForwardList", setNewWindowsCopyBackForwardListCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setPageVisibility", setPageVisibilityCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setPOSIXLocale", setPOSIXLocaleCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, @@ -2196,9 +2200,6 @@ JSStaticFunction* TestRunner::staticFunctions() { "setTelephoneNumberParsingEnabled", setTelephoneNumberParsingEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setPagePaused", setPagePausedCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, #endif -#if ENABLE(IOS_TEXT_AUTOSIZING) - { "setTextAutosizingEnabled", setTextAutosizingEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, -#endif { "setUseDashboardCompatibilityMode", setUseDashboardCompatibilityModeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setUserStyleSheetEnabled", setUserStyleSheetEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setUserStyleSheetLocation", setUserStyleSheetLocationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, @@ -2209,6 +2210,7 @@ JSStaticFunction* TestRunner::staticFunctions() { "setWillSendRequestReturnsNull", setWillSendRequestReturnsNullCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setWillSendRequestReturnsNullOnRedirect", setWillSendRequestReturnsNullOnRedirectCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setWindowIsKey", setWindowIsKeyCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setViewSize", setViewSizeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setJavaScriptCanAccessClipboard", setJavaScriptCanAccessClipboardCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setXSSAuditorEnabled", setXSSAuditorEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "showWebInspector", showWebInspectorCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, @@ -2221,12 +2223,6 @@ JSStaticFunction* TestRunner::staticFunctions() { "addOriginAccessWhitelistEntry", addOriginAccessWhitelistEntryCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setScrollbarPolicy", setScrollbarPolicyCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "authenticateSession", authenticateSessionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "deleteAllLocalStorage", deleteAllLocalStorageCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "syncLocalStorage", syncLocalStorageCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "observeStorageTrackerNotifications", observeStorageTrackerNotificationsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "deleteLocalStorageForOrigin", deleteLocalStorageForOriginCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "localStorageDiskUsageForOrigin", localStorageDiskUsageForOriginCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "originsWithLocalStorage", originsWithLocalStorageCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setShouldPaintBrokenImage", setShouldPaintBrokenImageCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setTextDirection", setTextDirectionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "setShouldStayOnPageAfterHandlingBeforeUnload", setShouldStayOnPageAfterHandlingBeforeUnloadCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, @@ -2242,8 +2238,13 @@ JSStaticFunction* TestRunner::staticFunctions() { "denyWebNotificationPermission", denyWebNotificationPermissionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "removeAllWebNotificationPermissions", removeAllWebNotificationPermissionsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "simulateWebNotificationClick", simulateWebNotificationClickCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "failNextNewCodeBlock", failNextNewCodeBlock, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "numberOfDFGCompiles", numberOfDFGCompiles, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { "neverInlineFunction", neverInlineFunction, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "accummulateLogsForChannel", accummulateLogsForChannel, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "runUIScript", runUIScriptCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "imageCountInGeneralPasteboard", imageCountInGeneralPasteboardCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { "setSpellCheckerLoggingEnabled", setSpellCheckerLoggingEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, { 0, 0, 0 } }; @@ -2252,37 +2253,37 @@ JSStaticFunction* TestRunner::staticFunctions() void TestRunner::queueLoadHTMLString(JSStringRef content, JSStringRef baseURL) { - WorkQueue::shared()->queue(new LoadHTMLStringItem(content, baseURL)); + WorkQueue::singleton().queue(new LoadHTMLStringItem(content, baseURL)); } void TestRunner::queueLoadAlternateHTMLString(JSStringRef content, JSStringRef baseURL, JSStringRef unreachableURL) { - WorkQueue::shared()->queue(new LoadHTMLStringItem(content, baseURL, unreachableURL)); + WorkQueue::singleton().queue(new LoadHTMLStringItem(content, baseURL, unreachableURL)); } void TestRunner::queueBackNavigation(int howFarBack) { - WorkQueue::shared()->queue(new BackItem(howFarBack)); + WorkQueue::singleton().queue(new BackItem(howFarBack)); } void TestRunner::queueForwardNavigation(int howFarForward) { - WorkQueue::shared()->queue(new ForwardItem(howFarForward)); + WorkQueue::singleton().queue(new ForwardItem(howFarForward)); } void TestRunner::queueLoadingScript(JSStringRef script) { - WorkQueue::shared()->queue(new LoadingScriptItem(script)); + WorkQueue::singleton().queue(new LoadingScriptItem(script)); } void TestRunner::queueNonLoadingScript(JSStringRef script) { - WorkQueue::shared()->queue(new NonLoadingScriptItem(script)); + WorkQueue::singleton().queue(new NonLoadingScriptItem(script)); } void TestRunner::queueReload() { - WorkQueue::shared()->queue(new ReloadItem); + WorkQueue::singleton().queue(new ReloadItem); } void TestRunner::ignoreLegacyWebNotificationPermissionRequests() @@ -2293,8 +2294,14 @@ void TestRunner::ignoreLegacyWebNotificationPermissionRequests() void TestRunner::waitToDumpWatchdogTimerFired() { const char* message = "FAIL: Timed out waiting for notifyDone to be called\n"; - fprintf(stderr, "%s", message); - fprintf(stdout, "%s", message); + fprintf(testResult, "%s", message); + + auto accumulatedLogs = getAndResetAccumulatedLogs(); + if (!accumulatedLogs.isEmpty()) { + const char* message = "Logs accumulated during test run:\n"; + fprintf(testResult, "%s%s\n", message, accumulatedLogs.utf8().data()); + } + notifyDone(); } @@ -2325,3 +2332,118 @@ void TestRunner::setShouldPaintBrokenImage(bool shouldPaintBrokenImage) { m_shouldPaintBrokenImage = shouldPaintBrokenImage; } + +void TestRunner::setAccummulateLogsForChannel(JSStringRef channel) +{ + size_t maxLength = JSStringGetMaximumUTF8CStringSize(channel); + auto buffer = std::make_unique<char[]>(maxLength + 1); + JSStringGetUTF8CString(channel, buffer.get(), maxLength + 1); + + WebCoreTestSupport::setLogChannelToAccumulate({ buffer.get() }); +} + +typedef WTF::HashMap<unsigned, JSValueRef> CallbackMap; +static CallbackMap& callbackMap() +{ + static CallbackMap& map = *new CallbackMap; + return map; +} + +void TestRunner::cacheTestRunnerCallback(unsigned index, JSValueRef callback) +{ + if (!callback) + return; + + if (callbackMap().contains(index)) { + fprintf(stderr, "FAIL: Tried to install a second TestRunner callback for the same event (id %d)\n", index); + return; + } + + JSContextRef context = mainFrameJSContext(); + JSValueProtect(context, callback); + callbackMap().add(index, callback); +} + +void TestRunner::callTestRunnerCallback(unsigned index, size_t argumentCount, const JSValueRef arguments[]) +{ + if (!callbackMap().contains(index)) + return; + + JSContextRef context = mainFrameJSContext(); + if (JSObjectRef callback = JSValueToObject(context, callbackMap().take(index), 0)) { + JSObjectCallAsFunction(context, callback, JSContextGetGlobalObject(context), argumentCount, arguments, 0); + JSValueUnprotect(context, callback); + } +} + +void TestRunner::clearTestRunnerCallbacks() +{ + JSContextRef context = mainFrameJSContext(); + + for (auto& iter : callbackMap()) { + if (JSObjectRef callback = JSValueToObject(context, iter.value, 0)) + JSValueUnprotect(context, callback); + } + + callbackMap().clear(); +} + +enum { + FirstUIScriptCallbackID = 100 +}; + +static unsigned nextUIScriptCallbackID() +{ + static unsigned callbackID = FirstUIScriptCallbackID; + return callbackID++; +} + +void TestRunner::runUIScript(JSContextRef context, JSStringRef script, JSValueRef callback) +{ + m_pendingUIScriptInvocationData = nullptr; + + unsigned callbackID = nextUIScriptCallbackID(); + cacheTestRunnerCallback(callbackID, callback); + + if (!m_UIScriptContext) + m_UIScriptContext = std::make_unique<WTR::UIScriptContext>(*this); + + String scriptString(JSStringGetCharactersPtr(script), JSStringGetLength(script)); + m_UIScriptContext->runUIScript(scriptString, callbackID); +} + +void TestRunner::callUIScriptCallback(unsigned callbackID, JSStringRef result) +{ + JSRetainPtr<JSStringRef> protectedResult(result); +#if !PLATFORM(IOS) + RunLoop::main().dispatch([protectedThis = makeRef(*this), callbackID, protectedResult]() mutable { + JSContextRef context = protectedThis->mainFrameJSContext(); + JSValueRef resultValue = JSValueMakeString(context, protectedResult.get()); + protectedThis->callTestRunnerCallback(callbackID, 1, &resultValue); + }); +#else + WebThreadRun( + BlockPtr<void()>::fromCallable([protectedThis = makeRef(*this), callbackID, protectedResult] { + JSContextRef context = protectedThis->mainFrameJSContext(); + JSValueRef resultValue = JSValueMakeString(context, protectedResult.get()); + protectedThis->callTestRunnerCallback(callbackID, 1, &resultValue); + }).get() + ); +#endif +} + +void TestRunner::uiScriptDidComplete(const String& result, unsigned callbackID) +{ + JSRetainPtr<JSStringRef> stringRef(Adopt, JSStringCreateWithUTF8CString(result.utf8().data())); + callUIScriptCallback(callbackID, stringRef.get()); +} + +void TestRunner::setAllowsAnySSLCertificate(bool allowsAnySSLCertificate) +{ + WebCoreTestSupport::setAllowsAnySSLCertificate(allowsAnySSLCertificate); +} + +void TestRunner::cleanup() +{ + clearTestRunnerCallbacks(); +} diff --git a/Tools/DumpRenderTree/TestRunner.h b/Tools/DumpRenderTree/TestRunner.h index 882c0e96c..57c401003 100644 --- a/Tools/DumpRenderTree/TestRunner.h +++ b/Tools/DumpRenderTree/TestRunner.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008, 2009, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2007-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,7 +10,7 @@ * 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 + * 3. Neither the name of Apple 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. * @@ -25,21 +25,23 @@ * (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 TestRunner_h -#define TestRunner_h +#pragma once + +#include "UIScriptContext.h" #include <JavaScriptCore/JSObjectRef.h> #include <map> #include <set> #include <string> #include <vector> -#include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> -class TestRunner : public RefCounted<TestRunner> { +extern FILE* testResult; + +class TestRunner : public WTR::UIScriptContextDelegate, public RefCounted<TestRunner> { + WTF_MAKE_NONCOPYABLE(TestRunner); public: - static PassRefPtr<TestRunner> create(const std::string& testPathOrURL, const std::string& expectedPixelHash); + static Ref<TestRunner> create(const std::string& testURL, const std::string& expectedPixelHash); static const unsigned viewWidth; static const unsigned viewHeight; @@ -47,11 +49,15 @@ public: static const unsigned w3cSVGViewWidth; static const unsigned w3cSVGViewHeight; - ~TestRunner(); + virtual ~TestRunner(); + + void cleanup(); void makeWindowObject(JSContextRef, JSObjectRef windowObject, JSValueRef* exception); void addDisallowedURL(JSStringRef url); + const std::set<std::string>& allowedHosts() const { return m_allowedHosts; } + void setAllowedHosts(std::set<std::string> hosts) { m_allowedHosts = WTFMove(hosts); } void addURLToRedirect(std::string origin, std::string destination); const std::string& redirectionDestinationForURL(std::string); void clearAllApplicationCaches(); @@ -74,6 +80,7 @@ public: void keepWebHistory(); void notifyDone(); int numberOfPendingGeolocationPermissionRequests(); + bool isGeolocationProviderActive(); void overridePreference(JSStringRef key, JSStringRef value); JSStringRef pathToLocalResource(JSContextRef, JSStringRef url); void queueBackNavigation(int howFarBackward); @@ -86,8 +93,10 @@ public: void queueReload(); void removeAllVisitedLinks(); void setAcceptsEditing(bool); + void setFetchAPIEnabled(bool); void setAllowUniversalAccessFromFileURLs(bool); void setAllowFileAccessFromFileURLs(bool); + void setNeedsStorageAccessFromFileURLsQuirk(bool); void setAppCacheMaximumSize(unsigned long long quota); void setAuthorAndUserStylesEnabled(bool); void setCacheModel(int); @@ -102,8 +111,6 @@ public: void setMockDeviceOrientation(bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma); void setMockGeolocationPosition(double latitude, double longitude, double accuracy, bool providesAltitude, double altitude, bool providesAltitudeAccuracy, double altitudeAccuracy, bool providesHeading, double heading, bool providesSpeed, double speed); void setMockGeolocationPositionUnavailableError(JSStringRef message); - void addMockSpeechInputResult(JSStringRef result, double confidence, JSStringRef language); - void setMockSpeechInputDumpRect(bool flag); void setPersistentUserStyleSheetLocation(JSStringRef path); void setPluginsEnabled(bool); void setPopupBlockingEnabled(bool); @@ -117,7 +124,6 @@ public: void setXSSAuditorEnabled(bool flag); void setSpatialNavigationEnabled(bool); void setScrollbarPolicy(JSStringRef orientation, JSStringRef policy); - void startSpeechInput(JSContextRef inputElement); #if PLATFORM(IOS) void setTelephoneNumberParsingEnabled(bool enable); void setPagePaused(bool paused); @@ -126,14 +132,20 @@ public: void setPageVisibility(const char*); void resetPageVisibility(); + static void setAllowsAnySSLCertificate(bool); + void waitForPolicyDelegate(); size_t webHistoryItemCount(); int windowCount(); -#if ENABLE(IOS_TEXT_AUTOSIZING) +#if ENABLE(TEXT_AUTOSIZING) void setTextAutosizingEnabled(bool); #endif + void setAccummulateLogsForChannel(JSStringRef); + + void runUIScript(JSContextRef, JSStringRef, JSValueRef callback); + // Legacy here refers to the old TestRunner API for handling web notifications, not the legacy web notification API. void ignoreLegacyWebNotificationPermissionRequests(); // Legacy here refers to the old TestRunner API for handling web notifications, not the legacy web notification API. @@ -209,9 +221,6 @@ public: bool dumpTitleChanges() const { return m_dumpTitleChanges; } void setDumpTitleChanges(bool dumpTitleChanges) { m_dumpTitleChanges = dumpTitleChanges; } - bool dumpIconChanges() const { return m_dumpIconChanges; } - void setDumpIconChanges(bool dumpIconChanges) { m_dumpIconChanges = dumpIconChanges; } - bool dumpVisitedLinksCallback() const { return m_dumpVisitedLinksCallback; } void setDumpVisitedLinksCallback(bool dumpVisitedLinksCallback) { m_dumpVisitedLinksCallback = dumpVisitedLinksCallback; } @@ -258,9 +267,14 @@ public: bool windowIsKey() const { return m_windowIsKey; } void setWindowIsKey(bool); + void setViewSize(double width, double height); + bool alwaysAcceptCookies() const { return m_alwaysAcceptCookies; } void setAlwaysAcceptCookies(bool); + bool rejectsProtectionSpaceAndContinueForAuthenticationChallenges() const { return m_rejectsProtectionSpaceAndContinueForAuthenticationChallenges; } + void setRejectsProtectionSpaceAndContinueForAuthenticationChallenges(bool value) { m_rejectsProtectionSpaceAndContinueForAuthenticationChallenges = value; } + bool handlesAuthenticationChallenges() const { return m_handlesAuthenticationChallenges; } void setHandlesAuthenticationChallenges(bool handlesAuthenticationChallenges) { m_handlesAuthenticationChallenges = handlesAuthenticationChallenges; } @@ -282,13 +296,10 @@ public: double databaseMaxQuota() const { return m_databaseMaxQuota; } void setDatabaseMaxQuota(double quota) { m_databaseMaxQuota = quota; } - bool deferMainResourceDataLoad() const { return m_deferMainResourceDataLoad; } - void setDeferMainResourceDataLoad(bool flag) { m_deferMainResourceDataLoad = flag; } - bool useDeferredFrameLoading() const { return m_useDeferredFrameLoading; } void setUseDeferredFrameLoading(bool flag) { m_useDeferredFrameLoading = flag; } - const std::string& testPathOrURL() const { return m_testPathOrURL; } + const std::string& testURL() const { return m_testURL; } const std::string& expectedPixelHash() const { return m_expectedPixelHash; } const std::vector<char>& audioResult() const { return m_audioResult; } @@ -307,7 +318,9 @@ public: void setDeveloperExtrasEnabled(bool); void showWebInspector(); void closeWebInspector(); - void evaluateInWebInspector(long callId, JSStringRef script); + void evaluateInWebInspector(JSStringRef script); + JSStringRef inspectorTestStubURL(); + void evaluateScriptInIsolatedWorld(unsigned worldID, JSObjectRef globalObject, JSStringRef script); void evaluateScriptInIsolatedWorldAndReturnValue(unsigned worldID, JSObjectRef globalObject, JSStringRef script); @@ -336,13 +349,6 @@ public: // Simulate a request an embedding application could make, populating per-session credential storage. void authenticateSession(JSStringRef url, JSStringRef username, JSStringRef password); - JSValueRef originsWithLocalStorage(JSContextRef); - void deleteAllLocalStorage(); - void deleteLocalStorageForOrigin(JSStringRef originIdentifier); - long long localStorageDiskUsageForOrigin(JSStringRef originIdentifier); - void observeStorageTrackerNotifications(unsigned number); - void syncLocalStorage(); - void setShouldPaintBrokenImage(bool); bool shouldPaintBrokenImage() const { return m_shouldPaintBrokenImage; } @@ -359,8 +365,29 @@ public: bool hasPendingWebNotificationClick() const { return m_hasPendingWebNotificationClick; } + void setCustomTimeout(int duration) { m_timeout = duration; } + double timeout() { return m_timeout; } + + unsigned imageCountInGeneralPasteboard() const; + + void callUIScriptCallback(unsigned callbackID, JSStringRef result); + + void setDumpJSConsoleLogInStdErr(bool inStdErr) { m_dumpJSConsoleLogInStdErr = inStdErr; } + bool dumpJSConsoleLogInStdErr() const { return m_dumpJSConsoleLogInStdErr; } + + void setSpellCheckerLoggingEnabled(bool); + private: - TestRunner(const std::string& testPathOrURL, const std::string& expectedPixelHash); + TestRunner(const std::string& testURL, const std::string& expectedPixelHash); + + JSContextRef mainFrameJSContext(); + + // UIScriptContextDelegate + void uiScriptDidComplete(const String&, unsigned callbackID) override; + + void cacheTestRunnerCallback(unsigned index, JSValueRef); + void callTestRunnerCallback(unsigned index, size_t argumentCount = 0, const JSValueRef arguments[] = nullptr); + void clearTestRunnerCallbacks(); void setGeolocationPermissionCommon(bool allow); @@ -385,7 +412,6 @@ private: bool m_dumpSourceAsWebArchive; bool m_dumpStatusCallbacks; bool m_dumpTitleChanges; - bool m_dumpIconChanges; bool m_dumpVisitedLinksCallback; bool m_dumpWillCacheResponse; bool m_generatePixelResults; @@ -405,9 +431,9 @@ private: bool m_globalFlag; bool m_isGeolocationPermissionSet; bool m_geolocationPermission; + bool m_rejectsProtectionSpaceAndContinueForAuthenticationChallenges; bool m_handlesAuthenticationChallenges; bool m_isPrinting; - bool m_deferMainResourceDataLoad; bool m_useDeferredFrameLoading; bool m_shouldPaintBrokenImage; bool m_shouldStayOnPageAfterHandlingBeforeUnload; @@ -415,25 +441,35 @@ private: bool m_areLegacyWebNotificationPermissionRequestsIgnored; bool m_customFullScreenBehavior; bool m_hasPendingWebNotificationClick; + bool m_dumpJSConsoleLogInStdErr { false }; double m_databaseDefaultQuota; double m_databaseMaxQuota; std::string m_authenticationUsername; std::string m_authenticationPassword; - std::string m_testPathOrURL; + std::string m_testURL; std::string m_expectedPixelHash; // empty string if no hash std::string m_titleTextDirection; std::set<std::string> m_willSendRequestClearHeaders; + std::set<std::string> m_allowedHosts; std::vector<char> m_audioResult; std::map<std::string, std::string> m_URLsToRedirect; - + + struct UIScriptInvocationData { + unsigned callbackID; + String scriptString; + }; + + std::unique_ptr<WTR::UIScriptContext> m_UIScriptContext; + UIScriptInvocationData* m_pendingUIScriptInvocationData { nullptr }; + static JSClassRef getJSClass(); static JSStaticValue* staticValues(); static JSStaticFunction* staticFunctions(); -}; -#endif // TestRunner_h + int m_timeout; +}; diff --git a/Tools/DumpRenderTree/gtk/TextInputController.h b/Tools/DumpRenderTree/TextInputController.h index 53793f637..3472ee789 100644 --- a/Tools/DumpRenderTree/gtk/TextInputController.h +++ b/Tools/DumpRenderTree/TextInputController.h @@ -1,18 +1,18 @@ /* - * Copyright (C) 2011 Igalia S.L. + * Copyright (C) 2005, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * 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 + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple 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 @@ -26,12 +26,16 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef TextInputController_h -#define TextInputController_h +#import <Foundation/Foundation.h> -typedef const struct OpaqueJSContext* JSContextRef; -typedef struct OpaqueJSValue* JSObjectRef; +@class WebView; +@class WebHTMLView; +@class WebScriptObject; -JSObjectRef makeTextInputController(JSContextRef); - -#endif +@interface TextInputController : NSObject { + WebView *webView; + WebHTMLView *inputMethodView; + WebScriptObject *inputMethodHandler; +} +- (id)initWithWebView:(WebView *)view; +@end diff --git a/Tools/DumpRenderTree/WorkQueue.cpp b/Tools/DumpRenderTree/WorkQueue.cpp index 0106fbac1..097f4cdd2 100644 --- a/Tools/DumpRenderTree/WorkQueue.cpp +++ b/Tools/DumpRenderTree/WorkQueue.cpp @@ -10,7 +10,7 @@ * 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 + * 3. Neither the name of Apple 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. * @@ -31,6 +31,7 @@ #include "WorkQueueItem.h" #include <wtf/Assertions.h> +#include <wtf/NeverDestroyed.h> static const unsigned queueLength = 1024; @@ -38,9 +39,9 @@ static WorkQueueItem* theQueue[queueLength]; static unsigned startOfQueue; static unsigned endOfQueue; -WorkQueue* WorkQueue::shared() +WorkQueue& WorkQueue::singleton() { - static WorkQueue* sharedInstance = new WorkQueue; + static NeverDestroyed<WorkQueue> sharedInstance; return sharedInstance; } diff --git a/Tools/DumpRenderTree/WorkQueue.h b/Tools/DumpRenderTree/WorkQueue.h index 649c6c1f5..0697e7c3e 100644 --- a/Tools/DumpRenderTree/WorkQueue.h +++ b/Tools/DumpRenderTree/WorkQueue.h @@ -10,7 +10,7 @@ * 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 + * 3. Neither the name of Apple 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. * @@ -29,11 +29,15 @@ #ifndef WorkQueue_h #define WorkQueue_h +#include <wtf/Forward.h> + class WorkQueueItem; class WorkQueue { +friend class WTF::NeverDestroyed<WorkQueue>; + public: - static WorkQueue* shared(); + static WorkQueue& singleton(); void queue(WorkQueueItem*); WorkQueueItem* dequeue(); diff --git a/Tools/DumpRenderTree/WorkQueueItem.h b/Tools/DumpRenderTree/WorkQueueItem.h index 08fc2208b..6a49f593f 100644 --- a/Tools/DumpRenderTree/WorkQueueItem.h +++ b/Tools/DumpRenderTree/WorkQueueItem.h @@ -10,7 +10,7 @@ * 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 + * 3. Neither the name of Apple 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. * diff --git a/Tools/DumpRenderTree/atk/AccessibilityCallbacks.h b/Tools/DumpRenderTree/atk/AccessibilityCallbacks.h deleted file mode 100644 index 0feef55c8..000000000 --- a/Tools/DumpRenderTree/atk/AccessibilityCallbacks.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2011 Igalia S.L. - * - * 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. - */ - -#ifndef AccessibilityCallbacks_h -#define AccessibilityCallbacks_h - -#if HAVE(ACCESSIBILITY) - -#include "AccessibilityNotificationHandlerAtk.h" -#include "AccessibilityUIElement.h" - -void connectAccessibilityCallbacks(); -bool disconnectAccessibilityCallbacks(); -void addAccessibilityNotificationHandler(AccessibilityNotificationHandler*); -void removeAccessibilityNotificationHandler(AccessibilityNotificationHandler*); - -#endif // HAVE(ACCESSIBILITY) - -#endif // AccessibilityCallbacks_h diff --git a/Tools/DumpRenderTree/atk/AccessibilityCallbacksAtk.cpp b/Tools/DumpRenderTree/atk/AccessibilityCallbacksAtk.cpp deleted file mode 100644 index 01f6651b4..000000000 --- a/Tools/DumpRenderTree/atk/AccessibilityCallbacksAtk.cpp +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright (C) 2011 Igalia S.L. - * - * 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. - */ - -#include "config.h" -#include "AccessibilityCallbacks.h" - -#if HAVE(ACCESSIBILITY) - -#include "AccessibilityController.h" -#include "AccessibilityNotificationHandlerAtk.h" -#include "DumpRenderTree.h" -#include "JSRetainPtr.h" -#include <atk/atk.h> -#include <wtf/gobject/GUniquePtr.h> - -#if PLATFORM(GTK) -#include "WebCoreSupport/DumpRenderTreeSupportGtk.h" -#include <webkit/webkit.h> -#endif - -#if PLATFORM(EFL) -#include "DumpRenderTreeChrome.h" -#include "WebCoreSupport/DumpRenderTreeSupportEfl.h" -#endif - -typedef HashMap<PlatformUIElement, AccessibilityNotificationHandler*> NotificationHandlersMap; - -static guint stateChangeListenerId = 0; -static guint focusEventListenerId = 0; -static guint activeDescendantChangedListenerId = 0; -static guint childrenChangedListenerId = 0; -static guint propertyChangedListenerId = 0; -static guint visibleDataChangedListenerId = 0; -static guint loadCompleteListenerId = 0; -// Up to 2014 it was obligatory to mirror the changes from -// WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.cpp, -// but the habit has been dropped: https://bugs.webkit.org/show_bug.cgi?id=132527#c6 -static NotificationHandlersMap notificationHandlers; -static AccessibilityNotificationHandler* globalNotificationHandler = 0; - -extern bool loggingAccessibilityEvents; - -static void printAccessibilityEvent(AtkObject* accessible, const gchar* signalName, const gchar* signalValue) -{ - // Do not handle state-change:defunct signals, as the AtkObject - // associated to them will not be valid at this point already. - if (!signalName || !g_strcmp0(signalName, "state-change:defunct")) - return; - - if (!accessible || !ATK_IS_OBJECT(accessible)) - return; - - const gchar* objectName = atk_object_get_name(accessible); - AtkRole objectRole = atk_object_get_role(accessible); - - // Try to always provide a name to be logged for the object. - if (!objectName || *objectName == '\0') - objectName = "(No name)"; - - GUniquePtr<gchar> signalNameAndValue(signalValue ? g_strdup_printf("%s = %s", signalName, signalValue) : g_strdup(signalName)); - printf("Accessibility object emitted \"%s\" / Name: \"%s\" / Role: %d\n", signalNameAndValue.get(), objectName, objectRole); -} - -static gboolean axObjectEventListener(GSignalInvocationHint *signalHint, guint numParamValues, const GValue *paramValues, gpointer data) -{ - // At least we should receive the instance emitting the signal. - if (numParamValues < 1) - return true; - - AtkObject* accessible = ATK_OBJECT(g_value_get_object(¶mValues[0])); - if (!accessible || !ATK_IS_OBJECT(accessible)) - return true; - - GSignalQuery signalQuery; - GUniquePtr<gchar> signalName; - GUniquePtr<gchar> signalValue; - String notificationName; - - g_signal_query(signalHint->signal_id, &signalQuery); - - if (!g_strcmp0(signalQuery.signal_name, "state-change")) { - signalName.reset(g_strdup_printf("state-change:%s", g_value_get_string(¶mValues[1]))); - signalValue.reset(g_strdup_printf("%d", g_value_get_boolean(¶mValues[2]))); - if (!g_strcmp0(g_value_get_string(¶mValues[1]), "checked")) - notificationName = "CheckedStateChanged"; - else if (!g_strcmp0(g_value_get_string(¶mValues[1]), "invalid-entry")) - notificationName = "AXInvalidStatusChanged"; - } else if (!g_strcmp0(signalQuery.signal_name, "focus-event")) { - signalName.reset(g_strdup("focus-event")); - signalValue.reset(g_strdup_printf("%d", g_value_get_boolean(¶mValues[1]))); - if (g_value_get_boolean(¶mValues[1])) - notificationName = "AXFocusedUIElementChanged"; - } else if (!g_strcmp0(signalQuery.signal_name, "children-changed")) { - const gchar* childrenChangedDetail = g_quark_to_string(signalHint->detail); - signalName.reset(g_strdup_printf("children-changed:%s", childrenChangedDetail)); - signalValue.reset(g_strdup_printf("%d", g_value_get_uint(¶mValues[1]))); - notificationName = !g_strcmp0(childrenChangedDetail, "add") ? "AXChildrenAdded" : "AXChildrenRemoved"; - } else if (!g_strcmp0(signalQuery.signal_name, "property-change")) { - signalName.reset(g_strdup_printf("property-change:%s", g_quark_to_string(signalHint->detail))); - if (!g_strcmp0(g_quark_to_string(signalHint->detail), "accessible-value")) - notificationName = "AXValueChanged"; - } else if (!g_strcmp0(signalQuery.signal_name, "load-complete")) - notificationName = "AXLoadComplete"; - else - signalName.reset(g_strdup(signalQuery.signal_name)); - - if (loggingAccessibilityEvents) - printAccessibilityEvent(accessible, signalName.get(), signalValue.get()); - -#if PLATFORM(GTK) - JSGlobalContextRef jsContext = webkit_web_frame_get_global_context(mainFrame); -#elif PLATFORM(EFL) - JSGlobalContextRef jsContext = DumpRenderTreeSupportEfl::globalContextRefForFrame(browser->mainFrame()); -#else - JSContextRef jsContext = 0; -#endif - if (!jsContext) - return true; - - if (notificationName.length()) { - JSRetainPtr<JSStringRef> jsNotificationEventName(Adopt, JSStringCreateWithUTF8CString(notificationName.utf8().data())); - JSValueRef notificationNameArgument = JSValueMakeString(jsContext, jsNotificationEventName.get()); - NotificationHandlersMap::iterator elementNotificationHandler = notificationHandlers.find(accessible); - if (elementNotificationHandler != notificationHandlers.end()) { - // Listener for one element just gets one argument, the notification name. - JSObjectCallAsFunction(jsContext, elementNotificationHandler->value->notificationFunctionCallback(), 0, 1, ¬ificationNameArgument, 0); - } - - if (globalNotificationHandler) { - // A global listener gets the element and the notification name as arguments. - JSValueRef arguments[2]; - arguments[0] = AccessibilityUIElement::makeJSAccessibilityUIElement(jsContext, AccessibilityUIElement(accessible)); - arguments[1] = notificationNameArgument; - JSObjectCallAsFunction(jsContext, globalNotificationHandler->notificationFunctionCallback(), 0, 2, arguments, 0); - } - } - - return true; -} - -void connectAccessibilityCallbacks() -{ - // Ensure no callbacks are connected before. - if (!disconnectAccessibilityCallbacks()) - return; - - // Ensure that accessibility is initialized for the WebView by querying for - // the root accessible object, which will create the full hierarchy. -#if PLATFORM(GTK) - DumpRenderTreeSupportGtk::getRootAccessibleElement(mainFrame); -#elif PLATFORM(EFL) - DumpRenderTreeSupportEfl::rootAccessibleElement(browser->mainFrame()); -#endif - - // Add global listeners for AtkObject's signals. - stateChangeListenerId = atk_add_global_event_listener(axObjectEventListener, "ATK:AtkObject:state-change"); - focusEventListenerId = atk_add_global_event_listener(axObjectEventListener, "ATK:AtkObject:focus-event"); - activeDescendantChangedListenerId = atk_add_global_event_listener(axObjectEventListener, "ATK:AtkObject:active-descendant-changed"); - childrenChangedListenerId = atk_add_global_event_listener(axObjectEventListener, "ATK:AtkObject:children-changed"); - propertyChangedListenerId = atk_add_global_event_listener(axObjectEventListener, "ATK:AtkObject:property-change"); - visibleDataChangedListenerId = atk_add_global_event_listener(axObjectEventListener, "ATK:AtkObject:visible-data-changed"); - loadCompleteListenerId = atk_add_global_event_listener(axObjectEventListener, "ATK:AtkDocument:load-complete"); - - // Ensure the Atk interface types are registered, otherwise - // the AtkDocument signal handlers below won't get registered. - GObject* dummyAxObject = G_OBJECT(g_object_new(ATK_TYPE_OBJECT, 0)); - AtkObject* dummyNoOpAxObject = atk_no_op_object_new(dummyAxObject); - g_object_unref(G_OBJECT(dummyNoOpAxObject)); - g_object_unref(dummyAxObject); -} - -bool disconnectAccessibilityCallbacks() -{ - // Only disconnect if logging is off and there is no notification handler. - if (loggingAccessibilityEvents || !notificationHandlers.isEmpty() || globalNotificationHandler) - return false; - - // AtkObject signals. - if (stateChangeListenerId) { - atk_remove_global_event_listener(stateChangeListenerId); - stateChangeListenerId = 0; - } - if (focusEventListenerId) { - atk_remove_global_event_listener(focusEventListenerId); - focusEventListenerId = 0; - } - if (activeDescendantChangedListenerId) { - atk_remove_global_event_listener(activeDescendantChangedListenerId); - activeDescendantChangedListenerId = 0; - } - if (childrenChangedListenerId) { - atk_remove_global_event_listener(childrenChangedListenerId); - childrenChangedListenerId = 0; - } - if (propertyChangedListenerId) { - atk_remove_global_event_listener(propertyChangedListenerId); - propertyChangedListenerId = 0; - } - if (visibleDataChangedListenerId) { - atk_remove_global_event_listener(visibleDataChangedListenerId); - visibleDataChangedListenerId = 0; - } - if (loadCompleteListenerId) { - atk_remove_global_event_listener(loadCompleteListenerId); - loadCompleteListenerId = 0; - } - - return true; -} - -void addAccessibilityNotificationHandler(AccessibilityNotificationHandler* notificationHandler) -{ - if (!notificationHandler) - return; - -#if PLATFORM(GTK) - JSGlobalContextRef jsContext = webkit_web_frame_get_global_context(mainFrame); -#elif PLATFORM(EFL) - JSGlobalContextRef jsContext = DumpRenderTreeSupportEfl::globalContextRefForFrame(browser->mainFrame()); -#else - JSContextRef jsContext = 0; -#endif - if (!jsContext) - return; - - JSValueProtect(jsContext, notificationHandler->notificationFunctionCallback()); - // Check if this notification handler is related to a specific element. - if (notificationHandler->platformElement()) { - NotificationHandlersMap::iterator currentNotificationHandler = notificationHandlers.find(notificationHandler->platformElement()); - if (currentNotificationHandler != notificationHandlers.end()) { - ASSERT(currentNotificationHandler->value->platformElement()); - JSValueUnprotect(jsContext, currentNotificationHandler->value->notificationFunctionCallback()); - notificationHandlers.remove(currentNotificationHandler->value->platformElement()); - } - notificationHandlers.add(notificationHandler->platformElement(), notificationHandler); - } else { - if (globalNotificationHandler) - JSValueUnprotect(jsContext, globalNotificationHandler->notificationFunctionCallback()); - globalNotificationHandler = notificationHandler; - } - - connectAccessibilityCallbacks(); -} - -void removeAccessibilityNotificationHandler(AccessibilityNotificationHandler* notificationHandler) -{ - if (!notificationHandler) - return; - -#if PLATFORM(GTK) - JSGlobalContextRef jsContext = webkit_web_frame_get_global_context(mainFrame); -#elif PLATFORM(EFL) - JSGlobalContextRef jsContext = DumpRenderTreeSupportEfl::globalContextRefForFrame(browser->mainFrame()); -#else - JSGlobalContextRef jsContext = 0; -#endif - if (!jsContext) - return; - - if (globalNotificationHandler == notificationHandler) { - JSValueUnprotect(jsContext, globalNotificationHandler->notificationFunctionCallback()); - globalNotificationHandler = 0; - } else if (notificationHandler->platformElement()) { - NotificationHandlersMap::iterator removeNotificationHandler = notificationHandlers.find(notificationHandler->platformElement()); - if (removeNotificationHandler != notificationHandlers.end()) { - JSValueUnprotect(jsContext, removeNotificationHandler->value->notificationFunctionCallback()); - notificationHandlers.remove(removeNotificationHandler); - } - } -} - -#endif diff --git a/Tools/DumpRenderTree/atk/AccessibilityControllerAtk.cpp b/Tools/DumpRenderTree/atk/AccessibilityControllerAtk.cpp deleted file mode 100644 index d8d0fc96c..000000000 --- a/Tools/DumpRenderTree/atk/AccessibilityControllerAtk.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* - * 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 - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "AccessibilityController.h" - -#if HAVE(ACCESSIBILITY) - -#include "AccessibilityCallbacks.h" -#include "AccessibilityUIElement.h" -#include "DumpRenderTree.h" - -#include <atk/atk.h> - -bool loggingAccessibilityEvents = false; - -AccessibilityController::AccessibilityController() - : m_globalNotificationHandler(nullptr) -{ -} - -AccessibilityController::~AccessibilityController() -{ -} - -AccessibilityUIElement AccessibilityController::elementAtPoint(int x, int y) -{ - // FIXME: implement - return nullptr; -} - -void AccessibilityController::platformResetToConsistentState() -{ -} - -void AccessibilityController::setLogFocusEvents(bool) -{ -} - -void AccessibilityController::setLogScrollingStartEvents(bool) -{ -} - -void AccessibilityController::setLogValueChangeEvents(bool) -{ -} - -void AccessibilityController::setLogAccessibilityEvents(bool logAccessibilityEvents) -{ - if (logAccessibilityEvents == loggingAccessibilityEvents) - return; - - if (!logAccessibilityEvents) { - loggingAccessibilityEvents = false; - disconnectAccessibilityCallbacks(); - return; - } - - connectAccessibilityCallbacks(); - loggingAccessibilityEvents = true; -} - -bool AccessibilityController::addNotificationListener(JSObjectRef functionCallback) -{ - if (!functionCallback) - return false; - - // Only one global notification listener. - if (m_globalNotificationHandler) - return false; - - m_globalNotificationHandler = AccessibilityNotificationHandler::create(); - m_globalNotificationHandler->setNotificationFunctionCallback(functionCallback); - - return true; -} - -void AccessibilityController::removeNotificationListener() -{ - // Programmers should not be trying to remove a listener that's already removed. - ASSERT(m_globalNotificationHandler); - - m_globalNotificationHandler = nullptr; -} - -JSRetainPtr<JSStringRef> AccessibilityController::platformName() const -{ - JSRetainPtr<JSStringRef> platformName(Adopt, JSStringCreateWithUTF8CString("atk")); - return platformName; -} - -AtkObject* AccessibilityController::childElementById(AtkObject* parent, const char* id) -{ - if (!ATK_IS_OBJECT(parent)) - return nullptr; - - bool parentFound = false; - AtkAttributeSet* attributeSet(atk_object_get_attributes(parent)); - for (AtkAttributeSet* attributes = attributeSet; attributes; attributes = attributes->next) { - AtkAttribute* attribute = static_cast<AtkAttribute*>(attributes->data); - if (!strcmp(attribute->name, "html-id")) { - if (!strcmp(attribute->value, id)) - parentFound = true; - break; - } - } - atk_attribute_set_free(attributeSet); - - if (parentFound) - return parent; - - int childCount = atk_object_get_n_accessible_children(parent); - for (int i = 0; i < childCount; i++) { - AtkObject* result = childElementById(atk_object_ref_accessible_child(parent, i), id); - if (ATK_IS_OBJECT(result)) - return result; - } - - return nullptr; -} - -#endif diff --git a/Tools/DumpRenderTree/atk/AccessibilityNotificationHandlerAtk.cpp b/Tools/DumpRenderTree/atk/AccessibilityNotificationHandlerAtk.cpp deleted file mode 100644 index 4565d5506..000000000 --- a/Tools/DumpRenderTree/atk/AccessibilityNotificationHandlerAtk.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2013 Samsung Electronics Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" -#include "AccessibilityNotificationHandlerAtk.h" - -#if HAVE(ACCESSIBILITY) - -#include "AccessibilityCallbacks.h" - -AccessibilityNotificationHandler::AccessibilityNotificationHandler(void) - : m_platformElement(nullptr) - , m_notificationFunctionCallback(nullptr) -{ -} - -AccessibilityNotificationHandler::~AccessibilityNotificationHandler() -{ - removeAccessibilityNotificationHandler(this); - disconnectAccessibilityCallbacks(); -} - -void AccessibilityNotificationHandler::setNotificationFunctionCallback(JSObjectRef notificationFunctionCallback) -{ - if (!notificationFunctionCallback) { - removeAccessibilityNotificationHandler(this); - disconnectAccessibilityCallbacks(); - return; - } - - if (m_notificationFunctionCallback) - removeAccessibilityNotificationHandler(this); - - m_notificationFunctionCallback = notificationFunctionCallback; - connectAccessibilityCallbacks(); - addAccessibilityNotificationHandler(this); -} - -#endif // HAVE(ACCESSIBILITY) diff --git a/Tools/DumpRenderTree/atk/AccessibilityNotificationHandlerAtk.h b/Tools/DumpRenderTree/atk/AccessibilityNotificationHandlerAtk.h deleted file mode 100644 index 9018e7290..000000000 --- a/Tools/DumpRenderTree/atk/AccessibilityNotificationHandlerAtk.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2013 Samsung Electronics Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef AccessibilityNotificationHandlerAtk_h -#define AccessibilityNotificationHandlerAtk_h - -#if HAVE(ACCESSIBILITY) - -#include <JavaScriptCore/JSObjectRef.h> -#include <atk/atk.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> - -class AccessibilityNotificationHandler : public RefCounted<AccessibilityNotificationHandler> { -public: - static PassRefPtr<AccessibilityNotificationHandler> create() - { - return adoptRef(new AccessibilityNotificationHandler()); - } - AccessibilityNotificationHandler(void); - ~AccessibilityNotificationHandler(); - - void setPlatformElement(AtkObject* platformElement) { m_platformElement = platformElement; } - AtkObject* platformElement(void) const { return m_platformElement; } - void setNotificationFunctionCallback(JSObjectRef); - JSObjectRef notificationFunctionCallback(void) const { return m_notificationFunctionCallback; } - -private: - AtkObject* m_platformElement; - JSObjectRef m_notificationFunctionCallback; -}; - -#endif // HAVE(ACCESSIBILITY) - -#endif // AccessibilityNotificationHandlerAtk_h diff --git a/Tools/DumpRenderTree/atk/AccessibilityUIElementAtk.cpp b/Tools/DumpRenderTree/atk/AccessibilityUIElementAtk.cpp deleted file mode 100644 index 41317bdd1..000000000 --- a/Tools/DumpRenderTree/atk/AccessibilityUIElementAtk.cpp +++ /dev/null @@ -1,1604 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * Copyright (C) 2009 Jan Michael Alonzo - * Copyright (C) 2013 Samsung Electronics. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "AccessibilityUIElement.h" - -#if HAVE(ACCESSIBILITY) - -#include "AccessibilityNotificationHandlerAtk.h" -#include <JavaScriptCore/JSStringRef.h> -#include <JavaScriptCore/OpaqueJSString.h> -#include <atk/atk.h> -#include <wtf/Assertions.h> -#include <wtf/gobject/GRefPtr.h> -#include <wtf/gobject/GUniquePtr.h> -#include <wtf/text/CString.h> -#include <wtf/text/StringBuilder.h> -#include <wtf/text/WTFString.h> -#include <wtf/unicode/CharacterNames.h> - -namespace { - -enum AtkAttributeType { - ObjectAttributeType, - TextAttributeType -}; - -enum AttributeDomain { - CoreDomain = 0, - AtkDomain -}; - -enum AttributesIndex { - // Attribute names. - InvalidNameIndex = 0, - PlaceholderNameIndex, - SortNameIndex, - - // Attribute values. - SortAscendingValueIndex, - SortDescendingValueIndex, - SortUnknownValueIndex, - - NumberOfAttributes -}; - -// Attribute names & Values (keep on sync with enum AttributesIndex). -const String attributesMap[][2] = { - // Attribute names. - { "AXInvalid", "invalid" }, - { "AXPlaceholderValue", "placeholder-text" } , - { "AXSortDirection", "sort" }, - - // Attribute values. - { "AXAscendingSortDirection", "ascending" }, - { "AXDescendingSortDirection", "descending" }, - { "AXUnknownSortDirection", "unknown" } -}; - -#if ATK_CHECK_VERSION(2, 11, 3) -const char* landmarkStringBanner = "AXLandmarkBanner"; -const char* landmarkStringComplementary = "AXLandmarkComplementary"; -const char* landmarkStringContentinfo = "AXLandmarkContentInfo"; -const char* landmarkStringMain = "AXLandmarkMain"; -const char* landmarkStringNavigation = "AXLandmarkNavigation"; -const char* landmarkStringSearch = "AXLandmarkSearch"; -#endif - -String jsStringToWTFString(JSStringRef attribute) -{ - size_t bufferSize = JSStringGetMaximumUTF8CStringSize(attribute); - GUniquePtr<gchar> buffer(static_cast<gchar*>(g_malloc(bufferSize))); - JSStringGetUTF8CString(attribute, buffer.get(), bufferSize); - - return String::fromUTF8(buffer.get()); -} - -String coreAttributeToAtkAttribute(JSStringRef attribute) -{ - String attributeString = jsStringToWTFString(attribute); - for (int i = 0; i < NumberOfAttributes; ++i) { - if (attributesMap[i][CoreDomain] == attributeString) - return attributesMap[i][AtkDomain]; - } - - return attributeString; -} - -String atkAttributeValueToCoreAttributeValue(AtkAttributeType type, const String& id, const String& value) -{ - if (type == ObjectAttributeType) { - // We need to translate ATK values exposed for 'aria-sort' (e.g. 'ascending') - // into those expected by the layout tests (e.g. 'AXAscendingSortDirection'). - if (id == attributesMap[SortNameIndex][AtkDomain] && !value.isEmpty()) { - if (value == attributesMap[SortAscendingValueIndex][AtkDomain]) - return attributesMap[SortAscendingValueIndex][CoreDomain]; - if (value == attributesMap[SortDescendingValueIndex][AtkDomain]) - return attributesMap[SortDescendingValueIndex][CoreDomain]; - - return attributesMap[SortUnknownValueIndex][CoreDomain]; - } - } else if (type == TextAttributeType) { - // In case of 'aria-invalid' when the attribute empty or has "false" for ATK - // it should not be mapped at all, but layout tests will expect 'false'. - if (id == attributesMap[InvalidNameIndex][AtkDomain] && value.isEmpty()) - return "false"; - } - - return value; -} - -AtkAttributeSet* getAttributeSet(AtkObject* accessible, AtkAttributeType type) -{ - if (type == ObjectAttributeType) - return atk_object_get_attributes(accessible); - - if (type == TextAttributeType) { - if (!ATK_IS_TEXT(accessible)) - return nullptr; - - return atk_text_get_default_attributes(ATK_TEXT(accessible)); - } - - ASSERT_NOT_REACHED(); - return nullptr; -} - -String getAttributeSetValueForId(AtkObject* accessible, AtkAttributeType type, String id) -{ - AtkAttributeSet* attributeSet = getAttributeSet(accessible, type); - if (!attributeSet) - return String(); - - String attributeValue; - for (AtkAttributeSet* attributes = attributeSet; attributes; attributes = attributes->next) { - AtkAttribute* atkAttribute = static_cast<AtkAttribute*>(attributes->data); - if (id == atkAttribute->name) { - attributeValue = String::fromUTF8(atkAttribute->value); - break; - } - } - atk_attribute_set_free(attributeSet); - - return atkAttributeValueToCoreAttributeValue(type, id, attributeValue); -} - -String getAtkAttributeSetAsString(AtkObject* accessible, AtkAttributeType type) -{ - AtkAttributeSet* attributeSet = getAttributeSet(accessible, type); - if (!attributeSet) - return String(); - - StringBuilder builder; - for (AtkAttributeSet* attributes = attributeSet; attributes; attributes = attributes->next) { - AtkAttribute* attribute = static_cast<AtkAttribute*>(attributes->data); - GUniquePtr<gchar> attributeData(g_strconcat(attribute->name, ":", attribute->value, NULL)); - builder.append(attributeData.get()); - if (attributes->next) - builder.append(", "); - } - atk_attribute_set_free(attributeSet); - - return builder.toString(); -} - -const char* roleToString(AtkObject* object) -{ - AtkRole role = atk_object_get_role(object); - -#if ATK_CHECK_VERSION(2, 11, 3) - if (role == ATK_ROLE_LANDMARK) { - String xmlRolesValue = getAttributeSetValueForId(object, ObjectAttributeType, "xml-roles"); - if (equalIgnoringCase(xmlRolesValue, "banner")) - return landmarkStringBanner; - if (equalIgnoringCase(xmlRolesValue, "complementary")) - return landmarkStringComplementary; - if (equalIgnoringCase(xmlRolesValue, "contentinfo")) - return landmarkStringContentinfo; - if (equalIgnoringCase(xmlRolesValue, "main")) - return landmarkStringMain; - if (equalIgnoringCase(xmlRolesValue, "navigation")) - return landmarkStringNavigation; - if (equalIgnoringCase(xmlRolesValue, "search")) - return landmarkStringSearch; - } -#endif - - switch (role) { - case ATK_ROLE_ALERT: - return "AXAlert"; - case ATK_ROLE_DIALOG: - return "AXDialog"; - case ATK_ROLE_CANVAS: - return "AXCanvas"; - case ATK_ROLE_CHECK_BOX: - return "AXCheckBox"; - case ATK_ROLE_COLOR_CHOOSER: - return "AXColorWell"; - case ATK_ROLE_COLUMN_HEADER: - return "AXColumnHeader"; - case ATK_ROLE_COMBO_BOX: - return "AXComboBox"; - case ATK_ROLE_COMMENT: - return "AXComment"; - case ATK_ROLE_DOCUMENT_FRAME: - return "AXDocument"; - case ATK_ROLE_DOCUMENT_WEB: - return "AXWebArea"; - case ATK_ROLE_EMBEDDED: - return "AXEmbedded"; - case ATK_ROLE_ENTRY: - return "AXTextField"; - case ATK_ROLE_FOOTER: - return "AXFooter"; - case ATK_ROLE_FORM: - return "AXForm"; - case ATK_ROLE_GROUPING: - return "AXGroup"; - case ATK_ROLE_HEADING: - return "AXHeading"; - case ATK_ROLE_IMAGE: - return "AXImage"; - case ATK_ROLE_IMAGE_MAP: - return "AXImageMap"; - case ATK_ROLE_LABEL: - return "AXLabel"; - case ATK_ROLE_LINK: - return "AXLink"; - case ATK_ROLE_LIST: - return "AXList"; - case ATK_ROLE_LIST_BOX: - return "AXListBox"; - case ATK_ROLE_LIST_ITEM: - return "AXListItem"; - case ATK_ROLE_MENU: - return "AXMenu"; - case ATK_ROLE_MENU_BAR: - return "AXMenuBar"; - case ATK_ROLE_MENU_ITEM: - return "AXMenuItem"; - case ATK_ROLE_PAGE_TAB: - return "AXTab"; - case ATK_ROLE_PAGE_TAB_LIST: - return "AXTabGroup"; - case ATK_ROLE_PANEL: - return "AXGroup"; - case ATK_ROLE_PARAGRAPH: - return "AXParagraph"; - case ATK_ROLE_PASSWORD_TEXT: - return "AXPasswordField"; - case ATK_ROLE_PROGRESS_BAR: - return "AXProgressIndicator"; - case ATK_ROLE_PUSH_BUTTON: - return "AXButton"; - case ATK_ROLE_RADIO_BUTTON: - return "AXRadioButton"; - case ATK_ROLE_RADIO_MENU_ITEM: - return "AXRadioMenuItem"; - case ATK_ROLE_ROW_HEADER: - return "AXRowHeader"; - case ATK_ROLE_CHECK_MENU_ITEM: - return "AXCheckMenuItem"; - case ATK_ROLE_RULER: - return "AXRuler"; - case ATK_ROLE_SCROLL_BAR: - return "AXScrollBar"; - case ATK_ROLE_SCROLL_PANE: - return "AXScrollArea"; - case ATK_ROLE_SECTION: - return "AXSection"; - case ATK_ROLE_SEPARATOR: - return "AXSeparator"; - case ATK_ROLE_SLIDER: - return "AXSlider"; - case ATK_ROLE_SPIN_BUTTON: - return "AXSpinButton"; - case ATK_ROLE_STATUSBAR: - return "AXStatusBar"; - case ATK_ROLE_TABLE: - return "AXTable"; - case ATK_ROLE_TABLE_CELL: - return "AXCell"; - case ATK_ROLE_TABLE_COLUMN_HEADER: - return "AXColumnHeader"; - case ATK_ROLE_TABLE_ROW: - return "AXRow"; - case ATK_ROLE_TABLE_ROW_HEADER: - return "AXRowHeader"; - case ATK_ROLE_TOGGLE_BUTTON: - return "AXToggleButton"; - case ATK_ROLE_TOOL_BAR: - return "AXToolbar"; - case ATK_ROLE_TOOL_TIP: - return "AXUserInterfaceTooltip"; - case ATK_ROLE_TREE: - return "AXTree"; - case ATK_ROLE_TREE_TABLE: - return "AXTreeGrid"; - case ATK_ROLE_TREE_ITEM: - return "AXTreeItem"; - case ATK_ROLE_WINDOW: - return "AXWindow"; - case ATK_ROLE_UNKNOWN: - return "AXUnknown"; -#if ATK_CHECK_VERSION(2, 11, 3) - case ATK_ROLE_ARTICLE: - return "AXArticle"; - case ATK_ROLE_DEFINITION: - return "AXDefinition"; - case ATK_ROLE_LOG: - return "AXLog"; - case ATK_ROLE_MARQUEE: - return "AXMarquee"; - case ATK_ROLE_MATH: - return "AXMath"; - case ATK_ROLE_TIMER: - return "AXTimer"; -#endif -#if ATK_CHECK_VERSION(2, 11, 4) - case ATK_ROLE_DESCRIPTION_LIST: - return "AXDescriptionList"; - case ATK_ROLE_DESCRIPTION_TERM: - return "AXDescriptionTerm"; - case ATK_ROLE_DESCRIPTION_VALUE: - return "AXDescriptionValue"; -#endif - default: - // We want to distinguish ATK_ROLE_UNKNOWN from a known AtkRole which - // our DRT isn't properly handling. - return "FIXME not identified"; - } -} - -inline gchar* replaceCharactersForResults(gchar* str) -{ - String uString = String::fromUTF8(str); - - // The object replacement character is passed along to ATs so we need to be - // able to test for their presence and do so without causing test failures. - uString.replace(objectReplacementCharacter, "<obj>"); - - // The presence of newline characters in accessible text of a single object - // is appropriate, but it makes test results (especially the accessible tree) - // harder to read. - uString.replace("\n", "<\\n>"); - - return g_strdup(uString.utf8().data()); -} - -bool checkElementState(PlatformUIElement element, AtkStateType stateType) -{ - if (!ATK_IS_OBJECT(element)) - return false; - - GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(element))); - return atk_state_set_contains_state(stateSet.get(), stateType); -} - -String attributesOfElement(AccessibilityUIElement* element) -{ - StringBuilder builder; - - builder.append(String::format("%s\n", element->role()->string().utf8().data())); - - // For the parent we print its role and its name, if available. - builder.append("AXParent: "); - AccessibilityUIElement parent = element->parentElement(); - if (AtkObject* atkParent = parent.platformUIElement()) { - builder.append(roleToString(atkParent)); - const char* parentName = atk_object_get_name(atkParent); - if (parentName && g_utf8_strlen(parentName, -1)) - builder.append(String::format(": %s", parentName)); - } else - builder.append("(null)"); - builder.append("\n"); - - builder.append(String::format("AXChildren: %d\n", element->childrenCount())); - builder.append(String::format("AXPosition: { %f, %f }\n", element->x(), element->y())); - builder.append(String::format("AXSize: { %f, %f }\n", element->width(), element->height())); - - String title = element->title()->string(); - if (!title.isEmpty()) - builder.append(String::format("%s\n", title.utf8().data())); - - String description = element->description()->string(); - if (!description.isEmpty()) - builder.append(String::format("%s\n", description.utf8().data())); - - String value = element->stringValue()->string(); - if (!value.isEmpty()) - builder.append(String::format("%s\n", value.utf8().data())); - - builder.append(String::format("AXFocusable: %d\n", element->isFocusable())); - builder.append(String::format("AXFocused: %d\n", element->isFocused())); - builder.append(String::format("AXSelectable: %d\n", element->isSelectable())); - builder.append(String::format("AXSelected: %d\n", element->isSelected())); - builder.append(String::format("AXMultiSelectable: %d\n", element->isMultiSelectable())); - builder.append(String::format("AXEnabled: %d\n", element->isEnabled())); - builder.append(String::format("AXExpanded: %d\n", element->isExpanded())); - builder.append(String::format("AXRequired: %d\n", element->isRequired())); - builder.append(String::format("AXChecked: %d\n", element->isChecked())); - - String url = element->url()->string(); - if (!url.isEmpty()) - builder.append(String::format("%s\n", url.utf8().data())); - - // We append the ATK specific attributes as a single line at the end. - builder.append("AXPlatformAttributes: "); - builder.append(getAtkAttributeSetAsString(element->platformUIElement(), ObjectAttributeType)); - - return builder.toString(); -} - -static JSStringRef createStringWithAttributes(const Vector<AccessibilityUIElement>& elements) -{ - StringBuilder builder; - - for (Vector<AccessibilityUIElement>::const_iterator it = elements.begin(); it != elements.end(); ++it) { - builder.append(attributesOfElement(const_cast<AccessibilityUIElement*>(it))); - builder.append("\n------------\n"); - } - - return JSStringCreateWithUTF8CString(builder.toString().utf8().data()); -} - -static Vector<AccessibilityUIElement> getRowHeaders(AtkTable* accessible) -{ - Vector<AccessibilityUIElement> rowHeaders; - - int rowsCount = atk_table_get_n_rows(accessible); - for (int row = 0; row < rowsCount; ++row) - rowHeaders.append(AccessibilityUIElement(atk_table_get_row_header(accessible, row))); - - return rowHeaders; -} - -static Vector<AccessibilityUIElement> getColumnHeaders(AtkTable* accessible) -{ - Vector<AccessibilityUIElement> columnHeaders; - - int columnsCount = atk_table_get_n_columns(accessible); - for (int column = 0; column < columnsCount; ++column) - columnHeaders.append(AccessibilityUIElement(atk_table_get_column_header(accessible, column))); - - return columnHeaders; -} - -static Vector<AccessibilityUIElement> getVisibleCells(AccessibilityUIElement* element) -{ - Vector<AccessibilityUIElement> visibleCells; - - AtkTable* accessible = ATK_TABLE(element->platformUIElement()); - int rowsCount = atk_table_get_n_rows(accessible); - int columnsCount = atk_table_get_n_columns(accessible); - - for (int row = 0; row < rowsCount; ++row) { - for (int column = 0; column < columnsCount; ++column) - visibleCells.append(element->cellForColumnAndRow(column, row)); - } - - return visibleCells; -} - -} // namespace - -JSStringRef indexRangeInTable(PlatformUIElement element, bool isRowRange) -{ - GUniquePtr<gchar> rangeString(g_strdup("{0, 0}")); - - if (!ATK_IS_OBJECT(element)) - return JSStringCreateWithUTF8CString(rangeString.get()); - - AtkObject* axTable = atk_object_get_parent(ATK_OBJECT(element)); - if (!axTable || !ATK_IS_TABLE(axTable)) - return JSStringCreateWithUTF8CString(rangeString.get()); - - // Look for the cell in the table. - gint indexInParent = atk_object_get_index_in_parent(ATK_OBJECT(element)); - if (indexInParent == -1) - return JSStringCreateWithUTF8CString(rangeString.get()); - - int row = -1; - int column = -1; - row = atk_table_get_row_at_index(ATK_TABLE(axTable), indexInParent); - column = atk_table_get_column_at_index(ATK_TABLE(axTable), indexInParent); - - // Get the actual values, if row and columns are valid values. - if (row != -1 && column != -1) { - int base = 0; - int length = 0; - if (isRowRange) { - base = row; - length = atk_table_get_row_extent_at(ATK_TABLE(axTable), row, column); - } else { - base = column; - length = atk_table_get_column_extent_at(ATK_TABLE(axTable), row, column); - } - rangeString.reset(g_strdup_printf("{%d, %d}", base, length)); - } - - return JSStringCreateWithUTF8CString(rangeString.get()); -} - -void alterCurrentValue(PlatformUIElement element, int factor) -{ - if (!ATK_IS_VALUE(element)) - return; - - GValue currentValue = G_VALUE_INIT; - atk_value_get_current_value(ATK_VALUE(element), ¤tValue); - - GValue increment = G_VALUE_INIT; - atk_value_get_minimum_increment(ATK_VALUE(element), &increment); - - GValue newValue = G_VALUE_INIT; - g_value_init(&newValue, G_TYPE_FLOAT); - - g_value_set_float(&newValue, g_value_get_float(¤tValue) + factor * g_value_get_float(&increment)); - atk_value_set_current_value(ATK_VALUE(element), &newValue); - - g_value_unset(&newValue); - g_value_unset(&increment); - g_value_unset(¤tValue); -} - -AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element) - : m_element(element) -{ - if (m_element) - g_object_ref(m_element); -} - -AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other) - : m_element(other.m_element) -{ - if (m_element) - g_object_ref(m_element); -} - -AccessibilityUIElement::~AccessibilityUIElement() -{ - if (m_element) - g_object_unref(m_element); -} - -void AccessibilityUIElement::getLinkedUIElements(Vector<AccessibilityUIElement>& elements) -{ - // FIXME: implement -} - -void AccessibilityUIElement::getDocumentLinks(Vector<AccessibilityUIElement>&) -{ - // FIXME: implement -} - -void AccessibilityUIElement::getChildren(Vector<AccessibilityUIElement>& children) -{ - if (!ATK_IS_OBJECT(m_element)) - return; - - int count = childrenCount(); - for (int i = 0; i < count; i++) { - AtkObject* child = atk_object_ref_accessible_child(ATK_OBJECT(m_element), i); - children.append(AccessibilityUIElement(child)); - } -} - -void AccessibilityUIElement::getChildrenWithRange(Vector<AccessibilityUIElement>& elementVector, unsigned start, unsigned end) -{ - if (!ATK_IS_OBJECT(m_element)) - return; - - for (unsigned i = start; i < end; i++) { - AtkObject* child = atk_object_ref_accessible_child(ATK_OBJECT(m_element), i); - elementVector.append(AccessibilityUIElement(child)); - } -} - -int AccessibilityUIElement::rowCount() -{ - if (!ATK_IS_TABLE(m_element)) - return 0; - - return atk_table_get_n_rows(ATK_TABLE(m_element)); -} - -int AccessibilityUIElement::columnCount() -{ - if (!ATK_IS_TABLE(m_element)) - return 0; - - return atk_table_get_n_columns(ATK_TABLE(m_element)); -} - -int AccessibilityUIElement::childrenCount() -{ - if (!ATK_IS_OBJECT(m_element)) - return 0; - - return atk_object_get_n_accessible_children(ATK_OBJECT(m_element)); -} - -AccessibilityUIElement AccessibilityUIElement::elementAtPoint(int x, int y) -{ - if (!ATK_IS_COMPONENT(m_element)) - return nullptr; - - GRefPtr<AtkObject> objectAtPoint = adoptGRef(atk_component_ref_accessible_at_point(ATK_COMPONENT(m_element), x, y, ATK_XY_WINDOW)); - return AccessibilityUIElement(objectAtPoint ? objectAtPoint.get() : m_element); -} - -AccessibilityUIElement AccessibilityUIElement::linkedUIElementAtIndex(unsigned index) -{ - // FIXME: implement - return nullptr; -} - -AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index) -{ - if (!ATK_IS_OBJECT(m_element)) - return nullptr; - - Vector<AccessibilityUIElement> children; - getChildrenWithRange(children, index, index + 1); - - if (children.size() == 1) - return children.at(0); - - return nullptr; -} - -unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element) -{ - // FIXME: implement - return 0; -} - -JSStringRef AccessibilityUIElement::allAttributes() -{ - if (!ATK_IS_OBJECT(m_element)) - return JSStringCreateWithCharacters(0, 0); - - return JSStringCreateWithUTF8CString(attributesOfElement(this).utf8().data()); -} - -JSStringRef AccessibilityUIElement::attributesOfLinkedUIElements() -{ - // FIXME: implement - return JSStringCreateWithCharacters(0, 0); -} - -JSStringRef AccessibilityUIElement::attributesOfDocumentLinks() -{ - // FIXME: implement - return JSStringCreateWithCharacters(0, 0); -} - -AccessibilityUIElement AccessibilityUIElement::titleUIElement() -{ - if (!ATK_IS_OBJECT(m_element)) - return nullptr; - - AtkRelationSet* set = atk_object_ref_relation_set(ATK_OBJECT(m_element)); - if (!set) - return nullptr; - - AtkObject* target = nullptr; - int count = atk_relation_set_get_n_relations(set); - for (int i = 0; i < count; i++) { - AtkRelation* relation = atk_relation_set_get_relation(set, i); - if (atk_relation_get_relation_type(relation) == ATK_RELATION_LABELLED_BY) { - GPtrArray* targetList = atk_relation_get_target(relation); - if (targetList->len) - target = static_cast<AtkObject*>(g_ptr_array_index(targetList, 0)); - } - } - - g_object_unref(set); - return target ? AccessibilityUIElement(target) : nullptr; -} - -AccessibilityUIElement AccessibilityUIElement::parentElement() -{ - if (!ATK_IS_OBJECT(m_element)) - return nullptr; - - AtkObject* parent = atk_object_get_parent(ATK_OBJECT(m_element)); - return parent ? AccessibilityUIElement(parent) : nullptr; -} - -JSStringRef AccessibilityUIElement::attributesOfChildren() -{ - if (!ATK_IS_OBJECT(m_element)) - return JSStringCreateWithCharacters(0, 0); - - Vector<AccessibilityUIElement> children; - getChildren(children); - - return createStringWithAttributes(children); -} - -JSStringRef AccessibilityUIElement::parameterizedAttributeNames() -{ - // FIXME: implement - return JSStringCreateWithCharacters(0, 0); -} - -JSStringRef AccessibilityUIElement::role() -{ - if (!ATK_IS_OBJECT(m_element)) - return JSStringCreateWithCharacters(0, 0); - - if (!atk_object_get_role(ATK_OBJECT(m_element))) - return JSStringCreateWithCharacters(0, 0); - - GUniquePtr<char> roleStringWithPrefix(g_strdup_printf("AXRole: %s", roleToString(ATK_OBJECT(m_element)))); - return JSStringCreateWithUTF8CString(roleStringWithPrefix.get()); -} - -JSStringRef AccessibilityUIElement::subrole() -{ - return nullptr; -} - -JSStringRef AccessibilityUIElement::roleDescription() -{ - return nullptr; -} - -JSStringRef AccessibilityUIElement::title() -{ - if (!ATK_IS_OBJECT(m_element)) - return JSStringCreateWithCharacters(0, 0); - - const gchar* name = atk_object_get_name(ATK_OBJECT(m_element)); - GUniquePtr<gchar> axTitle(g_strdup_printf("AXTitle: %s", name ? name : "")); - - return JSStringCreateWithUTF8CString(axTitle.get()); -} - -JSStringRef AccessibilityUIElement::description() -{ - if (!ATK_IS_OBJECT(m_element)) - return JSStringCreateWithCharacters(0, 0); - - const gchar* description = atk_object_get_description(ATK_OBJECT(m_element)); - if (!description) - return JSStringCreateWithCharacters(0, 0); - - GUniquePtr<gchar> axDesc(g_strdup_printf("AXDescription: %s", description)); - - return JSStringCreateWithUTF8CString(axDesc.get()); -} - -JSStringRef AccessibilityUIElement::stringValue() -{ - if (!ATK_IS_TEXT(m_element)) - return JSStringCreateWithCharacters(0, 0); - - GUniquePtr<gchar> text(atk_text_get_text(ATK_TEXT(m_element), 0, -1)); - GUniquePtr<gchar> textWithReplacedCharacters(replaceCharactersForResults(text.get())); - GUniquePtr<gchar> axValue(g_strdup_printf("AXValue: %s", textWithReplacedCharacters.get())); - - return JSStringCreateWithUTF8CString(axValue.get()); -} - -JSStringRef AccessibilityUIElement::language() -{ - if (!ATK_IS_OBJECT(m_element)) - return JSStringCreateWithCharacters(0, 0); - - const gchar* locale = atk_object_get_object_locale(ATK_OBJECT(m_element)); - if (!locale) - return JSStringCreateWithCharacters(0, 0); - - GUniquePtr<char> axValue(g_strdup_printf("AXLanguage: %s", locale)); - return JSStringCreateWithUTF8CString(axValue.get()); -} - -JSStringRef AccessibilityUIElement::helpText() const -{ - if (!ATK_IS_OBJECT(m_element)) - return JSStringCreateWithCharacters(0, 0); - - AtkRelationSet* relationSet = atk_object_ref_relation_set(ATK_OBJECT(m_element)); - if (!relationSet) - return nullptr; - - AtkRelation* relation = atk_relation_set_get_relation_by_type(relationSet, ATK_RELATION_DESCRIBED_BY); - if (!relation) - return nullptr; - - GPtrArray* targetList = atk_relation_get_target(relation); - if (!targetList || !targetList->len) - return nullptr; - - StringBuilder builder; - builder.append("AXHelp: "); - - for (int targetCount = 0; targetCount < targetList->len; targetCount++) { - if (AtkObject* target = static_cast<AtkObject*>(g_ptr_array_index(targetList, targetCount))) { - GUniquePtr<gchar> text(atk_text_get_text(ATK_TEXT(target), 0, -1)); - if (!builder.isEmpty()) - builder.append(" "); - builder.append(text.get()); - } - } - - g_object_unref(relationSet); - - return JSStringCreateWithUTF8CString(builder.toString().utf8().data()); - -} - -double AccessibilityUIElement::x() -{ - if (!ATK_IS_COMPONENT(m_element)) - return 0; - - int x, y; - atk_component_get_position(ATK_COMPONENT(m_element), &x, &y, ATK_XY_SCREEN); - - return x; -} - -double AccessibilityUIElement::y() -{ - if (!ATK_IS_COMPONENT(m_element)) - return 0; - - int x, y; - atk_component_get_position(ATK_COMPONENT(m_element), &x, &y, ATK_XY_SCREEN); - - return y; -} - -double AccessibilityUIElement::width() -{ - if (!ATK_IS_COMPONENT(m_element)) - return 0; - - int width, height; - atk_component_get_size(ATK_COMPONENT(m_element), &width, &height); - - return width; -} - -double AccessibilityUIElement::height() -{ - if (!ATK_IS_COMPONENT(m_element)) - return 0; - - int width, height; - atk_component_get_size(ATK_COMPONENT(m_element), &width, &height); - - return height; -} - -double AccessibilityUIElement::clickPointX() -{ - if (!ATK_IS_COMPONENT(m_element)) - return 0; - - int x, y; - atk_component_get_position(ATK_COMPONENT(m_element), &x, &y, ATK_XY_WINDOW); - - int width, height; - atk_component_get_size(ATK_COMPONENT(m_element), &width, &height); - - return x + width / 2.0; -} - -double AccessibilityUIElement::clickPointY() -{ - if (!ATK_IS_COMPONENT(m_element)) - return 0; - - int x, y; - atk_component_get_position(ATK_COMPONENT(m_element), &x, &y, ATK_XY_WINDOW); - - int width, height; - atk_component_get_size(ATK_COMPONENT(m_element), &width, &height); - - return y + height / 2.0; -} - -JSStringRef AccessibilityUIElement::orientation() const -{ - if (!ATK_IS_OBJECT(m_element)) - return JSStringCreateWithCharacters(0, 0); - - const char* axOrientation = nullptr; - if (checkElementState(m_element, ATK_STATE_HORIZONTAL)) - axOrientation = "AXOrientation: AXHorizontalOrientation"; - else if (checkElementState(m_element, ATK_STATE_VERTICAL)) - axOrientation = "AXOrientation: AXVerticalOrientation"; - - if (!axOrientation) - return JSStringCreateWithCharacters(0, 0); - - return JSStringCreateWithUTF8CString(axOrientation); -} - -double AccessibilityUIElement::intValue() const -{ - if (!ATK_IS_OBJECT(m_element)) - return 0; - - if (ATK_IS_VALUE(m_element)) { - GValue value = G_VALUE_INIT; - atk_value_get_current_value(ATK_VALUE(m_element), &value); - if (!G_VALUE_HOLDS_FLOAT(&value)) - return 0; - return g_value_get_float(&value); - } - - // Consider headings as an special case when returning the "int value" of - // an AccessibilityUIElement, so we can reuse some tests to check the level - // both for HTML headings and objects with the aria-level attribute. - if (atk_object_get_role(ATK_OBJECT(m_element)) == ATK_ROLE_HEADING) { - String headingLevel = getAttributeSetValueForId(ATK_OBJECT(m_element), ObjectAttributeType, "level"); - bool ok; - double headingLevelValue = headingLevel.toDouble(&ok); - if (ok) - return headingLevelValue; - } - - return 0; -} - -double AccessibilityUIElement::minValue() -{ - if (!ATK_IS_VALUE(m_element)) - return 0; - - GValue value = G_VALUE_INIT; - atk_value_get_minimum_value(ATK_VALUE(m_element), &value); - if (!G_VALUE_HOLDS_FLOAT(&value)) - return 0; - return g_value_get_float(&value); -} - -double AccessibilityUIElement::maxValue() -{ - if (!ATK_IS_VALUE(m_element)) - return 0; - - GValue value = G_VALUE_INIT; - atk_value_get_maximum_value(ATK_VALUE(m_element), &value); - if (!G_VALUE_HOLDS_FLOAT(&value)) - return 0; - return g_value_get_float(&value); -} - -JSStringRef AccessibilityUIElement::valueDescription() -{ - // FIXME: implement after it has been implemented in ATK. - // See: https://bugzilla.gnome.org/show_bug.cgi?id=684576 - return JSStringCreateWithCharacters(0, 0); -} - -bool AccessibilityUIElement::isEnabled() -{ - return checkElementState(m_element, ATK_STATE_ENABLED); -} - -int AccessibilityUIElement::insertionPointLineNumber() -{ - // FIXME: implement - return 0; -} - -bool AccessibilityUIElement::isPressActionSupported() -{ - if (!ATK_IS_ACTION(m_element)) - return false; - - const gchar* actionName = atk_action_get_name(ATK_ACTION(m_element), 0); - return equalIgnoringCase(actionName, String("press")) || equalIgnoringCase(actionName, String("jump")); -} - -bool AccessibilityUIElement::isIncrementActionSupported() -{ - // FIXME: implement - return false; -} - -bool AccessibilityUIElement::isDecrementActionSupported() -{ - // FIXME: implement - return false; -} - -bool AccessibilityUIElement::isRequired() const -{ - return checkElementState(m_element, ATK_STATE_REQUIRED); -} - -bool AccessibilityUIElement::isFocused() const -{ - if (!ATK_IS_OBJECT(m_element)) - return false; - - GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element))); - gboolean isFocused = atk_state_set_contains_state(stateSet.get(), ATK_STATE_FOCUSED); - - return isFocused; -} - -bool AccessibilityUIElement::isSelected() const -{ - return checkElementState(m_element, ATK_STATE_SELECTED); -} - -int AccessibilityUIElement::hierarchicalLevel() const -{ - // FIXME: implement - return 0; -} - -bool AccessibilityUIElement::ariaIsGrabbed() const -{ - return false; -} - -JSStringRef AccessibilityUIElement::ariaDropEffects() const -{ - return nullptr; -} - -bool AccessibilityUIElement::isExpanded() const -{ - if (!ATK_IS_OBJECT(m_element)) - return false; - - GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element))); - gboolean isExpanded = atk_state_set_contains_state(stateSet.get(), ATK_STATE_EXPANDED); - - return isExpanded; -} - -bool AccessibilityUIElement::isChecked() const -{ - if (!ATK_IS_OBJECT(m_element)) - return false; - - GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element))); - gboolean isChecked = atk_state_set_contains_state(stateSet.get(), ATK_STATE_CHECKED); - - return isChecked; -} - -bool AccessibilityUIElement::isIndeterminate() const -{ - if (!ATK_IS_OBJECT(m_element)) - return false; - - GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element))); - return atk_state_set_contains_state(stateSet.get(), ATK_STATE_INDETERMINATE); -} - -JSStringRef AccessibilityUIElement::attributesOfColumnHeaders() -{ - if (!ATK_IS_TABLE(m_element)) - return JSStringCreateWithCharacters(0, 0); - - Vector<AccessibilityUIElement> columnHeaders = getColumnHeaders(ATK_TABLE(m_element)); - return createStringWithAttributes(columnHeaders); -} - -JSStringRef AccessibilityUIElement::attributesOfRowHeaders() -{ - if (!ATK_IS_TABLE(m_element)) - return JSStringCreateWithCharacters(0, 0); - - Vector<AccessibilityUIElement> rowHeaders = getRowHeaders(ATK_TABLE(m_element)); - return createStringWithAttributes(rowHeaders); -} - -JSStringRef AccessibilityUIElement::attributesOfColumns() -{ - // FIXME: implement - return JSStringCreateWithCharacters(0, 0); -} - -JSStringRef AccessibilityUIElement::attributesOfRows() -{ - // FIXME: implement - return JSStringCreateWithCharacters(0, 0); -} - -JSStringRef AccessibilityUIElement::attributesOfVisibleCells() -{ - if (!ATK_IS_TABLE(m_element)) - return JSStringCreateWithCharacters(0, 0); - - Vector<AccessibilityUIElement> visibleCells = getVisibleCells(this); - return createStringWithAttributes(visibleCells); -} - -JSStringRef AccessibilityUIElement::attributesOfHeader() -{ - // FIXME: implement - return JSStringCreateWithCharacters(0, 0); -} - -int AccessibilityUIElement::indexInTable() -{ - // FIXME: implement - return 0; -} - -JSStringRef AccessibilityUIElement::rowIndexRange() -{ - // Range in table for rows. - return indexRangeInTable(m_element, true); -} - -JSStringRef AccessibilityUIElement::columnIndexRange() -{ - // Range in table for columns. - return indexRangeInTable(m_element, false); -} - -int AccessibilityUIElement::lineForIndex(int index) -{ - if (!ATK_IS_TEXT(m_element)) - return -1; - - if (index < 0 || index > atk_text_get_character_count(ATK_TEXT(m_element))) - return -1; - - GUniquePtr<gchar> text(atk_text_get_text(ATK_TEXT(m_element), 0, index)); - int lineNo = 0; - for (gchar* offset = text.get(); *offset; ++offset) { - if (*offset == '\n') - ++lineNo; - } - - return lineNo; -} - -JSStringRef AccessibilityUIElement::boundsForRange(unsigned location, unsigned length) -{ - // FIXME: implement - return JSStringCreateWithCharacters(0, 0); -} - -JSStringRef AccessibilityUIElement::stringForRange(unsigned location, unsigned length) -{ - if (!ATK_IS_TEXT(m_element)) - return JSStringCreateWithCharacters(0, 0); - - String string = atk_text_get_text(ATK_TEXT(m_element), location, location + length); - return JSStringCreateWithUTF8CString(string.utf8().data()); -} - -JSStringRef AccessibilityUIElement::attributedStringForRange(unsigned, unsigned) -{ - // FIXME: implement - return JSStringCreateWithCharacters(0, 0); -} - -bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned location, unsigned length) -{ - // FIXME: implement - return false; -} - -unsigned AccessibilityUIElement::uiElementCountForSearchPredicate(JSContextRef context, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly) -{ - // FIXME: implement - return 0; -} - -AccessibilityUIElement AccessibilityUIElement::uiElementForSearchPredicate(JSContextRef context, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly) -{ - // FIXME: implement - return nullptr; -} - -AccessibilityUIElement AccessibilityUIElement::cellForColumnAndRow(unsigned column, unsigned row) -{ - if (!ATK_IS_TABLE(m_element)) - return nullptr; - - // Adopt the AtkObject representing the cell because - // at_table_ref_at() transfers full ownership. - GRefPtr<AtkObject> foundCell = adoptGRef(atk_table_ref_at(ATK_TABLE(m_element), row, column)); - return foundCell ? AccessibilityUIElement(foundCell.get()) : nullptr; -} - -JSStringRef AccessibilityUIElement::selectedTextRange() -{ - if (!ATK_IS_TEXT(m_element)) - return JSStringCreateWithCharacters(0, 0); - - gint start, end; - g_free(atk_text_get_selection(ATK_TEXT(m_element), 0, &start, &end)); - - GUniquePtr<gchar> selection(g_strdup_printf("{%d, %d}", start, end - start)); - return JSStringCreateWithUTF8CString(selection.get()); -} - -void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length) -{ - if (!ATK_IS_TEXT(m_element)) - return; - - atk_text_set_selection(ATK_TEXT(m_element), 0, location, location + length); -} - -JSStringRef AccessibilityUIElement::stringAttributeValue(JSStringRef attribute) -{ - if (!ATK_IS_OBJECT(m_element)) - return JSStringCreateWithCharacters(0, 0); - - String atkAttributeName = coreAttributeToAtkAttribute(attribute); - - // Try object attributes first. - String attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element), ObjectAttributeType, atkAttributeName); - - // Try text attributes if the requested one was not found and we have an AtkText object. - if (attributeValue.isEmpty() && ATK_IS_TEXT(m_element)) - attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element), TextAttributeType, atkAttributeName); - - // Additional check to make sure that the exposure of the state ATK_STATE_INVALID_ENTRY - // is consistent with the exposure of aria-invalid as a text attribute, if present. - if (atkAttributeName == attributesMap[InvalidNameIndex][AtkDomain]) { - bool isInvalidState = checkElementState(m_element, ATK_STATE_INVALID_ENTRY); - if (attributeValue.isEmpty()) - return JSStringCreateWithUTF8CString(isInvalidState ? "true" : "false"); - - // If the text attribute was there, check that it's consistent with - // what the state says or force the test to fail otherwise. - bool isAriaInvalid = attributeValue != "false"; - if (isInvalidState != isAriaInvalid) - return JSStringCreateWithCharacters(0, 0); - } - - return JSStringCreateWithUTF8CString(attributeValue.utf8().data()); -} - -double AccessibilityUIElement::numberAttributeValue(JSStringRef attribute) -{ - // FIXME: implement - return 0; -} - -bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute) -{ - // FIXME: implement - return false; -} - -bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute) -{ - if (!ATK_IS_OBJECT(m_element)) - return false; - - String attributeString = jsStringToWTFString(attribute); - if (attributeString == "AXValue") - return checkElementState(m_element, ATK_STATE_EDITABLE); - - return false; -} - -bool AccessibilityUIElement::isAttributeSupported(JSStringRef attribute) -{ - if (!ATK_IS_OBJECT(m_element)) - return false; - - String atkAttributeName = coreAttributeToAtkAttribute(attribute); - if (atkAttributeName.isEmpty()) - return false; - - // For now, an attribute is supported whether it's exposed as a object or a text attribute. - String attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element), ObjectAttributeType, atkAttributeName); - if (attributeValue.isEmpty()) - attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element), TextAttributeType, atkAttributeName); - - return !attributeValue.isEmpty(); -} - -void AccessibilityUIElement::increment() -{ - alterCurrentValue(m_element, 1); -} - -void AccessibilityUIElement::decrement() -{ - alterCurrentValue(m_element, -1); -} - -void AccessibilityUIElement::press() -{ - if (!ATK_IS_ACTION(m_element)) - return; - - // Only one action per object is supported so far. - atk_action_do_action(ATK_ACTION(m_element), 0); -} - -void AccessibilityUIElement::showMenu() -{ - // FIXME: implement -} - -AccessibilityUIElement AccessibilityUIElement::disclosedRowAtIndex(unsigned index) -{ - return nullptr; -} - -AccessibilityUIElement AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index) -{ - return nullptr; -} - -AccessibilityUIElement AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index) -{ - if (!ATK_IS_OBJECT(m_element)) - return nullptr; - - AtkRelationSet* relationSet = atk_object_ref_relation_set(ATK_OBJECT(m_element)); - if (!relationSet) - return nullptr; - - AtkRelation* relation = atk_relation_set_get_relation_by_type(relationSet, ATK_RELATION_FLOWS_TO); - if (!relation) - return nullptr; - - GPtrArray* targetList = atk_relation_get_target(relation); - if (!targetList || !targetList->len || index >= targetList->len) - return nullptr; - - g_object_unref(relationSet); - - AtkObject* target = static_cast<AtkObject*>(g_ptr_array_index(targetList, index)); - return target ? AccessibilityUIElement(target) : nullptr; -} - -AccessibilityUIElement AccessibilityUIElement::selectedRowAtIndex(unsigned index) -{ - return nullptr; -} - -AccessibilityUIElement AccessibilityUIElement::rowAtIndex(unsigned index) -{ - return nullptr; -} - -AccessibilityUIElement AccessibilityUIElement::disclosedByRow() -{ - return nullptr; -} - -JSStringRef AccessibilityUIElement::accessibilityValue() const -{ - // FIXME: implement - return JSStringCreateWithCharacters(0, 0); -} - -JSStringRef AccessibilityUIElement::documentEncoding() -{ - if (!ATK_IS_DOCUMENT(m_element)) - return JSStringCreateWithCharacters(0, 0); - - AtkRole role = atk_object_get_role(ATK_OBJECT(m_element)); - if (role != ATK_ROLE_DOCUMENT_FRAME) - return JSStringCreateWithCharacters(0, 0); - - return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element), "Encoding")); -} - -JSStringRef AccessibilityUIElement::documentURI() -{ - if (!ATK_IS_DOCUMENT(m_element)) - return JSStringCreateWithCharacters(0, 0); - - AtkRole role = atk_object_get_role(ATK_OBJECT(m_element)); - if (role != ATK_ROLE_DOCUMENT_FRAME) - return JSStringCreateWithCharacters(0, 0); - - return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element), "URI")); -} - -JSStringRef AccessibilityUIElement::url() -{ - if (!ATK_IS_HYPERLINK_IMPL(m_element)) - return JSStringCreateWithCharacters(0, 0); - - AtkHyperlink* hyperlink = atk_hyperlink_impl_get_hyperlink(ATK_HYPERLINK_IMPL(m_element)); - GUniquePtr<char> hyperlinkURI(atk_hyperlink_get_uri(hyperlink, 0)); - - // Build the result string, stripping the absolute URL paths if present. - char* localURI = g_strstr_len(hyperlinkURI.get(), -1, "LayoutTests"); - String axURL = String::format("AXURL: %s", localURI ? localURI : hyperlinkURI.get()); - return JSStringCreateWithUTF8CString(axURL.utf8().data()); -} - -bool AccessibilityUIElement::addNotificationListener(JSObjectRef functionCallback) -{ - if (!functionCallback) - return false; - - // Only one notification listener per element. - if (m_notificationHandler) - return false; - - m_notificationHandler = AccessibilityNotificationHandler::create(); - m_notificationHandler->setPlatformElement(platformUIElement()); - m_notificationHandler->setNotificationFunctionCallback(functionCallback); - - return true; -} - -void AccessibilityUIElement::removeNotificationListener() -{ - // Programmers should not be trying to remove a listener that's already removed. - ASSERT(m_notificationHandler); - - m_notificationHandler = nullptr; -} - -bool AccessibilityUIElement::isFocusable() const -{ - if (!ATK_IS_OBJECT(m_element)) - return false; - - GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element))); - gboolean isFocusable = atk_state_set_contains_state(stateSet.get(), ATK_STATE_FOCUSABLE); - - return isFocusable; -} - -bool AccessibilityUIElement::isSelectable() const -{ - return checkElementState(m_element, ATK_STATE_SELECTABLE); -} - -bool AccessibilityUIElement::isMultiSelectable() const -{ - return checkElementState(m_element, ATK_STATE_MULTISELECTABLE); -} - -bool AccessibilityUIElement::isSelectedOptionActive() const -{ - return checkElementState(m_element, ATK_STATE_ACTIVE); -} - -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::isIgnored() const -{ - // FIXME: implement - return false; -} - -bool AccessibilityUIElement::hasPopup() const -{ - if (!ATK_IS_OBJECT(m_element)) - return false; - - String hasPopupValue = getAttributeSetValueForId(ATK_OBJECT(m_element), ObjectAttributeType, "haspopup"); - return equalIgnoringCase(hasPopupValue, "true"); -} - -void AccessibilityUIElement::takeFocus() -{ - // FIXME: implement -} - -void AccessibilityUIElement::takeSelection() -{ - // FIXME: implement -} - -void AccessibilityUIElement::addSelection() -{ - // FIXME: implement -} - -void AccessibilityUIElement::removeSelection() -{ - // FIXME: implement -} - -void AccessibilityUIElement::scrollToMakeVisible() -{ - // FIXME: implement -} - -void AccessibilityUIElement::scrollToMakeVisibleWithSubFocus(int x, int y, int width, int height) -{ - // FIXME: implement -} - -void AccessibilityUIElement::scrollToGlobalPoint(int x, int y) -{ - // FIXME: implement -} - -JSStringRef AccessibilityUIElement::classList() const -{ - // FIXME: implement - return nullptr; -} - -JSStringRef stringAtOffset(PlatformUIElement element, AtkTextBoundary boundary, int offset) -{ - if (!ATK_IS_TEXT(element)) - return JSStringCreateWithCharacters(0, 0); - - gint startOffset, endOffset; - StringBuilder builder; - -#if ATK_CHECK_VERSION(2, 10, 0) - AtkTextGranularity granularity; - switch (boundary) { - case ATK_TEXT_BOUNDARY_CHAR: - granularity = ATK_TEXT_GRANULARITY_CHAR; - break; - case ATK_TEXT_BOUNDARY_WORD_START: - granularity = ATK_TEXT_GRANULARITY_WORD; - break; - case ATK_TEXT_BOUNDARY_LINE_START: - granularity = ATK_TEXT_GRANULARITY_LINE; - break; - case ATK_TEXT_BOUNDARY_SENTENCE_START: - granularity = ATK_TEXT_GRANULARITY_SENTENCE; - break; - default: - return JSStringCreateWithCharacters(0, 0); - } - - builder.append(atk_text_get_string_at_offset(ATK_TEXT(element), offset, granularity, &startOffset, &endOffset)); -#else - builder.append(atk_text_get_text_at_offset(ATK_TEXT(element), offset, boundary, &startOffset, &endOffset)); -#endif - builder.append(String::format(", %i, %i", startOffset, endOffset)); - return JSStringCreateWithUTF8CString(builder.toString().utf8().data()); -} - -JSStringRef AccessibilityUIElement::characterAtOffset(int offset) -{ - return stringAtOffset(m_element, ATK_TEXT_BOUNDARY_CHAR, offset); -} - -JSStringRef AccessibilityUIElement::wordAtOffset(int offset) -{ - return stringAtOffset(m_element, ATK_TEXT_BOUNDARY_WORD_START, offset); -} - -JSStringRef AccessibilityUIElement::lineAtOffset(int offset) -{ - return stringAtOffset(m_element, ATK_TEXT_BOUNDARY_LINE_START, offset); -} - -JSStringRef AccessibilityUIElement::sentenceAtOffset(int offset) -{ - return stringAtOffset(m_element, ATK_TEXT_BOUNDARY_SENTENCE_START, offset); -} - -#endif diff --git a/Tools/DumpRenderTree/cairo/PixelDumpSupportCairo.cpp b/Tools/DumpRenderTree/cairo/PixelDumpSupportCairo.cpp index fe6046c68..9c8931075 100644 --- a/Tools/DumpRenderTree/cairo/PixelDumpSupportCairo.cpp +++ b/Tools/DumpRenderTree/cairo/PixelDumpSupportCairo.cpp @@ -12,7 +12,7 @@ * 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 + * 3. Neither the name of Apple 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. * diff --git a/Tools/DumpRenderTree/cairo/PixelDumpSupportCairo.h b/Tools/DumpRenderTree/cairo/PixelDumpSupportCairo.h index 071e874d0..8cc59589d 100644 --- a/Tools/DumpRenderTree/cairo/PixelDumpSupportCairo.h +++ b/Tools/DumpRenderTree/cairo/PixelDumpSupportCairo.h @@ -11,7 +11,7 @@ * 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 + * 3. Neither the name of Apple 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. * @@ -27,10 +27,9 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef PixelDumpSupportCairo_h -#define PixelDumpSupportCairo_h +#pragma once -#include <wtf/PassRefPtr.h> +#include <wtf/Ref.h> #include <wtf/RefCounted.h> #if PLATFORM(WIN) @@ -48,9 +47,9 @@ typedef void* PlatformBitmapBuffer; class BitmapContext : public RefCounted<BitmapContext> { public: - static PassRefPtr<BitmapContext> createByAdoptingBitmapAndContext(PlatformBitmapBuffer buffer, cairo_t* context) + static Ref<BitmapContext> createByAdoptingBitmapAndContext(PlatformBitmapBuffer buffer, cairo_t* context) { - return adoptRef(new BitmapContext(buffer, context)); + return adoptRef(*new BitmapContext(buffer, context)); } ~BitmapContext() @@ -77,5 +76,3 @@ private: PlatformBitmapBuffer m_buffer; cairo_t* m_context; }; - -#endif // PixelDumpSupportCairo_h diff --git a/Tools/DumpRenderTree/config.h b/Tools/DumpRenderTree/config.h index ddb1d5195..3ee18a3cd 100644 --- a/Tools/DumpRenderTree/config.h +++ b/Tools/DumpRenderTree/config.h @@ -18,18 +18,13 @@ * */ -#define Config_H +#pragma once -#if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H -#if defined(BUILDING_WITH_CMAKE) +#if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H && defined(BUILDING_WITH_CMAKE) #include "cmakeconfig.h" -#else -#include "autotoolsconfig.h" -#endif #endif -#include <wtf/Platform.h> -#include <wtf/ExportMacros.h> +#include <WebCore/PlatformExportMacros.h> #include <runtime/JSExportMacros.h> #ifdef __cplusplus @@ -38,39 +33,25 @@ #include <wtf/FastMalloc.h> #endif -#if PLATFORM(MAC) -#define WTF_USE_CF 1 - -// FIXME: These can be removed after sufficient time has passed since the removal of BUILDING_ON / TARGETING macros. - -#define ERROR_PLEASE_COMPARE_WITH_MAC_OS_X_VERSION_MIN_REQUIRED 0 / 0 -#define ERROR_PLEASE_COMPARE_WITH_MAC_OS_X_VERSION_MAX_ALLOWED 0 / 0 - -#define BUILDING_ON_LEOPARD ERROR_PLEASE_COMPARE_WITH_MAC_OS_X_VERSION_MIN_REQUIRED -#define BUILDING_ON_SNOW_LEOPARD ERROR_PLEASE_COMPARE_WITH_MAC_OS_X_VERSION_MIN_REQUIRED -#define BUILDING_ON_LION ERROR_PLEASE_COMPARE_WITH_MAC_OS_X_VERSION_MIN_REQUIRED - -#define TARGETING_LEOPARD ERROR_PLEASE_COMPARE_WITH_MAC_OS_X_VERSION_MAX_ALLOWED -#define TARGETING_SNOW_LEOPARD ERROR_PLEASE_COMPARE_WITH_MAC_OS_X_VERSION_MAX_ALLOWED -#define TARGETING_LION ERROR_PLEASE_COMPARE_WITH_MAC_OS_X_VERSION_MAX_ALLOWED - -#endif // PLATFORM(MAC) +#if PLATFORM(COCOA) +#define USE_CF 1 +#endif #if PLATFORM(WIN) -#define WTF_USE_CF 1 +#define USE_CF 1 #if PLATFORM(WIN_CAIRO) -#define WTF_USE_CAIRO 1 -#define WTF_USE_CURL 1 +#define USE_CAIRO 1 +#define USE_CURL 1 #else -#define WTF_USE_CG 1 -#define WTF_USE_CFNETWORK 1 +#define USE_CG 1 +#define USE_CFURLCONNECTION 1 #endif #undef _WIN32_WINNT -#define _WIN32_WINNT 0x0502 +#define _WIN32_WINNT 0x601 #undef WINVER -#define WINVER 0x0502 +#define WINVER 0x0601 #undef _WINSOCKAPI_ #define _WINSOCKAPI_ // Prevent inclusion of winsock.h in windows.h diff --git a/Tools/DumpRenderTree/gtk/AccessibilityControllerGtk.cpp b/Tools/DumpRenderTree/gtk/AccessibilityControllerGtk.cpp deleted file mode 100644 index 7ee1d9460..000000000 --- a/Tools/DumpRenderTree/gtk/AccessibilityControllerGtk.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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 - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if HAVE(ACCESSIBILITY) - -#include "AccessibilityController.h" - -#include "AccessibilityCallbacks.h" -#include "AccessibilityUIElement.h" -#include "DumpRenderTree.h" -#include "WebCoreSupport/DumpRenderTreeSupportGtk.h" - -#include <atk/atk.h> -#include <gtk/gtk.h> -#include <webkit/webkit.h> -#include <wtf/gobject/GUniquePtr.h> - -AccessibilityUIElement AccessibilityController::focusedElement() -{ - AtkObject* accessible = DumpRenderTreeSupportGtk::getFocusedAccessibleElement(mainFrame); - if (!accessible) - return 0; - - return AccessibilityUIElement(accessible); -} - -AccessibilityUIElement AccessibilityController::rootElement() -{ - AtkObject* accessible = DumpRenderTreeSupportGtk::getRootAccessibleElement(mainFrame); - if (!accessible) - return 0; - - return AccessibilityUIElement(accessible); -} - -AccessibilityUIElement AccessibilityController::accessibleElementById(JSStringRef id) -{ - AtkObject* root = DumpRenderTreeSupportGtk::getRootAccessibleElement(mainFrame); - if (!root) - return 0; - - size_t bufferSize = JSStringGetMaximumUTF8CStringSize(id); - GUniquePtr<gchar> idBuffer(static_cast<gchar*>(g_malloc(bufferSize))); - JSStringGetUTF8CString(id, idBuffer.get(), bufferSize); - - AtkObject* result = childElementById(root, idBuffer.get()); - if (ATK_IS_OBJECT(result)) - return AccessibilityUIElement(result); - - return 0; - -} - -#endif // HAVE(ACCESSIBILITY) diff --git a/Tools/DumpRenderTree/gtk/DumpRenderTree.cpp b/Tools/DumpRenderTree/gtk/DumpRenderTree.cpp deleted file mode 100644 index 73d710a04..000000000 --- a/Tools/DumpRenderTree/gtk/DumpRenderTree.cpp +++ /dev/null @@ -1,1557 +0,0 @@ -/* - * Copyright (C) 2007 Eric Seidel <eric@webkit.org> - * Copyright (C) 2008 Alp Toker <alp@nuanti.com> - * Copyright (C) 2009 Jan Alonzo <jmalonzo@gmail.com> - * Copyright (C) 2010, 2011 Igalia S.L. - * - * 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. - */ - -#include "config.h" -#include "DumpRenderTree.h" - -#include "AccessibilityController.h" -#include "EditingCallbacks.h" -#include "EventSender.h" -#include "GCController.h" -#include "PixelDumpSupport.h" -#include "SelfScrollingWebKitWebView.h" -#include "TestRunner.h" -#include "TextInputController.h" -#include "WebCoreSupport/DumpRenderTreeSupportGtk.h" -#include "WebCoreTestSupport.h" -#include "WorkQueue.h" -#include "WorkQueueItem.h" -#include <JavaScriptCore/JavaScript.h> -#include <WebCore/platform/network/soup/GUniquePtrSoup.h> -#include <cassert> -#include <cstdlib> -#include <cstring> -#include <getopt.h> -#include <gtk/gtk.h> -#include <locale.h> -#include <webkit/webkit.h> -#include <wtf/Assertions.h> -#include <wtf/gobject/GlibUtilities.h> -#include <wtf/text/WTFString.h> - -#if PLATFORM(X11) -#include <fontconfig/fontconfig.h> -#endif - - -using namespace std; - -extern "C" { -// This API is not yet public. -extern gchar* webkit_web_history_item_get_target(WebKitWebHistoryItem*); -extern gboolean webkit_web_history_item_is_target_item(WebKitWebHistoryItem*); -extern GList* webkit_web_history_item_get_children(WebKitWebHistoryItem*); -extern void webkit_web_settings_add_extra_plugin_directory(WebKitWebView* view, const gchar* directory); -extern gchar* webkit_web_frame_get_response_mime_type(WebKitWebFrame* frame); -} - -volatile bool done; -static bool printSeparators; -static int dumpPixelsForAllTests = false; -static bool dumpPixelsForCurrentTest; -static int dumpTree = 1; -static int useTimeoutWatchdog = 1; - -#if HAVE(ACCESSIBILITY) -AccessibilityController* axController = 0; -#endif -RefPtr<TestRunner> gTestRunner; -static GCController* gcController = 0; -static WebKitWebView* webView; -static GtkWidget* window; -static GtkWidget* container; -static GtkWidget* webInspectorWindow; -WebKitWebFrame* mainFrame = 0; -WebKitWebFrame* topLoadingFrame = 0; -guint waitToDumpWatchdog = 0; -bool waitForPolicy = false; - -// This is a list of opened webviews -GSList* webViewList = 0; - -// current b/f item at the end of the previous test -static WebKitWebHistoryItem* prevTestBFItem = NULL; - -const unsigned historyItemIndent = 8; - -static void runTest(const string& inputLine); - -static void didRunInsecureContent(WebKitWebFrame*, WebKitSecurityOrigin*, const char* url); - -static bool shouldLogFrameLoadDelegates(const string& pathOrURL) -{ - return pathOrURL.find("loading/") != string::npos; -} - -static bool shouldOpenWebInspector(const string& pathOrURL) -{ - return pathOrURL.find("inspector/") != string::npos; -} - -static bool shouldDumpAsText(const string& pathOrURL) -{ - return pathOrURL.find("dumpAsText/") != string::npos; -} - -static bool shouldEnableDeveloperExtras(const string& pathOrURL) -{ - return true; -} - -void dumpFrameScrollPosition(WebKitWebFrame* frame) -{ - WebKitDOMDocument* document = webkit_web_frame_get_dom_document(frame); - if (!document) - return; - - WebKitDOMDOMWindow* domWindow = webkit_dom_document_get_default_view(document); - if (!domWindow) - return; - - glong x = webkit_dom_dom_window_get_page_x_offset(domWindow); - glong y = webkit_dom_dom_window_get_page_y_offset(domWindow); - - if (abs(x) > 0 || abs(y) > 0) { - if (webkit_web_frame_get_parent(frame)) - printf("frame '%s' ", webkit_web_frame_get_name(frame)); - printf("scrolled to %ld,%ld\n", x, y); - } - - if (gTestRunner->dumpChildFrameScrollPositions()) { - GSList* children = DumpRenderTreeSupportGtk::getFrameChildren(frame); - for (GSList* child = children; child; child = g_slist_next(child)) - dumpFrameScrollPosition(static_cast<WebKitWebFrame*>(child->data)); - g_slist_free(children); - } -} - -void displayWebView() -{ - DumpRenderTreeSupportGtk::forceWebViewPaint(webView); - DumpRenderTreeSupportGtk::setTracksRepaints(mainFrame, true); - DumpRenderTreeSupportGtk::resetTrackedRepaints(mainFrame); -} - -static void appendString(gchar*& target, const gchar* string) -{ - gchar* oldString = target; - target = g_strconcat(target, string, NULL); - g_free(oldString); -} - -static void initializeGtkFontSettings(const char* testURL) -{ - GtkSettings* settings = gtk_settings_get_default(); - if (!settings) - return; - g_object_set(settings, - "gtk-xft-dpi", 98304, // This is 96 * 1024 or 96 DPI according to the GTK+ docs. - "gtk-xft-antialias", 1, - "gtk-xft-hinting", 0, - "gtk-font-name", "Liberation Sans 12", - "gtk-icon-theme-name", "gnome", - NULL); - gdk_screen_set_resolution(gdk_screen_get_default(), 96.0); - - // One test needs subpixel anti-aliasing turned on, but generally we - // want all text in other tests to use to grayscale anti-aliasing. - if (testURL && strstr(testURL, "xsettings_antialias_settings.html")) - g_object_set(settings, "gtk-xft-rgba", "rgb", NULL); - else - g_object_set(settings, "gtk-xft-rgba", "none", NULL); -} - -CString getTopLevelPath() -{ - if (const gchar* topLevel = g_getenv("WEBKIT_TOP_LEVEL")) - return topLevel; - - g_setenv("WEBKIT_TOP_LEVEL", TOP_LEVEL_DIR, FALSE); - return TOP_LEVEL_DIR; -} - -CString getOutputDir() -{ - const char* webkitOutputDir = g_getenv("WEBKIT_OUTPUTDIR"); - if (webkitOutputDir) - return webkitOutputDir; - - CString topLevelPath = getTopLevelPath(); - GUniquePtr<char> outputDir(g_build_filename(topLevelPath.data(), "WebKitBuild", NULL)); - return outputDir.get(); -} - -static CString getFontsPath() -{ - CString webkitOutputDir = getOutputDir(); - GUniquePtr<char> fontsPath(g_build_filename(webkitOutputDir.data(), "Dependencies", "Root", "webkitgtk-test-fonts", NULL)); - if (g_file_test(fontsPath.get(), static_cast<GFileTest>(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) - return fontsPath.get(); - - // Try alternative fonts path. - fontsPath.reset(g_build_filename(webkitOutputDir.data(), "webkitgtk-test-fonts", NULL)); - if (g_file_test(fontsPath.get(), static_cast<GFileTest>(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) - return fontsPath.get(); - - return CString(); -} - -static void initializeFonts(const char* testURL = 0) -{ -#if PLATFORM(X11) - initializeGtkFontSettings(testURL); - - FcInit(); - - // If a test resulted a font being added or removed via the @font-face rule, then - // we want to reset the FontConfig configuration to prevent it from affecting other tests. - static int numFonts = 0; - FcFontSet* appFontSet = FcConfigGetFonts(0, FcSetApplication); - if (appFontSet && numFonts && appFontSet->nfont == numFonts) - return; - - // Load our configuration file, which sets up proper aliases for family - // names like sans, serif and monospace. - FcConfig* config = FcConfigCreate(); - GUniquePtr<gchar> fontConfigFilename(g_build_filename(FONTS_CONF_DIR, "fonts.conf", nullptr)); - if (!FcConfigParseAndLoad(config, reinterpret_cast<FcChar8*>(fontConfigFilename.get()), true)) - g_error("Couldn't load font configuration file from: %s", fontConfigFilename.get()); - - CString fontsPath = getFontsPath(); - if (fontsPath.isNull()) - g_error("Could not locate test fonts at $WEBKIT_TOP_LEVEL/WebKitBuild/Dependencies/Root/webkitgtk-test-fonts. " - "WEBKIT_TOP_LEVEL is your WebKit checkout by default, and can be overridden by setting it as an environment variable."); - - GUniquePtr<GDir> fontsDirectory(g_dir_open(fontsPath.data(), 0, nullptr)); - while (const char* directoryEntry = g_dir_read_name(fontsDirectory.get())) { - if (!g_str_has_suffix(directoryEntry, ".ttf") && !g_str_has_suffix(directoryEntry, ".otf")) - continue; - GUniquePtr<gchar> fontPath(g_build_filename(fontsPath.data(), directoryEntry, nullptr)); - if (!FcConfigAppFontAddFile(config, reinterpret_cast<const FcChar8*>(fontPath.get()))) - g_error("Could not load font at %s!", fontPath.get()); - - } - - // Ahem is used by many layout tests. - GUniquePtr<gchar> ahemFontFilename(g_build_filename(FONTS_CONF_DIR, "AHEM____.TTF", nullptr)); - if (!FcConfigAppFontAddFile(config, reinterpret_cast<FcChar8*>(ahemFontFilename.get()))) - g_error("Could not load font at %s!", ahemFontFilename.get()); - - for (int i = 1; i <= 9; i++) { - GUniquePtr<gchar> fontFilename(g_strdup_printf("WebKitWeightWatcher%i00.ttf", i)); - GUniquePtr<gchar> fontPath(g_build_filename(FONTS_CONF_DIR, "..", "..", "fonts", fontFilename.get(), nullptr)); - if (!FcConfigAppFontAddFile(config, reinterpret_cast<FcChar8*>(fontPath.get()))) - g_error("Could not load font at %s!", fontPath.get()); - } - - // A font with no valid Fontconfig encoding to test https://bugs.webkit.org/show_bug.cgi?id=47452 - GUniquePtr<gchar> fontWithNoValidEncodingFilename(g_build_filename(FONTS_CONF_DIR, "FontWithNoValidEncoding.fon", nullptr)); - if (!FcConfigAppFontAddFile(config, reinterpret_cast<FcChar8*>(fontWithNoValidEncodingFilename.get()))) - g_error("Could not load font at %s!", fontWithNoValidEncodingFilename.get()); - - if (!FcConfigSetCurrent(config)) - g_error("Could not set the current font configuration!"); - - numFonts = FcConfigGetFonts(config, FcSetApplication)->nfont; -#endif -} - -static gchar* dumpFramesAsText(WebKitWebFrame* frame) -{ - gchar* result = 0; - - // Add header for all but the main frame. - bool isMainFrame = (webkit_web_view_get_main_frame(webView) == frame); - - CString innerText = DumpRenderTreeSupportGtk::getInnerText(frame); - if (isMainFrame) - result = g_strdup_printf("%s\n", innerText.data()); - else { - const gchar* frameName = webkit_web_frame_get_name(frame); - result = g_strdup_printf("\n--------\nFrame: '%s'\n--------\n%s\n", frameName, innerText.data()); - } - - if (gTestRunner->dumpChildFramesAsText()) { - GSList* children = DumpRenderTreeSupportGtk::getFrameChildren(frame); - for (GSList* child = children; child; child = g_slist_next(child)) { - GUniquePtr<gchar> childData(dumpFramesAsText(static_cast<WebKitWebFrame*>(child->data))); - appendString(result, childData.get()); - } - g_slist_free(children); - } - - return result; -} - -static gint compareHistoryItems(gpointer* item1, gpointer* item2) -{ - GUniquePtr<gchar> firstItemTarget(webkit_web_history_item_get_target(WEBKIT_WEB_HISTORY_ITEM(item1))); - GUniquePtr<gchar> secondItemTarget(webkit_web_history_item_get_target(WEBKIT_WEB_HISTORY_ITEM(item2))); - return g_ascii_strcasecmp(firstItemTarget.get(), secondItemTarget.get()); -} - -static void dumpHistoryItem(WebKitWebHistoryItem* item, int indent, bool current) -{ - ASSERT(item != NULL); - int start = 0; - g_object_ref(item); - if (current) { - printf("curr->"); - start = 6; - } - for (int i = start; i < indent; i++) - putchar(' '); - - // normalize file URLs. - const gchar* uri = webkit_web_history_item_get_uri(item); - gchar* uriScheme = g_uri_parse_scheme(uri); - if (g_strcmp0(uriScheme, "file") == 0) { - gchar* pos = g_strstr_len(uri, -1, "/LayoutTests/"); - if (!pos) { - g_free(uriScheme); - return; - } - - GString* result = g_string_sized_new(strlen(uri)); - result = g_string_append(result, "(file test):"); - result = g_string_append(result, pos + strlen("/LayoutTests/")); - printf("%s", result->str); - g_string_free(result, TRUE); - } else - printf("%s", uri); - - g_free(uriScheme); - - GUniquePtr<gchar> target(webkit_web_history_item_get_target(item)); - if (target.get() && strlen(target.get()) > 0) - printf(" (in frame \"%s\")", target.get()); - if (webkit_web_history_item_is_target_item(item)) - printf(" **nav target**"); - putchar('\n'); - - if (GList* kids = webkit_web_history_item_get_children(item)) { - // must sort to eliminate arbitrary result ordering which defeats reproducible testing - for (GList* kid = g_list_sort(kids, (GCompareFunc) compareHistoryItems); kid; kid = g_list_next(kid)) { - WebKitWebHistoryItem* item = WEBKIT_WEB_HISTORY_ITEM(kid->data); - dumpHistoryItem(item, indent + 4, FALSE); - g_object_unref(item); - } - g_list_free(kids); - } - g_object_unref(item); -} - -static void dumpBackForwardListForWebView(WebKitWebView* view) -{ - printf("\n============== Back Forward List ==============\n"); - WebKitWebBackForwardList* bfList = webkit_web_view_get_back_forward_list(view); - - // Print out all items in the list after prevTestBFItem, which was from the previous test - // Gather items from the end of the list, the print them out from oldest to newest - GList* itemsToPrint = NULL; - gint forwardListCount = webkit_web_back_forward_list_get_forward_length(bfList); - for (int i = forwardListCount; i > 0; i--) { - WebKitWebHistoryItem* item = webkit_web_back_forward_list_get_nth_item(bfList, i); - // something is wrong if the item from the last test is in the forward part of the b/f list - ASSERT(item != prevTestBFItem); - g_object_ref(item); - itemsToPrint = g_list_prepend(itemsToPrint, item); - } - - WebKitWebHistoryItem* currentItem = webkit_web_back_forward_list_get_current_item(bfList); - g_object_ref(currentItem); - itemsToPrint = g_list_prepend(itemsToPrint, currentItem); - - gint backListCount = webkit_web_back_forward_list_get_back_length(bfList); - for (int i = -1; i >= -(backListCount); i--) { - WebKitWebHistoryItem* item = webkit_web_back_forward_list_get_nth_item(bfList, i); - if (item == prevTestBFItem) - break; - g_object_ref(item); - itemsToPrint = g_list_prepend(itemsToPrint, item); - } - - for (GList* itemToPrint = itemsToPrint; itemToPrint; itemToPrint = g_list_next(itemToPrint)) { - WebKitWebHistoryItem* item = WEBKIT_WEB_HISTORY_ITEM(itemToPrint->data); - dumpHistoryItem(item, historyItemIndent, item == currentItem); - g_object_unref(item); - } - - g_list_free(itemsToPrint); - printf("===============================================\n"); -} - -static void dumpBackForwardListForAllWebViews() -{ - // Dump the back forward list of the main WebView first - dumpBackForwardListForWebView(webView); - - // The view list is prepended. Reverse the list so we get the order right. - for (GSList* currentView = g_slist_reverse(webViewList); currentView; currentView = g_slist_next(currentView)) - dumpBackForwardListForWebView(WEBKIT_WEB_VIEW(currentView->data)); -} - -void setWaitToDumpWatchdog(guint timer) -{ - waitToDumpWatchdog = timer; -} - -bool shouldSetWaitToDumpWatchdog() -{ - return !waitToDumpWatchdog && useTimeoutWatchdog; -} - -CString soupURIToStringPreservingPassword(SoupURI* soupURI) -{ - if (!soupURI->password) { - GUniquePtr<char> uriString(soup_uri_to_string(soupURI, FALSE)); - return uriString.get(); - } - - // soup_uri_to_string does not insert the password into the string, so we need to create the - // URI string and then reinsert any credentials that were present in the SoupURI. All tests that - // use URL-embedded credentials use HTTP, so it's safe here. - GUniquePtr<char> password(soupURI->password); - GUniquePtr<char> user(soupURI->user); - soupURI->password = 0; - soupURI->user = 0; - - GUniquePtr<char> uriString(soup_uri_to_string(soupURI, FALSE)); - String absoluteURIWithoutCredentialString = String::fromUTF8(uriString.get()); - String protocolAndCredential = String::format("http://%s:%s@", user ? user.get() : "", password.get()); - return absoluteURIWithoutCredentialString.replace("http://", protocolAndCredential).utf8(); -} - -static void invalidateAnyPreviousWaitToDumpWatchdog() -{ - if (waitToDumpWatchdog) { - g_source_remove(waitToDumpWatchdog); - waitToDumpWatchdog = 0; - } - - waitForPolicy = false; -} - -static void resetDefaultsToConsistentValues() -{ - WebKitWebSettings* settings = webkit_web_view_get_settings(webView); - GUniquePtr<gchar> localStoragePath(g_build_filename(g_get_user_data_dir(), "DumpRenderTreeGtk", "databases", nullptr)); - g_object_set(G_OBJECT(settings), - "enable-accelerated-compositing", FALSE, - "enable-private-browsing", FALSE, - "enable-developer-extras", FALSE, - "enable-spell-checking", TRUE, - "enable-html5-database", TRUE, - "enable-html5-local-storage", TRUE, - "html5-local-storage-database-path", localStoragePath.get(), - "enable-xss-auditor", FALSE, - "enable-spatial-navigation", FALSE, - "javascript-can-access-clipboard", TRUE, - "javascript-can-open-windows-automatically", TRUE, - "enable-offline-web-application-cache", TRUE, - "enable-universal-access-from-file-uris", TRUE, - "enable-file-access-from-file-uris", TRUE, - "enable-scripts", TRUE, - "enable-dom-paste", TRUE, - "default-font-family", "Times", - "monospace-font-family", "Courier", - "serif-font-family", "Times", - "sans-serif-font-family", "Helvetica", - "cursive-font-family", "cursive", - "fantasy-font-family", "fantasy", - "default-font-size", 12, - "default-monospace-font-size", 10, - "minimum-font-size", 0, - "enable-caret-browsing", FALSE, - "enable-page-cache", FALSE, - "auto-resize-window", TRUE, - "auto-load-images", TRUE, - "enable-java-applet", FALSE, - "enable-plugins", TRUE, - "enable-hyperlink-auditing", FALSE, - "editing-behavior", WEBKIT_EDITING_BEHAVIOR_UNIX, - "enable-fullscreen", TRUE, - "enable-mediasource", TRUE, - NULL); - webkit_web_view_set_settings(webView, settings); - webkit_set_cache_model(WEBKIT_CACHE_MODEL_DOCUMENT_BROWSER); - - DumpRenderTreeSupportGtk::clearMainFrameName(mainFrame); - DumpRenderTreeSupportGtk::scalePageBy(webView, 1, 0, 0); - - 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); - - DumpRenderTreeSupportGtk::resetOriginAccessWhiteLists(); - - WebKitWebBackForwardList* list = webkit_web_view_get_back_forward_list(webView); - webkit_web_back_forward_list_clear(list); - - SoupSession* session = webkit_get_default_session(); - SoupCookieJar* jar = reinterpret_cast<SoupCookieJar*>(soup_session_get_feature(session, SOUP_TYPE_COOKIE_JAR)); - - // We only create the jar when the soup backend needs to do - // HTTP. Should we initialize it earlier, perhaps? - if (jar) - g_object_set(G_OBJECT(jar), SOUP_COOKIE_JAR_ACCEPT_POLICY, SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY, NULL); - - setlocale(LC_ALL, ""); - - DumpRenderTreeSupportGtk::setLinksIncludedInFocusChain(true); - webkit_icon_database_set_path(webkit_get_icon_database(), 0); - DumpRenderTreeSupportGtk::setDefersLoading(webView, false); - DumpRenderTreeSupportGtk::setSerializeHTTPLoads(false); - -#if HAVE(ACCESSIBILITY) - if (axController) - axController->resetToConsistentState(); -#endif - - DumpRenderTreeSupportGtk::clearOpener(mainFrame); - DumpRenderTreeSupportGtk::setTracksRepaints(mainFrame, false); - - DumpRenderTreeSupportGtk::resetGeolocationClientMock(webView); - - DumpRenderTreeSupportGtk::setCSSGridLayoutEnabled(webView, false); - DumpRenderTreeSupportGtk::setCSSRegionsEnabled(webView, true); - DumpRenderTreeSupportGtk::setExperimentalContentSecurityPolicyFeaturesEnabled(true); - DumpRenderTreeSupportGtk::setSeamlessIFramesEnabled(true); - DumpRenderTreeSupportGtk::setShadowDOMEnabled(true); - - if (gTestRunner) { - gTestRunner->setAuthenticationPassword(""); - gTestRunner->setAuthenticationUsername(""); - gTestRunner->setHandlesAuthenticationChallenges(false); - } - - gtk_widget_set_direction(GTK_WIDGET(webView), GTK_TEXT_DIR_NONE); -} - -static bool useLongRunningServerMode(int argc, char *argv[]) -{ - // This assumes you've already called getopt_long - return (argc == optind+1 && !strcmp(argv[optind], "-")); -} - -static void runTestingServerLoop() -{ - // When DumpRenderTree runs in server mode, we just wait around for file names - // to be passed to us and read each in turn, passing the results back to the client - char filenameBuffer[2048]; - while (fgets(filenameBuffer, sizeof(filenameBuffer), stdin)) { - char* newLineCharacter = strchr(filenameBuffer, '\n'); - if (newLineCharacter) - *newLineCharacter = '\0'; - - if (!strlen(filenameBuffer)) - continue; - - runTest(filenameBuffer); - } -} - -static void initializeGlobalsFromCommandLineOptions(int argc, char *argv[]) -{ - struct option options[] = { - {"notree", no_argument, &dumpTree, false}, - {"pixel-tests", no_argument, &dumpPixelsForAllTests, true}, - {"tree", no_argument, &dumpTree, true}, - {"no-timeout", no_argument, &useTimeoutWatchdog, false}, - {NULL, 0, NULL, 0} - }; - - int option; - while ((option = getopt_long(argc, (char * const *)argv, "", options, NULL)) != -1) { - switch (option) { - case '?': // unknown or ambiguous option - case ':': // missing argument - exit(1); - break; - } - } -} - - -void dump() -{ - invalidateAnyPreviousWaitToDumpWatchdog(); - - // Grab widget focus before dumping the contents of a widget, in - // case it was lost in the course of the test. - gtk_widget_grab_focus(GTK_WIDGET(webView)); - - if (dumpTree) { - char* result = 0; - gchar* responseMimeType = webkit_web_frame_get_response_mime_type(mainFrame); - - if (g_str_equal(responseMimeType, "text/plain")) { - gTestRunner->setDumpAsText(true); - gTestRunner->setGeneratePixelResults(false); - } - g_free(responseMimeType); - - if (gTestRunner->dumpAsText()) - result = dumpFramesAsText(mainFrame); - else { - // Widget resizing is done asynchronously in GTK+. We pump the main - // loop here, to flush any pending resize requests. This prevents - // timing issues which affect the size of elements in the output. - // We only enable this workaround for tests that print the render tree - // because this seems to break some dumpAsText tests: see bug 39988 - // After fixing that test, we should apply this approach to all dumps. - while (gtk_events_pending()) - gtk_main_iteration(); - - result = g_strdup(DumpRenderTreeSupportGtk::dumpRenderTree(mainFrame).data()); - } - - if (!result) { - const char* errorMessage; - if (gTestRunner->dumpAsText()) - errorMessage = "[documentElement innerText]"; - else if (gTestRunner->dumpDOMAsWebArchive()) - errorMessage = "[[mainFrame DOMDocument] webArchive]"; - else if (gTestRunner->dumpSourceAsWebArchive()) - errorMessage = "[[mainFrame dataSource] webArchive]"; - else - errorMessage = "[mainFrame renderTreeAsExternalRepresentation]"; - printf("ERROR: nil result from %s", errorMessage); - } else { - printf("%s", result); - g_free(result); - if (!gTestRunner->dumpAsText() && !gTestRunner->dumpDOMAsWebArchive() && !gTestRunner->dumpSourceAsWebArchive()) - dumpFrameScrollPosition(mainFrame); - - if (gTestRunner->dumpBackForwardList()) - dumpBackForwardListForAllWebViews(); - } - - if (printSeparators) { - puts("#EOF"); // terminate the content block - fputs("#EOF\n", stderr); - fflush(stdout); - fflush(stderr); - } - } - - if (dumpPixelsForCurrentTest - && gTestRunner->generatePixelResults() - && !gTestRunner->dumpDOMAsWebArchive() - && !gTestRunner->dumpSourceAsWebArchive()) { - DumpRenderTreeSupportGtk::forceWebViewPaint(webView); - dumpWebViewAsPixelsAndCompareWithExpected(gTestRunner->expectedPixelHash()); - } - - // FIXME: call displayWebView here when we support --paint - - done = true; - gtk_main_quit(); -} - -static CString temporaryDatabaseDirectory() -{ - const char* directoryFromEnvironment = g_getenv("DUMPRENDERTREE_TEMP"); - if (directoryFromEnvironment) - return directoryFromEnvironment; - GUniquePtr<char> fallback(g_build_filename(g_get_user_data_dir(), "gtkwebkitdrt", "databases", NULL)); - return fallback.get(); -} - -static void setDefaultsToConsistentStateValuesForTesting() -{ - resetDefaultsToConsistentValues(); - -#if PLATFORM(X11) - webkit_web_settings_add_extra_plugin_directory(webView, TEST_PLUGIN_DIR); -#endif - - webkit_set_web_database_directory_path(temporaryDatabaseDirectory().data()); - -#if defined(GTK_API_VERSION_2) - gtk_rc_parse_string("style \"nix_scrollbar_spacing\" " - "{ " - " GtkScrolledWindow::scrollbar-spacing = 0 " - "} " - "class \"GtkWidget\" style \"nix_scrollbar_spacing\""); - -#else - GtkCssProvider* cssProvider = gtk_css_provider_new(); - gtk_css_provider_load_from_data(cssProvider, - "@binding-set NoKeyboardNavigation { " - " unbind \"<shift>F10\"; " - "} " - " * { " - " -GtkScrolledWindow-scrollbar-spacing: 0;" - " gtk-key-bindings: NoKeyboardNavigation; " - "} ", - -1, 0); - gtk_style_context_add_provider_for_screen(gdk_display_get_default_screen(gdk_display_get_default()), - GTK_STYLE_PROVIDER(cssProvider), - GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); - g_object_unref(cssProvider); -#endif -} - -static void sendPixelResultsEOF() -{ - puts("#EOF"); - - fflush(stdout); - fflush(stderr); -} - -static void runTest(const string& inputLine) -{ - ASSERT(!inputLine.empty()); - - TestCommand command = parseInputLine(inputLine); - string& testURL = command.pathOrURL; - dumpPixelsForCurrentTest = command.shouldDumpPixels || dumpPixelsForAllTests; - - // Convert the path into a full file URL if it does not look - // like an HTTP/S URL (doesn't start with http:// or https://). - if (testURL.find("http://") && testURL.find("https://")) { - GFile* testFile = g_file_new_for_path(testURL.c_str()); - gchar* testURLCString = g_file_get_uri(testFile); - testURL = testURLCString; - g_free(testURLCString); - g_object_unref(testFile); - } - - resetDefaultsToConsistentValues(); - - gTestRunner = TestRunner::create(testURL, command.expectedPixelHash); - topLoadingFrame = 0; - done = false; - - gTestRunner->setIconDatabaseEnabled(false); - - if (shouldLogFrameLoadDelegates(testURL)) - gTestRunner->setDumpFrameLoadCallbacks(true); - - if (shouldEnableDeveloperExtras(testURL)) { - gTestRunner->setDeveloperExtrasEnabled(true); - if (shouldOpenWebInspector(testURL)) - gTestRunner->showWebInspector(); - if (shouldDumpAsText(testURL)) { - gTestRunner->setDumpAsText(true); - gTestRunner->setGeneratePixelResults(false); - } - } - - WorkQueue::shared()->clear(); - WorkQueue::shared()->setFrozen(false); - - bool isSVGW3CTest = (testURL.find("svg/W3C-SVG-1.1") != string::npos); - GtkAllocation size; - size.x = size.y = 0; - size.width = isSVGW3CTest ? TestRunner::w3cSVGViewWidth : TestRunner::viewWidth; - size.height = isSVGW3CTest ? TestRunner::w3cSVGViewHeight : TestRunner::viewHeight; - gtk_window_resize(GTK_WINDOW(window), size.width, size.height); - gtk_widget_size_allocate(container, &size); - - if (prevTestBFItem) - g_object_unref(prevTestBFItem); - WebKitWebBackForwardList* bfList = webkit_web_view_get_back_forward_list(webView); - prevTestBFItem = webkit_web_back_forward_list_get_current_item(bfList); - if (prevTestBFItem) - g_object_ref(prevTestBFItem); - - initializeFonts(testURL.c_str()); - - // Focus the web view before loading the test to avoid focusing problems - gtk_widget_grab_focus(GTK_WIDGET(webView)); - webkit_web_view_open(webView, testURL.c_str()); - - gtk_main(); - - // If developer extras enabled Web Inspector may have been open by the test. - if (shouldEnableDeveloperExtras(testURL)) { - gTestRunner->closeWebInspector(); - gTestRunner->setDeveloperExtrasEnabled(false); - } - - // Also check if we still have opened webViews and free them. - if (gTestRunner->closeRemainingWindowsWhenComplete() || webViewList) { - while (webViewList) { - g_object_unref(WEBKIT_WEB_VIEW(webViewList->data)); - webViewList = g_slist_next(webViewList); - } - g_slist_free(webViewList); - webViewList = 0; - } - - WebCoreTestSupport::resetInternalsObject(webkit_web_frame_get_global_context(mainFrame)); - DumpRenderTreeSupportGtk::clearMemoryCache(); - DumpRenderTreeSupportGtk::clearApplicationCache(); - - // A blank load seems to be necessary to reset state after certain tests. - webkit_web_view_open(webView, "about:blank"); - - gTestRunner.clear(); - - // terminate the (possibly empty) pixels block after all the state reset - sendPixelResultsEOF(); -} - -void webViewLoadStarted(WebKitWebView* view, WebKitWebFrame* frame, void*) -{ - // Make sure we only set this once per test. If it gets cleared, and then set again, we might - // end up doing two dumps for one test. - if (!topLoadingFrame && !done) - topLoadingFrame = frame; -} - -static gboolean processWork(void* data) -{ - // if we finish all the commands, we're ready to dump state - if (WorkQueue::shared()->processWork() && !gTestRunner->waitToDump()) - dump(); - - return FALSE; -} - -static char* getFrameNameSuitableForTestResult(WebKitWebView* view, WebKitWebFrame* frame) -{ - char* frameName = g_strdup(webkit_web_frame_get_name(frame)); - - if (frame == webkit_web_view_get_main_frame(view)) { - // This is a bit strange. Shouldn't web_frame_get_name return NULL? - if (frameName && (frameName[0] != '\0')) { - char* tmp = g_strdup_printf("main frame \"%s\"", frameName); - g_free(frameName); - frameName = tmp; - } else { - g_free(frameName); - frameName = g_strdup("main frame"); - } - } else if (!frameName || (frameName[0] == '\0')) { - g_free(frameName); - frameName = g_strdup("frame (anonymous)"); - } else { - char* tmp = g_strdup_printf("frame \"%s\"", frameName); - g_free(frameName); - frameName = tmp; - } - - return frameName; -} - -static void webViewLoadFinished(WebKitWebView* view, WebKitWebFrame* frame, void*) -{ - // The deprecated "load-finished" signal is triggered by postProgressFinishedNotification(), - // so we can use it here in the DRT to provide the correct dump. - if (frame != topLoadingFrame) - return; - if (gTestRunner->dumpProgressFinishedCallback()) - printf("postProgressFinishedNotification\n"); -} - -static gboolean webViewLoadError(WebKitWebView*, WebKitWebFrame*, gchar*, gpointer, gpointer) -{ - return TRUE; // Return true here to disable the default error page. -} - -static void webViewDocumentLoadFinished(WebKitWebView* view, WebKitWebFrame* frame, void*) -{ - if (!done && gTestRunner->dumpFrameLoadCallbacks()) { - char* frameName = getFrameNameSuitableForTestResult(view, frame); - printf("%s - didFinishDocumentLoadForFrame\n", frameName); - g_free(frameName); - } else if (!done) { - guint pendingFrameUnloadEvents = DumpRenderTreeSupportGtk::getPendingUnloadEventCount(frame); - if (pendingFrameUnloadEvents) { - char* frameName = getFrameNameSuitableForTestResult(view, frame); - printf("%s - has %u onunload handler(s)\n", frameName, pendingFrameUnloadEvents); - g_free(frameName); - } - } -} - -static void webViewOnloadEvent(WebKitWebView* view, WebKitWebFrame* frame, void*) -{ - if (!done && gTestRunner->dumpFrameLoadCallbacks()) { - char* frameName = getFrameNameSuitableForTestResult(view, frame); - printf("%s - didHandleOnloadEventsForFrame\n", frameName); - g_free(frameName); - } -} - -static void addControllerToWindow(JSContextRef context, JSObjectRef windowObject, const char* controllerName, JSValueRef controller) -{ - JSStringRef controllerNameStr = JSStringCreateWithUTF8CString(controllerName); - JSObjectSetProperty(context, windowObject, controllerNameStr, controller, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, 0); - JSStringRelease(controllerNameStr); -} - -static void webViewWindowObjectCleared(WebKitWebView* view, WebKitWebFrame* frame, JSGlobalContextRef context, JSObjectRef windowObject, gpointer data) -{ - JSValueRef exception = 0; - ASSERT(gTestRunner); - - gTestRunner->makeWindowObject(context, windowObject, &exception); - ASSERT(!exception); - - gcController->makeWindowObject(context, windowObject, &exception); - ASSERT(!exception); - -#if HAVE(ACCESSIBILITY) - axController->makeWindowObject(context, windowObject, &exception); - ASSERT(!exception); -#endif - - addControllerToWindow(context, windowObject, "eventSender", makeEventSender(context, !webkit_web_frame_get_parent(frame))); - addControllerToWindow(context, windowObject, "textInputController", makeTextInputController(context)); - WebCoreTestSupport::injectInternalsObject(context); -} - -static gboolean webViewConsoleMessage(WebKitWebView* view, const gchar* message, unsigned int line, const gchar* sourceId, gpointer data) -{ - gchar* testMessage = 0; - const gchar* uriScheme; - - // Tests expect only the filename part of local URIs - uriScheme = g_strstr_len(message, -1, "file://"); - if (uriScheme) { - GString* tempString = g_string_sized_new(strlen(message)); - gchar* filename = g_strrstr(uriScheme, G_DIR_SEPARATOR_S); - - if (filename) { - // If the path is a lone slash, keep it to avoid empty output. - if (strlen(filename) > 1) - filename += strlen(G_DIR_SEPARATOR_S); - tempString = g_string_append_len(tempString, message, (uriScheme - message)); - tempString = g_string_append_len(tempString, filename, strlen(filename)); - testMessage = g_string_free(tempString, FALSE); - } - } - - fprintf(stdout, "CONSOLE MESSAGE: "); - if (line) - fprintf(stdout, "line %d: ", line); - fprintf(stdout, "%s\n", testMessage ? testMessage : message); - g_free(testMessage); - - return TRUE; -} - - -static gboolean webViewScriptAlert(WebKitWebView* view, WebKitWebFrame* frame, const gchar* message, gpointer data) -{ - fprintf(stdout, "ALERT: %s\n", message); - fflush(stdout); - return TRUE; -} - -static gboolean webViewScriptPrompt(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message, const gchar* defaultValue, gchar** value, gpointer data) -{ - fprintf(stdout, "PROMPT: %s, default text: %s\n", message, defaultValue); - *value = g_strdup(defaultValue); - return TRUE; -} - -static gboolean webViewScriptConfirm(WebKitWebView* view, WebKitWebFrame* frame, const gchar* message, gboolean* didConfirm, gpointer data) -{ - fprintf(stdout, "CONFIRM: %s\n", message); - *didConfirm = TRUE; - return TRUE; -} - -static void webViewTitleChanged(WebKitWebView* view, WebKitWebFrame* frame, const gchar* title, gpointer data) -{ - if (gTestRunner->dumpFrameLoadCallbacks() && !done) { - GUniquePtr<char> frameName(getFrameNameSuitableForTestResult(view, frame)); - printf("%s - didReceiveTitle: %s\n", frameName.get(), title ? title : ""); - } - - if (gTestRunner->dumpTitleChanges() && !done) - printf("TITLE CHANGED: '%s'\n", title ? title : ""); -} - -static bool webViewNavigationPolicyDecisionRequested(WebKitWebView* view, WebKitWebFrame* frame, - WebKitNetworkRequest* request, - WebKitWebNavigationAction* navAction, - WebKitWebPolicyDecision* policyDecision) -{ - // Use the default handler if we're not waiting for policy, - // i.e., TestRunner::waitForPolicyDelegate - if (!waitForPolicy) - return FALSE; - - gchar* typeDescription; - WebKitWebNavigationReason reason; - g_object_get(G_OBJECT(navAction), "reason", &reason, NULL); - - switch(reason) { - case WEBKIT_WEB_NAVIGATION_REASON_LINK_CLICKED: - typeDescription = g_strdup("link clicked"); - break; - case WEBKIT_WEB_NAVIGATION_REASON_FORM_SUBMITTED: - typeDescription = g_strdup("form submitted"); - break; - case WEBKIT_WEB_NAVIGATION_REASON_BACK_FORWARD: - typeDescription = g_strdup("back/forward"); - break; - case WEBKIT_WEB_NAVIGATION_REASON_RELOAD: - typeDescription = g_strdup("reload"); - break; - case WEBKIT_WEB_NAVIGATION_REASON_FORM_RESUBMITTED: - typeDescription = g_strdup("form resubmitted"); - break; - case WEBKIT_WEB_NAVIGATION_REASON_OTHER: - typeDescription = g_strdup("other"); - break; - default: - typeDescription = g_strdup("illegal value"); - } - - printf("Policy delegate: attempt to load %s with navigation type '%s'\n", webkit_network_request_get_uri(request), typeDescription); - g_free(typeDescription); - - webkit_web_policy_decision_ignore(policyDecision); - gTestRunner->notifyDone(); - - return TRUE; -} - -static void webViewStatusBarTextChanged(WebKitWebView* view, const gchar* message, gpointer data) -{ - // Are we doing anything wrong? One test that does not call - // dumpStatusCallbacks gets true here - if (gTestRunner->dumpStatusCallbacks()) - printf("UI DELEGATE STATUS CALLBACK: setStatusText:%s\n", message); -} - -static gboolean webViewClose(WebKitWebView* view) -{ - ASSERT(view); - - webViewList = g_slist_remove(webViewList, view); - g_object_unref(view); - - return TRUE; -} - -static void databaseQuotaExceeded(WebKitWebView* view, WebKitWebFrame* frame, WebKitWebDatabase *database) -{ - ASSERT(view); - ASSERT(frame); - ASSERT(database); - - WebKitSecurityOrigin* origin = webkit_web_database_get_security_origin(database); - if (gTestRunner->dumpDatabaseCallbacks()) { - printf("UI DELEGATE DATABASE CALLBACK: exceededDatabaseQuotaForSecurityOrigin:{%s, %s, %i} database:%s\n", - webkit_security_origin_get_protocol(origin), - webkit_security_origin_get_host(origin), - webkit_security_origin_get_port(origin), - webkit_web_database_get_name(database)); - } - webkit_security_origin_set_web_database_quota(origin, 5 * 1024 * 1024); -} - -static bool -geolocationPolicyDecisionRequested(WebKitWebView*, WebKitWebFrame*, WebKitGeolocationPolicyDecision* decision) -{ - if (!gTestRunner->isGeolocationPermissionSet()) - return FALSE; - if (gTestRunner->geolocationPermission()) - webkit_geolocation_policy_allow(decision); - else - webkit_geolocation_policy_deny(decision); - - return TRUE; -} - - -static WebKitWebView* webViewCreate(WebKitWebView*, WebKitWebFrame*); - -static gboolean webInspectorShowWindow(WebKitWebInspector*, gpointer data) -{ - gtk_window_set_default_size(GTK_WINDOW(webInspectorWindow), TestRunner::viewWidth, TestRunner::viewHeight); - gtk_widget_show_all(webInspectorWindow); - return TRUE; -} - -static gboolean webInspectorCloseWindow(WebKitWebInspector*, gpointer data) -{ - gtk_widget_destroy(webInspectorWindow); - webInspectorWindow = 0; - return TRUE; -} - -static WebKitWebView* webInspectorInspectWebView(WebKitWebInspector*, gpointer data) -{ - webInspectorWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); - - GtkWidget* webView = self_scrolling_webkit_web_view_new(); - gtk_container_add(GTK_CONTAINER(webInspectorWindow), - webView); - - return WEBKIT_WEB_VIEW(webView); -} - -static void topLoadingFrameLoadFinished() -{ - topLoadingFrame = 0; - WorkQueue::shared()->setFrozen(true); // first complete load freezes the queue for the rest of this test - if (gTestRunner->waitToDump()) - return; - - if (WorkQueue::shared()->count()) - g_idle_add_full(G_PRIORITY_DEFAULT, processWork, 0, 0); - else - dump(); -} - -static void webFrameLoadStatusNotified(WebKitWebFrame* frame, gpointer user_data) -{ - WebKitLoadStatus loadStatus = webkit_web_frame_get_load_status(frame); - - if (gTestRunner->dumpFrameLoadCallbacks()) { - GUniquePtr<char> frameName(getFrameNameSuitableForTestResult(webkit_web_frame_get_web_view(frame), frame)); - - switch (loadStatus) { - case WEBKIT_LOAD_PROVISIONAL: - if (!done) - printf("%s - didStartProvisionalLoadForFrame\n", frameName.get()); - break; - case WEBKIT_LOAD_COMMITTED: - if (!done) - printf("%s - didCommitLoadForFrame\n", frameName.get()); - break; - case WEBKIT_LOAD_FINISHED: - if (!done) - printf("%s - didFinishLoadForFrame\n", frameName.get()); - break; - case WEBKIT_LOAD_FAILED: - if (!done) - printf("%s - didFailLoadWithError\n", frameName.get()); - break; - default: - break; - } - } - - if ((loadStatus == WEBKIT_LOAD_FINISHED || loadStatus == WEBKIT_LOAD_FAILED) - && frame == topLoadingFrame) - topLoadingFrameLoadFinished(); -} - -static void frameCreatedCallback(WebKitWebView* webView, WebKitWebFrame* webFrame, gpointer user_data) -{ - g_signal_connect(webFrame, "notify::load-status", G_CALLBACK(webFrameLoadStatusNotified), NULL); - g_signal_connect(webFrame, "insecure-content-run", G_CALLBACK(didRunInsecureContent), NULL); -} - -static String pathFromSoupURI(SoupURI* uri) -{ - if (!uri) - return "(null)"; - - if (!g_str_equal(uri->scheme, "file")) - return soupURIToStringPreservingPassword(uri).data(); - - String pathString = uri->path; - GUniquePtr<gchar> pathBasename(g_path_get_basename(pathString.utf8().data())); - - WebKitWebFrame* mainFrame = webkit_web_view_get_main_frame(webView); - GUniquePtr<SoupURI> mainFrameUri(soup_uri_new(webkit_web_frame_get_uri(mainFrame))); - - String mainFrameUriPathString = mainFrameUri.get()->path; - String basePath = mainFrameUriPathString.substring(0, mainFrameUriPathString.reverseFind('/') + 1); - - if (!basePath.isEmpty() && pathString.startsWith(basePath)) - return pathString.substring(basePath.length()); - - return pathBasename.get(); -} - -static CString convertSoupMessageToURLPath(SoupMessage* soupMessage) -{ - if (!soupMessage) - return CString("(null)"); - if (SoupURI* requestURI = soup_message_get_uri(soupMessage)) - return pathFromSoupURI(requestURI).utf8(); - return CString("(null)"); -} - -static CString convertNetworkRequestToURLPath(WebKitNetworkRequest* request) -{ - return convertSoupMessageToURLPath(webkit_network_request_get_message(request)); -} - -static CString convertWebResourceToURLPath(WebKitWebResource* webResource) -{ - GUniquePtr<SoupURI> uri(soup_uri_new(webkit_web_resource_get_uri(webResource))); - return pathFromSoupURI(uri.get()).utf8(); -} - -static CString urlSuitableForTestResult(const char* uriString) -{ - if (!g_str_has_prefix(uriString, "file://")) - return CString(uriString); - - GUniquePtr<gchar> basename(g_path_get_basename(uriString)); - return CString(basename.get()); -} - -static CString descriptionSuitableForTestResult(SoupURI* uri) -{ - if (!uri) - return CString("(null)"); - - GUniquePtr<char> uriString(soup_uri_to_string(uri, false)); - return urlSuitableForTestResult(uriString.get()); -} - -static CString descriptionSuitableForTestResult(GError* error, WebKitWebResource* webResource) -{ - const gchar* errorDomain = g_quark_to_string(error->domain); - CString resourceURIString(urlSuitableForTestResult(webkit_web_resource_get_uri(webResource))); - - if (g_str_equal(errorDomain, "webkit-network-error-quark") || g_str_equal(errorDomain, "soup_http_error_quark")) - errorDomain = "NSURLErrorDomain"; - - if (g_str_equal(errorDomain, "WebKitPolicyError")) - errorDomain = "WebKitErrorDomain"; - - // TODO: the other ports get the failingURL from the ResourceError - GUniquePtr<char> errorString(g_strdup_printf("<NSError domain %s, code %d, failing URL \"%s\">", - errorDomain, error->code, resourceURIString.data())); - return CString(errorString.get()); -} - -static CString descriptionSuitableForTestResult(WebKitNetworkRequest* request) -{ - SoupMessage* soupMessage = webkit_network_request_get_message(request); - - if (!soupMessage) - return CString("(null)"); - - SoupURI* mainDocumentURI = soup_message_get_first_party(soupMessage); - CString mainDocumentURIString(descriptionSuitableForTestResult(mainDocumentURI)); - CString path(convertNetworkRequestToURLPath(request)); - GUniquePtr<char> description(g_strdup_printf("<NSURLRequest URL %s, main document URL %s, http method %s>", - path.data(), mainDocumentURIString.data(), soupMessage->method)); - return CString(description.get()); -} - -static CString descriptionSuitableForTestResult(WebKitNetworkResponse* response) -{ - if (!response) - return CString("(null)"); - - int statusCode = 0; - CString responseURIString(urlSuitableForTestResult(webkit_network_response_get_uri(response))); - SoupMessage* soupMessage = webkit_network_response_get_message(response); - CString path; - - if (soupMessage) { - statusCode = soupMessage->status_code; - path = convertSoupMessageToURLPath(soupMessage); - } else - path = CString("(null)"); - - GUniquePtr<char> description(g_strdup_printf("<NSURLResponse %s, http status code %d>", path.data(), statusCode)); - return CString(description.get()); -} - -static void willSendRequestCallback(WebKitWebView* webView, WebKitWebFrame* webFrame, WebKitWebResource* resource, WebKitNetworkRequest* request, WebKitNetworkResponse* response) -{ - - - if (!done && gTestRunner->willSendRequestReturnsNull()) { - // As requested by the TestRunner, don't perform the request. - webkit_network_request_set_uri(request, "about:blank"); - return; - } - - if (!done && gTestRunner->dumpResourceLoadCallbacks()) - printf("%s - willSendRequest %s redirectResponse %s\n", - convertNetworkRequestToURLPath(request).data(), - descriptionSuitableForTestResult(request).data(), - descriptionSuitableForTestResult(response).data()); - - SoupMessage* soupMessage = webkit_network_request_get_message(request); - SoupURI* uri = soup_uri_new(webkit_network_request_get_uri(request)); - - if (SOUP_URI_IS_VALID(uri)) { - GUniquePtr<char> uriString(soup_uri_to_string(uri, FALSE)); - - if (SOUP_URI_VALID_FOR_HTTP(uri) && g_strcmp0(uri->host, "127.0.0.1") - && g_strcmp0(uri->host, "255.255.255.255") - && g_ascii_strncasecmp(uri->host, "localhost", 9)) { - printf("Blocked access to external URL %s\n", uriString.get()); - // Cancel load of blocked resource to avoid potential - // network-related timeouts in tests. - webkit_network_request_set_uri(request, "about:blank"); - soup_uri_free(uri); - return; - } - - const string& destination = gTestRunner->redirectionDestinationForURL(uriString.get()); - if (!destination.empty()) - webkit_network_request_set_uri(request, destination.c_str()); - } - - if (uri) - soup_uri_free(uri); - - if (soupMessage) { - const set<string>& clearHeaders = gTestRunner->willSendRequestClearHeaders(); - for (set<string>::const_iterator header = clearHeaders.begin(); header != clearHeaders.end(); ++header) - soup_message_headers_remove(soupMessage->request_headers, header->c_str()); - } -} - - -static void didReceiveResponse(WebKitWebView* webView, WebKitWebFrame*, WebKitWebResource* webResource, WebKitNetworkResponse* response) -{ - if (!done && gTestRunner->dumpResourceLoadCallbacks()) { - CString responseDescription(descriptionSuitableForTestResult(response)); - CString path(convertWebResourceToURLPath(webResource)); - printf("%s - didReceiveResponse %s\n", path.data(), responseDescription.data()); - } - - // TODO: add "has MIME type" whenever dumpResourceResponseMIMETypes() is supported. - // See https://bugs.webkit.org/show_bug.cgi?id=58222. -} - -static void didFinishLoading(WebKitWebView* webView, WebKitWebFrame* webFrame, WebKitWebResource* webResource) -{ - if (!done && gTestRunner->dumpResourceLoadCallbacks()) - printf("%s - didFinishLoading\n", convertWebResourceToURLPath(webResource).data()); -} - -static void didFailLoadingWithError(WebKitWebView* webView, WebKitWebFrame* webFrame, WebKitWebResource* webResource, GError* webError) -{ - if (!done && gTestRunner->dumpResourceLoadCallbacks()) { - CString webErrorString(descriptionSuitableForTestResult(webError, webResource)); - printf("%s - didFailLoadingWithError: %s\n", convertWebResourceToURLPath(webResource).data(), - webErrorString.data()); - } -} - -static void didRunInsecureContent(WebKitWebFrame*, WebKitSecurityOrigin*, const char* url) -{ - if (!done && gTestRunner->dumpFrameLoadCallbacks()) - printf("didRunInsecureContent\n"); -} - -static gboolean webViewRunFileChooser(WebKitWebView*, WebKitFileChooserRequest*) -{ - // We return TRUE to not propagate the event further so the - // default file chooser dialog is not shown. - return TRUE; -} - -static void frameLoadEventCallback(WebKitWebFrame* frame, DumpRenderTreeSupportGtk::FrameLoadEvent event, const char* url) -{ - if (done || !gTestRunner->dumpFrameLoadCallbacks()) - return; - - GUniquePtr<char> frameName(getFrameNameSuitableForTestResult(webkit_web_frame_get_web_view(frame), frame)); - switch (event) { - case DumpRenderTreeSupportGtk::WillPerformClientRedirectToURL: - ASSERT(url); - printf("%s - willPerformClientRedirectToURL: %s \n", frameName.get(), url); - break; - case DumpRenderTreeSupportGtk::DidCancelClientRedirect: - printf("%s - didCancelClientRedirectForFrame\n", frameName.get()); - break; - case DumpRenderTreeSupportGtk::DidReceiveServerRedirectForProvisionalLoad: - printf("%s - didReceiveServerRedirectForProvisionalLoadForFrame\n", frameName.get()); - break; - case DumpRenderTreeSupportGtk::DidDisplayInsecureContent: - printf ("didDisplayInsecureContent\n"); - break; - case DumpRenderTreeSupportGtk::DidDetectXSS: - printf ("didDetectXSS\n"); - break; - default: - ASSERT_NOT_REACHED(); - } -} - -static bool authenticationCallback(CString& username, CString& password, WebKitWebResource* webResource) -{ - CString description(convertWebResourceToURLPath(webResource)); - - if (!gTestRunner->handlesAuthenticationChallenges()) { - printf("%s - didReceiveAuthenticationChallenge - Simulating cancelled authentication sheet\n", description.data()); - return false; - } - - username = gTestRunner->authenticationUsername().c_str(); - password = gTestRunner->authenticationPassword().c_str(); - printf("%s - didReceiveAuthenticationChallenge - Responding with %s:%s\n", description.data(), username.data(), password.data()); - return true; -} - -static WebKitWebView* createWebView() -{ - // It is important to declare DRT is running early so when creating - // web view mock clients are used instead of proper ones. - DumpRenderTreeSupportGtk::setDumpRenderTreeModeEnabled(true); - - DumpRenderTreeSupportGtk::setFrameLoadEventCallback(frameLoadEventCallback); - DumpRenderTreeSupportGtk::setAuthenticationCallback(authenticationCallback); - - WebKitWebView* view = WEBKIT_WEB_VIEW(self_scrolling_webkit_web_view_new()); - - g_object_connect(G_OBJECT(view), - "signal::load-started", webViewLoadStarted, 0, - "signal::load-finished", webViewLoadFinished, 0, - "signal::load-error", webViewLoadError, 0, - "signal::window-object-cleared", webViewWindowObjectCleared, 0, - "signal::console-message", webViewConsoleMessage, 0, - "signal::script-alert", webViewScriptAlert, 0, - "signal::script-prompt", webViewScriptPrompt, 0, - "signal::script-confirm", webViewScriptConfirm, 0, - "signal::title-changed", webViewTitleChanged, 0, - "signal::navigation-policy-decision-requested", webViewNavigationPolicyDecisionRequested, 0, - "signal::status-bar-text-changed", webViewStatusBarTextChanged, 0, - "signal::create-web-view", webViewCreate, 0, - "signal::close-web-view", webViewClose, 0, - "signal::database-quota-exceeded", databaseQuotaExceeded, 0, - "signal::document-load-finished", webViewDocumentLoadFinished, 0, - "signal::geolocation-policy-decision-requested", geolocationPolicyDecisionRequested, 0, - "signal::onload-event", webViewOnloadEvent, 0, - "signal::drag-begin", dragBeginCallback, 0, - "signal::drag-end", dragEndCallback, 0, - "signal::drag-failed", dragFailedCallback, 0, - "signal::frame-created", frameCreatedCallback, 0, - "signal::resource-request-starting", willSendRequestCallback, 0, - "signal::resource-response-received", didReceiveResponse, 0, - "signal::resource-load-finished", didFinishLoading, 0, - "signal::resource-load-failed", didFailLoadingWithError, 0, - "signal::run-file-chooser", webViewRunFileChooser, 0, - NULL); - connectEditingCallbacks(view); - - WebKitWebInspector* inspector = webkit_web_view_get_inspector(view); - g_object_connect(G_OBJECT(inspector), - "signal::inspect-web-view", webInspectorInspectWebView, 0, - "signal::show-window", webInspectorShowWindow, 0, - "signal::close-window", webInspectorCloseWindow, 0, - NULL); - - if (webView) { - WebKitWebSettings* settings = webkit_web_view_get_settings(webView); - webkit_web_view_set_settings(view, settings); - } - - // frame-created is not issued for main frame. That's why we must do this here - WebKitWebFrame* frame = webkit_web_view_get_main_frame(view); - g_signal_connect(frame, "notify::load-status", G_CALLBACK(webFrameLoadStatusNotified), NULL); - g_signal_connect(frame, "insecure-content-run", G_CALLBACK(didRunInsecureContent), NULL); - - return view; -} - -static WebKitWebView* webViewCreate(WebKitWebView* view, WebKitWebFrame* frame) -{ - if (!gTestRunner->canOpenWindows()) - return 0; - - // Make sure that waitUntilDone has been called. - ASSERT(gTestRunner->waitToDump()); - - WebKitWebView* newWebView = createWebView(); - g_object_ref_sink(G_OBJECT(newWebView)); - webViewList = g_slist_prepend(webViewList, newWebView); - return newWebView; -} - -static void logHandler(const gchar* domain, GLogLevelFlags level, const gchar* message, gpointer data) -{ - if (level < G_LOG_LEVEL_DEBUG) - fprintf(stderr, "%s\n", message); -} - -int main(int argc, char* argv[]) -{ - gtk_init(&argc, &argv); - - // Some plugins might try to use the GLib logger for printing debug - // messages. This will cause tests to fail because of unexpected output. - // We squelch all debug messages sent to the logger. - g_log_set_default_handler(logHandler, 0); - - initializeGlobalsFromCommandLineOptions(argc, argv); - initializeFonts(); - - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); -#ifdef GTK_API_VERSION_2 - container = gtk_hbox_new(TRUE, 0); -#else - container = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - gtk_box_set_homogeneous(GTK_BOX(container), TRUE); -#endif - gtk_container_add(GTK_CONTAINER(window), container); - gtk_widget_show_all(window); - - webView = createWebView(); - gtk_box_pack_start(GTK_BOX(container), GTK_WIDGET(webView), TRUE, TRUE, 0); - gtk_widget_realize(GTK_WIDGET(webView)); - gtk_widget_show_all(container); - mainFrame = webkit_web_view_get_main_frame(webView); - - setDefaultsToConsistentStateValuesForTesting(); - - gcController = new GCController(); -#if HAVE(ACCESSIBILITY) - axController = new AccessibilityController(); -#endif - - if (useLongRunningServerMode(argc, argv)) { - printSeparators = true; - runTestingServerLoop(); - } else { - printSeparators = (optind < argc-1 || (dumpPixelsForCurrentTest && dumpTree)); - for (int i = optind; i != argc; ++i) - runTest(argv[i]); - } - - delete gcController; - gcController = 0; - -#if HAVE(ACCESSIBILITY) - delete axController; - axController = 0; -#endif - - gtk_widget_destroy(window); - - return 0; -} diff --git a/Tools/DumpRenderTree/gtk/DumpRenderTreeGtk.h b/Tools/DumpRenderTree/gtk/DumpRenderTreeGtk.h deleted file mode 100644 index 4b33458f3..000000000 --- a/Tools/DumpRenderTree/gtk/DumpRenderTreeGtk.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2007 Eric Seidel <eric@webkit.org> - * - * 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. - */ - -#ifndef DumpRenderTreeGtk_h -#define DumpRenderTreeGtk_h - -#include <JavaScriptCore/JSBase.h> -#include <glib.h> -#include <libsoup/soup.h> -#include <webkit/webkitdefines.h> -#include <wtf/text/CString.h> - -extern WebKitWebFrame* mainFrame; -extern WebKitWebFrame* topLoadingFrame; -extern bool waitForPolicy; -extern GSList* webViewList; - -gchar* JSStringCopyUTF8CString(JSStringRef jsString); -CString getTopLevelPath(); - -void setWaitToDumpWatchdog(guint timer); -bool shouldSetWaitToDumpWatchdog(); -CString soupURIToStringPreservingPassword(SoupURI* soupURI); - -#endif // DumpRenderTreeGtk_h diff --git a/Tools/DumpRenderTree/gtk/EditingCallbacks.cpp b/Tools/DumpRenderTree/gtk/EditingCallbacks.cpp deleted file mode 100644 index 3c08f80b3..000000000 --- a/Tools/DumpRenderTree/gtk/EditingCallbacks.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (C) 2010 Igalia S.L. - * - * 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. - */ - -#include "config.h" -#include "EditingCallbacks.h" - -#include "DumpRenderTree.h" -#include "TestRunner.h" -#include <gtk/gtk.h> -#include <webkit/webkit.h> -#include <wtf/gobject/GUniquePtr.h> -#include <wtf/text/CString.h> - -static CString dumpNodePath(WebKitDOMNode* node) -{ - GUniquePtr<gchar> nodeName(webkit_dom_node_get_node_name(node)); - GString* path = g_string_new(nodeName.get()); - - WebKitDOMNode* parent = webkit_dom_node_get_parent_node(node); - while (parent) { - GUniquePtr<gchar> parentName(webkit_dom_node_get_node_name(parent)); - - g_string_append(path, " > "); - g_string_append(path, parentName.get()); - parent = webkit_dom_node_get_parent_node(parent); - } - - GUniquePtr<gchar> pathBuffer(g_string_free(path, FALSE)); - return pathBuffer.get(); -} - -static CString dumpRange(WebKitDOMRange* range) -{ - if (!range) - return "(null)"; - - GUniquePtr<gchar> dump(g_strdup_printf("range from %li of %s to %li of %s", - webkit_dom_range_get_start_offset(range, 0), - dumpNodePath(webkit_dom_range_get_start_container(range, 0)).data(), - webkit_dom_range_get_end_offset(range, 0), - dumpNodePath(webkit_dom_range_get_end_container(range, 0)).data())); - - return dump.get(); -} - -static const char* insertActionString(WebKitInsertAction action) -{ - switch (action) { - case WEBKIT_INSERT_ACTION_TYPED: - return "WebViewInsertActionTyped"; - case WEBKIT_INSERT_ACTION_PASTED: - return "WebViewInsertActionPasted"; - case WEBKIT_INSERT_ACTION_DROPPED: - return "WebViewInsertActionDropped"; - } - ASSERT_NOT_REACHED(); - return "WebViewInsertActionTyped"; -} - -static const char* selectionAffinityString(WebKitSelectionAffinity affinity) -{ - switch (affinity) { - case WEBKIT_SELECTION_AFFINITY_UPSTREAM: - return "NSSelectionAffinityUpstream"; - case WEBKIT_SELECTION_AFFINITY_DOWNSTREAM: - return "NSSelectionAffinityDownstream"; - } - ASSERT_NOT_REACHED(); - return "NSSelectionAffinityUpstream"; -} - -gboolean shouldBeginEditing(WebKitWebView* webView, WebKitDOMRange* range) -{ - if (!done && gTestRunner->dumpEditingCallbacks()) - printf("EDITING DELEGATE: shouldBeginEditingInDOMRange:%s\n", dumpRange(range).data()); - return TRUE; -} - -gboolean shouldEndEditing(WebKitWebView* webView, WebKitDOMRange* range) -{ - if (!done && gTestRunner->dumpEditingCallbacks()) - printf("EDITING DELEGATE: shouldEndEditingInDOMRange:%s\n", dumpRange(range).data()); - return TRUE; -} - -gboolean shouldInsertNode(WebKitWebView* webView, WebKitDOMNode* node, WebKitDOMRange* range, WebKitInsertAction action) -{ - if (!done && gTestRunner->dumpEditingCallbacks()) { - printf("EDITING DELEGATE: shouldInsertNode:%s replacingDOMRange:%s givenAction:%s\n", - dumpNodePath(node).data(), dumpRange(range).data(), insertActionString(action)); - } - return TRUE; -} - -gboolean shouldInsertText(WebKitWebView* webView, const gchar* text, WebKitDOMRange* range, WebKitInsertAction action) -{ - if (!done && gTestRunner->dumpEditingCallbacks()) { - printf("EDITING DELEGATE: shouldInsertText:%s replacingDOMRange:%s givenAction:%s\n", - text, dumpRange(range).data(), insertActionString(action)); - } - return TRUE; -} - -gboolean shouldDeleteRange(WebKitWebView* webView, WebKitDOMRange* range) -{ - if (!done && gTestRunner->dumpEditingCallbacks()) - printf("EDITING DELEGATE: shouldDeleteDOMRange:%s\n", dumpRange(range).data()); - return TRUE; -} - -gboolean shouldShowDeleteInterfaceForElement(WebKitWebView* webView, WebKitDOMHTMLElement* element) -{ - return FALSE; -} - -gboolean shouldChangeSelectedRange(WebKitWebView* webView, WebKitDOMRange* fromRange, WebKitDOMRange* toRange, WebKitSelectionAffinity affinity, gboolean stillSelecting) -{ - if (!done && gTestRunner->dumpEditingCallbacks()) { - printf("EDITING DELEGATE: shouldChangeSelectedDOMRange:%s toDOMRange:%s affinity:%s stillSelecting:%s\n", - dumpRange(fromRange).data(), dumpRange(toRange).data(), selectionAffinityString(affinity), - stillSelecting ? "TRUE" : "FALSE"); - } - return TRUE; -} - -gboolean shouldApplyStyle(WebKitWebView* webView, WebKitDOMCSSStyleDeclaration* style, WebKitDOMRange* range) -{ - if (!done && gTestRunner->dumpEditingCallbacks()) { - GUniquePtr<gchar> styleText(webkit_dom_css_style_declaration_get_css_text(style)); - printf("EDITING DELEGATE: shouldApplyStyle:%s toElementsInDOMRange:%s\n", - styleText.get(), dumpRange(range).data()); - } - return TRUE; -} - -void editingBegan(WebKitWebView*) -{ - if (!done && gTestRunner->dumpEditingCallbacks()) - printf("EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification\n"); -} - -void userChangedContents(WebKitWebView*) -{ - if (!done && gTestRunner->dumpEditingCallbacks()) - printf("EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification\n"); -} - -void editingEnded(WebKitWebView*) -{ - if (!done && gTestRunner->dumpEditingCallbacks()) - printf("EDITING DELEGATE: webViewDidEndEditing:WebViewDidEndEditingNotification\n"); -} - -void selectionChanged(WebKitWebView*) -{ - if (!done && gTestRunner->dumpEditingCallbacks()) - printf("EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification\n"); -} - -void connectEditingCallbacks(WebKitWebView* webView) -{ - g_object_connect(G_OBJECT(webView), - "signal::should-begin-editing", shouldBeginEditing, 0, - "signal::should-end-editing", shouldEndEditing, 0, - "signal::should-insert-node", shouldInsertNode, 0, - "signal::should-insert-text", shouldInsertText, 0, - "signal::should-delete-range", shouldDeleteRange, 0, - "signal::should-show-delete-interface-for-element", shouldShowDeleteInterfaceForElement, 0, - "signal::should-change-selected-range", shouldChangeSelectedRange, 0, - "signal::should-apply-style", shouldApplyStyle, 0, - "signal::editing-began", editingBegan, 0, - "signal::user-changed-contents", userChangedContents, 0, - "signal::editing-ended", editingEnded, 0, - "signal::selection-changed", selectionChanged, 0, - NULL); -} - diff --git a/Tools/DumpRenderTree/gtk/EditingCallbacks.h b/Tools/DumpRenderTree/gtk/EditingCallbacks.h deleted file mode 100644 index 7a9514917..000000000 --- a/Tools/DumpRenderTree/gtk/EditingCallbacks.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2010 Igalia S.L. - * - * 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. - */ - -#ifndef EditingCallbacks_h -#define EditingCallbacks_h - -typedef struct _WebKitWebView WebKitWebView; -void connectEditingCallbacks(WebKitWebView*); - -#endif diff --git a/Tools/DumpRenderTree/gtk/EventSender.cpp b/Tools/DumpRenderTree/gtk/EventSender.cpp deleted file mode 100644 index bd8e4fb8f..000000000 --- a/Tools/DumpRenderTree/gtk/EventSender.cpp +++ /dev/null @@ -1,1004 +0,0 @@ -/* - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2009 Zan Dobersek <zandobersek@gmail.com> - * Copyright (C) 2009 Holger Hans Peter Freyther - * Copyright (C) 2010 Igalia S.L. - * Copyright (C) 2012 ChangSeok Oh <shivamidow@gmail.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. - */ - -#include "config.h" -#include "EventSender.h" - -#include "DumpRenderTree.h" -#include "WebCoreSupport/DumpRenderTreeSupportGtk.h" -#include <GRefPtrGtk.h> -#include <GtkVersioning.h> -#include <JavaScriptCore/JSObjectRef.h> -#include <JavaScriptCore/JSRetainPtr.h> -#include <JavaScriptCore/JSStringRef.h> -#include <cstring> -#include <gdk/gdk.h> -#include <gdk/gdkkeysyms.h> -#include <webkit/webkitwebframe.h> -#include <webkit/webkitwebview.h> -#include <wtf/ASCIICType.h> -#include <wtf/Platform.h> -#include <wtf/gobject/GUniquePtr.h> -#include <wtf/text/CString.h> - -extern "C" { - extern GtkMenu* webkit_web_view_get_context_menu(WebKitWebView*); -} - -static bool dragMode; -static int timeOffset = 0; - -static int lastMousePositionX; -static int lastMousePositionY; -static int lastClickPositionX; -static int lastClickPositionY; -static int lastClickTimeOffset; -static int lastClickButton; -static unsigned buttonCurrentlyDown; -static int clickCount; -GdkDragContext* currentDragSourceContext; - -struct DelayedMessage { - GdkEvent* event; - gulong delay; -}; - -static DelayedMessage msgQueue[1024]; - -static unsigned endOfQueue; -static unsigned startOfQueue; - -static const float zoomMultiplierRatio = 1.2f; - -// WebCore and layout tests assume this value. -static const float pixelsPerScrollTick = 40; - -// 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 void sendOrQueueEvent(GdkEvent*, bool = true); -static void dispatchEvent(GdkEvent* event); -static guint getStateFlags(); - -static JSValueRef getDragModeCallback(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) -{ - return JSValueMakeBoolean(context, dragMode); -} - -static bool setDragModeCallback(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception) -{ - dragMode = JSValueToBoolean(context, value); - return true; -} - -static JSValueRef leapForwardCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - if (argumentCount > 0) { - msgQueue[endOfQueue].delay = JSValueToNumber(context, arguments[0], exception); - timeOffset += msgQueue[endOfQueue].delay; - ASSERT(!exception || !*exception); - } - - return JSValueMakeUndefined(context); -} - -bool prepareMouseButtonEvent(GdkEvent* event, int eventSenderButtonNumber, guint modifiers) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - if (!view) - return false; - - // The logic for mapping EventSender button numbers to GDK button - // numbers originates from the Windows EventSender. - int gdkButtonNumber = 3; - if (eventSenderButtonNumber >= 0 && eventSenderButtonNumber <= 2) - gdkButtonNumber = eventSenderButtonNumber + 1; - - // fast/events/mouse-click-events expects the 4th button - // to be event->button = 1, so send a middle-button event. - else if (eventSenderButtonNumber == 3) - gdkButtonNumber = 2; - - event->button.button = gdkButtonNumber; - event->button.x = lastMousePositionX; - event->button.y = lastMousePositionY; - event->button.window = gtk_widget_get_window(GTK_WIDGET(view)); - g_object_ref(event->button.window); - event->button.device = getDefaultGDKPointerDevice(event->button.window); - event->button.state = modifiers | getStateFlags(); - event->button.time = GDK_CURRENT_TIME; - event->button.axes = 0; - - int xRoot, yRoot; - gdk_window_get_root_coords(gtk_widget_get_window(GTK_WIDGET(view)), lastMousePositionX, lastMousePositionY, &xRoot, &yRoot); - event->button.x_root = xRoot; - event->button.y_root = yRoot; - - return true; -} - -static JSValueRef getMenuItemTitleCallback(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) -{ - GtkWidget* widget = GTK_WIDGET(JSObjectGetPrivate(object)); - CString label; - if (GTK_IS_SEPARATOR_MENU_ITEM(widget)) - label = "<separator>"; - else - label = gtk_menu_item_get_label(GTK_MENU_ITEM(widget)); - - JSRetainPtr<JSStringRef> itemText(Adopt, JSStringCreateWithUTF8CString(label.data())); - return JSValueMakeString(context, itemText.get()); -} - -static bool setMenuItemTitleCallback(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception) -{ - return true; -} - -static JSValueRef menuItemClickCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - GtkMenuItem* item = GTK_MENU_ITEM(JSObjectGetPrivate(thisObject)); - gtk_menu_item_activate(item); - return JSValueMakeUndefined(context); -} - -static JSStaticFunction staticMenuItemFunctions[] = { - { "click", menuItemClickCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { 0, 0, 0 } -}; - -static JSStaticValue staticMenuItemValues[] = { - { "title", getMenuItemTitleCallback, setMenuItemTitleCallback, kJSPropertyAttributeNone }, - { 0, 0, 0, 0 } -}; - -static JSClassRef getMenuItemClass() -{ - static JSClassRef menuItemClass = 0; - - if (!menuItemClass) { - JSClassDefinition classDefinition = { - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - classDefinition.staticFunctions = staticMenuItemFunctions; - classDefinition.staticValues = staticMenuItemValues; - - menuItemClass = JSClassCreate(&classDefinition); - } - - return menuItemClass; -} - - -static JSValueRef contextClickCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - GdkEvent* pressEvent = gdk_event_new(GDK_BUTTON_PRESS); - - if (!prepareMouseButtonEvent(pressEvent, 2, 0)) { - gdk_event_free(pressEvent); - return JSObjectMakeArray(context, 0, 0, 0); - } - - GdkEvent* releaseEvent = gdk_event_copy(pressEvent); - sendOrQueueEvent(pressEvent); - - JSValueRef valueRef = JSObjectMakeArray(context, 0, 0, 0); - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - GtkMenu* gtkMenu = webkit_web_view_get_context_menu(view); - if (gtkMenu) { - GUniquePtr<GList> items(gtk_container_get_children(GTK_CONTAINER(gtkMenu))); - JSValueRef arrayValues[g_list_length(items.get())]; - int index = 0; - for (GList* item = g_list_first(items.get()); item; item = g_list_next(item)) { - arrayValues[index] = JSObjectMake(context, getMenuItemClass(), item->data); - index++; - } - if (index) - valueRef = JSObjectMakeArray(context, index - 1, arrayValues, 0); - } - - releaseEvent->type = GDK_BUTTON_RELEASE; - sendOrQueueEvent(releaseEvent); - return valueRef; -} - -static gboolean sendClick(gpointer) -{ - GdkEvent* pressEvent = gdk_event_new(GDK_BUTTON_PRESS); - - if (!prepareMouseButtonEvent(pressEvent, 1, 0)) { - gdk_event_free(pressEvent); - return FALSE; - } - - GdkEvent* releaseEvent = gdk_event_copy(pressEvent); - dispatchEvent(pressEvent); - releaseEvent->type = GDK_BUTTON_RELEASE; - dispatchEvent(releaseEvent); - - return FALSE; -} - -static JSValueRef scheduleAsynchronousClickCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - g_idle_add_full(G_PRIORITY_DEFAULT, sendClick, 0, 0); - return JSValueMakeUndefined(context); -} - -static void updateClickCount(int button) -{ - if (lastClickPositionX != lastMousePositionX - || lastClickPositionY != lastMousePositionY - || lastClickButton != button - || timeOffset - lastClickTimeOffset >= 1) - clickCount = 1; - else - clickCount++; -} - -static guint gdkModifierFromJSValue(JSContextRef context, const JSValueRef value) -{ - JSStringRef string = JSValueToStringCopy(context, value, 0); - guint gdkModifier = 0; - if (JSStringIsEqualToUTF8CString(string, "ctrlKey") - || JSStringIsEqualToUTF8CString(string, "addSelectionKey")) - gdkModifier = GDK_CONTROL_MASK; - else if (JSStringIsEqualToUTF8CString(string, "shiftKey") - || JSStringIsEqualToUTF8CString(string, "rangeSelectionKey")) - gdkModifier = GDK_SHIFT_MASK; - else if (JSStringIsEqualToUTF8CString(string, "altKey")) - gdkModifier = GDK_MOD1_MASK; - - // Currently the metaKey as defined in WebCore/platform/gtk/PlatformMouseEventGtk.cpp - // is GDK_META_MASK. This code must be kept in sync with that file. - else if (JSStringIsEqualToUTF8CString(string, "metaKey")) - gdkModifier = GDK_META_MASK; - - JSStringRelease(string); - return gdkModifier; -} - -static guint gdkModifersFromJSValue(JSContextRef context, const JSValueRef modifiers) -{ - // The value may either be a string with a single modifier or an array of modifiers. - if (JSValueIsString(context, modifiers)) - return gdkModifierFromJSValue(context, modifiers); - - JSObjectRef modifiersArray = JSValueToObject(context, modifiers, 0); - if (!modifiersArray) - return 0; - - guint gdkModifiers = 0; - JSRetainPtr<JSStringRef> lengthProperty(Adopt, JSStringCreateWithUTF8CString("length")); - int modifiersCount = JSValueToNumber(context, JSObjectGetProperty(context, modifiersArray, lengthProperty.get(), 0), 0); - for (int i = 0; i < modifiersCount; ++i) - gdkModifiers |= gdkModifierFromJSValue(context, JSObjectGetPropertyAtIndex(context, modifiersArray, i, 0)); - return gdkModifiers; -} - -static JSValueRef mouseDownCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - int button = 0; - if (argumentCount == 1) { - button = static_cast<int>(JSValueToNumber(context, arguments[0], exception)); - g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context)); - } - guint modifiers = argumentCount >= 2 ? gdkModifersFromJSValue(context, arguments[1]) : 0; - - GdkEvent* event = gdk_event_new(GDK_BUTTON_PRESS); - if (!prepareMouseButtonEvent(event, button, modifiers)) { - gdk_event_free(event); - return JSValueMakeUndefined(context); - } - - // If the same mouse button is already in the down position don't send another event as it may confuse Xvfb. - if (buttonCurrentlyDown == event->button.button) { - gdk_event_free(event); - return JSValueMakeUndefined(context); - } - - buttonCurrentlyDown = event->button.button; - - // Normally GDK will send both GDK_BUTTON_PRESS and GDK_2BUTTON_PRESS for - // the second button press during double-clicks. WebKit GTK+ selectively - // ignores the first GDK_BUTTON_PRESS of that pair using gdk_event_peek. - // Since our events aren't ever going onto the GDK event queue, WebKit won't - // be able to filter out the first GDK_BUTTON_PRESS, so we just don't send - // it here. Eventually this code should probably figure out a way to get all - // appropriate events onto the event queue and this work-around should be - // removed. - updateClickCount(event->button.button); - if (clickCount == 2) - event->type = GDK_2BUTTON_PRESS; - else if (clickCount == 3) - event->type = GDK_3BUTTON_PRESS; - - sendOrQueueEvent(event); - return JSValueMakeUndefined(context); -} - -static guint getStateFlags() -{ - if (buttonCurrentlyDown == 1) - return GDK_BUTTON1_MASK; - if (buttonCurrentlyDown == 2) - return GDK_BUTTON2_MASK; - if (buttonCurrentlyDown == 3) - return GDK_BUTTON3_MASK; - return 0; -} - -static JSValueRef mouseUpCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - int button = 0; - if (argumentCount == 1) { - button = static_cast<int>(JSValueToNumber(context, arguments[0], exception)); - g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context)); - } - guint modifiers = argumentCount >= 2 ? gdkModifersFromJSValue(context, arguments[1]) : 0; - - GdkEvent* event = gdk_event_new(GDK_BUTTON_RELEASE); - if (!prepareMouseButtonEvent(event, button, modifiers)) { - gdk_event_free(event); - return JSValueMakeUndefined(context); - } - - lastClickPositionX = lastMousePositionX; - lastClickPositionY = lastMousePositionY; - lastClickButton = buttonCurrentlyDown; - lastClickTimeOffset = timeOffset; - buttonCurrentlyDown = 0; - - sendOrQueueEvent(event); - return JSValueMakeUndefined(context); -} - -static JSValueRef mouseMoveToCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - if (!view) - return JSValueMakeUndefined(context); - - if (argumentCount < 2) - return JSValueMakeUndefined(context); - - lastMousePositionX = (int)JSValueToNumber(context, arguments[0], exception); - g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context)); - lastMousePositionY = (int)JSValueToNumber(context, arguments[1], exception); - g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context)); - - GdkEvent* event = gdk_event_new(GDK_MOTION_NOTIFY); - event->motion.x = lastMousePositionX; - event->motion.y = lastMousePositionY; - - event->motion.time = GDK_CURRENT_TIME; - event->motion.window = gtk_widget_get_window(GTK_WIDGET(view)); - g_object_ref(event->motion.window); - event->button.device = getDefaultGDKPointerDevice(event->motion.window); - - guint modifiers = argumentCount >= 3 ? gdkModifersFromJSValue(context, arguments[2]) : 0; - event->motion.state = modifiers | getStateFlags(); - event->motion.axes = 0; - - int xRoot, yRoot; - gdk_window_get_root_coords(gtk_widget_get_window(GTK_WIDGET(view)), lastMousePositionX, lastMousePositionY, &xRoot, &yRoot); - event->motion.x_root = xRoot; - event->motion.y_root = yRoot; - - sendOrQueueEvent(event, false); - return JSValueMakeUndefined(context); -} - -static JSValueRef mouseScrollByCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - if (!view) - return JSValueMakeUndefined(context); - - if (argumentCount < 2) - return JSValueMakeUndefined(context); - - int horizontal = (int)JSValueToNumber(context, arguments[0], exception); - g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context)); - int vertical = (int)JSValueToNumber(context, arguments[1], exception); - g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context)); - - // Copy behaviour of Qt and EFL - just return in case of (0,0) mouse scroll - if (!horizontal && !vertical) - return JSValueMakeUndefined(context); - - GdkEvent* event = gdk_event_new(GDK_SCROLL); - event->scroll.x = lastMousePositionX; - event->scroll.y = lastMousePositionY; - event->scroll.time = GDK_CURRENT_TIME; - event->scroll.window = gtk_widget_get_window(GTK_WIDGET(view)); - g_object_ref(event->scroll.window); - - // GTK+ only supports one tick in each scroll event that is not smooth. For the cases of more than one direction, - // and more than one step in a direction, we can only use smooth events, supported from Gtk 3.3.18. -#if GTK_CHECK_VERSION(3, 3, 18) - if ((horizontal && vertical) || horizontal > 1 || horizontal < -1 || vertical > 1 || vertical < -1) { - event->scroll.direction = GDK_SCROLL_SMOOTH; - event->scroll.delta_x = -horizontal; - event->scroll.delta_y = -vertical; - - sendOrQueueEvent(event); - return JSValueMakeUndefined(context); - } -#else - g_return_val_if_fail((!vertical || !horizontal), JSValueMakeUndefined(context)); -#endif - - if (horizontal < 0) - event->scroll.direction = GDK_SCROLL_RIGHT; - else if (horizontal > 0) - event->scroll.direction = GDK_SCROLL_LEFT; - else if (vertical < 0) - event->scroll.direction = GDK_SCROLL_DOWN; - else if (vertical > 0) - event->scroll.direction = GDK_SCROLL_UP; - else - g_assert_not_reached(); - - sendOrQueueEvent(event); - return JSValueMakeUndefined(context); -} - -static JSValueRef continuousMouseScrollByCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ -#if GTK_CHECK_VERSION(3, 3, 18) - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - if (!view) - return JSValueMakeUndefined(context); - - if (argumentCount < 2) - return JSValueMakeUndefined(context); - - int horizontal = JSValueToNumber(context, arguments[0], exception); - g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context)); - int vertical = JSValueToNumber(context, arguments[1], exception); - g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context)); - - // We do not yet support continuous scrolling by page. - if (argumentCount >= 3 && JSValueToBoolean(context, arguments[2])) - return JSValueMakeUndefined(context); - - GdkEvent* event = gdk_event_new(GDK_SCROLL); - event->scroll.x = lastMousePositionX; - event->scroll.y = lastMousePositionY; - event->scroll.time = GDK_CURRENT_TIME; - event->scroll.window = gtk_widget_get_window(GTK_WIDGET(view)); - g_object_ref(event->scroll.window); - - event->scroll.direction = GDK_SCROLL_SMOOTH; - event->scroll.delta_x = -horizontal / pixelsPerScrollTick; - event->scroll.delta_y = -vertical / pixelsPerScrollTick; - - sendOrQueueEvent(event); -#endif - return JSValueMakeUndefined(context); -} - -static void dragWithFilesDragDataGetCallback(GtkWidget*, GdkDragContext*, GtkSelectionData *data, guint, guint, gpointer userData) -{ - gtk_selection_data_set_uris(data, static_cast<gchar**>(userData)); -} - -static void dragWithFilesDragEndCallback(GtkWidget* widget, GdkDragContext*, gpointer userData) -{ - g_signal_handlers_disconnect_by_func(widget, reinterpret_cast<void*>(dragWithFilesDragEndCallback), userData); - g_signal_handlers_disconnect_by_func(widget, reinterpret_cast<void*>(dragWithFilesDragDataGetCallback), userData); - g_strfreev(static_cast<gchar**>(userData)); -} - -static JSValueRef beginDragWithFilesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - if (argumentCount < 1) - return JSValueMakeUndefined(context); - - JSObjectRef filesArray = JSValueToObject(context, arguments[0], exception); - ASSERT(!exception || !*exception); - - const gchar* mainFrameURI = webkit_web_frame_get_uri(mainFrame); - GRefPtr<GFile> testFile(adoptGRef(g_file_new_for_uri(mainFrameURI))); - GRefPtr<GFile> parentDirectory(g_file_get_parent(testFile.get())); - if (!parentDirectory) - return JSValueMakeUndefined(context); - - // If this is an HTTP test, we still need to pass a local file path - // to WebCore. Even though the file doesn't exist, this should be fine - // for most tests. - GUniquePtr<gchar> scheme(g_file_get_uri_scheme(parentDirectory.get())); - if (g_str_equal(scheme.get(), "http") || g_str_equal(scheme.get(), "https")) { - GUniquePtr<gchar> currentDirectory(g_get_current_dir()); - parentDirectory = adoptGRef(g_file_new_for_path(currentDirectory.get())); - } - - JSStringRef lengthProperty = JSStringCreateWithUTF8CString("length"); - int filesArrayLength = JSValueToNumber(context, JSObjectGetProperty(context, filesArray, lengthProperty, 0), 0); - JSStringRelease(lengthProperty); - - gchar** draggedFilesURIList = g_new0(gchar*, filesArrayLength + 1); - for (int i = 0; i < filesArrayLength; ++i) { - JSStringRef filenameString = JSValueToStringCopy(context, - JSObjectGetPropertyAtIndex(context, filesArray, i, 0), 0); - size_t bufferSize = JSStringGetMaximumUTF8CStringSize(filenameString); - GUniquePtr<gchar> filenameBuffer(static_cast<gchar*>(g_malloc(bufferSize))); - JSStringGetUTF8CString(filenameString, filenameBuffer.get(), bufferSize); - JSStringRelease(filenameString); - - GRefPtr<GFile> dragFile(g_file_get_child(parentDirectory.get(), filenameBuffer.get())); - draggedFilesURIList[i] = g_file_get_uri(dragFile.get()); - } - - GtkWidget* view = GTK_WIDGET(webkit_web_frame_get_web_view(mainFrame)); - g_object_connect(G_OBJECT(view), - "signal::drag-end", dragWithFilesDragEndCallback, draggedFilesURIList, - "signal::drag-data-get", dragWithFilesDragDataGetCallback, draggedFilesURIList, - NULL); - - GdkEvent event; - GdkWindow* viewGDKWindow = gtk_widget_get_window(view); - memset(&event, 0, sizeof(event)); - event.type = GDK_MOTION_NOTIFY; - event.motion.x = lastMousePositionX; - event.motion.y = lastMousePositionY; - event.motion.time = GDK_CURRENT_TIME; - event.motion.window = viewGDKWindow; - event.motion.device = getDefaultGDKPointerDevice(viewGDKWindow); - event.motion.state = GDK_BUTTON1_MASK; - - int xRoot, yRoot; - gdk_window_get_root_coords(viewGDKWindow, lastMousePositionX, lastMousePositionY, &xRoot, &yRoot); - event.motion.x_root = xRoot; - event.motion.y_root = yRoot; - - GtkTargetList* targetList = gtk_target_list_new(0, 0); - gtk_target_list_add_uri_targets(targetList, 0); - gtk_drag_begin(view, targetList, GDK_ACTION_COPY, 1, &event); - gtk_target_list_unref(targetList); - - return JSValueMakeUndefined(context); -} - -static void sendOrQueueEvent(GdkEvent* event, bool shouldReplaySavedEvents) -{ - // Mouse move events are queued if the previous event was queued or if a - // delay was set up by leapForward(). - if ((dragMode && buttonCurrentlyDown) || endOfQueue != startOfQueue || msgQueue[endOfQueue].delay) { - msgQueue[endOfQueue++].event = event; - - if (shouldReplaySavedEvents) - replaySavedEvents(); - - return; - } - - dispatchEvent(event); -} - -static void dispatchEvent(GdkEvent* event) -{ - DumpRenderTreeSupportGtk::layoutFrame(mainFrame); - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - if (!view) { - gdk_event_free(event); - return; - } - - // The widget focus may have been lost in the course of the test, - // so force another explicit focus grab here. - gtk_widget_grab_focus(GTK_WIDGET(view)); - gtk_main_do_event(event); - - if (!currentDragSourceContext) { - gdk_event_free(event); - return; - } - - if (event->type == GDK_MOTION_NOTIFY) { - // WebKit has called gtk_drag_start(), but because the main loop isn't - // running GDK internals don't know that the drag has started yet. Pump - // the main loop a little bit so that GDK is in the correct state. - while (gtk_events_pending()) - gtk_main_iteration(); - - // Simulate a drag motion on the top-level GDK window. - GtkWidget* parentWidget = gtk_widget_get_parent(GTK_WIDGET(view)); - GdkWindow* parentWidgetWindow = gtk_widget_get_window(parentWidget); - gdk_drag_motion(currentDragSourceContext, parentWidgetWindow, GDK_DRAG_PROTO_XDND, - event->motion.x_root, event->motion.y_root, - gdk_drag_context_get_selected_action(currentDragSourceContext), - gdk_drag_context_get_actions(currentDragSourceContext), - GDK_CURRENT_TIME); - - } else if (currentDragSourceContext && event->type == GDK_BUTTON_RELEASE) { - // We've released the mouse button, we should just be able to spin the - // event loop here and have GTK+ send the appropriate notifications for - // the end of the drag. - while (gtk_events_pending()) - gtk_main_iteration(); - } - - gdk_event_free(event); -} - -void replaySavedEvents() -{ - // First send all the events that are ready to be sent - while (startOfQueue < endOfQueue) { - if (msgQueue[startOfQueue].delay) { - g_usleep(msgQueue[startOfQueue].delay * 1000); - msgQueue[startOfQueue].delay = 0; - } - - dispatchEvent(msgQueue[startOfQueue++].event); - } - - startOfQueue = 0; - endOfQueue = 0; -} - -static GdkEvent* createKeyPressEvent(JSContextRef context, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - g_return_val_if_fail(argumentCount >= 1, 0); - guint modifiers = argumentCount >= 2 ? gdkModifersFromJSValue(context, arguments[1]) : 0; - - // 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), 0); - - 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 if (JSStringIsEqualToUTF8CString(character, "insert")) - gdkKeySym = GDK_KP_Insert; - else if (JSStringIsEqualToUTF8CString(character, "delete")) - gdkKeySym = GDK_KP_Delete; - else - // If we get some other key specified with the numpad location, - // crash here, so we add it sooner rather than later. - 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, "insert")) - gdkKeySym = GDK_Insert; - else if (JSStringIsEqualToUTF8CString(character, "delete")) - gdkKeySym = GDK_Delete; - else if (JSStringIsEqualToUTF8CString(character, "printScreen")) - gdkKeySym = GDK_Print; - else if (JSStringIsEqualToUTF8CString(character, "menu")) - gdkKeySym = GDK_Menu; - 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 if (JSStringIsEqualToUTF8CString(character, "leftAlt")) - gdkKeySym = GDK_Alt_L; - else if (JSStringIsEqualToUTF8CString(character, "leftControl")) - gdkKeySym = GDK_Control_L; - else if (JSStringIsEqualToUTF8CString(character, "leftShift")) - gdkKeySym = GDK_Shift_L; - else if (JSStringIsEqualToUTF8CString(character, "rightAlt")) - gdkKeySym = GDK_Alt_R; - else if (JSStringIsEqualToUTF8CString(character, "rightControl")) - gdkKeySym = GDK_Control_R; - else if (JSStringIsEqualToUTF8CString(character, "rightShift")) - gdkKeySym = GDK_Shift_R; - 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') - gdkKeySym = GDK_BackSpace; - else { - gdkKeySym = gdk_unicode_to_keyval(charCode); - if (WTF::isASCIIUpper(charCode)) - modifiers |= GDK_SHIFT_MASK; - } - } - } - JSStringRelease(character); - - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - g_return_val_if_fail(view, 0); - - GdkEvent* pressEvent = gdk_event_new(GDK_KEY_PRESS); - pressEvent->key.keyval = gdkKeySym; - pressEvent->key.state = modifiers; - pressEvent->key.window = gtk_widget_get_window(GTK_WIDGET(view)); - g_object_ref(pressEvent->key.window); -#ifndef GTK_API_VERSION_2 - gdk_event_set_device(pressEvent, getDefaultGDKPointerDevice(pressEvent->key.window)); -#endif - - // When synthesizing an event, an invalid hardware_keycode value - // can cause it to be badly processed by Gtk+. - GUniqueOutPtr<GdkKeymapKey> keys; - gint nKeys; - if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), gdkKeySym, &keys.outPtr(), &nKeys)) - pressEvent->key.hardware_keycode = keys.get()[0].keycode; - - return pressEvent; -} - -static void sendKeyDown(GdkEvent* pressEvent) -{ - g_return_if_fail(pressEvent); - GdkEvent* releaseEvent = gdk_event_copy(pressEvent); - releaseEvent->type = GDK_KEY_RELEASE; - - dispatchEvent(pressEvent); - dispatchEvent(releaseEvent); - - DumpRenderTreeSupportGtk::deliverAllMutationsIfNecessary(); -} - -static JSValueRef keyDownCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - GdkEvent* pressEvent = createKeyPressEvent(context, argumentCount, arguments, exception); - sendKeyDown(pressEvent); - - return JSValueMakeUndefined(context); -} - -static void zoomIn(gboolean fullContentsZoom) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - if (!view) - return; - - webkit_web_view_set_full_content_zoom(view, fullContentsZoom); - gfloat currentZoom = webkit_web_view_get_zoom_level(view); - webkit_web_view_set_zoom_level(view, currentZoom * zoomMultiplierRatio); -} - -static void zoomOut(gboolean fullContentsZoom) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - if (!view) - return; - - webkit_web_view_set_full_content_zoom(view, fullContentsZoom); - gfloat currentZoom = webkit_web_view_get_zoom_level(view); - webkit_web_view_set_zoom_level(view, currentZoom / zoomMultiplierRatio); -} - -static JSValueRef textZoomInCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - zoomIn(FALSE); - return JSValueMakeUndefined(context); -} - -static JSValueRef textZoomOutCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - zoomOut(FALSE); - return JSValueMakeUndefined(context); -} - -static JSValueRef zoomPageInCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - zoomIn(TRUE); - return JSValueMakeUndefined(context); -} - -static JSValueRef zoomPageOutCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - zoomOut(TRUE); - return JSValueMakeUndefined(context); -} - -static JSValueRef scalePageByCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - if (argumentCount < 3) - return JSValueMakeUndefined(context); - - float scaleFactor = JSValueToNumber(context, arguments[0], exception); - float x = JSValueToNumber(context, arguments[1], exception); - float y = JSValueToNumber(context, arguments[2], exception); - - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - if (!view) - return JSValueMakeUndefined(context); - - DumpRenderTreeSupportGtk::scalePageBy(view, scaleFactor, x, y); - - return JSValueMakeUndefined(context); -} - -static gboolean sendAsynchronousKeyDown(gpointer userData) -{ - sendKeyDown(static_cast<GdkEvent*>(userData)); - return FALSE; -} - -static JSValueRef scheduleAsynchronousKeyDownCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - GdkEvent* pressEvent = createKeyPressEvent(context, argumentCount, arguments, exception); - if (pressEvent) - g_idle_add_full(G_PRIORITY_DEFAULT, sendAsynchronousKeyDown, static_cast<gpointer>(pressEvent), 0); - - return JSValueMakeUndefined(context); -} - -static JSValueRef clearTouchPointsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - return JSValueMakeUndefined(context); -} - -static JSStaticFunction staticFunctions[] = { - { "mouseScrollBy", mouseScrollByCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "continuousMouseScrollBy", continuousMouseScrollByCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "contextClick", contextClickCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "mouseDown", mouseDownCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "mouseUp", mouseUpCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "mouseMoveTo", mouseMoveToCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "beginDragWithFiles", beginDragWithFilesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "leapForward", leapForwardCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "keyDown", keyDownCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "textZoomIn", textZoomInCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "textZoomOut", textZoomOutCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "zoomPageIn", zoomPageInCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "zoomPageOut", zoomPageOutCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "scheduleAsynchronousClick", scheduleAsynchronousClickCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "scalePageBy", scalePageByCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "scheduleAsynchronousKeyDown", scheduleAsynchronousKeyDownCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - - { 0, 0, 0 } -}; - -static JSStaticValue staticValues[] = { - { "dragMode", getDragModeCallback, setDragModeCallback, kJSPropertyAttributeNone }, - { 0, 0, 0, 0 } -}; - -static JSClassRef getClass(JSContextRef context) -{ - static JSClassRef eventSenderClass = 0; - - if (!eventSenderClass) { - JSClassDefinition classDefinition = { - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - classDefinition.staticFunctions = staticFunctions; - classDefinition.staticValues = staticValues; - - eventSenderClass = JSClassCreate(&classDefinition); - } - - return eventSenderClass; -} - -JSObjectRef makeEventSender(JSContextRef context, bool isTopFrame) -{ - if (isTopFrame) { - dragMode = true; - - // Fly forward in time one second when the main frame loads. This will - // ensure that when a test begins clicking in the same location as - // a previous test, those clicks won't be interpreted as continuations - // of the previous test's click sequences. - timeOffset += 1000; - - lastMousePositionX = lastMousePositionY = 0; - lastClickPositionX = lastClickPositionY = 0; - lastClickTimeOffset = 0; - lastClickButton = 0; - buttonCurrentlyDown = 0; - clickCount = 0; - - endOfQueue = 0; - startOfQueue = 0; - - currentDragSourceContext = 0; - } - - return JSObjectMake(context, getClass(context), 0); -} - -void dragBeginCallback(GtkWidget*, GdkDragContext* context, gpointer) -{ - currentDragSourceContext = context; -} - -void dragEndCallback(GtkWidget*, GdkDragContext* context, gpointer) -{ - currentDragSourceContext = 0; -} - -gboolean dragFailedCallback(GtkWidget*, GdkDragContext* context, gpointer) -{ - // Return TRUE here to disable the stupid GTK+ drag failed animation, - // which introduces asynchronous behavior into our drags. - return TRUE; -} diff --git a/Tools/DumpRenderTree/gtk/EventSender.h b/Tools/DumpRenderTree/gtk/EventSender.h deleted file mode 100644 index f440f0d3d..000000000 --- a/Tools/DumpRenderTree/gtk/EventSender.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * Copyright (C) 2009 Holger Hans Peter Freyther - * - * 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. - */ - -#ifndef EventSender_h -#define EventSender_h - -typedef const struct OpaqueJSContext* JSContextRef; -typedef struct OpaqueJSValue* JSObjectRef; - -JSObjectRef makeEventSender(JSContextRef context, bool isTopFrame); -void replaySavedEvents(); -void dragBeginCallback(GtkWidget*, GdkDragContext*, gpointer); -void dragEndCallback(GtkWidget*, GdkDragContext*, gpointer); -gboolean dragFailedCallback(GtkWidget*, GdkDragContext*, gpointer); - -#endif diff --git a/Tools/DumpRenderTree/gtk/GCControllerGtk.cpp b/Tools/DumpRenderTree/gtk/GCControllerGtk.cpp deleted file mode 100644 index 4eb5d6ec9..000000000 --- a/Tools/DumpRenderTree/gtk/GCControllerGtk.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2007 Eric Seidel <eric@webkit.org> - * - * 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. - */ - -#include "config.h" -#include "GCController.h" - -#include "WebCoreSupport/DumpRenderTreeSupportGtk.h" - -#include <glib.h> -#include <webkit/webkit.h> - -void GCController::collect() const -{ - DumpRenderTreeSupportGtk::gcCollectJavascriptObjects(); -} - -void GCController::collectOnAlternateThread(bool waitUntilDone) const -{ - DumpRenderTreeSupportGtk::gcCollectJavascriptObjectsOnAlternateThread(waitUntilDone); -} - -size_t GCController::getJSObjectCount() const -{ - return DumpRenderTreeSupportGtk::gcCountJavascriptObjects(); -} diff --git a/Tools/DumpRenderTree/gtk/PixelDumpSupportGtk.cpp b/Tools/DumpRenderTree/gtk/PixelDumpSupportGtk.cpp deleted file mode 100644 index 0a800ec13..000000000 --- a/Tools/DumpRenderTree/gtk/PixelDumpSupportGtk.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2009 Zan Dobersek <zandobersek@gmail.com> - * Copyright (C) 2010 Igalia S.L. - * - * 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. - */ - -#include "config.h" - -#include "DumpRenderTree.h" -#include "GtkVersioning.h" -#include "PixelDumpSupportCairo.h" -#include "WebCoreSupport/DumpRenderTreeSupportGtk.h" -#include <webkit/webkit.h> - -static void paintOverlay(cairo_surface_t* surface) -{ - cairo_t* context = cairo_create(surface); - - // Paint a transparent black overlay from which the repainted rectangles are then cleared. - // The alpha component of the overlay should have a value of 0.66, as on other ports. - cairo_set_source_rgba(context, 0.0, 0.0, 0.0, 0.66); - cairo_rectangle(context, 0, 0, cairo_image_surface_get_width(surface), cairo_image_surface_get_height(surface)); - cairo_fill(context); - - GSList* trackedRectsList = DumpRenderTreeSupportGtk::trackedRepaintRects(mainFrame); - for (GSList* listElement = trackedRectsList; listElement; listElement = g_slist_next(listElement)) { - GdkRectangle* rect = static_cast<GdkRectangle*>(listElement->data); - - cairo_set_operator(context, CAIRO_OPERATOR_CLEAR); - cairo_rectangle(context, rect->x, rect->y, rect->width, rect->height); - cairo_fill(context); - } - - g_slist_free_full(trackedRectsList, g_free); - cairo_destroy(context); -} - -static void fillRepaintOverlayIntoContext(cairo_t* context, gint width, gint height) -{ - cairo_surface_t* overlaySurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); - paintOverlay(overlaySurface); - - cairo_set_source_surface(context, overlaySurface, 0, 0); - cairo_rectangle(context, 0, 0, width, height); - cairo_fill(context); - - cairo_surface_destroy(overlaySurface); -} - -PassRefPtr<BitmapContext> createBitmapContextFromWebView(bool, bool, bool, bool drawSelectionRect) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - GtkWidget* viewContainer = gtk_widget_get_parent(GTK_WIDGET(view)); - gint width, height; -#ifdef GTK_API_VERSION_2 - GdkPixmap* pixmap = gtk_widget_get_snapshot(viewContainer, 0); - gdk_pixmap_get_size(pixmap, &width, &height); -#else - width = gtk_widget_get_allocated_width(viewContainer); - height = gtk_widget_get_allocated_height(viewContainer); -#endif - - while (gtk_events_pending()) - gtk_main_iteration(); - - cairo_surface_t* imageSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); - cairo_t* context = cairo_create(imageSurface); - -#ifdef GTK_API_VERSION_2 - gdk_cairo_set_source_pixmap(context, pixmap, 0, 0); - cairo_paint(context); - g_object_unref(pixmap); -#else - gtk_widget_draw(viewContainer, context); -#endif - - if (DumpRenderTreeSupportGtk::isTrackingRepaints(mainFrame)) - fillRepaintOverlayIntoContext(context, width, height); - - if (drawSelectionRect) { - cairo_rectangle_int_t rectangle; - DumpRenderTreeSupportGtk::rectangleForSelection(mainFrame, &rectangle); - - cairo_set_line_width(context, 1.0); - cairo_rectangle(context, rectangle.x, rectangle.y, rectangle.width, rectangle.height); - cairo_set_source_rgba(context, 1.0, 0.0, 0.0, 1.0); - cairo_stroke(context); - } - - cairo_surface_destroy(imageSurface); - return BitmapContext::createByAdoptingBitmapAndContext(0, context); -} diff --git a/Tools/DumpRenderTree/gtk/SelfScrollingWebKitWebView.cpp b/Tools/DumpRenderTree/gtk/SelfScrollingWebKitWebView.cpp deleted file mode 100644 index d77cfd5f1..000000000 --- a/Tools/DumpRenderTree/gtk/SelfScrollingWebKitWebView.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2011 Igalia S.L. - * - * 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. - */ - -#include "config.h" -#include "SelfScrollingWebKitWebView.h" - -#include <webkit/webkit.h> - -G_BEGIN_DECLS - -#ifdef GTK_API_VERSION_2 -static void sizeRequestMethod(GtkWidget*, GtkRequisition*); -#else -static void getPreferredSizeMethod(GtkWidget*, gint* minimum, gint* natural); -#endif - -G_DEFINE_TYPE(SelfScrollingWebKitWebView, self_scrolling_webkit_web_view, WEBKIT_TYPE_WEB_VIEW) - -static void self_scrolling_webkit_web_view_class_init(SelfScrollingWebKitWebViewClass* klass) -{ - GtkWidgetClass* widgetClass = GTK_WIDGET_CLASS(klass); -#ifdef GTK_API_VERSION_2 - widgetClass->size_request = sizeRequestMethod; -#else - widgetClass->get_preferred_width = getPreferredSizeMethod; - widgetClass->get_preferred_height = getPreferredSizeMethod; -#endif -} - -static void self_scrolling_webkit_web_view_init(SelfScrollingWebKitWebView* webView) -{ -} - -GtkWidget* self_scrolling_webkit_web_view_new() -{ - return GTK_WIDGET(g_object_new(self_scrolling_webkit_web_view_get_type(), "self-scrolling", TRUE, NULL)); -} - -#ifdef GTK_API_VERSION_2 -static void sizeRequestMethod(GtkWidget*, GtkRequisition* requisition) -{ - requisition->width = 1; - requisition->height = 1; -} -#else -static void getPreferredSizeMethod(GtkWidget*, gint* minimum, gint* natural) -{ - *minimum = 1; - *natural = 1; -} -#endif - -G_END_DECLS diff --git a/Tools/DumpRenderTree/gtk/SelfScrollingWebKitWebView.h b/Tools/DumpRenderTree/gtk/SelfScrollingWebKitWebView.h deleted file mode 100644 index 648d38c97..000000000 --- a/Tools/DumpRenderTree/gtk/SelfScrollingWebKitWebView.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2011 Igalia S.L. - * - * 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. - */ - -#ifndef SelfScrollingWebKitWebView_h -#define SelfScrollingWebKitWebView_h - -#include <webkit/webkit.h> - -G_BEGIN_DECLS - -typedef struct _SelfScrollingWebKitWebView SelfScrollingWebKitWebView; -typedef struct _SelfScrollingWebKitWebViewClass SelfScrollingWebKitWebViewClass; - -struct _SelfScrollingWebKitWebView { - WebKitWebView web_view; -}; - -struct _SelfScrollingWebKitWebViewClass { - WebKitWebViewClass parent_class; -}; - -GtkWidget* self_scrolling_webkit_web_view_new(); - -G_END_DECLS - -#endif // SelfScrollingWebKitWebView_h diff --git a/Tools/DumpRenderTree/gtk/TestRunnerGtk.cpp b/Tools/DumpRenderTree/gtk/TestRunnerGtk.cpp deleted file mode 100644 index c0b2deca2..000000000 --- a/Tools/DumpRenderTree/gtk/TestRunnerGtk.cpp +++ /dev/null @@ -1,914 +0,0 @@ -/* - * Copyright (C) 2007, 2012 Apple Inc. All rights reserved. - * Copyright (C) 2007 Eric Seidel <eric@webkit.org> - * Copyright (C) 2008 Nuanti Ltd. - * Copyright (C) 2009 Jan Michael Alonzo <jmalonzo@gmail.com> - * Copyright (C) 2009,2011 Collabora Ltd. - * Copyright (C) 2010 Joone Hur <joone@kldp.org> - * - * 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. - */ - -#include "config.h" -#include "TestRunner.h" - -#include "DumpRenderTree.h" -#include "WebCoreSupport/DumpRenderTreeSupportGtk.h" -#include "WorkQueue.h" -#include "WorkQueueItem.h" -#include <JavaScriptCore/JSRetainPtr.h> -#include <JavaScriptCore/JSStringRef.h> -#include <cstring> -#include <iostream> -#include <sstream> -#include <stdio.h> -#include <glib.h> -#include <libsoup/soup.h> -#include <webkit/webkit.h> -#include <wtf/gobject/GUniquePtr.h> -#include <wtf/text/WTFString.h> - -extern "C" { -void webkit_web_inspector_execute_script(WebKitWebInspector* inspector, long callId, const gchar* script); -} - -TestRunner::~TestRunner() -{ - // FIXME: implement -} - -void TestRunner::addDisallowedURL(JSStringRef url) -{ - // FIXME: implement -} - -void TestRunner::clearBackForwardList() -{ - WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame); - WebKitWebBackForwardList* list = webkit_web_view_get_back_forward_list(webView); - WebKitWebHistoryItem* item = webkit_web_back_forward_list_get_current_item(list); - g_object_ref(item); - - // We clear the history by setting the back/forward list's capacity to 0 - // then restoring it back and adding back the current item. - gint limit = webkit_web_back_forward_list_get_limit(list); - webkit_web_back_forward_list_set_limit(list, 0); - webkit_web_back_forward_list_set_limit(list, limit); - webkit_web_back_forward_list_add_item(list, item); - webkit_web_back_forward_list_go_to_item(list, item); - g_object_unref(item); -} - -JSStringRef TestRunner::copyDecodedHostName(JSStringRef name) -{ - // FIXME: implement - return 0; -} - -JSStringRef TestRunner::copyEncodedHostName(JSStringRef name) -{ - // FIXME: implement - return 0; -} - -void TestRunner::dispatchPendingLoadRequests() -{ - // FIXME: Implement for testing fix for 6727495 -} - -void TestRunner::display() -{ - displayWebView(); -} - -void TestRunner::keepWebHistory() -{ - // FIXME: implement -} - -size_t TestRunner::webHistoryItemCount() -{ - WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame); - WebKitWebBackForwardList* list = webkit_web_view_get_back_forward_list(webView); - - if (!list) - return -1; - - // We do not add the current page to the total count as it's not - // considered in DRT tests - return webkit_web_back_forward_list_get_back_length(list) + - webkit_web_back_forward_list_get_forward_length(list); -} - -void TestRunner::notifyDone() -{ - if (m_waitToDump && !topLoadingFrame && !WorkQueue::shared()->count()) - dump(); - m_waitToDump = false; - waitForPolicy = false; -} - -JSStringRef TestRunner::pathToLocalResource(JSContextRef context, JSStringRef url) -{ - GUniquePtr<char> urlCString(JSStringCopyUTF8CString(url)); - if (!g_str_has_prefix(urlCString.get(), "file:///tmp/LayoutTests/")) - return JSStringRetain(url); - - const char* layoutTestsSuffix = urlCString.get() + strlen("file:///tmp/"); - GUniquePtr<char> testPath(g_build_filename(getTopLevelPath().data(), layoutTestsSuffix, nullptr)); - GUniquePtr<char> testURI(g_filename_to_uri(testPath.get(), 0, 0)); - return JSStringCreateWithUTF8CString(testURI.get()); -} - -void TestRunner::queueLoad(JSStringRef url, JSStringRef target) -{ - GUniquePtr<gchar> relativeURL(JSStringCopyUTF8CString(url)); - SoupURI* baseURI = soup_uri_new(webkit_web_frame_get_uri(mainFrame)); - SoupURI* absoluteURI = soup_uri_new_with_base(baseURI, relativeURL.get()); - soup_uri_free(baseURI); - - if (!absoluteURI) { - WorkQueue::shared()->queue(new LoadItem(url, target)); - return; - } - - CString absoluteURIString = soupURIToStringPreservingPassword(absoluteURI); - JSRetainPtr<JSStringRef> absoluteURL(Adopt, JSStringCreateWithUTF8CString(absoluteURIString.data())); - WorkQueue::shared()->queue(new LoadItem(absoluteURL.get(), target)); - soup_uri_free(absoluteURI); -} - -void TestRunner::setAcceptsEditing(bool acceptsEditing) -{ - WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame); - webkit_web_view_set_editable(webView, acceptsEditing); -} - -void TestRunner::setAlwaysAcceptCookies(bool alwaysAcceptCookies) -{ - SoupSession* session = webkit_get_default_session(); - SoupCookieJar* jar = reinterpret_cast<SoupCookieJar*>(soup_session_get_feature(session, SOUP_TYPE_COOKIE_JAR)); - - /* If the jar was not created - we create it on demand, i.e, just - in case we have HTTP requests - then we must create it here in - order to set the proper accept policy */ - if (!jar) { - jar = soup_cookie_jar_new(); - soup_session_add_feature(session, SOUP_SESSION_FEATURE(jar)); - g_object_unref(jar); - } - - SoupCookieJarAcceptPolicy policy; - - if (alwaysAcceptCookies) - policy = SOUP_COOKIE_JAR_ACCEPT_ALWAYS; - else - policy = SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY; - - g_object_set(G_OBJECT(jar), SOUP_COOKIE_JAR_ACCEPT_POLICY, policy, NULL); -} - -void TestRunner::setCustomPolicyDelegate(bool setDelegate, bool permissive) -{ - // FIXME: implement -} - -void TestRunner::waitForPolicyDelegate() -{ - waitForPolicy = true; - setWaitToDump(true); -} - -void TestRunner::setScrollbarPolicy(JSStringRef orientation, JSStringRef policy) -{ - // FIXME: implement -} - -void TestRunner::addOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef protocol, JSStringRef host, bool includeSubdomains) -{ - gchar* sourceOriginGChar = JSStringCopyUTF8CString(sourceOrigin); - gchar* protocolGChar = JSStringCopyUTF8CString(protocol); - gchar* hostGChar = JSStringCopyUTF8CString(host); - DumpRenderTreeSupportGtk::whiteListAccessFromOrigin(sourceOriginGChar, protocolGChar, hostGChar, includeSubdomains); - g_free(sourceOriginGChar); - g_free(protocolGChar); - g_free(hostGChar); -} - -void TestRunner::removeOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef protocol, JSStringRef host, bool includeSubdomains) -{ - GUniquePtr<gchar> sourceOriginGChar(JSStringCopyUTF8CString(sourceOrigin)); - GUniquePtr<gchar> protocolGChar(JSStringCopyUTF8CString(protocol)); - GUniquePtr<gchar> hostGChar(JSStringCopyUTF8CString(host)); - DumpRenderTreeSupportGtk::removeWhiteListAccessFromOrigin(sourceOriginGChar.get(), protocolGChar.get(), hostGChar.get(), includeSubdomains); -} - -void TestRunner::setMainFrameIsFirstResponder(bool flag) -{ - // FIXME: implement -} - -void TestRunner::setTabKeyCyclesThroughElements(bool cycles) -{ - WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame); - WebKitWebSettings* settings = webkit_web_view_get_settings(webView); - g_object_set(G_OBJECT(settings), "tab-key-cycles-through-elements", cycles, NULL); -} - -void TestRunner::setUseDashboardCompatibilityMode(bool flag) -{ - // FIXME: implement -} - -static gchar* userStyleSheet = NULL; -static gboolean userStyleSheetEnabled = TRUE; - -void TestRunner::setUserStyleSheetEnabled(bool flag) -{ - userStyleSheetEnabled = flag; - - WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame); - WebKitWebSettings* settings = webkit_web_view_get_settings(webView); - if (flag && userStyleSheet) - g_object_set(G_OBJECT(settings), "user-stylesheet-uri", userStyleSheet, NULL); - else - g_object_set(G_OBJECT(settings), "user-stylesheet-uri", "", NULL); -} - -void TestRunner::setUserStyleSheetLocation(JSStringRef path) -{ - g_free(userStyleSheet); - userStyleSheet = JSStringCopyUTF8CString(path); - if (userStyleSheetEnabled) - setUserStyleSheetEnabled(true); -} - -void TestRunner::setValueForUser(JSContextRef context, JSValueRef nodeObject, JSStringRef value) -{ - DumpRenderTreeSupportGtk::setValueForUser(context, nodeObject, value); -} - -void TestRunner::setViewModeMediaFeature(JSStringRef mode) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - ASSERT(view); - - char* viewMode = JSStringCopyUTF8CString(mode); - - if (!g_strcmp0(viewMode, "windowed")) - webkit_web_view_set_view_mode(view, WEBKIT_WEB_VIEW_VIEW_MODE_WINDOWED); - else if (!g_strcmp0(viewMode, "floating")) - webkit_web_view_set_view_mode(view, WEBKIT_WEB_VIEW_VIEW_MODE_FLOATING); - else if (!g_strcmp0(viewMode, "fullscreen")) - webkit_web_view_set_view_mode(view, WEBKIT_WEB_VIEW_VIEW_MODE_FULLSCREEN); - else if (!g_strcmp0(viewMode, "maximized")) - webkit_web_view_set_view_mode(view, WEBKIT_WEB_VIEW_VIEW_MODE_MAXIMIZED); - else if (!g_strcmp0(viewMode, "minimized")) - webkit_web_view_set_view_mode(view, WEBKIT_WEB_VIEW_VIEW_MODE_MINIMIZED); - - g_free(viewMode); -} - -void TestRunner::setWindowIsKey(bool windowIsKey) -{ - // FIXME: implement -} - -static gboolean waitToDumpWatchdogFired(void*) -{ - setWaitToDumpWatchdog(0); - gTestRunner->waitToDumpWatchdogTimerFired(); - return FALSE; -} - -void TestRunner::setWaitToDump(bool waitUntilDone) -{ - static const int timeoutSeconds = 30; - - m_waitToDump = waitUntilDone; - if (m_waitToDump && shouldSetWaitToDumpWatchdog()) { - guint id = g_timeout_add_seconds(timeoutSeconds, waitToDumpWatchdogFired, 0); - g_source_set_name_by_id(id, "[WebKit] waitToDumpWatchdogFired"); - setWaitToDumpWatchdog(id); - } -} - -int TestRunner::windowCount() -{ - // +1 -> including the main view - return g_slist_length(webViewList) + 1; -} - -void TestRunner::setPrivateBrowsingEnabled(bool flag) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - ASSERT(view); - - WebKitWebSettings* settings = webkit_web_view_get_settings(view); - g_object_set(G_OBJECT(settings), "enable-private-browsing", flag, NULL); -} - -void TestRunner::setJavaScriptCanAccessClipboard(bool flag) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - ASSERT(view); - - WebKitWebSettings* settings = webkit_web_view_get_settings(view); - g_object_set(G_OBJECT(settings), "javascript-can-access-clipboard", flag, NULL); -} - -void TestRunner::setXSSAuditorEnabled(bool flag) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - ASSERT(view); - - WebKitWebSettings* settings = webkit_web_view_get_settings(view); - g_object_set(G_OBJECT(settings), "enable-xss-auditor", flag, NULL); -} - -void TestRunner::setSpatialNavigationEnabled(bool flag) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - ASSERT(view); - - WebKitWebSettings* settings = webkit_web_view_get_settings(view); - g_object_set(G_OBJECT(settings), "enable-spatial-navigation", flag, NULL); -} - -void TestRunner::setAllowUniversalAccessFromFileURLs(bool flag) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - ASSERT(view); - - WebKitWebSettings* settings = webkit_web_view_get_settings(view); - g_object_set(G_OBJECT(settings), "enable-universal-access-from-file-uris", flag, NULL); -} - -void TestRunner::setAllowFileAccessFromFileURLs(bool flag) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - ASSERT(view); - - WebKitWebSettings* settings = webkit_web_view_get_settings(view); - g_object_set(G_OBJECT(settings), "enable-file-access-from-file-uris", flag, NULL); -} - -void TestRunner::setAuthorAndUserStylesEnabled(bool flag) -{ - // FIXME: implement -} - -void TestRunner::setMockDeviceOrientation(bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma) -{ - // FIXME: Implement for DeviceOrientation layout tests. - // See https://bugs.webkit.org/show_bug.cgi?id=30335. -} - -void TestRunner::setMockGeolocationPosition(double latitude, double longitude, double accuracy, bool, double, bool, double, bool, double, bool, double) -{ - WebKitWebView* view = WEBKIT_WEB_VIEW(g_slist_nth_data(webViewList, 0)); - if (!view) - view = webkit_web_frame_get_web_view(mainFrame); - ASSERT(view); - - DumpRenderTreeSupportGtk::setMockGeolocationPosition(view, latitude, longitude, accuracy); -} - -void TestRunner::setMockGeolocationPositionUnavailableError(JSStringRef message) -{ - WebKitWebView* view = WEBKIT_WEB_VIEW(g_slist_nth_data(webViewList, 0)); - if (!view) - view = webkit_web_frame_get_web_view(mainFrame); - ASSERT(view); - - GUniquePtr<gchar> cMessage(JSStringCopyUTF8CString(message)); - DumpRenderTreeSupportGtk::setMockGeolocationPositionUnavailableError(view, cMessage.get()); -} - -void TestRunner::setGeolocationPermission(bool allow) -{ - setGeolocationPermissionCommon(allow); - WebKitWebView* view = WEBKIT_WEB_VIEW(g_slist_nth_data(webViewList, 0)); - if (!view) - view = webkit_web_frame_get_web_view(mainFrame); - ASSERT(view); - - DumpRenderTreeSupportGtk::setMockGeolocationPermission(view, allow); -} - -int TestRunner::numberOfPendingGeolocationPermissionRequests() -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - if (!view) - view = webkit_web_frame_get_web_view(mainFrame); - ASSERT(view); - - return DumpRenderTreeSupportGtk::numberOfPendingGeolocationPermissionRequests(view); -} - -void TestRunner::addMockSpeechInputResult(JSStringRef result, double confidence, JSStringRef language) -{ - // FIXME: Implement for speech input layout tests. - // See https://bugs.webkit.org/show_bug.cgi?id=39485. -} - -void TestRunner::setMockSpeechInputDumpRect(bool flag) -{ - // FIXME: Implement for speech input layout tests. - // See https://bugs.webkit.org/show_bug.cgi?id=39485. -} - -void TestRunner::startSpeechInput(JSContextRef inputElement) -{ - // FIXME: Implement for speech input layout tests. - // See https://bugs.webkit.org/show_bug.cgi?id=39485. -} - -void TestRunner::setIconDatabaseEnabled(bool enabled) -{ - WebKitIconDatabase* database = webkit_get_icon_database(); - if (enabled) { - GUniquePtr<gchar> iconDatabasePath(g_build_filename(g_get_tmp_dir(), "DumpRenderTree", "icondatabase", nullptr)); - webkit_icon_database_set_path(database, iconDatabasePath.get()); - } else - webkit_icon_database_set_path(database, 0); -} - -void TestRunner::setPopupBlockingEnabled(bool flag) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - ASSERT(view); - - WebKitWebSettings* settings = webkit_web_view_get_settings(view); - g_object_set(G_OBJECT(settings), "javascript-can-open-windows-automatically", !flag, NULL); - -} - -void TestRunner::setPluginsEnabled(bool flag) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - ASSERT(view); - - WebKitWebSettings* settings = webkit_web_view_get_settings(view); - g_object_set(G_OBJECT(settings), "enable-plugins", flag, NULL); -} - -void TestRunner::execCommand(JSStringRef name, JSStringRef value) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - ASSERT(view); - - gchar* cName = JSStringCopyUTF8CString(name); - gchar* cValue = JSStringCopyUTF8CString(value); - DumpRenderTreeSupportGtk::executeCoreCommandByName(view, cName, cValue); - g_free(cName); - g_free(cValue); -} - -bool TestRunner::findString(JSContextRef context, JSStringRef target, JSObjectRef optionsArray) -{ - WebKitFindOptions findOptions = 0; - WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame); - ASSERT(webView); - - JSRetainPtr<JSStringRef> lengthPropertyName(Adopt, JSStringCreateWithUTF8CString("length")); - JSValueRef lengthValue = JSObjectGetProperty(context, optionsArray, lengthPropertyName.get(), 0); - if (!JSValueIsNumber(context, lengthValue)) - return false; - - GUniquePtr<gchar> targetString(JSStringCopyUTF8CString(target)); - - size_t length = static_cast<size_t>(JSValueToNumber(context, lengthValue, 0)); - for (size_t i = 0; i < length; ++i) { - JSValueRef value = JSObjectGetPropertyAtIndex(context, optionsArray, i, 0); - if (!JSValueIsString(context, value)) - continue; - - JSRetainPtr<JSStringRef> optionName(Adopt, JSValueToStringCopy(context, value, 0)); - - if (JSStringIsEqualToUTF8CString(optionName.get(), "CaseInsensitive")) - findOptions |= WebKit::WebFindOptionsCaseInsensitive; - else if (JSStringIsEqualToUTF8CString(optionName.get(), "AtWordStarts")) - findOptions |= WebKit::WebFindOptionsAtWordStarts; - else if (JSStringIsEqualToUTF8CString(optionName.get(), "TreatMedialCapitalAsWordStart")) - findOptions |= WebKit::WebFindOptionsTreatMedialCapitalAsWordStart; - else if (JSStringIsEqualToUTF8CString(optionName.get(), "Backwards")) - findOptions |= WebKit::WebFindOptionsBackwards; - else if (JSStringIsEqualToUTF8CString(optionName.get(), "WrapAround")) - findOptions |= WebKit::WebFindOptionsWrapAround; - else if (JSStringIsEqualToUTF8CString(optionName.get(), "StartInSelection")) - findOptions |= WebKit::WebFindOptionsStartInSelection; - } - - return DumpRenderTreeSupportGtk::findString(webView, targetString.get(), findOptions); -} - -bool TestRunner::isCommandEnabled(JSStringRef name) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - ASSERT(view); - - gchar* cName = JSStringCopyUTF8CString(name); - bool result = DumpRenderTreeSupportGtk::isCommandEnabled(view, cName); - g_free(cName); - return result; -} - -void TestRunner::setCacheModel(int cacheModel) -{ - // These constants are derived from the Mac cache model enum in Source/WebKit/mac/WebView/WebPreferences.h. - switch (cacheModel) { - case 0: - webkit_set_cache_model(WEBKIT_CACHE_MODEL_DOCUMENT_VIEWER); - break; - case 1: - webkit_set_cache_model(WEBKIT_CACHE_MODEL_DOCUMENT_BROWSER); - break; - case 2: - webkit_set_cache_model(WEBKIT_CACHE_MODEL_WEB_BROWSER); - break; - default: - ASSERT_NOT_REACHED(); - } -} - -void TestRunner::setPersistentUserStyleSheetLocation(JSStringRef jsURL) -{ - // FIXME: implement -} - -void TestRunner::clearPersistentUserStyleSheet() -{ - // FIXME: implement -} - -void TestRunner::clearAllApplicationCaches() -{ - // FIXME: Implement to support application cache quotas. -} - -void TestRunner::clearApplicationCacheForOrigin(OpaqueJSString*) -{ - // FIXME: Implement to support deleting all application caches for an origin. -} - -long long TestRunner::localStorageDiskUsageForOrigin(JSStringRef originIdentifier) -{ - // FIXME: Implement to support getting disk usage in bytes for an origin. - return 0; -} - -JSValueRef TestRunner::originsWithApplicationCache(JSContextRef context) -{ - // FIXME: Implement to get origins that contain application caches. - return JSValueMakeUndefined(context); -} - -long long TestRunner::applicationCacheDiskUsageForOrigin(JSStringRef name) -{ - // FIXME: implement - return 0; -} - -void TestRunner::clearAllDatabases() -{ - webkit_remove_all_web_databases(); -} - -void TestRunner::setDatabaseQuota(unsigned long long quota) -{ - WebKitSecurityOrigin* origin = webkit_web_frame_get_security_origin(mainFrame); - webkit_security_origin_set_web_database_quota(origin, quota); -} - -JSValueRef TestRunner::originsWithLocalStorage(JSContextRef context) -{ - // FIXME: implement - return JSValueMakeUndefined(context); -} - -void TestRunner::deleteAllLocalStorage() -{ - // FIXME: implement -} - -void TestRunner::deleteLocalStorageForOrigin(JSStringRef originIdentifier) -{ - // FIXME: implement -} - -void TestRunner::observeStorageTrackerNotifications(unsigned number) -{ - // FIXME: implement -} - -void TestRunner::syncLocalStorage() -{ - // FIXME: implement -} - -void TestRunner::setDomainRelaxationForbiddenForURLScheme(bool forbidden, JSStringRef scheme) -{ - GUniquePtr<gchar> urlScheme(JSStringCopyUTF8CString(scheme)); - DumpRenderTreeSupportGtk::setDomainRelaxationForbiddenForURLScheme(forbidden, urlScheme.get()); -} - -void TestRunner::goBack() -{ - WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame); - webkit_web_view_go_back(webView); -} - -void TestRunner::setDefersLoading(bool defers) -{ - WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame); - DumpRenderTreeSupportGtk::setDefersLoading(webView, defers); -} - -void TestRunner::setAppCacheMaximumSize(unsigned long long size) -{ - webkit_application_cache_set_maximum_size(size); -} - -static gboolean booleanFromValue(gchar* value) -{ - return !g_ascii_strcasecmp(value, "true") || !g_ascii_strcasecmp(value, "1"); -} - -void TestRunner::overridePreference(JSStringRef key, JSStringRef value) -{ - GUniquePtr<gchar> originalName(JSStringCopyUTF8CString(key)); - GUniquePtr<gchar> valueAsString(JSStringCopyUTF8CString(value)); - - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - ASSERT(view); - - // This transformation could be handled by a hash table (and it once was), but - // having it prominent, makes it easier for people from other ports to keep the - // list up to date. - const gchar* propertyName = 0; - if (g_str_equal(originalName.get(), "WebKitJavaScriptEnabled")) - propertyName = "enable-scripts"; - else if (g_str_equal(originalName.get(), "WebKitDefaultFontSize")) - propertyName = "default-font-size"; - else if (g_str_equal(originalName.get(), "WebKitEnableCaretBrowsing")) - propertyName = "enable-caret-browsing"; - else if (g_str_equal(originalName.get(), "WebKitUsesPageCachePreferenceKey")) - propertyName = "enable-page-cache"; - else if (g_str_equal(originalName.get(), "WebKitPluginsEnabled")) - propertyName = "enable-plugins"; - else if (g_str_equal(originalName.get(), "WebKitHyperlinkAuditingEnabled")) - propertyName = "enable-hyperlink-auditing"; - else if (g_str_equal(originalName.get(), "WebKitWebGLEnabled")) - propertyName = "enable-webgl"; - else if (g_str_equal(originalName.get(), "WebKitWebAudioEnabled")) - propertyName = "enable-webaudio"; - else if (g_str_equal(originalName.get(), "WebKitDisplayImagesKey")) - propertyName = "auto-load-images"; - else if (g_str_equal(originalName.get(), "WebKitShouldRespectImageOrientation")) - propertyName = "respect-image-orientation"; - else if (g_str_equal(originalName.get(), "WebKitMediaSourceEnabled")) - propertyName = "enable-mediasource"; - else if (g_str_equal(originalName.get(), "WebKitTabToLinksPreferenceKey")) { - DumpRenderTreeSupportGtk::setLinksIncludedInFocusChain(booleanFromValue(valueAsString.get())); - return; - } else if (g_str_equal(originalName.get(), "WebKitPageCacheSupportsPluginsPreferenceKey")) { - DumpRenderTreeSupportGtk::setPageCacheSupportsPlugins(webkit_web_frame_get_web_view(mainFrame), booleanFromValue(valueAsString.get())); - return; - } else if (g_str_equal(originalName.get(), "WebKitCSSGridLayoutEnabled")) { - DumpRenderTreeSupportGtk::setCSSGridLayoutEnabled(webkit_web_frame_get_web_view(mainFrame), booleanFromValue(valueAsString.get())); - return; - } else if (g_str_equal(originalName.get(), "WebKitCSSRegionsEnabled")) { - DumpRenderTreeSupportGtk::setCSSRegionsEnabled(webkit_web_frame_get_web_view(mainFrame), booleanFromValue(valueAsString.get())); - return; - } else { - fprintf(stderr, "TestRunner::overridePreference tried to override " - "unknown preference '%s'.\n", originalName.get()); - return; - } - - WebKitWebSettings* settings = webkit_web_view_get_settings(view); - GParamSpec* pspec = g_object_class_find_property(G_OBJECT_CLASS( - WEBKIT_WEB_SETTINGS_GET_CLASS(settings)), propertyName); - GValue currentPropertyValue = { 0, { { 0 } } }; - g_value_init(¤tPropertyValue, pspec->value_type); - - if (G_VALUE_HOLDS_STRING(¤tPropertyValue)) - g_object_set(settings, propertyName, valueAsString.get(), NULL); - else if (G_VALUE_HOLDS_BOOLEAN(¤tPropertyValue)) - g_object_set(G_OBJECT(settings), propertyName, booleanFromValue(valueAsString.get()), NULL); - else if (G_VALUE_HOLDS_INT(¤tPropertyValue)) - g_object_set(G_OBJECT(settings), propertyName, atoi(valueAsString.get()), NULL); - else if (G_VALUE_HOLDS_FLOAT(¤tPropertyValue)) { - gfloat newValue = g_ascii_strtod(valueAsString.get(), 0); - g_object_set(G_OBJECT(settings), propertyName, newValue, NULL); - } else - fprintf(stderr, "TestRunner::overridePreference failed to override " - "preference '%s'.\n", originalName.get()); -} - -void TestRunner::addUserScript(JSStringRef source, bool runAtStart, bool allFrames) -{ - GUniquePtr<gchar> sourceCode(JSStringCopyUTF8CString(source)); - DumpRenderTreeSupportGtk::addUserScript(mainFrame, sourceCode.get(), runAtStart, allFrames); -} - -void TestRunner::addUserStyleSheet(JSStringRef source, bool allFrames) -{ - GUniquePtr<gchar> sourceCode(JSStringCopyUTF8CString(source)); - DumpRenderTreeSupportGtk::addUserStyleSheet(mainFrame, sourceCode.get(), allFrames); - // FIXME: needs more investigation why userscripts/user-style-top-frame-only.html fails when allFrames is false. - -} - -void TestRunner::setDeveloperExtrasEnabled(bool enabled) -{ - WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame); - WebKitWebSettings* webSettings = webkit_web_view_get_settings(webView); - - g_object_set(webSettings, "enable-developer-extras", enabled, NULL); -} - -void TestRunner::showWebInspector() -{ - WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame); - WebKitWebInspector* inspector = webkit_web_view_get_inspector(webView); - - webkit_web_inspector_show(inspector); -} - -void TestRunner::closeWebInspector() -{ - WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame); - WebKitWebInspector* inspector = webkit_web_view_get_inspector(webView); - - webkit_web_inspector_close(inspector); -} - -void TestRunner::evaluateInWebInspector(long callId, JSStringRef script) -{ - WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame); - WebKitWebInspector* inspector = webkit_web_view_get_inspector(webView); - char* scriptString = JSStringCopyUTF8CString(script); - - webkit_web_inspector_execute_script(inspector, callId, scriptString); - g_free(scriptString); -} - -void TestRunner::evaluateScriptInIsolatedWorldAndReturnValue(unsigned worldID, JSObjectRef globalObject, JSStringRef script) -{ - // FIXME: Implement this. -} - -void TestRunner::evaluateScriptInIsolatedWorld(unsigned worldID, JSObjectRef globalObject, JSStringRef script) -{ - // FIXME: Implement this. -} - -void TestRunner::removeAllVisitedLinks() -{ - // FIXME: Implement this. -} - -bool TestRunner::callShouldCloseOnWebView() -{ - return DumpRenderTreeSupportGtk::shouldClose(mainFrame); -} - -void TestRunner::apiTestNewWindowDataLoadBaseURL(JSStringRef utf8Data, JSStringRef baseURL) -{ - -} - -void TestRunner::apiTestGoToCurrentBackForwardItem() -{ - -} - -void TestRunner::setWebViewEditable(bool) -{ -} - -void TestRunner::authenticateSession(JSStringRef, JSStringRef, JSStringRef) -{ -} - -void TestRunner::abortModal() -{ -} - -void TestRunner::setSerializeHTTPLoads(bool serialize) -{ - DumpRenderTreeSupportGtk::setSerializeHTTPLoads(serialize); -} - -void TestRunner::setTextDirection(JSStringRef direction) -{ - GUniquePtr<gchar> writingDirection(JSStringCopyUTF8CString(direction)); - - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - ASSERT(view); - - if (g_str_equal(writingDirection.get(), "auto")) - gtk_widget_set_direction(GTK_WIDGET(view), GTK_TEXT_DIR_NONE); - else if (g_str_equal(writingDirection.get(), "ltr")) - gtk_widget_set_direction(GTK_WIDGET(view), GTK_TEXT_DIR_LTR); - else if (g_str_equal(writingDirection.get(), "rtl")) - gtk_widget_set_direction(GTK_WIDGET(view), GTK_TEXT_DIR_RTL); - else - fprintf(stderr, "TestRunner::setTextDirection called with unknown direction: '%s'.\n", writingDirection.get()); -} - -void TestRunner::addChromeInputField() -{ -} - -void TestRunner::removeChromeInputField() -{ -} - -void TestRunner::focusWebView() -{ -} - -void TestRunner::setBackingScaleFactor(double) -{ -} - -void TestRunner::grantWebNotificationPermission(JSStringRef origin) -{ -} - -void TestRunner::denyWebNotificationPermission(JSStringRef jsOrigin) -{ -} - -void TestRunner::removeAllWebNotificationPermissions() -{ -} - -void TestRunner::simulateWebNotificationClick(JSValueRef jsNotification) -{ -} - -void TestRunner::simulateLegacyWebNotificationClick(JSStringRef title) -{ -} - -void TestRunner::resetPageVisibility() -{ - WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame); - DumpRenderTreeSupportGtk::setPageVisibility(webView, WebCore::PageVisibilityStateVisible, true); -} - -void TestRunner::setPageVisibility(const char* visibility) -{ - WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame); - String visibilityString(visibility); - WebCore::PageVisibilityState visibilityState = WebCore::PageVisibilityStateVisible; - - if (visibilityString == "visible") - visibilityState = WebCore::PageVisibilityStateVisible; - else if (visibilityString == "hidden") - visibilityState = WebCore::PageVisibilityStateHidden; - else - return; - - DumpRenderTreeSupportGtk::setPageVisibility(webView, visibilityState, false); -} - -void TestRunner::setAutomaticLinkDetectionEnabled(bool) -{ - // FIXME: Implement this. -} - -void TestRunner::setStorageDatabaseIdleInterval(double) -{ - // FIXME: Implement this. -} - -void TestRunner::closeIdleLocalStorageDatabases() -{ -} diff --git a/Tools/DumpRenderTree/gtk/TextInputController.cpp b/Tools/DumpRenderTree/gtk/TextInputController.cpp deleted file mode 100644 index aee5597ed..000000000 --- a/Tools/DumpRenderTree/gtk/TextInputController.cpp +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (C) 2011 Igalia S.L. - * - * 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. - */ - -#include "config.h" -#include "TextInputController.h" - -#include "DumpRenderTree.h" -#include "WebCoreSupport/DumpRenderTreeSupportGtk.h" -#include <GUniquePtrGtk.h> -#include <JavaScriptCore/JSObjectRef.h> -#include <JavaScriptCore/JSRetainPtr.h> -#include <JavaScriptCore/JSStringRef.h> -#include <cstring> -#include <webkit/webkit.h> - -static JSValueRef setMarkedTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - ASSERT(view); - if (argumentCount < 3) - return JSValueMakeUndefined(context); - - JSStringRef string = JSValueToStringCopy(context, arguments[0], exception); - ASSERT(!exception || !*exception); - - size_t bufferSize = JSStringGetMaximumUTF8CStringSize(string); - GUniquePtr<gchar> stringBuffer(static_cast<gchar*>(g_malloc(bufferSize))); - JSStringGetUTF8CString(string, stringBuffer.get(), bufferSize); - JSStringRelease(string); - - int start = static_cast<int>(JSValueToNumber(context, arguments[1], exception)); - ASSERT(!exception || !*exception); - - int length = static_cast<int>(JSValueToNumber(context, arguments[2], exception)); - ASSERT(!exception || !*exception); - - DumpRenderTreeSupportGtk::setComposition(view, stringBuffer.get(), start, length); - return JSValueMakeUndefined(context); -} - -static JSValueRef hasMarkedTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - ASSERT(view); - return JSValueMakeBoolean(context, DumpRenderTreeSupportGtk::hasComposition(view)); -} - -static JSValueRef markedRangeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - ASSERT(view); - - int start, length; - if (!DumpRenderTreeSupportGtk::compositionRange(view, &start, &length)) - return JSValueMakeUndefined(context); - - JSValueRef arrayValues[2]; - arrayValues[0] = JSValueMakeNumber(context, start); - arrayValues[1] = JSValueMakeNumber(context, length); - JSObjectRef arrayObject = JSObjectMakeArray(context, 2, arrayValues, exception); - ASSERT(!exception || !*exception); - return arrayObject; -} - -static JSValueRef insertTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - ASSERT(view); - - if (argumentCount < 1) - return JSValueMakeUndefined(context); - - JSStringRef string = JSValueToStringCopy(context, arguments[0], exception); - ASSERT(!exception || !*exception); - - size_t bufferSize = JSStringGetMaximumUTF8CStringSize(string); - GUniquePtr<gchar> stringBuffer(static_cast<gchar*>(g_malloc(bufferSize))); - JSStringGetUTF8CString(string, stringBuffer.get(), bufferSize); - JSStringRelease(string); - - DumpRenderTreeSupportGtk::confirmComposition(view, stringBuffer.get()); - return JSValueMakeUndefined(context); -} - -static JSValueRef unmarkTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - ASSERT(view); - - DumpRenderTreeSupportGtk::confirmComposition(view, 0); - return JSValueMakeUndefined(context); -} - -static JSValueRef firstRectForCharacterRangeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - ASSERT(view); - if (argumentCount < 2) - return JSValueMakeUndefined(context); - - int location = static_cast<int>(JSValueToNumber(context, arguments[0], exception)); - ASSERT(!exception || !*exception); - - int length = static_cast<int>(JSValueToNumber(context, arguments[1], exception)); - ASSERT(!exception || !*exception); - - cairo_rectangle_int_t rect; - if (!DumpRenderTreeSupportGtk::firstRectForCharacterRange(view, location, length, &rect)) - return JSValueMakeUndefined(context); - - JSValueRef arrayValues[4]; - arrayValues[0] = JSValueMakeNumber(context, rect.x); - arrayValues[1] = JSValueMakeNumber(context, rect.y); - arrayValues[2] = JSValueMakeNumber(context, rect.width); - arrayValues[3] = JSValueMakeNumber(context, rect.height); - JSObjectRef arrayObject = JSObjectMakeArray(context, 4, arrayValues, exception); - ASSERT(!exception || !*exception); - - return arrayObject; -} - -static JSValueRef selectedRangeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - ASSERT(view); - - int start, length; - if (!DumpRenderTreeSupportGtk::selectedRange(view, &start, &length)) - return JSValueMakeUndefined(context); - - JSValueRef arrayValues[2]; - arrayValues[0] = JSValueMakeNumber(context, start); - arrayValues[1] = JSValueMakeNumber(context, length); - JSObjectRef arrayObject = JSObjectMakeArray(context, 2, arrayValues, exception); - ASSERT(!exception || !*exception); - - return arrayObject; -} - -static JSValueRef doCommandCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - ASSERT(view); - if (argumentCount < 1) - return JSValueMakeUndefined(context); - - JSStringRef string = JSValueToStringCopy(context, arguments[0], exception); - ASSERT(!exception || !*exception); - - size_t bufferSize = JSStringGetMaximumUTF8CStringSize(string); - GUniquePtr<gchar> stringBuffer(static_cast<gchar*>(g_malloc(bufferSize))); - JSStringGetUTF8CString(string, stringBuffer.get(), bufferSize); - JSStringRelease(string); - - DumpRenderTreeSupportGtk::doCommand(view, stringBuffer.get()); - return JSValueMakeUndefined(context); -} - -static JSStaticFunction staticFunctions[] = { - { "setMarkedText", setMarkedTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "hasMarkedText", hasMarkedTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "markedRange", markedRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "insertText", insertTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "unmarkText", unmarkTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "firstRectForCharacterRange", firstRectForCharacterRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "selectedRange", selectedRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "doCommand", doCommandCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { 0, 0, 0 } -}; - -static JSClassRef getClass(JSContextRef context) -{ - static JSClassRef textInputControllerClass = 0; - - if (!textInputControllerClass) { - JSClassDefinition classDefinition = { - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - classDefinition.staticFunctions = staticFunctions; - - textInputControllerClass = JSClassCreate(&classDefinition); - } - - return textInputControllerClass; -} - -JSObjectRef makeTextInputController(JSContextRef context) -{ - return JSObjectMake(context, getClass(context), 0); -} diff --git a/Tools/DumpRenderTree/gtk/WorkQueueItemGtk.cpp b/Tools/DumpRenderTree/gtk/WorkQueueItemGtk.cpp deleted file mode 100644 index 95461276e..000000000 --- a/Tools/DumpRenderTree/gtk/WorkQueueItemGtk.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2007 Alp Toker <alp@atoker.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" -#include "WorkQueueItem.h" - -#include "DumpRenderTree.h" - -#include <JavaScriptCore/JSStringRef.h> -#include <string.h> -#include <webkit/webkit.h> -#include <wtf/gobject/GUniquePtr.h> - -// Returns a newly allocated UTF-8 character buffer which must be freed with g_free() -gchar* JSStringCopyUTF8CString(JSStringRef jsString) -{ - size_t dataSize = JSStringGetMaximumUTF8CStringSize(jsString); - gchar* utf8 = (gchar*)g_malloc(dataSize); - JSStringGetUTF8CString(jsString, utf8, dataSize); - - return utf8; -} - -bool LoadItem::invoke() const -{ - gchar* targetString = JSStringCopyUTF8CString(m_target.get()); - - WebKitWebFrame* targetFrame; - if (!strlen(targetString)) - targetFrame = mainFrame; - else - targetFrame = webkit_web_frame_find_frame(mainFrame, targetString); - g_free(targetString); - - gchar* urlString = JSStringCopyUTF8CString(m_url.get()); - WebKitNetworkRequest* request = webkit_network_request_new(urlString); - g_free(urlString); - webkit_web_frame_load_request(targetFrame, request); - g_object_unref(request); - - return true; -} - -bool LoadHTMLStringItem::invoke() const -{ - GUniquePtr<gchar> content(JSStringCopyUTF8CString(m_content.get())); - GUniquePtr<gchar> baseURL(JSStringCopyUTF8CString(m_baseURL.get())); - - if (m_unreachableURL) { - GUniquePtr<gchar> unreachableURL(JSStringCopyUTF8CString(m_unreachableURL.get())); - webkit_web_frame_load_alternate_string(mainFrame, content.get(), baseURL.get(), unreachableURL.get()); - return true; - } - webkit_web_frame_load_string(mainFrame, content.get(), 0, 0, baseURL.get()); - return true; -} - -bool ReloadItem::invoke() const -{ - webkit_web_frame_reload(mainFrame); - return true; -} - -bool ScriptItem::invoke() const -{ - WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame); - gchar* scriptString = JSStringCopyUTF8CString(m_script.get()); - webkit_web_view_execute_script(webView, scriptString); - g_free(scriptString); - return true; -} - -bool BackForwardItem::invoke() const -{ - WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame); - if (m_howFar == 1) - webkit_web_view_go_forward(webView); - else if (m_howFar == -1) - webkit_web_view_go_back(webView); - else { - WebKitWebBackForwardList* webBackForwardList = webkit_web_view_get_back_forward_list(webView); - WebKitWebHistoryItem* item = webkit_web_back_forward_list_get_nth_item(webBackForwardList, m_howFar); - webkit_web_view_go_to_back_forward_item(webView, item); - } - return true; -} |