diff options
Diffstat (limited to 'Tools/WebKitTestRunner/InjectedBundle')
39 files changed, 3883 insertions, 1170 deletions
diff --git a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.cpp b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.cpp index f5d1bd58b..0a130d4e8 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.cpp +++ b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.cpp @@ -32,15 +32,15 @@ #include "JSAccessibilityController.h" #include <JavaScriptCore/JSRetainPtr.h> -#include <WebKit2/WKBundle.h> -#include <WebKit2/WKBundlePage.h> -#include <WebKit2/WKBundlePagePrivate.h> +#include <WebKit/WKBundle.h> +#include <WebKit/WKBundlePage.h> +#include <WebKit/WKBundlePagePrivate.h> namespace WTR { -PassRefPtr<AccessibilityController> AccessibilityController::create() +Ref<AccessibilityController> AccessibilityController::create() { - return adoptRef(new AccessibilityController); + return adoptRef(*new AccessibilityController); } AccessibilityController::AccessibilityController() @@ -61,44 +61,43 @@ JSClassRef AccessibilityController::wrapperClass() return JSAccessibilityController::accessibilityControllerClass(); } +void AccessibilityController::enableEnhancedAccessibility(bool enable) +{ + WKAccessibilityEnableEnhancedAccessibility(enable); +} + +bool AccessibilityController::enhancedAccessibilityEnabled() +{ + return WKAccessibilityEnhancedAccessibilityEnabled(); +} + #if !PLATFORM(GTK) && !PLATFORM(EFL) -PassRefPtr<AccessibilityUIElement> AccessibilityController::rootElement() +Ref<AccessibilityUIElement> AccessibilityController::rootElement() { - WKBundlePageRef page = InjectedBundle::shared().page()->page(); + WKBundlePageRef page = InjectedBundle::singleton().page()->page(); void* root = WKAccessibilityRootObject(page); return AccessibilityUIElement::create(static_cast<PlatformUIElement>(root)); } -PassRefPtr<AccessibilityUIElement> AccessibilityController::focusedElement() +Ref<AccessibilityUIElement> AccessibilityController::focusedElement() { - WKBundlePageRef page = InjectedBundle::shared().page()->page(); + WKBundlePageRef page = InjectedBundle::singleton().page()->page(); void* root = WKAccessibilityFocusedObject(page); return AccessibilityUIElement::create(static_cast<PlatformUIElement>(root)); } #endif -PassRefPtr<AccessibilityUIElement> AccessibilityController::elementAtPoint(int x, int y) +RefPtr<AccessibilityUIElement> AccessibilityController::elementAtPoint(int x, int y) { - RefPtr<AccessibilityUIElement> uiElement = rootElement(); + Ref<AccessibilityUIElement> uiElement = rootElement(); return uiElement->elementAtPoint(x, y); } -// Unsupported methods on various platforms. -// As they're implemented on other platforms this list should be modified. -#if (!PLATFORM(GTK) && !PLATFORM(MAC) && !PLATFORM(EFL)) || !HAVE(ACCESSIBILITY) -bool AccessibilityController::addNotificationListener(JSValueRef) { return false; } -bool AccessibilityController::removeNotificationListener() { return false; } -PassRefPtr<AccessibilityUIElement> AccessibilityController::accessibleElementById(JSStringRef attribute) { return nullptr; } -void AccessibilityController::logAccessibilityEvents() { } -void AccessibilityController::resetToConsistentState() { } -JSRetainPtr<JSStringRef> AccessibilityController::platformName() { return JSRetainPtr<JSStringRef>(Adopt, JSStringCreateWithUTF8CString("")); } -#endif - #if !HAVE(ACCESSIBILITY) && (PLATFORM(GTK) || PLATFORM(EFL)) -PassRefPtr<AccessibilityUIElement> AccessibilityController::rootElement() { return nullptr; } -PassRefPtr<AccessibilityUIElement> AccessibilityController::focusedElement() { return nullptr; } +RefPtr<AccessibilityUIElement> AccessibilityController::rootElement() { return nullptr; } +RefPtr<AccessibilityUIElement> AccessibilityController::focusedElement() { return nullptr; } #endif } // namespace WTR diff --git a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.h b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.h index 7ce1a45c3..5cf0d739c 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.h +++ b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.h @@ -23,14 +23,15 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef AccessibilityController_h -#define AccessibilityController_h +#pragma once + +#if HAVE(ACCESSIBILITY) #include "AccessibilityUIElement.h" #include "JSWrappable.h" #include <JavaScriptCore/JSObjectRef.h> #include <wtf/Platform.h> -#if HAVE(ACCESSIBILITY) && (PLATFORM(GTK) || PLATFORM(EFL)) +#if PLATFORM(GTK) || PLATFORM(EFL) #include "AccessibilityNotificationHandlerAtk.h" #endif @@ -38,19 +39,23 @@ namespace WTR { class AccessibilityController : public JSWrappable { public: - static PassRefPtr<AccessibilityController> create(); + static Ref<AccessibilityController> create(); ~AccessibilityController(); void makeWindowObject(JSContextRef, JSObjectRef windowObject, JSValueRef* exception); virtual JSClassRef wrapperClass(); + // Enhanced accessibility. + void enableEnhancedAccessibility(bool); + bool enhancedAccessibilityEnabled(); + JSRetainPtr<JSStringRef> platformName(); // Controller Methods - platform-independent implementations. - PassRefPtr<AccessibilityUIElement> rootElement(); - PassRefPtr<AccessibilityUIElement> focusedElement(); - PassRefPtr<AccessibilityUIElement> elementAtPoint(int x, int y); - PassRefPtr<AccessibilityUIElement> accessibleElementById(JSStringRef idAttribute); + Ref<AccessibilityUIElement> rootElement(); + Ref<AccessibilityUIElement> focusedElement(); + RefPtr<AccessibilityUIElement> elementAtPoint(int x, int y); + RefPtr<AccessibilityUIElement> accessibleElementById(JSStringRef idAttribute); bool addNotificationListener(JSValueRef functionCallback); bool removeNotificationListener(); @@ -59,22 +64,20 @@ public: void logFocusEvents() { } void logValueChangeEvents() { } void logScrollingStartEvents() { } - void logAccessibilityEvents(); + void logAccessibilityEvents() { }; void resetToConsistentState(); private: AccessibilityController(); -#if PLATFORM(MAC) +#if PLATFORM(COCOA) RetainPtr<NotificationHandler> m_globalNotificationHandler; -#endif - -#if HAVE(ACCESSIBILITY) && (PLATFORM(GTK) || PLATFORM(EFL)) +#else RefPtr<AccessibilityNotificationHandler> m_globalNotificationHandler; #endif }; } // namespace WTR -#endif // AccessibilityController_h +#endif // HAVE(ACCESSIBILITY) diff --git a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarker.cpp b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarker.cpp index a7a4b7def..7e99fbb12 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarker.cpp +++ b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarker.cpp @@ -33,14 +33,14 @@ namespace WTR { -PassRefPtr<AccessibilityTextMarker> AccessibilityTextMarker::create(PlatformTextMarker marker) +Ref<AccessibilityTextMarker> AccessibilityTextMarker::create(PlatformTextMarker marker) { - return adoptRef(new AccessibilityTextMarker(marker)); + return adoptRef(*new AccessibilityTextMarker(marker)); } -PassRefPtr<AccessibilityTextMarker> AccessibilityTextMarker::create(const AccessibilityTextMarker& marker) +Ref<AccessibilityTextMarker> AccessibilityTextMarker::create(const AccessibilityTextMarker& marker) { - return adoptRef(new AccessibilityTextMarker(marker)); + return adoptRef(*new AccessibilityTextMarker(marker)); } AccessibilityTextMarker::AccessibilityTextMarker(PlatformTextMarker marker) @@ -60,7 +60,7 @@ AccessibilityTextMarker::~AccessibilityTextMarker() PlatformTextMarker AccessibilityTextMarker::platformTextMarker() const { -#if PLATFORM(MAC) +#if PLATFORM(COCOA) return m_textMarker.get(); #else return m_textMarker; diff --git a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarker.h b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarker.h index c4d4d0481..041f81bc7 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarker.h +++ b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarker.h @@ -23,15 +23,14 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef AccessibilityTextMarker_h -#define AccessibilityTextMarker_h +#pragma once #include "JSWrappable.h" #include <JavaScriptCore/JSObjectRef.h> -#include <wtf/PassRefPtr.h> #include <wtf/Platform.h> +#include <wtf/Ref.h> -#if PLATFORM(MAC) +#if PLATFORM(COCOA) #include <wtf/RetainPtr.h> typedef CFTypeRef PlatformTextMarker; #else @@ -44,8 +43,8 @@ class AccessibilityUIElement; class AccessibilityTextMarker : public JSWrappable { public: - static PassRefPtr<AccessibilityTextMarker> create(PlatformTextMarker); - static PassRefPtr<AccessibilityTextMarker> create(const AccessibilityTextMarker&); + static Ref<AccessibilityTextMarker> create(PlatformTextMarker); + static Ref<AccessibilityTextMarker> create(const AccessibilityTextMarker&); ~AccessibilityTextMarker(); @@ -59,17 +58,15 @@ private: AccessibilityTextMarker(PlatformTextMarker); AccessibilityTextMarker(const AccessibilityTextMarker&); -#if PLATFORM(MAC) +#if PLATFORM(COCOA) RetainPtr<PlatformTextMarker> m_textMarker; #else PlatformTextMarker m_textMarker; #endif }; -#if !PLATFORM(MAC) +#if !PLATFORM(COCOA) inline bool AccessibilityTextMarker::isEqual(AccessibilityTextMarker*) { return false; } #endif } // namespace WTR - -#endif // AccessibilityTextMarker_h diff --git a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarkerRange.cpp b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarkerRange.cpp index 3613f3728..7444f3522 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarkerRange.cpp +++ b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarkerRange.cpp @@ -33,14 +33,14 @@ namespace WTR { -PassRefPtr<AccessibilityTextMarkerRange> AccessibilityTextMarkerRange::create(PlatformTextMarkerRange markerRange) +Ref<AccessibilityTextMarkerRange> AccessibilityTextMarkerRange::create(PlatformTextMarkerRange markerRange) { - return adoptRef(new AccessibilityTextMarkerRange(markerRange)); + return adoptRef(*new AccessibilityTextMarkerRange(markerRange)); } -PassRefPtr<AccessibilityTextMarkerRange> AccessibilityTextMarkerRange::create(const AccessibilityTextMarkerRange& markerRange) +Ref<AccessibilityTextMarkerRange> AccessibilityTextMarkerRange::create(const AccessibilityTextMarkerRange& markerRange) { - return adoptRef(new AccessibilityTextMarkerRange(markerRange)); + return adoptRef(*new AccessibilityTextMarkerRange(markerRange)); } AccessibilityTextMarkerRange::AccessibilityTextMarkerRange(PlatformTextMarkerRange markerRange) @@ -60,7 +60,7 @@ AccessibilityTextMarkerRange::~AccessibilityTextMarkerRange() PlatformTextMarkerRange AccessibilityTextMarkerRange::platformTextMarkerRange() const { -#if PLATFORM(MAC) +#if PLATFORM(COCOA) return m_textMarkerRange.get(); #else return m_textMarkerRange; diff --git a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarkerRange.h b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarkerRange.h index e57a29cd7..18c18d48e 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarkerRange.h +++ b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarkerRange.h @@ -23,15 +23,14 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef AccessibilityTextMarkerRange_h -#define AccessibilityTextMarkerRange_h +#pragma once #include "JSWrappable.h" #include <JavaScriptCore/JSObjectRef.h> -#include <wtf/PassRefPtr.h> #include <wtf/Platform.h> +#include <wtf/Ref.h> -#if PLATFORM(MAC) +#if PLATFORM(COCOA) #include <wtf/RetainPtr.h> typedef CFTypeRef PlatformTextMarkerRange; #else @@ -42,8 +41,8 @@ namespace WTR { class AccessibilityTextMarkerRange : public JSWrappable { public: - static PassRefPtr<AccessibilityTextMarkerRange> create(PlatformTextMarkerRange); - static PassRefPtr<AccessibilityTextMarkerRange> create(const AccessibilityTextMarkerRange&); + static Ref<AccessibilityTextMarkerRange> create(PlatformTextMarkerRange); + static Ref<AccessibilityTextMarkerRange> create(const AccessibilityTextMarkerRange&); ~AccessibilityTextMarkerRange(); @@ -57,17 +56,15 @@ private: AccessibilityTextMarkerRange(PlatformTextMarkerRange); AccessibilityTextMarkerRange(const AccessibilityTextMarkerRange&); -#if PLATFORM(MAC) +#if PLATFORM(COCOA) RetainPtr<PlatformTextMarkerRange> m_textMarkerRange; #else PlatformTextMarkerRange m_textMarkerRange; #endif }; -#if !PLATFORM(MAC) +#if !PLATFORM(COCOA) inline bool AccessibilityTextMarkerRange::isEqual(AccessibilityTextMarkerRange*) { return false; } #endif } // namespace WTR - -#endif // AccessibilityTextMarkerRange_h diff --git a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp index 00e965ff3..233ff7d20 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp +++ b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp @@ -31,14 +31,14 @@ namespace WTR { -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::create(PlatformUIElement uiElement) +Ref<AccessibilityUIElement> AccessibilityUIElement::create(PlatformUIElement uiElement) { - return adoptRef(new AccessibilityUIElement(uiElement)); + return adoptRef(*new AccessibilityUIElement(uiElement)); } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::create(const AccessibilityUIElement& uiElement) +Ref<AccessibilityUIElement> AccessibilityUIElement::create(const AccessibilityUIElement& uiElement) { - return adoptRef(new AccessibilityUIElement(uiElement)); + return adoptRef(*new AccessibilityUIElement(uiElement)); } JSClassRef AccessibilityUIElement::wrapperClass() @@ -53,154 +53,55 @@ bool AccessibilityUIElement::isValid() const return m_element; } +// iOS specific methods +#if !PLATFORM(IOS) +JSRetainPtr<JSStringRef> AccessibilityUIElement::identifier() { return nullptr; } +JSRetainPtr<JSStringRef> AccessibilityUIElement::traits() { return nullptr; } +int AccessibilityUIElement::elementTextPosition() { return 0; } +int AccessibilityUIElement::elementTextLength() { return 0; } +JSRetainPtr<JSStringRef> AccessibilityUIElement::stringForSelection() { return nullptr; } +JSValueRef AccessibilityUIElement::elementsForRange(unsigned, unsigned) { return nullptr; } +void AccessibilityUIElement::increaseTextSelection() { } +void AccessibilityUIElement::decreaseTextSelection() { } +RefPtr<AccessibilityUIElement> AccessibilityUIElement::linkedElement() { return nullptr; } +RefPtr<AccessibilityUIElement> AccessibilityUIElement::headerElementAtIndex(unsigned) { return nullptr; } +void AccessibilityUIElement::assistiveTechnologySimulatedFocus() { return; } +bool AccessibilityUIElement::scrollPageUp() { return false; } +bool AccessibilityUIElement::scrollPageDown() { return false; } +bool AccessibilityUIElement::scrollPageLeft() { return false; } +bool AccessibilityUIElement::scrollPageRight() { return false; } +bool AccessibilityUIElement::hasContainedByFieldsetTrait() { return false; } +RefPtr<AccessibilityUIElement> AccessibilityUIElement::fieldsetAncestorElement() { return nullptr; } +bool AccessibilityUIElement::isSearchField() const { return false; } +bool AccessibilityUIElement::isTextArea() const { return false; } + +#endif + // Unsupported methods on various platforms. As they're implemented on other platforms this list should be modified. #if (!PLATFORM(GTK) && !PLATFORM(EFL)) || !HAVE(ACCESSIBILITY) -JSRetainPtr<JSStringRef> AccessibilityUIElement::characterAtOffset(int) { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::wordAtOffset(int) { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::lineAtOffset(int) { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::sentenceAtOffset(int) { return 0; } +JSRetainPtr<JSStringRef> AccessibilityUIElement::characterAtOffset(int) { return nullptr; } +JSRetainPtr<JSStringRef> AccessibilityUIElement::wordAtOffset(int) { return nullptr; } +JSRetainPtr<JSStringRef> AccessibilityUIElement::lineAtOffset(int) { return nullptr; } +JSRetainPtr<JSStringRef> AccessibilityUIElement::sentenceAtOffset(int) { return nullptr; } #endif -#if (!PLATFORM(MAC) && !PLATFORM(GTK) && !PLATFORM(EFL)) || !HAVE(ACCESSIBILITY) -AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement) { } -AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement&) { } -AccessibilityUIElement::~AccessibilityUIElement() { } -bool AccessibilityUIElement::isEqual(AccessibilityUIElement*) { return false; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::elementAtPoint(int, int) { return 0; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::childAtIndex(unsigned) { return 0; } -unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement*) { return 0; } -int AccessibilityUIElement::childrenCount() { return 0; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::titleUIElement() { return 0; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::parentElement() { return 0; } -void AccessibilityUIElement::takeFocus() { } -void AccessibilityUIElement::takeSelection() { } -void AccessibilityUIElement::addSelection() { } -void AccessibilityUIElement::removeSelection() { } -JSRetainPtr<JSStringRef> AccessibilityUIElement::allAttributes() { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfLinkedUIElements() { return 0; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::linkedUIElementAtIndex(unsigned) { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfDocumentLinks() { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfChildren() { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::parameterizedAttributeNames() { return 0; } -void AccessibilityUIElement::increment() { } -void AccessibilityUIElement::decrement() { } -void AccessibilityUIElement::showMenu() { } -void AccessibilityUIElement::press() { } -JSRetainPtr<JSStringRef> AccessibilityUIElement::stringAttributeValue(JSStringRef) { return 0; } -JSValueRef AccessibilityUIElement::uiElementArrayAttributeValue(JSStringRef) const { return nullptr; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::uiElementAttributeValue(JSStringRef) const { return 0; } -double AccessibilityUIElement::numberAttributeValue(JSStringRef) { return 0; } -bool AccessibilityUIElement::boolAttributeValue(JSStringRef) { return false; } -bool AccessibilityUIElement::isAttributeSupported(JSStringRef) { return false; } -bool AccessibilityUIElement::isAttributeSettable(JSStringRef) { return false; } -bool AccessibilityUIElement::isPressActionSupported() { return false; } -bool AccessibilityUIElement::isIncrementActionSupported() { return false; } -bool AccessibilityUIElement::isDecrementActionSupported() { return false; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::role() { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::subrole() { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::roleDescription() { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::title() { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::description() { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::language() { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::stringValue() { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::accessibilityValue() const { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::helpText() const { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::orientation() const { return 0; } -double AccessibilityUIElement::x() { return 0; } -double AccessibilityUIElement::y() { return 0; } -double AccessibilityUIElement::width() { return 0; } -double AccessibilityUIElement::height() { return 0; } -double AccessibilityUIElement::intValue() const { return 0; } -double AccessibilityUIElement::minValue() { return 0; } -double AccessibilityUIElement::maxValue() { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::valueDescription() { return 0; } -int AccessibilityUIElement::insertionPointLineNumber() { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::selectedTextRange() { return 0; } -bool AccessibilityUIElement::isEnabled() { return false; } -bool AccessibilityUIElement::isRequired() const { return false; } -bool AccessibilityUIElement::isFocused() const { return false; } -bool AccessibilityUIElement::isFocusable() const { return false; } -bool AccessibilityUIElement::isSelected() const { return false; } -bool AccessibilityUIElement::isSelectedOptionActive() const { return false; } -bool AccessibilityUIElement::isSelectable() const { return false; } -bool AccessibilityUIElement::isMultiSelectable() const { return false; } -void AccessibilityUIElement::setSelectedChild(AccessibilityUIElement*) const { } -unsigned AccessibilityUIElement::selectedChildrenCount() const { return 0; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::selectedChildAtIndex(unsigned) const { return 0; } -bool AccessibilityUIElement::isExpanded() const { return false; } -bool AccessibilityUIElement::isChecked() const { return false; } -bool AccessibilityUIElement::isIndeterminate() const { return false; } -bool AccessibilityUIElement::isVisible() const { return false; } -bool AccessibilityUIElement::isOffScreen() const { return false; } -bool AccessibilityUIElement::isCollapsed() const { return false; } -bool AccessibilityUIElement::isIgnored() const { return false; } -bool AccessibilityUIElement::hasPopup() const { return false; } -int AccessibilityUIElement::hierarchicalLevel() const { return 0; } -double AccessibilityUIElement::clickPointX() { return 0; } -double AccessibilityUIElement::clickPointY() { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::documentEncoding() { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::documentURI() { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::url() { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::speak() { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfColumnHeaders() { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfRowHeaders() { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfColumns() { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfRows() { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfVisibleCells() { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfHeader() { return 0; } -int AccessibilityUIElement::indexInTable() { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::rowIndexRange() { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::columnIndexRange() { return 0; } -int AccessibilityUIElement::rowCount() { return 0; } -int AccessibilityUIElement::columnCount() { return 0; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::selectedRowAtIndex(unsigned) { return 0; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::disclosedByRow() { return 0; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::disclosedRowAtIndex(unsigned) { return 0; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::rowAtIndex(unsigned) { return 0; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned) { return 0; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned) { return 0; } -bool AccessibilityUIElement::ariaIsGrabbed() const { return false; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::ariaDropEffects() const { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::classList() const { return 0; } -int AccessibilityUIElement::lineForIndex(int) { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::rangeForLine(int) { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::rangeForPosition(int, int) { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::boundsForRange(unsigned, unsigned) { return 0; } -bool AccessibilityUIElement::setSelectedTextRange(unsigned, unsigned) { return false; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::stringForRange(unsigned, unsigned) { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::attributedStringForRange(unsigned, unsigned) { return 0; } -bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned, unsigned) { return false; } -unsigned AccessibilityUIElement::uiElementCountForSearchPredicate(JSContextRef, AccessibilityUIElement*, bool, JSValueRef, JSStringRef, bool) { return 0; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::uiElementForSearchPredicate(JSContextRef, AccessibilityUIElement*, bool, JSValueRef, JSStringRef, bool) { return 0; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::cellForColumnAndRow(unsigned, unsigned) { return 0; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::horizontalScrollbar() const { return 0; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::verticalScrollbar() const { return 0; } -bool AccessibilityUIElement::addNotificationListener(JSValueRef) { return false; } -bool AccessibilityUIElement::removeNotificationListener() { return false; } -PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::textMarkerRangeForElement(AccessibilityUIElement*) { return 0; } -int AccessibilityUIElement::textMarkerRangeLength(AccessibilityTextMarkerRange*) { return 0; } -PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::textMarkerRangeForMarkers(AccessibilityTextMarker*, AccessibilityTextMarker*) { return 0; } -PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::startTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange*) { return 0; } -PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::endTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange*) { return 0; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::accessibilityElementForTextMarker(AccessibilityTextMarker*) { return 0; } -PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::endTextMarkerForBounds(int x, int y, int width, int height) { return 0; } -PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::startTextMarkerForBounds(int x, int y, int width, int height) { return 0; } -PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::textMarkerForPoint(int, int) { return 0; } -PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::previousTextMarker(AccessibilityTextMarker*) { return 0; } -PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::nextTextMarker(AccessibilityTextMarker*) { return 0; } -PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::startTextMarker() { return 0; } -PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::endTextMarker() { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::stringForTextMarkerRange(AccessibilityTextMarkerRange*) { return 0; } -bool AccessibilityUIElement::attributedStringForTextMarkerRangeContainsAttribute(JSStringRef, AccessibilityTextMarkerRange*) { return false; } -int AccessibilityUIElement::indexForTextMarker(AccessibilityTextMarker*) { return -1; } -bool AccessibilityUIElement::isTextMarkerValid(AccessibilityTextMarker*) { return false; } -PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::textMarkerForIndex(int) { return 0; } -void AccessibilityUIElement::scrollToMakeVisible() { } -JSRetainPtr<JSStringRef> AccessibilityUIElement::supportedActions() const { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::mathPostscriptsDescription() const { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::mathPrescriptsDescription() const { return 0; } -JSRetainPtr<JSStringRef> AccessibilityUIElement::pathDescription() const { return 0; } +#if !PLATFORM(MAC) || !HAVE(ACCESSIBILITY) +RefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::selectedTextMarkerRange() { return nullptr; } +void AccessibilityUIElement::resetSelectedTextMarkerRange() { } +void AccessibilityUIElement::setBoolAttributeValue(JSStringRef, bool) { } +#endif +#if !PLATFORM(COCOA) || !HAVE(ACCESSIBILITY) +RefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::leftWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*) { return nullptr; } +RefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*) { return nullptr; } +RefPtr<AccessibilityTextMarker> AccessibilityUIElement::previousWordStartTextMarkerForTextMarker(AccessibilityTextMarker*) { return nullptr; } +RefPtr<AccessibilityTextMarker> AccessibilityUIElement::nextWordEndTextMarkerForTextMarker(AccessibilityTextMarker*) { return nullptr; } +RefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::paragraphTextMarkerRangeForTextMarker(AccessibilityTextMarker*) { return nullptr; } +RefPtr<AccessibilityTextMarker> AccessibilityUIElement::nextParagraphEndTextMarkerForTextMarker(AccessibilityTextMarker*) { return nullptr; } +RefPtr<AccessibilityTextMarker> AccessibilityUIElement::previousParagraphStartTextMarkerForTextMarker(AccessibilityTextMarker*) { return nullptr; } +RefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::sentenceTextMarkerRangeForTextMarker(AccessibilityTextMarker*) { return nullptr; } +RefPtr<AccessibilityTextMarker> AccessibilityUIElement::nextSentenceEndTextMarkerForTextMarker(AccessibilityTextMarker*) { return nullptr; } +RefPtr<AccessibilityTextMarker> AccessibilityUIElement::previousSentenceStartTextMarkerForTextMarker(AccessibilityTextMarker*) { return nullptr; } #endif } // namespace WTR diff --git a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h index 807b82446..5509af217 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h +++ b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef AccessibilityUIElement_h -#define AccessibilityUIElement_h +#pragma once #include "AccessibilityTextMarker.h" #include "AccessibilityTextMarkerRange.h" @@ -35,7 +34,7 @@ #include <wtf/Platform.h> #include <wtf/Vector.h> -#if PLATFORM(MAC) +#if PLATFORM(COCOA) #ifdef __OBJC__ typedef id PlatformUIElement; #else @@ -44,13 +43,13 @@ typedef struct objc_object* PlatformUIElement; #elif HAVE(ACCESSIBILITY) && (PLATFORM(GTK) || PLATFORM(EFL)) #include "AccessibilityNotificationHandlerAtk.h" #include <atk/atk.h> -#include <wtf/gobject/GRefPtr.h> +#include <wtf/glib/GRefPtr.h> typedef GRefPtr<AtkObject> PlatformUIElement; #else typedef void* PlatformUIElement; #endif -#if PLATFORM(MAC) +#if PLATFORM(COCOA) #ifdef __OBJC__ typedef id NotificationHandler; #else @@ -62,8 +61,8 @@ namespace WTR { class AccessibilityUIElement : public JSWrappable { public: - static PassRefPtr<AccessibilityUIElement> create(PlatformUIElement); - static PassRefPtr<AccessibilityUIElement> create(const AccessibilityUIElement&); + static Ref<AccessibilityUIElement> create(PlatformUIElement); + static Ref<AccessibilityUIElement> create(const AccessibilityUIElement&); ~AccessibilityUIElement(); @@ -74,12 +73,12 @@ public: bool isEqual(AccessibilityUIElement* otherElement); - PassRefPtr<AccessibilityUIElement> elementAtPoint(int x, int y); - PassRefPtr<AccessibilityUIElement> childAtIndex(unsigned); + RefPtr<AccessibilityUIElement> elementAtPoint(int x, int y); + RefPtr<AccessibilityUIElement> childAtIndex(unsigned); unsigned indexOfChild(AccessibilityUIElement*); int childrenCount(); - PassRefPtr<AccessibilityUIElement> titleUIElement(); - PassRefPtr<AccessibilityUIElement> parentElement(); + RefPtr<AccessibilityUIElement> titleUIElement(); + RefPtr<AccessibilityUIElement> parentElement(); void takeFocus(); void takeSelection(); @@ -89,7 +88,7 @@ public: // Methods - platform-independent implementations JSRetainPtr<JSStringRef> allAttributes(); JSRetainPtr<JSStringRef> attributesOfLinkedUIElements(); - PassRefPtr<AccessibilityUIElement> linkedUIElementAtIndex(unsigned); + RefPtr<AccessibilityUIElement> linkedUIElementAtIndex(unsigned); JSRetainPtr<JSStringRef> attributesOfDocumentLinks(); JSRetainPtr<JSStringRef> attributesOfChildren(); @@ -103,8 +102,9 @@ public: JSRetainPtr<JSStringRef> stringAttributeValue(JSStringRef attribute); double numberAttributeValue(JSStringRef attribute); JSValueRef uiElementArrayAttributeValue(JSStringRef attribute) const; - PassRefPtr<AccessibilityUIElement> uiElementAttributeValue(JSStringRef attribute) const; + RefPtr<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(); @@ -113,6 +113,7 @@ public: JSRetainPtr<JSStringRef> role(); JSRetainPtr<JSStringRef> subrole(); JSRetainPtr<JSStringRef> roleDescription(); + JSRetainPtr<JSStringRef> computedRoleString(); JSRetainPtr<JSStringRef> title(); JSRetainPtr<JSStringRef> description(); JSRetainPtr<JSStringRef> language(); @@ -140,8 +141,11 @@ public: bool isSelectable() const; bool isMultiSelectable() const; void setSelectedChild(AccessibilityUIElement*) const; + void setSelectedChildAtIndex(unsigned) const; + void removeSelectionAtIndex(unsigned) const; + void clearSelectedChildren() const; unsigned selectedChildrenCount() const; - PassRefPtr<AccessibilityUIElement> selectedChildAtIndex(unsigned) const; + RefPtr<AccessibilityUIElement> selectedChildAtIndex(unsigned) const; bool isValid() const; bool isExpanded() const; @@ -151,6 +155,8 @@ public: bool isOffScreen() const; bool isCollapsed() const; bool isIgnored() const; + bool isSingleLine() const; + bool isMultiLine() const; bool hasPopup() const; int hierarchicalLevel() const; double clickPointX(); @@ -179,14 +185,15 @@ public: JSValueRef columnHeaders() const; // Tree/Outline specific attributes - PassRefPtr<AccessibilityUIElement> selectedRowAtIndex(unsigned); - PassRefPtr<AccessibilityUIElement> disclosedByRow(); - PassRefPtr<AccessibilityUIElement> disclosedRowAtIndex(unsigned); - PassRefPtr<AccessibilityUIElement> rowAtIndex(unsigned); + RefPtr<AccessibilityUIElement> selectedRowAtIndex(unsigned); + RefPtr<AccessibilityUIElement> disclosedByRow(); + RefPtr<AccessibilityUIElement> disclosedRowAtIndex(unsigned); + RefPtr<AccessibilityUIElement> rowAtIndex(unsigned); // ARIA specific - PassRefPtr<AccessibilityUIElement> ariaOwnsElementAtIndex(unsigned); - PassRefPtr<AccessibilityUIElement> ariaFlowToElementAtIndex(unsigned); + RefPtr<AccessibilityUIElement> ariaOwnsElementAtIndex(unsigned); + RefPtr<AccessibilityUIElement> ariaFlowToElementAtIndex(unsigned); + RefPtr<AccessibilityUIElement> ariaControlsElementAtIndex(unsigned); // ARIA Drag and Drop bool ariaIsGrabbed() const; @@ -202,8 +209,9 @@ public: JSRetainPtr<JSStringRef> stringForRange(unsigned location, unsigned length); JSRetainPtr<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); - PassRefPtr<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); + RefPtr<AccessibilityUIElement> uiElementForSearchPredicate(JSContextRef, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly, bool immediateDescendantsOnly); + JSRetainPtr<JSStringRef> selectTextWithCriteria(JSContextRef, JSStringRef ambiguityResolution, JSValueRef searchStrings, JSStringRef replacementString, JSStringRef activity); // Text-specific JSRetainPtr<JSStringRef> characterAtOffset(int offset); @@ -212,33 +220,49 @@ public: JSRetainPtr<JSStringRef> sentenceAtOffset(int offset); // Table-specific - PassRefPtr<AccessibilityUIElement> cellForColumnAndRow(unsigned column, unsigned row); + RefPtr<AccessibilityUIElement> cellForColumnAndRow(unsigned column, unsigned row); // Scrollarea-specific - PassRefPtr<AccessibilityUIElement> horizontalScrollbar() const; - PassRefPtr<AccessibilityUIElement> verticalScrollbar() const; + RefPtr<AccessibilityUIElement> horizontalScrollbar() const; + RefPtr<AccessibilityUIElement> verticalScrollbar() const; void scrollToMakeVisible(); + void scrollToGlobalPoint(int x, int y); + void scrollToMakeVisibleWithSubFocus(int x, int y, int width, int height); // Text markers. - PassRefPtr<AccessibilityTextMarkerRange> textMarkerRangeForElement(AccessibilityUIElement*); - PassRefPtr<AccessibilityTextMarkerRange> textMarkerRangeForMarkers(AccessibilityTextMarker* startMarker, AccessibilityTextMarker* endMarker); - PassRefPtr<AccessibilityTextMarker> startTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange*); - PassRefPtr<AccessibilityTextMarker> endTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange*); - PassRefPtr<AccessibilityTextMarker> endTextMarkerForBounds(int x, int y, int width, int height); - PassRefPtr<AccessibilityTextMarker> startTextMarkerForBounds(int x, int y, int width, int height); - PassRefPtr<AccessibilityTextMarker> textMarkerForPoint(int x, int y); - PassRefPtr<AccessibilityTextMarker> previousTextMarker(AccessibilityTextMarker*); - PassRefPtr<AccessibilityTextMarker> nextTextMarker(AccessibilityTextMarker*); - PassRefPtr<AccessibilityUIElement> accessibilityElementForTextMarker(AccessibilityTextMarker*); + RefPtr<AccessibilityTextMarkerRange> lineTextMarkerRangeForTextMarker(AccessibilityTextMarker*); + RefPtr<AccessibilityTextMarkerRange> textMarkerRangeForElement(AccessibilityUIElement*); + RefPtr<AccessibilityTextMarkerRange> textMarkerRangeForMarkers(AccessibilityTextMarker* startMarker, AccessibilityTextMarker* endMarker); + RefPtr<AccessibilityTextMarkerRange> selectedTextMarkerRange(); + void resetSelectedTextMarkerRange(); + RefPtr<AccessibilityTextMarker> startTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange*); + RefPtr<AccessibilityTextMarker> endTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange*); + RefPtr<AccessibilityTextMarker> endTextMarkerForBounds(int x, int y, int width, int height); + RefPtr<AccessibilityTextMarker> startTextMarkerForBounds(int x, int y, int width, int height); + RefPtr<AccessibilityTextMarker> textMarkerForPoint(int x, int y); + RefPtr<AccessibilityTextMarker> previousTextMarker(AccessibilityTextMarker*); + RefPtr<AccessibilityTextMarker> nextTextMarker(AccessibilityTextMarker*); + RefPtr<AccessibilityUIElement> accessibilityElementForTextMarker(AccessibilityTextMarker*); JSRetainPtr<JSStringRef> stringForTextMarkerRange(AccessibilityTextMarkerRange*); int textMarkerRangeLength(AccessibilityTextMarkerRange*); bool attributedStringForTextMarkerRangeContainsAttribute(JSStringRef, AccessibilityTextMarkerRange*); int indexForTextMarker(AccessibilityTextMarker*); bool isTextMarkerValid(AccessibilityTextMarker*); - PassRefPtr<AccessibilityTextMarker> textMarkerForIndex(int); - PassRefPtr<AccessibilityTextMarker> startTextMarker(); - PassRefPtr<AccessibilityTextMarker> endTextMarker(); + RefPtr<AccessibilityTextMarker> textMarkerForIndex(int); + RefPtr<AccessibilityTextMarker> startTextMarker(); + RefPtr<AccessibilityTextMarker> endTextMarker(); + bool setSelectedVisibleTextRange(AccessibilityTextMarkerRange*); + RefPtr<AccessibilityTextMarkerRange> leftWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*); + RefPtr<AccessibilityTextMarkerRange> rightWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*); + RefPtr<AccessibilityTextMarker> previousWordStartTextMarkerForTextMarker(AccessibilityTextMarker*); + RefPtr<AccessibilityTextMarker> nextWordEndTextMarkerForTextMarker(AccessibilityTextMarker*); + RefPtr<AccessibilityTextMarkerRange> paragraphTextMarkerRangeForTextMarker(AccessibilityTextMarker*); + RefPtr<AccessibilityTextMarker> nextParagraphEndTextMarkerForTextMarker(AccessibilityTextMarker*); + RefPtr<AccessibilityTextMarker> previousParagraphStartTextMarkerForTextMarker(AccessibilityTextMarker*); + RefPtr<AccessibilityTextMarkerRange> sentenceTextMarkerRangeForTextMarker(AccessibilityTextMarker*); + RefPtr<AccessibilityTextMarker> nextSentenceEndTextMarkerForTextMarker(AccessibilityTextMarker*); + RefPtr<AccessibilityTextMarker> previousSentenceStartTextMarkerForTextMarker(AccessibilityTextMarker*); // Returns an ordered list of supported actions for an element. JSRetainPtr<JSStringRef> supportedActions() const; @@ -253,6 +277,29 @@ public: // Make sure you call remove, because you can't rely on objects being deallocated in a timely fashion. bool removeNotificationListener(); + JSRetainPtr<JSStringRef> identifier(); + JSRetainPtr<JSStringRef> traits(); + int elementTextPosition(); + int elementTextLength(); + JSRetainPtr<JSStringRef> stringForSelection(); + JSValueRef elementsForRange(unsigned location, unsigned length); + void increaseTextSelection(); + void decreaseTextSelection(); + RefPtr<AccessibilityUIElement> linkedElement(); + RefPtr<AccessibilityUIElement> headerElementAtIndex(unsigned index); + void assistiveTechnologySimulatedFocus(); + bool isSearchField() const; + bool isTextArea() const; + + bool scrollPageUp(); + bool scrollPageDown(); + bool scrollPageLeft(); + bool scrollPageRight(); + + // Fieldset + bool hasContainedByFieldsetTrait(); + RefPtr<AccessibilityUIElement> fieldsetAncestorElement(); + private: AccessibilityUIElement(PlatformUIElement); AccessibilityUIElement(const AccessibilityUIElement&); @@ -261,7 +308,7 @@ private: // A retained, platform specific object used to help manage notifications for this object. #if HAVE(ACCESSIBILITY) -#if PLATFORM(MAC) +#if PLATFORM(COCOA) NotificationHandler m_notificationHandler; void getLinkedUIElements(Vector<RefPtr<AccessibilityUIElement> >&); @@ -270,7 +317,7 @@ private: void getUIElementsWithAttribute(JSStringRef, Vector<RefPtr<AccessibilityUIElement> >&) const; #endif -#if PLATFORM(MAC) || PLATFORM(GTK) || PLATFORM(EFL) +#if PLATFORM(COCOA) || PLATFORM(GTK) || PLATFORM(EFL) void getChildren(Vector<RefPtr<AccessibilityUIElement> >&); void getChildrenWithRange(Vector<RefPtr<AccessibilityUIElement> >&, unsigned location, unsigned length); #endif @@ -282,5 +329,3 @@ private: }; } // namespace WTR - -#endif // AccessibilityUIElement_h diff --git a/Tools/WebKitTestRunner/InjectedBundle/Bindings/JSWrapper.h b/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityController.idl index d885801b9..d50a2033f 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/Bindings/JSWrapper.h +++ b/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityController.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2011 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,35 +23,23 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSWrapper_h -#define JSWrapper_h - -#include "JSWrappable.h" -#include <JavaScriptCore/JSRetainPtr.h> - -namespace WTR { - -// FIXME: If necessary, we can do wrapper caching here. -class JSWrapper { -public: - static JSValueRef wrap(JSContextRef context, JSWrappable* object); - static JSWrappable* unwrap(JSContextRef context, JSValueRef value); - - static void initialize(JSContextRef, JSObjectRef); - static void finalize(JSObjectRef); +interface AccessibilityController { + void enableEnhancedAccessibility(boolean enable); + readonly attribute boolean enhancedAccessibilityEnabled; + + readonly attribute DOMString platformName; + readonly attribute AccessibilityUIElement rootElement; + readonly attribute AccessibilityUIElement focusedElement; + AccessibilityUIElement elementAtPoint(long x, long y); + AccessibilityUIElement accessibleElementById(DOMString id); + + boolean addNotificationListener(object functionCallback); + boolean removeNotificationListener(); + + void logFocusEvents(); + void logValueChangeEvents(); + void logScrollingStartEvents(); + void logAccessibilityEvents(); + void resetToConsistentState(); }; -inline JSValueRef toJS(JSContextRef context, JSWrappable* impl) -{ - return JSWrapper::wrap(context, impl); -} - -inline void setProperty(JSContextRef context, JSObjectRef object, const char* propertyName, JSWrappable* value, JSPropertyAttributes attributes, JSValueRef* exception) -{ - JSRetainPtr<JSStringRef> propertyNameString(Adopt, JSStringCreateWithUTF8CString(propertyName)); - JSObjectSetProperty(context, object, propertyNameString.get(), JSWrapper::wrap(context, value), attributes, exception); -} - -} // namespace WTR - -#endif // JSWrapper_h diff --git a/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityTextMarker.idl b/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityTextMarker.idl new file mode 100644 index 000000000..149c95f34 --- /dev/null +++ b/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityTextMarker.idl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2011 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. + */ + +interface AccessibilityTextMarker { + boolean isEqual(AccessibilityTextMarker otherMarker); +}; + diff --git a/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityTextMarkerRange.idl b/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityTextMarkerRange.idl new file mode 100644 index 000000000..962c584e6 --- /dev/null +++ b/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityTextMarkerRange.idl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2011 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. + */ + +interface AccessibilityTextMarkerRange { + boolean isEqual(AccessibilityTextMarkerRange otherMarkerRange); +}; + diff --git a/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl b/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl new file mode 100644 index 000000000..967cb975d --- /dev/null +++ b/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl @@ -0,0 +1,249 @@ +/* + * Copyright (C) 2011 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. + */ + +interface AccessibilityUIElement { + boolean isEqual(AccessibilityUIElement otherElement); + + // Document information + readonly attribute DOMString documentEncoding; + readonly attribute DOMString documentURI; + + // Element access. + AccessibilityUIElement elementAtPoint(long x, long y); + AccessibilityUIElement childAtIndex(unsigned long index); + unsigned long indexOfChild(AccessibilityUIElement child); + AccessibilityUIElement linkedUIElementAtIndex(unsigned long index); + AccessibilityUIElement selectedChildAtIndex(unsigned long index); + void setSelectedChild(AccessibilityUIElement element); + void setSelectedChildAtIndex(unsigned long index); + void removeSelectionAtIndex(unsigned long index); + void clearSelectedChildren(); + AccessibilityUIElement titleUIElement(); + AccessibilityUIElement parentElement(); + + readonly attribute DOMString role; + readonly attribute DOMString subrole; + readonly attribute DOMString roleDescription; + readonly attribute DOMString computedRoleString; + readonly attribute DOMString title; + readonly attribute DOMString description; + readonly attribute DOMString language; + readonly attribute DOMString helpText; + readonly attribute DOMString valueDescription; + readonly attribute DOMString url; + readonly attribute DOMString speak; + readonly attribute DOMString orientation; + readonly attribute long insertionPointLineNumber; + readonly attribute DOMString selectedTextRange; + + DOMString stringAttributeValue(DOMString attr); + double numberAttributeValue(DOMString attr); + object uiElementArrayAttributeValue(DOMString attr); + AccessibilityUIElement uiElementAttributeValue(DOMString attr); + boolean boolAttributeValue(DOMString attr); + void setBoolAttributeValue(DOMString attr, boolean value); + boolean isAttributeSupported(DOMString attr); + boolean isAttributeSettable(DOMString attr); + boolean isPressActionSupported(); + boolean isIncrementActionSupported(); + boolean isDecrementActionSupported(); + + readonly attribute DOMString stringValue; + readonly attribute long intValue; + readonly attribute long minValue; + readonly attribute long maxValue; + + readonly attribute boolean isEnabled; + readonly attribute boolean isRequired; + readonly attribute boolean isFocused; + readonly attribute boolean isFocusable; + readonly attribute boolean isSelectable; + readonly attribute boolean isSelected; + readonly attribute boolean isSelectedOptionActive; + readonly attribute boolean isMultiSelectable; + readonly attribute boolean isExpanded; + readonly attribute boolean isChecked; + readonly attribute boolean isIndeterminate; + readonly attribute boolean isVisible; + readonly attribute boolean isCollapsed; + readonly attribute boolean hasPopup; + readonly attribute boolean isIgnored; + readonly attribute boolean isSingleLine; + readonly attribute boolean isMultiLine; + readonly attribute boolean isOffScreen; + readonly attribute boolean isValid; + readonly attribute long hierarchicalLevel; + readonly attribute boolean ariaIsGrabbed; + readonly attribute DOMString ariaDropEffects; + readonly attribute DOMString classList; + + readonly attribute long x; + readonly attribute long y; + readonly attribute long width; + readonly attribute long height; + readonly attribute long clickPointX; + readonly attribute long clickPointY; + + readonly attribute long childrenCount; + readonly attribute long selectedChildrenCount; + readonly attribute long rowCount; + readonly attribute long columnCount; + + // Actions. + void increment(); + void decrement(); + void press(); + void showMenu(); + + // Attribute info. + DOMString allAttributes(); + DOMString attributesOfChildren(); + DOMString attributesOfLinkedUIElements(); + DOMString attributesOfDocumentLinks(); + + // Text info. + DOMString characterAtOffset(long offset); + DOMString wordAtOffset(long offset); + DOMString lineAtOffset(long offset); + DOMString sentenceAtOffset(long offset); + + // Table info. + DOMString attributesOfColumnHeaders(); + DOMString attributesOfRowHeaders(); + DOMString attributesOfColumns(); + DOMString attributesOfRows(); + DOMString attributesOfVisibleCells(); + DOMString attributesOfHeader(); + AccessibilityUIElement cellForColumnAndRow(unsigned long column, unsigned long row); + AccessibilityUIElement selectedRowAtIndex(unsigned long index); + AccessibilityUIElement disclosedByRow(); + AccessibilityUIElement disclosedRowAtIndex(unsigned long index); + AccessibilityUIElement rowAtIndex(unsigned long index); + long indexInTable(); + DOMString rowIndexRange(); + DOMString columnIndexRange(); + long rowCount(); + long columnCount(); + object columnHeaders(); + object rowHeaders(); + + AccessibilityUIElement ariaOwnsElementAtIndex(unsigned long index); + AccessibilityUIElement ariaFlowToElementAtIndex(unsigned long index); + AccessibilityUIElement ariaControlsElementAtIndex(unsigned long index); + + // Paramaterized attributes. + DOMString parameterizedAttributeNames(); + long lineForIndex(long index); + DOMString rangeForLine(long index); + DOMString rangeForPosition(long x, long y); + DOMString boundsForRange(unsigned long location, unsigned long length); + DOMString stringForRange(unsigned long location, unsigned long length); + DOMString attributedStringForRange(unsigned long location, unsigned long length); + boolean attributedStringRangeIsMisspelled(unsigned long location, unsigned long length); + [PassContext] unsigned long uiElementCountForSearchPredicate(AccessibilityUIElement startElement, boolean isDirectionNext, object searchKey, DOMString searchText, boolean visibleOnly, boolean immediateDescendantsOnly); + [PassContext] AccessibilityUIElement uiElementForSearchPredicate(AccessibilityUIElement startElement, boolean isDirectionNext, object searchKey, DOMString searchText, boolean visibleOnly, boolean immediateDescendantsOnly); + [PassContext] DOMString selectTextWithCriteria(DOMString ambiguityResolution, object searchStrings, DOMString replacementString, DOMString activity); + boolean setSelectedTextRange(unsigned long location, unsigned long length); + + // Scroll area attributes. + readonly attribute AccessibilityUIElement horizontalScrollbar; + readonly attribute AccessibilityUIElement verticalScrollbar; + + void scrollToMakeVisible(); + void scrollToGlobalPoint(long x, long y); + void scrollToMakeVisibleWithSubFocus(long x, long y, long width, long height); + + void takeFocus(); + boolean scrollPageDown(); + boolean scrollPageUp(); + boolean scrollPageLeft(); + boolean scrollPageRight(); + + // Text markers. + AccessibilityTextMarkerRange lineTextMarkerRangeForTextMarker(AccessibilityTextMarker textMarker); + AccessibilityTextMarkerRange textMarkerRangeForElement(AccessibilityUIElement element); + AccessibilityTextMarkerRange textMarkerRangeForMarkers(AccessibilityTextMarker startMarker, AccessibilityTextMarker endMarker); + AccessibilityTextMarkerRange selectedTextMarkerRange(); + void resetSelectedTextMarkerRange(); + AccessibilityTextMarker startTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange range); + AccessibilityTextMarker endTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange range); + AccessibilityTextMarker endTextMarkerForBounds(long x, long y, long width, long height); + AccessibilityTextMarker startTextMarkerForBounds(long x, long y, long width, long height); + AccessibilityTextMarker textMarkerForPoint(long x, long y); + AccessibilityTextMarker previousTextMarker(AccessibilityTextMarker marker); + AccessibilityTextMarker nextTextMarker(AccessibilityTextMarker marker); + AccessibilityUIElement accessibilityElementForTextMarker(AccessibilityTextMarker marker); + DOMString stringForTextMarkerRange(AccessibilityTextMarkerRange range); + long textMarkerRangeLength(AccessibilityTextMarkerRange range); + boolean attributedStringForTextMarkerRangeContainsAttribute(DOMString attr, AccessibilityTextMarkerRange range); + long indexForTextMarker(AccessibilityTextMarker marker); + boolean isTextMarkerValid(AccessibilityTextMarker marker); + AccessibilityTextMarker textMarkerForIndex(long textIndex); + readonly attribute AccessibilityTextMarker startTextMarker; + readonly attribute AccessibilityTextMarker endTextMarker; + boolean setSelectedVisibleTextRange(AccessibilityTextMarkerRange range); + AccessibilityTextMarkerRange leftWordTextMarkerRangeForTextMarker(AccessibilityTextMarker textMarker); + AccessibilityTextMarkerRange rightWordTextMarkerRangeForTextMarker(AccessibilityTextMarker textMarker); + AccessibilityTextMarker previousWordStartTextMarkerForTextMarker(AccessibilityTextMarker textMarker); + AccessibilityTextMarker nextWordEndTextMarkerForTextMarker(AccessibilityTextMarker textMarker); + AccessibilityTextMarkerRange paragraphTextMarkerRangeForTextMarker(AccessibilityTextMarker textMarker); + AccessibilityTextMarker previousParagraphStartTextMarkerForTextMarker(AccessibilityTextMarker textMarker); + AccessibilityTextMarker nextParagraphEndTextMarkerForTextMarker(AccessibilityTextMarker textMarker); + AccessibilityTextMarkerRange sentenceTextMarkerRangeForTextMarker(AccessibilityTextMarker textMarker); + AccessibilityTextMarker previousSentenceStartTextMarkerForTextMarker(AccessibilityTextMarker textMarker); + AccessibilityTextMarker nextSentenceEndTextMarkerForTextMarker(AccessibilityTextMarker textMarker); + + // Returns an ordered list of supported actions for an element. + readonly attribute DOMString supportedActions; + readonly attribute DOMString mathPostscriptsDescription; + readonly attribute DOMString mathPrescriptsDescription; + + readonly attribute DOMString pathDescription; + + // iOS specific accessibility methods. + readonly attribute DOMString identifier; + readonly attribute DOMString traits; + readonly attribute long elementTextPosition; + readonly attribute long elementTextLength; + readonly attribute DOMString stringForSelection; + object elementsForRange(unsigned long location, unsigned long length); + void increaseTextSelection(); + void decreaseTextSelection(); + AccessibilityUIElement linkedElement(); + AccessibilityUIElement headerElementAtIndex(unsigned long index); + // This will simulate the accessibilityDidBecomeFocused API in UIKit. + void assistiveTechnologySimulatedFocus(); + readonly attribute boolean isSearchField; + readonly attribute boolean isTextArea; + + // Fieldset + readonly attribute boolean hasContainedByFieldsetTrait; + AccessibilityUIElement fieldsetAncestorElement(); + + // Notification support. + boolean addNotificationListener(object callbackFunction); + boolean removeNotificationListener(); +}; + diff --git a/Tools/WebKitTestRunner/InjectedBundle/Bindings/CodeGeneratorTestRunner.pm b/Tools/WebKitTestRunner/InjectedBundle/Bindings/CodeGeneratorTestRunner.pm new file mode 100644 index 000000000..98d37dab9 --- /dev/null +++ b/Tools/WebKitTestRunner/InjectedBundle/Bindings/CodeGeneratorTestRunner.pm @@ -0,0 +1,577 @@ +# Copyright (C) 2010 Apple Inc. All rights reserved. +# Copyright (C) 2012 Samsung Electronics +# +# 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 CodeGeneratorTestRunner; + +use Carp qw<longmess>; +use Data::Dumper; + +sub assert +{ + my $message = shift; + + my $mess = longmess(); + print Dumper($mess); + + die $message; +} + +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) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * 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/WebKitTestRunner/InjectedBundle/Bindings/EventSendingController.idl b/Tools/WebKitTestRunner/InjectedBundle/Bindings/EventSendingController.idl new file mode 100644 index 000000000..f3280bb94 --- /dev/null +++ b/Tools/WebKitTestRunner/InjectedBundle/Bindings/EventSendingController.idl @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2010, 2011, 2014-2015 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. + */ + +interface EventSendingController { + void mouseDown(long buttonNumber, object modifierArray); + void mouseUp(long buttonNumber, object modifierArray); + void mouseMoveTo(long x, long y); + void mouseForceClick(); + void startAndCancelMouseForceClick(); + void mouseForceDown(); + void mouseForceUp(); + void mouseForceChanged(double force); + void mouseScrollBy(long x, long y); + void mouseScrollByWithWheelAndMomentumPhases(long x, long y, DOMString phase, DOMString momentum); + void swipeGestureWithWheelAndMomentumPhases(long x, long y, DOMString phase, DOMString momentum); + void continuousMouseScrollBy(long x, long y, optional boolean paged); + object contextClick(); + void scheduleAsynchronousClick(); + + void leapForward(long milliseconds); + + void keyDown(DOMString key, object modifierArray, long location); + void scheduleAsynchronousKeyDown(DOMString key); + + // Zoom functions. + void textZoomIn(); + void textZoomOut(); + void zoomPageIn(); + void zoomPageOut(); + void scalePageBy(double scale, double x, double y); + + void monitorWheelEvents(); + void callAfterScrollingCompletes(object functionCallback); + +#if defined(ENABLE_TOUCH_EVENTS) && ENABLE_TOUCH_EVENTS + // Touch events. + void addTouchPoint(long x, long y); + void updateTouchPoint(long index, long x, long y); + void setTouchModifier(DOMString modifier, boolean enable); + void setTouchPointRadius(long radiusX, long radiusY); + void touchStart(); + void touchMove(); + void touchEnd(); + void touchCancel(); + void clearTouchPoints(); + void releaseTouchPoint(long index); + void cancelTouchPoint(long index); +#endif +}; + diff --git a/Tools/WebKitTestRunner/InjectedBundle/Bindings/JSWrappable.h b/Tools/WebKitTestRunner/InjectedBundle/Bindings/GCController.idl index 5ec7197c5..fb933834d 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/Bindings/JSWrappable.h +++ b/Tools/WebKitTestRunner/InjectedBundle/Bindings/GCController.idl @@ -23,25 +23,9 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSWrappable_h -#define JSWrappable_h - -#include <JavaScriptCore/JavaScript.h> -#include <wtf/RefCounted.h> - -namespace WTR { - -class JSWrappable : public RefCounted<JSWrappable> { -public: - virtual ~JSWrappable() { } - virtual JSClassRef wrapperClass() = 0; +interface GCController { + void collect(); + void collectOnAlternateThread(boolean waitUntilDone); + unsigned long long getJSObjectCount(); }; -inline JSValueRef JSValueMakeStringOrNull(JSContextRef context, JSStringRef stringOrNull) -{ - return stringOrNull ? JSValueMakeString(context, stringOrNull) : JSValueMakeNull(context); -} - -} // namespace WTR - -#endif // JSWrappable_h diff --git a/Tools/WebKitTestRunner/InjectedBundle/Bindings/JSWrapper.cpp b/Tools/WebKitTestRunner/InjectedBundle/Bindings/JSWrapper.cpp deleted file mode 100644 index e3cf58c2c..000000000 --- a/Tools/WebKitTestRunner/InjectedBundle/Bindings/JSWrapper.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2010 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * 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 "config.h" -#include "JSWrapper.h" - -#include <JavaScriptCore/JSContextRefPrivate.h> - -namespace WTR { - -JSValueRef JSWrapper::wrap(JSContextRef context, JSWrappable* object) -{ - ASSERT_ARG(context, context); - - if (!object) - return JSValueMakeNull(context); - - JSClassRef objectClass = object->wrapperClass(); - ASSERT(objectClass); - JSObjectRef wrapperObject = JSObjectMake(context, objectClass, object); - ASSERT(wrapperObject); - - return wrapperObject; -} - -JSWrappable* JSWrapper::unwrap(JSContextRef context, JSValueRef value) -{ - ASSERT_ARG(context, context); - ASSERT_ARG(value, value); - if (!context || !value) - return 0; - return static_cast<JSWrappable*>(JSObjectGetPrivate(JSValueToObject(context, value, 0))); -} - -static JSWrappable* unwrapObject(JSObjectRef object) -{ - JSWrappable* wrappable = static_cast<JSWrappable*>(JSObjectGetPrivate(object)); - ASSERT(wrappable); - return wrappable; -} - -void JSWrapper::initialize(JSContextRef ctx, JSObjectRef object) -{ - JSWrappable* wrappable = unwrapObject(object); - if (!wrappable) - return; - wrappable->ref(); -} - -void JSWrapper::finalize(JSObjectRef object) -{ - JSWrappable* wrappable = unwrapObject(object); - if (!wrappable) - return; - wrappable->deref(); -} - -} // namespace WTR diff --git a/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl b/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl new file mode 100644 index 000000000..352fa0ae7 --- /dev/null +++ b/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl @@ -0,0 +1,262 @@ +/* + * Copyright (C) 2010-2017 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. + */ + +interface TestRunner { + readonly attribute boolean isWebKit2; + + // The basics. + void dumpAsText(boolean dumpPixels); + void dumpChildFramesAsText(); + void waitForPolicyDelegate(); + void waitUntilDone(); + void waitUntilDownloadFinished(); + void notifyDone(); + double preciseTime(); + readonly attribute double timeout; + + // Other dumping. + void dumpBackForwardList(); + void dumpChildFrameScrollPositions(); + void dumpEditingCallbacks(); + void dumpSelectionRect(); + void dumpStatusCallbacks(); + void dumpTitleChanges(); + void dumpFullScreenCallbacks(); + void dumpFrameLoadCallbacks(); + void dumpProgressFinishedCallback(); + void dumpResourceLoadCallbacks(); + void dumpResourceResponseMIMETypes(); + void dumpWillCacheResponse(); + void dumpApplicationCacheDelegateCallbacks(); + void dumpDatabaseCallbacks(); + void dumpDOMAsWebArchive(); + void dumpPolicyDelegateCallbacks(); + + // Special options. + void keepWebHistory(); + void setAcceptsEditing(boolean value); + void setCanOpenWindows(boolean value); + void setCloseRemainingWindowsWhenComplete(boolean value); + void setXSSAuditorEnabled(boolean value); + void setAllowUniversalAccessFromFileURLs(boolean value); + void setAllowFileAccessFromFileURLs(boolean value); + void setNeedsStorageAccessFromFileURLsQuirk(boolean value); + void setPluginsEnabled(boolean value); + void setJavaScriptCanAccessClipboard(boolean value); + void setPrivateBrowsingEnabled(boolean value); + void setUseDashboardCompatibilityMode(boolean value); + void setPopupBlockingEnabled(boolean value); + void setAuthorAndUserStylesEnabled(boolean value); + void setCustomPolicyDelegate(boolean enabled, boolean permissive); + void addOriginAccessWhitelistEntry(DOMString sourceOrigin, DOMString destinationProtocol, DOMString destinationHost, boolean allowDestinationSubdomains); + void removeOriginAccessWhitelistEntry(DOMString sourceOrigin, DOMString destinationProtocol, DOMString destinationHost, boolean allowDestinationSubdomains); + void setUserStyleSheetEnabled(boolean value); + void setUserStyleSheetLocation(DOMString location); + void setSpatialNavigationEnabled(boolean value); + void setTabKeyCyclesThroughElements(boolean enabled); + void setSerializeHTTPLoads(); + void dispatchPendingLoadRequests(); + void setCacheModel(long model); + void setAsynchronousSpellCheckingEnabled(boolean value); + void setPrinting(); + void setShouldDecideNavigationPolicyAfterDelay(boolean value); + void setNavigationGesturesEnabled(boolean value); + void setIgnoresViewportScaleLimits(boolean value); + void setShouldDownloadUndisplayableMIMETypes(boolean value); + + // Special DOM functions. + void clearBackForwardList(); + void execCommand(DOMString name, DOMString argument); + boolean isCommandEnabled(DOMString name); + unsigned long windowCount(); + + // Special DOM variables. + attribute boolean globalFlag; + + // Repaint testing. + void testRepaint(); + void repaintSweepHorizontally(); + void display(); + + // Printing + boolean isPageBoxVisible(long pageIndex); + + [PassContext] void setValueForUser(object element, DOMString value); + + // UserContent testing. + void addUserScript(DOMString source, boolean runAtStart, boolean allFrames); + void addUserStyleSheet(DOMString source, boolean allFrames); + + // Local storage API + void clearAllDatabases(); + void setDatabaseQuota(unsigned long long quota); + DOMString pathToLocalResource(DOMString url); + + attribute double databaseDefaultQuota; + attribute double databaseMaxQuota; + + // Application Cache API + void clearAllApplicationCaches(); + void setAppCacheMaximumSize(unsigned long long size); + long long applicationCacheDiskUsageForOrigin(DOMString origin); + void clearApplicationCacheForOrigin(DOMString name); + void disallowIncreaseForApplicationCacheQuota(); + object originsWithApplicationCache(); + + // Text search testing. + boolean findString(DOMString target, object optionsArray); + + // Evaluating script in a special context. + [PassContext] void evaluateScriptInIsolatedWorld(unsigned long worldID, DOMString script); + + // For Web Inspector tests + void showWebInspector(); + void closeWebInspector(); + void evaluateInWebInspector(DOMString script); + readonly attribute DOMString inspectorTestStubURL; + + void setPOSIXLocale(DOMString locale); + + void setTextDirection(DOMString direction); + + void setWillSendRequestReturnsNull(boolean flag); + void setWillSendRequestReturnsNullOnRedirect(boolean flag); + void setWillSendRequestAddsHTTPBody(DOMString body); + + void setShouldStayOnPageAfterHandlingBeforeUnload(boolean flag); + + void setDefersLoading(boolean flag); + void setStopProvisionalFrameLoads(); + + // Focus testing. + void addChromeInputField(object callback); + void removeChromeInputField(object callback); + void focusWebView(object callback); + + // Window/view state + void setBackingScaleFactor(double backingScaleFactor, object callback); + + void setWindowIsKey(boolean isKey); + void setViewSize(double width, double height); + + // Cookies testing + void setAlwaysAcceptCookies(boolean accept); + + void overridePreference(DOMString preference, DOMString value); + + // Page Visibility API + void setPageVisibility(DOMString state); + void resetPageVisibility(); + + // Control full screen behavior. + void setHasCustomFullScreenBehavior(boolean value); + + // Web notifications support + void grantWebNotificationPermission(DOMString origin); + void denyWebNotificationPermission(DOMString origin); + void removeAllWebNotificationPermissions(); + void simulateWebNotificationClick(object notification); + + // Geolocation + void setGeolocationPermission(boolean value); + void setMockGeolocationPosition(double latitude, double longitude, double accuracy, optional object altitude, optional object altitudeAccuracy, optional object heading, optional object speed); + void setMockGeolocationPositionUnavailableError(DOMString errorMessage); + boolean isGeolocationProviderActive(); + + // MediaStream + void setUserMediaPermission(boolean value); + void setUserMediaPersistentPermissionForOrigin(boolean permission, DOMString origin, DOMString parentOrigin); + unsigned long userMediaPermissionRequestCountForOrigin(DOMString origin, DOMString parentOrigin); + void resetUserMediaPermissionRequestCountForOrigin(DOMString origin, DOMString parentOrigin); + + // Audio testing. + [PassContext] void setAudioResult(object data); + + boolean callShouldCloseOnWebView(); + + // Work queue. + void queueBackNavigation(unsigned long howFarBackward); + void queueForwardNavigation(unsigned long howFarForward); + void queueLoad(DOMString url, DOMString target, optional boolean shouldOpenExternalURLs); + void queueLoadHTMLString(DOMString content, optional DOMString baseURL, optional DOMString unreachableURL); + void queueReload(); + void queueLoadingScript(DOMString script); + void queueNonLoadingScript(DOMString script); + + // Authentication + void setRejectsProtectionSpaceAndContinueForAuthenticationChallenges(boolean value); + void setHandlesAuthenticationChallenges(boolean value); + void setShouldLogCanAuthenticateAgainstProtectionSpace(boolean value); + void setAuthenticationUsername(DOMString username); + void setAuthenticationPassword(DOMString password); + + void setAllowsAnySSLCertificate(boolean value); + + // Secure text input mode (Mac only) + readonly attribute boolean secureEventInputIsEnabled; + + // Override plugin load policy. + void setBlockAllPlugins(boolean shouldBlock); + + // Hooks to the JSC compiler. + object failNextNewCodeBlock(); + object numberOfDFGCompiles(object function); + object neverInlineFunction(object function); + + // Swipe gestures + void installDidBeginSwipeCallback(object callback); + void installWillEndSwipeCallback(object callback); + void installDidEndSwipeCallback(object callback); + void installDidRemoveSwipeSnapshotCallback(object callback); + + unsigned long imageCountInGeneralPasteboard(); + + // UI Process Testing + void runUIScript(DOMString script, object callback); + + void clearTestRunnerCallbacks(); + + void accummulateLogsForChannel(DOMString channel); + + // Gamepad + void setMockGamepadDetails(unsigned long index, DOMString id, unsigned long axisCount, unsigned long buttonCount); + void setMockGamepadAxisValue(unsigned long index, unsigned long axisIndex, double value); + void setMockGamepadButtonValue(unsigned long index, unsigned long buttonIndex, double value); + void connectMockGamepad(unsigned long index); + void disconnectMockGamepad(unsigned long index); + + // Resource Load Statistics + void installStatisticsDidModifyDataRecordsCallback(object callback); + void setStatisticsPrevalentResource(DOMString hostName, boolean value); + boolean isStatisticsPrevalentResource(DOMString hostName); + void setStatisticsHasHadUserInteraction(DOMString hostName, boolean value); + boolean isStatisticsHasHadUserInteraction(DOMString hostName); + void setStatisticsTimeToLiveUserInteraction(double seconds); + void statisticsFireDataModificationHandler(); + void setStatisticsNotifyPagesWhenDataRecordsWereScanned(boolean value); + void setStatisticsShouldClassifyResourcesBeforeDataRecordsRemoval(boolean value); + void setStatisticsMinimumTimeBetweeenDataRecordsRemoval(double seconds); + void statisticsResetToConsistentState(); +}; diff --git a/Tools/WebKitTestRunner/InjectedBundle/Bindings/TextInputController.idl b/Tools/WebKitTestRunner/InjectedBundle/Bindings/TextInputController.idl new file mode 100644 index 000000000..d95a6985d --- /dev/null +++ b/Tools/WebKitTestRunner/InjectedBundle/Bindings/TextInputController.idl @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies) + * + * 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. + */ + +interface TextInputController { + void setMarkedText(DOMString string, long from, long length); + boolean hasMarkedText(); + void unmarkText(); + void insertText(DOMString string); +}; + diff --git a/Tools/WebKitTestRunner/InjectedBundle/EventSendingController.cpp b/Tools/WebKitTestRunner/InjectedBundle/EventSendingController.cpp index 65e355652..6bd165288 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/EventSendingController.cpp +++ b/Tools/WebKitTestRunner/InjectedBundle/EventSendingController.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2011 Apple Inc. All rights reserved. + * Copyright (C) 2010, 2011, 2014-2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,13 +30,13 @@ #include "InjectedBundlePage.h" #include "JSEventSendingController.h" #include "StringFunctions.h" -#include <WebKit2/WKBundle.h> -#include <WebKit2/WKBundleFrame.h> -#include <WebKit2/WKBundlePagePrivate.h> -#include <WebKit2/WKBundlePrivate.h> -#include <WebKit2/WKContextMenuItem.h> -#include <WebKit2/WKMutableDictionary.h> -#include <WebKit2/WKNumber.h> +#include <WebKit/WKBundle.h> +#include <WebKit/WKBundleFrame.h> +#include <WebKit/WKBundlePagePrivate.h> +#include <WebKit/WKBundlePrivate.h> +#include <WebKit/WKContextMenuItem.h> +#include <WebKit/WKMutableDictionary.h> +#include <WebKit/WKNumber.h> #include <wtf/StdLibExtras.h> namespace WTR { @@ -116,6 +116,8 @@ static WKEventModifiers parseModifier(JSStringRef modifier) return kWKEventModifiersAltKey; if (JSStringIsEqualToUTF8CString(modifier, "metaKey")) return kWKEventModifiersMetaKey; + if (JSStringIsEqualToUTF8CString(modifier, "capsLockKey")) + return kWKEventModifiersCapsLockKey; if (JSStringIsEqualToUTF8CString(modifier, "addSelectionKey")) { #if OS(MAC_OS_X) return kWKEventModifiersMetaKey; @@ -164,9 +166,9 @@ static WKEventModifiers parseModifierArray(JSContextRef context, JSValueRef arra return modifiers; } -PassRefPtr<EventSendingController> EventSendingController::create() +Ref<EventSendingController> EventSendingController::create() { - return adoptRef(new EventSendingController); + return adoptRef(*new EventSendingController); } EventSendingController::EventSendingController() @@ -208,7 +210,8 @@ static WKMutableDictionaryRef createMouseMessageBody(MouseState state, int butto void EventSendingController::mouseDown(int button, JSValueRef modifierArray) { - WKBundlePageRef page = InjectedBundle::shared().page()->page(); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundlePageRef page = injectedBundle.page()->page(); WKBundleFrameRef frame = WKBundlePageGetMainFrame(page); JSContextRef context = WKBundleFrameGetJavaScriptContext(frame); WKEventModifiers modifiers = parseModifierArray(context, modifierArray); @@ -216,12 +219,12 @@ void EventSendingController::mouseDown(int button, JSValueRef modifierArray) WKRetainPtr<WKStringRef> EventSenderMessageName(AdoptWK, WKStringCreateWithUTF8CString("EventSender")); WKRetainPtr<WKMutableDictionaryRef> EventSenderMessageBody(AdoptWK, createMouseMessageBody(MouseDown, button, modifiers)); - WKBundlePostSynchronousMessage(InjectedBundle::shared().bundle(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); + WKBundlePagePostSynchronousMessageForTesting(page, EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); } void EventSendingController::mouseUp(int button, JSValueRef modifierArray) { - WKBundlePageRef page = InjectedBundle::shared().page()->page(); + WKBundlePageRef page = InjectedBundle::singleton().page()->page(); WKBundleFrameRef frame = WKBundlePageGetMainFrame(page); JSContextRef context = WKBundleFrameGetJavaScriptContext(frame); WKEventModifiers modifiers = parseModifierArray(context, modifierArray); @@ -229,7 +232,7 @@ void EventSendingController::mouseUp(int button, JSValueRef modifierArray) WKRetainPtr<WKStringRef> EventSenderMessageName(AdoptWK, WKStringCreateWithUTF8CString("EventSender")); WKRetainPtr<WKMutableDictionaryRef> EventSenderMessageBody(AdoptWK, createMouseMessageBody(MouseUp, button, modifiers)); - WKBundlePostSynchronousMessage(InjectedBundle::shared().bundle(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); + WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); } void EventSendingController::mouseMoveTo(int x, int y) @@ -249,7 +252,73 @@ void EventSendingController::mouseMoveTo(int x, int y) WKRetainPtr<WKDoubleRef> yRef(AdoptWK, WKDoubleCreate(y)); WKDictionarySetItem(EventSenderMessageBody.get(), yKey.get(), yRef.get()); - WKBundlePostSynchronousMessage(InjectedBundle::shared().bundle(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); + m_position = WKPointMake(x, y); + + WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); +} + +void EventSendingController::mouseForceClick() +{ + WKRetainPtr<WKStringRef> EventSenderMessageName(AdoptWK, WKStringCreateWithUTF8CString("EventSender")); + WKRetainPtr<WKMutableDictionaryRef> EventSenderMessageBody(AdoptWK, WKMutableDictionaryCreate()); + + WKRetainPtr<WKStringRef> subMessageKey(AdoptWK, WKStringCreateWithUTF8CString("SubMessage")); + WKRetainPtr<WKStringRef> subMessageName(AdoptWK, WKStringCreateWithUTF8CString("MouseForceClick")); + WKDictionarySetItem(EventSenderMessageBody.get(), subMessageKey.get(), subMessageName.get()); + + WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); +} + +void EventSendingController::startAndCancelMouseForceClick() +{ + WKRetainPtr<WKStringRef> EventSenderMessageName(AdoptWK, WKStringCreateWithUTF8CString("EventSender")); + WKRetainPtr<WKMutableDictionaryRef> EventSenderMessageBody(AdoptWK, WKMutableDictionaryCreate()); + + WKRetainPtr<WKStringRef> subMessageKey(AdoptWK, WKStringCreateWithUTF8CString("SubMessage")); + WKRetainPtr<WKStringRef> subMessageName(AdoptWK, WKStringCreateWithUTF8CString("StartAndCancelMouseForceClick")); + WKDictionarySetItem(EventSenderMessageBody.get(), subMessageKey.get(), subMessageName.get()); + + WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); +} + +void EventSendingController::mouseForceDown() +{ + WKRetainPtr<WKStringRef> EventSenderMessageName(AdoptWK, WKStringCreateWithUTF8CString("EventSender")); + WKRetainPtr<WKMutableDictionaryRef> EventSenderMessageBody(AdoptWK, WKMutableDictionaryCreate()); + + WKRetainPtr<WKStringRef> subMessageKey(AdoptWK, WKStringCreateWithUTF8CString("SubMessage")); + WKRetainPtr<WKStringRef> subMessageName(AdoptWK, WKStringCreateWithUTF8CString("MouseForceDown")); + WKDictionarySetItem(EventSenderMessageBody.get(), subMessageKey.get(), subMessageName.get()); + + WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); +} + +void EventSendingController::mouseForceUp() +{ + WKRetainPtr<WKStringRef> EventSenderMessageName(AdoptWK, WKStringCreateWithUTF8CString("EventSender")); + WKRetainPtr<WKMutableDictionaryRef> EventSenderMessageBody(AdoptWK, WKMutableDictionaryCreate()); + + WKRetainPtr<WKStringRef> subMessageKey(AdoptWK, WKStringCreateWithUTF8CString("SubMessage")); + WKRetainPtr<WKStringRef> subMessageName(AdoptWK, WKStringCreateWithUTF8CString("MouseForceUp")); + WKDictionarySetItem(EventSenderMessageBody.get(), subMessageKey.get(), subMessageName.get()); + + WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); +} + +void EventSendingController::mouseForceChanged(double force) +{ + WKRetainPtr<WKStringRef> EventSenderMessageName(AdoptWK, WKStringCreateWithUTF8CString("EventSender")); + WKRetainPtr<WKMutableDictionaryRef> EventSenderMessageBody(AdoptWK, WKMutableDictionaryCreate()); + + WKRetainPtr<WKStringRef> subMessageKey(AdoptWK, WKStringCreateWithUTF8CString("SubMessage")); + WKRetainPtr<WKStringRef> subMessageName(AdoptWK, WKStringCreateWithUTF8CString("MouseForceChanged")); + WKDictionarySetItem(EventSenderMessageBody.get(), subMessageKey.get(), subMessageName.get()); + + WKRetainPtr<WKStringRef> forceKey(AdoptWK, WKStringCreateWithUTF8CString("Force")); + WKRetainPtr<WKDoubleRef> forceRef(AdoptWK, WKDoubleCreate(force)); + WKDictionarySetItem(EventSenderMessageBody.get(), forceKey.get(), forceRef.get()); + + WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); } void EventSendingController::leapForward(int milliseconds) @@ -265,7 +334,7 @@ void EventSendingController::leapForward(int milliseconds) WKRetainPtr<WKUInt64Ref> timeRef(AdoptWK, WKUInt64Create(milliseconds)); WKDictionarySetItem(EventSenderMessageBody.get(), timeKey.get(), timeRef.get()); - WKBundlePostSynchronousMessage(InjectedBundle::shared().bundle(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); + WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); } void EventSendingController::scheduleAsynchronousClick() @@ -277,11 +346,11 @@ void EventSendingController::scheduleAsynchronousClick() // Asynchronous mouse down. WKRetainPtr<WKMutableDictionaryRef> mouseDownMessageBody(AdoptWK, createMouseMessageBody(MouseDown, button, modifiers)); - WKBundlePostMessage(InjectedBundle::shared().bundle(), EventSenderMessageName.get(), mouseDownMessageBody.get()); + WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), mouseDownMessageBody.get()); // Asynchronous mouse up. WKRetainPtr<WKMutableDictionaryRef> mouseUpMessageBody(AdoptWK, createMouseMessageBody(MouseUp, button, modifiers)); - WKBundlePostMessage(InjectedBundle::shared().bundle(), EventSenderMessageName.get(), mouseUpMessageBody.get()); + WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), mouseUpMessageBody.get()); } static WKRetainPtr<WKMutableDictionaryRef> createKeyDownMessageBody(JSStringRef key, WKEventModifiers modifiers, int location) @@ -308,7 +377,7 @@ static WKRetainPtr<WKMutableDictionaryRef> createKeyDownMessageBody(JSStringRef void EventSendingController::keyDown(JSStringRef key, JSValueRef modifierArray, int location) { - WKBundlePageRef page = InjectedBundle::shared().page()->page(); + WKBundlePageRef page = InjectedBundle::singleton().page()->page(); WKBundleFrameRef frame = WKBundlePageGetMainFrame(page); JSContextRef context = WKBundleFrameGetJavaScriptContext(frame); WKEventModifiers modifiers = parseModifierArray(context, modifierArray); @@ -316,7 +385,7 @@ void EventSendingController::keyDown(JSStringRef key, JSValueRef modifierArray, WKRetainPtr<WKStringRef> EventSenderMessageName(AdoptWK, WKStringCreateWithUTF8CString("EventSender")); WKRetainPtr<WKMutableDictionaryRef> keyDownMessageBody = createKeyDownMessageBody(key, modifiers, location); - WKBundlePostSynchronousMessage(InjectedBundle::shared().bundle(), EventSenderMessageName.get(), keyDownMessageBody.get(), 0); + WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), keyDownMessageBody.get(), 0); } void EventSendingController::scheduleAsynchronousKeyDown(JSStringRef key) @@ -324,7 +393,7 @@ void EventSendingController::scheduleAsynchronousKeyDown(JSStringRef key) WKRetainPtr<WKStringRef> EventSenderMessageName(AdoptWK, WKStringCreateWithUTF8CString("EventSender")); WKRetainPtr<WKMutableDictionaryRef> keyDownMessageBody = createKeyDownMessageBody(key, 0 /* modifiers */, 0 /* location */); - WKBundlePostMessage(InjectedBundle::shared().bundle(), EventSenderMessageName.get(), keyDownMessageBody.get()); + WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), keyDownMessageBody.get()); } void EventSendingController::mouseScrollBy(int x, int y) @@ -344,7 +413,106 @@ void EventSendingController::mouseScrollBy(int x, int y) WKRetainPtr<WKDoubleRef> yRef(AdoptWK, WKDoubleCreate(y)); WKDictionarySetItem(EventSenderMessageBody.get(), yKey.get(), yRef.get()); - WKBundlePostSynchronousMessage(InjectedBundle::shared().bundle(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); + WKBundlePageForceRepaint(InjectedBundle::singleton().page()->page()); // Triggers a scrolling tree commit. + WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), EventSenderMessageBody.get()); +} + +static uint64_t cgEventPhaseFromString(JSStringRef phaseStr) +{ + if (JSStringIsEqualToUTF8CString(phaseStr, "none")) + return 0; + if (JSStringIsEqualToUTF8CString(phaseStr, "began")) + return 1; // kCGScrollPhaseBegan + if (JSStringIsEqualToUTF8CString(phaseStr, "changed")) + return 2; // kCGScrollPhaseChanged + if (JSStringIsEqualToUTF8CString(phaseStr, "ended")) + return 4; // kCGScrollPhaseEnded + if (JSStringIsEqualToUTF8CString(phaseStr, "cancelled")) + return 8; // kCGScrollPhaseCancelled + if (JSStringIsEqualToUTF8CString(phaseStr, "maybegin")) + return 128; // kCGScrollPhaseMayBegin + + ASSERT_NOT_REACHED(); + return 0; +} + +static uint64_t cgEventMomentumPhaseFromString(JSStringRef phaseStr) +{ + if (JSStringIsEqualToUTF8CString(phaseStr, "none")) + return 0; // kCGMomentumScrollPhaseNone + if (JSStringIsEqualToUTF8CString(phaseStr, "begin")) + return 1; // kCGMomentumScrollPhaseBegin + if (JSStringIsEqualToUTF8CString(phaseStr, "continue")) + return 2; // kCGMomentumScrollPhaseContinue + if (JSStringIsEqualToUTF8CString(phaseStr, "end")) + return 3; // kCGMomentumScrollPhaseEnd + + ASSERT_NOT_REACHED(); + return 0; +} + +void EventSendingController::mouseScrollByWithWheelAndMomentumPhases(int x, int y, JSStringRef phaseStr, JSStringRef momentumStr) +{ + WKRetainPtr<WKStringRef> EventSenderMessageName(AdoptWK, WKStringCreateWithUTF8CString("EventSender")); + WKRetainPtr<WKMutableDictionaryRef> EventSenderMessageBody(AdoptWK, WKMutableDictionaryCreate()); + + WKRetainPtr<WKStringRef> subMessageKey(AdoptWK, WKStringCreateWithUTF8CString("SubMessage")); + WKRetainPtr<WKStringRef> subMessageName(AdoptWK, WKStringCreateWithUTF8CString("MouseScrollByWithWheelAndMomentumPhases")); + WKDictionarySetItem(EventSenderMessageBody.get(), subMessageKey.get(), subMessageName.get()); + + WKRetainPtr<WKStringRef> xKey(AdoptWK, WKStringCreateWithUTF8CString("X")); + WKRetainPtr<WKDoubleRef> xRef(AdoptWK, WKDoubleCreate(x)); + WKDictionarySetItem(EventSenderMessageBody.get(), xKey.get(), xRef.get()); + + WKRetainPtr<WKStringRef> yKey(AdoptWK, WKStringCreateWithUTF8CString("Y")); + WKRetainPtr<WKDoubleRef> yRef(AdoptWK, WKDoubleCreate(y)); + WKDictionarySetItem(EventSenderMessageBody.get(), yKey.get(), yRef.get()); + + uint64_t phase = cgEventPhaseFromString(phaseStr); + uint64_t momentum = cgEventMomentumPhaseFromString(momentumStr); + + WKRetainPtr<WKStringRef> phaseKey(AdoptWK, WKStringCreateWithUTF8CString("Phase")); + WKRetainPtr<WKUInt64Ref> phaseRef(AdoptWK, WKUInt64Create(phase)); + WKDictionarySetItem(EventSenderMessageBody.get(), phaseKey.get(), phaseRef.get()); + + WKRetainPtr<WKStringRef> momentumKey(AdoptWK, WKStringCreateWithUTF8CString("Momentum")); + WKRetainPtr<WKUInt64Ref> momentumRef(AdoptWK, WKUInt64Create(momentum)); + WKDictionarySetItem(EventSenderMessageBody.get(), momentumKey.get(), momentumRef.get()); + + WKBundlePageForceRepaint(InjectedBundle::singleton().page()->page()); // Triggers a scrolling tree commit. + WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), EventSenderMessageBody.get()); +} + +void EventSendingController::swipeGestureWithWheelAndMomentumPhases(int x, int y, JSStringRef phaseStr, JSStringRef momentumStr) +{ + WKRetainPtr<WKStringRef> EventSenderMessageName(AdoptWK, WKStringCreateWithUTF8CString("EventSender")); + WKRetainPtr<WKMutableDictionaryRef> EventSenderMessageBody(AdoptWK, WKMutableDictionaryCreate()); + + WKRetainPtr<WKStringRef> subMessageKey(AdoptWK, WKStringCreateWithUTF8CString("SubMessage")); + WKRetainPtr<WKStringRef> subMessageName(AdoptWK, WKStringCreateWithUTF8CString("SwipeGestureWithWheelAndMomentumPhases")); + WKDictionarySetItem(EventSenderMessageBody.get(), subMessageKey.get(), subMessageName.get()); + + WKRetainPtr<WKStringRef> xKey(AdoptWK, WKStringCreateWithUTF8CString("X")); + WKRetainPtr<WKDoubleRef> xRef(AdoptWK, WKDoubleCreate(x)); + WKDictionarySetItem(EventSenderMessageBody.get(), xKey.get(), xRef.get()); + + WKRetainPtr<WKStringRef> yKey(AdoptWK, WKStringCreateWithUTF8CString("Y")); + WKRetainPtr<WKDoubleRef> yRef(AdoptWK, WKDoubleCreate(y)); + WKDictionarySetItem(EventSenderMessageBody.get(), yKey.get(), yRef.get()); + + uint64_t phase = cgEventPhaseFromString(phaseStr); + uint64_t momentum = cgEventMomentumPhaseFromString(momentumStr); + + WKRetainPtr<WKStringRef> phaseKey(AdoptWK, WKStringCreateWithUTF8CString("Phase")); + WKRetainPtr<WKUInt64Ref> phaseRef(AdoptWK, WKUInt64Create(phase)); + WKDictionarySetItem(EventSenderMessageBody.get(), phaseKey.get(), phaseRef.get()); + + WKRetainPtr<WKStringRef> momentumKey(AdoptWK, WKStringCreateWithUTF8CString("Momentum")); + WKRetainPtr<WKUInt64Ref> momentumRef(AdoptWK, WKUInt64Create(momentum)); + WKDictionarySetItem(EventSenderMessageBody.get(), momentumKey.get(), momentumRef.get()); + + WKBundlePageForceRepaint(InjectedBundle::singleton().page()->page()); // Triggers a scrolling tree commit. + WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), EventSenderMessageBody.get()); } void EventSendingController::continuousMouseScrollBy(int x, int y, bool paged) @@ -368,31 +536,33 @@ void EventSendingController::continuousMouseScrollBy(int x, int y, bool paged) WKRetainPtr<WKUInt64Ref> pagedRef(AdoptWK, WKUInt64Create(paged)); WKDictionarySetItem(EventSenderMessageBody.get(), pagedKey.get(), pagedRef.get()); - WKBundlePostSynchronousMessage(InjectedBundle::shared().bundle(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); + // FIXME: This message should be asynchronous, as scrolling is intrinsically asynchronous. + // See also: <https://bugs.webkit.org/show_bug.cgi?id=148256>. + WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); } JSValueRef EventSendingController::contextClick() { - WKBundlePageRef page = InjectedBundle::shared().page()->page(); + WKBundlePageRef page = InjectedBundle::singleton().page()->page(); WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(page); JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame); #if ENABLE(CONTEXT_MENUS) - // Do mouse context click. - mouseDown(2, 0); - mouseUp(2, 0); + WKRetainPtr<WKArrayRef> menuEntries = adoptWK(WKBundlePageCopyContextMenuAtPointInWindow(page, m_position)); + JSValueRef arrayResult = JSObjectMakeArray(context, 0, 0, 0); + if (!menuEntries) + return arrayResult; - WKRetainPtr<WKArrayRef> menuEntries = adoptWK(WKBundlePageCopyContextMenuItems(page)); + JSObjectRef arrayObj = JSValueToObject(context, arrayResult, 0); size_t entriesSize = WKArrayGetSize(menuEntries.get()); - auto jsValuesArray = std::make_unique<JSValueRef[]>(entriesSize); for (size_t i = 0; i < entriesSize; ++i) { ASSERT(WKGetTypeID(WKArrayGetItemAtIndex(menuEntries.get(), i)) == WKContextMenuItemGetTypeID()); WKContextMenuItemRef item = static_cast<WKContextMenuItemRef>(WKArrayGetItemAtIndex(menuEntries.get(), i)); MenuItemPrivateData* privateData = new MenuItemPrivateData(page, item); - jsValuesArray[i] = JSObjectMake(context, getMenuItemClass(), privateData); + JSObjectSetPropertyAtIndex(context, arrayObj, i, JSObjectMake(context, getMenuItemClass(), privateData), 0); } - return JSObjectMakeArray(context, entriesSize, jsValuesArray.get(), 0); + return arrayResult; #else return JSValueMakeUndefined(context); #endif @@ -400,44 +570,96 @@ JSValueRef EventSendingController::contextClick() void EventSendingController::textZoomIn() { + auto& injectedBundle = InjectedBundle::singleton(); // Ensure page zoom is reset. - WKBundlePageSetPageZoomFactor(InjectedBundle::shared().page()->page(), 1); + WKBundlePageSetPageZoomFactor(injectedBundle.page()->page(), 1); - double zoomFactor = WKBundlePageGetTextZoomFactor(InjectedBundle::shared().page()->page()); - WKBundlePageSetTextZoomFactor(InjectedBundle::shared().page()->page(), zoomFactor * ZoomMultiplierRatio); + double zoomFactor = WKBundlePageGetTextZoomFactor(injectedBundle.page()->page()); + WKBundlePageSetTextZoomFactor(injectedBundle.page()->page(), zoomFactor * ZoomMultiplierRatio); } void EventSendingController::textZoomOut() { + auto& injectedBundle = InjectedBundle::singleton(); // Ensure page zoom is reset. - WKBundlePageSetPageZoomFactor(InjectedBundle::shared().page()->page(), 1); + WKBundlePageSetPageZoomFactor(injectedBundle.page()->page(), 1); - double zoomFactor = WKBundlePageGetTextZoomFactor(InjectedBundle::shared().page()->page()); - WKBundlePageSetTextZoomFactor(InjectedBundle::shared().page()->page(), zoomFactor / ZoomMultiplierRatio); + double zoomFactor = WKBundlePageGetTextZoomFactor(injectedBundle.page()->page()); + WKBundlePageSetTextZoomFactor(injectedBundle.page()->page(), zoomFactor / ZoomMultiplierRatio); } void EventSendingController::zoomPageIn() { + auto& injectedBundle = InjectedBundle::singleton(); // Ensure text zoom is reset. - WKBundlePageSetTextZoomFactor(InjectedBundle::shared().page()->page(), 1); + WKBundlePageSetTextZoomFactor(injectedBundle.page()->page(), 1); - double zoomFactor = WKBundlePageGetPageZoomFactor(InjectedBundle::shared().page()->page()); - WKBundlePageSetPageZoomFactor(InjectedBundle::shared().page()->page(), zoomFactor * ZoomMultiplierRatio); + double zoomFactor = WKBundlePageGetPageZoomFactor(injectedBundle.page()->page()); + WKBundlePageSetPageZoomFactor(injectedBundle.page()->page(), zoomFactor * ZoomMultiplierRatio); } void EventSendingController::zoomPageOut() { + auto& injectedBundle = InjectedBundle::singleton(); // Ensure text zoom is reset. - WKBundlePageSetTextZoomFactor(InjectedBundle::shared().page()->page(), 1); + WKBundlePageSetTextZoomFactor(injectedBundle.page()->page(), 1); - double zoomFactor = WKBundlePageGetPageZoomFactor(InjectedBundle::shared().page()->page()); - WKBundlePageSetPageZoomFactor(InjectedBundle::shared().page()->page(), zoomFactor / ZoomMultiplierRatio); + double zoomFactor = WKBundlePageGetPageZoomFactor(injectedBundle.page()->page()); + WKBundlePageSetPageZoomFactor(injectedBundle.page()->page(), zoomFactor / ZoomMultiplierRatio); } void EventSendingController::scalePageBy(double scale, double x, double y) { WKPoint origin = { x, y }; - WKBundlePageSetScaleAtOrigin(InjectedBundle::shared().page()->page(), scale, origin); + WKBundlePageSetScaleAtOrigin(InjectedBundle::singleton().page()->page(), scale, origin); +} + +void EventSendingController::monitorWheelEvents() +{ + WKBundlePageRef page = InjectedBundle::singleton().page()->page(); + + WKBundlePageStartMonitoringScrollOperations(page); +} + +struct ScrollCompletionCallbackData { + JSContextRef m_context; + JSObjectRef m_function; + + ScrollCompletionCallbackData(JSContextRef context, JSObjectRef function) + : m_context(context), m_function(function) + { + } +}; + +static void executeCallback(void* context) +{ + if (!context) + return; + + std::unique_ptr<ScrollCompletionCallbackData> callBackData(reinterpret_cast<ScrollCompletionCallbackData*>(context)); + + JSObjectCallAsFunction(callBackData->m_context, callBackData->m_function, nullptr, 0, nullptr, nullptr); + JSValueUnprotect(callBackData->m_context, callBackData->m_function); +} + +void EventSendingController::callAfterScrollingCompletes(JSValueRef functionCallback) +{ + if (!functionCallback) + return; + + WKBundlePageRef page = InjectedBundle::singleton().page()->page(); + WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(page); + JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame); + + JSObjectRef functionCallbackObject = JSValueToObject(context, functionCallback, nullptr); + if (!functionCallbackObject) + return; + + JSValueProtect(context, functionCallbackObject); + + auto scrollCompletionCallbackData = std::make_unique<ScrollCompletionCallbackData>(context, functionCallbackObject); + + WKBundlePageRegisterScrollOperationCompletionCallback(page, executeCallback, scrollCompletionCallbackData.release()); } #if ENABLE(TOUCH_EVENTS) @@ -458,7 +680,7 @@ void EventSendingController::addTouchPoint(int x, int y) WKRetainPtr<WKUInt64Ref> yRef(AdoptWK, WKUInt64Create(y)); WKDictionarySetItem(EventSenderMessageBody.get(), yKey.get(), yRef.get()); - WKBundlePostSynchronousMessage(InjectedBundle::shared().bundle(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); + WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); } void EventSendingController::updateTouchPoint(int index, int x, int y) @@ -482,7 +704,7 @@ void EventSendingController::updateTouchPoint(int index, int x, int y) WKRetainPtr<WKUInt64Ref> yRef(AdoptWK, WKUInt64Create(y)); WKDictionarySetItem(EventSenderMessageBody.get(), yKey.get(), yRef.get()); - WKBundlePostSynchronousMessage(InjectedBundle::shared().bundle(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); + WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); } void EventSendingController::setTouchModifier(const JSStringRef &modifier, bool enable) @@ -512,7 +734,7 @@ void EventSendingController::setTouchModifier(const JSStringRef &modifier, bool WKRetainPtr<WKUInt64Ref> enableRef(AdoptWK, WKUInt64Create(enable)); WKDictionarySetItem(EventSenderMessageBody.get(), enableKey.get(), enableRef.get()); - WKBundlePostSynchronousMessage(InjectedBundle::shared().bundle(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); + WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); } @@ -533,7 +755,7 @@ void EventSendingController::setTouchPointRadius(int radiusX, int radiusY) WKRetainPtr<WKUInt64Ref> yRef(AdoptWK, WKUInt64Create(radiusY)); WKDictionarySetItem(EventSenderMessageBody.get(), yKey.get(), yRef.get()); - WKBundlePostSynchronousMessage(InjectedBundle::shared().bundle(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); + WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); } void EventSendingController::touchStart() @@ -545,7 +767,7 @@ void EventSendingController::touchStart() WKRetainPtr<WKStringRef> subMessageName(AdoptWK, WKStringCreateWithUTF8CString("TouchStart")); WKDictionarySetItem(EventSenderMessageBody.get(), subMessageKey.get(), subMessageName.get()); - WKBundlePostSynchronousMessage(InjectedBundle::shared().bundle(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); + WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); } void EventSendingController::touchMove() @@ -557,7 +779,7 @@ void EventSendingController::touchMove() WKRetainPtr<WKStringRef> subMessageName(AdoptWK, WKStringCreateWithUTF8CString("TouchMove")); WKDictionarySetItem(EventSenderMessageBody.get(), subMessageKey.get(), subMessageName.get()); - WKBundlePostSynchronousMessage(InjectedBundle::shared().bundle(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); + WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); } void EventSendingController::touchEnd() @@ -569,7 +791,7 @@ void EventSendingController::touchEnd() WKRetainPtr<WKStringRef> subMessageName(AdoptWK, WKStringCreateWithUTF8CString("TouchEnd")); WKDictionarySetItem(EventSenderMessageBody.get(), subMessageKey.get(), subMessageName.get()); - WKBundlePostSynchronousMessage(InjectedBundle::shared().bundle(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); + WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); } void EventSendingController::touchCancel() @@ -581,7 +803,7 @@ void EventSendingController::touchCancel() WKRetainPtr<WKStringRef> subMessageName(AdoptWK, WKStringCreateWithUTF8CString("TouchCancel")); WKDictionarySetItem(EventSenderMessageBody.get(), subMessageKey.get(), subMessageName.get()); - WKBundlePostSynchronousMessage(InjectedBundle::shared().bundle(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); + WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); } void EventSendingController::clearTouchPoints() @@ -593,7 +815,7 @@ void EventSendingController::clearTouchPoints() WKRetainPtr<WKStringRef> subMessageName(AdoptWK, WKStringCreateWithUTF8CString("ClearTouchPoints")); WKDictionarySetItem(EventSenderMessageBody.get(), subMessageKey.get(), subMessageName.get()); - WKBundlePostSynchronousMessage(InjectedBundle::shared().bundle(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); + WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); } void EventSendingController::releaseTouchPoint(int index) @@ -609,7 +831,7 @@ void EventSendingController::releaseTouchPoint(int index) WKRetainPtr<WKUInt64Ref> indexRef(AdoptWK, WKUInt64Create(index)); WKDictionarySetItem(EventSenderMessageBody.get(), indexKey.get(), indexRef.get()); - WKBundlePostSynchronousMessage(InjectedBundle::shared().bundle(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); + WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); } void EventSendingController::cancelTouchPoint(int index) @@ -625,7 +847,7 @@ void EventSendingController::cancelTouchPoint(int index) WKRetainPtr<WKUInt64Ref> indexRef(AdoptWK, WKUInt64Create(index)); WKDictionarySetItem(EventSenderMessageBody.get(), indexKey.get(), indexRef.get()); - WKBundlePostSynchronousMessage(InjectedBundle::shared().bundle(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); + WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), EventSenderMessageBody.get(), 0); } #endif diff --git a/Tools/WebKitTestRunner/InjectedBundle/EventSendingController.h b/Tools/WebKitTestRunner/InjectedBundle/EventSendingController.h index c6a9131e4..3eb8129c7 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/EventSendingController.h +++ b/Tools/WebKitTestRunner/InjectedBundle/EventSendingController.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2011 Apple Inc. All rights reserved. + * Copyright (C) 2010, 2011, 2014-2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,19 +23,18 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef EventSendingController_h -#define EventSendingController_h +#pragma once #include "JSWrappable.h" -#include <WebKit2/WKEvent.h> -#include <WebKit2/WKGeometry.h> -#include <wtf/PassRefPtr.h> +#include <WebKit/WKEvent.h> +#include <WebKit/WKGeometry.h> +#include <wtf/Ref.h> namespace WTR { class EventSendingController : public JSWrappable { public: - static PassRefPtr<EventSendingController> create(); + static Ref<EventSendingController> create(); virtual ~EventSendingController(); void makeWindowObject(JSContextRef, JSObjectRef windowObject, JSValueRef* exception); @@ -46,11 +45,20 @@ public: void mouseDown(int button, JSValueRef modifierArray); void mouseUp(int button, JSValueRef modifierArray); void mouseMoveTo(int x, int y); + void mouseForceClick(); + void startAndCancelMouseForceClick(); + void mouseForceDown(); + void mouseForceUp(); + void mouseForceChanged(double force); void mouseScrollBy(int x, int y); + void mouseScrollByWithWheelAndMomentumPhases(int x, int y, JSStringRef phase, JSStringRef momentum); + void swipeGestureWithWheelAndMomentumPhases(int x, int y, JSStringRef phase, JSStringRef momentum); void continuousMouseScrollBy(int x, int y, bool paged); JSValueRef contextClick(); void leapForward(int milliseconds); void scheduleAsynchronousClick(); + void monitorWheelEvents(); + void callAfterScrollingCompletes(JSValueRef functionCallback); void keyDown(JSStringRef key, JSValueRef modifierArray, int location); void scheduleAsynchronousKeyDown(JSStringRef key); @@ -79,8 +87,7 @@ public: private: EventSendingController(); + WKPoint m_position; }; } // namespace WTR - -#endif // EventSendingController_h diff --git a/Tools/WebKitTestRunner/InjectedBundle/GCController.cpp b/Tools/WebKitTestRunner/InjectedBundle/GCController.cpp index 10c21dba8..9358f4a0d 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/GCController.cpp +++ b/Tools/WebKitTestRunner/InjectedBundle/GCController.cpp @@ -28,13 +28,13 @@ #include "InjectedBundle.h" #include "JSGCController.h" -#include <WebKit2/WKBundlePrivate.h> +#include <WebKit/WKBundlePrivate.h> namespace WTR { -PassRefPtr<GCController> GCController::create() +Ref<GCController> GCController::create() { - return adoptRef(new GCController); + return adoptRef(*new GCController); } GCController::GCController() @@ -52,17 +52,17 @@ JSClassRef GCController::wrapperClass() void GCController::collect() { - WKBundleGarbageCollectJavaScriptObjects(InjectedBundle::shared().bundle()); + WKBundleGarbageCollectJavaScriptObjects(InjectedBundle::singleton().bundle()); } void GCController::collectOnAlternateThread(bool waitUntilDone) { - WKBundleGarbageCollectJavaScriptObjectsOnAlternateThreadForDebugging(InjectedBundle::shared().bundle(), waitUntilDone); + WKBundleGarbageCollectJavaScriptObjectsOnAlternateThreadForDebugging(InjectedBundle::singleton().bundle(), waitUntilDone); } size_t GCController::getJSObjectCount() { - return WKBundleGetJavaScriptObjectsCount(InjectedBundle::shared().bundle()); + return WKBundleGetJavaScriptObjectsCount(InjectedBundle::singleton().bundle()); } // Object Creation diff --git a/Tools/WebKitTestRunner/InjectedBundle/GCController.h b/Tools/WebKitTestRunner/InjectedBundle/GCController.h index 760fbb1e6..d349c1ce9 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/GCController.h +++ b/Tools/WebKitTestRunner/InjectedBundle/GCController.h @@ -23,17 +23,16 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef GCController_h -#define GCController_h +#pragma once #include "JSWrappable.h" -#include <wtf/PassRefPtr.h> +#include <wtf/Ref.h> namespace WTR { class GCController : public JSWrappable { public: - static PassRefPtr<GCController> create(); + static Ref<GCController> create(); virtual ~GCController(); void makeWindowObject(JSContextRef, JSObjectRef windowObject, JSValueRef* exception); @@ -50,5 +49,3 @@ private: }; } // namespace WTR - -#endif // GCController_h diff --git a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp index f71fe9360..f247b362b 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp +++ b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2011, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2010-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,20 +29,20 @@ #include "ActivateFonts.h" #include "InjectedBundlePage.h" #include "StringFunctions.h" -#include <WebKit2/WKBundle.h> -#include <WebKit2/WKBundlePage.h> -#include <WebKit2/WKBundlePagePrivate.h> -#include <WebKit2/WKBundlePrivate.h> -#include <WebKit2/WKRetainPtr.h> -#include <WebKit2/WebKit2_C.h> -#include <wtf/PassOwnPtr.h> +#include "WebCoreTestSupport.h" +#include <WebKit/WKBundle.h> +#include <WebKit/WKBundlePage.h> +#include <WebKit/WKBundlePagePrivate.h> +#include <WebKit/WKBundlePrivate.h> +#include <WebKit/WKRetainPtr.h> +#include <WebKit/WebKit2_C.h> #include <wtf/text/CString.h> #include <wtf/text/StringBuilder.h> #include <wtf/Vector.h> namespace WTR { -InjectedBundle& InjectedBundle::shared() +InjectedBundle& InjectedBundle::singleton() { static InjectedBundle& shared = *new InjectedBundle; return shared; @@ -101,23 +101,18 @@ void InjectedBundle::initialize(WKBundleRef bundle, WKTypeRef initializationUser platformInitialize(initializationUserData); activateFonts(); - WKBundleActivateMacFontAscentHack(m_bundle); } void InjectedBundle::didCreatePage(WKBundlePageRef page) { - m_pages.append(adoptPtr(new InjectedBundlePage(page))); + m_pages.append(std::make_unique<InjectedBundlePage>(page)); } void InjectedBundle::willDestroyPage(WKBundlePageRef page) { - size_t size = m_pages.size(); - for (size_t i = 0; i < size; ++i) { - if (m_pages[i]->page() == page) { - m_pages.remove(i); - break; - } - } + m_pages.removeFirstMatching([page](auto& current) { + return current->page() == page; + }); } void InjectedBundle::didInitializePageGroup(WKBundlePageGroupRef pageGroup) @@ -139,6 +134,13 @@ void InjectedBundle::resetLocalSettings() void InjectedBundle::didReceiveMessage(WKStringRef messageName, WKTypeRef messageBody) { + WKRetainPtr<WKStringRef> errorMessageName(AdoptWK, WKStringCreateWithUTF8CString("Error")); + WKRetainPtr<WKStringRef> errorMessageBody(AdoptWK, WKStringCreateWithUTF8CString("Unknown")); + WKBundlePostMessage(m_bundle, errorMessageName.get(), errorMessageBody.get()); +} + +void InjectedBundle::didReceiveMessageToPage(WKBundlePageRef page, WKStringRef messageName, WKTypeRef messageBody) +{ if (WKStringIsEqualToUTF8CString(messageName, "BeginTest")) { ASSERT(messageBody); ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID()); @@ -153,13 +155,18 @@ void InjectedBundle::didReceiveMessage(WKStringRef messageName, WKTypeRef messag WKRetainPtr<WKStringRef> timeoutKey(AdoptWK, WKStringCreateWithUTF8CString("Timeout")); m_timeout = (int)WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, timeoutKey.get()))); + WKRetainPtr<WKStringRef> dumpJSConsoleLogInStdErrKey(AdoptWK, WKStringCreateWithUTF8CString("DumpJSConsoleLogInStdErr")); + m_dumpJSConsoleLogInStdErr = WKBooleanGetValue(static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, dumpJSConsoleLogInStdErrKey.get()))); + WKRetainPtr<WKStringRef> ackMessageName(AdoptWK, WKStringCreateWithUTF8CString("Ack")); WKRetainPtr<WKStringRef> ackMessageBody(AdoptWK, WKStringCreateWithUTF8CString("BeginTest")); - WKBundlePostMessage(m_bundle, ackMessageName.get(), ackMessageBody.get()); + WKBundlePagePostMessage(page, ackMessageName.get(), ackMessageBody.get()); beginTesting(messageBodyDictionary); return; - } else if (WKStringIsEqualToUTF8CString(messageName, "Reset")) { + } + + if (WKStringIsEqualToUTF8CString(messageName, "Reset")) { ASSERT(messageBody); ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID()); WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody); @@ -170,48 +177,103 @@ void InjectedBundle::didReceiveMessage(WKStringRef messageName, WKTypeRef messag if (shouldGC) WKBundleGarbageCollectJavaScriptObjects(m_bundle); + WKRetainPtr<WKStringRef> allowedHostsKey(AdoptWK, WKStringCreateWithUTF8CString("AllowedHosts")); + WKTypeRef allowedHostsValue = WKDictionaryGetItemForKey(messageBodyDictionary, allowedHostsKey.get()); + if (allowedHostsValue && WKGetTypeID(allowedHostsValue) == WKArrayGetTypeID()) { + WKArrayRef allowedHostsArray = static_cast<WKArrayRef>(allowedHostsValue); + for (size_t i = 0, size = WKArrayGetSize(allowedHostsArray); i < size; ++i) { + WKTypeRef item = WKArrayGetItemAtIndex(allowedHostsArray, i); + if (item && WKGetTypeID(item) == WKStringGetTypeID()) + m_allowedHosts.append(toWTFString(static_cast<WKStringRef>(item))); + } + } + m_state = Idle; m_dumpPixels = false; + m_pixelResultIsPending = false; resetLocalSettings(); - m_testRunner->removeAllWebNotificationPermissions(); + TestRunner::removeAllWebNotificationPermissions(); - page()->resetAfterTest(); + InjectedBundle::page()->resetAfterTest(); return; } + if (WKStringIsEqualToUTF8CString(messageName, "CallAddChromeInputFieldCallback")) { m_testRunner->callAddChromeInputFieldCallback(); return; } + if (WKStringIsEqualToUTF8CString(messageName, "CallRemoveChromeInputFieldCallback")) { m_testRunner->callRemoveChromeInputFieldCallback(); return; } + if (WKStringIsEqualToUTF8CString(messageName, "CallFocusWebViewCallback")) { m_testRunner->callFocusWebViewCallback(); return; } + if (WKStringIsEqualToUTF8CString(messageName, "CallSetBackingScaleFactorCallback")) { m_testRunner->callSetBackingScaleFactorCallback(); return; - } + } + + if (WKStringIsEqualToUTF8CString(messageName, "CallDidBeginSwipeCallback")) { + m_testRunner->callDidBeginSwipeCallback(); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "CallWillEndSwipeCallback")) { + m_testRunner->callWillEndSwipeCallback(); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "CallDidEndSwipeCallback")) { + m_testRunner->callDidEndSwipeCallback(); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "CallDidRemoveSwipeSnapshotCallback")) { + m_testRunner->callDidRemoveSwipeSnapshotCallback(); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "NotifyDownloadDone")) { + m_testRunner->notifyDone(); + return; + } + + if (WKStringIsEqualToUTF8CString(messageName, "CallUISideScriptCallback")) { + WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody); + + WKRetainPtr<WKStringRef> resultKey(AdoptWK, WKStringCreateWithUTF8CString("Result")); + WKRetainPtr<WKStringRef> callbackIDKey(AdoptWK, WKStringCreateWithUTF8CString("CallbackID")); + + unsigned callbackID = (unsigned)WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, callbackIDKey.get()))); + + WKStringRef resultString = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, resultKey.get())); + auto resultJSString = toJS(resultString); + + m_testRunner->runUIScriptCallback(callbackID, resultJSString.get()); + return; + } + if (WKStringIsEqualToUTF8CString(messageName, "WorkQueueProcessedCallback")) { if (!topLoadingFrame() && !m_testRunner->waitToDump()) - page()->dump(); + InjectedBundle::page()->dump(); return; } - WKRetainPtr<WKStringRef> errorMessageName(AdoptWK, WKStringCreateWithUTF8CString("Error")); - WKRetainPtr<WKStringRef> errorMessageBody(AdoptWK, WKStringCreateWithUTF8CString("Unknown")); - WKBundlePostMessage(m_bundle, errorMessageName.get(), errorMessageBody.get()); -} + if (WKStringIsEqualToUTF8CString(messageName, "WebsiteDataDeletionForTopPrivatelyOwnedDomainsFinished")) { + m_testRunner->statisticsDidModifyDataRecordsCallback(); + return; + } -void InjectedBundle::didReceiveMessageToPage(WKBundlePageRef page, WKStringRef messageName, WKTypeRef messageBody) -{ WKRetainPtr<WKStringRef> errorMessageName(AdoptWK, WKStringCreateWithUTF8CString("Error")); WKRetainPtr<WKStringRef> errorMessageBody(AdoptWK, WKStringCreateWithUTF8CString("Unknown")); - WKBundlePostMessage(m_bundle, errorMessageName.get(), errorMessageBody.get()); + WKBundlePagePostMessage(page, errorMessageName.get(), errorMessageBody.get()); } bool InjectedBundle::booleanForKey(WKDictionaryRef dictionary, const char* key) @@ -236,41 +298,60 @@ void InjectedBundle::beginTesting(WKDictionaryRef settings) m_gcController = GCController::create(); m_eventSendingController = EventSendingController::create(); m_textInputController = TextInputController::create(); +#if HAVE(ACCESSIBILITY) m_accessibilityController = AccessibilityController::create(); +#endif - WKBundleSetShouldTrackVisitedLinks(m_bundle, false); - WKBundleRemoveAllVisitedLinks(m_bundle); WKBundleSetAllowUniversalAccessFromFileURLs(m_bundle, m_pageGroup, true); WKBundleSetJavaScriptCanAccessClipboard(m_bundle, m_pageGroup, true); WKBundleSetPrivateBrowsingEnabled(m_bundle, m_pageGroup, false); + WKBundleSetUseDashboardCompatibilityMode(m_bundle, m_pageGroup, false); WKBundleSetAuthorAndUserStylesEnabled(m_bundle, m_pageGroup, true); WKBundleSetFrameFlatteningEnabled(m_bundle, m_pageGroup, false); WKBundleSetMinimumLogicalFontSize(m_bundle, m_pageGroup, 9); WKBundleSetSpatialNavigationEnabled(m_bundle, m_pageGroup, false); WKBundleSetAllowFileAccessFromFileURLs(m_bundle, m_pageGroup, true); - WKBundleSetPluginsEnabled(m_bundle, m_pageGroup, true); WKBundleSetPopupBlockingEnabled(m_bundle, m_pageGroup, false); - WKBundleSetAlwaysAcceptCookies(m_bundle, false); - WKBundleSetSerialLoadingEnabled(m_bundle, false); - WKBundleSetShadowDOMEnabled(m_bundle, true); - WKBundleSetSeamlessIFramesEnabled(m_bundle, true); - WKBundleSetCacheModel(m_bundle, 1 /*CacheModelDocumentBrowser*/); + WKBundleSetAllowStorageAccessFromFileURLS(m_bundle, m_pageGroup, false); - WKBundleRemoveAllUserContent(m_bundle, m_pageGroup); +#if PLATFORM(IOS) + WKBundlePageSetUseTestingViewportConfiguration(page()->page(), !booleanForKey(settings, "UseFlexibleViewport")); +#endif + + m_testRunner->setPluginsEnabled(true); m_testRunner->setShouldDumpFrameLoadCallbacks(booleanForKey(settings, "DumpFrameLoadDelegates")); m_testRunner->setUserStyleSheetEnabled(false); m_testRunner->setXSSAuditorEnabled(false); + + m_testRunner->setShadowDOMEnabled(true); + m_testRunner->setCustomElementsEnabled(true); + + m_testRunner->setWebGL2Enabled(true); + + m_testRunner->setFetchAPIEnabled(true); + + m_testRunner->setDownloadAttributeEnabled(true); + + m_testRunner->setEncryptedMediaAPIEnabled(true); + m_testRunner->setCloseRemainingWindowsWhenComplete(false); m_testRunner->setAcceptsEditing(true); m_testRunner->setTabKeyCyclesThroughElements(true); + m_testRunner->clearTestRunnerCallbacks(); + + m_testRunner->setSubtleCryptoEnabled(true); - m_testRunner->setCustomTimeout(m_timeout); + m_testRunner->setMediaStreamEnabled(true); + m_testRunner->setPeerConnectionEnabled(true); + + if (m_timeout > 0) + m_testRunner->setCustomTimeout(m_timeout); page()->prepare(); WKBundleClearAllDatabases(m_bundle); - WKBundleClearApplicationCache(m_bundle); + WKBundlePageClearApplicationCache(page()->page()); WKBundleResetOriginAccessWhitelists(m_bundle); // [WK2] REGRESSION(r128623): It made layout tests extremely slow @@ -287,13 +368,21 @@ void InjectedBundle::done() page()->stopLoading(); setTopLoadingFrame(0); + m_testRunner->invalidateWaitToDumpWatchdogTimer(); + m_accessibilityController->resetToConsistentState(); WKRetainPtr<WKStringRef> doneMessageName(AdoptWK, WKStringCreateWithUTF8CString("Done")); WKRetainPtr<WKMutableDictionaryRef> doneMessageBody(AdoptWK, WKMutableDictionaryCreate()); - WKRetainPtr<WKStringRef> pixelResultKey = adoptWK(WKStringCreateWithUTF8CString("PixelResult")); - WKDictionarySetItem(doneMessageBody.get(), pixelResultKey.get(), m_pixelResult.get()); + WKRetainPtr<WKStringRef> pixelResultIsPendingKey = adoptWK(WKStringCreateWithUTF8CString("PixelResultIsPending")); + WKRetainPtr<WKBooleanRef> pixelResultIsPending(AdoptWK, WKBooleanCreate(m_pixelResultIsPending)); + WKDictionarySetItem(doneMessageBody.get(), pixelResultIsPendingKey.get(), pixelResultIsPending.get()); + + if (!m_pixelResultIsPending) { + WKRetainPtr<WKStringRef> pixelResultKey = adoptWK(WKStringCreateWithUTF8CString("PixelResult")); + WKDictionarySetItem(doneMessageBody.get(), pixelResultKey.get(), m_pixelResult.get()); + } WKRetainPtr<WKStringRef> repaintRectsKey = adoptWK(WKStringCreateWithUTF8CString("RepaintRects")); WKDictionarySetItem(doneMessageBody.get(), repaintRectsKey.get(), m_repaintRects.get()); @@ -301,7 +390,7 @@ void InjectedBundle::done() WKRetainPtr<WKStringRef> audioResultKey = adoptWK(WKStringCreateWithUTF8CString("AudioResult")); WKDictionarySetItem(doneMessageBody.get(), audioResultKey.get(), m_audioResult.get()); - WKBundlePostMessage(m_bundle, doneMessageName.get(), doneMessageBody.get()); + WKBundlePagePostMessage(page()->page(), doneMessageName.get(), doneMessageBody.get()); closeOtherPages(); @@ -326,6 +415,17 @@ void InjectedBundle::dumpBackForwardListsForAllPages(StringBuilder& stringBuilde m_pages[i]->dumpBackForwardList(stringBuilder); } +void InjectedBundle::dumpToStdErr(const String& output) +{ + if (m_state != Testing) + return; + if (output.isEmpty()) + return; + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("DumpToStdErr")); + WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithUTF8CString(output.utf8().data())); + WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get()); +} + void InjectedBundle::outputText(const String& output) { if (m_state != Testing) @@ -334,60 +434,85 @@ void InjectedBundle::outputText(const String& output) return; WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("TextOutput")); WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithUTF8CString(output.utf8().data())); - WKBundlePostMessage(m_bundle, messageName.get(), messageBody.get()); + WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get()); } void InjectedBundle::postNewBeforeUnloadReturnValue(bool value) { WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("BeforeUnloadReturnValue")); WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value)); - WKBundlePostMessage(m_bundle, messageName.get(), messageBody.get()); + WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get()); } void InjectedBundle::postAddChromeInputField() { WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("AddChromeInputField")); - WKBundlePostMessage(m_bundle, messageName.get(), 0); + WKBundlePagePostMessage(page()->page(), messageName.get(), 0); } void InjectedBundle::postRemoveChromeInputField() { WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("RemoveChromeInputField")); - WKBundlePostMessage(m_bundle, messageName.get(), 0); + WKBundlePagePostMessage(page()->page(), messageName.get(), 0); } void InjectedBundle::postFocusWebView() { WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("FocusWebView")); - WKBundlePostMessage(m_bundle, messageName.get(), 0); + WKBundlePagePostMessage(page()->page(), messageName.get(), 0); } void InjectedBundle::postSetBackingScaleFactor(double backingScaleFactor) { WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetBackingScaleFactor")); WKRetainPtr<WKDoubleRef> messageBody(AdoptWK, WKDoubleCreate(backingScaleFactor)); - WKBundlePostMessage(m_bundle, messageName.get(), messageBody.get()); + WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get()); } void InjectedBundle::postSetWindowIsKey(bool isKey) { WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetWindowIsKey")); WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(isKey)); - WKBundlePostSynchronousMessage(m_bundle, messageName.get(), messageBody.get(), 0); + WKBundlePagePostSynchronousMessageForTesting(page()->page(), messageName.get(), messageBody.get(), 0); +} + +void InjectedBundle::postSetViewSize(double width, double height) +{ + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetViewSize")); + + WKRetainPtr<WKStringRef> widthKey(AdoptWK, WKStringCreateWithUTF8CString("width")); + WKRetainPtr<WKStringRef> heightKey(AdoptWK, WKStringCreateWithUTF8CString("height")); + + WKRetainPtr<WKMutableDictionaryRef> messageBody(AdoptWK, WKMutableDictionaryCreate()); + + WKRetainPtr<WKDoubleRef> widthWK(AdoptWK, WKDoubleCreate(width)); + WKDictionarySetItem(messageBody.get(), widthKey.get(), widthWK.get()); + + WKRetainPtr<WKDoubleRef> heightWK(AdoptWK, WKDoubleCreate(height)); + WKDictionarySetItem(messageBody.get(), heightKey.get(), heightWK.get()); + + WKBundlePagePostSynchronousMessageForTesting(page()->page(), messageName.get(), messageBody.get(), 0); } void InjectedBundle::postSimulateWebNotificationClick(uint64_t notificationID) { WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SimulateWebNotificationClick")); WKRetainPtr<WKUInt64Ref> messageBody(AdoptWK, WKUInt64Create(notificationID)); - WKBundlePostMessage(m_bundle, messageName.get(), messageBody.get()); + WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get()); +} + +void InjectedBundle::postSetAddsVisitedLinks(bool addsVisitedLinks) +{ + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetAddsVisitedLinks")); + WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(addsVisitedLinks)); + WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get()); } void InjectedBundle::setGeolocationPermission(bool enabled) { WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetGeolocationPermission")); WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(enabled)); - WKBundlePostMessage(m_bundle, messageName.get(), messageBody.get()); + WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get()); } void InjectedBundle::setMockGeolocationPosition(double latitude, double longitude, double accuracy, bool providesAltitude, double altitude, bool providesAltitudeAccuracy, double altitudeAccuracy, bool providesHeading, double heading, bool providesSpeed, double speed) @@ -440,13 +565,90 @@ void InjectedBundle::setMockGeolocationPosition(double latitude, double longitud WKRetainPtr<WKDoubleRef> speedWK(AdoptWK, WKDoubleCreate(speed)); WKDictionarySetItem(messageBody.get(), speedKeyWK.get(), speedWK.get()); - WKBundlePostMessage(m_bundle, messageName.get(), messageBody.get()); + WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get()); } void InjectedBundle::setMockGeolocationPositionUnavailableError(WKStringRef errorMessage) { WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetMockGeolocationPositionUnavailableError")); - WKBundlePostMessage(m_bundle, messageName.get(), errorMessage); + WKBundlePagePostMessage(page()->page(), messageName.get(), errorMessage); +} + +bool InjectedBundle::isGeolocationProviderActive() const +{ + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("IsGeolocationClientActive")); + WKTypeRef resultToPass = 0; + WKBundlePagePostSynchronousMessageForTesting(page()->page(), messageName.get(), 0, &resultToPass); + WKRetainPtr<WKBooleanRef> isActive(AdoptWK, static_cast<WKBooleanRef>(resultToPass)); + + return WKBooleanGetValue(isActive.get()); +} + +unsigned InjectedBundle::imageCountInGeneralPasteboard() const +{ + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("ImageCountInGeneralPasteboard")); + WKTypeRef resultToPass = 0; + WKBundlePagePostSynchronousMessageForTesting(page()->page(), messageName.get(), 0, &resultToPass); + WKRetainPtr<WKUInt64Ref> imageCount(AdoptWK, static_cast<WKUInt64Ref>(resultToPass)); + + return static_cast<unsigned>(WKUInt64GetValue(imageCount.get())); +} + +void InjectedBundle::setUserMediaPermission(bool enabled) +{ + auto messageName = adoptWK(WKStringCreateWithUTF8CString("SetUserMediaPermission")); + auto messageBody = adoptWK(WKBooleanCreate(enabled)); + WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get()); +} + +void InjectedBundle::setUserMediaPersistentPermissionForOrigin(bool permission, WKStringRef origin, WKStringRef parentOrigin) +{ + auto messageName = adoptWK(WKStringCreateWithUTF8CString("SetUserMediaPersistentPermissionForOrigin")); + WKRetainPtr<WKMutableDictionaryRef> messageBody(AdoptWK, WKMutableDictionaryCreate()); + + WKRetainPtr<WKStringRef> permissionKeyWK(AdoptWK, WKStringCreateWithUTF8CString("permission")); + WKRetainPtr<WKBooleanRef> permissionWK(AdoptWK, WKBooleanCreate(permission)); + WKDictionarySetItem(messageBody.get(), permissionKeyWK.get(), permissionWK.get()); + + WKRetainPtr<WKStringRef> originKeyWK(AdoptWK, WKStringCreateWithUTF8CString("origin")); + WKDictionarySetItem(messageBody.get(), originKeyWK.get(), origin); + + WKRetainPtr<WKStringRef> parentOriginKeyWK(AdoptWK, WKStringCreateWithUTF8CString("parentOrigin")); + WKDictionarySetItem(messageBody.get(), parentOriginKeyWK.get(), parentOrigin); + + WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get()); +} + +unsigned InjectedBundle::userMediaPermissionRequestCountForOrigin(WKStringRef origin, WKStringRef parentOrigin) const +{ + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("UserMediaPermissionRequestCountForOrigin")); + WKRetainPtr<WKMutableDictionaryRef> messageBody(AdoptWK, WKMutableDictionaryCreate()); + + WKRetainPtr<WKStringRef> originKeyWK(AdoptWK, WKStringCreateWithUTF8CString("origin")); + WKDictionarySetItem(messageBody.get(), originKeyWK.get(), origin); + + WKRetainPtr<WKStringRef> parentOriginKeyWK(AdoptWK, WKStringCreateWithUTF8CString("parentOrigin")); + WKDictionarySetItem(messageBody.get(), parentOriginKeyWK.get(), parentOrigin); + + WKTypeRef resultToPass = 0; + WKBundlePagePostSynchronousMessageForTesting(page()->page(), messageName.get(), messageBody.get(), &resultToPass); + WKRetainPtr<WKUInt64Ref> count(AdoptWK, static_cast<WKUInt64Ref>(resultToPass)); + + return static_cast<unsigned>(WKUInt64GetValue(count.get())); +} + +void InjectedBundle::resetUserMediaPermissionRequestCountForOrigin(WKStringRef origin, WKStringRef parentOrigin) +{ + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("ResetUserMediaPermissionRequestCountForOrigin")); + WKRetainPtr<WKMutableDictionaryRef> messageBody(AdoptWK, WKMutableDictionaryCreate()); + + WKRetainPtr<WKStringRef> originKeyWK(AdoptWK, WKStringCreateWithUTF8CString("origin")); + WKDictionarySetItem(messageBody.get(), originKeyWK.get(), origin); + + WKRetainPtr<WKStringRef> parentOriginKeyWK(AdoptWK, WKStringCreateWithUTF8CString("parentOrigin")); + WKDictionarySetItem(messageBody.get(), parentOriginKeyWK.get(), parentOrigin); + + WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get()); } void InjectedBundle::setCustomPolicyDelegate(bool enabled, bool permissive) @@ -463,23 +665,26 @@ void InjectedBundle::setCustomPolicyDelegate(bool enabled, bool permissive) WKRetainPtr<WKBooleanRef> permissiveWK(AdoptWK, WKBooleanCreate(permissive)); WKDictionarySetItem(messageBody.get(), permissiveKeyWK.get(), permissiveWK.get()); - WKBundlePostMessage(m_bundle, messageName.get(), messageBody.get()); + WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get()); } -void InjectedBundle::setVisibilityState(WKPageVisibilityState visibilityState, bool isInitialState) +void InjectedBundle::setHidden(bool hidden) { - WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetVisibilityState")); + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetHidden")); WKRetainPtr<WKMutableDictionaryRef> messageBody(AdoptWK, WKMutableDictionaryCreate()); - WKRetainPtr<WKStringRef> visibilityStateKeyWK(AdoptWK, WKStringCreateWithUTF8CString("visibilityState")); - WKRetainPtr<WKUInt64Ref> visibilityStateWK(AdoptWK, WKUInt64Create(visibilityState)); - WKDictionarySetItem(messageBody.get(), visibilityStateKeyWK.get(), visibilityStateWK.get()); - - WKRetainPtr<WKStringRef> isInitialKeyWK(AdoptWK, WKStringCreateWithUTF8CString("isInitialState")); - WKRetainPtr<WKBooleanRef> isInitialWK(AdoptWK, WKBooleanCreate(isInitialState)); + WKRetainPtr<WKStringRef> isInitialKeyWK(AdoptWK, WKStringCreateWithUTF8CString("hidden")); + WKRetainPtr<WKBooleanRef> isInitialWK(AdoptWK, WKBooleanCreate(hidden)); WKDictionarySetItem(messageBody.get(), isInitialKeyWK.get(), isInitialWK.get()); - WKBundlePostMessage(m_bundle, messageName.get(), messageBody.get()); + WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get()); +} + +void InjectedBundle::setCacheModel(int model) +{ + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetCacheModel")); + WKRetainPtr<WKUInt64Ref> messageBody(AdoptWK, WKUInt64Create(model)); + WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get()); } bool InjectedBundle::shouldProcessWorkQueue() const @@ -489,7 +694,7 @@ bool InjectedBundle::shouldProcessWorkQueue() const WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("IsWorkQueueEmpty")); WKTypeRef resultToPass = 0; - WKBundlePostSynchronousMessage(m_bundle, messageName.get(), 0, &resultToPass); + WKBundlePagePostSynchronousMessageForTesting(page()->page(), messageName.get(), 0, &resultToPass); WKRetainPtr<WKBooleanRef> isEmpty(AdoptWK, static_cast<WKBooleanRef>(resultToPass)); return !WKBooleanGetValue(isEmpty.get()); @@ -498,7 +703,7 @@ bool InjectedBundle::shouldProcessWorkQueue() const void InjectedBundle::processWorkQueue() { WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("ProcessWorkQueue")); - WKBundlePostMessage(m_bundle, messageName.get(), 0); + WKBundlePagePostMessage(page()->page(), messageName.get(), 0); } void InjectedBundle::queueBackNavigation(unsigned howFarBackward) @@ -507,7 +712,7 @@ void InjectedBundle::queueBackNavigation(unsigned howFarBackward) WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("QueueBackNavigation")); WKRetainPtr<WKUInt64Ref> messageBody(AdoptWK, WKUInt64Create(howFarBackward)); - WKBundlePostMessage(m_bundle, messageName.get(), messageBody.get()); + WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get()); } void InjectedBundle::queueForwardNavigation(unsigned howFarForward) @@ -516,10 +721,10 @@ void InjectedBundle::queueForwardNavigation(unsigned howFarForward) WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("QueueForwardNavigation")); WKRetainPtr<WKUInt64Ref> messageBody(AdoptWK, WKUInt64Create(howFarForward)); - WKBundlePostMessage(m_bundle, messageName.get(), messageBody.get()); + WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get()); } -void InjectedBundle::queueLoad(WKStringRef url, WKStringRef target) +void InjectedBundle::queueLoad(WKStringRef url, WKStringRef target, bool shouldOpenExternalURLs) { m_useWorkQueue = true; @@ -533,7 +738,11 @@ void InjectedBundle::queueLoad(WKStringRef url, WKStringRef target) WKRetainPtr<WKStringRef> targetKey(AdoptWK, WKStringCreateWithUTF8CString("target")); WKDictionarySetItem(loadData.get(), targetKey.get(), target); - WKBundlePostMessage(m_bundle, messageName.get(), loadData.get()); + WKRetainPtr<WKStringRef> shouldOpenExternalURLsKey(AdoptWK, WKStringCreateWithUTF8CString("shouldOpenExternalURLs")); + WKRetainPtr<WKBooleanRef> shouldOpenExternalURLsValue(AdoptWK, WKBooleanCreate(shouldOpenExternalURLs)); + WKDictionarySetItem(loadData.get(), shouldOpenExternalURLsKey.get(), shouldOpenExternalURLsValue.get()); + + WKBundlePagePostMessage(page()->page(), messageName.get(), loadData.get()); } void InjectedBundle::queueLoadHTMLString(WKStringRef content, WKStringRef baseURL, WKStringRef unreachableURL) @@ -557,7 +766,7 @@ void InjectedBundle::queueLoadHTMLString(WKStringRef content, WKStringRef baseUR WKDictionarySetItem(loadData.get(), unreachableURLKey.get(), unreachableURL); } - WKBundlePostMessage(m_bundle, messageName.get(), loadData.get()); + WKBundlePagePostMessage(page()->page(), messageName.get(), loadData.get()); } void InjectedBundle::queueReload() @@ -565,7 +774,7 @@ void InjectedBundle::queueReload() m_useWorkQueue = true; WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("QueueReload")); - WKBundlePostMessage(m_bundle, messageName.get(), 0); + WKBundlePagePostMessage(page()->page(), messageName.get(), 0); } void InjectedBundle::queueLoadingScript(WKStringRef script) @@ -573,7 +782,7 @@ void InjectedBundle::queueLoadingScript(WKStringRef script) m_useWorkQueue = true; WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("QueueLoadingScript")); - WKBundlePostMessage(m_bundle, messageName.get(), script); + WKBundlePagePostMessage(page()->page(), messageName.get(), script); } void InjectedBundle::queueNonLoadingScript(WKStringRef script) @@ -581,7 +790,19 @@ void InjectedBundle::queueNonLoadingScript(WKStringRef script) m_useWorkQueue = true; WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("QueueNonLoadingScript")); - WKBundlePostMessage(m_bundle, messageName.get(), script); + WKBundlePagePostMessage(page()->page(), messageName.get(), script); +} + +bool InjectedBundle::isAllowedHost(WKStringRef host) +{ + if (m_allowedHosts.isEmpty()) + return false; + return m_allowedHosts.contains(toWTFString(host)); +} + +void InjectedBundle::setAllowsAnySSLCertificate(bool allowsAnySSLCertificate) +{ + WebCoreTestSupport::setAllowsAnySSLCertificate(allowsAnySSLCertificate); } } // namespace WTR diff --git a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h index 170c8ac70..2edd5e797 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h +++ b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2011, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2010-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 @@ -23,29 +23,30 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef InjectedBundle_h -#define InjectedBundle_h +#pragma once -#include "AccessibilityController.h" #include "EventSendingController.h" #include "GCController.h" #include "TestRunner.h" #include "TextInputController.h" -#include <WebKit2/WKBase.h> -#include <WebKit2/WKRetainPtr.h> +#include <WebKit/WKBase.h> +#include <WebKit/WKRetainPtr.h> #include <sstream> #include <wtf/Forward.h> -#include <wtf/OwnPtr.h> #include <wtf/RefPtr.h> #include <wtf/Vector.h> +#if HAVE(ACCESSIBILITY) +#include "AccessibilityController.h" +#endif + namespace WTR { class InjectedBundlePage; class InjectedBundle { public: - static InjectedBundle& shared(); + static InjectedBundle& singleton(); // Initialize the InjectedBundle. void initialize(WKBundleRef, WKTypeRef initializationUserData); @@ -57,7 +58,9 @@ public: GCController* gcController() { return m_gcController.get(); } EventSendingController* eventSendingController() { return m_eventSendingController.get(); } TextInputController* textInputController() { return m_textInputController.get(); } +#if HAVE(ACCESSIBILITY) AccessibilityController* accessibilityController() { return m_accessibilityController.get(); } +#endif InjectedBundlePage* page() const; size_t pageCount() const { return m_pages.size(); } @@ -67,7 +70,8 @@ public: void done(); void setAudioResult(WKDataRef audioData) { m_audioResult = audioData; } - void setPixelResult(WKImageRef image) { m_pixelResult = image; } + void setPixelResult(WKImageRef image) { m_pixelResult = image; m_pixelResultIsPending = false; } + void setPixelResultIsPending(bool isPending) { m_pixelResultIsPending = isPending; } void setRepaintRects(WKArrayRef rects) { m_repaintRects = rects; } bool isTestRunning() { return m_state == Testing; } @@ -77,38 +81,58 @@ public: bool shouldDumpPixels() const { return m_dumpPixels; } bool useWaitToDumpWatchdogTimer() const { return m_useWaitToDumpWatchdogTimer; } - + bool dumpJSConsoleLogInStdErr() const { return m_dumpJSConsoleLogInStdErr; }; + void outputText(const String&); + void dumpToStdErr(const String&); void postNewBeforeUnloadReturnValue(bool); void postAddChromeInputField(); void postRemoveChromeInputField(); void postFocusWebView(); void postSetBackingScaleFactor(double); void postSetWindowIsKey(bool); + void postSetViewSize(double width, double height); void postSimulateWebNotificationClick(uint64_t notificationID); + void postSetAddsVisitedLinks(bool); // Geolocation. void setGeolocationPermission(bool); 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(WKStringRef errorMessage); + bool isGeolocationProviderActive() const; + + // MediaStream. + void setUserMediaPermission(bool); + void setUserMediaPersistentPermissionForOrigin(bool permission, WKStringRef origin, WKStringRef parentOrigin); + unsigned userMediaPermissionRequestCountForOrigin(WKStringRef origin, WKStringRef parentOrigin) const; + void resetUserMediaPermissionRequestCountForOrigin(WKStringRef origin, WKStringRef parentOrigin); // Policy delegate. void setCustomPolicyDelegate(bool enabled, bool permissive); // Page Visibility. - void setVisibilityState(WKPageVisibilityState, bool isInitialState); + void setHidden(bool); + + // Cache. + void setCacheModel(int); // Work queue. bool shouldProcessWorkQueue() const; void processWorkQueue(); void queueBackNavigation(unsigned howFarBackward); void queueForwardNavigation(unsigned howFarForward); - void queueLoad(WKStringRef url, WKStringRef target); + void queueLoad(WKStringRef url, WKStringRef target, bool shouldOpenExternalURLs = false); void queueLoadHTMLString(WKStringRef content, WKStringRef baseURL = 0, WKStringRef unreachableURL = 0); void queueReload(); void queueLoadingScript(WKStringRef script); void queueNonLoadingScript(WKStringRef script); + bool isAllowedHost(WKStringRef); + + unsigned imageCountInGeneralPasteboard() const; + + void setAllowsAnySSLCertificate(bool); + private: InjectedBundle(); ~InjectedBundle(); @@ -134,9 +158,11 @@ private: WKBundleRef m_bundle; WKBundlePageGroupRef m_pageGroup; - Vector<OwnPtr<InjectedBundlePage> > m_pages; + Vector<std::unique_ptr<InjectedBundlePage>> m_pages; +#if HAVE(ACCESSIBILITY) RefPtr<AccessibilityController> m_accessibilityController; +#endif RefPtr<TestRunner> m_testRunner; RefPtr<GCController> m_gcController; RefPtr<EventSendingController> m_eventSendingController; @@ -155,12 +181,14 @@ private: bool m_useWaitToDumpWatchdogTimer; bool m_useWorkQueue; int m_timeout; + bool m_pixelResultIsPending { false }; + bool m_dumpJSConsoleLogInStdErr { false }; WKRetainPtr<WKDataRef> m_audioResult; WKRetainPtr<WKImageRef> m_pixelResult; WKRetainPtr<WKArrayRef> m_repaintRects; + + Vector<String> m_allowedHosts; }; } // namespace WTR - -#endif // InjectedBundle_h diff --git a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundleMain.cpp b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundleMain.cpp index 58af68221..4f1272214 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundleMain.cpp +++ b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundleMain.cpp @@ -26,10 +26,10 @@ #include "config.h" #include "InjectedBundle.h" -#include <WebKit2/WKBundleInitialize.h> +#include <WebKit/WKBundleInitialize.h> extern "C" void WKBundleInitialize(WKBundleRef bundle, WKTypeRef initializationUserData) { - WTR::InjectedBundle::shared().initialize(bundle, initializationUserData); + WTR::InjectedBundle::singleton().initialize(bundle, initializationUserData); } diff --git a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp index e161156a7..61c59b2e3 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp +++ b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2011, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2010-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 @@ -31,19 +31,20 @@ #include "WebCoreTestSupport.h" #include <cmath> #include <JavaScriptCore/JSRetainPtr.h> -#include <WebKit2/WKArray.h> -#include <WebKit2/WKBundle.h> -#include <WebKit2/WKBundleBackForwardList.h> -#include <WebKit2/WKBundleBackForwardListItem.h> -#include <WebKit2/WKBundleFrame.h> -#include <WebKit2/WKBundleFramePrivate.h> -#include <WebKit2/WKBundleHitTestResult.h> -#include <WebKit2/WKBundleNavigationAction.h> -#include <WebKit2/WKBundleNodeHandlePrivate.h> -#include <WebKit2/WKBundlePagePrivate.h> -#include <WebKit2/WKBundlePrivate.h> -#include <WebKit2/WKSecurityOrigin.h> -#include <WebKit2/WKURLRequest.h> +#include <WebKit/WKArray.h> +#include <WebKit/WKBundle.h> +#include <WebKit/WKBundleBackForwardList.h> +#include <WebKit/WKBundleBackForwardListItem.h> +#include <WebKit/WKBundleFrame.h> +#include <WebKit/WKBundleFramePrivate.h> +#include <WebKit/WKBundleHitTestResult.h> +#include <WebKit/WKBundleNavigationAction.h> +#include <WebKit/WKBundleNavigationActionPrivate.h> +#include <WebKit/WKBundleNodeHandlePrivate.h> +#include <WebKit/WKBundlePagePrivate.h> +#include <WebKit/WKBundlePrivate.h> +#include <WebKit/WKSecurityOriginRef.h> +#include <WebKit/WKURLRequest.h> #include <wtf/HashMap.h> #include <wtf/text/CString.h> #include <wtf/text/StringBuilder.h> @@ -240,7 +241,7 @@ static inline WTF::String pathSuitableForTestResult(WKURLRef fileUrl) if (!isLocalFileScheme(schemeString.get())) return toWTFString(adoptWK(WKURLCopyString(fileUrl))); - WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page()); + WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page()); WKRetainPtr<WKURLRef> mainFrameURL = adoptWK(WKBundleFrameCopyURL(mainFrame)); if (!mainFrameURL) mainFrameURL = adoptWK(WKBundleFrameCopyProvisionalURL(mainFrame)); @@ -268,8 +269,8 @@ InjectedBundlePage::InjectedBundlePage(WKBundlePageRef page) : m_page(page) , m_world(AdoptWK, WKBundleScriptWorldCreateWorld()) { - WKBundlePageLoaderClientV7 loaderClient = { - { 7, this }, + WKBundlePageLoaderClientV8 loaderClient = { + { 8, this }, didStartProvisionalLoadForFrame, didReceiveServerRedirectForProvisionalLoadForFrame, didFailProvisionalLoadWithErrorForFrame, @@ -304,7 +305,8 @@ InjectedBundlePage::InjectedBundlePage(WKBundlePageRef page) 0, // featuresUsedInPage 0, // willLoadURLRequest 0, // willLoadDataRequest - 0, // willDestroyFrame + 0, // willDestroyFrame_unavailable + 0, // userAgentForURL }; WKBundlePageSetPageLoaderClient(m_page, &loaderClient.base); @@ -412,14 +414,26 @@ void InjectedBundlePage::prepare() WKBundleFrameClearOpener(WKBundlePageGetMainFrame(m_page)); WKBundlePageSetTracksRepaints(m_page, false); + + // Force consistent "responsive" behavior for WebPage::eventThrottlingDelay() for testing. Tests can override via internals. + WKEventThrottlingBehavior behavior = kWKEventThrottlingBehaviorResponsive; + WKBundlePageSetEventThrottlingBehaviorOverride(m_page, &behavior); } void InjectedBundlePage::resetAfterTest() { WKBundleFrameRef frame = WKBundlePageGetMainFrame(m_page); + + // WebKit currently doesn't reset focus even when navigating to a new page. This may or may not be a bug + // (see <https://bugs.webkit.org/show_bug.cgi?id=138334>), however for tests, we want to start each one with a clean state. + WKBundleFrameFocus(frame); + JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame); WebCoreTestSupport::resetInternalsObject(context); assignedUrlsCache.clear(); + + // User scripts need to be removed after the test and before loading about:blank, as otherwise they would run in about:blank, and potentially leak results into a subsequest test. + WKBundlePageRemoveAllUserContent(m_page); } // Loader Client Callbacks @@ -457,7 +471,7 @@ static void dumpLoadEvent(WKBundleFrameRef frame, const char* eventName) stringBuilder.appendLiteral(" - "); stringBuilder.append(eventName); stringBuilder.append('\n'); - InjectedBundle::shared().outputText(stringBuilder.toString()); + InjectedBundle::singleton().outputText(stringBuilder.toString()); } static inline void dumpRequestDescriptionSuitableForTestResult(WKURLRequestRef request, StringBuilder& stringBuilder) @@ -646,49 +660,64 @@ bool InjectedBundlePage::shouldCacheResponse(WKBundlePageRef page, WKBundleFrame void InjectedBundlePage::didStartProvisionalLoadForFrame(WKBundleFrameRef frame) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return; + if (!injectedBundle.testRunner()->testURL()) { + WKRetainPtr<WKURLRef> testURL = adoptWK(WKBundleFrameCopyProvisionalURL(frame)); + injectedBundle.testRunner()->setTestURL(testURL.get()); + } + platformDidStartProvisionalLoadForFrame(frame); - if (InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks()) + if (injectedBundle.testRunner()->shouldDumpFrameLoadCallbacks()) dumpLoadEvent(frame, "didStartProvisionalLoadForFrame"); - if (!InjectedBundle::shared().topLoadingFrame()) - InjectedBundle::shared().setTopLoadingFrame(frame); + if (!injectedBundle.topLoadingFrame()) + injectedBundle.setTopLoadingFrame(frame); - if (InjectedBundle::shared().testRunner()->shouldStopProvisionalFrameLoads()) + if (injectedBundle.testRunner()->shouldStopProvisionalFrameLoads()) dumpLoadEvent(frame, "stopping load in didStartProvisionalLoadForFrame callback"); } void InjectedBundlePage::didReceiveServerRedirectForProvisionalLoadForFrame(WKBundleFrameRef frame) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return; - if (!InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks()) + if (!injectedBundle.testRunner()->shouldDumpFrameLoadCallbacks()) return; dumpLoadEvent(frame, "didReceiveServerRedirectForProvisionalLoadForFrame"); } -void InjectedBundlePage::didFailProvisionalLoadWithErrorForFrame(WKBundleFrameRef frame, WKErrorRef) +void InjectedBundlePage::didFailProvisionalLoadWithErrorForFrame(WKBundleFrameRef frame, WKErrorRef error) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return; - if (InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks()) + if (injectedBundle.testRunner()->shouldDumpFrameLoadCallbacks()) { dumpLoadEvent(frame, "didFailProvisionalLoadWithError"); + auto code = WKErrorGetErrorCode(error); + if (code == kWKErrorCodeCannotShowURL) + dumpLoadEvent(frame, "(ErrorCodeCannotShowURL)"); + else if (code == kWKErrorCodeFrameLoadBlockedByContentBlocker) + dumpLoadEvent(frame, "(kWKErrorCodeFrameLoadBlockedByContentBlocker)"); + } frameDidChangeLocation(frame); } void InjectedBundlePage::didCommitLoadForFrame(WKBundleFrameRef frame) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return; - if (!InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks()) + if (!injectedBundle.testRunner()->shouldDumpFrameLoadCallbacks()) return; dumpLoadEvent(frame, "didCommitLoadForFrame"); @@ -696,13 +725,14 @@ void InjectedBundlePage::didCommitLoadForFrame(WKBundleFrameRef frame) void InjectedBundlePage::didFinishProgress() { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return; - if (!InjectedBundle::shared().testRunner()->shouldDumpProgressFinishedCallback()) + if (!injectedBundle.testRunner()->shouldDumpProgressFinishedCallback()) return; - InjectedBundle::shared().outputText("postProgressFinishedNotification\n"); + injectedBundle.outputText("postProgressFinishedNotification\n"); } enum FrameNamePolicy { ShouldNotIncludeFrameName, ShouldIncludeFrameName }; @@ -816,16 +846,15 @@ void InjectedBundlePage::dumpDOMAsWebArchive(WKBundleFrameRef frame, StringBuild #if USE(CF) WKRetainPtr<WKDataRef> wkData = adoptWK(WKBundleFrameCopyWebArchive(frame)); RetainPtr<CFDataRef> cfData = adoptCF(CFDataCreate(0, WKDataGetBytes(wkData.get()), WKDataGetSize(wkData.get()))); - RetainPtr<CFStringRef> cfString = adoptCF(createXMLStringFromWebArchiveData(cfData.get())); + RetainPtr<CFStringRef> cfString = adoptCF(WebCoreTestSupport::createXMLStringFromWebArchiveData(cfData.get())); stringBuilder.append(cfString.get()); #endif } void InjectedBundlePage::dump() { - ASSERT(InjectedBundle::shared().isTestRunning()); - - InjectedBundle::shared().testRunner()->invalidateWaitToDumpWatchdogTimer(); + auto& injectedBundle = InjectedBundle::singleton(); + ASSERT(injectedBundle.isTestRunning()); // Force a paint before dumping. This matches DumpRenderTree on Windows. (DumpRenderTree on Mac // does this at a slightly different time.) See <http://webkit.org/b/55469> for details. @@ -836,13 +865,13 @@ void InjectedBundlePage::dump() String url = toWTFString(adoptWK(WKURLCopyString(urlRef.get()))); WKRetainPtr<WKStringRef> mimeType = adoptWK(WKBundleFrameCopyMIMETypeForResourceWithURL(frame, urlRef.get())); if (url.find("dumpAsText/") != notFound || WKStringIsEqualToUTF8CString(mimeType.get(), "text/plain")) - InjectedBundle::shared().testRunner()->dumpAsText(false); + injectedBundle.testRunner()->dumpAsText(false); StringBuilder stringBuilder; - switch (InjectedBundle::shared().testRunner()->whatToDump()) { + switch (injectedBundle.testRunner()->whatToDump()) { case TestRunner::RenderTree: { - if (InjectedBundle::shared().testRunner()->isPrinting()) + if (injectedBundle.testRunner()->isPrinting()) stringBuilder.append(toWTFString(adoptWK(WKBundlePageCopyRenderTreeExternalRepresentationForPrinting(m_page)).get())); else stringBuilder.append(toWTFString(adoptWK(WKBundlePageCopyRenderTreeExternalRepresentation(m_page)).get())); @@ -861,34 +890,47 @@ void InjectedBundlePage::dump() break; } - if (InjectedBundle::shared().testRunner()->shouldDumpAllFrameScrollPositions()) + if (injectedBundle.testRunner()->shouldDumpAllFrameScrollPositions()) dumpAllFrameScrollPositions(stringBuilder); - else if (InjectedBundle::shared().testRunner()->shouldDumpMainFrameScrollPosition()) + else if (injectedBundle.testRunner()->shouldDumpMainFrameScrollPosition()) dumpFrameScrollPosition(WKBundlePageGetMainFrame(m_page), stringBuilder); - if (InjectedBundle::shared().testRunner()->shouldDumpBackForwardListsForAllWindows()) - InjectedBundle::shared().dumpBackForwardListsForAllPages(stringBuilder); + if (injectedBundle.testRunner()->shouldDumpBackForwardListsForAllWindows()) + injectedBundle.dumpBackForwardListsForAllPages(stringBuilder); + + if (injectedBundle.shouldDumpPixels() && injectedBundle.testRunner()->shouldDumpPixels()) { + bool shouldCreateSnapshot = injectedBundle.testRunner()->isPrinting(); + if (shouldCreateSnapshot) { + WKSnapshotOptions options = kWKSnapshotOptionsShareable; + WKRect snapshotRect = WKBundleFrameGetVisibleContentBounds(WKBundlePageGetMainFrame(m_page)); - if (InjectedBundle::shared().shouldDumpPixels() && InjectedBundle::shared().testRunner()->shouldDumpPixels()) { - WKSnapshotOptions options = kWKSnapshotOptionsShareable | kWKSnapshotOptionsInViewCoordinates; - if (InjectedBundle::shared().testRunner()->shouldDumpSelectionRect()) - options |= kWKSnapshotOptionsPaintSelectionRectangle; + if (injectedBundle.testRunner()->isPrinting()) + options |= kWKSnapshotOptionsPrinting; + else { + options |= kWKSnapshotOptionsInViewCoordinates; + if (injectedBundle.testRunner()->shouldDumpSelectionRect()) + options |= kWKSnapshotOptionsPaintSelectionRectangle; + } + + injectedBundle.setPixelResult(adoptWK(WKBundlePageCreateSnapshotWithOptions(m_page, snapshotRect, options)).get()); + } else + injectedBundle.setPixelResultIsPending(true); - InjectedBundle::shared().setPixelResult(adoptWK(WKBundlePageCreateSnapshotWithOptions(m_page, WKBundleFrameGetVisibleContentBounds(WKBundlePageGetMainFrame(m_page)), options)).get()); - if (WKBundlePageIsTrackingRepaints(m_page)) - InjectedBundle::shared().setRepaintRects(adoptWK(WKBundlePageCopyTrackedRepaintRects(m_page)).get()); + if (WKBundlePageIsTrackingRepaints(m_page) && !injectedBundle.testRunner()->isPrinting()) + injectedBundle.setRepaintRects(adoptWK(WKBundlePageCopyTrackedRepaintRects(m_page)).get()); } - InjectedBundle::shared().outputText(stringBuilder.toString()); - InjectedBundle::shared().done(); + injectedBundle.outputText(stringBuilder.toString()); + injectedBundle.done(); } void InjectedBundlePage::didFinishLoadForFrame(WKBundleFrameRef frame) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return; - if (InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks()) + if (injectedBundle.testRunner()->shouldDumpFrameLoadCallbacks()) dumpLoadEvent(frame, "didFinishLoadForFrame"); frameDidChangeLocation(frame, /*shouldDump*/ true); @@ -896,10 +938,11 @@ void InjectedBundlePage::didFinishLoadForFrame(WKBundleFrameRef frame) void InjectedBundlePage::didFailLoadWithErrorForFrame(WKBundleFrameRef frame, WKErrorRef) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return; - if (InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks()) + if (injectedBundle.testRunner()->shouldDumpFrameLoadCallbacks()) dumpLoadEvent(frame, "didFailLoadWithError"); frameDidChangeLocation(frame); @@ -907,29 +950,31 @@ void InjectedBundlePage::didFailLoadWithErrorForFrame(WKBundleFrameRef frame, WK void InjectedBundlePage::didReceiveTitleForFrame(WKStringRef title, WKBundleFrameRef frame) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return; StringBuilder stringBuilder; - if (InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks()) { + if (injectedBundle.testRunner()->shouldDumpFrameLoadCallbacks()) { dumpFrameDescriptionSuitableForTestResult(frame, stringBuilder); stringBuilder.appendLiteral(" - didReceiveTitle: "); stringBuilder.append(toWTFString(title)); stringBuilder.append('\n'); } - if (InjectedBundle::shared().testRunner()->shouldDumpTitleChanges()) { + if (injectedBundle.testRunner()->shouldDumpTitleChanges()) { stringBuilder.appendLiteral("TITLE CHANGED: '"); stringBuilder.append(toWTFString(title)); stringBuilder.appendLiteral("'\n"); } - InjectedBundle::shared().outputText(stringBuilder.toString()); + injectedBundle.outputText(stringBuilder.toString()); } void InjectedBundlePage::didClearWindowForFrame(WKBundleFrameRef frame, WKBundleScriptWorldRef world) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return; JSGlobalContextRef context = WKBundleFrameGetJavaScriptContextForWorld(frame, world); @@ -940,22 +985,23 @@ void InjectedBundlePage::didClearWindowForFrame(WKBundleFrameRef frame, WKBundle return; } - JSValueRef exception = 0; - InjectedBundle::shared().testRunner()->makeWindowObject(context, window, &exception); - InjectedBundle::shared().gcController()->makeWindowObject(context, window, &exception); - InjectedBundle::shared().eventSendingController()->makeWindowObject(context, window, &exception); - InjectedBundle::shared().textInputController()->makeWindowObject(context, window, &exception); - InjectedBundle::shared().accessibilityController()->makeWindowObject(context, window, &exception); + JSValueRef exception = nullptr; + injectedBundle.testRunner()->makeWindowObject(context, window, &exception); + injectedBundle.gcController()->makeWindowObject(context, window, &exception); + injectedBundle.eventSendingController()->makeWindowObject(context, window, &exception); + injectedBundle.textInputController()->makeWindowObject(context, window, &exception); + injectedBundle.accessibilityController()->makeWindowObject(context, window, &exception); WebCoreTestSupport::injectInternalsObject(context); } void InjectedBundlePage::didCancelClientRedirectForFrame(WKBundleFrameRef frame) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return; - if (!InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks()) + if (!injectedBundle.testRunner()->shouldDumpFrameLoadCallbacks()) return; dumpLoadEvent(frame, "didCancelClientRedirectForFrame"); @@ -963,10 +1009,11 @@ void InjectedBundlePage::didCancelClientRedirectForFrame(WKBundleFrameRef frame) void InjectedBundlePage::willPerformClientRedirectForFrame(WKBundlePageRef, WKBundleFrameRef frame, WKURLRef url, double delay, double date) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return; - if (!InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks()) + if (!injectedBundle.testRunner()->shouldDumpFrameLoadCallbacks()) return; StringBuilder stringBuilder; @@ -974,19 +1021,31 @@ void InjectedBundlePage::willPerformClientRedirectForFrame(WKBundlePageRef, WKBu stringBuilder.appendLiteral(" - willPerformClientRedirectToURL: "); stringBuilder.append(pathSuitableForTestResult(url)); stringBuilder.appendLiteral(" \n"); - InjectedBundle::shared().outputText(stringBuilder.toString()); + injectedBundle.outputText(stringBuilder.toString()); } void InjectedBundlePage::didSameDocumentNavigationForFrame(WKBundleFrameRef frame, WKSameDocumentNavigationType type) { + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) + return; + + if (!injectedBundle.testRunner()->shouldDumpFrameLoadCallbacks()) + return; + + if (type != kWKSameDocumentNavigationAnchorNavigation) + return; + + dumpLoadEvent(frame, "didChangeLocationWithinPageForFrame"); } void InjectedBundlePage::didFinishDocumentLoadForFrame(WKBundleFrameRef frame) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return; - if (InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks()) + if (injectedBundle.testRunner()->shouldDumpFrameLoadCallbacks()) dumpLoadEvent(frame, "didFinishDocumentLoadForFrame"); unsigned pendingFrameUnloadEvents = WKBundleFrameGetPendingUnloadCount(frame); @@ -996,40 +1055,44 @@ void InjectedBundlePage::didFinishDocumentLoadForFrame(WKBundleFrameRef frame) stringBuilder.appendLiteral(" - has "); stringBuilder.appendNumber(pendingFrameUnloadEvents); stringBuilder.appendLiteral(" onunload handler(s)\n"); - InjectedBundle::shared().outputText(stringBuilder.toString()); + injectedBundle.outputText(stringBuilder.toString()); } } void InjectedBundlePage::didHandleOnloadEventsForFrame(WKBundleFrameRef frame) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return; - if (InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks()) + if (injectedBundle.testRunner()->shouldDumpFrameLoadCallbacks()) dumpLoadEvent(frame, "didHandleOnloadEventsForFrame"); } -void InjectedBundlePage::didDisplayInsecureContentForFrame(WKBundleFrameRef frame) +void InjectedBundlePage::didDisplayInsecureContentForFrame(WKBundleFrameRef) { - if (InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks()) - InjectedBundle::shared().outputText("didDisplayInsecureContent\n"); + auto& injectedBundle = InjectedBundle::singleton(); + if (injectedBundle.testRunner()->shouldDumpFrameLoadCallbacks()) + injectedBundle.outputText("didDisplayInsecureContent\n"); } -void InjectedBundlePage::didRunInsecureContentForFrame(WKBundleFrameRef frame) +void InjectedBundlePage::didRunInsecureContentForFrame(WKBundleFrameRef) { - if (InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks()) - InjectedBundle::shared().outputText("didRunInsecureContent\n"); + auto& injectedBundle = InjectedBundle::singleton(); + if (injectedBundle.testRunner()->shouldDumpFrameLoadCallbacks()) + injectedBundle.outputText("didRunInsecureContent\n"); } -void InjectedBundlePage::didDetectXSSForFrame(WKBundleFrameRef frame) +void InjectedBundlePage::didDetectXSSForFrame(WKBundleFrameRef) { - if (InjectedBundle::shared().testRunner()->shouldDumpFrameLoadCallbacks()) - InjectedBundle::shared().outputText("didDetectXSS\n"); + auto& injectedBundle = InjectedBundle::singleton(); + if (injectedBundle.testRunner()->shouldDumpFrameLoadCallbacks()) + injectedBundle.outputText("didDetectXSS\n"); } void InjectedBundlePage::didInitiateLoadForResource(WKBundlePageRef page, WKBundleFrameRef, uint64_t identifier, WKURLRequestRef request, bool) { - if (!InjectedBundle::shared().isTestRunning()) + if (!InjectedBundle::singleton().isTestRunning()) return; WKRetainPtr<WKURLRef> url = adoptWK(WKURLRequestCopyURL(request)); @@ -1048,10 +1111,16 @@ static inline bool isHTTPOrHTTPSScheme(WKStringRef scheme) return WKStringIsEqualToUTF8CStringIgnoringCase(scheme, "http") || WKStringIsEqualToUTF8CStringIgnoringCase(scheme, "https"); } +static inline bool isAllowedHost(WKStringRef host) +{ + return InjectedBundle::singleton().isAllowedHost(host); +} + WKURLRequestRef InjectedBundlePage::willSendRequestForFrame(WKBundlePageRef page, WKBundleFrameRef frame, uint64_t identifier, WKURLRequestRef request, WKURLResponseRef response) { - if (InjectedBundle::shared().isTestRunning() - && InjectedBundle::shared().testRunner()->shouldDumpResourceLoadCallbacks()) { + auto& injectedBundle = InjectedBundle::singleton(); + if (injectedBundle.isTestRunning() + && injectedBundle.testRunner()->shouldDumpResourceLoadCallbacks()) { StringBuilder stringBuilder; dumpResourceURL(identifier, stringBuilder); stringBuilder.appendLiteral(" - willSendRequest "); @@ -1059,16 +1128,16 @@ WKURLRequestRef InjectedBundlePage::willSendRequestForFrame(WKBundlePageRef page stringBuilder.appendLiteral(" redirectResponse "); dumpResponseDescriptionSuitableForTestResult(response, stringBuilder); stringBuilder.append('\n'); - InjectedBundle::shared().outputText(stringBuilder.toString()); + injectedBundle.outputText(stringBuilder.toString()); } - if (InjectedBundle::shared().isTestRunning() && InjectedBundle::shared().testRunner()->willSendRequestReturnsNull()) - return 0; + if (injectedBundle.isTestRunning() && injectedBundle.testRunner()->willSendRequestReturnsNull()) + return nullptr; WKRetainPtr<WKURLRef> redirectURL = adoptWK(WKURLResponseCopyURL(response)); - if (InjectedBundle::shared().isTestRunning() && InjectedBundle::shared().testRunner()->willSendRequestReturnsNullOnRedirect() && redirectURL) { - InjectedBundle::shared().outputText("Returning null for this redirect\n"); - return 0; + if (injectedBundle.isTestRunning() && injectedBundle.testRunner()->willSendRequestReturnsNullOnRedirect() && redirectURL) { + injectedBundle.outputText("Returning null for this redirect\n"); + return nullptr; } WKRetainPtr<WKURLRef> url = adoptWK(WKURLRequestCopyURL(request)); @@ -1080,23 +1149,31 @@ WKURLRequestRef InjectedBundlePage::willSendRequestForFrame(WKBundlePageRef page && !WKStringIsEqualToUTF8CString(host.get(), "255.255.255.255") // Used in some tests that expect to get back an error. && !isLocalHost(host.get())) { bool mainFrameIsExternal = false; - if (InjectedBundle::shared().isTestRunning()) { - WKBundleFrameRef mainFrame = InjectedBundle::shared().topLoadingFrame(); + if (injectedBundle.isTestRunning()) { + WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(m_page); WKRetainPtr<WKURLRef> mainFrameURL = adoptWK(WKBundleFrameCopyURL(mainFrame)); if (!mainFrameURL || WKStringIsEqualToUTF8CString(adoptWK(WKURLCopyString(mainFrameURL.get())).get(), "about:blank")) mainFrameURL = adoptWK(WKBundleFrameCopyProvisionalURL(mainFrame)); - WKRetainPtr<WKStringRef> mainFrameHost = WKURLCopyHostName(mainFrameURL.get()); - WKRetainPtr<WKStringRef> mainFrameScheme = WKURLCopyScheme(mainFrameURL.get()); + WKRetainPtr<WKStringRef> mainFrameHost = adoptWK(WKURLCopyHostName(mainFrameURL.get())); + WKRetainPtr<WKStringRef> mainFrameScheme = adoptWK(WKURLCopyScheme(mainFrameURL.get())); mainFrameIsExternal = isHTTPOrHTTPSScheme(mainFrameScheme.get()) && !isLocalHost(mainFrameHost.get()); } - if (!mainFrameIsExternal) { + if (!mainFrameIsExternal && !isAllowedHost(host.get())) { StringBuilder stringBuilder; stringBuilder.appendLiteral("Blocked access to external URL "); stringBuilder.append(toWTFString(urlString)); stringBuilder.append('\n'); - InjectedBundle::shared().outputText(stringBuilder.toString()); - return 0; + injectedBundle.outputText(stringBuilder.toString()); + return nullptr; + } + } + + if (injectedBundle.isTestRunning()) { + String body = injectedBundle.testRunner()->willSendRequestHTTPBody(); + if (!body.isEmpty()) { + CString cBody = body.utf8(); + return WKURLRequestCopySettingHTTPBody(request, WKDataCreate(reinterpret_cast<const unsigned char*>(cBody.data()), cBody.length())); } } @@ -1106,20 +1183,21 @@ WKURLRequestRef InjectedBundlePage::willSendRequestForFrame(WKBundlePageRef page void InjectedBundlePage::didReceiveResponseForResource(WKBundlePageRef page, WKBundleFrameRef, uint64_t identifier, WKURLResponseRef response) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return; - if (InjectedBundle::shared().testRunner()->shouldDumpResourceLoadCallbacks()) { + if (injectedBundle.testRunner()->shouldDumpResourceLoadCallbacks()) { StringBuilder stringBuilder; dumpResourceURL(identifier, stringBuilder); stringBuilder.appendLiteral(" - didReceiveResponse "); dumpResponseDescriptionSuitableForTestResult(response, stringBuilder); stringBuilder.append('\n'); - InjectedBundle::shared().outputText(stringBuilder.toString()); + injectedBundle.outputText(stringBuilder.toString()); } - if (!InjectedBundle::shared().testRunner()->shouldDumpResourceResponseMIMETypes()) + if (!injectedBundle.testRunner()->shouldDumpResourceResponseMIMETypes()) return; WKRetainPtr<WKURLRef> url = adoptWK(WKURLResponseCopyURL(response)); @@ -1130,8 +1208,16 @@ void InjectedBundlePage::didReceiveResponseForResource(WKBundlePageRef page, WKB stringBuilder.append(toWTFString(urlString)); stringBuilder.appendLiteral(" has MIME type "); stringBuilder.append(toWTFString(mimeTypeString)); + + String platformMimeType = platformResponseMimeType(response); + if (!platformMimeType.isEmpty() && platformMimeType != toWTFString(mimeTypeString)) { + stringBuilder.appendLiteral(" but platform response has "); + stringBuilder.append(platformMimeType); + } + stringBuilder.append('\n'); - InjectedBundle::shared().outputText(stringBuilder.toString()); + + injectedBundle.outputText(stringBuilder.toString()); } void InjectedBundlePage::didReceiveContentLengthForResource(WKBundlePageRef, WKBundleFrameRef, uint64_t, uint64_t) @@ -1140,24 +1226,26 @@ void InjectedBundlePage::didReceiveContentLengthForResource(WKBundlePageRef, WKB void InjectedBundlePage::didFinishLoadForResource(WKBundlePageRef, WKBundleFrameRef, uint64_t identifier) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return; - if (!InjectedBundle::shared().testRunner()->shouldDumpResourceLoadCallbacks()) + if (!injectedBundle.testRunner()->shouldDumpResourceLoadCallbacks()) return; StringBuilder stringBuilder; dumpResourceURL(identifier, stringBuilder); stringBuilder.appendLiteral(" - didFinishLoading\n"); - InjectedBundle::shared().outputText(stringBuilder.toString()); + injectedBundle.outputText(stringBuilder.toString()); } void InjectedBundlePage::didFailLoadForResource(WKBundlePageRef, WKBundleFrameRef, uint64_t identifier, WKErrorRef error) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return; - if (!InjectedBundle::shared().testRunner()->shouldDumpResourceLoadCallbacks()) + if (!injectedBundle.testRunner()->shouldDumpResourceLoadCallbacks()) return; StringBuilder stringBuilder; @@ -1166,21 +1254,22 @@ void InjectedBundlePage::didFailLoadForResource(WKBundlePageRef, WKBundleFrameRe dumpErrorDescriptionSuitableForTestResult(error, stringBuilder); stringBuilder.append('\n'); - InjectedBundle::shared().outputText(stringBuilder.toString()); + injectedBundle.outputText(stringBuilder.toString()); } bool InjectedBundlePage::shouldCacheResponse(WKBundlePageRef, WKBundleFrameRef, uint64_t identifier) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return true; - if (!InjectedBundle::shared().testRunner()->shouldDumpWillCacheResponse()) + if (!injectedBundle.testRunner()->shouldDumpWillCacheResponse()) return true; StringBuilder stringBuilder; stringBuilder.appendNumber(identifier); stringBuilder.appendLiteral(" - willCacheResponse: called\n"); - InjectedBundle::shared().outputText(stringBuilder.toString()); + injectedBundle.outputText(stringBuilder.toString()); // The default behavior is the cache the response. return true; @@ -1211,11 +1300,30 @@ void InjectedBundlePage::unableToImplementPolicy(WKBundlePageRef page, WKBundleF WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForNavigationAction(WKBundlePageRef page, WKBundleFrameRef frame, WKBundleNavigationActionRef navigationAction, WKURLRequestRef request, WKTypeRef* userData) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return WKBundlePagePolicyActionUse; - if (!InjectedBundle::shared().testRunner()->isPolicyDelegateEnabled()) - return WKBundlePagePolicyActionUse; + if (injectedBundle.testRunner()->shouldDumpPolicyCallbacks()) { + StringBuilder stringBuilder; + stringBuilder.appendLiteral(" - decidePolicyForNavigationAction \n"); + dumpRequestDescriptionSuitableForTestResult(request, stringBuilder); + stringBuilder.appendLiteral(" is main frame - "); + stringBuilder.append(WKBundleFrameIsMainFrame(frame) ? "yes" : "no"); + stringBuilder.appendLiteral(" should open URLs externally - "); + stringBuilder.append(WKBundleNavigationActionGetShouldOpenExternalURLs(navigationAction) ? "yes" : "no"); + stringBuilder.append('\n'); + injectedBundle.outputText(stringBuilder.toString()); + } + + if (injectedBundle.testRunner()->shouldDecideNavigationPolicyAfterDelay()) + return WKBundlePagePolicyActionPassThrough; + + if (!injectedBundle.testRunner()->isPolicyDelegateEnabled()) { + WKRetainPtr<WKStringRef> downloadAttributeRef(AdoptWK, WKBundleNavigationActionCopyDownloadAttribute(navigationAction)); + String downloadAttribute = toWTFString(downloadAttributeRef); + return downloadAttribute.isNull() ? WKBundlePagePolicyActionUse : WKBundlePagePolicyActionPassThrough; + } WKRetainPtr<WKURLRef> url = adoptWK(WKURLRequestCopyURL(request)); WKRetainPtr<WKStringRef> urlScheme = adoptWK(WKURLCopyScheme(url.get())); @@ -1239,10 +1347,10 @@ WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForNavigationAction(WKB } stringBuilder.append('\n'); - InjectedBundle::shared().outputText(stringBuilder.toString()); - InjectedBundle::shared().testRunner()->notifyDone(); + injectedBundle.outputText(stringBuilder.toString()); + injectedBundle.testRunner()->notifyDone(); - if (InjectedBundle::shared().testRunner()->isPolicyDelegatePermissive()) + if (injectedBundle.testRunner()->isPolicyDelegatePermissive()) return WKBundlePagePolicyActionUse; return WKBundlePagePolicyActionPassThrough; } @@ -1254,13 +1362,13 @@ WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForNewWindowAction(WKBu WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForResponse(WKBundlePageRef page, WKBundleFrameRef, WKURLResponseRef response, WKURLRequestRef, WKTypeRef*) { - if (WKURLResponseIsAttachment(response)) { + if (InjectedBundle::singleton().testRunner()->isPolicyDelegateEnabled() && WKURLResponseIsAttachment(response)) { StringBuilder stringBuilder; WKRetainPtr<WKStringRef> filename = adoptWK(WKURLResponseCopySuggestedFilename(response)); stringBuilder.appendLiteral("Policy delegate: resource is an attachment, suggested file name \'"); stringBuilder.append(toWTFString(filename)); stringBuilder.appendLiteral("\'\n"); - InjectedBundle::shared().outputText(stringBuilder.toString()); + InjectedBundle::singleton().outputText(stringBuilder.toString()); } WKRetainPtr<WKStringRef> mimeType = adoptWK(WKURLResponseCopyMIMEType(response)); @@ -1330,7 +1438,8 @@ static WTF::String lastFileURLPathComponent(const WTF::String& path) void InjectedBundlePage::willAddMessageToConsole(WKStringRef message, uint32_t lineNumber) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return; WTF::String messageString = toWTFString(message); @@ -1352,46 +1461,53 @@ void InjectedBundlePage::willAddMessageToConsole(WKStringRef message, uint32_t l } stringBuilder.append(messageString); stringBuilder.append('\n'); - InjectedBundle::shared().outputText(stringBuilder.toString()); + + if (injectedBundle.dumpJSConsoleLogInStdErr()) + injectedBundle.dumpToStdErr(stringBuilder.toString()); + else + injectedBundle.outputText(stringBuilder.toString()); } void InjectedBundlePage::willSetStatusbarText(WKStringRef statusbarText) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return; - if (!InjectedBundle::shared().testRunner()->shouldDumpStatusCallbacks()) + if (!injectedBundle.testRunner()->shouldDumpStatusCallbacks()) return; StringBuilder stringBuilder; stringBuilder.appendLiteral("UI DELEGATE STATUS CALLBACK: setStatusText:"); stringBuilder.append(toWTFString(statusbarText)); stringBuilder.append('\n'); - InjectedBundle::shared().outputText(stringBuilder.toString()); + injectedBundle.outputText(stringBuilder.toString()); } void InjectedBundlePage::willRunJavaScriptAlert(WKStringRef message, WKBundleFrameRef) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return; StringBuilder stringBuilder; stringBuilder.appendLiteral("ALERT: "); stringBuilder.append(toWTFString(message)); stringBuilder.append('\n'); - InjectedBundle::shared().outputText(stringBuilder.toString()); + injectedBundle.outputText(stringBuilder.toString()); } void InjectedBundlePage::willRunJavaScriptConfirm(WKStringRef message, WKBundleFrameRef) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return; StringBuilder stringBuilder; stringBuilder.appendLiteral("CONFIRM: "); stringBuilder.append(toWTFString(message)); stringBuilder.append('\n'); - InjectedBundle::shared().outputText(stringBuilder.toString()); + injectedBundle.outputText(stringBuilder.toString()); } void InjectedBundlePage::willRunJavaScriptPrompt(WKStringRef message, WKStringRef defaultValue, WKBundleFrameRef) @@ -1402,12 +1518,13 @@ void InjectedBundlePage::willRunJavaScriptPrompt(WKStringRef message, WKStringRe stringBuilder.appendLiteral(", default text: "); stringBuilder.append(toWTFString(defaultValue)); stringBuilder.append('\n'); - InjectedBundle::shared().outputText(stringBuilder.toString()); + InjectedBundle::singleton().outputText(stringBuilder.toString()); } void InjectedBundlePage::didReachApplicationCacheOriginQuota(WKSecurityOriginRef origin, int64_t totalBytesNeeded) { - if (InjectedBundle::shared().testRunner()->shouldDumpApplicationCacheDelegateCallbacks()) { + auto& injectedBundle = InjectedBundle::singleton(); + if (injectedBundle.testRunner()->shouldDumpApplicationCacheDelegateCallbacks()) { // For example, numbers from 30000 - 39999 will output as 30000. // Rounding up or down does not really matter for these tests. It's // sufficient to just get a range of 10000 to determine if we were @@ -1420,36 +1537,37 @@ void InjectedBundlePage::didReachApplicationCacheOriginQuota(WKSecurityOriginRef stringBuilder.appendLiteral(" totalSpaceNeeded:~"); stringBuilder.appendNumber(truncatedSpaceNeeded); stringBuilder.append('\n'); - InjectedBundle::shared().outputText(stringBuilder.toString()); + injectedBundle.outputText(stringBuilder.toString()); } - if (InjectedBundle::shared().testRunner()->shouldDisallowIncreaseForApplicationCacheQuota()) + if (injectedBundle.testRunner()->shouldDisallowIncreaseForApplicationCacheQuota()) return; // Reset default application cache quota. - WKBundleResetApplicationCacheOriginQuota(InjectedBundle::shared().bundle(), adoptWK(WKSecurityOriginCopyToString(origin)).get()); + WKBundlePageResetApplicationCacheOriginQuota(injectedBundle.page()->page(), adoptWK(WKSecurityOriginCopyToString(origin)).get()); } uint64_t InjectedBundlePage::didExceedDatabaseQuota(WKSecurityOriginRef origin, WKStringRef databaseName, WKStringRef databaseDisplayName, uint64_t currentQuotaBytes, uint64_t currentOriginUsageBytes, uint64_t currentDatabaseUsageBytes, uint64_t expectedUsageBytes) { - if (InjectedBundle::shared().testRunner()->shouldDumpDatabaseCallbacks()) { + auto& injectedBundle = InjectedBundle::singleton(); + if (injectedBundle.testRunner()->shouldDumpDatabaseCallbacks()) { StringBuilder stringBuilder; stringBuilder.appendLiteral("UI DELEGATE DATABASE CALLBACK: exceededDatabaseQuotaForSecurityOrigin:"); stringBuilder.append(securityOriginToStr(origin)); stringBuilder.appendLiteral(" database:"); stringBuilder.append(toWTFString(databaseName)); stringBuilder.append('\n'); - InjectedBundle::shared().outputText(stringBuilder.toString()); + injectedBundle.outputText(stringBuilder.toString()); } uint64_t defaultQuota = 5 * 1024 * 1024; - double testDefaultQuota = InjectedBundle::shared().testRunner()->databaseDefaultQuota(); + double testDefaultQuota = injectedBundle.testRunner()->databaseDefaultQuota(); if (testDefaultQuota >= 0) defaultQuota = testDefaultQuota; unsigned long long newQuota = defaultQuota; - double maxQuota = InjectedBundle::shared().testRunner()->databaseMaxQuota(); + double maxQuota = injectedBundle.testRunner()->databaseMaxQuota(); if (maxQuota >= 0) { if (defaultQuota < expectedUsageBytes && expectedUsageBytes <= maxQuota) { newQuota = expectedUsageBytes; @@ -1458,7 +1576,7 @@ uint64_t InjectedBundlePage::didExceedDatabaseQuota(WKSecurityOriginRef origin, stringBuilder.appendLiteral("UI DELEGATE DATABASE CALLBACK: increased quota to "); stringBuilder.appendNumber(newQuota); stringBuilder.append('\n'); - InjectedBundle::shared().outputText(stringBuilder.toString()); + injectedBundle.outputText(stringBuilder.toString()); } } return newQuota; @@ -1523,37 +1641,40 @@ void InjectedBundlePage::didChangeSelection(WKBundlePageRef page, WKStringRef no bool InjectedBundlePage::shouldBeginEditing(WKBundleRangeHandleRef range) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return true; - if (InjectedBundle::shared().testRunner()->shouldDumpEditingCallbacks()) { + if (injectedBundle.testRunner()->shouldDumpEditingCallbacks()) { StringBuilder stringBuilder; stringBuilder.appendLiteral("EDITING DELEGATE: shouldBeginEditingInDOMRange:"); stringBuilder.append(rangeToStr(m_page, m_world.get(), range)); stringBuilder.append('\n'); - InjectedBundle::shared().outputText(stringBuilder.toString()); + injectedBundle.outputText(stringBuilder.toString()); } - return InjectedBundle::shared().testRunner()->shouldAllowEditing(); + return injectedBundle.testRunner()->shouldAllowEditing(); } bool InjectedBundlePage::shouldEndEditing(WKBundleRangeHandleRef range) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return true; - if (InjectedBundle::shared().testRunner()->shouldDumpEditingCallbacks()) { + if (injectedBundle.testRunner()->shouldDumpEditingCallbacks()) { StringBuilder stringBuilder; stringBuilder.appendLiteral("EDITING DELEGATE: shouldEndEditingInDOMRange:"); stringBuilder.append(rangeToStr(m_page, m_world.get(), range)); stringBuilder.append('\n'); - InjectedBundle::shared().outputText(stringBuilder.toString()); + injectedBundle.outputText(stringBuilder.toString()); } - return InjectedBundle::shared().testRunner()->shouldAllowEditing(); + return injectedBundle.testRunner()->shouldAllowEditing(); } bool InjectedBundlePage::shouldInsertNode(WKBundleNodeHandleRef node, WKBundleRangeHandleRef rangeToReplace, WKInsertActionType action) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return true; static const char* insertactionstring[] = { @@ -1562,7 +1683,7 @@ bool InjectedBundlePage::shouldInsertNode(WKBundleNodeHandleRef node, WKBundleRa "WebViewInsertActionDropped", }; - if (InjectedBundle::shared().testRunner()->shouldDumpEditingCallbacks()) { + if (injectedBundle.testRunner()->shouldDumpEditingCallbacks()) { StringBuilder stringBuilder; stringBuilder.appendLiteral("EDITING DELEGATE: shouldInsertNode:"); stringBuilder.append(dumpPath(m_page, m_world.get(), node)); @@ -1571,14 +1692,15 @@ bool InjectedBundlePage::shouldInsertNode(WKBundleNodeHandleRef node, WKBundleRa stringBuilder.appendLiteral(" givenAction:"); stringBuilder.append(insertactionstring[action]); stringBuilder.append('\n'); - InjectedBundle::shared().outputText(stringBuilder.toString()); + injectedBundle.outputText(stringBuilder.toString()); } - return InjectedBundle::shared().testRunner()->shouldAllowEditing(); + return injectedBundle.testRunner()->shouldAllowEditing(); } bool InjectedBundlePage::shouldInsertText(WKStringRef text, WKBundleRangeHandleRef rangeToReplace, WKInsertActionType action) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return true; static const char *insertactionstring[] = { @@ -1587,7 +1709,7 @@ bool InjectedBundlePage::shouldInsertText(WKStringRef text, WKBundleRangeHandleR "WebViewInsertActionDropped", }; - if (InjectedBundle::shared().testRunner()->shouldDumpEditingCallbacks()) { + if (injectedBundle.testRunner()->shouldDumpEditingCallbacks()) { StringBuilder stringBuilder; stringBuilder.appendLiteral("EDITING DELEGATE: shouldInsertText:"); stringBuilder.append(toWTFString(text)); @@ -1596,29 +1718,31 @@ bool InjectedBundlePage::shouldInsertText(WKStringRef text, WKBundleRangeHandleR stringBuilder.appendLiteral(" givenAction:"); stringBuilder.append(insertactionstring[action]); stringBuilder.append('\n'); - InjectedBundle::shared().outputText(stringBuilder.toString()); + injectedBundle.outputText(stringBuilder.toString()); } - return InjectedBundle::shared().testRunner()->shouldAllowEditing(); + return injectedBundle.testRunner()->shouldAllowEditing(); } bool InjectedBundlePage::shouldDeleteRange(WKBundleRangeHandleRef range) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return true; - if (InjectedBundle::shared().testRunner()->shouldDumpEditingCallbacks()) { + if (injectedBundle.testRunner()->shouldDumpEditingCallbacks()) { StringBuilder stringBuilder; stringBuilder.appendLiteral("EDITING DELEGATE: shouldDeleteDOMRange:"); stringBuilder.append(rangeToStr(m_page, m_world.get(), range)); stringBuilder.append('\n'); - InjectedBundle::shared().outputText(stringBuilder.toString()); + injectedBundle.outputText(stringBuilder.toString()); } - return InjectedBundle::shared().testRunner()->shouldAllowEditing(); + return injectedBundle.testRunner()->shouldAllowEditing(); } bool InjectedBundlePage::shouldChangeSelectedRange(WKBundleRangeHandleRef fromRange, WKBundleRangeHandleRef toRange, WKAffinityType affinity, bool stillSelecting) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return true; static const char *affinitystring[] = { @@ -1630,7 +1754,7 @@ bool InjectedBundlePage::shouldChangeSelectedRange(WKBundleRangeHandleRef fromRa "TRUE" }; - if (InjectedBundle::shared().testRunner()->shouldDumpEditingCallbacks()) { + if (injectedBundle.testRunner()->shouldDumpEditingCallbacks()) { StringBuilder stringBuilder; stringBuilder.appendLiteral("EDITING DELEGATE: shouldChangeSelectedDOMRange:"); stringBuilder.append(rangeToStr(m_page, m_world.get(), fromRange)); @@ -1641,98 +1765,105 @@ bool InjectedBundlePage::shouldChangeSelectedRange(WKBundleRangeHandleRef fromRa stringBuilder.appendLiteral(" stillSelecting:"); stringBuilder.append(boolstring[stillSelecting]); stringBuilder.append('\n'); - InjectedBundle::shared().outputText(stringBuilder.toString()); + injectedBundle.outputText(stringBuilder.toString()); } - return InjectedBundle::shared().testRunner()->shouldAllowEditing(); + return injectedBundle.testRunner()->shouldAllowEditing(); } bool InjectedBundlePage::shouldApplyStyle(WKBundleCSSStyleDeclarationRef style, WKBundleRangeHandleRef range) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return true; - if (InjectedBundle::shared().testRunner()->shouldDumpEditingCallbacks()) { + if (injectedBundle.testRunner()->shouldDumpEditingCallbacks()) { StringBuilder stringBuilder; stringBuilder.appendLiteral("EDITING DELEGATE: shouldApplyStyle:"); stringBuilder.append(styleDecToStr(style)); stringBuilder.appendLiteral(" toElementsInDOMRange:"); stringBuilder.append(rangeToStr(m_page, m_world.get(), range)); stringBuilder.append('\n'); - InjectedBundle::shared().outputText(stringBuilder.toString()); + injectedBundle.outputText(stringBuilder.toString()); } - return InjectedBundle::shared().testRunner()->shouldAllowEditing(); + return injectedBundle.testRunner()->shouldAllowEditing(); } void InjectedBundlePage::didBeginEditing(WKStringRef notificationName) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return; - if (!InjectedBundle::shared().testRunner()->shouldDumpEditingCallbacks()) + if (!injectedBundle.testRunner()->shouldDumpEditingCallbacks()) return; StringBuilder stringBuilder; stringBuilder.appendLiteral("EDITING DELEGATE: webViewDidBeginEditing:"); stringBuilder.append(toWTFString(notificationName)); stringBuilder.append('\n'); - InjectedBundle::shared().outputText(stringBuilder.toString()); + injectedBundle.outputText(stringBuilder.toString()); } void InjectedBundlePage::didEndEditing(WKStringRef notificationName) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return; - if (!InjectedBundle::shared().testRunner()->shouldDumpEditingCallbacks()) + if (!injectedBundle.testRunner()->shouldDumpEditingCallbacks()) return; StringBuilder stringBuilder; stringBuilder.appendLiteral("EDITING DELEGATE: webViewDidEndEditing:"); stringBuilder.append(toWTFString(notificationName)); stringBuilder.append('\n'); - InjectedBundle::shared().outputText(stringBuilder.toString()); + injectedBundle.outputText(stringBuilder.toString()); } void InjectedBundlePage::didChange(WKStringRef notificationName) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return; - if (!InjectedBundle::shared().testRunner()->shouldDumpEditingCallbacks()) + if (!injectedBundle.testRunner()->shouldDumpEditingCallbacks()) return; StringBuilder stringBuilder; stringBuilder.appendLiteral("EDITING DELEGATE: webViewDidChange:"); stringBuilder.append(toWTFString(notificationName)); stringBuilder.append('\n'); - InjectedBundle::shared().outputText(stringBuilder.toString()); + injectedBundle.outputText(stringBuilder.toString()); } void InjectedBundlePage::didChangeSelection(WKStringRef notificationName) { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return; - if (!InjectedBundle::shared().testRunner()->shouldDumpEditingCallbacks()) + if (!injectedBundle.testRunner()->shouldDumpEditingCallbacks()) return; StringBuilder stringBuilder; stringBuilder.appendLiteral("EDITING DELEGATE: webViewDidChangeSelection:"); stringBuilder.append(toWTFString(notificationName)); stringBuilder.append('\n'); - InjectedBundle::shared().outputText(stringBuilder.toString()); + injectedBundle.outputText(stringBuilder.toString()); } #if ENABLE(FULLSCREEN_API) bool InjectedBundlePage::supportsFullScreen(WKBundlePageRef pageRef, WKFullScreenKeyboardRequestType requestType) { - if (InjectedBundle::shared().testRunner()->shouldDumpFullScreenCallbacks()) - InjectedBundle::shared().outputText("supportsFullScreen() == true\n"); + auto& injectedBundle = InjectedBundle::singleton(); + if (injectedBundle.testRunner()->shouldDumpFullScreenCallbacks()) + injectedBundle.outputText("supportsFullScreen() == true\n"); return true; } void InjectedBundlePage::enterFullScreenForElement(WKBundlePageRef pageRef, WKBundleNodeHandleRef elementRef) { - if (InjectedBundle::shared().testRunner()->shouldDumpFullScreenCallbacks()) - InjectedBundle::shared().outputText("enterFullScreenForElement()\n"); + auto& injectedBundle = InjectedBundle::singleton(); + if (injectedBundle.testRunner()->shouldDumpFullScreenCallbacks()) + injectedBundle.outputText("enterFullScreenForElement()\n"); - if (!InjectedBundle::shared().testRunner()->hasCustomFullScreenBehavior()) { + if (!injectedBundle.testRunner()->hasCustomFullScreenBehavior()) { WKBundlePageWillEnterFullScreen(pageRef); WKBundlePageDidEnterFullScreen(pageRef); } @@ -1740,10 +1871,11 @@ void InjectedBundlePage::enterFullScreenForElement(WKBundlePageRef pageRef, WKBu void InjectedBundlePage::exitFullScreenForElement(WKBundlePageRef pageRef, WKBundleNodeHandleRef elementRef) { - if (InjectedBundle::shared().testRunner()->shouldDumpFullScreenCallbacks()) - InjectedBundle::shared().outputText("exitFullScreenForElement()\n"); + auto& injectedBundle = InjectedBundle::singleton(); + if (injectedBundle.testRunner()->shouldDumpFullScreenCallbacks()) + injectedBundle.outputText("exitFullScreenForElement()\n"); - if (!InjectedBundle::shared().testRunner()->hasCustomFullScreenBehavior()) { + if (!injectedBundle.testRunner()->hasCustomFullScreenBehavior()) { WKBundlePageWillExitFullScreen(pageRef); WKBundlePageDidExitFullScreen(pageRef); } @@ -1751,22 +1883,25 @@ void InjectedBundlePage::exitFullScreenForElement(WKBundlePageRef pageRef, WKBun void InjectedBundlePage::beganEnterFullScreen(WKBundlePageRef, WKRect, WKRect) { - if (InjectedBundle::shared().testRunner()->shouldDumpFullScreenCallbacks()) - InjectedBundle::shared().outputText("beganEnterFullScreen()\n"); + auto& injectedBundle = InjectedBundle::singleton(); + if (injectedBundle.testRunner()->shouldDumpFullScreenCallbacks()) + injectedBundle.outputText("beganEnterFullScreen()\n"); } void InjectedBundlePage::beganExitFullScreen(WKBundlePageRef, WKRect, WKRect) { - if (InjectedBundle::shared().testRunner()->shouldDumpFullScreenCallbacks()) - InjectedBundle::shared().outputText("beganExitFullScreen()\n"); + auto& injectedBundle = InjectedBundle::singleton(); + if (injectedBundle.testRunner()->shouldDumpFullScreenCallbacks()) + injectedBundle.outputText("beganExitFullScreen()\n"); } void InjectedBundlePage::closeFullScreen(WKBundlePageRef pageRef) { - if (InjectedBundle::shared().testRunner()->shouldDumpFullScreenCallbacks()) - InjectedBundle::shared().outputText("closeFullScreen()\n"); + auto& injectedBundle = InjectedBundle::singleton(); + if (injectedBundle.testRunner()->shouldDumpFullScreenCallbacks()) + injectedBundle.outputText("closeFullScreen()\n"); - if (!InjectedBundle::shared().testRunner()->hasCustomFullScreenBehavior()) { + if (!injectedBundle.testRunner()->hasCustomFullScreenBehavior()) { WKBundlePageWillExitFullScreen(pageRef); WKBundlePageDidExitFullScreen(pageRef); } @@ -1862,31 +1997,37 @@ void InjectedBundlePage::dumpBackForwardList(StringBuilder& stringBuilder) stringBuilder.appendLiteral("===============================================\n"); } -#if !PLATFORM(MAC) +#if !PLATFORM(COCOA) void InjectedBundlePage::platformDidStartProvisionalLoadForFrame(WKBundleFrameRef) { } + +String InjectedBundlePage::platformResponseMimeType(WKURLResponseRef) +{ + return String(); +} #endif void InjectedBundlePage::frameDidChangeLocation(WKBundleFrameRef frame, bool shouldDump) { - if (frame != InjectedBundle::shared().topLoadingFrame()) + auto& injectedBundle = InjectedBundle::singleton(); + if (frame != injectedBundle.topLoadingFrame()) return; - InjectedBundle::shared().setTopLoadingFrame(0); + injectedBundle.setTopLoadingFrame(nullptr); - if (InjectedBundle::shared().testRunner()->waitToDump()) + if (injectedBundle.testRunner()->waitToDump()) return; - if (InjectedBundle::shared().shouldProcessWorkQueue()) { - InjectedBundle::shared().processWorkQueue(); + if (injectedBundle.shouldProcessWorkQueue()) { + injectedBundle.processWorkQueue(); return; } if (shouldDump) - InjectedBundle::shared().page()->dump(); + injectedBundle.page()->dump(); else - InjectedBundle::shared().done(); + injectedBundle.done(); } } // namespace WTR diff --git a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.h b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.h index f01b50b54..746fc33c5 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.h +++ b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.h @@ -26,9 +26,9 @@ #ifndef InjectedBundlePage_h #define InjectedBundlePage_h -#include <WebKit2/WKBundlePage.h> -#include <WebKit2/WKBundleScriptWorld.h> -#include <WebKit2/WKRetainPtr.h> +#include <WebKit/WKBundlePage.h> +#include <WebKit/WKBundleScriptWorld.h> +#include <WebKit/WKRetainPtr.h> #include <wtf/text/WTFString.h> namespace WTR { @@ -169,6 +169,7 @@ private: void dumpDOMAsWebArchive(WKBundleFrameRef, WTF::StringBuilder&); void platformDidStartProvisionalLoadForFrame(WKBundleFrameRef); + String platformResponseMimeType(WKURLResponseRef); void frameDidChangeLocation(WKBundleFrameRef, bool shouldDump = false); diff --git a/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp b/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp index 2b30f5df6..6f7eb0c07 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp +++ b/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2010-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,20 +33,22 @@ #include "StringFunctions.h" #include "TestController.h" #include <JavaScriptCore/JSCTestRunnerUtils.h> -#include <WebKit2/WKBundle.h> -#include <WebKit2/WKBundleBackForwardList.h> -#include <WebKit2/WKBundleFrame.h> -#include <WebKit2/WKBundleFramePrivate.h> -#include <WebKit2/WKBundleInspector.h> -#include <WebKit2/WKBundleNodeHandlePrivate.h> -#include <WebKit2/WKBundlePage.h> -#include <WebKit2/WKBundlePagePrivate.h> -#include <WebKit2/WKBundlePrivate.h> -#include <WebKit2/WKBundleScriptWorld.h> -#include <WebKit2/WKData.h> -#include <WebKit2/WKRetainPtr.h> -#include <WebKit2/WKSerializedScriptValue.h> -#include <WebKit2/WebKit2_C.h> +#include <WebCore/ResourceLoadObserver.h> +#include <WebKit/WKBundle.h> +#include <WebKit/WKBundleBackForwardList.h> +#include <WebKit/WKBundleFrame.h> +#include <WebKit/WKBundleFramePrivate.h> +#include <WebKit/WKBundleInspector.h> +#include <WebKit/WKBundleNodeHandlePrivate.h> +#include <WebKit/WKBundlePage.h> +#include <WebKit/WKBundlePagePrivate.h> +#include <WebKit/WKBundlePrivate.h> +#include <WebKit/WKBundleScriptWorld.h> +#include <WebKit/WKData.h> +#include <WebKit/WKPagePrivate.h> +#include <WebKit/WKRetainPtr.h> +#include <WebKit/WKSerializedScriptValue.h> +#include <WebKit/WebKit2_C.h> #include <wtf/CurrentTime.h> #include <wtf/HashMap.h> #include <wtf/StdLibExtras.h> @@ -55,11 +57,9 @@ namespace WTR { -const double TestRunner::waitToDumpWatchdogTimerInterval = 30; - -PassRefPtr<TestRunner> TestRunner::create() +Ref<TestRunner> TestRunner::create() { - return adoptRef(new TestRunner); + return adoptRef(*new TestRunner); } TestRunner::TestRunner() @@ -93,10 +93,14 @@ TestRunner::TestRunner() , m_policyDelegatePermissive(false) , m_globalFlag(false) , m_customFullScreenBehavior(false) + , m_timeout(30000) , m_databaseDefaultQuota(-1) , m_databaseMaxQuota(-1) , m_userStyleSheetEnabled(false) , m_userStyleSheetLocation(adoptWK(WKStringCreateWithUTF8CString(""))) +#if PLATFORM(GTK) + , m_waitToDumpWatchdogTimer(RunLoop::main(), this, &TestRunner::waitToDumpWatchdogTimerFired) +#endif { platformInitialize(); } @@ -112,7 +116,7 @@ JSClassRef TestRunner::wrapperClass() void TestRunner::display() { - WKBundlePageRef page = InjectedBundle::shared().page()->page(); + WKBundlePageRef page = InjectedBundle::singleton().page()->page(); WKBundlePageForceRepaint(page); WKBundlePageSetTracksRepaints(page, true); WKBundlePageResetTrackedRepaints(page); @@ -130,7 +134,7 @@ void TestRunner::setCustomPolicyDelegate(bool enabled, bool permissive) m_policyDelegateEnabled = enabled; m_policyDelegatePermissive = permissive; - InjectedBundle::shared().setCustomPolicyDelegate(enabled, permissive); + InjectedBundle::singleton().setCustomPolicyDelegate(enabled, permissive); } void TestRunner::waitForPolicyDelegate() @@ -139,42 +143,58 @@ void TestRunner::waitForPolicyDelegate() waitUntilDone(); } +void TestRunner::waitUntilDownloadFinished() +{ + m_shouldFinishAfterDownload = true; + waitUntilDone(); +} + void TestRunner::waitUntilDone() { m_waitToDump = true; - if (InjectedBundle::shared().useWaitToDumpWatchdogTimer()) + if (InjectedBundle::singleton().useWaitToDumpWatchdogTimer()) initializeWaitToDumpWatchdogTimerIfNeeded(); } void TestRunner::waitToDumpWatchdogTimerFired() { invalidateWaitToDumpWatchdogTimer(); - InjectedBundle::shared().outputText("FAIL: Timed out waiting for notifyDone to be called\n\n"); - InjectedBundle::shared().done(); + auto& injectedBundle = InjectedBundle::singleton(); +#if PLATFORM(COCOA) + char buffer[1024]; + snprintf(buffer, sizeof(buffer), "#PID UNRESPONSIVE - %s (pid %d)\n", getprogname(), getpid()); + injectedBundle.outputText(buffer); +#endif + injectedBundle.outputText("FAIL: Timed out waiting for notifyDone to be called\n\n"); + injectedBundle.done(); } void TestRunner::notifyDone() { - if (!InjectedBundle::shared().isTestRunning()) + auto& injectedBundle = InjectedBundle::singleton(); + if (!injectedBundle.isTestRunning()) return; - if (m_waitToDump && !InjectedBundle::shared().topLoadingFrame()) - InjectedBundle::shared().page()->dump(); + if (m_waitToDump && !injectedBundle.topLoadingFrame()) + injectedBundle.page()->dump(); + + // We don't call invalidateWaitToDumpWatchdogTimer() here, even if we continue to wait for a load to finish. + // The test is still subject to timeout checking - it is better to detect an async timeout inside WebKitTestRunner + // than to let webkitpy do that, because WebKitTestRunner will dump partial results. m_waitToDump = false; } -void TestRunner::setCustomTimeout(int timeout) +unsigned TestRunner::imageCountInGeneralPasteboard() const { - m_timeout = timeout; + return InjectedBundle::singleton().imageCountInGeneralPasteboard(); } void TestRunner::addUserScript(JSStringRef source, bool runAtStart, bool allFrames) { WKRetainPtr<WKStringRef> sourceWK = toWK(source); - WKRetainPtr<WKBundleScriptWorldRef> scriptWorld(AdoptWK, WKBundleScriptWorldCreateWorld()); - WKBundleAddUserScript(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), scriptWorld.get(), sourceWK.get(), 0, 0, 0, + WKBundlePageAddUserScript(InjectedBundle::singleton().page()->page(), sourceWK.get(), (runAtStart ? kWKInjectAtDocumentStart : kWKInjectAtDocumentEnd), (allFrames ? kWKInjectInAllFrames : kWKInjectInTopFrameOnly)); } @@ -182,27 +202,27 @@ void TestRunner::addUserScript(JSStringRef source, bool runAtStart, bool allFram void TestRunner::addUserStyleSheet(JSStringRef source, bool allFrames) { WKRetainPtr<WKStringRef> sourceWK = toWK(source); - WKRetainPtr<WKBundleScriptWorldRef> scriptWorld(AdoptWK, WKBundleScriptWorldCreateWorld()); - WKBundleAddUserStyleSheet(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), scriptWorld.get(), sourceWK.get(), 0, 0, 0, + WKBundlePageAddUserStyleSheet(InjectedBundle::singleton().page()->page(), sourceWK.get(), (allFrames ? kWKInjectInAllFrames : kWKInjectInTopFrameOnly)); } void TestRunner::keepWebHistory() { - WKBundleSetShouldTrackVisitedLinks(InjectedBundle::shared().bundle(), true); + InjectedBundle::singleton().postSetAddsVisitedLinks(true); } void TestRunner::execCommand(JSStringRef name, JSStringRef argument) { - WKBundlePageExecuteEditingCommand(InjectedBundle::shared().page()->page(), toWK(name).get(), toWK(argument).get()); + WKBundlePageExecuteEditingCommand(InjectedBundle::singleton().page()->page(), toWK(name).get(), toWK(argument).get()); } bool TestRunner::findString(JSStringRef target, JSValueRef optionsArrayAsValue) { WKFindOptions options = 0; - WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page()); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(injectedBundle.page()->page()); JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame); JSRetainPtr<JSStringRef> lengthPropertyName(Adopt, JSStringCreateWithUTF8CString("length")); JSObjectRef optionsArray = JSValueToObject(context, optionsArrayAsValue, 0); @@ -233,37 +253,42 @@ bool TestRunner::findString(JSStringRef target, JSValueRef optionsArrayAsValue) } } - return WKBundlePageFindString(InjectedBundle::shared().page()->page(), toWK(target).get(), options); + return WKBundlePageFindString(injectedBundle.page()->page(), toWK(target).get(), options); } void TestRunner::clearAllDatabases() { - WKBundleClearAllDatabases(InjectedBundle::shared().bundle()); + WKBundleClearAllDatabases(InjectedBundle::singleton().bundle()); + + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("DeleteAllIndexedDatabases")); + WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(true)); + + WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr); } void TestRunner::setDatabaseQuota(uint64_t quota) { - return WKBundleSetDatabaseQuota(InjectedBundle::shared().bundle(), quota); + return WKBundleSetDatabaseQuota(InjectedBundle::singleton().bundle(), quota); } void TestRunner::clearAllApplicationCaches() { - WKBundleClearApplicationCache(InjectedBundle::shared().bundle()); + WKBundlePageClearApplicationCache(InjectedBundle::singleton().page()->page()); } void TestRunner::clearApplicationCacheForOrigin(JSStringRef origin) { - WKBundleClearApplicationCacheForOrigin(InjectedBundle::shared().bundle(), toWK(origin).get()); + WKBundlePageClearApplicationCacheForOrigin(InjectedBundle::singleton().page()->page(), toWK(origin).get()); } void TestRunner::setAppCacheMaximumSize(uint64_t size) { - WKBundleSetAppCacheMaximumSize(InjectedBundle::shared().bundle(), size); + WKBundlePageSetAppCacheMaximumSize(InjectedBundle::singleton().page()->page(), size); } long long TestRunner::applicationCacheDiskUsageForOrigin(JSStringRef origin) { - return WKBundleGetAppCacheUsageForOrigin(InjectedBundle::shared().bundle(), toWK(origin).get()); + return WKBundlePageGetAppCacheUsageForOrigin(InjectedBundle::singleton().page()->page(), toWK(origin).get()); } void TestRunner::disallowIncreaseForApplicationCacheQuota() @@ -275,21 +300,24 @@ static inline JSValueRef stringArrayToJS(JSContextRef context, WKArrayRef string { const size_t count = WKArrayGetSize(strings); - auto jsStringsArray = std::make_unique<JSValueRef[]>(count); + JSValueRef arrayResult = JSObjectMakeArray(context, 0, 0, 0); + JSObjectRef arrayObj = JSValueToObject(context, arrayResult, 0); for (size_t i = 0; i < count; ++i) { WKStringRef stringRef = static_cast<WKStringRef>(WKArrayGetItemAtIndex(strings, i)); JSRetainPtr<JSStringRef> stringJS = toJS(stringRef); - jsStringsArray[i] = JSValueMakeString(context, stringJS.get()); + JSObjectSetPropertyAtIndex(context, arrayObj, i, JSValueMakeString(context, stringJS.get()), 0); } - return JSObjectMakeArray(context, count, jsStringsArray.get(), 0); + return arrayResult; } JSValueRef TestRunner::originsWithApplicationCache() { - WKRetainPtr<WKArrayRef> origins(AdoptWK, WKBundleCopyOriginsWithApplicationCache(InjectedBundle::shared().bundle())); + WKBundlePageRef page = InjectedBundle::singleton().page()->page(); + + WKRetainPtr<WKArrayRef> origins(AdoptWK, WKBundlePageCopyOriginsWithApplicationCache(page)); - WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page()); + WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(page); JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame); return stringArrayToJS(context, origins.get()); @@ -297,70 +325,174 @@ JSValueRef TestRunner::originsWithApplicationCache() bool TestRunner::isCommandEnabled(JSStringRef name) { - return WKBundlePageIsEditingCommandEnabled(InjectedBundle::shared().page()->page(), toWK(name).get()); + return WKBundlePageIsEditingCommandEnabled(InjectedBundle::singleton().page()->page(), toWK(name).get()); } void TestRunner::setCanOpenWindows(bool) { - // It's not clear if or why any tests require opening windows be forbidden. - // For now, just ignore this setting, and if we find later it's needed we can add it. + // The test plugins/get-url-with-blank-target.html requires that the embedding client forbid + // opening windows (by omitting a call to this function) so as to test that NPN_GetURL() + // with a blank target will return an error. + // + // It is not clear if we should implement this functionality or remove it and plugins/get-url-with-blank-target.html + // per the remark in <https://trac.webkit.org/changeset/64504/trunk/LayoutTests/platform/mac-wk2/Skipped>. + // For now, just ignore this setting. } void TestRunner::setXSSAuditorEnabled(bool enabled) { WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitXSSAuditorEnabled")); - WKBundleOverrideBoolPreferenceForTestRunner(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), key.get(), enabled); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled); +} + +void TestRunner::setShadowDOMEnabled(bool enabled) +{ + WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitShadowDOMEnabled")); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled); +} + +void TestRunner::setCustomElementsEnabled(bool enabled) +{ + WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitCustomElementsEnabled")); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled); +} + +void TestRunner::setSubtleCryptoEnabled(bool enabled) +{ + WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitSubtleCryptoEnabled")); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled); +} + +void TestRunner::setMediaStreamEnabled(bool enabled) +{ + WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitMediaStreamEnabled")); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled); +} + +void TestRunner::setPeerConnectionEnabled(bool enabled) +{ + WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitPeerConnectionEnabled")); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled); +} + +void TestRunner::setModernMediaControlsEnabled(bool enabled) +{ + WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitModernMediaControlsEnabled")); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled); +} + +void TestRunner::setWebGL2Enabled(bool enabled) +{ + WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitWebGL2Enabled")); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled); +} + +void TestRunner::setFetchAPIEnabled(bool enabled) +{ + WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitFetchAPIEnabled")); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled); +} + +void TestRunner::setDownloadAttributeEnabled(bool enabled) +{ + WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitDownloadAttributeEnabled")); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled); +} + +void TestRunner::setEncryptedMediaAPIEnabled(bool enabled) +{ + WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitEncryptedMediaAPIEnabled")); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled); +} + +void TestRunner::setAllowsAnySSLCertificate(bool enabled) +{ + InjectedBundle::singleton().setAllowsAnySSLCertificate(enabled); } void TestRunner::setAllowUniversalAccessFromFileURLs(bool enabled) { - WKBundleSetAllowUniversalAccessFromFileURLs(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), enabled); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleSetAllowUniversalAccessFromFileURLs(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled); } void TestRunner::setAllowFileAccessFromFileURLs(bool enabled) { - WKBundleSetAllowFileAccessFromFileURLs(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), enabled); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleSetAllowFileAccessFromFileURLs(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled); } +void TestRunner::setNeedsStorageAccessFromFileURLsQuirk(bool needsQuirk) +{ + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleSetAllowStorageAccessFromFileURLS(injectedBundle.bundle(), injectedBundle.pageGroup(), needsQuirk); +} + void TestRunner::setPluginsEnabled(bool enabled) { - WKBundleSetPluginsEnabled(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), enabled); + WKRetainPtr<WKStringRef> key(AdoptWK, WKStringCreateWithUTF8CString("WebKitPluginsEnabled")); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), key.get(), enabled); } void TestRunner::setJavaScriptCanAccessClipboard(bool enabled) { - WKBundleSetJavaScriptCanAccessClipboard(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), enabled); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleSetJavaScriptCanAccessClipboard(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled); } void TestRunner::setPrivateBrowsingEnabled(bool enabled) { - WKBundleSetPrivateBrowsingEnabled(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), enabled); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleSetPrivateBrowsingEnabled(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled); } +void TestRunner::setUseDashboardCompatibilityMode(bool enabled) +{ +#if ENABLE(DASHBOARD_SUPPORT) + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleSetUseDashboardCompatibilityMode(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled); +#endif +} + void TestRunner::setPopupBlockingEnabled(bool enabled) { - WKBundleSetPopupBlockingEnabled(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), enabled); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleSetPopupBlockingEnabled(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled); } void TestRunner::setAuthorAndUserStylesEnabled(bool enabled) { - WKBundleSetAuthorAndUserStylesEnabled(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), enabled); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleSetAuthorAndUserStylesEnabled(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled); } void TestRunner::addOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains) { - WKBundleAddOriginAccessWhitelistEntry(InjectedBundle::shared().bundle(), toWK(sourceOrigin).get(), toWK(destinationProtocol).get(), toWK(destinationHost).get(), allowDestinationSubdomains); + WKBundleAddOriginAccessWhitelistEntry(InjectedBundle::singleton().bundle(), toWK(sourceOrigin).get(), toWK(destinationProtocol).get(), toWK(destinationHost).get(), allowDestinationSubdomains); } void TestRunner::removeOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef destinationProtocol, JSStringRef destinationHost, bool allowDestinationSubdomains) { - WKBundleRemoveOriginAccessWhitelistEntry(InjectedBundle::shared().bundle(), toWK(sourceOrigin).get(), toWK(destinationProtocol).get(), toWK(destinationHost).get(), allowDestinationSubdomains); + WKBundleRemoveOriginAccessWhitelistEntry(InjectedBundle::singleton().bundle(), toWK(sourceOrigin).get(), toWK(destinationProtocol).get(), toWK(destinationHost).get(), allowDestinationSubdomains); } bool TestRunner::isPageBoxVisible(int pageIndex) { - WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page()); - return WKBundleIsPageBoxVisible(InjectedBundle::shared().bundle(), mainFrame, pageIndex); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(injectedBundle.page()->page()); + return WKBundleIsPageBoxVisible(injectedBundle.bundle(), mainFrame, pageIndex); } void TestRunner::setValueForUser(JSContextRef context, JSValueRef element, JSStringRef value) @@ -374,21 +506,22 @@ void TestRunner::setValueForUser(JSContextRef context, JSValueRef element, JSStr void TestRunner::setAudioResult(JSContextRef context, JSValueRef data) { + auto& injectedBundle = InjectedBundle::singleton(); // FIXME (123058): Use a JSC API to get buffer contents once such is exposed. - WKRetainPtr<WKDataRef> audioData(AdoptWK, WKBundleCreateWKDataFromUInt8Array(InjectedBundle::shared().bundle(), context, data)); - InjectedBundle::shared().setAudioResult(audioData.get()); + WKRetainPtr<WKDataRef> audioData(AdoptWK, WKBundleCreateWKDataFromUInt8Array(injectedBundle.bundle(), context, data)); + injectedBundle.setAudioResult(audioData.get()); m_whatToDump = Audio; m_dumpPixels = false; } unsigned TestRunner::windowCount() { - return InjectedBundle::shared().pageCount(); + return InjectedBundle::singleton().pageCount(); } void TestRunner::clearBackForwardList() { - WKBundleBackForwardListClear(WKBundlePageGetBackForwardList(InjectedBundle::shared().page()->page())); + WKBundleBackForwardListClear(WKBundlePageGetBackForwardList(InjectedBundle::singleton().page()->page())); } // Object Creation @@ -400,24 +533,18 @@ void TestRunner::makeWindowObject(JSContextRef context, JSObjectRef windowObject void TestRunner::showWebInspector() { -#if ENABLE(INSPECTOR) - WKBundleInspectorShow(WKBundlePageGetInspector(InjectedBundle::shared().page()->page())); -#endif // ENABLE(INSPECTOR) + WKBundleInspectorShow(WKBundlePageGetInspector(InjectedBundle::singleton().page()->page())); } void TestRunner::closeWebInspector() { -#if ENABLE(INSPECTOR) - WKBundleInspectorClose(WKBundlePageGetInspector(InjectedBundle::shared().page()->page())); -#endif // ENABLE(INSPECTOR) + WKBundleInspectorClose(WKBundlePageGetInspector(InjectedBundle::singleton().page()->page())); } -void TestRunner::evaluateInWebInspector(long callID, JSStringRef script) +void TestRunner::evaluateInWebInspector(JSStringRef script) { -#if ENABLE(INSPECTOR) WKRetainPtr<WKStringRef> scriptWK = toWK(script); - WKBundleInspectorEvaluateScriptForTest(WKBundlePageGetInspector(InjectedBundle::shared().page()->page()), callID, scriptWK.get()); -#endif // ENABLE(INSPECTOR) + WKBundleInspectorEvaluateScriptForTest(WKBundlePageGetInspector(InjectedBundle::singleton().page()->page()), scriptWK.get()); } typedef WTF::HashMap<unsigned, WKRetainPtr<WKBundleScriptWorldRef> > WorldMap; @@ -454,7 +581,7 @@ void TestRunner::evaluateScriptInIsolatedWorld(JSContextRef context, unsigned wo WKBundleFrameRef frame = WKBundleFrameForJavaScriptContext(context); if (!frame) - frame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page()); + frame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page()); JSGlobalContextRef jsContext = WKBundleFrameGetJavaScriptContextForWorld(frame, world.get()); JSEvaluateScript(jsContext, script, 0, 0, 0, 0); @@ -469,35 +596,28 @@ void TestRunner::setPOSIXLocale(JSStringRef locale) void TestRunner::setTextDirection(JSStringRef direction) { - WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page()); + WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page()); return WKBundleFrameSetTextDirection(mainFrame, toWK(direction).get()); } void TestRunner::setShouldStayOnPageAfterHandlingBeforeUnload(bool shouldStayOnPage) { - InjectedBundle::shared().postNewBeforeUnloadReturnValue(!shouldStayOnPage); + InjectedBundle::singleton().postNewBeforeUnloadReturnValue(!shouldStayOnPage); } void TestRunner::setDefersLoading(bool shouldDeferLoading) { - WKBundlePageSetDefersLoading(InjectedBundle::shared().page()->page(), shouldDeferLoading); + WKBundlePageSetDefersLoading(InjectedBundle::singleton().page()->page(), shouldDeferLoading); } void TestRunner::setPageVisibility(JSStringRef state) { - WKPageVisibilityState visibilityState = kWKPageVisibilityStateVisible; - - if (JSStringIsEqualToUTF8CString(state, "hidden")) - visibilityState = kWKPageVisibilityStateHidden; - else if (JSStringIsEqualToUTF8CString(state, "prerender")) - visibilityState = kWKPageVisibilityStatePrerender; - - InjectedBundle::shared().setVisibilityState(visibilityState, false); + InjectedBundle::singleton().setHidden(JSStringIsEqualToUTF8CString(state, "hidden") || JSStringIsEqualToUTF8CString(state, "prerender")); } void TestRunner::resetPageVisibility() { - InjectedBundle::shared().setVisibilityState(kWKPageVisibilityStateVisible, true); + InjectedBundle::singleton().setHidden(false); } typedef WTF::HashMap<unsigned, JSValueRef> CallbackMap; @@ -511,7 +631,13 @@ enum { AddChromeInputFieldCallbackID = 1, RemoveChromeInputFieldCallbackID, FocusWebViewCallbackID, - SetBackingScaleFactorCallbackID + SetBackingScaleFactorCallbackID, + DidBeginSwipeCallbackID, + WillEndSwipeCallbackID, + DidEndSwipeCallbackID, + DidRemoveSwipeSnapshotCallbackID, + StatisticsDidModifyDataRecordsCallbackID, + FirstUIScriptCallbackID = 100 }; static void cacheTestRunnerCallback(unsigned index, JSValueRef callback) @@ -519,50 +645,77 @@ static void cacheTestRunnerCallback(unsigned index, JSValueRef callback) if (!callback) return; - WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page()); + if (callbackMap().contains(index)) { + InjectedBundle::singleton().outputText(String::format("FAIL: Tried to install a second TestRunner callback for the same event (id %d)\n\n", index)); + return; + } + + WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page()); JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame); JSValueProtect(context, callback); callbackMap().add(index, callback); } -static void callTestRunnerCallback(unsigned index) +static void callTestRunnerCallback(unsigned index, size_t argumentCount = 0, const JSValueRef arguments[] = nullptr) { if (!callbackMap().contains(index)) return; - WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page()); + WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page()); JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame); JSObjectRef callback = JSValueToObject(context, callbackMap().take(index), 0); - JSObjectCallAsFunction(context, callback, JSContextGetGlobalObject(context), 0, 0, 0); + JSObjectCallAsFunction(context, callback, JSContextGetGlobalObject(context), argumentCount, arguments, 0); JSValueUnprotect(context, callback); } +void TestRunner::clearTestRunnerCallbacks() +{ + for (auto& iter : callbackMap()) { + WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page()); + JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame); + JSObjectRef callback = JSValueToObject(context, iter.value, 0); + JSValueUnprotect(context, callback); + } + + callbackMap().clear(); +} + +void TestRunner::accummulateLogsForChannel(JSStringRef) +{ + // FIXME: Implement getting the call to all processes. +} + void TestRunner::addChromeInputField(JSValueRef callback) { cacheTestRunnerCallback(AddChromeInputFieldCallbackID, callback); - InjectedBundle::shared().postAddChromeInputField(); + InjectedBundle::singleton().postAddChromeInputField(); } void TestRunner::removeChromeInputField(JSValueRef callback) { cacheTestRunnerCallback(RemoveChromeInputFieldCallbackID, callback); - InjectedBundle::shared().postRemoveChromeInputField(); + InjectedBundle::singleton().postRemoveChromeInputField(); } void TestRunner::focusWebView(JSValueRef callback) { cacheTestRunnerCallback(FocusWebViewCallbackID, callback); - InjectedBundle::shared().postFocusWebView(); + InjectedBundle::singleton().postFocusWebView(); } void TestRunner::setBackingScaleFactor(double backingScaleFactor, JSValueRef callback) { cacheTestRunnerCallback(SetBackingScaleFactorCallbackID, callback); - InjectedBundle::shared().postSetBackingScaleFactor(backingScaleFactor); + InjectedBundle::singleton().postSetBackingScaleFactor(backingScaleFactor); } void TestRunner::setWindowIsKey(bool isKey) { - InjectedBundle::shared().postSetWindowIsKey(isKey); + InjectedBundle::singleton().postSetWindowIsKey(isKey); +} + +void TestRunner::setViewSize(double width, double height) +{ + InjectedBundle::singleton().postSetViewSize(width, height); } void TestRunner::callAddChromeInputFieldCallback() @@ -592,13 +745,18 @@ static inline bool toBool(JSStringRef value) void TestRunner::overridePreference(JSStringRef preference, JSStringRef value) { + auto& injectedBundle = InjectedBundle::singleton(); // FIXME: handle non-boolean preferences. - WKBundleOverrideBoolPreferenceForTestRunner(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), toWK(preference).get(), toBool(value)); + WKBundleOverrideBoolPreferenceForTestRunner(injectedBundle.bundle(), injectedBundle.pageGroup(), toWK(preference).get(), toBool(value)); } void TestRunner::setAlwaysAcceptCookies(bool accept) { - WKBundleSetAlwaysAcceptCookies(InjectedBundle::shared().bundle(), accept); + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetAlwaysAcceptCookies")); + + WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(accept)); + + WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr); } double TestRunner::preciseTime() @@ -612,7 +770,8 @@ void TestRunner::setUserStyleSheetEnabled(bool enabled) WKRetainPtr<WKStringRef> emptyUrl = adoptWK(WKStringCreateWithUTF8CString("")); WKStringRef location = enabled ? m_userStyleSheetLocation.get() : emptyUrl.get(); - WKBundleSetUserStyleSheetLocation(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), location); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleSetUserStyleSheetLocation(injectedBundle.bundle(), injectedBundle.pageGroup(), location); } void TestRunner::setUserStyleSheetLocation(JSStringRef location) @@ -625,68 +784,81 @@ void TestRunner::setUserStyleSheetLocation(JSStringRef location) void TestRunner::setSpatialNavigationEnabled(bool enabled) { - WKBundleSetSpatialNavigationEnabled(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), enabled); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleSetSpatialNavigationEnabled(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled); } void TestRunner::setTabKeyCyclesThroughElements(bool enabled) { - WKBundleSetTabKeyCyclesThroughElements(InjectedBundle::shared().bundle(), InjectedBundle::shared().page()->page(), enabled); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleSetTabKeyCyclesThroughElements(injectedBundle.bundle(), injectedBundle.page()->page(), enabled); } void TestRunner::setSerializeHTTPLoads() { - WKBundleSetSerialLoadingEnabled(InjectedBundle::shared().bundle(), true); + // WK2 doesn't reorder loads. } void TestRunner::dispatchPendingLoadRequests() { - WKBundleDispatchPendingLoadRequests(InjectedBundle::shared().bundle()); + // WK2 doesn't keep pending requests. } void TestRunner::setCacheModel(int model) { - WKBundleSetCacheModel(InjectedBundle::shared().bundle(), model); + InjectedBundle::singleton().setCacheModel(model); } void TestRunner::setAsynchronousSpellCheckingEnabled(bool enabled) { - WKBundleSetAsynchronousSpellCheckingEnabled(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), enabled); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleSetAsynchronousSpellCheckingEnabled(injectedBundle.bundle(), injectedBundle.pageGroup(), enabled); } void TestRunner::grantWebNotificationPermission(JSStringRef origin) { WKRetainPtr<WKStringRef> originWK = toWK(origin); - WKBundleSetWebNotificationPermission(InjectedBundle::shared().bundle(), InjectedBundle::shared().page()->page(), originWK.get(), true); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleSetWebNotificationPermission(injectedBundle.bundle(), injectedBundle.page()->page(), originWK.get(), true); } void TestRunner::denyWebNotificationPermission(JSStringRef origin) { WKRetainPtr<WKStringRef> originWK = toWK(origin); - WKBundleSetWebNotificationPermission(InjectedBundle::shared().bundle(), InjectedBundle::shared().page()->page(), originWK.get(), false); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleSetWebNotificationPermission(injectedBundle.bundle(), injectedBundle.page()->page(), originWK.get(), false); } void TestRunner::removeAllWebNotificationPermissions() { - WKBundleRemoveAllWebNotificationPermissions(InjectedBundle::shared().bundle(), InjectedBundle::shared().page()->page()); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleRemoveAllWebNotificationPermissions(injectedBundle.bundle(), injectedBundle.page()->page()); } void TestRunner::simulateWebNotificationClick(JSValueRef notification) { - WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page()); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(injectedBundle.page()->page()); JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame); - uint64_t notificationID = WKBundleGetWebNotificationID(InjectedBundle::shared().bundle(), context, notification); - InjectedBundle::shared().postSimulateWebNotificationClick(notificationID); + uint64_t notificationID = WKBundleGetWebNotificationID(injectedBundle.bundle(), context, notification); + injectedBundle.postSimulateWebNotificationClick(notificationID); } void TestRunner::setGeolocationPermission(bool enabled) { // FIXME: this should be done by frame. - InjectedBundle::shared().setGeolocationPermission(enabled); + InjectedBundle::singleton().setGeolocationPermission(enabled); +} + +bool TestRunner::isGeolocationProviderActive() +{ + return InjectedBundle::singleton().isGeolocationProviderActive(); } void TestRunner::setMockGeolocationPosition(double latitude, double longitude, double accuracy, JSValueRef jsAltitude, JSValueRef jsAltitudeAccuracy, JSValueRef jsHeading, JSValueRef jsSpeed) { - WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page()); + auto& injectedBundle = InjectedBundle::singleton(); + WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(injectedBundle.page()->page()); JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame); bool providesAltitude = false; @@ -717,38 +889,66 @@ void TestRunner::setMockGeolocationPosition(double latitude, double longitude, d speed = JSValueToNumber(context, jsSpeed, 0); } - InjectedBundle::shared().setMockGeolocationPosition(latitude, longitude, accuracy, providesAltitude, altitude, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed); + injectedBundle.setMockGeolocationPosition(latitude, longitude, accuracy, providesAltitude, altitude, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed); } void TestRunner::setMockGeolocationPositionUnavailableError(JSStringRef message) { WKRetainPtr<WKStringRef> messageWK = toWK(message); - InjectedBundle::shared().setMockGeolocationPositionUnavailableError(messageWK.get()); + InjectedBundle::singleton().setMockGeolocationPositionUnavailableError(messageWK.get()); +} + +void TestRunner::setUserMediaPermission(bool enabled) +{ + // FIXME: this should be done by frame. + InjectedBundle::singleton().setUserMediaPermission(enabled); +} + +void TestRunner::setUserMediaPersistentPermissionForOrigin(bool permission, JSStringRef origin, JSStringRef parentOrigin) +{ + WKRetainPtr<WKStringRef> originWK = toWK(origin); + WKRetainPtr<WKStringRef> parentOriginWK = toWK(parentOrigin); + InjectedBundle::singleton().setUserMediaPersistentPermissionForOrigin(permission, originWK.get(), parentOriginWK.get()); +} + +unsigned TestRunner::userMediaPermissionRequestCountForOrigin(JSStringRef origin, JSStringRef parentOrigin) const +{ + WKRetainPtr<WKStringRef> originWK = toWK(origin); + WKRetainPtr<WKStringRef> parentOriginWK = toWK(parentOrigin); + return InjectedBundle::singleton().userMediaPermissionRequestCountForOrigin(originWK.get(), parentOriginWK.get()); +} + +void TestRunner::resetUserMediaPermissionRequestCountForOrigin(JSStringRef origin, JSStringRef parentOrigin) +{ + WKRetainPtr<WKStringRef> originWK = toWK(origin); + WKRetainPtr<WKStringRef> parentOriginWK = toWK(parentOrigin); + InjectedBundle::singleton().resetUserMediaPermissionRequestCountForOrigin(originWK.get(), parentOriginWK.get()); } bool TestRunner::callShouldCloseOnWebView() { - WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page()); + WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page()); return WKBundleFrameCallShouldCloseOnWebView(mainFrame); } void TestRunner::queueBackNavigation(unsigned howFarBackward) { - InjectedBundle::shared().queueBackNavigation(howFarBackward); + InjectedBundle::singleton().queueBackNavigation(howFarBackward); } void TestRunner::queueForwardNavigation(unsigned howFarForward) { - InjectedBundle::shared().queueForwardNavigation(howFarForward); + InjectedBundle::singleton().queueForwardNavigation(howFarForward); } -void TestRunner::queueLoad(JSStringRef url, JSStringRef target) +void TestRunner::queueLoad(JSStringRef url, JSStringRef target, bool shouldOpenExternalURLs) { - WKRetainPtr<WKURLRef> baseURLWK(AdoptWK, WKBundleFrameCopyURL(WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page()))); + auto& injectedBundle = InjectedBundle::singleton(); + WKRetainPtr<WKURLRef> baseURLWK(AdoptWK, WKBundleFrameCopyURL(WKBundlePageGetMainFrame(injectedBundle.page()->page()))); WKRetainPtr<WKURLRef> urlWK(AdoptWK, WKURLCreateWithBaseURL(baseURLWK.get(), toWTFString(toWK(url)).utf8().data())); WKRetainPtr<WKStringRef> urlStringWK(AdoptWK, WKURLCopyString(urlWK.get())); - InjectedBundle::shared().queueLoad(urlStringWK.get(), toWK(target).get()); + injectedBundle.queueLoad(urlStringWK.get(), toWK(target).get(), shouldOpenExternalURLs); } void TestRunner::queueLoadHTMLString(JSStringRef content, JSStringRef baseURL, JSStringRef unreachableURL) @@ -757,45 +957,59 @@ void TestRunner::queueLoadHTMLString(JSStringRef content, JSStringRef baseURL, J WKRetainPtr<WKStringRef> baseURLWK = baseURL ? toWK(baseURL) : WKRetainPtr<WKStringRef>(); WKRetainPtr<WKStringRef> unreachableURLWK = unreachableURL ? toWK(unreachableURL) : WKRetainPtr<WKStringRef>(); - InjectedBundle::shared().queueLoadHTMLString(contentWK.get(), baseURLWK.get(), unreachableURLWK.get()); + InjectedBundle::singleton().queueLoadHTMLString(contentWK.get(), baseURLWK.get(), unreachableURLWK.get()); } void TestRunner::queueReload() { - InjectedBundle::shared().queueReload(); + InjectedBundle::singleton().queueReload(); } void TestRunner::queueLoadingScript(JSStringRef script) { WKRetainPtr<WKStringRef> scriptWK = toWK(script); - InjectedBundle::shared().queueLoadingScript(scriptWK.get()); + InjectedBundle::singleton().queueLoadingScript(scriptWK.get()); } void TestRunner::queueNonLoadingScript(JSStringRef script) { WKRetainPtr<WKStringRef> scriptWK = toWK(script); - InjectedBundle::shared().queueNonLoadingScript(scriptWK.get()); + InjectedBundle::singleton().queueNonLoadingScript(scriptWK.get()); } +void TestRunner::setRejectsProtectionSpaceAndContinueForAuthenticationChallenges(bool value) +{ + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetRejectsProtectionSpaceAndContinueForAuthenticationChallenges")); + WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value)); + WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get()); +} + void TestRunner::setHandlesAuthenticationChallenges(bool handlesAuthenticationChallenges) { - WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetHandlesAuthenticationChallenge")); + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetHandlesAuthenticationChallenges")); WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(handlesAuthenticationChallenges)); - WKBundlePostMessage(InjectedBundle::shared().bundle(), messageName.get(), messageBody.get()); + WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get()); +} + +void TestRunner::setShouldLogCanAuthenticateAgainstProtectionSpace(bool value) +{ + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetShouldLogCanAuthenticateAgainstProtectionSpace")); + WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value)); + WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get()); } void TestRunner::setAuthenticationUsername(JSStringRef username) { WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetAuthenticationUsername")); WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(username)); - WKBundlePostMessage(InjectedBundle::shared().bundle(), messageName.get(), messageBody.get()); + WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get()); } void TestRunner::setAuthenticationPassword(JSStringRef password) { WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetAuthenticationPassword")); WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(password)); - WKBundlePostMessage(InjectedBundle::shared().bundle(), messageName.get(), messageBody.get()); + WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get()); } bool TestRunner::secureEventInputIsEnabled() const @@ -803,7 +1017,7 @@ bool TestRunner::secureEventInputIsEnabled() const WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SecureEventInputIsEnabled")); WKTypeRef returnData = 0; - WKBundlePostSynchronousMessage(InjectedBundle::shared().bundle(), messageName.get(), 0, &returnData); + WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), 0, &returnData); return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData)); } @@ -811,21 +1025,386 @@ void TestRunner::setBlockAllPlugins(bool shouldBlock) { WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetBlockAllPlugins")); WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(shouldBlock)); - WKBundlePostMessage(InjectedBundle::shared().bundle(), messageName.get(), messageBody.get()); + WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get()); +} + +JSValueRef TestRunner::failNextNewCodeBlock() +{ + WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page()); + JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame); + return JSC::failNextNewCodeBlock(context); } JSValueRef TestRunner::numberOfDFGCompiles(JSValueRef theFunction) { - WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page()); + WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page()); JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame); return JSC::numberOfDFGCompiles(context, theFunction); } JSValueRef TestRunner::neverInlineFunction(JSValueRef theFunction) { - WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page()); + WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page()); JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame); return JSC::setNeverInline(context, theFunction); } +void TestRunner::setShouldDecideNavigationPolicyAfterDelay(bool value) +{ + m_shouldDecideNavigationPolicyAfterDelay = value; + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetShouldDecideNavigationPolicyAfterDelay")); + WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value)); + WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get()); +} + +void TestRunner::setNavigationGesturesEnabled(bool value) +{ + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetNavigationGesturesEnabled")); + WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value)); + WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get()); +} + +void TestRunner::setIgnoresViewportScaleLimits(bool value) +{ + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetIgnoresViewportScaleLimits")); + WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value)); + WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get()); +} + +void TestRunner::setShouldDownloadUndisplayableMIMETypes(bool value) +{ + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetShouldDownloadUndisplayableMIMETypes")); + WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value)); + WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get()); +} + +static unsigned nextUIScriptCallbackID() +{ + static unsigned callbackID = FirstUIScriptCallbackID; + return callbackID++; +} + +void TestRunner::runUIScript(JSStringRef script, JSValueRef callback) +{ + unsigned callbackID = nextUIScriptCallbackID(); + cacheTestRunnerCallback(callbackID, callback); + + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("RunUIProcessScript")); + + WKRetainPtr<WKMutableDictionaryRef> testDictionary(AdoptWK, WKMutableDictionaryCreate()); + + WKRetainPtr<WKStringRef> scriptKey(AdoptWK, WKStringCreateWithUTF8CString("Script")); + WKRetainPtr<WKStringRef> scriptValue(AdoptWK, WKStringCreateWithJSString(script)); + + WKRetainPtr<WKStringRef> callbackIDKey(AdoptWK, WKStringCreateWithUTF8CString("CallbackID")); + WKRetainPtr<WKUInt64Ref> callbackIDValue = adoptWK(WKUInt64Create(callbackID)); + + WKDictionarySetItem(testDictionary.get(), scriptKey.get(), scriptValue.get()); + WKDictionarySetItem(testDictionary.get(), callbackIDKey.get(), callbackIDValue.get()); + + WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), testDictionary.get()); +} + +void TestRunner::runUIScriptCallback(unsigned callbackID, JSStringRef result) +{ + WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page()); + JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame); + + JSValueRef resultValue = JSValueMakeString(context, result); + callTestRunnerCallback(callbackID, 1, &resultValue); +} + +void TestRunner::installDidBeginSwipeCallback(JSValueRef callback) +{ + cacheTestRunnerCallback(DidBeginSwipeCallbackID, callback); +} + +void TestRunner::installWillEndSwipeCallback(JSValueRef callback) +{ + cacheTestRunnerCallback(WillEndSwipeCallbackID, callback); +} + +void TestRunner::installDidEndSwipeCallback(JSValueRef callback) +{ + cacheTestRunnerCallback(DidEndSwipeCallbackID, callback); +} + +void TestRunner::installDidRemoveSwipeSnapshotCallback(JSValueRef callback) +{ + cacheTestRunnerCallback(DidRemoveSwipeSnapshotCallbackID, callback); +} + +void TestRunner::callDidBeginSwipeCallback() +{ + callTestRunnerCallback(DidBeginSwipeCallbackID); +} + +void TestRunner::callWillEndSwipeCallback() +{ + callTestRunnerCallback(WillEndSwipeCallbackID); +} + +void TestRunner::callDidEndSwipeCallback() +{ + callTestRunnerCallback(DidEndSwipeCallbackID); +} + +void TestRunner::callDidRemoveSwipeSnapshotCallback() +{ + callTestRunnerCallback(DidRemoveSwipeSnapshotCallbackID); +} + +void TestRunner::setStatisticsPrevalentResource(JSStringRef hostName, bool value) +{ + Vector<WKRetainPtr<WKStringRef>> keys; + Vector<WKRetainPtr<WKTypeRef>> values; + + keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") }); + values.append({ AdoptWK, WKStringCreateWithJSString(hostName) }); + + keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") }); + values.append({ AdoptWK, WKBooleanCreate(value) }); + + Vector<WKStringRef> rawKeys; + Vector<WKTypeRef> rawValues; + rawKeys.resize(keys.size()); + rawValues.resize(values.size()); + + for (size_t i = 0; i < keys.size(); ++i) { + rawKeys[i] = keys[i].get(); + rawValues[i] = values[i].get(); + } + + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsPrevalentResource")); + WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size())); + + WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr); +} + +bool TestRunner::isStatisticsPrevalentResource(JSStringRef hostName) +{ + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("IsStatisticsPrevalentResource")); + WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(hostName)); + WKTypeRef returnData = 0; + WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData); + return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData)); +} + +void TestRunner::setStatisticsHasHadUserInteraction(JSStringRef hostName, bool value) +{ + Vector<WKRetainPtr<WKStringRef>> keys; + Vector<WKRetainPtr<WKTypeRef>> values; + + keys.append({ AdoptWK, WKStringCreateWithUTF8CString("HostName") }); + values.append({ AdoptWK, WKStringCreateWithJSString(hostName) }); + + keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") }); + values.append({ AdoptWK, WKBooleanCreate(value) }); + + Vector<WKStringRef> rawKeys; + Vector<WKTypeRef> rawValues; + rawKeys.resize(keys.size()); + rawValues.resize(values.size()); + + for (size_t i = 0; i < keys.size(); ++i) { + rawKeys[i] = keys[i].get(); + rawValues[i] = values[i].get(); + } + + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsHasHadUserInteraction")); + WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size())); + + WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr); +} + +bool TestRunner::isStatisticsHasHadUserInteraction(JSStringRef hostName) +{ + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("IsStatisticsHasHadUserInteraction")); + WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(hostName)); + WKTypeRef returnData = 0; + WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData); + return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData)); +} + +void TestRunner::setStatisticsTimeToLiveUserInteraction(double seconds) +{ + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsTimeToLiveUserInteraction")); + WKRetainPtr<WKDoubleRef> messageBody(AdoptWK, WKDoubleCreate(seconds)); + WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr); +} + +void TestRunner::installStatisticsDidModifyDataRecordsCallback(JSValueRef callback) +{ + cacheTestRunnerCallback(StatisticsDidModifyDataRecordsCallbackID, callback); +} + +void TestRunner::statisticsDidModifyDataRecordsCallback() +{ + callTestRunnerCallback(StatisticsDidModifyDataRecordsCallbackID); +} + +void TestRunner::statisticsFireDataModificationHandler() +{ + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsFireDataModificationHandler")); + WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr); +} + +void TestRunner::setStatisticsNotifyPagesWhenDataRecordsWereScanned(bool value) +{ + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsNotifyPagesWhenDataRecordsWereScanned")); + WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value)); + WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr); +} + +void TestRunner::setStatisticsShouldClassifyResourcesBeforeDataRecordsRemoval(bool value) +{ + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsShouldClassifyResourcesBeforeDataRecordsRemoval")); + WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value)); + WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr); +} + +void TestRunner::setStatisticsMinimumTimeBetweeenDataRecordsRemoval(double seconds) +{ + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetStatisticsMinimumTimeBetweeenDataRecordsRemoval")); + WKRetainPtr<WKDoubleRef> messageBody(AdoptWK, WKDoubleCreate(seconds)); + WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr); +} + +void TestRunner::statisticsResetToConsistentState() +{ + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("StatisticsResetToConsistentState")); + WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), 0, nullptr); +} + +#if PLATFORM(MAC) +void TestRunner::connectMockGamepad(unsigned index) +{ + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("ConnectMockGamepad")); + WKRetainPtr<WKTypeRef> messageBody(AdoptWK, WKUInt64Create(index)); + + WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr); +} + +void TestRunner::disconnectMockGamepad(unsigned index) +{ + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("DisconnectMockGamepad")); + WKRetainPtr<WKTypeRef> messageBody(AdoptWK, WKUInt64Create(index)); + + WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr); +} + +void TestRunner::setMockGamepadDetails(unsigned index, JSStringRef gamepadID, unsigned axisCount, unsigned buttonCount) +{ + Vector<WKRetainPtr<WKStringRef>> keys; + Vector<WKRetainPtr<WKTypeRef>> values; + + keys.append({ AdoptWK, WKStringCreateWithUTF8CString("GamepadID") }); + values.append(toWK(gamepadID)); + + keys.append({ AdoptWK, WKStringCreateWithUTF8CString("GamepadIndex") }); + values.append({ AdoptWK, WKUInt64Create(index) }); + + keys.append({ AdoptWK, WKStringCreateWithUTF8CString("AxisCount") }); + values.append({ AdoptWK, WKUInt64Create(axisCount) }); + + keys.append({ AdoptWK, WKStringCreateWithUTF8CString("ButtonCount") }); + values.append({ AdoptWK, WKUInt64Create(buttonCount) }); + + Vector<WKStringRef> rawKeys; + Vector<WKTypeRef> rawValues; + rawKeys.resize(keys.size()); + rawValues.resize(values.size()); + + for (size_t i = 0; i < keys.size(); ++i) { + rawKeys[i] = keys[i].get(); + rawValues[i] = values[i].get(); + } + + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetMockGamepadDetails")); + WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size())); + + WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr); +} + +void TestRunner::setMockGamepadAxisValue(unsigned index, unsigned axisIndex, double value) +{ + Vector<WKRetainPtr<WKStringRef>> keys; + Vector<WKRetainPtr<WKTypeRef>> values; + + keys.append({ AdoptWK, WKStringCreateWithUTF8CString("GamepadIndex") }); + values.append({ AdoptWK, WKUInt64Create(index) }); + + keys.append({ AdoptWK, WKStringCreateWithUTF8CString("AxisIndex") }); + values.append({ AdoptWK, WKUInt64Create(axisIndex) }); + + keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") }); + values.append({ AdoptWK, WKDoubleCreate(value) }); + + Vector<WKStringRef> rawKeys; + Vector<WKTypeRef> rawValues; + rawKeys.resize(keys.size()); + rawValues.resize(values.size()); + + for (size_t i = 0; i < keys.size(); ++i) { + rawKeys[i] = keys[i].get(); + rawValues[i] = values[i].get(); + } + + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetMockGamepadAxisValue")); + WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size())); + + WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr); +} + +void TestRunner::setMockGamepadButtonValue(unsigned index, unsigned buttonIndex, double value) +{ + Vector<WKRetainPtr<WKStringRef>> keys; + Vector<WKRetainPtr<WKTypeRef>> values; + + keys.append({ AdoptWK, WKStringCreateWithUTF8CString("GamepadIndex") }); + values.append({ AdoptWK, WKUInt64Create(index) }); + + keys.append({ AdoptWK, WKStringCreateWithUTF8CString("ButtonIndex") }); + values.append({ AdoptWK, WKUInt64Create(buttonIndex) }); + + keys.append({ AdoptWK, WKStringCreateWithUTF8CString("Value") }); + values.append({ AdoptWK, WKDoubleCreate(value) }); + + Vector<WKStringRef> rawKeys; + Vector<WKTypeRef> rawValues; + rawKeys.resize(keys.size()); + rawValues.resize(values.size()); + + for (size_t i = 0; i < keys.size(); ++i) { + rawKeys[i] = keys[i].get(); + rawValues[i] = values[i].get(); + } + + WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetMockGamepadButtonValue")); + WKRetainPtr<WKDictionaryRef> messageBody(AdoptWK, WKDictionaryCreate(rawKeys.data(), rawValues.data(), rawKeys.size())); + + WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr); +} +#else +void TestRunner::connectMockGamepad(unsigned) +{ +} + +void TestRunner::disconnectMockGamepad(unsigned) +{ +} + +void TestRunner::setMockGamepadDetails(unsigned, JSStringRef, unsigned, unsigned) +{ +} + +void TestRunner::setMockGamepadAxisValue(unsigned, unsigned, double) +{ +} + +void TestRunner::setMockGamepadButtonValue(unsigned, unsigned, double) +{ +} +#endif // PLATFORM(MAC) + } // namespace WTR diff --git a/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h b/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h index cefb6a5d1..764c9e4a9 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h +++ b/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2011, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2010-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,28 +23,28 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef TestRunner_h -#define TestRunner_h +#pragma once #include "JSWrappable.h" +#include "StringFunctions.h" #include <JavaScriptCore/JSRetainPtr.h> -#include <WebKit2/WKBundleScriptWorld.h> -#include <WebKit2/WKRetainPtr.h> +#include <WebKit/WKBundleScriptWorld.h> +#include <WebKit/WKRetainPtr.h> #include <string> -#include <wtf/PassRefPtr.h> +#include <wtf/Ref.h> +#include <wtf/text/WTFString.h> -#if PLATFORM(MAC) +#if PLATFORM(COCOA) #include <wtf/RetainPtr.h> #include <CoreFoundation/CFRunLoop.h> typedef RetainPtr<CFRunLoopTimerRef> PlatformTimerRef; #elif PLATFORM(GTK) -typedef unsigned int PlatformTimerRef; +#include <wtf/RunLoop.h> +namespace WTR { +class TestRunner; +typedef RunLoop::Timer<TestRunner> PlatformTimerRef; +} #elif PLATFORM(EFL) -#if USE(EO) -typedef struct _Eo_Opaque Ecore_Timer; -#else -typedef struct _Ecore_Timer Ecore_Timer; -#endif typedef Ecore_Timer* PlatformTimerRef; #endif @@ -52,7 +52,7 @@ namespace WTR { class TestRunner : public JSWrappable { public: - static PassRefPtr<TestRunner> create(); + static Ref<TestRunner> create(); virtual ~TestRunner(); // JSWrappable @@ -60,13 +60,19 @@ public: void makeWindowObject(JSContextRef, JSObjectRef windowObject, JSValueRef* exception); + bool isWebKit2() const { return true; } + // The basics. + WKURLRef testURL() const { return m_testURL.get(); } + void setTestURL(WKURLRef url) { m_testURL = url; } void dumpAsText(bool dumpPixels); void waitForPolicyDelegate(); void dumpChildFramesAsText() { m_whatToDump = AllFramesText; } + void waitUntilDownloadFinished(); void waitUntilDone(); void notifyDone(); double preciseTime(); + double timeout() { return m_timeout; } // Other dumping. void dumpBackForwardList() { m_shouldDumpBackForwardListsForAllWindows = true; } @@ -84,6 +90,7 @@ public: void dumpApplicationCacheDelegateCallbacks() { m_dumpApplicationCacheDelegateCallbacks = true; } void dumpDatabaseCallbacks() { m_dumpDatabaseCallbacks = true; } void dumpDOMAsWebArchive() { m_whatToDump = DOMAsWebArchive; } + void dumpPolicyDelegateCallbacks() { m_dumpPolicyCallbacks = true; } void setShouldDumpFrameLoadCallbacks(bool value) { m_dumpFrameLoadCallbacks = value; } void setShouldDumpProgressFinishedCallback(bool value) { m_dumpProgressFinishedCallback = value; } @@ -94,11 +101,18 @@ public: void setCanOpenWindows(bool); void setCloseRemainingWindowsWhenComplete(bool value) { m_shouldCloseExtraWindows = value; } void setXSSAuditorEnabled(bool); + void setShadowDOMEnabled(bool); + void setCustomElementsEnabled(bool); + void setModernMediaControlsEnabled(bool); + void setWebGL2Enabled(bool); + void setFetchAPIEnabled(bool); void setAllowUniversalAccessFromFileURLs(bool); void setAllowFileAccessFromFileURLs(bool); + void setNeedsStorageAccessFromFileURLsQuirk(bool); void setPluginsEnabled(bool); void setJavaScriptCanAccessClipboard(bool); void setPrivateBrowsingEnabled(bool); + void setUseDashboardCompatibilityMode(bool); void setPopupBlockingEnabled(bool); void setAuthorAndUserStylesEnabled(bool); void setCustomPolicyDelegate(bool enabled, bool permissive = false); @@ -112,6 +126,12 @@ public: void dispatchPendingLoadRequests(); void setCacheModel(int); void setAsynchronousSpellCheckingEnabled(bool); + void setDownloadAttributeEnabled(bool); + void setAllowsAnySSLCertificate(bool); + void setEncryptedMediaAPIEnabled(bool); + void setSubtleCryptoEnabled(bool); + void setMediaStreamEnabled(bool); + void setPeerConnectionEnabled(bool); // Special DOM functions. void clearBackForwardList(); @@ -151,7 +171,9 @@ public: void setPrinting() { m_isPrinting = true; } // Authentication + void setRejectsProtectionSpaceAndContinueForAuthenticationChallenges(bool); void setHandlesAuthenticationChallenges(bool); + void setShouldLogCanAuthenticateAgainstProtectionSpace(bool); void setAuthenticationUsername(JSStringRef); void setAuthenticationPassword(JSStringRef); @@ -181,6 +203,7 @@ public: bool shouldDumpApplicationCacheDelegateCallbacks() const { return m_dumpApplicationCacheDelegateCallbacks; } bool shouldDumpDatabaseCallbacks() const { return m_dumpDatabaseCallbacks; } bool shouldDumpSelectionRect() const { return m_dumpSelectionRect; } + bool shouldDumpPolicyCallbacks() const { return m_dumpPolicyCallbacks; } bool isPolicyDelegateEnabled() const { return m_policyDelegateEnabled; } bool isPolicyDelegatePermissive() const { return m_policyDelegatePermissive; } @@ -188,6 +211,7 @@ public: bool waitToDump() const { return m_waitToDump; } void waitToDumpWatchdogTimerFired(); void invalidateWaitToDumpWatchdogTimer(); + bool shouldFinishAfterDownload() const { return m_shouldFinishAfterDownload; } bool shouldAllowEditing() const { return m_shouldAllowEditing; } @@ -198,7 +222,8 @@ public: void showWebInspector(); void closeWebInspector(); - void evaluateInWebInspector(long callId, JSStringRef script); + void evaluateInWebInspector(JSStringRef script); + JSRetainPtr<JSStringRef> inspectorTestStubURL(); void setPOSIXLocale(JSStringRef); @@ -206,6 +231,8 @@ public: void setWillSendRequestReturnsNull(bool f) { m_willSendRequestReturnsNull = f; } bool willSendRequestReturnsNullOnRedirect() const { return m_willSendRequestReturnsNullOnRedirect; } void setWillSendRequestReturnsNullOnRedirect(bool f) { m_willSendRequestReturnsNullOnRedirect = f; } + void setWillSendRequestAddsHTTPBody(JSStringRef body) { m_willSendRequestHTTPBody = toWTFString(toWK(body)); } + String willSendRequestHTTPBody() const { return m_willSendRequestHTTPBody; } void setTextDirection(JSStringRef); @@ -232,6 +259,8 @@ public: void setWindowIsKey(bool); + void setViewSize(double width, double height); + void callAddChromeInputFieldCallback(); void callRemoveChromeInputFieldCallback(); void callFocusWebViewCallback(); @@ -247,45 +276,98 @@ public: bool hasCustomFullScreenBehavior() const { return m_customFullScreenBehavior; } // Web notifications. - void grantWebNotificationPermission(JSStringRef origin); - void denyWebNotificationPermission(JSStringRef origin); - void removeAllWebNotificationPermissions(); - void simulateWebNotificationClick(JSValueRef notification); + static void grantWebNotificationPermission(JSStringRef origin); + static void denyWebNotificationPermission(JSStringRef origin); + static void removeAllWebNotificationPermissions(); + static void simulateWebNotificationClick(JSValueRef notification); // Geolocation. void setGeolocationPermission(bool); void setMockGeolocationPosition(double latitude, double longitude, double accuracy, JSValueRef altitude, JSValueRef altitudeAccuracy, JSValueRef heading, JSValueRef speed); void setMockGeolocationPositionUnavailableError(JSStringRef message); + bool isGeolocationProviderActive(); + + // MediaStream + void setUserMediaPermission(bool); + void setUserMediaPersistentPermissionForOrigin(bool permission, JSStringRef origin, JSStringRef parentOrigin); + unsigned userMediaPermissionRequestCountForOrigin(JSStringRef origin, JSStringRef parentOrigin) const; + void resetUserMediaPermissionRequestCountForOrigin(JSStringRef origin, JSStringRef parentOrigin); void setPageVisibility(JSStringRef state); void resetPageVisibility(); bool callShouldCloseOnWebView(); - void setCustomTimeout(int duration); + void setCustomTimeout(int duration) { m_timeout = duration; } // Work queue. void queueBackNavigation(unsigned howFarBackward); void queueForwardNavigation(unsigned howFarForward); - void queueLoad(JSStringRef url, JSStringRef target); + void queueLoad(JSStringRef url, JSStringRef target, bool shouldOpenExternalURLs); void queueLoadHTMLString(JSStringRef content, JSStringRef baseURL, JSStringRef unreachableURL); void queueReload(); void queueLoadingScript(JSStringRef script); void queueNonLoadingScript(JSStringRef script); bool secureEventInputIsEnabled() const; - + + JSValueRef failNextNewCodeBlock(); JSValueRef numberOfDFGCompiles(JSValueRef theFunction); JSValueRef neverInlineFunction(JSValueRef theFunction); -private: - static const double waitToDumpWatchdogTimerInterval; + bool shouldDecideNavigationPolicyAfterDelay() const { return m_shouldDecideNavigationPolicyAfterDelay; } + void setShouldDecideNavigationPolicyAfterDelay(bool); + void setNavigationGesturesEnabled(bool); + void setIgnoresViewportScaleLimits(bool); + void setShouldDownloadUndisplayableMIMETypes(bool); + + void runUIScript(JSStringRef script, JSValueRef callback); + void runUIScriptCallback(unsigned callbackID, JSStringRef result); + + void installDidBeginSwipeCallback(JSValueRef); + void installWillEndSwipeCallback(JSValueRef); + void installDidEndSwipeCallback(JSValueRef); + void installDidRemoveSwipeSnapshotCallback(JSValueRef); + void callDidBeginSwipeCallback(); + void callWillEndSwipeCallback(); + void callDidEndSwipeCallback(); + void callDidRemoveSwipeSnapshotCallback(); + + void clearTestRunnerCallbacks(); + void accummulateLogsForChannel(JSStringRef channel); + + unsigned imageCountInGeneralPasteboard() const; + + // Gamepads + void connectMockGamepad(unsigned index); + void disconnectMockGamepad(unsigned index); + void setMockGamepadDetails(unsigned index, JSStringRef gamepadID, unsigned axisCount, unsigned buttonCount); + void setMockGamepadAxisValue(unsigned index, unsigned axisIndex, double value); + void setMockGamepadButtonValue(unsigned index, unsigned buttonIndex, double value); + + // Resource Load Statistics + void installStatisticsDidModifyDataRecordsCallback(JSValueRef callback); + void statisticsDidModifyDataRecordsCallback(); + void statisticsFireDataModificationHandler(); + void setStatisticsPrevalentResource(JSStringRef hostName, bool value); + bool isStatisticsPrevalentResource(JSStringRef hostName); + void setStatisticsHasHadUserInteraction(JSStringRef hostName, bool value); + bool isStatisticsHasHadUserInteraction(JSStringRef hostName); + void setStatisticsTimeToLiveUserInteraction(double seconds); + void setStatisticsNotifyPagesWhenDataRecordsWereScanned(bool); + void setStatisticsShouldClassifyResourcesBeforeDataRecordsRemoval(bool); + void setStatisticsMinimumTimeBetweeenDataRecordsRemoval(double); + void statisticsResetToConsistentState(); + +private: TestRunner(); void platformInitialize(); void initializeWaitToDumpWatchdogTimerIfNeeded(); + WKRetainPtr<WKURLRef> m_testURL; // Set by InjectedBundlePage once provisional load starts. + WhatToDump m_whatToDump; bool m_shouldDumpAllFrameScrollPositions; bool m_shouldDumpBackForwardListsForAllWindows; @@ -306,6 +388,7 @@ private: bool m_dumpWillCacheResponse; bool m_dumpApplicationCacheDelegateCallbacks; bool m_dumpDatabaseCallbacks; + bool m_dumpPolicyCallbacks { false }; bool m_disallowIncreaseForApplicationCacheQuota; bool m_waitToDump; // True if waitUntilDone() has been called, but notifyDone() has not yet been called. bool m_testRepaint; @@ -315,6 +398,7 @@ private: bool m_willSendRequestReturnsNull; bool m_willSendRequestReturnsNullOnRedirect; bool m_shouldStopProvisionalFrameLoads; + String m_willSendRequestHTTPBody; bool m_policyDelegateEnabled; bool m_policyDelegatePermissive; @@ -327,12 +411,17 @@ private: double m_databaseDefaultQuota; double m_databaseMaxQuota; + bool m_shouldDecideNavigationPolicyAfterDelay { false }; + bool m_shouldFinishAfterDownload { false }; + bool m_userStyleSheetEnabled; WKRetainPtr<WKStringRef> m_userStyleSheetLocation; + WKRetainPtr<WKArrayRef> m_allowedHosts; + + size_t m_userMediaPermissionRequestCount { 0 }; + PlatformTimerRef m_waitToDumpWatchdogTimer; }; } // namespace WTR - -#endif // TestRunner_h diff --git a/Tools/WebKitTestRunner/InjectedBundle/TextInputController.cpp b/Tools/WebKitTestRunner/InjectedBundle/TextInputController.cpp index 0087aa301..2e304e28c 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/TextInputController.cpp +++ b/Tools/WebKitTestRunner/InjectedBundle/TextInputController.cpp @@ -30,13 +30,13 @@ #include "InjectedBundlePage.h" #include "JSTextInputController.h" #include "StringFunctions.h" -#include <WebKit2/WKBundlePagePrivate.h> +#include <WebKit/WKBundlePagePrivate.h> namespace WTR { -PassRefPtr<TextInputController> TextInputController::create() +Ref<TextInputController> TextInputController::create() { - return adoptRef(new TextInputController); + return adoptRef(*new TextInputController); } TextInputController::TextInputController() @@ -59,22 +59,22 @@ void TextInputController::makeWindowObject(JSContextRef context, JSObjectRef win void TextInputController::setMarkedText(JSStringRef text, int from, int length) { - WKBundlePageSetComposition(InjectedBundle::shared().page()->page(), toWK(text).get(), from, length); + WKBundlePageSetComposition(InjectedBundle::singleton().page()->page(), toWK(text).get(), from, length); } bool TextInputController::hasMarkedText() { - return WKBundlePageHasComposition(InjectedBundle::shared().page()->page()); + return WKBundlePageHasComposition(InjectedBundle::singleton().page()->page()); } void TextInputController::unmarkText() { - WKBundlePageConfirmComposition(InjectedBundle::shared().page()->page()); + WKBundlePageConfirmComposition(InjectedBundle::singleton().page()->page()); } void TextInputController::insertText(JSStringRef text) { - WKBundlePageConfirmCompositionWithText(InjectedBundle::shared().page()->page(), toWK(text).get()); + WKBundlePageConfirmCompositionWithText(InjectedBundle::singleton().page()->page(), toWK(text).get()); } } // namespace WTR diff --git a/Tools/WebKitTestRunner/InjectedBundle/TextInputController.h b/Tools/WebKitTestRunner/InjectedBundle/TextInputController.h index 71a043752..ed174816f 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/TextInputController.h +++ b/Tools/WebKitTestRunner/InjectedBundle/TextInputController.h @@ -23,17 +23,16 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef TextInputController_h -#define TextInputController_h +#pragma once #include "JSWrappable.h" -#include <wtf/PassRefPtr.h> +#include <wtf/Ref.h> namespace WTR { class TextInputController : public JSWrappable { public: - static PassRefPtr<TextInputController> create(); + static Ref<TextInputController> create(); virtual ~TextInputController(); // JSWrappable @@ -51,5 +50,3 @@ private: }; } // namespace WTR - -#endif // TextInputController_h diff --git a/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityControllerAtk.cpp b/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityControllerAtk.cpp index 3573a2a5c..a1a554a9d 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityControllerAtk.cpp +++ b/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityControllerAtk.cpp @@ -33,35 +33,14 @@ #include "InjectedBundle.h" #include "InjectedBundlePage.h" -#include <WebKit2/WKBundlePagePrivate.h> +#include <WebKit/WKBundlePagePrivate.h> #include <atk/atk.h> #include <cstdio> -#include <wtf/gobject/GUniquePtr.h> +#include <wtf/glib/GUniquePtr.h> #include <wtf/text/StringBuilder.h> namespace WTR { -void AccessibilityController::logAccessibilityEvents() -{ - // Ensure no callbacks are connected before. - resetToConsistentState(); - - // Ensure that accessibility is initialized for the WebView by querying for - // the root accessible object, which will create the full hierarchy. - rootElement(); - - if (!m_globalNotificationHandler) - m_globalNotificationHandler = AccessibilityNotificationHandler::create(); - m_globalNotificationHandler->logAccessibilityEvents(); - - // 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, nullptr)); - AtkObject* dummyNoOpAxObject = atk_no_op_object_new(dummyAxObject); - g_object_unref(G_OBJECT(dummyNoOpAxObject)); - g_object_unref(dummyAxObject); -} - void AccessibilityController::resetToConsistentState() { m_globalNotificationHandler = nullptr; @@ -97,9 +76,9 @@ static AtkObject* childElementById(AtkObject* parent, const char* id) return nullptr; } -PassRefPtr<AccessibilityUIElement> AccessibilityController::accessibleElementById(JSStringRef id) +RefPtr<AccessibilityUIElement> AccessibilityController::accessibleElementById(JSStringRef id) { - AtkObject* root = ATK_OBJECT(WKAccessibilityRootObject(InjectedBundle::shared().page()->page())); + AtkObject* root = ATK_OBJECT(WKAccessibilityRootObject(InjectedBundle::singleton().page()->page())); if (!root) return nullptr; @@ -120,17 +99,17 @@ JSRetainPtr<JSStringRef> AccessibilityController::platformName() return platformName; } -PassRefPtr<AccessibilityUIElement> AccessibilityController::rootElement() +Ref<AccessibilityUIElement> AccessibilityController::rootElement() { - WKBundlePageRef page = InjectedBundle::shared().page()->page(); + WKBundlePageRef page = InjectedBundle::singleton().page()->page(); void* root = WKAccessibilityRootObject(page); return AccessibilityUIElement::create(static_cast<AtkObject*>(root)); } -PassRefPtr<AccessibilityUIElement> AccessibilityController::focusedElement() +Ref<AccessibilityUIElement> AccessibilityController::focusedElement() { - WKBundlePageRef page = InjectedBundle::shared().page()->page(); + WKBundlePageRef page = InjectedBundle::singleton().page()->page(); void* root = WKAccessibilityFocusedObject(page); return AccessibilityUIElement::create(static_cast<AtkObject*>(root)); diff --git a/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.cpp b/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.cpp index b6af081c2..bb2280877 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.cpp +++ b/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.cpp @@ -25,12 +25,12 @@ #include "InjectedBundle.h" #include "InjectedBundlePage.h" #include "JSWrapper.h" -#include <WebKit2/WKBundleFrame.h> -#include <WebKit2/WKBundlePage.h> -#include <WebKit2/WKBundlePagePrivate.h> +#include <WebKit/WKBundleFrame.h> +#include <WebKit/WKBundlePage.h> +#include <WebKit/WKBundlePagePrivate.h> #include <wtf/HashMap.h> #include <wtf/Vector.h> -#include <wtf/gobject/GUniquePtr.h> +#include <wtf/glib/GUniquePtr.h> #include <wtf/text/CString.h> #include <wtf/text/WTFString.h> @@ -43,29 +43,6 @@ typedef HashMap<AtkObject*, AccessibilityNotificationHandler*> NotificationHandl WTF::Vector<unsigned> listenerIds; NotificationHandlersMap notificationHandlers; AccessibilityNotificationHandler* globalNotificationHandler = nullptr; -bool loggingAccessibilityEvents = false; - -void printAccessibilityEvent(AtkObject* accessible, const char* signalName, const char* 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 char* 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<char> signalNameAndValue(signalValue ? g_strdup_printf("%s = %s", signalName, signalValue) : g_strdup(signalName)); - GUniquePtr<char> accessibilityEventString(g_strdup_printf("Accessibility object emitted \"%s\" / Name: \"%s\" / Role: %d\n", signalNameAndValue.get(), objectName, objectRole)); - InjectedBundle::shared().outputText(String::fromUTF8(accessibilityEventString.get())); -} gboolean axObjectEventListener(GSignalInvocationHint* signalHint, unsigned numParamValues, const GValue* paramValues, gpointer data) { @@ -78,7 +55,7 @@ gboolean axObjectEventListener(GSignalInvocationHint* signalHint, unsigned numPa return true; #if PLATFORM(GTK) || PLATFORM(EFL) - WKBundlePageRef page = InjectedBundle::shared().page()->page(); + WKBundlePageRef page = InjectedBundle::singleton().page()->page(); WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(page); JSContextRef jsContext = WKBundleFrameGetJavaScriptContext(mainFrame); #else @@ -86,47 +63,39 @@ gboolean axObjectEventListener(GSignalInvocationHint* signalHint, unsigned numPa #endif GSignalQuery signalQuery; - GUniquePtr<char> signalName; - GUniquePtr<char> signalValue; const char* notificationName = nullptr; Vector<JSValueRef> extraArgs; 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, "selection-changed")) { + notificationName = "AXSelectedChildrenChanged"; } 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"; + gpointer child = g_value_get_pointer(¶mValues[2]); + if (ATK_IS_OBJECT(child)) + extraArgs.append(toJS(jsContext, WTF::getPtr(WTR::AccessibilityUIElement::create(ATK_OBJECT(child))))); } 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 if (!g_strcmp0(signalQuery.signal_name, "text-caret-moved")) { notificationName = "AXTextCaretMoved"; - signalName.reset(g_strdup(signalQuery.signal_name)); - signalValue.reset(g_strdup_printf("%d", g_value_get_int(¶mValues[1]))); + GUniquePtr<char> signalValue(g_strdup_printf("%d", g_value_get_int(¶mValues[1]))); JSRetainPtr<JSStringRef> jsSignalValue(Adopt, JSStringCreateWithUTF8CString(signalValue.get())); extraArgs.append(JSValueMakeString(jsContext, jsSignalValue.get())); - } else - signalName.reset(g_strdup(signalQuery.signal_name)); - - if (loggingAccessibilityEvents) - printAccessibilityEvent(accessible, signalName.get(), signalValue.get()); + } else if (!g_strcmp0(signalQuery.signal_name, "text-insert") || !g_strcmp0(signalQuery.signal_name, "text-remove")) + notificationName = "AXTextChanged"; if (!jsContext) return true; @@ -174,12 +143,6 @@ AccessibilityNotificationHandler::~AccessibilityNotificationHandler() disconnectAccessibilityCallbacks(); } -void AccessibilityNotificationHandler::logAccessibilityEvents() -{ - connectAccessibilityCallbacks(); - loggingAccessibilityEvents = true; -} - void AccessibilityNotificationHandler::setNotificationFunctionCallback(JSValueRef notificationFunctionCallback) { if (!notificationFunctionCallback) { @@ -191,7 +154,7 @@ void AccessibilityNotificationHandler::setNotificationFunctionCallback(JSValueRe m_notificationFunctionCallback = notificationFunctionCallback; #if PLATFORM(GTK) || PLATFORM(EFL) - WKBundlePageRef page = InjectedBundle::shared().page()->page(); + WKBundlePageRef page = InjectedBundle::singleton().page()->page(); WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(page); JSContextRef jsContext = WKBundleFrameGetJavaScriptContext(mainFrame); #else @@ -222,7 +185,7 @@ void AccessibilityNotificationHandler::setNotificationFunctionCallback(JSValueRe void AccessibilityNotificationHandler::removeAccessibilityNotificationHandler() { #if PLATFORM(GTK) || PLATFORM(EFL) - WKBundlePageRef page = InjectedBundle::shared().page()->page(); + WKBundlePageRef page = InjectedBundle::singleton().page()->page(); WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(page); JSContextRef jsContext = WKBundleFrameGetJavaScriptContext(mainFrame); #else @@ -257,7 +220,10 @@ void AccessibilityNotificationHandler::connectAccessibilityCallbacks() "ATK:AtkObject:property-change", "ATK:AtkObject:visible-data-changed", "ATK:AtkDocument:load-complete", + "ATK:AtkSelection:selection-changed", "ATK:AtkText:text-caret-moved", + "ATK:AtkText:text-insert", + "ATK:AtkText:text-remove", 0 }; @@ -271,7 +237,7 @@ void AccessibilityNotificationHandler::connectAccessibilityCallbacks() unsigned id = atk_add_global_event_listener(axObjectEventListener, *signalName); if (!id) { String message = String::format("atk_add_global_event_listener failed for signal %s\n", *signalName); - InjectedBundle::shared().outputText(message); + InjectedBundle::singleton().outputText(message); continue; } diff --git a/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.h b/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.h index 3443bce2c..da5d8ecdd 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.h +++ b/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.h @@ -17,32 +17,29 @@ * Boston, MA 02110-1301, USA. */ -#ifndef AccessibilityNotificationHandlerAtk_h -#define AccessibilityNotificationHandlerAtk_h +#pragma once #if HAVE(ACCESSIBILITY) #include <JavaScriptCore/JSObjectRef.h> #include <atk/atk.h> #include <atk/atkobject.h> -#include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> -#include <wtf/gobject/GRefPtr.h> +#include <wtf/glib/GRefPtr.h> namespace WTR { class AccessibilityNotificationHandler : public RefCounted<AccessibilityNotificationHandler> { public: - static PassRefPtr<AccessibilityNotificationHandler> create() + static Ref<AccessibilityNotificationHandler> create() { - return adoptRef(new AccessibilityNotificationHandler()); + return adoptRef(*new AccessibilityNotificationHandler()); } ~AccessibilityNotificationHandler(); void setPlatformElement(GRefPtr<AtkObject> platformElement) { m_platformElement = platformElement; } GRefPtr<AtkObject> platformElement() const { return m_platformElement; } void setNotificationFunctionCallback(JSValueRef); JSValueRef notificationFunctionCallback() const { return m_notificationFunctionCallback; } - void logAccessibilityEvents(); private: AccessibilityNotificationHandler(); @@ -57,5 +54,3 @@ private: } // namespace WTR #endif // HAVE(ACCESSIBILITY) - -#endif // AccessibilityNotificationHandlerAtk_h diff --git a/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityUIElementAtk.cpp b/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityUIElementAtk.cpp index 440377937..7ecf65a29 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityUIElementAtk.cpp +++ b/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityUIElementAtk.cpp @@ -35,10 +35,13 @@ #include "NotImplemented.h" #include <JavaScriptCore/JSStringRef.h> #include <JavaScriptCore/OpaqueJSString.h> +#if ATK_CHECK_VERSION(2,11,90) +#include <WebKit/WKBundleFrame.h> +#endif #include <atk/atk.h> #include <wtf/Assertions.h> -#include <wtf/gobject/GRefPtr.h> -#include <wtf/gobject/GUniquePtr.h> +#include <wtf/glib/GRefPtr.h> +#include <wtf/glib/GUniquePtr.h> #include <wtf/text/CString.h> #include <wtf/text/StringBuilder.h> #include <wtf/text/WTFString.h> @@ -48,6 +51,13 @@ namespace WTR { namespace { +#if ATK_CHECK_VERSION(2,11,92) +enum RangeLimit { + RangeLimitMinimum, + RangeLimitMaximum +}; +#endif + enum AtkAttributeType { ObjectAttributeType, TextAttributeType @@ -61,6 +71,8 @@ enum AttributeDomain { enum AttributesIndex { // Attribute names. InvalidNameIndex = 0, + PosInSetIndex, + SetSizeIndex, PlaceholderNameIndex, SortNameIndex, @@ -76,6 +88,8 @@ enum AttributesIndex { const String attributesMap[][2] = { // Attribute names. { "AXInvalid", "invalid" }, + { "AXARIAPosInSet", "posinset" }, + { "AXARIASetSize", "setsize" }, { "AXPlaceholderValue", "placeholder-text" } , { "AXSortDirection", "sort" }, @@ -91,6 +105,7 @@ const char* landmarkStringComplementary = "AXLandmarkComplementary"; const char* landmarkStringContentinfo = "AXLandmarkContentInfo"; const char* landmarkStringMain = "AXLandmarkMain"; const char* landmarkStringNavigation = "AXLandmarkNavigation"; +const char* landmarkStringRegion = "AXLandmarkRegion"; const char* landmarkStringSearch = "AXLandmarkSearch"; #endif @@ -172,9 +187,8 @@ String getAttributeSetValueForId(AtkObject* accessible, AtkAttributeType type, S return atkAttributeValueToCoreAttributeValue(type, id, attributeValue); } -String getAtkAttributeSetAsString(AtkObject* accessible, AtkAttributeType type) +String attributeSetToString(AtkAttributeSet* attributeSet, String separator=", ") { - AtkAttributeSet* attributeSet = getAttributeSet(accessible, type); if (!attributeSet) return String(); @@ -184,13 +198,18 @@ String getAtkAttributeSetAsString(AtkObject* accessible, AtkAttributeType type) GUniquePtr<gchar> attributeData(g_strconcat(attribute->name, ":", attribute->value, NULL)); builder.append(attributeData.get()); if (attributes->next) - builder.append(", "); + builder.append(separator); } atk_attribute_set_free(attributeSet); return builder.toString(); } +String getAtkAttributeSetAsString(AtkObject* accessible, AtkAttributeType type, String separator=", ") +{ + return attributeSetToString(getAttributeSet(accessible, type), separator); +} + bool checkElementState(PlatformUIElement element, AtkStateType stateType) { if (!ATK_IS_OBJECT(element.get())) @@ -203,7 +222,10 @@ bool checkElementState(PlatformUIElement element, AtkStateType stateType) JSStringRef indexRangeInTable(PlatformUIElement element, bool isRowRange) { GUniquePtr<gchar> rangeString(g_strdup("{0, 0}")); - +#if ATK_CHECK_VERSION(2,11,90) + if (!ATK_IS_TABLE_CELL(element.get())) + return JSStringCreateWithUTF8CString(rangeString.get()); +#else if (!ATK_IS_OBJECT(element.get())) return JSStringCreateWithUTF8CString(rangeString.get()); @@ -215,11 +237,20 @@ JSStringRef indexRangeInTable(PlatformUIElement element, bool isRowRange) gint indexInParent = atk_object_get_index_in_parent(ATK_OBJECT(element.get())); if (indexInParent == -1) return JSStringCreateWithUTF8CString(rangeString.get()); +#endif - int row = -1; - int column = -1; + gint row = -1; + gint column = -1; + gint rowSpan = -1; + gint columnSpan = -1; +#if ATK_CHECK_VERSION(2,11,90) + atk_table_cell_get_row_column_span(ATK_TABLE_CELL(element.get()), &row, &column, &rowSpan, &columnSpan); +#else row = atk_table_get_row_at_index(ATK_TABLE(axTable), indexInParent); column = atk_table_get_column_at_index(ATK_TABLE(axTable), indexInParent); + rowSpan = atk_table_get_row_extent_at(ATK_TABLE(axTable), row, column); + columnSpan = atk_table_get_column_extent_at(ATK_TABLE(axTable), row, column); +#endif // Get the actual values, if row and columns are valid values. if (row != -1 && column != -1) { @@ -227,10 +258,10 @@ JSStringRef indexRangeInTable(PlatformUIElement element, bool isRowRange) int length = 0; if (isRowRange) { base = row; - length = atk_table_get_row_extent_at(ATK_TABLE(axTable), row, column); + length = rowSpan; } else { base = column; - length = atk_table_get_column_extent_at(ATK_TABLE(axTable), row, column); + length = columnSpan; } rangeString.reset(g_strdup_printf("{%d, %d}", base, length)); } @@ -243,6 +274,13 @@ void alterCurrentValue(PlatformUIElement element, int factor) if (!ATK_IS_VALUE(element.get())) return; +#if ATK_CHECK_VERSION(2,11,92) + double currentValue; + atk_value_get_value_and_text(ATK_VALUE(element.get()), ¤tValue, nullptr); + + double increment = atk_value_get_increment(ATK_VALUE(element.get())); + atk_value_set_value(ATK_VALUE(element.get()), currentValue + factor * increment); +#else GValue currentValue = G_VALUE_INIT; atk_value_get_current_value(ATK_VALUE(element.get()), ¤tValue); @@ -258,6 +296,7 @@ void alterCurrentValue(PlatformUIElement element, int factor) g_value_unset(&newValue); g_value_unset(&increment); g_value_unset(¤tValue); +#endif } gchar* replaceCharactersForResults(gchar* str) @@ -283,17 +322,19 @@ const gchar* roleToString(AtkObject* object) #if ATK_CHECK_VERSION(2, 11, 3) if (role == ATK_ROLE_LANDMARK) { String xmlRolesValue = getAttributeSetValueForId(object, ObjectAttributeType, "xml-roles"); - if (equalIgnoringCase(xmlRolesValue, "banner")) + if (equalLettersIgnoringASCIICase(xmlRolesValue, "banner")) return landmarkStringBanner; - if (equalIgnoringCase(xmlRolesValue, "complementary")) + if (equalLettersIgnoringASCIICase(xmlRolesValue, "complementary")) return landmarkStringComplementary; - if (equalIgnoringCase(xmlRolesValue, "contentinfo")) + if (equalLettersIgnoringASCIICase(xmlRolesValue, "contentinfo")) return landmarkStringContentinfo; - if (equalIgnoringCase(xmlRolesValue, "main")) + if (equalLettersIgnoringASCIICase(xmlRolesValue, "main")) return landmarkStringMain; - if (equalIgnoringCase(xmlRolesValue, "navigation")) + if (equalLettersIgnoringASCIICase(xmlRolesValue, "navigation")) return landmarkStringNavigation; - if (equalIgnoringCase(xmlRolesValue, "search")) + if (equalLettersIgnoringASCIICase(xmlRolesValue, "region")) + return landmarkStringRegion; + if (equalLettersIgnoringASCIICase(xmlRolesValue, "search")) return landmarkStringSearch; } #endif @@ -305,6 +346,8 @@ const gchar* roleToString(AtkObject* object) return "AXDialog"; case ATK_ROLE_CANVAS: return "AXCanvas"; + case ATK_ROLE_CAPTION: + return "AXCaption"; case ATK_ROLE_CHECK_BOX: return "AXCheckBox"; case ATK_ROLE_COLOR_CHOOSER: @@ -339,6 +382,8 @@ const gchar* roleToString(AtkObject* object) return "AXInvalid"; case ATK_ROLE_LABEL: return "AXLabel"; + case ATK_ROLE_LEVEL_BAR: + return "AXProgressIndicator"; case ATK_ROLE_LINK: return "AXLink"; case ATK_ROLE_LIST: @@ -420,6 +465,10 @@ const gchar* roleToString(AtkObject* object) #if ATK_CHECK_VERSION(2, 11, 3) case ATK_ROLE_ARTICLE: return "AXArticle"; + case ATK_ROLE_AUDIO: + return "AXAudio"; + case ATK_ROLE_BLOCK_QUOTE: + return "AXBlockquote"; case ATK_ROLE_DEFINITION: return "AXDefinition"; case ATK_ROLE_LOG: @@ -430,6 +479,8 @@ const gchar* roleToString(AtkObject* object) return "AXMath"; case ATK_ROLE_TIMER: return "AXTimer"; + case ATK_ROLE_VIDEO: + return "AXVideo"; #endif #if ATK_CHECK_VERSION(2, 11, 4) case ATK_ROLE_DESCRIPTION_LIST: @@ -439,6 +490,20 @@ const gchar* roleToString(AtkObject* object) case ATK_ROLE_DESCRIPTION_VALUE: return "AXDescriptionValue"; #endif +#if ATK_CHECK_VERSION(2, 15, 2) + case ATK_ROLE_STATIC: + return "AXStatic"; +#endif +#if ATK_CHECK_VERSION(2, 15, 4) + case ATK_ROLE_MATH_FRACTION: + return "AXMathFraction"; + case ATK_ROLE_MATH_ROOT: + return "AXMathRoot"; + case ATK_ROLE_SUBSCRIPT: + return "AXSubscript"; + case ATK_ROLE_SUPERSCRIPT: + return "AXSuperscript"; +#endif default: // We want to distinguish ATK_ROLE_UNKNOWN from a known AtkRole which // our DRT isn't properly handling. @@ -446,6 +511,19 @@ const gchar* roleToString(AtkObject* object) } } +String selectedText(AtkObject* accessible) +{ + if (!ATK_IS_TEXT(accessible)) + return String(); + + AtkText* text = ATK_TEXT(accessible); + + gint start, end; + g_free(atk_text_get_selection(text, 0, &start, &end)); + + return atk_text_get_text(text, start, end); +} + String attributesOfElement(AccessibilityUIElement* element) { StringBuilder builder; @@ -552,6 +630,53 @@ static Vector<RefPtr<AccessibilityUIElement> > getVisibleCells(AccessibilityUIEl return visibleCells; } +#if ATK_CHECK_VERSION(2,11,90) +static Vector<RefPtr<AccessibilityUIElement>> convertGPtrArrayToVector(const GPtrArray* array) +{ + Vector<RefPtr<AccessibilityUIElement>> cells; + for (guint i = 0; i < array->len; i++) { + if (AtkObject* atkObject = static_cast<AtkObject*>(g_ptr_array_index(array, i))) + cells.append(AccessibilityUIElement::create(atkObject)); + } + return cells; +} + +static JSValueRef convertToJSObjectArray(const Vector<RefPtr<AccessibilityUIElement>>& children) +{ + WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page()); + JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame); + + size_t elementCount = children.size(); + auto valueElements = std::make_unique<JSValueRef[]>(elementCount); + for (size_t i = 0; i < elementCount; i++) + valueElements[i] = JSObjectMake(context, children[i]->wrapperClass(), children[i].get()); + + return JSObjectMakeArray(context, elementCount, valueElements.get(), nullptr); +} +#endif + +#if ATK_CHECK_VERSION(2,11,92) +static double rangeMinMaxValue(AtkValue* atkValue, RangeLimit rangeLimit) +{ + AtkRange* range = atk_value_get_range(atkValue); + if (!range) + return 0; + + double rangeValue = 0; + switch (rangeLimit) { + case RangeLimitMinimum: + rangeValue = atk_range_get_lower_limit(range); + break; + case RangeLimitMaximum: + rangeValue = atk_range_get_upper_limit(range); + break; + }; + + atk_range_free(range); + return rangeValue; +} +#endif + } // namespace AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element) @@ -605,7 +730,7 @@ int AccessibilityUIElement::childrenCount() return atk_object_get_n_accessible_children(ATK_OBJECT(m_element.get())); } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::elementAtPoint(int x, int y) +RefPtr<AccessibilityUIElement> AccessibilityUIElement::elementAtPoint(int x, int y) { if (!ATK_IS_COMPONENT(m_element.get())) return nullptr; @@ -630,7 +755,7 @@ unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element) return 0; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::childAtIndex(unsigned index) +RefPtr<AccessibilityUIElement> AccessibilityUIElement::childAtIndex(unsigned index) { if (!ATK_IS_OBJECT(m_element.get())) return nullptr; @@ -644,28 +769,16 @@ PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::childAtIndex(unsigned return nullptr; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::linkedUIElementAtIndex(unsigned index) -{ - // FIXME: implement - return nullptr; -} - -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index) +static RefPtr<AccessibilityUIElement> accessibilityElementAtIndex(AtkObject* element, AtkRelationType relationType, unsigned index) { - // FIXME: implement - return nullptr; -} - -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index) -{ - if (!ATK_IS_OBJECT(m_element.get())) + if (!ATK_IS_OBJECT(element)) return nullptr; - AtkRelationSet* relationSet = atk_object_ref_relation_set(ATK_OBJECT(m_element.get())); + AtkRelationSet* relationSet = atk_object_ref_relation_set(element); if (!relationSet) return nullptr; - AtkRelation* relation = atk_relation_set_get_relation_by_type(relationSet, ATK_RELATION_FLOWS_TO); + AtkRelation* relation = atk_relation_set_get_relation_by_type(relationSet, relationType); if (!relation) return nullptr; @@ -673,43 +786,80 @@ PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::ariaFlowToElementAtIn if (!targetList || !targetList->len || index >= targetList->len) return nullptr; + AtkObject* target = static_cast<AtkObject*>(g_ptr_array_index(targetList, index)); g_object_unref(relationSet); - AtkObject* target = static_cast<AtkObject*>(g_ptr_array_index(targetList, index)); - return target ? AccessibilityUIElement::create(target) : nullptr; + return target ? AccessibilityUIElement::create(target).ptr() : nullptr; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::disclosedRowAtIndex(unsigned index) +RefPtr<AccessibilityUIElement> AccessibilityUIElement::linkedUIElementAtIndex(unsigned index) { // FIXME: implement return nullptr; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::rowAtIndex(unsigned index) +RefPtr<AccessibilityUIElement> AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index) { // FIXME: implement return nullptr; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::selectedChildAtIndex(unsigned index) const +RefPtr<AccessibilityUIElement> AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index) +{ + return accessibilityElementAtIndex(m_element.get(), ATK_RELATION_FLOWS_TO, index); +} + +RefPtr<AccessibilityUIElement> AccessibilityUIElement::ariaControlsElementAtIndex(unsigned index) +{ + return accessibilityElementAtIndex(m_element.get(), ATK_RELATION_CONTROLLER_FOR, index); +} + +RefPtr<AccessibilityUIElement> AccessibilityUIElement::disclosedRowAtIndex(unsigned index) { // FIXME: implement return nullptr; } +RefPtr<AccessibilityUIElement> AccessibilityUIElement::rowAtIndex(unsigned index) +{ + // ATK doesn't have API to get an accessible row by index directly. It does, however, have + // API to get cells in the row specified by index. The parent of a cell should be the row. + AtkTable* axTable = ATK_TABLE(m_element.get()); + unsigned nColumns = columnCount(); + for (unsigned col = 0; col < nColumns; col++) { + // Find the first cell in this row that only spans one row. + if (atk_table_get_row_extent_at(axTable, index, col) == 1) { + AtkObject* cell = atk_table_ref_at(axTable, index, col); + return cell ? AccessibilityUIElement::create(atk_object_get_parent(cell)).ptr() : nullptr; + } + } + + return nullptr; +} + +RefPtr<AccessibilityUIElement> AccessibilityUIElement::selectedChildAtIndex(unsigned index) const +{ + if (!ATK_SELECTION(m_element.get())) + return nullptr; + + GRefPtr<AtkObject> child = adoptGRef(atk_selection_ref_selection(ATK_SELECTION(m_element.get()), index)); + return child ? AccessibilityUIElement::create(child.get()).ptr() : nullptr; +} + unsigned AccessibilityUIElement::selectedChildrenCount() const { - // FIXME: implement - return 0; + if (!ATK_IS_SELECTION(m_element.get())) + return 0; + return atk_selection_get_selection_count(ATK_SELECTION(m_element.get())); } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::selectedRowAtIndex(unsigned index) +RefPtr<AccessibilityUIElement> AccessibilityUIElement::selectedRowAtIndex(unsigned index) { // FIXME: implement return nullptr; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::titleUIElement() +RefPtr<AccessibilityUIElement> AccessibilityUIElement::titleUIElement() { if (!ATK_IS_OBJECT(m_element.get())) return nullptr; @@ -730,19 +880,19 @@ PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::titleUIElement() } g_object_unref(set); - return target ? AccessibilityUIElement::create(target) : nullptr; + return target ? AccessibilityUIElement::create(target).ptr() : nullptr; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::parentElement() +RefPtr<AccessibilityUIElement> AccessibilityUIElement::parentElement() { if (!ATK_IS_OBJECT(m_element.get())) return nullptr; AtkObject* parent = atk_object_get_parent(ATK_OBJECT(m_element.get())); - return parent ? AccessibilityUIElement::create(parent) : nullptr; + return parent ? AccessibilityUIElement::create(parent).ptr() : nullptr; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::disclosedByRow() +RefPtr<AccessibilityUIElement> AccessibilityUIElement::disclosedByRow() { // FIXME: implement return nullptr; @@ -786,7 +936,13 @@ JSRetainPtr<JSStringRef> AccessibilityUIElement::stringAttributeValue(JSStringRe String atkAttributeName = coreAttributeToAtkAttribute(attribute); - // Try object attributes first. + // The value of AXSelectedText is not exposed through any AtkAttribute. + if (atkAttributeName == "AXSelectedText") { + String string = selectedText(m_element.get()); + return JSStringCreateWithUTF8CString(string.utf8().data()); + } + + // Try object attributes before text attributes. String attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), ObjectAttributeType, atkAttributeName); // Try text attributes if the requested one was not found and we have an AtkText object. @@ -812,7 +968,19 @@ JSRetainPtr<JSStringRef> AccessibilityUIElement::stringAttributeValue(JSStringRe double AccessibilityUIElement::numberAttributeValue(JSStringRef attribute) { - // FIXME: implement + if (!ATK_IS_OBJECT(m_element.get())) + return 0; + + String atkAttributeName = coreAttributeToAtkAttribute(attribute); + if (atkAttributeName.isEmpty()) + return 0; + + if (atkAttributeName == "setsize" || atkAttributeName == "posinset") { + String attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), ObjectAttributeType, atkAttributeName); + if (!attributeValue.isEmpty()) + return attributeValue.toDouble(); + } + return 0; } @@ -824,25 +992,87 @@ JSValueRef AccessibilityUIElement::uiElementArrayAttributeValue(JSStringRef attr JSValueRef AccessibilityUIElement::rowHeaders() const { - // FIXME: implement +#if ATK_CHECK_VERSION(2,11,90) + if (!ATK_IS_TABLE_CELL(m_element.get())) + return nullptr; + + GRefPtr<GPtrArray> array = adoptGRef(atk_table_cell_get_row_header_cells(ATK_TABLE_CELL(m_element.get()))); + if (!array) + return nullptr; + + Vector<RefPtr<AccessibilityUIElement>> rows = convertGPtrArrayToVector(array.get()); + return convertToJSObjectArray(rows); +#else return nullptr; +#endif } JSValueRef AccessibilityUIElement::columnHeaders() const { - // FIXME: implement +#if ATK_CHECK_VERSION(2,11,90) + if (!ATK_IS_TABLE_CELL(m_element.get()) && !ATK_IS_TABLE(m_element.get())) + return nullptr; + + Vector<RefPtr<AccessibilityUIElement>> columns; + if (ATK_IS_TABLE_CELL(m_element.get())) { + GRefPtr<GPtrArray> array = adoptGRef(atk_table_cell_get_column_header_cells(ATK_TABLE_CELL(m_element.get()))); + if (!array) + return nullptr; + + columns = convertGPtrArrayToVector(array.get()); + } else + columns = getColumnHeaders(ATK_TABLE(m_element.get())); + return convertToJSObjectArray(columns); +#else return nullptr; +#endif } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::uiElementAttributeValue(JSStringRef attribute) const +RefPtr<AccessibilityUIElement> AccessibilityUIElement::uiElementAttributeValue(JSStringRef attribute) const { - // FIXME: implement + if (!ATK_IS_OBJECT(m_element.get())) + return nullptr; + + // ATK does not have this API. So we're "faking it" here on a case-by-case basis. + String attributeString = jsStringToWTFString(attribute); + AtkRole role = atk_object_get_role(ATK_OBJECT(m_element.get())); + if (role == ATK_ROLE_SPIN_BUTTON && const_cast<AccessibilityUIElement*>(this)->childrenCount() == 2) { + if (attributeString == "AXDecrementButton") + return const_cast<AccessibilityUIElement*>(this)->childAtIndex(0); + if (attributeString == "AXIncrementButton") + return const_cast<AccessibilityUIElement*>(this)->childAtIndex(1); + } + return nullptr; } bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute) { - // FIXME: implement + if (!ATK_IS_OBJECT(m_element.get())) + return false; + + String attributeString = jsStringToWTFString(attribute); + if (attributeString == "AXElementBusy") + return checkElementState(m_element.get(), ATK_STATE_BUSY); + if (attributeString == "AXChecked") + return checkElementState(m_element.get(), ATK_STATE_CHECKED); + if (attributeString == "AXEnabled") + return checkElementState(m_element.get(), ATK_STATE_ENABLED); + if (attributeString == "AXExpanded") + return checkElementState(m_element.get(), ATK_STATE_EXPANDED); + if (attributeString == "AXFocused") + return checkElementState(m_element.get(), ATK_STATE_FOCUSED); + if (attributeString == "AXInvalid") + return checkElementState(m_element.get(), ATK_STATE_INVALID); + if (attributeString == "AXMultiSelectable") + return checkElementState(m_element.get(), ATK_STATE_MULTISELECTABLE); + if (attributeString == "AXRequired") + return checkElementState(m_element.get(), ATK_STATE_REQUIRED); + if (attributeString == "AXSelected") + return checkElementState(m_element.get(), ATK_STATE_SELECTED); + if (attributeString == "AXVisited") + return checkElementState(m_element.get(), ATK_STATE_VISITED); + return false; } @@ -852,8 +1082,51 @@ bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute) return false; String attributeString = jsStringToWTFString(attribute); - if (attributeString == "AXValue") - return checkElementState(m_element.get(), ATK_STATE_EDITABLE); + if (attributeString != "AXValue") + return false; + + // ATK does not have a single state or property to indicate whether or not the value + // of an accessible object can be set. ATs look at several states and properties based + // on the type of object. If nothing explicitly indicates the value can or cannot be + // set, ATs make role- and interface-based decisions. We'll do something similar here. + + // This state is expected to be present only for text widgets and contenteditable elements. + if (checkElementState(m_element.get(), ATK_STATE_EDITABLE)) + return true; + +#if ATK_CHECK_VERSION(2,11,2) + // This state is applicable to checkboxes, radiobuttons, switches, etc. + if (checkElementState(m_element.get(), ATK_STATE_CHECKABLE)) + return true; +#endif + +#if ATK_CHECK_VERSION(2,15,3) + // This state is expected to be present only for controls and only if explicitly set. + if (checkElementState(m_element.get(), ATK_STATE_READ_ONLY)) + return false; +#endif + + // We expose an object attribute to ATs when there is an author-provided ARIA property + // and also when there is a supported ARIA role but no author-provided value. + String isReadOnly = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), ObjectAttributeType, "readonly"); + if (!isReadOnly.isEmpty()) + return isReadOnly == "true" ? false : true; + + // If we have a native listbox or combobox and the value can be set, the options should + // have ATK_STATE_SELECTABLE. + AtkRole role = atk_object_get_role(ATK_OBJECT(m_element.get())); + if (role == ATK_ROLE_LIST_BOX || role == ATK_ROLE_COMBO_BOX) { + if (GRefPtr<AtkObject> child = adoptGRef(atk_object_ref_accessible_child(ATK_OBJECT(m_element.get()), 0))) { + if (atk_object_get_role(ATK_OBJECT(child.get())) == ATK_ROLE_MENU) + child = adoptGRef(atk_object_ref_accessible_child(ATK_OBJECT(child.get()), 0)); + return child && checkElementState(child.get(), ATK_STATE_SELECTABLE); + } + } + + // If we have a native element which exposes a range whose value can be set, it should + // be focusable and have a true range. + if (ATK_IS_VALUE(m_element.get()) && checkElementState(m_element.get(), ATK_STATE_FOCUSABLE)) + return minValue() != maxValue(); return false; } @@ -898,7 +1171,18 @@ JSRetainPtr<JSStringRef> AccessibilityUIElement::subrole() JSRetainPtr<JSStringRef> AccessibilityUIElement::roleDescription() { - // FIXME: implement + String roleDescription = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), ObjectAttributeType, "roledescription"); + GUniquePtr<gchar> axRoleDescription(g_strdup_printf("AXRoleDescription: %s", roleDescription.utf8().data())); + + return JSStringCreateWithUTF8CString(axRoleDescription.get()); +} + +JSRetainPtr<JSStringRef> AccessibilityUIElement::computedRoleString() +{ + String role = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), ObjectAttributeType, "computed-role"); + if (!role.isEmpty()) + return JSStringCreateWithUTF8CString(role.utf8().data()); + return JSStringCreateWithCharacters(0, 0); } @@ -976,15 +1260,15 @@ JSRetainPtr<JSStringRef> AccessibilityUIElement::helpText() const AtkRelationSet* relationSet = atk_object_ref_relation_set(ATK_OBJECT(m_element.get())); if (!relationSet) - return nullptr; + return JSStringCreateWithCharacters(0, 0); AtkRelation* relation = atk_relation_set_get_relation_by_type(relationSet, ATK_RELATION_DESCRIBED_BY); if (!relation) - return nullptr; + return JSStringCreateWithCharacters(0, 0); GPtrArray* targetList = atk_relation_get_target(relation); if (!targetList || !targetList->len) - return nullptr; + return JSStringCreateWithCharacters(0, 0); StringBuilder builder; builder.append("AXHelp: "); @@ -1008,8 +1292,12 @@ double AccessibilityUIElement::x() if (!ATK_IS_COMPONENT(m_element.get())) return 0; - int x, y; - atk_component_get_position(ATK_COMPONENT(m_element.get()), &x, &y, ATK_XY_SCREEN); + int x; +#if ATK_CHECK_VERSION(2,11,90) + atk_component_get_extents(ATK_COMPONENT(m_element.get()), &x, nullptr, nullptr, nullptr, ATK_XY_SCREEN); +#else + atk_component_get_position(ATK_COMPONENT(m_element.get()), &x, nullptr, ATK_XY_SCREEN); +#endif return x; } @@ -1018,8 +1306,12 @@ double AccessibilityUIElement::y() if (!ATK_IS_COMPONENT(m_element.get())) return 0; - int x, y; - atk_component_get_position(ATK_COMPONENT(m_element.get()), &x, &y, ATK_XY_SCREEN); + int y; +#if ATK_CHECK_VERSION(2,11,90) + atk_component_get_extents(ATK_COMPONENT(m_element.get()), nullptr, &y, nullptr, nullptr, ATK_XY_SCREEN); +#else + atk_component_get_position(ATK_COMPONENT(m_element.get()), nullptr, &y, ATK_XY_SCREEN); +#endif return y; } @@ -1028,8 +1320,12 @@ double AccessibilityUIElement::width() if (!ATK_IS_COMPONENT(m_element.get())) return 0; - int width, height; - atk_component_get_size(ATK_COMPONENT(m_element.get()), &width, &height); + int width; +#if ATK_CHECK_VERSION(2,11,90) + atk_component_get_extents(ATK_COMPONENT(m_element.get()), nullptr, nullptr, &width, nullptr, ATK_XY_WINDOW); +#else + atk_component_get_size(ATK_COMPONENT(m_element.get()), &width, nullptr); +#endif return width; } @@ -1038,8 +1334,12 @@ double AccessibilityUIElement::height() if (!ATK_IS_COMPONENT(m_element.get())) return 0; - int width, height; - atk_component_get_size(ATK_COMPONENT(m_element.get()), &width, &height); + int height; +#if ATK_CHECK_VERSION(2,11,90) + atk_component_get_extents(ATK_COMPONENT(m_element.get()), nullptr, nullptr, nullptr, &height, ATK_XY_WINDOW); +#else + atk_component_get_size(ATK_COMPONENT(m_element.get()), nullptr, &height); +#endif return height; } @@ -1048,11 +1348,13 @@ double AccessibilityUIElement::clickPointX() if (!ATK_IS_COMPONENT(m_element.get())) return 0; - int x, y; - atk_component_get_position(ATK_COMPONENT(m_element.get()), &x, &y, ATK_XY_WINDOW); - - int width, height; - atk_component_get_size(ATK_COMPONENT(m_element.get()), &width, &height); + int x, width; +#if ATK_CHECK_VERSION(2,11,90) + atk_component_get_extents(ATK_COMPONENT(m_element.get()), &x, nullptr, &width, nullptr, ATK_XY_WINDOW); +#else + atk_component_get_position(ATK_COMPONENT(m_element.get()), &x, nullptr, ATK_XY_WINDOW); + atk_component_get_size(ATK_COMPONENT(m_element.get()), &width, nullptr); +#endif return x + width / 2.0; } @@ -1062,11 +1364,13 @@ double AccessibilityUIElement::clickPointY() if (!ATK_IS_COMPONENT(m_element.get())) return 0; - int x, y; - atk_component_get_position(ATK_COMPONENT(m_element.get()), &x, &y, ATK_XY_WINDOW); - - int width, height; - atk_component_get_size(ATK_COMPONENT(m_element.get()), &width, &height); + int y, height; +#if ATK_CHECK_VERSION(2,11,90) + atk_component_get_extents(ATK_COMPONENT(m_element.get()), nullptr, &y, nullptr, &height, ATK_XY_WINDOW); +#else + atk_component_get_position(ATK_COMPONENT(m_element.get()), nullptr, &y, ATK_XY_WINDOW); + atk_component_get_size(ATK_COMPONENT(m_element.get()), nullptr, &height); +#endif return y + height / 2.0; } @@ -1077,11 +1381,17 @@ double AccessibilityUIElement::intValue() const return 0; if (ATK_IS_VALUE(m_element.get())) { +#if ATK_CHECK_VERSION(2,11,92) + double value; + atk_value_get_value_and_text(ATK_VALUE(m_element.get()), &value, nullptr); + return value; +#else GValue value = G_VALUE_INIT; atk_value_get_current_value(ATK_VALUE(m_element.get()), &value); if (!G_VALUE_HOLDS_FLOAT(&value)) return 0; return g_value_get_float(&value); +#endif } // Consider headings as an special case when returning the "int value" of @@ -1102,13 +1412,16 @@ double AccessibilityUIElement::minValue() { if (!ATK_IS_VALUE(m_element.get())) return 0; - +#if ATK_CHECK_VERSION(2,11,92) + return rangeMinMaxValue(ATK_VALUE(m_element.get()), RangeLimitMinimum); +#else GValue value = G_VALUE_INIT; atk_value_get_minimum_value(ATK_VALUE(m_element.get()), &value); if (!G_VALUE_HOLDS_FLOAT(&value)) return 0; return g_value_get_float(&value); +#endif } double AccessibilityUIElement::maxValue() @@ -1116,18 +1429,23 @@ double AccessibilityUIElement::maxValue() if (!ATK_IS_VALUE(m_element.get())) return 0; +#if ATK_CHECK_VERSION(2,11,92) + return rangeMinMaxValue(ATK_VALUE(m_element.get()), RangeLimitMaximum); +#else GValue value = G_VALUE_INIT; atk_value_get_maximum_value(ATK_VALUE(m_element.get()), &value); if (!G_VALUE_HOLDS_FLOAT(&value)) return 0; return g_value_get_float(&value); +#endif } JSRetainPtr<JSStringRef> AccessibilityUIElement::valueDescription() { - // FIXME: implement - return JSStringCreateWithCharacters(0, 0); + String valueText = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), ObjectAttributeType, "valuetext"); + GUniquePtr<gchar> valueDescription(g_strdup_printf("AXValueDescription: %s", valueText.utf8().data())); + return JSStringCreateWithUTF8CString(valueDescription.get()); } int AccessibilityUIElement::insertionPointLineNumber() @@ -1142,7 +1460,7 @@ bool AccessibilityUIElement::isPressActionSupported() return false; const gchar* actionName = atk_action_get_name(ATK_ACTION(m_element.get()), 0); - return equalIgnoringCase(actionName, String("press")) || equalIgnoringCase(actionName, String("jump")); + return equalLettersIgnoringASCIICase(String(actionName), "press") || equalLettersIgnoringASCIICase(String(actionName), "jump"); } bool AccessibilityUIElement::isIncrementActionSupported() @@ -1242,8 +1560,16 @@ int AccessibilityUIElement::lineForIndex(int index) JSRetainPtr<JSStringRef> AccessibilityUIElement::rangeForLine(int line) { - // FIXME: implement - return JSStringCreateWithCharacters(0, 0); + if (!ATK_IS_TEXT(m_element.get())) + return JSStringCreateWithCharacters(0, 0); + + AtkText* text = ATK_TEXT(m_element.get()); + gint startOffset = 0, endOffset = 0; + for (int i = 0; i <= line; ++i) + atk_text_get_string_at_offset(text, endOffset, ATK_TEXT_GRANULARITY_LINE, &startOffset, &endOffset); + + GUniquePtr<gchar> range(g_strdup_printf("{%d, %d}", startOffset, endOffset - startOffset)); + return JSStringCreateWithUTF8CString(range.get()); } JSRetainPtr<JSStringRef> AccessibilityUIElement::rangeForPosition(int x, int y) @@ -1254,8 +1580,14 @@ JSRetainPtr<JSStringRef> AccessibilityUIElement::rangeForPosition(int x, int y) JSRetainPtr<JSStringRef> AccessibilityUIElement::boundsForRange(unsigned location, unsigned length) { - // FIXME: implement - return JSStringCreateWithCharacters(0, 0); + if (!ATK_IS_TEXT(m_element.get())) + return JSStringCreateWithCharacters(0, 0); + + AtkTextRectangle rect; + atk_text_get_range_extents(ATK_TEXT(m_element.get()), location, location + length, ATK_XY_WINDOW, &rect); + + GUniquePtr<gchar> bounds(g_strdup_printf("{%d, %d, %d, %d}", rect.x, rect.y, rect.width, rect.height)); + return JSStringCreateWithUTF8CString(bounds.get()); } JSRetainPtr<JSStringRef> AccessibilityUIElement::stringForRange(unsigned location, unsigned length) @@ -1269,8 +1601,29 @@ JSRetainPtr<JSStringRef> AccessibilityUIElement::stringForRange(unsigned locatio JSRetainPtr<JSStringRef> AccessibilityUIElement::attributedStringForRange(unsigned location, unsigned length) { - // FIXME: implement - return JSStringCreateWithCharacters(0, 0); + if (!ATK_IS_TEXT(m_element.get())) + return JSStringCreateWithCharacters(0, 0); + + StringBuilder builder; + + // The default text attributes apply to the entire element. + builder.append("\n\tDefault text attributes:\n\t\t"); + builder.append(attributeSetToString(getAttributeSet(m_element.get(), TextAttributeType), "\n\t\t")); + + // The attribute run provides attributes specific to the range of text at the specified offset. + AtkAttributeSet* attributeSet; + AtkText* text = ATK_TEXT(m_element.get()); + gint start = 0, end = 0; + for (int i = location; i < location + length; i = end) { + AtkAttributeSet* attributeSet = atk_text_get_run_attributes(text, i, &start, &end); + GUniquePtr<gchar> substring(replaceCharactersForResults(atk_text_get_text(text, start, end))); + builder.append(String::format("\n\tRange attributes for '%s':\n\t\t", substring.get())); + builder.append(attributeSetToString(attributeSet, "\n\t\t")); + } + + atk_attribute_set_free(attributeSet); + + return JSStringCreateWithUTF8CString(builder.toString().utf8().data()); } bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned location, unsigned length) @@ -1279,13 +1632,19 @@ bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned location return false; } -unsigned AccessibilityUIElement::uiElementCountForSearchPredicate(JSContextRef context, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly) +unsigned AccessibilityUIElement::uiElementCountForSearchPredicate(JSContextRef context, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly, bool immediateDescendantsOnly) { // FIXME: implement return 0; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::uiElementForSearchPredicate(JSContextRef context, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly) +RefPtr<AccessibilityUIElement> AccessibilityUIElement::uiElementForSearchPredicate(JSContextRef context, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly, bool immediateDescendantsOnly) +{ + // FIXME: implement + return nullptr; +} + +JSRetainPtr<JSStringRef> AccessibilityUIElement::selectTextWithCriteria(JSContextRef context, JSStringRef ambiguityResolution, JSValueRef searchStrings, JSStringRef replacementString, JSStringRef activity) { // FIXME: implement return nullptr; @@ -1370,7 +1729,7 @@ JSRetainPtr<JSStringRef> AccessibilityUIElement::columnIndexRange() return indexRangeInTable(m_element.get(), false); } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::cellForColumnAndRow(unsigned col, unsigned row) +RefPtr<AccessibilityUIElement> AccessibilityUIElement::cellForColumnAndRow(unsigned col, unsigned row) { if (!ATK_IS_TABLE(m_element.get())) return nullptr; @@ -1378,16 +1737,16 @@ PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::cellForColumnAndRow(u // 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.get()), row, col)); - return foundCell ? AccessibilityUIElement::create(foundCell.get()) : nullptr; + return foundCell ? AccessibilityUIElement::create(foundCell.get()).ptr() : nullptr; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::horizontalScrollbar() const +RefPtr<AccessibilityUIElement> AccessibilityUIElement::horizontalScrollbar() const { // FIXME: implement return nullptr; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::verticalScrollbar() const +RefPtr<AccessibilityUIElement> AccessibilityUIElement::verticalScrollbar() const { // FIXME: implement return nullptr; @@ -1445,6 +1804,30 @@ void AccessibilityUIElement::setSelectedChild(AccessibilityUIElement* element) c // FIXME: implement } +void AccessibilityUIElement::setSelectedChildAtIndex(unsigned index) const +{ + if (!ATK_IS_SELECTION(m_element.get())) + return; + + atk_selection_add_selection(ATK_SELECTION(m_element.get()), index); +} + +void AccessibilityUIElement::removeSelectionAtIndex(unsigned index) const +{ + if (!ATK_IS_SELECTION(m_element.get())) + return; + + atk_selection_remove_selection(ATK_SELECTION(m_element.get()), index); +} + +void AccessibilityUIElement::clearSelectedChildren() const +{ + if (!ATK_IS_SELECTION(m_element.get())) + return; + + atk_selection_clear_selection(ATK_SELECTION(m_element.get())); +} + JSRetainPtr<JSStringRef> AccessibilityUIElement::accessibilityValue() const { // FIXME: implement @@ -1457,7 +1840,7 @@ JSRetainPtr<JSStringRef> AccessibilityUIElement::documentEncoding() return JSStringCreateWithCharacters(0, 0); AtkRole role = atk_object_get_role(ATK_OBJECT(m_element.get())); - if (role != ATK_ROLE_DOCUMENT_FRAME) + if (role != ATK_ROLE_DOCUMENT_WEB) return JSStringCreateWithCharacters(0, 0); return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element.get()), "Encoding")); @@ -1469,7 +1852,7 @@ JSRetainPtr<JSStringRef> AccessibilityUIElement::documentURI() return JSStringCreateWithCharacters(0, 0); AtkRole role = atk_object_get_role(ATK_OBJECT(m_element.get())); - if (role != ATK_ROLE_DOCUMENT_FRAME) + if (role != ATK_ROLE_DOCUMENT_WEB) return JSStringCreateWithCharacters(0, 0); return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element.get()), "URI")); @@ -1552,13 +1935,23 @@ bool AccessibilityUIElement::isIgnored() const return false; } +bool AccessibilityUIElement::isSingleLine() const +{ + return checkElementState(m_element.get(), ATK_STATE_SINGLE_LINE); +} + +bool AccessibilityUIElement::isMultiLine() const +{ + return checkElementState(m_element.get(), ATK_STATE_MULTI_LINE); +} + bool AccessibilityUIElement::hasPopup() const { if (!ATK_IS_OBJECT(m_element.get())) return false; String hasPopupValue = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), ObjectAttributeType, "haspopup"); - return equalIgnoringCase(hasPopupValue, "true"); + return equalLettersIgnoringASCIICase(hasPopupValue, "true"); } void AccessibilityUIElement::takeFocus() @@ -1582,7 +1975,13 @@ void AccessibilityUIElement::removeSelection() } // Text markers -PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::textMarkerRangeForElement(AccessibilityUIElement* element) +RefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::lineTextMarkerRangeForTextMarker(AccessibilityTextMarker* textMarker) +{ + // FIXME: implement + return nullptr; +} + +RefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::textMarkerRangeForElement(AccessibilityUIElement* element) { // FIXME: implement return nullptr; @@ -1594,13 +1993,13 @@ int AccessibilityUIElement::textMarkerRangeLength(AccessibilityTextMarkerRange* return 0; } -PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::previousTextMarker(AccessibilityTextMarker* textMarker) +RefPtr<AccessibilityTextMarker> AccessibilityUIElement::previousTextMarker(AccessibilityTextMarker* textMarker) { // FIXME: implement return nullptr; } -PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::nextTextMarker(AccessibilityTextMarker* textMarker) +RefPtr<AccessibilityTextMarker> AccessibilityUIElement::nextTextMarker(AccessibilityTextMarker* textMarker) { // FIXME: implement return nullptr; @@ -1612,43 +2011,43 @@ JSRetainPtr<JSStringRef> AccessibilityUIElement::stringForTextMarkerRange(Access return JSStringCreateWithCharacters(0, 0); } -PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::textMarkerRangeForMarkers(AccessibilityTextMarker* startMarker, AccessibilityTextMarker* endMarker) +RefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::textMarkerRangeForMarkers(AccessibilityTextMarker* startMarker, AccessibilityTextMarker* endMarker) { // FIXME: implement return nullptr; } -PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::startTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange* range) +RefPtr<AccessibilityTextMarker> AccessibilityUIElement::startTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange* range) { // FIXME: implement return nullptr; } -PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::endTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange* range) +RefPtr<AccessibilityTextMarker> AccessibilityUIElement::endTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange* range) { // FIXME: implement return nullptr; } -PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::endTextMarkerForBounds(int x, int y, int width, int height) +RefPtr<AccessibilityTextMarker> AccessibilityUIElement::endTextMarkerForBounds(int x, int y, int width, int height) { // FIXME: implement return nullptr; } -PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::startTextMarkerForBounds(int x, int y, int width, int height) +RefPtr<AccessibilityTextMarker> AccessibilityUIElement::startTextMarkerForBounds(int x, int y, int width, int height) { // FIXME: implement return nullptr; } -PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::textMarkerForPoint(int x, int y) +RefPtr<AccessibilityTextMarker> AccessibilityUIElement::textMarkerForPoint(int x, int y) { // FIXME: implement return nullptr; } -PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::accessibilityElementForTextMarker(AccessibilityTextMarker* marker) +RefPtr<AccessibilityUIElement> AccessibilityUIElement::accessibilityElementForTextMarker(AccessibilityTextMarker* marker) { // FIXME: implement return nullptr; @@ -1672,28 +2071,43 @@ bool AccessibilityUIElement::isTextMarkerValid(AccessibilityTextMarker* textMark return false; } -PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::textMarkerForIndex(int textIndex) +RefPtr<AccessibilityTextMarker> AccessibilityUIElement::textMarkerForIndex(int textIndex) { // FIXME: implement return nullptr; } -PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::startTextMarker() +RefPtr<AccessibilityTextMarker> AccessibilityUIElement::startTextMarker() { // FIXME: implement return nullptr; } -PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::endTextMarker() +RefPtr<AccessibilityTextMarker> AccessibilityUIElement::endTextMarker() { // FIXME: implement return nullptr; } +bool AccessibilityUIElement::setSelectedVisibleTextRange(AccessibilityTextMarkerRange*) +{ + return false; +} + void AccessibilityUIElement::scrollToMakeVisible() { // FIXME: implement } + +void AccessibilityUIElement::scrollToGlobalPoint(int x, int y) +{ + // FIXME: implement +} + +void AccessibilityUIElement::scrollToMakeVisibleWithSubFocus(int x, int y, int width, int height) +{ + // FIXME: implement +} JSRetainPtr<JSStringRef> AccessibilityUIElement::supportedActions() const { diff --git a/Tools/WebKitTestRunner/InjectedBundle/gtk/ActivateFontsGtk.cpp b/Tools/WebKitTestRunner/InjectedBundle/gtk/ActivateFontsGtk.cpp index 7c9dab7b9..496c1bcbf 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/gtk/ActivateFontsGtk.cpp +++ b/Tools/WebKitTestRunner/InjectedBundle/gtk/ActivateFontsGtk.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2005, 2006 Apple Inc. All rights reserved. * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) * Copyright (C) 2010 Igalia S.L. * @@ -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. * @@ -34,8 +34,8 @@ #include "InjectedBundleUtilities.h" #include <fontconfig/fontconfig.h> #include <gtk/gtk.h> -#include <wtf/gobject/GUniquePtr.h> -#include <wtf/gobject/GlibUtilities.h> +#include <wtf/glib/GLibUtilities.h> +#include <wtf/glib/GUniquePtr.h> namespace WTR { @@ -68,7 +68,7 @@ CString getOutputDir() static CString getFontsPath() { CString webkitOutputDir = getOutputDir(); - GUniquePtr<char> fontsPath(g_build_filename(webkitOutputDir.data(), "Dependencies", "Root", "webkitgtk-test-fonts", nullptr)); + GUniquePtr<char> fontsPath(g_build_filename(webkitOutputDir.data(), "DependenciesGTK", "Root", "webkitgtk-test-fonts", nullptr)); if (g_file_test(fontsPath.get(), static_cast<GFileTest>(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) return fontsPath.get(); diff --git a/Tools/WebKitTestRunner/InjectedBundle/gtk/InjectedBundleUtilities.cpp b/Tools/WebKitTestRunner/InjectedBundle/gtk/InjectedBundleUtilities.cpp index febdaad19..afbd3f74a 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/gtk/InjectedBundleUtilities.cpp +++ b/Tools/WebKitTestRunner/InjectedBundle/gtk/InjectedBundleUtilities.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. * @@ -30,8 +30,8 @@ #include "InjectedBundleUtilities.h" #include <gtk/gtk.h> -#include <wtf/gobject/GUniquePtr.h> -#include <wtf/gobject/GlibUtilities.h> +#include <wtf/glib/GLibUtilities.h> +#include <wtf/glib/GUniquePtr.h> namespace WTR { diff --git a/Tools/WebKitTestRunner/InjectedBundle/gtk/InjectedBundleUtilities.h b/Tools/WebKitTestRunner/InjectedBundle/gtk/InjectedBundleUtilities.h index 50f89dead..4062c6d44 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/gtk/InjectedBundleUtilities.h +++ b/Tools/WebKitTestRunner/InjectedBundle/gtk/InjectedBundleUtilities.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/WebKitTestRunner/InjectedBundle/gtk/TestRunnerGtk.cpp b/Tools/WebKitTestRunner/InjectedBundle/gtk/TestRunnerGtk.cpp index 254374884..a9f7f409c 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/gtk/TestRunnerGtk.cpp +++ b/Tools/WebKitTestRunner/InjectedBundle/gtk/TestRunnerGtk.cpp @@ -30,37 +30,25 @@ #include "InjectedBundle.h" #include "InjectedBundleUtilities.h" #include <glib.h> -#include <wtf/gobject/GUniquePtr.h> +#include <wtf/glib/GUniquePtr.h> namespace WTR { -static gboolean waitToDumpWatchdogTimerCallback(gpointer) -{ - InjectedBundle::shared().testRunner()->waitToDumpWatchdogTimerFired(); - return FALSE; -} - void TestRunner::platformInitialize() { - m_waitToDumpWatchdogTimer = 0; } void TestRunner::invalidateWaitToDumpWatchdogTimer() { - if (!m_waitToDumpWatchdogTimer) - return; - g_source_remove(m_waitToDumpWatchdogTimer); - m_waitToDumpWatchdogTimer = 0; + m_waitToDumpWatchdogTimer.stop(); } void TestRunner::initializeWaitToDumpWatchdogTimerIfNeeded() { - if (m_waitToDumpWatchdogTimer) + if (m_waitToDumpWatchdogTimer.isActive()) return; - m_waitToDumpWatchdogTimer = g_timeout_add(waitToDumpWatchdogTimerInterval * 1000, - waitToDumpWatchdogTimerCallback, 0); - g_source_set_name_by_id(m_waitToDumpWatchdogTimer, "[WebKit] waitToDumpWatchdogTimerCallback"); + m_waitToDumpWatchdogTimer.startOneShot(m_timeout / 1000.0); } JSRetainPtr<JSStringRef> TestRunner::pathToLocalResource(JSStringRef url) @@ -78,4 +66,9 @@ JSRetainPtr<JSStringRef> TestRunner::pathToLocalResource(JSStringRef url) return JSStringCreateWithUTF8CString(testURI.get()); } +JSRetainPtr<JSStringRef> TestRunner::inspectorTestStubURL() +{ + return JSStringCreateWithUTF8CString("resource:///org/webkitgtk/inspector/UserInterface/TestStub.html"); +} + } // namespace WTR |