summaryrefslogtreecommitdiff
path: root/Tools
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2016-05-24 08:28:08 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2016-05-24 08:28:08 +0000
commita4e969f4965059196ca948db781e52f7cfebf19e (patch)
tree6ca352808c8fdc52006a0f33f6ae3c593b23867d /Tools
parent41386e9cb918eed93b3f13648cbef387e371e451 (diff)
downloadWebKitGtk-tarball-a4e969f4965059196ca948db781e52f7cfebf19e.tar.gz
webkitgtk-2.12.3webkitgtk-2.12.3
Diffstat (limited to 'Tools')
-rw-r--r--Tools/CMakeLists.txt38
-rw-r--r--Tools/DumpRenderTree/AccessibilityController.cpp16
-rw-r--r--Tools/DumpRenderTree/AccessibilityController.h6
-rw-r--r--Tools/DumpRenderTree/AccessibilityTextMarker.h8
-rw-r--r--Tools/DumpRenderTree/AccessibilityUIElement.cpp462
-rw-r--r--Tools/DumpRenderTree/AccessibilityUIElement.h57
-rw-r--r--Tools/DumpRenderTree/CMakeLists.txt127
-rw-r--r--Tools/DumpRenderTree/DefaultPolicyDelegate.h13
-rw-r--r--Tools/DumpRenderTree/DumpRenderTree.h4
-rw-r--r--Tools/DumpRenderTree/DumpRenderTree.sln100
-rw-r--r--Tools/DumpRenderTree/DumpRenderTreeFileDraggingSource.h43
-rw-r--r--Tools/DumpRenderTree/DumpRenderTreePrefix.h13
-rw-r--r--Tools/DumpRenderTree/ForwardingHeaders/runtime/ArrayBufferView.h1
-rw-r--r--Tools/DumpRenderTree/ForwardingHeaders/runtime/JSArrayBufferView.h1
-rw-r--r--Tools/DumpRenderTree/ForwardingHeaders/runtime/JSExportMacros.h1
-rw-r--r--Tools/DumpRenderTree/ForwardingHeaders/runtime/TypedArrayInlines.h1
-rw-r--r--Tools/DumpRenderTree/GCController.cpp2
-rw-r--r--Tools/DumpRenderTree/GCController.h4
-rw-r--r--Tools/DumpRenderTree/JavaScriptThreading.cpp157
-rw-r--r--Tools/DumpRenderTree/JavaScriptThreading.h2
-rw-r--r--Tools/DumpRenderTree/PixelDumpSupport.cpp4
-rw-r--r--Tools/DumpRenderTree/PixelDumpSupport.h2
-rw-r--r--Tools/DumpRenderTree/TestNetscapePlugIn/CMakeLists.txt61
-rw-r--r--Tools/DumpRenderTree/TestNetscapePlugIn/ForwardingHeaders/WebKit/npapi.h (renamed from Tools/DumpRenderTree/TestNetscapePlugIn/unix/ForwardingHeaders/WebKit/npapi.h)0
-rw-r--r--Tools/DumpRenderTree/TestNetscapePlugIn/ForwardingHeaders/WebKit/npfunctions.h (renamed from Tools/DumpRenderTree/TestNetscapePlugIn/unix/ForwardingHeaders/WebKit/npfunctions.h)0
-rw-r--r--Tools/DumpRenderTree/TestNetscapePlugIn/ForwardingHeaders/WebKit/npruntime.h (renamed from Tools/DumpRenderTree/TestNetscapePlugIn/unix/ForwardingHeaders/WebKit/npruntime.h)0
-rw-r--r--Tools/DumpRenderTree/TestNetscapePlugIn/PluginObject.cpp44
-rw-r--r--Tools/DumpRenderTree/TestNetscapePlugIn/PluginTest.cpp19
-rw-r--r--Tools/DumpRenderTree/TestNetscapePlugIn/PluginTest.h7
-rw-r--r--Tools/DumpRenderTree/TestNetscapePlugIn/Tests/EvaluateJSWithinNPP_New.cpp56
-rw-r--r--Tools/DumpRenderTree/TestNetscapePlugIn/Tests/InvokeDestroysPluginWithinNPP_New.cpp67
-rw-r--r--Tools/DumpRenderTree/TestNetscapePlugIn/Tests/PluginScriptableObjectOverridesAllProperties.cpp82
-rw-r--r--Tools/DumpRenderTree/TestNetscapePlugIn/Tests/SlowNPPNew.cpp87
-rw-r--r--Tools/DumpRenderTree/TestNetscapePlugIn/Tests/URLRedirect.cpp167
-rw-r--r--Tools/DumpRenderTree/TestNetscapePlugIn/main.cpp53
-rw-r--r--Tools/DumpRenderTree/TestRunner.cpp162
-rw-r--r--Tools/DumpRenderTree/TestRunner.h34
-rw-r--r--Tools/DumpRenderTree/WorkQueue.cpp7
-rw-r--r--Tools/DumpRenderTree/WorkQueue.h8
-rw-r--r--Tools/DumpRenderTree/WorkQueueItem.h2
-rw-r--r--Tools/DumpRenderTree/atk/AccessibilityCallbacks.h44
-rw-r--r--Tools/DumpRenderTree/atk/AccessibilityCallbacksAtk.cpp297
-rw-r--r--Tools/DumpRenderTree/atk/AccessibilityControllerAtk.cpp145
-rw-r--r--Tools/DumpRenderTree/atk/AccessibilityNotificationHandlerAtk.cpp55
-rw-r--r--Tools/DumpRenderTree/atk/AccessibilityNotificationHandlerAtk.h51
-rw-r--r--Tools/DumpRenderTree/atk/AccessibilityUIElementAtk.cpp1604
-rw-r--r--Tools/DumpRenderTree/cairo/PixelDumpSupportCairo.cpp2
-rw-r--r--Tools/DumpRenderTree/cairo/PixelDumpSupportCairo.h2
-rw-r--r--Tools/DumpRenderTree/config.h43
-rw-r--r--Tools/DumpRenderTree/gtk/AccessibilityControllerGtk.cpp79
-rw-r--r--Tools/DumpRenderTree/gtk/DumpRenderTree.cpp1557
-rw-r--r--Tools/DumpRenderTree/gtk/DumpRenderTreeGtk.h50
-rw-r--r--Tools/DumpRenderTree/gtk/EditingCallbacks.cpp202
-rw-r--r--Tools/DumpRenderTree/gtk/EditingCallbacks.h35
-rw-r--r--Tools/DumpRenderTree/gtk/EventSender.cpp1004
-rw-r--r--Tools/DumpRenderTree/gtk/EventSender.h42
-rw-r--r--Tools/DumpRenderTree/gtk/GCControllerGtk.cpp50
-rw-r--r--Tools/DumpRenderTree/gtk/PixelDumpSupportGtk.cpp115
-rw-r--r--Tools/DumpRenderTree/gtk/SelfScrollingWebKitWebView.cpp78
-rw-r--r--Tools/DumpRenderTree/gtk/SelfScrollingWebKitWebView.h51
-rw-r--r--Tools/DumpRenderTree/gtk/TestRunnerGtk.cpp914
-rw-r--r--Tools/DumpRenderTree/gtk/TextInputController.cpp215
-rw-r--r--Tools/DumpRenderTree/gtk/WorkQueueItemGtk.cpp102
-rw-r--r--Tools/GNUmakefile.am277
-rw-r--r--Tools/GtkLauncher/GNUmakefile.am42
-rw-r--r--Tools/GtkLauncher/LauncherInspectorWindow.c115
-rw-r--r--Tools/GtkLauncher/main.c564
-rw-r--r--Tools/ImageDiff/CMakeLists.txt20
-rw-r--r--Tools/ImageDiff/PlatformGTK.cmake11
-rw-r--r--Tools/ImageDiff/gtk/ImageDiff.cpp17
-rw-r--r--Tools/MiniBrowser/Configurations/MiniBrowserCFLite.vsprops11
-rw-r--r--Tools/MiniBrowser/Configurations/MiniBrowserCommon.vsprops16
-rw-r--r--Tools/MiniBrowser/Configurations/MiniBrowserCoreFoundation.vsprops11
-rw-r--r--Tools/MiniBrowser/Configurations/MiniBrowserDebug.vsprops8
-rw-r--r--Tools/MiniBrowser/Configurations/MiniBrowserDebugAll.vsprops8
-rw-r--r--Tools/MiniBrowser/Configurations/MiniBrowserDebugCairoCFLite.vsprops8
-rw-r--r--Tools/MiniBrowser/Configurations/MiniBrowserLauncherCommon.vsprops13
-rw-r--r--Tools/MiniBrowser/Configurations/MiniBrowserLauncherDebug.vsprops8
-rw-r--r--Tools/MiniBrowser/Configurations/MiniBrowserLauncherDebugAll.vsprops8
-rw-r--r--Tools/MiniBrowser/Configurations/MiniBrowserLauncherDebugCairoCFLite.vsprops8
-rw-r--r--Tools/MiniBrowser/Configurations/MiniBrowserLauncherProduction.vsprops8
-rw-r--r--Tools/MiniBrowser/Configurations/MiniBrowserLauncherRelease.vsprops8
-rw-r--r--Tools/MiniBrowser/Configurations/MiniBrowserLauncherReleaseCairoCFLite.vsprops8
-rw-r--r--Tools/MiniBrowser/Configurations/MiniBrowserProduction.vsprops8
-rw-r--r--Tools/MiniBrowser/Configurations/MiniBrowserRelease.vsprops8
-rw-r--r--Tools/MiniBrowser/Configurations/MiniBrowserReleaseCairoCFLite.vsprops8
-rw-r--r--Tools/MiniBrowser/MBToolbarItem.h27
-rw-r--r--Tools/MiniBrowser/MiniBrowserWebProcessPlugIn.h34
-rw-r--r--Tools/MiniBrowser/gtk/BrowserDownloadsBar.c1
-rw-r--r--Tools/MiniBrowser/gtk/BrowserSearchBar.c12
-rw-r--r--Tools/MiniBrowser/gtk/BrowserWindow.c579
-rw-r--r--Tools/MiniBrowser/gtk/BrowserWindow.h3
-rw-r--r--Tools/MiniBrowser/gtk/CMakeLists.txt63
-rw-r--r--Tools/MiniBrowser/gtk/GNUmakefile.am75
-rw-r--r--Tools/MiniBrowser/gtk/main.c63
-rw-r--r--Tools/Scripts/VCSUtils.pm2338
-rwxr-xr-xTools/Scripts/run-gtk-tests468
-rwxr-xr-xTools/Scripts/webkit-build-directory84
-rwxr-xr-xTools/Scripts/webkitdirs.pm2649
-rw-r--r--Tools/TestWebKitAPI/CMakeLists.txt228
-rw-r--r--Tools/TestWebKitAPI/Configurations/TestWebKitAPICFLite.vsprops11
-rw-r--r--Tools/TestWebKitAPI/Configurations/TestWebKitAPICFNetwork.vsprops11
-rw-r--r--Tools/TestWebKitAPI/Configurations/TestWebKitAPICommon.vsprops16
-rw-r--r--Tools/TestWebKitAPI/Configurations/TestWebKitAPICoreFoundation.vsprops11
-rw-r--r--Tools/TestWebKitAPI/Configurations/TestWebKitAPIDebug.vsprops8
-rw-r--r--Tools/TestWebKitAPI/Configurations/TestWebKitAPIDebugAll.vsprops8
-rw-r--r--Tools/TestWebKitAPI/Configurations/TestWebKitAPIDebugCairoCFLite.vsprops8
-rw-r--r--Tools/TestWebKitAPI/Configurations/TestWebKitAPIInjectedBundleCommon.vsprops11
-rw-r--r--Tools/TestWebKitAPI/Configurations/TestWebKitAPIRelease.vsprops8
-rw-r--r--Tools/TestWebKitAPI/Configurations/TestWebKitAPIReleaseCairoCFLite.vsprops8
-rw-r--r--Tools/TestWebKitAPI/Counters.cpp34
-rw-r--r--Tools/TestWebKitAPI/Counters.h88
-rw-r--r--Tools/TestWebKitAPI/ForwardingHeaders/WebCore/LayoutUnit.h4
-rw-r--r--Tools/TestWebKitAPI/GNUmakefile.am934
-rw-r--r--Tools/TestWebKitAPI/InjectedBundleController.cpp7
-rw-r--r--Tools/TestWebKitAPI/InjectedBundleController.h4
-rw-r--r--Tools/TestWebKitAPI/InjectedBundleMain.cpp9
-rw-r--r--Tools/TestWebKitAPI/InjectedBundleTest.h2
-rw-r--r--Tools/TestWebKitAPI/JavaScriptTest.cpp9
-rw-r--r--Tools/TestWebKitAPI/JavaScriptTest.h13
-rw-r--r--Tools/TestWebKitAPI/PlatformGTK.cmake166
-rw-r--r--Tools/TestWebKitAPI/PlatformMac.cmake32
-rw-r--r--Tools/TestWebKitAPI/PlatformUtilities.cpp13
-rw-r--r--Tools/TestWebKitAPI/PlatformUtilities.h29
-rw-r--r--Tools/TestWebKitAPI/PlatformWebView.h43
-rw-r--r--Tools/TestWebKitAPI/Test.h16
-rw-r--r--Tools/TestWebKitAPI/Tests/JavaScriptCore/VMInspector.cpp689
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/AtomicString.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/BloomFilter.cpp250
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/CheckedArithmeticOperations.cpp554
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/Condition.cpp257
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/DateMath.cpp208
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/Deque.cpp191
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/HashCountedSet.cpp468
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp557
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/HashSet.cpp254
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/ListHashSet.cpp16
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/Lock.cpp189
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/MediaTime.cpp48
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/MetaAllocator.cpp6
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/NakedPtr.cpp238
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/OptionSet.cpp271
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/Optional.cpp150
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/ParkingLot.cpp275
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/RedBlackTree.cpp2
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/Ref.cpp57
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/RefCounter.cpp158
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/RefLogger.h2
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/RefPtr.cpp26
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/RunLoop.cpp57
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/StringBuilder.cpp25
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/StringHasher.cpp2
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp460
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/StringOperators.cpp16
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/StringView.cpp736
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/Vector.cpp428
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/WTFString.cpp295
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/WeakPtr.cpp187
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/WorkQueue.cpp203
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/darwin/OSObjectPtr.cpp66
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/glib/GUniquePtr.cpp (renamed from Tools/TestWebKitAPI/Tests/WTF/gobject/GUniquePtr.cpp)2
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/glib/WorkQueueGLib.cpp71
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/CSSParser.cpp88
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/CalculationValue.cpp283
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp2795
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/DFACombiner.cpp121
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/DFAHelpers.h67
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/DFAMinimizer.cpp121
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/FileSystem.cpp96
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/LayoutUnit.cpp42
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/ParsedContentRange.cpp98
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/PublicSuffix.cpp78
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/SharedBuffer.cpp119
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/TimeRanges.cpp293
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/gtk/UserAgentQuirks.cpp15
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/18-characters.html0
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/AboutBlankLoad.cpp5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/Ahem.ttfbin0 -> 12480 bytes
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/CanHandleRequest.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/CanHandleRequest_Bundle.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/CloseFromWithinCreatePage.cpp87
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/CloseThenTerminate.cpp5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/CookieManager.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewIsActiveSetIsActive.cpp131
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewIsActiveSetIsActive_Bundle.cpp52
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewRestoreZoomAndScrollBackForward.cpp129
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewUserViewportToContents.cpp148
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/backforward1.html5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/backforward2.html1
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic_Bundle.cpp19
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache.cpp5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache_Bundle.cpp19
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/DidAssociateFormControls.cpp5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/DidAssociateFormControls_Bundle.cpp11
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/DidNotHandleKeyDown.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/DocumentStartUserScriptAlertCrash.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/DocumentStartUserScriptAlertCrash_Bundle.cpp13
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/DownloadDecideDestinationCrash.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/EphemeralSessionPushStateNoHistoryCallback.cpp83
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/EvaluateJavaScript.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/FailedLoad.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/Find.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ForceRepaint.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypeHTML.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypePNG.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/Geolocation.cpp55
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback_Bundle.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/HitTestResultNodeHandle.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/HitTestResultNodeHandle_Bundle.cpp13
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic_Bundle.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleFrameHitTest.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleFrameHitTest_Bundle.cpp15
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins_Bundle.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleMakeAllShadowRootOpen_Bundle.cpp65
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleMakeAllShadowRootsOpen.cpp72
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/LayoutMilestonesWithAllContentInFrame.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/LoadAlternateHTMLStringWithNonDirectoryURL.cpp37
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/LoadCanceledNoServerRedirectCallback.cpp11
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/LoadCanceledNoServerRedirectCallback_Bundle.cpp11
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/LoadPageOnCrash.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/MenuTypesForMouseEvents.cpp149
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ModalAlertsSPI.cpp123
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/MouseMoveAfterCrash.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/MouseMoveAfterCrash_Bundle.cpp5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails_Bundle.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages_Bundle.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames.cpp11
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout_Bundle.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/PageLoadBasic.cpp28
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/PageLoadDidChangeLocationWithinPageForFrame.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ParentFrame.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ParentFrame_Bundle.cpp11
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/PasteboardNotifications_Bundle.cpp89
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/PendingAPIRequestURL.cpp162
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/PreventEmptyUserAgent.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/PrivateBrowsingPushStateNoHistoryCallback.cpp32
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ReloadPageAfterCrash.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ResizeReversePaginatedWebView.cpp11
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ResizeWindowAfterCrash.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ResponsivenessTimerDoesntFireEarly.cpp5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ResponsivenessTimerDoesntFireEarly_Bundle.cpp5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/RestoreSessionStateContainingFormData.cpp17
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ScrollPinningBehaviors.cpp13
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/SeccompFilters.cpp441
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ShouldGoToBackForwardListItem.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ShouldGoToBackForwardListItem_Bundle.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ShouldKeepCurrentBackForwardListItemInList.cpp163
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/SpacebarScrolling.cpp27
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/StopLoadingDuringDidFailProvisionalLoad.cpp83
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/StopLoadingDuringDidFailProvisionalLoad_bundle.cpp81
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/TerminateTwice.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/TextFieldDidBeginAndEndEditing.cpp131
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/TextFieldDidBeginAndEndEditing_Bundle.cpp76
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/UserMedia.cpp84
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/UserMessage.cpp13
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/UserMessage_Bundle.cpp5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WKBundleFileHandle.cpp86
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WKBundleFileHandle_Bundle.cpp99
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WKImageCreateCGImageCrash.cpp41
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WKPageConfiguration.cpp132
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WKPageCopySessionStateWithFiltering.cpp136
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WKPageGetScaleFactorNotZero.cpp15
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WKPageIsPlayingAudio.cpp152
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WKPreferences.cpp37
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WKRetainPtr.cpp (renamed from Tools/GtkLauncher/LauncherInspectorWindow.h)43
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WKString.cpp4
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WKStringJSString.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WebArchive.cpp135
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WebArchive_Bundle.cpp69
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WebCoreStatisticsWithNoWebProcess.cpp55
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WillLoad.cpp11
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WillLoad_Bundle.cpp13
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WillSendSubmitEvent.cpp5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WillSendSubmitEvent_Bundle.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/all-content-in-one-iframe.html1
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/associate-form-controls.html31
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/auto-submitting-form.html20
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/bundle-file.html16
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/close-from-within-create-page.html16
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/custom-protocol-sync-xhr.html6
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/execCopy.html15
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/file-with-anchor.html19
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/file-with-mse.html46
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/file-with-video.html18
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/find.html5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/findRanges.html11
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/geolocationGetCurrentPosition.html3
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/geolocationGetCurrentPositionWithHighAccuracy.html3
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/geolocationWatchPosition.html3
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/geolocationWatchPositionWithHighAccuracy.html3
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/getUserMedia.html14
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/gtk/InputMethodFilter.cpp (renamed from Tools/TestWebKitAPI/Tests/gtk/InputMethodFilter.cpp)100
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/icon.pngbin0 -> 36541 bytes
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/input-focus-blur.html18
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/link-with-title.html5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/lots-of-iframes.html35
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/lots-of-images.html17
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/lots-of-text-vertical-lr.html3
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/lots-of-text.html3
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/modal-alerts-in-new-about-blank-window.html13
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/mouse-button-listener.html30
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/mouse-move-listener.html16
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/open-and-close-window.html11
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/push-state.html3
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/should-open-external-schemes.html21
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/simple-accelerated-compositing.html5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/simple-form.html11
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/simple-iframe.html6
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/simple-tall.html7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/simple.html5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/simple2.html5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/simple3.html5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/spacebar-scrolling.html26
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/test-mse.mp4bin0 -> 80933 bytes
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/test.mp4bin0 -> 192844 bytes
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/webfont.html15
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.h28
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.html6
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-1.html46
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-2.html32
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBPersistence-1.html35
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBPersistence-2.html22
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/RemoteObjectRegistry.h48
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/AutocleanupsTest.cpp72
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/CMakeLists.txt135
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMDOMWindowTest.cpp221
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMNodeFilterTest.cpp204
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMNodeTest.cpp122
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMXPathNSResolverTest.cpp124
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/EditorTest.cpp131
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/FrameTest.cpp3
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestAuthentication.cpp30
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestAutocleanups.cpp64
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestBackForwardList.cpp137
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestConsoleMessage.cpp158
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestContextMenu.cpp208
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestCookieManager.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMDOMWindow.cpp152
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMNode.cpp37
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMNodeFilter.cpp55
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMXPathNSResolver.cpp52
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDownloads.cpp152
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestEditor.cpp (renamed from Tools/TestWebKitAPI/Tests/WebKitGtk/testapplicationcache.c)35
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestFrame.cpp2
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestInspector.cpp17
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestInspectorServer.cpp12
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestLoaderClient.cpp92
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestMultiprocess.cpp77
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestPrinting.cpp16
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestResources.cpp108
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestSSL.cpp210
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestUIClient.cpp407
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebExtensions.cpp70
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitAccessibility.cpp4
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFaviconDatabase.cpp44
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFindController.cpp2
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitPolicyClient.cpp15
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitSettings.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitUserContentManager.cpp388
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebContext.cpp278
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp369
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebViewGroup.cpp206
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebViewEditor.cpp328
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp163
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebProcessTest.cpp33
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebProcessTest.h4
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/blank.icobin0 -> 198 bytes
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/boring.html1
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/link-title.js1
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/test-cert.pem13
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/test-key.pem16
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/webkit2gtk-tests.gresource.xml7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2ObjC/CustomProtocolsInvalidScheme_Bundle.cpp66
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2ObjC/PreventImageLoadWithAutoResizing_Bundle.cpp69
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/test_utils.c51
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testatk.c1476
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testatkroles.c426
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testcontextmenu.c317
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testcopyandpaste.c266
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testdomdocument.c445
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testdomdomwindow.c258
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testdomnode.c219
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testdownload.c325
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testfavicondatabase.c279
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testglobals.c110
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testhittestresult.c171
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testhttpbackend.c75
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testkeyevents.c390
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testloading.c437
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testmimehandling.c206
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testnetworkrequest.c96
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testnetworkresponse.c97
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testwebbackforwardlist.c326
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testwebdatasource.c242
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testwebframe.c220
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testwebhistoryitem.c70
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testwebinspector.c173
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testwebplugindatabase.c78
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testwebresource.c334
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testwebsettings.c110
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testwebview.c749
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testwindow.c119
-rw-r--r--Tools/TestWebKitAPI/TestsController.cpp33
-rw-r--r--Tools/TestWebKitAPI/TestsController.h6
-rw-r--r--Tools/TestWebKitAPI/WKWebViewConfigurationExtras.h34
-rw-r--r--Tools/TestWebKitAPI/config.h34
-rw-r--r--Tools/TestWebKitAPI/gtk/PlatformUtilitiesGtk.cpp6
-rw-r--r--Tools/TestWebKitAPI/gtk/PlatformWebViewGtk.cpp38
-rw-r--r--Tools/TestWebKitAPI/gtk/WebKit2Gtk/LoadTrackingTest.cpp81
-rw-r--r--Tools/TestWebKitAPI/gtk/WebKit2Gtk/LoadTrackingTest.h6
-rw-r--r--Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.cpp23
-rw-r--r--Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.h61
-rw-r--r--Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.cpp2
-rw-r--r--Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.h2
-rw-r--r--Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestServer.cpp26
-rw-r--r--Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestServer.h13
-rw-r--r--Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.cpp82
-rw-r--r--Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.h13
-rw-r--r--Tools/TestWebKitAPI/gtk/main.cpp2
-rw-r--r--Tools/WebKitTestRunner/CMakeLists.txt126
-rw-r--r--Tools/WebKitTestRunner/DerivedSources.make62
-rw-r--r--Tools/WebKitTestRunner/EventSenderProxy.h27
-rw-r--r--Tools/WebKitTestRunner/FontWithFeatures.otfbin0 -> 14452 bytes
-rw-r--r--Tools/WebKitTestRunner/FontWithFeatures.ttfbin0 -> 12324 bytes
-rw-r--r--Tools/WebKitTestRunner/GNUmakefile.am175
-rw-r--r--Tools/WebKitTestRunner/GeolocationProviderMock.cpp4
-rw-r--r--Tools/WebKitTestRunner/GeolocationProviderMock.h4
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.cpp22
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.h6
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarker.cpp2
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarker.h6
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarkerRange.cpp2
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarkerRange.h6
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp60
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h59
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityController.idl45
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityTextMarker.idl29
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityTextMarkerRange.idl29
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl246
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/Bindings/CodeGeneratorTestRunner.pm570
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/Bindings/EventSendingController.idl72
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/Bindings/GCController.idl31
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl223
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/Bindings/TextInputController.idl32
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/EventSendingController.cpp327
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/EventSendingController.h16
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/GCController.cpp8
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp254
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h30
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/InjectedBundleMain.cpp4
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp542
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.h7
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp422
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/TestRunner.h66
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/TextInputController.cpp10
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityControllerAtk.cpp29
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.cpp69
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.h3
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityUIElementAtk.cpp498
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/gtk/ActivateFontsGtk.cpp10
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/gtk/InjectedBundleUtilities.cpp6
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/gtk/InjectedBundleUtilities.h2
-rw-r--r--Tools/WebKitTestRunner/InjectedBundle/gtk/TestRunnerGtk.cpp25
-rw-r--r--Tools/WebKitTestRunner/Options.cpp43
-rw-r--r--Tools/WebKitTestRunner/Options.h9
-rw-r--r--Tools/WebKitTestRunner/PixelDumpSupport.cpp2
-rw-r--r--Tools/WebKitTestRunner/PixelDumpSupport.h2
-rw-r--r--Tools/WebKitTestRunner/PlatformGTK.cmake60
-rw-r--r--Tools/WebKitTestRunner/PlatformWebView.h60
-rw-r--r--Tools/WebKitTestRunner/StringFunctions.h8
-rw-r--r--Tools/WebKitTestRunner/TestController.cpp1190
-rw-r--r--Tools/WebKitTestRunner/TestController.h160
-rw-r--r--Tools/WebKitTestRunner/TestInvocation.cpp485
-rw-r--r--Tools/WebKitTestRunner/TestInvocation.h67
-rw-r--r--Tools/WebKitTestRunner/TestOptions.cpp72
-rw-r--r--Tools/WebKitTestRunner/TestOptions.h51
-rw-r--r--Tools/WebKitTestRunner/UIScriptContext/Bindings/UIScriptController.idl60
-rw-r--r--Tools/WebKitTestRunner/UIScriptContext/UIScriptContext.cpp202
-rw-r--r--Tools/WebKitTestRunner/UIScriptContext/UIScriptContext.h100
-rw-r--r--Tools/WebKitTestRunner/UIScriptContext/UIScriptController.cpp200
-rw-r--r--Tools/WebKitTestRunner/UIScriptContext/UIScriptController.h101
-rw-r--r--Tools/WebKitTestRunner/WebKitTestRunner.sln104
-rw-r--r--Tools/WebKitTestRunner/WebKitTestRunnerApp/AppDelegate.h15
-rw-r--r--Tools/WebKitTestRunner/WebKitTestRunnerPrefix.h7
-rw-r--r--Tools/WebKitTestRunner/WebNotificationProvider.cpp94
-rw-r--r--Tools/WebKitTestRunner/WebNotificationProvider.h12
-rw-r--r--Tools/WebKitTestRunner/WorkQueueManager.cpp22
-rw-r--r--Tools/WebKitTestRunner/WorkQueueManager.h5
-rw-r--r--Tools/WebKitTestRunner/cairo/TestInvocationCairo.cpp11
-rw-r--r--Tools/WebKitTestRunner/config.h (renamed from Tools/DumpRenderTree/gtk/TextInputController.h)36
-rw-r--r--Tools/WebKitTestRunner/gtk/EventSenderProxyGtk.cpp32
-rw-r--r--Tools/WebKitTestRunner/gtk/PlatformWebViewGtk.cpp85
-rw-r--r--Tools/WebKitTestRunner/gtk/TestControllerGtk.cpp82
-rw-r--r--Tools/WebKitTestRunner/gtk/fonts/AHEM____.TTFbin0 -> 12480 bytes
-rw-r--r--Tools/WebKitTestRunner/gtk/fonts/FontWithNoValidEncoding.fonbin0 -> 8368 bytes
-rw-r--r--Tools/WebKitTestRunner/gtk/fonts/fonts.conf435
-rw-r--r--Tools/WebKitTestRunner/gtk/main.cpp9
-rw-r--r--Tools/gtk/GNUmakefile.am153
-rwxr-xr-xTools/gtk/check-for-webkitdom-api-breaks23
-rw-r--r--Tools/gtk/common.py52
-rwxr-xr-xTools/gtk/generate-feature-defines-files58
-rwxr-xr-xTools/gtk/generate-gtkdoc62
-rwxr-xr-xTools/gtk/generate-inspector-gresource-manifest.py14
-rw-r--r--Tools/gtk/gtkdoc.py21
-rwxr-xr-xTools/gtk/install-dependencies436
-rw-r--r--Tools/gtk/jhbuild-webrtc.modules132
-rw-r--r--Tools/gtk/jhbuild.modules516
-rw-r--r--Tools/gtk/jhbuildrc37
-rwxr-xr-xTools/gtk/make-dist.py327
-rw-r--r--Tools/gtk/manifest.txt.in106
-rw-r--r--Tools/gtk/patches/fontconfig-C-11-requires-a-space-between-literal-and-identifier.patch30
-rw-r--r--Tools/gtk/patches/fontconfig-fix-osx-cache.diff207
-rw-r--r--Tools/gtk/patches/freetype6-2.4.11-truetype-font-height-fix.patch39
-rw-r--r--Tools/gtk/patches/glib-warning-fix.patch34
-rw-r--r--Tools/gtk/patches/librsvg-2.36.1-bump-up-config.guess-to-support-aarch64.patch1581
-rw-r--r--Tools/gtk/patches/mesa-gallivm-Fix-build-after-LLVM-commit-211259.patch29
-rw-r--r--Tools/gtk/patches/rtspsrc-timeout-on-udpsrc-is-in-nanoseconds.patch27
-rw-r--r--Tools/gtk/patches/shared-mime-info-xht-glob.patch21
-rw-r--r--Tools/gtk/patches/shared-mime-info-xhtml-magic.patch26
-rw-r--r--Tools/gtk/patches/udpsrc-improve-timeouts.patch53
-rw-r--r--Tools/gtk/patches/xserver-remove-bogus-dependencies.patch43
-rwxr-xr-xTools/gtk/webkitdom.py72
-rw-r--r--Tools/gtk/ycm_extra_conf.py133
-rw-r--r--Tools/jhbuild/jhbuildutils.py56
532 files changed, 39380 insertions, 21079 deletions
diff --git a/Tools/CMakeLists.txt b/Tools/CMakeLists.txt
new file mode 100644
index 000000000..03af222ca
--- /dev/null
+++ b/Tools/CMakeLists.txt
@@ -0,0 +1,38 @@
+if ("${PORT}" STREQUAL "Efl")
+ if (DEVELOPER_MODE)
+ add_subdirectory(WebKitTestRunner)
+ add_subdirectory(ImageDiff)
+ if (ENABLE_X11_TARGET)
+ add_subdirectory(DumpRenderTree/TestNetscapePlugIn)
+ endif ()
+ endif ()
+
+ if (ENABLE_MINIBROWSER)
+ add_subdirectory(MiniBrowser/efl)
+ endif ()
+elseif ("${PORT}" STREQUAL "GTK")
+ if (DEVELOPER_MODE)
+ add_subdirectory(WebKitTestRunner)
+ add_subdirectory(ImageDiff)
+ if (ENABLE_API_TESTS)
+ add_subdirectory(TestWebKitAPI/Tests/WebKit2Gtk)
+ endif ()
+ if (ENABLE_X11_TARGET)
+ add_subdirectory(DumpRenderTree/TestNetscapePlugIn)
+ endif ()
+ endif ()
+
+ if (ENABLE_MINIBROWSER)
+ add_subdirectory(MiniBrowser/gtk)
+ endif ()
+endif ()
+
+if (WIN32)
+ add_subdirectory(DumpRenderTree)
+ add_subdirectory(TestWebKitAPI)
+ add_subdirectory(MiniBrowser/win)
+endif ()
+
+if (ENABLE_WEBKIT2 AND ENABLE_API_TESTS)
+ add_subdirectory(TestWebKitAPI)
+endif ()
diff --git a/Tools/DumpRenderTree/AccessibilityController.cpp b/Tools/DumpRenderTree/AccessibilityController.cpp
index dd9996be8..d035dea99 100644
--- a/Tools/DumpRenderTree/AccessibilityController.cpp
+++ b/Tools/DumpRenderTree/AccessibilityController.cpp
@@ -130,6 +130,20 @@ static JSValueRef removeNotificationListenerCallback(JSContextRef context, JSObj
return JSValueMakeUndefined(context);
}
+static JSValueRef enableEnhancedAccessibilityCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ AccessibilityController* controller = static_cast<AccessibilityController*>(JSObjectGetPrivate(thisObject));
+ if (argumentCount == 1)
+ controller->enableEnhancedAccessibility(JSValueToBoolean(context, arguments[0]));
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef getEnhancedAccessibilityEnabledCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
+{
+ AccessibilityController* controller = static_cast<AccessibilityController*>(JSObjectGetPrivate(thisObject));
+ return JSValueMakeBoolean(context, controller->enhancedAccessibilityEnabled());
+}
+
static JSValueRef getPlatformNameCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
{
AccessibilityController* controller = static_cast<AccessibilityController*>(JSObjectGetPrivate(thisObject));
@@ -150,12 +164,14 @@ JSClassRef AccessibilityController::getJSClass()
{ "accessibleElementById", getAccessibleElementByIdCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "addNotificationListener", addNotificationListenerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "removeNotificationListener", removeNotificationListenerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "enableEnhancedAccessibility", enableEnhancedAccessibilityCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ 0, 0, 0 }
};
static JSStaticValue staticValues[] = {
{ "focusedElement", getFocusedElementCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "rootElement", getRootElementCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "enhancedAccessibilityEnabled", getEnhancedAccessibilityEnabledCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "platformName", getPlatformNameCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ 0, 0, 0, 0 }
};
diff --git a/Tools/DumpRenderTree/AccessibilityController.h b/Tools/DumpRenderTree/AccessibilityController.h
index 2f4f6ae9e..9f66dd6ee 100644
--- a/Tools/DumpRenderTree/AccessibilityController.h
+++ b/Tools/DumpRenderTree/AccessibilityController.h
@@ -64,6 +64,10 @@ public:
bool addNotificationListener(JSObjectRef functionCallback);
void removeNotificationListener();
+ // Enhanced accessibility.
+ void enableEnhancedAccessibility(bool);
+ bool enhancedAccessibilityEnabled();
+
JSRetainPtr<JSStringRef> platformName() const;
#if PLATFORM(WIN)
@@ -89,7 +93,7 @@ private:
HashMap<PlatformUIElement, JSObjectRef> m_notificationListeners;
#endif
-#if PLATFORM(MAC)
+#if PLATFORM(COCOA) || PLATFORM(IOS)
RetainPtr<NotificationHandler> m_globalNotificationHandler;
#endif
diff --git a/Tools/DumpRenderTree/AccessibilityTextMarker.h b/Tools/DumpRenderTree/AccessibilityTextMarker.h
index b890e28a9..7809ea459 100644
--- a/Tools/DumpRenderTree/AccessibilityTextMarker.h
+++ b/Tools/DumpRenderTree/AccessibilityTextMarker.h
@@ -28,13 +28,13 @@
#include <JavaScriptCore/JSObjectRef.h>
-#if PLATFORM(MAC) && !PLATFORM(IOS)
+#if PLATFORM(MAC) || PLATFORM(IOS)
#define SUPPORTS_AX_TEXTMARKERS 1
#else
#define SUPPORTS_AX_TEXTMARKERS 0
#endif
-#if PLATFORM(MAC)
+#if PLATFORM(COCOA)
#include <wtf/RetainPtr.h>
typedef CFTypeRef PlatformTextMarker;
typedef CFTypeRef PlatformTextMarkerRange;
@@ -58,7 +58,7 @@ public:
private:
static JSClassRef getJSClass();
-#if SUPPORTS_AX_TEXTMARKERS
+#if SUPPORTS_AX_TEXTMARKERS && PLATFORM(MAC)
RetainPtr<PlatformTextMarker> m_textMarker;
#else
PlatformTextMarker m_textMarker;
@@ -78,7 +78,7 @@ public:
private:
static JSClassRef getJSClass();
-#if SUPPORTS_AX_TEXTMARKERS
+#if SUPPORTS_AX_TEXTMARKERS && PLATFORM(MAC)
RetainPtr<PlatformTextMarkerRange> m_textMarkerRange;
#else
PlatformTextMarkerRange m_textMarkerRange;
diff --git a/Tools/DumpRenderTree/AccessibilityUIElement.cpp b/Tools/DumpRenderTree/AccessibilityUIElement.cpp
index 793b3103d..1d77d7717 100644
--- a/Tools/DumpRenderTree/AccessibilityUIElement.cpp
+++ b/Tools/DumpRenderTree/AccessibilityUIElement.cpp
@@ -209,7 +209,8 @@ static JSValueRef uiElementCountForSearchPredicateCallback(JSContextRef context,
JSValueRef searchKey = nullptr;
JSRetainPtr<JSStringRef> searchText = nullptr;
bool visibleOnly = false;
- if (argumentCount == 5) {
+ bool immediateDescendantsOnly = false;
+ if (argumentCount >= 5 && argumentCount <= 6) {
if (JSValueIsObject(context, arguments[0]))
startElement = toAXElement(JSValueToObject(context, arguments[0], exception));
@@ -221,9 +222,12 @@ static JSValueRef uiElementCountForSearchPredicateCallback(JSContextRef context,
searchText.adopt(JSValueToStringCopy(context, arguments[3], exception));
visibleOnly = JSValueToBoolean(context, arguments[4]);
+
+ if (argumentCount == 6)
+ immediateDescendantsOnly = JSValueToBoolean(context, arguments[5]);
}
- return JSValueMakeNumber(context, toAXElement(thisObject)->uiElementCountForSearchPredicate(context, startElement, isDirectionNext, searchKey, searchText.get(), visibleOnly));
+ return JSValueMakeNumber(context, toAXElement(thisObject)->uiElementCountForSearchPredicate(context, startElement, isDirectionNext, searchKey, searchText.get(), visibleOnly, immediateDescendantsOnly));
}
static JSValueRef uiElementForSearchPredicateCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
@@ -233,7 +237,8 @@ static JSValueRef uiElementForSearchPredicateCallback(JSContextRef context, JSOb
JSValueRef searchKey = nullptr;
JSRetainPtr<JSStringRef> searchText = nullptr;
bool visibleOnly = false;
- if (argumentCount == 5) {
+ bool immediateDescendantsOnly = false;
+ if (argumentCount >= 5 && argumentCount <= 6) {
if (JSValueIsObject(context, arguments[0]))
startElement = toAXElement(JSValueToObject(context, arguments[0], exception));
@@ -245,9 +250,34 @@ static JSValueRef uiElementForSearchPredicateCallback(JSContextRef context, JSOb
searchText.adopt(JSValueToStringCopy(context, arguments[3], exception));
visibleOnly = JSValueToBoolean(context, arguments[4]);
+
+ if (argumentCount == 6)
+ immediateDescendantsOnly = JSValueToBoolean(context, arguments[5]);
}
- return AccessibilityUIElement::makeJSAccessibilityUIElement(context, toAXElement(thisObject)->uiElementForSearchPredicate(context, startElement, isDirectionNext, searchKey, searchText.get(), visibleOnly));
+ return AccessibilityUIElement::makeJSAccessibilityUIElement(context, toAXElement(thisObject)->uiElementForSearchPredicate(context, startElement, isDirectionNext, searchKey, searchText.get(), visibleOnly, immediateDescendantsOnly));
+}
+
+static JSValueRef selectTextWithCriteriaCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ if (argumentCount < 2 || argumentCount > 4)
+ return JSValueMakeUndefined(context);
+
+ JSRetainPtr<JSStringRef> ambiguityResolution(Adopt, JSValueToStringCopy(context, arguments[0], exception));
+ JSValueRef searchStrings = arguments[1];
+ JSStringRef replacementString = nullptr;
+ if (argumentCount == 3)
+ replacementString = JSValueToStringCopy(context, arguments[2], exception);
+ JSStringRef activityString = nullptr;
+ if (argumentCount == 4)
+ activityString = JSValueToStringCopy(context, arguments[3], exception);
+
+ JSRetainPtr<JSStringRef> result(Adopt, toAXElement(thisObject)->selectTextWithCriteria(context, ambiguityResolution.get(), searchStrings, replacementString, activityString));
+ if (replacementString)
+ JSStringRelease(replacementString);
+ if (activityString)
+ JSStringRelease(activityString);
+ return JSValueMakeString(context, result.get());
}
static JSValueRef indexOfChildCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
@@ -287,12 +317,13 @@ static JSValueRef elementsForRangeCallback(JSContextRef context, JSObjectRef fun
Vector<AccessibilityUIElement> elements;
toAXElement(thisObject)->elementsForRange(location, length, elements);
+ JSValueRef arrayResult = JSObjectMakeArray(context, 0, 0, 0);
+ JSObjectRef arrayObj = JSValueToObject(context, arrayResult, 0);
unsigned elementsSize = elements.size();
- JSValueRef valueElements[elementsSize];
for (unsigned k = 0; k < elementsSize; ++k)
- valueElements[k] = AccessibilityUIElement::makeJSAccessibilityUIElement(context, elements[k]);
+ JSObjectSetPropertyAtIndex(context, arrayObj, k, AccessibilityUIElement::makeJSAccessibilityUIElement(context, elements[k]), 0);
- return JSObjectMakeArray(context, elementsSize, valueElements, 0);
+ return arrayResult;
}
static JSValueRef increaseTextSelectionCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
@@ -301,6 +332,26 @@ static JSValueRef increaseTextSelectionCallback(JSContextRef context, JSObjectRe
return JSValueMakeUndefined(context);
}
+static JSValueRef scrollPageUpCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ return JSValueMakeBoolean(context, toAXElement(thisObject)->scrollPageUp());
+}
+
+static JSValueRef scrollPageDownCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ return JSValueMakeBoolean(context, toAXElement(thisObject)->scrollPageDown());
+}
+
+static JSValueRef scrollPageLeftCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ return JSValueMakeBoolean(context, toAXElement(thisObject)->scrollPageLeft());
+}
+
+static JSValueRef scrollPageRightCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ return JSValueMakeBoolean(context, toAXElement(thisObject)->scrollPageRight());
+}
+
static JSValueRef decreaseTextSelectionCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
toAXElement(thisObject)->decreaseTextSelection();
@@ -313,6 +364,11 @@ static JSValueRef assistiveTechnologySimulatedFocusCallback(JSContextRef context
return JSValueMakeUndefined(context);
}
+static JSValueRef fieldsetAncestorElementCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ return AccessibilityUIElement::makeJSAccessibilityUIElement(context, toAXElement(thisObject)->fieldsetAncestorElement());
+}
+
#endif
static JSValueRef childAtIndexCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
@@ -369,6 +425,15 @@ static JSValueRef ariaFlowToElementAtIndexCallback(JSContextRef context, JSObjec
return AccessibilityUIElement::makeJSAccessibilityUIElement(context, toAXElement(thisObject)->ariaFlowToElementAtIndex(indexNumber));
}
+static JSValueRef ariaControlsElementAtIndexCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ int indexNumber = 0;
+ if (argumentCount == 1)
+ indexNumber = JSValueToNumber(context, arguments[0], exception);
+
+ return AccessibilityUIElement::makeJSAccessibilityUIElement(context, toAXElement(thisObject)->ariaControlsElementAtIndex(indexNumber));
+}
+
static JSValueRef selectedRowAtIndexCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
int indexNumber = 0;
@@ -398,6 +463,19 @@ static JSValueRef isEqualCallback(JSContextRef context, JSObjectRef function, JS
return JSValueMakeBoolean(context, toAXElement(thisObject)->isEqual(toAXElement(otherElement)));
}
+static JSValueRef setValueCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ JSRetainPtr<JSStringRef> valueText = 0;
+ if (argumentCount == 1) {
+ if (JSValueIsString(context, arguments[0]))
+ valueText.adopt(JSValueToStringCopy(context, arguments[0], exception));
+ }
+
+ toAXElement(thisObject)->setValue(valueText.get());
+
+ return JSValueMakeUndefined(context);
+}
+
static JSValueRef setSelectedChildCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
JSObjectRef element = 0;
@@ -409,6 +487,24 @@ static JSValueRef setSelectedChildCallback(JSContextRef context, JSObjectRef fun
return JSValueMakeUndefined(context);
}
+static JSValueRef setSelectedChildAtIndexCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ if (argumentCount == 1) {
+ unsigned indexNumber = JSValueToNumber(context, arguments[0], exception);
+ toAXElement(thisObject)->setSelectedChildAtIndex(indexNumber);
+ }
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef removeSelectionAtIndexCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ if (argumentCount == 1) {
+ unsigned indexNumber = JSValueToNumber(context, arguments[0], exception);
+ toAXElement(thisObject)->removeSelectionAtIndex(indexNumber);
+ }
+ return JSValueMakeUndefined(context);
+}
+
static JSValueRef elementAtPointCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
int x = 0;
@@ -470,6 +566,20 @@ static JSValueRef boolAttributeValueCallback(JSContextRef context, JSObjectRef f
return result;
}
+static JSValueRef setBoolAttributeValueCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ JSStringRef attribute = nullptr;
+ bool value = false;
+ if (argumentCount == 2) {
+ attribute = JSValueToStringCopy(context, arguments[0], exception);
+ value = JSValueToBoolean(context, arguments[1]);
+ }
+ toAXElement(thisObject)->setBoolAttributeValue(attribute, value);
+ if (attribute)
+ JSStringRelease(attribute);
+ return JSValueMakeUndefined(context);
+}
+
static JSValueRef stringAttributeValueCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
JSStringRef attribute = 0;
@@ -484,12 +594,14 @@ static JSValueRef stringAttributeValueCallback(JSContextRef context, JSObjectRef
static JSValueRef convertElementsToObjectArray(JSContextRef context, Vector<AccessibilityUIElement>& elements, JSValueRef* exception)
{
+ JSValueRef arrayResult = JSObjectMakeArray(context, 0, 0, 0);
+ JSObjectRef arrayObj = JSValueToObject(context, arrayResult, 0);
+
size_t elementCount = elements.size();
- auto valueElements = std::make_unique<JSValueRef[]>(elementCount);
for (size_t i = 0; i < elementCount; ++i)
- valueElements[i] = AccessibilityUIElement::makeJSAccessibilityUIElement(context, elements[i]);
-
- return JSObjectMakeArray(context, elementCount, valueElements.get(), exception);
+ JSObjectSetPropertyAtIndex(context, arrayObj, i, AccessibilityUIElement::makeJSAccessibilityUIElement(context, elements[i]), 0);
+
+ return arrayResult;
}
static JSValueRef columnHeadersCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
@@ -601,6 +713,36 @@ static JSValueRef pressCallback(JSContextRef context, JSObjectRef function, JSOb
return JSValueMakeUndefined(context);
}
+static JSValueRef scrollToMakeVisibleWithSubFocusCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ unsigned x = 0;
+ unsigned y = 0;
+ unsigned width = 0;
+ unsigned height = 0;
+ if (argumentCount == 4) {
+ x = JSValueToNumber(context, arguments[0], exception);
+ y = JSValueToNumber(context, arguments[1], exception);
+ width = JSValueToNumber(context, arguments[2], exception);
+ height = JSValueToNumber(context, arguments[3], exception);
+ }
+
+ toAXElement(thisObject)->scrollToMakeVisibleWithSubFocus(x, y, width, height);
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef scrollToGlobalPointCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ unsigned x = 0;
+ unsigned y = 0;
+ if (argumentCount == 2) {
+ x = JSValueToNumber(context, arguments[0], exception);
+ y = JSValueToNumber(context, arguments[1], exception);
+ }
+
+ toAXElement(thisObject)->scrollToGlobalPoint(x, y);
+ return JSValueMakeUndefined(context);
+}
+
static JSValueRef scrollToMakeVisibleCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
toAXElement(thisObject)->scrollToMakeVisible();
@@ -631,6 +773,14 @@ static JSValueRef removeSelectionCallback(JSContextRef context, JSObjectRef func
return JSValueMakeUndefined(context);
}
+static JSValueRef lineTextMarkerRangeForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ AccessibilityTextMarker* textMarker = nullptr;
+ if (argumentCount == 1)
+ textMarker = toTextMarker(JSValueToObject(context, arguments[0], exception));
+ return AccessibilityTextMarkerRange::makeJSAccessibilityTextMarkerRange(context, toAXElement(thisObject)->lineTextMarkerRangeForTextMarker(textMarker));
+}
+
static JSValueRef textMarkerRangeForElementCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
AccessibilityUIElement* uiElement = 0;
@@ -640,6 +790,17 @@ static JSValueRef textMarkerRangeForElementCallback(JSContextRef context, JSObje
return AccessibilityTextMarkerRange::makeJSAccessibilityTextMarkerRange(context, toAXElement(thisObject)->textMarkerRangeForElement(uiElement));
}
+static JSValueRef selectedTextMarkerRangeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ return AccessibilityTextMarkerRange::makeJSAccessibilityTextMarkerRange(context, toAXElement(thisObject)->selectedTextMarkerRange());
+}
+
+static JSValueRef resetSelectedTextMarkerRangeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ toAXElement(thisObject)->resetSelectedTextMarkerRange();
+ return JSValueMakeUndefined(context);
+}
+
static JSValueRef attributedStringForTextMarkerRangeContainsAttributeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
AccessibilityTextMarkerRange* markerRange = 0;
@@ -813,6 +974,109 @@ static JSValueRef endTextMarkerCallback(JSContextRef context, JSObjectRef thisOb
return AccessibilityTextMarker::makeJSAccessibilityTextMarker(context, toAXElement(thisObject)->endTextMarker());
}
+static JSValueRef leftWordTextMarkerRangeForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ AccessibilityTextMarker* marker = nullptr;
+ if (argumentCount == 1)
+ marker = toTextMarker(JSValueToObject(context, arguments[0], exception));
+
+ return AccessibilityTextMarkerRange::makeJSAccessibilityTextMarkerRange(context, toAXElement(thisObject)->leftWordTextMarkerRangeForTextMarker(marker));
+}
+
+static JSValueRef rightWordTextMarkerRangeForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ AccessibilityTextMarker* marker = nullptr;
+ if (argumentCount == 1)
+ marker = toTextMarker(JSValueToObject(context, arguments[0], exception));
+
+ return AccessibilityTextMarkerRange::makeJSAccessibilityTextMarkerRange(context, toAXElement(thisObject)->rightWordTextMarkerRangeForTextMarker(marker));
+}
+
+static JSValueRef previousWordStartTextMarkerForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ AccessibilityTextMarker* marker = nullptr;
+ if (argumentCount == 1)
+ marker = toTextMarker(JSValueToObject(context, arguments[0], exception));
+
+ return AccessibilityTextMarker::makeJSAccessibilityTextMarker(context, toAXElement(thisObject)->previousWordStartTextMarkerForTextMarker(marker));
+}
+
+static JSValueRef nextWordEndTextMarkerForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ AccessibilityTextMarker* marker = nullptr;
+ if (argumentCount == 1)
+ marker = toTextMarker(JSValueToObject(context, arguments[0], exception));
+
+ return AccessibilityTextMarker::makeJSAccessibilityTextMarker(context, toAXElement(thisObject)->nextWordEndTextMarkerForTextMarker(marker));
+}
+
+static JSValueRef paragraphTextMarkerRangeForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ AccessibilityTextMarker* marker = nullptr;
+ if (argumentCount == 1)
+ marker = toTextMarker(JSValueToObject(context, arguments[0], exception));
+
+ return AccessibilityTextMarkerRange::makeJSAccessibilityTextMarkerRange(context, toAXElement(thisObject)->paragraphTextMarkerRangeForTextMarker(marker));
+}
+
+static JSValueRef previousParagraphStartTextMarkerForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ AccessibilityTextMarker* marker = nullptr;
+ if (argumentCount == 1)
+ marker = toTextMarker(JSValueToObject(context, arguments[0], exception));
+
+ return AccessibilityTextMarker::makeJSAccessibilityTextMarker(context, toAXElement(thisObject)->previousParagraphStartTextMarkerForTextMarker(marker));
+}
+
+static JSValueRef nextParagraphEndTextMarkerForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ AccessibilityTextMarker* marker = nullptr;
+ if (argumentCount == 1)
+ marker = toTextMarker(JSValueToObject(context, arguments[0], exception));
+
+ return AccessibilityTextMarker::makeJSAccessibilityTextMarker(context, toAXElement(thisObject)->nextParagraphEndTextMarkerForTextMarker(marker));
+}
+
+static JSValueRef sentenceTextMarkerRangeForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ AccessibilityTextMarker* marker = nullptr;
+ if (argumentCount == 1)
+ marker = toTextMarker(JSValueToObject(context, arguments[0], exception));
+
+ return AccessibilityTextMarkerRange::makeJSAccessibilityTextMarkerRange(context, toAXElement(thisObject)->sentenceTextMarkerRangeForTextMarker(marker));
+}
+
+static JSValueRef previousSentenceStartTextMarkerForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ AccessibilityTextMarker* marker = nullptr;
+ if (argumentCount == 1)
+ marker = toTextMarker(JSValueToObject(context, arguments[0], exception));
+
+ return AccessibilityTextMarker::makeJSAccessibilityTextMarker(context, toAXElement(thisObject)->previousSentenceStartTextMarkerForTextMarker(marker));
+}
+
+static JSValueRef nextSentenceEndTextMarkerForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ AccessibilityTextMarker* marker = nullptr;
+ if (argumentCount == 1)
+ marker = toTextMarker(JSValueToObject(context, arguments[0], exception));
+
+ return AccessibilityTextMarker::makeJSAccessibilityTextMarker(context, toAXElement(thisObject)->nextSentenceEndTextMarkerForTextMarker(marker));
+}
+
+static JSValueRef setSelectedVisibleTextRangeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ AccessibilityUIElement* uiElement = toAXElement(thisObject);
+ AccessibilityTextMarkerRange* textMarkerRange = nullptr;
+ if (argumentCount == 1)
+ textMarkerRange = toTextMarkerRange(JSValueToObject(context, arguments[0], exception));
+
+ if (uiElement)
+ return JSValueMakeBoolean(context, uiElement->setSelectedVisibleTextRange(textMarkerRange));
+
+ return JSValueMakeBoolean(context, false);
+}
+
// Static Value Getters
static JSValueRef getARIADropEffectsCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
@@ -861,6 +1125,12 @@ static JSValueRef getRoleDescriptionCallback(JSContextRef context, JSObjectRef t
return JSValueMakeString(context, roleDesc.get());
}
+static JSValueRef getComputedRoleStringCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
+{
+ JSRetainPtr<JSStringRef> compRole(Adopt, toAXElement(thisObject)->computedRoleString());
+ return JSValueMakeString(context, compRole.get());
+}
+
static JSValueRef getTitleCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
{
JSRetainPtr<JSStringRef> title(Adopt, toAXElement(thisObject)->title());
@@ -1169,56 +1439,48 @@ static JSValueRef sentenceAtOffsetCallback(JSContextRef context, JSObjectRef fun
#elif PLATFORM(IOS)
-static JSValueRef stringForSelectionCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
+static JSValueRef getIsSearchFieldCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
{
- JSRetainPtr<JSStringRef> labelString(Adopt, toAXElement(thisObject)->stringForSelection());
- return JSValueMakeString(context, labelString.get());
-}
-
-static JSValueRef getIPhoneLabelCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
-{
- JSRetainPtr<JSStringRef> labelString(Adopt, toAXElement(thisObject)->iphoneLabel());
- return JSValueMakeString(context, labelString.get());
+ return JSValueMakeBoolean(context, toAXElement(thisObject)->isSearchField());
}
-static JSValueRef getIPhoneHintCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
+static JSValueRef getIsTextAreaCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
{
- JSRetainPtr<JSStringRef> hintString(Adopt, toAXElement(thisObject)->iphoneHint());
- return JSValueMakeString(context, hintString.get());
+ return JSValueMakeBoolean(context, toAXElement(thisObject)->isTextArea());
}
-static JSValueRef getIPhoneValueCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
+static JSValueRef stringForSelectionCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
{
- JSRetainPtr<JSStringRef> valueString(Adopt, toAXElement(thisObject)->iphoneValue());
- return JSValueMakeString(context, valueString.get());
+ JSRetainPtr<JSStringRef> labelString(Adopt, toAXElement(thisObject)->stringForSelection());
+ return JSValueMakeString(context, labelString.get());
}
-static JSValueRef getIPhoneIdentifierCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
+static JSValueRef getIdentifierCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
{
- JSRetainPtr<JSStringRef> valueString(Adopt, toAXElement(thisObject)->iphoneIdentifier());
+ JSRetainPtr<JSStringRef> valueString(Adopt, toAXElement(thisObject)->identifier());
return JSValueMakeString(context, valueString.get());
}
-static JSValueRef getIPhoneTraitsCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
+static JSValueRef getTraitsCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
{
- JSRetainPtr<JSStringRef> valueString(Adopt, toAXElement(thisObject)->iphoneTraits());
+ JSRetainPtr<JSStringRef> valueString(Adopt, toAXElement(thisObject)->traits());
return JSValueMakeString(context, valueString.get());
}
-static JSValueRef getIPhoneIsElementCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
+static JSValueRef getElementTextPositionCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
{
- return JSValueMakeBoolean(context, toAXElement(thisObject)->iphoneIsElement());
+ return JSValueMakeNumber(context, toAXElement(thisObject)->elementTextPosition());
}
-static JSValueRef getIPhoneElementTextPositionCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
+static JSValueRef getElementTextLengthCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
{
- return JSValueMakeNumber(context, toAXElement(thisObject)->iphoneElementTextPosition());
+ return JSValueMakeNumber(context, toAXElement(thisObject)->elementTextLength());
}
-static JSValueRef getIPhoneElementTextLengthCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
+static JSValueRef hasContainedByFieldsetTraitCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef, JSValueRef*)
{
- return JSValueMakeNumber(context, toAXElement(thisObject)->iphoneElementTextLength());
+ return JSValueMakeBoolean(context, toAXElement(thisObject)->hasContainedByFieldsetTrait());
}
#endif // PLATFORM(IOS)
@@ -1252,8 +1514,8 @@ JSStringRef AccessibilityUIElement::speak() { return 0; }
JSStringRef AccessibilityUIElement::rangeForLine(int line) { return 0; }
JSStringRef AccessibilityUIElement::rangeForPosition(int, int) { return 0; }
void AccessibilityUIElement::setSelectedChild(AccessibilityUIElement*) const { }
-unsigned AccessibilityUIElement::selectedChildrenCount() const { return 0; }
-AccessibilityUIElement AccessibilityUIElement::selectedChildAtIndex(unsigned) const { return 0; }
+void AccessibilityUIElement::setSelectedChildAtIndex(unsigned) const { }
+void AccessibilityUIElement::removeSelectionAtIndex(unsigned) const { }
AccessibilityUIElement AccessibilityUIElement::horizontalScrollbar() const { return 0; }
AccessibilityUIElement AccessibilityUIElement::verticalScrollbar() const { return 0; }
AccessibilityUIElement AccessibilityUIElement::uiElementAttributeValue(JSStringRef) const { return 0; }
@@ -1261,12 +1523,11 @@ AccessibilityUIElement AccessibilityUIElement::uiElementAttributeValue(JSStringR
#if !PLATFORM(MAC) && !PLATFORM(IOS)
JSStringRef AccessibilityUIElement::pathDescription() const { return 0; }
+void AccessibilityUIElement::setValue(JSStringRef) { }
#endif
-#if !PLATFORM(MAC)
+#if !PLATFORM(COCOA)
void AccessibilityUIElement::uiElementArrayAttributeValue(JSStringRef, Vector<AccessibilityUIElement>&) const { }
-void AccessibilityUIElement::columnHeaders(Vector<AccessibilityUIElement>&) const { }
-void AccessibilityUIElement::rowHeaders(Vector<AccessibilityUIElement>&) const { }
#endif
#if !PLATFORM(WIN)
@@ -1278,13 +1539,31 @@ bool AccessibilityUIElement::isEqual(AccessibilityUIElement* otherElement)
}
#endif
+#if !PLATFORM(MAC)
+void AccessibilityUIElement::setBoolAttributeValue(JSStringRef, bool) { }
+#endif
+
#if !SUPPORTS_AX_TEXTMARKERS
+AccessibilityTextMarkerRange AccessibilityUIElement::lineTextMarkerRangeForTextMarker(AccessibilityTextMarker*)
+{
+ return nullptr;
+}
+
AccessibilityTextMarkerRange AccessibilityUIElement::textMarkerRangeForElement(AccessibilityUIElement*)
{
return 0;
}
+AccessibilityTextMarkerRange AccessibilityUIElement::selectedTextMarkerRange()
+{
+ return nullptr;
+}
+
+void AccessibilityUIElement::resetSelectedTextMarkerRange()
+{
+}
+
int AccessibilityUIElement::textMarkerRangeLength(AccessibilityTextMarkerRange*)
{
return 0;
@@ -1370,6 +1649,61 @@ AccessibilityTextMarker AccessibilityUIElement::endTextMarker()
return nullptr;
}
+bool AccessibilityUIElement::setSelectedVisibleTextRange(AccessibilityTextMarkerRange*)
+{
+ return false;
+}
+
+AccessibilityTextMarkerRange AccessibilityUIElement::leftWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*)
+{
+ return nullptr;
+}
+
+AccessibilityTextMarkerRange AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*)
+{
+ return nullptr;
+}
+
+AccessibilityTextMarker AccessibilityUIElement::previousWordStartTextMarkerForTextMarker(AccessibilityTextMarker*)
+{
+ return nullptr;
+}
+
+AccessibilityTextMarker AccessibilityUIElement::nextWordEndTextMarkerForTextMarker(AccessibilityTextMarker*)
+{
+ return nullptr;
+}
+
+AccessibilityTextMarkerRange AccessibilityUIElement::paragraphTextMarkerRangeForTextMarker(AccessibilityTextMarker*)
+{
+ return nullptr;
+}
+
+AccessibilityTextMarker AccessibilityUIElement::previousParagraphStartTextMarkerForTextMarker(AccessibilityTextMarker*)
+{
+ return nullptr;
+}
+
+AccessibilityTextMarker AccessibilityUIElement::nextParagraphEndTextMarkerForTextMarker(AccessibilityTextMarker*)
+{
+ return nullptr;
+}
+
+AccessibilityTextMarkerRange AccessibilityUIElement::sentenceTextMarkerRangeForTextMarker(AccessibilityTextMarker*)
+{
+ return nullptr;
+}
+
+AccessibilityTextMarker AccessibilityUIElement::previousSentenceStartTextMarkerForTextMarker(AccessibilityTextMarker*)
+{
+ return nullptr;
+}
+
+AccessibilityTextMarker AccessibilityUIElement::nextSentenceEndTextMarkerForTextMarker(AccessibilityTextMarker*)
+{
+ return nullptr;
+}
+
#endif
// Destruction
@@ -1396,6 +1730,7 @@ JSClassRef AccessibilityUIElement::getJSClass()
{ "role", getRoleCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "subrole", getSubroleCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "roleDescription", getRoleDescriptionCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "computedRoleString", getComputedRoleStringCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "title", getTitleCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "description", getDescriptionCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "language", getLanguageCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
@@ -1449,15 +1784,14 @@ JSClassRef AccessibilityUIElement::getJSClass()
{ "startTextMarker", startTextMarkerCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "endTextMarker", endTextMarkerCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
#if PLATFORM(IOS)
- { "iphoneLabel", getIPhoneLabelCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "iphoneHint", getIPhoneHintCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "iphoneValue", getIPhoneValueCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "iphoneIdentifier", getIPhoneIdentifierCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "iphoneTraits", getIPhoneTraitsCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "iphoneIsElement", getIPhoneIsElementCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "iphoneElementTextPosition", getIPhoneElementTextPositionCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "iphoneElementTextLength", getIPhoneElementTextLengthCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "identifier", getIdentifierCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "traits", getTraitsCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "elementTextPosition", getElementTextPositionCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "elementTextLength", getElementTextLengthCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "stringForSelection", stringForSelectionCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "hasContainedByFieldsetTrait", hasContainedByFieldsetTraitCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "isSearchField", getIsSearchFieldCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "isTextArea", getIsTextAreaCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
#endif // PLATFORM(IOS)
#if PLATFORM(MAC) && !PLATFORM(IOS)
{ "supportedActions", supportedActionsCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
@@ -1480,8 +1814,9 @@ JSClassRef AccessibilityUIElement::getJSClass()
{ "stringForRange", stringForRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "attributedStringForRange", attributedStringForRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "attributedStringRangeIsMisspelled", attributedStringRangeIsMisspelledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "uiElementCountForSearchPredicate", uiElementCountForSearchPredicateCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeReadOnly },
+ { "uiElementCountForSearchPredicate", uiElementCountForSearchPredicateCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "uiElementForSearchPredicate", uiElementForSearchPredicateCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "selectTextWithCriteria", selectTextWithCriteriaCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "childAtIndex", childAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "linkedUIElementAtIndex", linkedUIElementAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "indexOfChild", indexOfChildCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
@@ -1505,6 +1840,7 @@ JSClassRef AccessibilityUIElement::getJSClass()
{ "uiElementAttributeValue", uiElementAttributeValueCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "numberAttributeValue", numberAttributeValueCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "boolAttributeValue", boolAttributeValueCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "setBoolAttributeValue", setBoolAttributeValueCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "isAttributeSupported", isAttributeSupportedCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "isAttributeSettable", isAttributeSettableCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "isPressActionSupported", isPressActionSupportedCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
@@ -1519,6 +1855,7 @@ JSClassRef AccessibilityUIElement::getJSClass()
{ "disclosedRowAtIndex", disclosedRowAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "ariaOwnsElementAtIndex", ariaOwnsElementAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "ariaFlowToElementAtIndex", ariaFlowToElementAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "ariaControlsElementAtIndex", ariaControlsElementAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "selectedRowAtIndex", selectedRowAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "rowAtIndex", rowAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "isEqual", isEqualCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
@@ -1528,7 +1865,10 @@ JSClassRef AccessibilityUIElement::getJSClass()
{ "takeSelection", takeSelectionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "addSelection", addSelectionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "removeSelection", removeSelectionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "lineTextMarkerRangeForTextMarker", lineTextMarkerRangeForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "textMarkerRangeForElement", textMarkerRangeForElementCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "selectedTextMarkerRange", selectedTextMarkerRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "resetSelectedTextMarkerRange", resetSelectedTextMarkerRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "attributedStringForTextMarkerRangeContainsAttribute", attributedStringForTextMarkerRangeContainsAttributeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "indexForTextMarker", indexForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "isTextMarkerValid", isTextMarkerValidCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
@@ -1544,9 +1884,25 @@ JSClassRef AccessibilityUIElement::getJSClass()
{ "nextTextMarker", nextTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "previousTextMarker", previousTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "stringForTextMarkerRange", stringForTextMarkerRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "leftWordTextMarkerRangeForTextMarker", leftWordTextMarkerRangeForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "rightWordTextMarkerRangeForTextMarker", rightWordTextMarkerRangeForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "previousWordStartTextMarkerForTextMarker", previousWordStartTextMarkerForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "nextWordEndTextMarkerForTextMarker", nextWordEndTextMarkerForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "paragraphTextMarkerRangeForTextMarker", paragraphTextMarkerRangeForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "previousParagraphStartTextMarkerForTextMarker", previousParagraphStartTextMarkerForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "nextParagraphEndTextMarkerForTextMarker", nextParagraphEndTextMarkerForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "sentenceTextMarkerRangeForTextMarker", sentenceTextMarkerRangeForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "previousSentenceStartTextMarkerForTextMarker", previousSentenceStartTextMarkerForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "nextSentenceEndTextMarkerForTextMarker", nextSentenceEndTextMarkerForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "setSelectedChild", setSelectedChildCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "setSelectedChildAtIndex", setSelectedChildAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "removeSelectionAtIndex", removeSelectionAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "setValue", setValueCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "setSelectedVisibleTextRange", setSelectedVisibleTextRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "selectedChildAtIndex", selectedChildAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "scrollToMakeVisible", scrollToMakeVisibleCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "scrollToGlobalPoint", scrollToGlobalPointCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "scrollToMakeVisibleWithSubFocus", scrollToMakeVisibleWithSubFocusCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
#if PLATFORM(GTK) || PLATFORM(EFL)
{ "characterAtOffset", characterAtOffsetCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "wordAtOffset", wordAtOffsetCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
@@ -1558,8 +1914,12 @@ JSClassRef AccessibilityUIElement::getJSClass()
{ "elementsForRange", elementsForRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "increaseTextSelection", increaseTextSelectionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "decreaseTextSelection", decreaseTextSelectionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "scrollPageUp", scrollPageUpCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "scrollPageDown", scrollPageDownCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "scrollPageLeft", scrollPageLeftCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "scrollPageRight", scrollPageRightCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "assistiveTechnologySimulatedFocus", assistiveTechnologySimulatedFocusCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
-
+ { "fieldsetAncestorElement", fieldsetAncestorElementCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
#endif
{ 0, 0, 0 }
};
diff --git a/Tools/DumpRenderTree/AccessibilityUIElement.h b/Tools/DumpRenderTree/AccessibilityUIElement.h
index f1f21b69b..4abf9e9aa 100644
--- a/Tools/DumpRenderTree/AccessibilityUIElement.h
+++ b/Tools/DumpRenderTree/AccessibilityUIElement.h
@@ -31,7 +31,7 @@
#include <wtf/Platform.h>
#include <wtf/Vector.h>
-#if PLATFORM(MAC)
+#if PLATFORM(COCOA)
#ifdef __OBJC__
typedef id PlatformUIElement;
#else
@@ -53,7 +53,7 @@ typedef AtkObject* PlatformUIElement;
typedef void* PlatformUIElement;
#endif
-#if PLATFORM(MAC)
+#if PLATFORM(COCOA)
#ifdef __OBJC__
typedef id NotificationHandler;
#else
@@ -109,6 +109,7 @@ public:
void uiElementArrayAttributeValue(JSStringRef attribute, Vector<AccessibilityUIElement>& elements) const;
AccessibilityUIElement uiElementAttributeValue(JSStringRef attribute) const;
bool boolAttributeValue(JSStringRef attribute);
+ void setBoolAttributeValue(JSStringRef attribute, bool value);
bool isAttributeSupported(JSStringRef attribute);
bool isAttributeSettable(JSStringRef attribute);
bool isPressActionSupported();
@@ -117,11 +118,13 @@ public:
JSStringRef role();
JSStringRef subrole();
JSStringRef roleDescription();
+ JSStringRef computedRoleString();
JSStringRef title();
JSStringRef description();
JSStringRef language();
JSStringRef stringValue();
JSStringRef accessibilityValue() const;
+ void setValue(JSStringRef);
JSStringRef helpText() const;
JSStringRef orientation() const;
double x();
@@ -147,6 +150,8 @@ public:
void setSelectedChild(AccessibilityUIElement*) const;
unsigned selectedChildrenCount() const;
AccessibilityUIElement selectedChildAtIndex(unsigned) const;
+ void setSelectedChildAtIndex(unsigned) const;
+ void removeSelectionAtIndex(unsigned) const;
bool isExpanded() const;
bool isChecked() const;
@@ -191,6 +196,7 @@ public:
// ARIA specific
AccessibilityUIElement ariaOwnsElementAtIndex(unsigned);
AccessibilityUIElement ariaFlowToElementAtIndex(unsigned);
+ AccessibilityUIElement ariaControlsElementAtIndex(unsigned);
// ARIA Drag and Drop
bool ariaIsGrabbed() const;
@@ -206,14 +212,23 @@ public:
JSStringRef stringForRange(unsigned location, unsigned length);
JSStringRef attributedStringForRange(unsigned location, unsigned length);
bool attributedStringRangeIsMisspelled(unsigned location, unsigned length);
- unsigned uiElementCountForSearchPredicate(JSContextRef, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly);
- AccessibilityUIElement uiElementForSearchPredicate(JSContextRef, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly);
+ unsigned uiElementCountForSearchPredicate(JSContextRef, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly, bool immediateDescendantsOnly);
+ AccessibilityUIElement uiElementForSearchPredicate(JSContextRef, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly, bool immediateDescendantsOnly);
+ JSStringRef selectTextWithCriteria(JSContextRef, JSStringRef ambiguityResolution, JSValueRef searchStrings, JSStringRef replacementString, JSStringRef activity);
#if PLATFORM(IOS)
void elementsForRange(unsigned location, unsigned length, Vector<AccessibilityUIElement>& elements);
JSStringRef stringForSelection();
void increaseTextSelection();
void decreaseTextSelection();
AccessibilityUIElement linkedElement();
+
+ bool scrollPageUp();
+ bool scrollPageDown();
+ bool scrollPageLeft();
+ bool scrollPageRight();
+
+ bool hasContainedByFieldsetTrait();
+ AccessibilityUIElement fieldsetAncestorElement();
#endif
#if PLATFORM(GTK) || PLATFORM(EFL)
@@ -232,6 +247,7 @@ public:
AccessibilityUIElement verticalScrollbar() const;
// Text markers.
+ AccessibilityTextMarkerRange lineTextMarkerRangeForTextMarker(AccessibilityTextMarker*);
AccessibilityTextMarkerRange textMarkerRangeForElement(AccessibilityUIElement*);
AccessibilityTextMarkerRange textMarkerRangeForMarkers(AccessibilityTextMarker* startMarker, AccessibilityTextMarker* endMarker);
AccessibilityTextMarker startTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange*);
@@ -244,6 +260,19 @@ public:
AccessibilityUIElement accessibilityElementForTextMarker(AccessibilityTextMarker*);
AccessibilityTextMarker startTextMarker();
AccessibilityTextMarker endTextMarker();
+ AccessibilityTextMarkerRange leftWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*);
+ AccessibilityTextMarkerRange rightWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*);
+ AccessibilityTextMarker previousWordStartTextMarkerForTextMarker(AccessibilityTextMarker*);
+ AccessibilityTextMarker nextWordEndTextMarkerForTextMarker(AccessibilityTextMarker*);
+ AccessibilityTextMarkerRange paragraphTextMarkerRangeForTextMarker(AccessibilityTextMarker*);
+ AccessibilityTextMarker previousParagraphStartTextMarkerForTextMarker(AccessibilityTextMarker*);
+ AccessibilityTextMarker nextParagraphEndTextMarkerForTextMarker(AccessibilityTextMarker*);
+ AccessibilityTextMarkerRange sentenceTextMarkerRangeForTextMarker(AccessibilityTextMarker*);
+ AccessibilityTextMarker previousSentenceStartTextMarkerForTextMarker(AccessibilityTextMarker*);
+ AccessibilityTextMarker nextSentenceEndTextMarkerForTextMarker(AccessibilityTextMarker*);
+ AccessibilityTextMarkerRange selectedTextMarkerRange();
+ void resetSelectedTextMarkerRange();
+ bool setSelectedVisibleTextRange(AccessibilityTextMarkerRange*);
JSStringRef stringForTextMarkerRange(AccessibilityTextMarkerRange*);
int textMarkerRangeLength(AccessibilityTextMarkerRange*);
@@ -263,17 +292,17 @@ public:
void removeNotificationListener();
#if PLATFORM(IOS)
- JSStringRef iphoneLabel();
- JSStringRef iphoneValue();
- JSStringRef iphoneTraits();
- JSStringRef iphoneHint();
- JSStringRef iphoneIdentifier();
- bool iphoneIsElement();
- int iphoneElementTextPosition();
- int iphoneElementTextLength();
+ JSStringRef traits();
+ JSStringRef identifier();
+ int elementTextPosition();
+ int elementTextLength();
AccessibilityUIElement headerElementAtIndex(unsigned);
// This will simulate the accessibilityDidBecomeFocused API in UIKit.
void assistiveTechnologySimulatedFocus();
+
+ bool isTextArea() const;
+ bool isSearchField() const;
+
#endif // PLATFORM(IOS)
#if PLATFORM(MAC) && !PLATFORM(IOS)
@@ -289,9 +318,7 @@ private:
static JSClassRef getJSClass();
PlatformUIElement m_element;
-#if PLATFORM(IOS)
- JSObjectRef m_notificationFunctionCallback;
-#elif PLATFORM(MAC)
+#if PLATFORM(COCOA)
// A retained, platform specific object used to help manage notifications for this object.
NotificationHandler m_notificationHandler;
#endif
diff --git a/Tools/DumpRenderTree/CMakeLists.txt b/Tools/DumpRenderTree/CMakeLists.txt
new file mode 100644
index 000000000..1baa510fb
--- /dev/null
+++ b/Tools/DumpRenderTree/CMakeLists.txt
@@ -0,0 +1,127 @@
+set(DumpRenderTree_SOURCES
+ AccessibilityController.cpp
+ AccessibilityTextMarker.cpp
+ AccessibilityUIElement.cpp
+ CyclicRedundancyCheck.cpp
+ DumpRenderTreeCommon.cpp
+ GCController.cpp
+ JavaScriptThreading.cpp
+ PixelDumpSupport.cpp
+ TestRunner.cpp
+ WorkQueue.cpp
+)
+
+set(DumpRenderTree_LIBRARIES
+ JavaScriptCore
+ WTF
+ WebCoreTestSupport
+ WebKit
+)
+
+set(DumpRenderTree_INCLUDE_DIRECTORIES
+ ${WEBCORE_DIR}
+ ${WEBCORE_DIR}/bindings
+ ${WEBCORE_DIR}/bridge
+ ${WEBCORE_DIR}/bridge/jsc
+ ${WEBCORE_DIR}/css
+ ${WEBCORE_DIR}/dom
+ ${WEBCORE_DIR}/editing
+ ${WEBCORE_DIR}/history
+ ${WEBCORE_DIR}/html
+ ${WEBCORE_DIR}/inspector
+ ${WEBCORE_DIR}/loader
+ ${WEBCORE_DIR}/loader/cache
+ ${WEBCORE_DIR}/loader/icon
+ ${WEBCORE_DIR}/page
+ ${WEBCORE_DIR}/page/animation
+ ${WEBCORE_DIR}/platform
+ ${WEBCORE_DIR}/platform/animation
+ ${WEBCORE_DIR}/platform/graphics
+ ${WEBCORE_DIR}/platform/graphics/transforms
+ ${WEBCORE_DIR}/platform/network
+ ${WEBCORE_DIR}/platform/text
+ ${WEBCORE_DIR}/plugins
+ ${WEBCORE_DIR}/rendering
+ ${WEBCORE_DIR}/rendering/shapes
+ ${WEBCORE_DIR}/rendering/style
+ ${JAVASCRIPTCORE_DIR}
+ ${JAVASCRIPTCORE_DIR}/API
+ ${JAVASCRIPTCORE_DIR}/assembler
+ ${JAVASCRIPTCORE_DIR}/bytecode
+ ${JAVASCRIPTCORE_DIR}/dfg
+ ${JAVASCRIPTCORE_DIR}/disassembler
+ ${JAVASCRIPTCORE_DIR}/heap
+ ${JAVASCRIPTCORE_DIR}/interpreter
+ ${JAVASCRIPTCORE_DIR}/jit
+ ${JAVASCRIPTCORE_DIR}/llint
+ ${JAVASCRIPTCORE_DIR}/parser
+ ${JAVASCRIPTCORE_DIR}/profiler
+ ${JAVASCRIPTCORE_DIR}/runtime
+ ${JAVASCRIPTCORE_DIR}/ForwardingHeaders
+ ${DERIVED_SOURCES_DIR}/ForwardingHeaders
+ ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}
+ ${TOOLS_DIR}/DumpRenderTree
+ ${WTF_DIR}
+ ${CMAKE_SOURCE_DIR}/Source
+ ${CMAKE_BINARY_DIR}
+ ${DERIVED_SOURCES_DIR}
+ ${DERIVED_SOURCES_WEBCORE_DIR}
+ ${WEBCORE_DIR}/bindings/js
+ ${WEBCORE_DIR}/testing/js
+)
+
+set(TestNetscapePlugin_SOURCES
+ TestNetscapePlugin/PluginObject.cpp
+ TestNetscapePlugin/PluginTest.cpp
+ TestNetscapePlugin/TestObject.cpp
+ TestNetscapePlugin/main.cpp
+
+ TestNetscapePlugin/Tests/DocumentOpenInDestroyStream.cpp
+ TestNetscapePlugin/Tests/EvaluateJSAfterRemovingPluginElement.cpp
+ TestNetscapePlugin/Tests/FormValue.cpp
+ TestNetscapePlugin/Tests/GetURLNotifyWithURLThatFailsToLoad.cpp
+ TestNetscapePlugin/Tests/GetURLWithJavaScriptURL.cpp
+ TestNetscapePlugin/Tests/GetURLWithJavaScriptURLDestroyingPlugin.cpp
+ TestNetscapePlugin/Tests/GetUserAgentWithNullNPPFromNPPNew.cpp
+ TestNetscapePlugin/Tests/LogNPPSetWindow.cpp
+ TestNetscapePlugin/Tests/NPDeallocateCalledBeforeNPShutdown.cpp
+ TestNetscapePlugin/Tests/NPPNewFails.cpp
+ TestNetscapePlugin/Tests/NPPSetWindowCalledDuringDestruction.cpp
+ TestNetscapePlugin/Tests/NPRuntimeCallsWithNullNPP.cpp
+ TestNetscapePlugin/Tests/NPRuntimeObjectFromDestroyedPlugin.cpp
+ TestNetscapePlugin/Tests/NPRuntimeRemoveProperty.cpp
+ TestNetscapePlugin/Tests/NullNPPGetValuePointer.cpp
+ TestNetscapePlugin/Tests/PassDifferentNPPStruct.cpp
+ TestNetscapePlugin/Tests/PluginScriptableNPObjectInvokeDefault.cpp
+ TestNetscapePlugin/Tests/PluginScriptableObjectOverridesAllProperties.cpp
+ TestNetscapePlugin/Tests/PrivateBrowsing.cpp
+ TestNetscapePlugin/Tests/ToStringAndValueOfObject.cpp
+ TestNetscapePlugin/Tests/URLRedirect.cpp
+)
+
+set(TestNetscapePlugin_LIBRARIES
+ JavaScriptCore
+ WTF
+ WebCoreTestSupport
+ WebKit
+)
+
+list(APPEND TestNetscapePlugin_LIBRARIES
+ WebKit
+)
+
+WEBKIT_INCLUDE_CONFIG_FILES_IF_EXISTS()
+
+include_directories(${DumpRenderTree_INCLUDE_DIRECTORIES})
+
+add_executable(DumpRenderTree ${DumpRenderTree_SOURCES})
+target_link_libraries(DumpRenderTree ${DumpRenderTree_LIBRARIES})
+set_target_properties(DumpRenderTree PROPERTIES FOLDER "Tools")
+
+add_library(TestNetscapePlugin SHARED ${TestNetscapePlugin_SOURCES})
+target_link_libraries(TestNetscapePlugin ${TestNetscapePlugin_LIBRARIES})
+set_target_properties(TestNetscapePlugin PROPERTIES FOLDER "Tools")
+
+if (WIN32)
+ add_dependencies(DumpRenderTree DumpRenderTreeLib)
+endif ()
diff --git a/Tools/DumpRenderTree/DefaultPolicyDelegate.h b/Tools/DumpRenderTree/DefaultPolicyDelegate.h
new file mode 100644
index 000000000..6ff5becca
--- /dev/null
+++ b/Tools/DumpRenderTree/DefaultPolicyDelegate.h
@@ -0,0 +1,13 @@
+//
+// DefaultPolicyDelegate.h
+// DumpRenderTree
+//
+// Created by Anders Carlsson on 7/9/13.
+//
+//
+
+#import <WebKit/WebDefaultPolicyDelegate.h>
+
+@interface DefaultPolicyDelegate : WebDefaultPolicyDelegate
+
+@end
diff --git a/Tools/DumpRenderTree/DumpRenderTree.h b/Tools/DumpRenderTree/DumpRenderTree.h
index 3e6323525..2a2ea1467 100644
--- a/Tools/DumpRenderTree/DumpRenderTree.h
+++ b/Tools/DumpRenderTree/DumpRenderTree.h
@@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -34,7 +34,7 @@
#include <wtf/Platform.h>
#endif
-#if PLATFORM(MAC)
+#if PLATFORM(COCOA)
#include "DumpRenderTreeMac.h"
#elif PLATFORM(WIN)
#include "DumpRenderTreeWin.h"
diff --git a/Tools/DumpRenderTree/DumpRenderTree.sln b/Tools/DumpRenderTree/DumpRenderTree.sln
new file mode 100644
index 000000000..7cce30330
--- /dev/null
+++ b/Tools/DumpRenderTree/DumpRenderTree.sln
@@ -0,0 +1,100 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DumpRenderTree", "win\DumpRenderTree.vcproj", "{6567DFD4-D6DE-4CD5-825D-17E353D160E1}"
+ ProjectSection(ProjectDependencies) = postProject
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C} = {C0737398-3565-439E-A2B8-AB2BE4D5430C}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestNetscapePlugin", "TestNetscapePlugin\win\TestNetscapePlugin.vcproj", "{C0737398-3565-439E-A2B8-AB2BE4D5430C}"
+ ProjectSection(ProjectDependencies) = postProject
+ {DD7949B6-F2B4-47C2-9C42-E21E84CB1017} = {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ImageDiff", "win\ImageDiff.vcproj", "{59CC0547-70AC-499C-9B19-EC01C6F61137}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DumpRenderTreeLauncher", "win\DumpRenderTreeLauncher.vcproj", "{2974EA02-840B-4995-8719-8920A61006F1}"
+ ProjectSection(ProjectDependencies) = postProject
+ {6567DFD4-D6DE-4CD5-825D-17E353D160E1} = {6567DFD4-D6DE-4CD5-825D-17E353D160E1}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ImageDiffLauncher", "win\ImageDiffLauncher.vcproj", "{DD7949B6-F2B4-47C2-9C42-E21E84CB1017}"
+ ProjectSection(ProjectDependencies) = postProject
+ {59CC0547-70AC-499C-9B19-EC01C6F61137} = {59CC0547-70AC-499C-9B19-EC01C6F61137}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug_All|Win32 = Debug_All|Win32
+ Debug_Cairo_CFLite|Win32 = Debug_Cairo_CFLite|Win32
+ Debug|Win32 = Debug|Win32
+ Production|Win32 = Production|Win32
+ Release_Cairo_CFLite|Win32 = Release_Cairo_CFLite|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {6567DFD4-D6DE-4CD5-825D-17E353D160E1}.Debug_All|Win32.ActiveCfg = Debug_All|Win32
+ {6567DFD4-D6DE-4CD5-825D-17E353D160E1}.Debug_All|Win32.Build.0 = Debug_All|Win32
+ {6567DFD4-D6DE-4CD5-825D-17E353D160E1}.Debug_Cairo_CFLite|Win32.ActiveCfg = Debug_Cairo_CFLite|Win32
+ {6567DFD4-D6DE-4CD5-825D-17E353D160E1}.Debug_Cairo_CFLite|Win32.Build.0 = Debug_Cairo_CFLite|Win32
+ {6567DFD4-D6DE-4CD5-825D-17E353D160E1}.Debug|Win32.ActiveCfg = Debug|Win32
+ {6567DFD4-D6DE-4CD5-825D-17E353D160E1}.Debug|Win32.Build.0 = Debug|Win32
+ {6567DFD4-D6DE-4CD5-825D-17E353D160E1}.Production|Win32.ActiveCfg = Production|Win32
+ {6567DFD4-D6DE-4CD5-825D-17E353D160E1}.Production|Win32.Build.0 = Production|Win32
+ {6567DFD4-D6DE-4CD5-825D-17E353D160E1}.Release_Cairo_CFLite|Win32.ActiveCfg = Release_Cairo_CFLite|Win32
+ {6567DFD4-D6DE-4CD5-825D-17E353D160E1}.Release_Cairo_CFLite|Win32.Build.0 = Release_Cairo_CFLite|Win32
+ {6567DFD4-D6DE-4CD5-825D-17E353D160E1}.Release|Win32.ActiveCfg = Release|Win32
+ {6567DFD4-D6DE-4CD5-825D-17E353D160E1}.Release|Win32.Build.0 = Release|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Debug_All|Win32.ActiveCfg = Debug_All|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Debug_All|Win32.Build.0 = Debug_All|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Debug_Cairo_CFLite|Win32.ActiveCfg = Debug_Cairo_CFLite|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Debug_Cairo_CFLite|Win32.Build.0 = Debug_Cairo_CFLite|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Debug|Win32.ActiveCfg = Debug|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Debug|Win32.Build.0 = Debug|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Production|Win32.ActiveCfg = Production|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Production|Win32.Build.0 = Production|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Release_Cairo_CFLite|Win32.ActiveCfg = Release_Cairo_CFLite|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Release_Cairo_CFLite|Win32.Build.0 = Release_Cairo_CFLite|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Release|Win32.ActiveCfg = Release|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Release|Win32.Build.0 = Release|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Debug_All|Win32.ActiveCfg = Debug_All|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Debug_All|Win32.Build.0 = Debug_All|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Debug_Cairo_CFLite|Win32.ActiveCfg = Debug_Cairo_CFLite|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Debug_Cairo_CFLite|Win32.Build.0 = Debug_Cairo_CFLite|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Debug|Win32.ActiveCfg = Debug|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Debug|Win32.Build.0 = Debug|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Production|Win32.ActiveCfg = Production|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Production|Win32.Build.0 = Production|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Release_Cairo_CFLite|Win32.ActiveCfg = Release_Cairo_CFLite|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Release_Cairo_CFLite|Win32.Build.0 = Release_Cairo_CFLite|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Release|Win32.ActiveCfg = Release|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Release|Win32.Build.0 = Release|Win32
+ {2974EA02-840B-4995-8719-8920A61006F1}.Debug_All|Win32.ActiveCfg = Debug_All|Win32
+ {2974EA02-840B-4995-8719-8920A61006F1}.Debug_All|Win32.Build.0 = Debug_All|Win32
+ {2974EA02-840B-4995-8719-8920A61006F1}.Debug_Cairo_CFLite|Win32.ActiveCfg = Debug_Cairo_CFLite|Win32
+ {2974EA02-840B-4995-8719-8920A61006F1}.Debug_Cairo_CFLite|Win32.Build.0 = Debug_Cairo_CFLite|Win32
+ {2974EA02-840B-4995-8719-8920A61006F1}.Debug|Win32.ActiveCfg = Debug|Win32
+ {2974EA02-840B-4995-8719-8920A61006F1}.Debug|Win32.Build.0 = Debug|Win32
+ {2974EA02-840B-4995-8719-8920A61006F1}.Production|Win32.ActiveCfg = Production|Win32
+ {2974EA02-840B-4995-8719-8920A61006F1}.Production|Win32.Build.0 = Production|Win32
+ {2974EA02-840B-4995-8719-8920A61006F1}.Release_Cairo_CFLite|Win32.ActiveCfg = Release_Cairo_CFLite|Win32
+ {2974EA02-840B-4995-8719-8920A61006F1}.Release_Cairo_CFLite|Win32.Build.0 = Release_Cairo_CFLite|Win32
+ {2974EA02-840B-4995-8719-8920A61006F1}.Release|Win32.ActiveCfg = Release|Win32
+ {2974EA02-840B-4995-8719-8920A61006F1}.Release|Win32.Build.0 = Release|Win32
+ {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Debug_All|Win32.ActiveCfg = Debug_All|Win32
+ {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Debug_All|Win32.Build.0 = Debug_All|Win32
+ {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Debug_Cairo_CFLite|Win32.ActiveCfg = Debug_Cairo_CFLite|Win32
+ {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Debug_Cairo_CFLite|Win32.Build.0 = Debug_Cairo_CFLite|Win32
+ {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Debug|Win32.ActiveCfg = Debug|Win32
+ {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Debug|Win32.Build.0 = Debug|Win32
+ {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Production|Win32.ActiveCfg = Production|Win32
+ {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Production|Win32.Build.0 = Production|Win32
+ {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Release_Cairo_CFLite|Win32.ActiveCfg = Release_Cairo_CFLite|Win32
+ {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Release_Cairo_CFLite|Win32.Build.0 = Release_Cairo_CFLite|Win32
+ {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Release|Win32.ActiveCfg = Release|Win32
+ {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Tools/DumpRenderTree/DumpRenderTreeFileDraggingSource.h b/Tools/DumpRenderTree/DumpRenderTreeFileDraggingSource.h
new file mode 100644
index 000000000..1d42a474c
--- /dev/null
+++ b/Tools/DumpRenderTree/DumpRenderTreeFileDraggingSource.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2009, Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#if !PLATFORM(IOS)
+
+#import <Cocoa/Cocoa.h>
+
+// An implementation of NSDraggingSource for use with DumpRenderTreeDraggingInfo when dragging files
+// Used by -[EventSendingController beginDragWithFiles:]
+
+@interface DumpRenderTreeFileDraggingSource : NSObject {
+}
+
+- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)flag;
+
+@end
+
+#endif
diff --git a/Tools/DumpRenderTree/DumpRenderTreePrefix.h b/Tools/DumpRenderTree/DumpRenderTreePrefix.h
index 64eae0704..105b54356 100644
--- a/Tools/DumpRenderTree/DumpRenderTreePrefix.h
+++ b/Tools/DumpRenderTree/DumpRenderTreePrefix.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2005 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -26,8 +26,17 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H && defined(BUILDING_WITH_CMAKE)
+#include "cmakeconfig.h"
+#endif
+
#include <wtf/Platform.h>
#ifdef __OBJC__
#import <Foundation/Foundation.h>
#endif
+
+#if OS(WINDOWS)
+#undef WEBCORE_EXPORT
+#define WEBCORE_EXPORT WTF_IMPORT_DECLARATION
+#endif
diff --git a/Tools/DumpRenderTree/ForwardingHeaders/runtime/ArrayBufferView.h b/Tools/DumpRenderTree/ForwardingHeaders/runtime/ArrayBufferView.h
new file mode 100644
index 000000000..7731671c8
--- /dev/null
+++ b/Tools/DumpRenderTree/ForwardingHeaders/runtime/ArrayBufferView.h
@@ -0,0 +1 @@
+#include <JavaScriptCore/ArrayBufferView.h>
diff --git a/Tools/DumpRenderTree/ForwardingHeaders/runtime/JSArrayBufferView.h b/Tools/DumpRenderTree/ForwardingHeaders/runtime/JSArrayBufferView.h
new file mode 100644
index 000000000..e38a8040f
--- /dev/null
+++ b/Tools/DumpRenderTree/ForwardingHeaders/runtime/JSArrayBufferView.h
@@ -0,0 +1 @@
+#include <JavaScriptCore/JSArrayBufferView.h>
diff --git a/Tools/DumpRenderTree/ForwardingHeaders/runtime/JSExportMacros.h b/Tools/DumpRenderTree/ForwardingHeaders/runtime/JSExportMacros.h
new file mode 100644
index 000000000..4c5dcb983
--- /dev/null
+++ b/Tools/DumpRenderTree/ForwardingHeaders/runtime/JSExportMacros.h
@@ -0,0 +1 @@
+#include <JavaScriptCore/JSExportMacros.h> \ No newline at end of file
diff --git a/Tools/DumpRenderTree/ForwardingHeaders/runtime/TypedArrayInlines.h b/Tools/DumpRenderTree/ForwardingHeaders/runtime/TypedArrayInlines.h
new file mode 100644
index 000000000..6a61945ea
--- /dev/null
+++ b/Tools/DumpRenderTree/ForwardingHeaders/runtime/TypedArrayInlines.h
@@ -0,0 +1 @@
+#include <JavaScriptCore/TypedArrayInlines.h>
diff --git a/Tools/DumpRenderTree/GCController.cpp b/Tools/DumpRenderTree/GCController.cpp
index 06a04fbca..781a828eb 100644
--- a/Tools/DumpRenderTree/GCController.cpp
+++ b/Tools/DumpRenderTree/GCController.cpp
@@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
diff --git a/Tools/DumpRenderTree/GCController.h b/Tools/DumpRenderTree/GCController.h
index afc1de087..79ceafc9f 100644
--- a/Tools/DumpRenderTree/GCController.h
+++ b/Tools/DumpRenderTree/GCController.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
diff --git a/Tools/DumpRenderTree/JavaScriptThreading.cpp b/Tools/DumpRenderTree/JavaScriptThreading.cpp
new file mode 100644
index 000000000..e2f9bade6
--- /dev/null
+++ b/Tools/DumpRenderTree/JavaScriptThreading.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * (C) 2007 Graham Dennis (graham.dennis@gmail.com)
+ * (C) 2007 Eric Seidel <eric@webkit.org>
+ * (C) 2012 Patrick Ganstere <paroga@paroga.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JavaScriptThreading.h"
+
+#include <JavaScriptCore/JavaScriptCore.h>
+#include <stdlib.h>
+#include <wtf/Assertions.h>
+#include <wtf/HashSet.h>
+#include <wtf/Lock.h>
+#include <wtf/Threading.h>
+#include <wtf/ThreadingPrimitives.h>
+#include <wtf/Vector.h>
+
+static const size_t javaScriptThreadsCount = 4;
+static bool javaScriptThreadsShouldTerminate;
+static JSContextGroupRef javaScriptThreadsGroup;
+
+static Lock& javaScriptThreadsMutex()
+{
+ DEPRECATED_DEFINE_STATIC_LOCAL(Lock, staticMutex, ());
+ return staticMutex;
+}
+
+typedef HashSet<ThreadIdentifier> ThreadSet;
+static ThreadSet& javaScriptThreads()
+{
+ DEPRECATED_DEFINE_STATIC_LOCAL(ThreadSet, staticJavaScriptThreads, ());
+ ASSERT(!javaScriptThreadsMutex().tryLock());
+ return staticJavaScriptThreads;
+}
+
+// This function exercises JSC in a loop until javaScriptThreadsShouldTerminate
+// becomes true or it probabilistically decides to spawn a replacement thread and exit.
+void runJavaScriptThread(void*)
+{
+ static const char* const script =
+ "var array = [];"
+ "for (var i = 0; i < 1024; i++) {"
+ " array.push(String(i));"
+ "}";
+
+ JSGlobalContextRef ctx;
+ {
+ LockHolder locker(javaScriptThreadsMutex());
+ ctx = JSGlobalContextCreateInGroup(javaScriptThreadsGroup, 0);
+ }
+
+ JSStringRef scriptRef;
+ {
+ LockHolder locker(javaScriptThreadsMutex());
+ scriptRef = JSStringCreateWithUTF8CString(script);
+ }
+
+ while (true) {
+ {
+ LockHolder locker(javaScriptThreadsMutex());
+ JSValueRef exception = 0;
+ JSEvaluateScript(ctx, scriptRef, 0, 0, 1, &exception);
+ ASSERT(!exception);
+ }
+
+ {
+ LockHolder locker(javaScriptThreadsMutex());
+ const size_t valuesCount = 1024;
+ JSValueRef values[valuesCount];
+ for (size_t i = 0; i < valuesCount; ++i)
+ values[i] = JSObjectMake(ctx, 0, 0);
+ }
+
+ {
+ LockHolder locker(javaScriptThreadsMutex());
+ if (javaScriptThreadsShouldTerminate)
+ break;
+ }
+
+ // Respawn probabilistically.
+ if (rand() % 5)
+ continue;
+
+ LockHolder locker(javaScriptThreadsMutex());
+ ThreadIdentifier thread = currentThread();
+ detachThread(thread);
+ javaScriptThreads().remove(thread);
+ javaScriptThreads().add(createThread(&runJavaScriptThread, 0, 0));
+ break;
+ }
+
+ LockHolder locker(javaScriptThreadsMutex());
+ JSStringRelease(scriptRef);
+ JSGarbageCollect(ctx);
+ JSGlobalContextRelease(ctx);
+}
+
+void startJavaScriptThreads()
+{
+ javaScriptThreadsGroup = JSContextGroupCreate();
+
+ LockHolder locker(javaScriptThreadsMutex());
+
+ for (size_t i = 0; i < javaScriptThreadsCount; ++i)
+ javaScriptThreads().add(createThread(&runJavaScriptThread, 0, 0));
+}
+
+void stopJavaScriptThreads()
+{
+ {
+ LockHolder locker(javaScriptThreadsMutex());
+ javaScriptThreadsShouldTerminate = true;
+ }
+
+ Vector<ThreadIdentifier, javaScriptThreadsCount> threads;
+ {
+ LockHolder locker(javaScriptThreadsMutex());
+ copyToVector(javaScriptThreads(), threads);
+ ASSERT(threads.size() == javaScriptThreadsCount);
+ }
+
+ for (size_t i = 0; i < javaScriptThreadsCount; ++i)
+ waitForThreadCompletion(threads[i]);
+
+ {
+ LockHolder locker(javaScriptThreadsMutex());
+ javaScriptThreads().clear();
+ }
+
+ JSContextGroupRelease(javaScriptThreadsGroup);
+}
diff --git a/Tools/DumpRenderTree/JavaScriptThreading.h b/Tools/DumpRenderTree/JavaScriptThreading.h
index 43795a1a2..5bbe9cafe 100644
--- a/Tools/DumpRenderTree/JavaScriptThreading.h
+++ b/Tools/DumpRenderTree/JavaScriptThreading.h
@@ -12,7 +12,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
diff --git a/Tools/DumpRenderTree/PixelDumpSupport.cpp b/Tools/DumpRenderTree/PixelDumpSupport.cpp
index ba619bbea..aeb902ceb 100644
--- a/Tools/DumpRenderTree/PixelDumpSupport.cpp
+++ b/Tools/DumpRenderTree/PixelDumpSupport.cpp
@@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -43,7 +43,6 @@
#include "PixelDumpSupportCairo.h"
#endif
-#if !PLATFORM(IOS)
void dumpWebViewAsPixelsAndCompareWithExpected(const std::string& expectedHash)
{
RefPtr<BitmapContext> context;
@@ -74,7 +73,6 @@ void dumpWebViewAsPixelsAndCompareWithExpected(const std::string& expectedHash)
if (dumpImage)
dumpBitmap(context.get(), actualHash);
}
-#endif
static void appendIntToVector(unsigned number, Vector<unsigned char>& vector)
{
diff --git a/Tools/DumpRenderTree/PixelDumpSupport.h b/Tools/DumpRenderTree/PixelDumpSupport.h
index 3bd8820c7..a0ec1e1c7 100644
--- a/Tools/DumpRenderTree/PixelDumpSupport.h
+++ b/Tools/DumpRenderTree/PixelDumpSupport.h
@@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
diff --git a/Tools/DumpRenderTree/TestNetscapePlugIn/CMakeLists.txt b/Tools/DumpRenderTree/TestNetscapePlugIn/CMakeLists.txt
new file mode 100644
index 000000000..c431667b2
--- /dev/null
+++ b/Tools/DumpRenderTree/TestNetscapePlugIn/CMakeLists.txt
@@ -0,0 +1,61 @@
+set(WEBKIT_TESTNETSCAPEPLUGIN_DIR "${TOOLS_DIR}/DumpRenderTree/TestNetscapePlugIn")
+
+set(WebKitTestNetscapePlugin_SOURCES
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/PluginObject.cpp
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/PluginTest.cpp
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/TestObject.cpp
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/main.cpp
+
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/DocumentOpenInDestroyStream.cpp
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/EvaluateJSAfterRemovingPluginElement.cpp
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/FormValue.cpp
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/GetURLNotifyWithURLThatFailsToLoad.cpp
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/GetURLWithJavaScriptURL.cpp
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/GetURLWithJavaScriptURLDestroyingPlugin.cpp
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/GetUserAgentWithNullNPPFromNPPNew.cpp
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/LogNPPSetWindow.cpp
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/NPDeallocateCalledBeforeNPShutdown.cpp
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/NPPNewFails.cpp
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/NPPSetWindowCalledDuringDestruction.cpp
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/NPRuntimeCallsWithNullNPP.cpp
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/NPRuntimeObjectFromDestroyedPlugin.cpp
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/NPRuntimeRemoveProperty.cpp
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/NullNPPGetValuePointer.cpp
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/PassDifferentNPPStruct.cpp
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/PluginScriptableNPObjectInvokeDefault.cpp
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/PluginScriptableObjectOverridesAllProperties.cpp
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/PrivateBrowsing.cpp
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/ToStringAndValueOfObject.cpp
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/URLRedirect.cpp
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/Tests/x11/CallInvalidateRectWithNullNPPArgument.cpp
+)
+
+set(WebKitTestNetscapePlugin_INCLUDE_DIRECTORIES
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}
+ ${WEBKIT_TESTNETSCAPEPLUGIN_DIR}/ForwardingHeaders
+ ${WEBCORE_DIR}
+ ${WTF_DIR}
+)
+
+set(WebKitTestNetscapePlugin_SYSTEM_INCLUDE_DIRECTORIES
+ ${X11_INCLUDE_DIR}
+)
+
+include_directories(${WebKitTestNetscapePlugin_INCLUDE_DIRECTORIES})
+include_directories(SYSTEM ${WebKitTestNetscapePlugin_SYSTEM_INCLUDE_DIRECTORIES})
+
+set(WebKitTestNetscapePlugin_LIBRARIES
+ ${X11_LIBRARIES}
+)
+
+if (WTF_OS_UNIX)
+ add_definitions(-DXP_UNIX)
+endif ()
+
+add_library(TestNetscapePlugin SHARED ${WebKitTestNetscapePlugin_SOURCES})
+target_link_libraries(TestNetscapePlugin ${WebKitTestNetscapePlugin_LIBRARIES})
+set_target_properties(TestNetscapePlugin PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/plugins)
+WEBKIT_SET_EXTRA_COMPILER_FLAGS(TestNetscapePlugin)
+
+# Suppress unused parameter warnings for sources in WebKit2.
+ADD_TARGET_PROPERTIES(TestNetscapePlugin COMPILE_FLAGS "-Wno-unused-parameter")
diff --git a/Tools/DumpRenderTree/TestNetscapePlugIn/unix/ForwardingHeaders/WebKit/npapi.h b/Tools/DumpRenderTree/TestNetscapePlugIn/ForwardingHeaders/WebKit/npapi.h
index 627bc97a9..627bc97a9 100644
--- a/Tools/DumpRenderTree/TestNetscapePlugIn/unix/ForwardingHeaders/WebKit/npapi.h
+++ b/Tools/DumpRenderTree/TestNetscapePlugIn/ForwardingHeaders/WebKit/npapi.h
diff --git a/Tools/DumpRenderTree/TestNetscapePlugIn/unix/ForwardingHeaders/WebKit/npfunctions.h b/Tools/DumpRenderTree/TestNetscapePlugIn/ForwardingHeaders/WebKit/npfunctions.h
index 54a603dbb..54a603dbb 100644
--- a/Tools/DumpRenderTree/TestNetscapePlugIn/unix/ForwardingHeaders/WebKit/npfunctions.h
+++ b/Tools/DumpRenderTree/TestNetscapePlugIn/ForwardingHeaders/WebKit/npfunctions.h
diff --git a/Tools/DumpRenderTree/TestNetscapePlugIn/unix/ForwardingHeaders/WebKit/npruntime.h b/Tools/DumpRenderTree/TestNetscapePlugIn/ForwardingHeaders/WebKit/npruntime.h
index e435ae2ab..e435ae2ab 100644
--- a/Tools/DumpRenderTree/TestNetscapePlugIn/unix/ForwardingHeaders/WebKit/npruntime.h
+++ b/Tools/DumpRenderTree/TestNetscapePlugIn/ForwardingHeaders/WebKit/npruntime.h
diff --git a/Tools/DumpRenderTree/TestNetscapePlugIn/PluginObject.cpp b/Tools/DumpRenderTree/TestNetscapePlugIn/PluginObject.cpp
index 75631842f..982452b68 100644
--- a/Tools/DumpRenderTree/TestNetscapePlugIn/PluginObject.cpp
+++ b/Tools/DumpRenderTree/TestNetscapePlugIn/PluginObject.cpp
@@ -30,10 +30,14 @@
#include "PluginTest.h"
#include "TestObject.h"
#include <assert.h>
+#include <memory>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <wtf/Platform.h>
+#include <wtf/ExportMacros.h>
+#include <wtf/Assertions.h>
// Helper function which takes in the plugin window object for logging to the console object.
static void pluginLogWithWindowObject(NPObject* windowObject, NPP instance, const char* message)
@@ -60,6 +64,7 @@ static void pluginLogWithWindowObject(NPObject* windowObject, NPP instance, cons
browser->releaseobject(consoleObject);
}
+WTF_ATTRIBUTE_PRINTF(2, 0)
void pluginLogWithArguments(NPP instance, const char* format, va_list args)
{
const size_t messageBufferSize = 2048;
@@ -80,6 +85,7 @@ void pluginLogWithArguments(NPP instance, const char* format, va_list args)
}
// Helper function to log to the console object.
+WTF_ATTRIBUTE_PRINTF(2, 3)
void pluginLog(NPP instance, const char* format, ...)
{
va_list args;
@@ -770,11 +776,15 @@ static bool testGetPropertyReturnValue(PluginObject* obj, const NPVariant* args,
return true;
}
-static char* toCString(const NPString& string)
+static std::unique_ptr<char[]> toCString(const NPString& string)
{
- char* result = static_cast<char*>(malloc(string.UTF8Length + 1));
- memcpy(result, string.UTF8Characters, string.UTF8Length);
- result[string.UTF8Length] = '\0';
+ size_t length = string.UTF8Length;
+ std::unique_ptr<char[]> result(new char[length + 1]);
+ if (!result)
+ return result;
+
+ memcpy(result.get(), string.UTF8Characters, length);
+ result[length] = '\0';
return result;
}
@@ -785,30 +795,27 @@ static bool testPostURLFile(PluginObject* obj, const NPVariant* args, uint32_t a
return false;
NPString urlString = NPVARIANT_TO_STRING(args[0]);
- char* url = toCString(urlString);
+ auto url = toCString(urlString);
NPString targetString = NPVARIANT_TO_STRING(args[1]);
- char* target = toCString(targetString);
+ auto target = toCString(targetString);
NPString pathString = NPVARIANT_TO_STRING(args[2]);
- char* path = toCString(pathString);
+ auto path = toCString(pathString);
NPString contentsString = NPVARIANT_TO_STRING(args[3]);
- FILE* tempFile = fopen(path, "w");
+ FILE* tempFile = fopen(path.get(), "w");
if (!tempFile)
return false;
- if (!fwrite(contentsString.UTF8Characters, contentsString.UTF8Length, 1, tempFile))
- return false;
-
+ size_t count = fwrite(contentsString.UTF8Characters, contentsString.UTF8Length, 1, tempFile);
fclose(tempFile);
- NPError error = browser->posturl(obj->npp, url, target, pathString.UTF8Length, path, TRUE);
+ if (!count)
+ return false;
- free(path);
- free(target);
- free(url);
+ NPError error = browser->posturl(obj->npp, url.get(), target.get(), pathString.UTF8Length, path.get(), TRUE);
BOOLEAN_TO_NPVARIANT(error == NPERR_NO_ERROR, *result);
return true;
@@ -967,15 +974,14 @@ bool testWindowOpen(NPP npp)
static bool testSetStatus(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
{
- char* message = 0;
+ std::unique_ptr<char[]> message;
if (argCount && NPVARIANT_IS_STRING(args[0])) {
NPString statusString = NPVARIANT_TO_STRING(args[0]);
message = toCString(statusString);
}
-
- browser->status(obj->npp, message);
- free(message);
+ browser->status(obj->npp, message.get());
+
return true;
}
diff --git a/Tools/DumpRenderTree/TestNetscapePlugIn/PluginTest.cpp b/Tools/DumpRenderTree/TestNetscapePlugIn/PluginTest.cpp
index c2195c5b1..da78148d4 100644
--- a/Tools/DumpRenderTree/TestNetscapePlugIn/PluginTest.cpp
+++ b/Tools/DumpRenderTree/TestNetscapePlugIn/PluginTest.cpp
@@ -28,6 +28,9 @@
#include "PluginObject.h"
#include <assert.h>
#include <string.h>
+#include <wtf/Platform.h>
+#include <wtf/ExportMacros.h>
+#include <wtf/Assertions.h>
#if defined(XP_UNIX) || defined(ANDROID)
#include <unistd.h>
@@ -133,6 +136,11 @@ bool PluginTest::NPP_URLNotify(const char* url, NPReason, void* notifyData)
return false;
}
+void PluginTest::NPP_URLRedirectNotify(const char*, int32_t, void* notifyData)
+{
+ NPN_URLRedirectResponse(notifyData, true);
+}
+
NPError PluginTest::NPP_GetValue(NPPVariable variable, void *value)
{
// We don't know anything about plug-in values so just return NPERR_GENERIC_ERROR.
@@ -156,6 +164,11 @@ NPError PluginTest::NPN_GetURLNotify(const char *url, const char *target, void *
return browser->geturlnotify(m_npp, url, target, notifyData);
}
+NPError PluginTest::NPN_PostURLNotify(const char *url, const char *target, uint32_t len, const char* buf, NPBool file, void *notifyData)
+{
+ return browser->posturlnotify(m_npp, url, target, len, buf, file, notifyData);
+}
+
NPError PluginTest::NPN_GetValue(NPNVariable variable, void* value)
{
return browser->getvalue(m_npp, variable, value);
@@ -228,6 +241,11 @@ void PluginTest::NPN_ReleaseVariantValue(NPVariant* variant)
browser->releasevariantvalue(variant);
}
+void PluginTest::NPN_URLRedirectResponse(void* notifyData, NPBool allow)
+{
+ browser->urlredirectresponse(m_npp, notifyData, allow);
+}
+
#ifdef XP_MACOSX
bool PluginTest::NPN_ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace)
{
@@ -254,6 +272,7 @@ void PluginTest::executeScript(const char* script)
browser->releasevariantvalue(&browserResult);
}
+WTF_ATTRIBUTE_PRINTF(2, 3)
void PluginTest::log(const char* format, ...)
{
va_list args;
diff --git a/Tools/DumpRenderTree/TestNetscapePlugIn/PluginTest.h b/Tools/DumpRenderTree/TestNetscapePlugIn/PluginTest.h
index f8a9aaee3..d7a5163ff 100644
--- a/Tools/DumpRenderTree/TestNetscapePlugIn/PluginTest.h
+++ b/Tools/DumpRenderTree/TestNetscapePlugIn/PluginTest.h
@@ -31,6 +31,10 @@
#include <map>
#include <string>
+#if defined(_MSC_VER) && _MSC_VER < 1900
+#define snprintf _snprintf
+#endif
+
// Helper classes for implementing has_member
typedef char (&no_tag)[1];
typedef char (&yes_tag)[2];
@@ -68,12 +72,14 @@ public:
virtual int16_t NPP_HandleEvent(void* event);
virtual bool NPP_URLNotify(const char* url, NPReason, void* notifyData);
+ virtual void NPP_URLRedirectNotify(const char* url, int32_t status, void* notifyData);
virtual NPError NPP_GetValue(NPPVariable, void* value);
virtual NPError NPP_SetValue(NPNVariable, void *value);
// NPN functions.
NPError NPN_GetURL(const char* url, const char* target);
NPError NPN_GetURLNotify(const char* url, const char* target, void* notifyData);
+ NPError NPN_PostURLNotify(const char *url, const char *target, uint32_t len, const char* buf, NPBool file, void *notifyData);
NPError NPN_GetValue(NPNVariable, void* value);
void NPN_InvalidateRect(NPRect* invalidRect);
bool NPN_Invoke(NPObject *, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result);
@@ -91,6 +97,7 @@ public:
void NPN_ReleaseObject(NPObject*);
bool NPN_RemoveProperty(NPObject*, NPIdentifier propertyName);
void NPN_ReleaseVariantValue(NPVariant*);
+ void NPN_URLRedirectResponse(void* notifyData, NPBool allow);
#ifdef XP_MACOSX
bool NPN_ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace);
diff --git a/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/EvaluateJSWithinNPP_New.cpp b/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/EvaluateJSWithinNPP_New.cpp
new file mode 100644
index 000000000..c066db59f
--- /dev/null
+++ b/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/EvaluateJSWithinNPP_New.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "PluginTest.h"
+
+#include "PluginObject.h"
+
+using namespace std;
+
+// Executing JS within NPP_New when initializing asynchronously should not be able to deadlock with the WebProcess
+
+class EvaluteJSWithinNPP_New : public PluginTest {
+public:
+ EvaluteJSWithinNPP_New(NPP, const string& identifier);
+
+private:
+ virtual NPError NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData *);
+
+};
+
+EvaluteJSWithinNPP_New::EvaluteJSWithinNPP_New(NPP npp, const string& identifier)
+ : PluginTest(npp, identifier)
+{
+}
+
+NPError EvaluteJSWithinNPP_New::NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData *saved)
+{
+ // Give the WebProcess enough time to be deadlocked waiting for the PluginProcess.
+ usleep(15000);
+ executeScript("var theLocation = window.location;");
+ return NPERR_NO_ERROR;
+}
+
+static PluginTest::Register<EvaluteJSWithinNPP_New> registrar("evalute-js-within-npp-new");
diff --git a/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/InvokeDestroysPluginWithinNPP_New.cpp b/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/InvokeDestroysPluginWithinNPP_New.cpp
new file mode 100644
index 000000000..0e2dbdce7
--- /dev/null
+++ b/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/InvokeDestroysPluginWithinNPP_New.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "PluginTest.h"
+
+#include "PluginObject.h"
+
+using namespace std;
+
+// Executing JS within NPP_New when initializing asynchronously should not be able to deadlock with the WebProcess
+
+class InvokeDestroysPluginWithinNPP_New : public PluginTest {
+public:
+ InvokeDestroysPluginWithinNPP_New(NPP, const string& identifier);
+
+private:
+ virtual NPError NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData *);
+
+};
+
+InvokeDestroysPluginWithinNPP_New::InvokeDestroysPluginWithinNPP_New(NPP npp, const string& identifier)
+ : PluginTest(npp, identifier)
+{
+}
+
+NPError InvokeDestroysPluginWithinNPP_New::NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData *saved)
+{
+ // Give the WebProcess enough time to be deadlocked waiting for the PluginProcess if things aren't working correctly.
+ usleep(15000);
+
+ NPObject* windowObject = 0;
+ if (NPN_GetValue(NPNVWindowNPObject, &windowObject) != NPERR_NO_ERROR)
+ return NPERR_GENERIC_ERROR;
+
+ if (!windowObject)
+ return NPERR_GENERIC_ERROR;
+
+ NPVariant result;
+ if (!NPN_Invoke(windowObject, NPN_GetStringIdentifier("removePluginElement"), 0, 0, &result))
+ return NPERR_GENERIC_ERROR;
+
+ return NPERR_NO_ERROR;
+}
+
+static PluginTest::Register<InvokeDestroysPluginWithinNPP_New> registrar("invoke-destroys-plugin-within-npp-new");
diff --git a/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/PluginScriptableObjectOverridesAllProperties.cpp b/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/PluginScriptableObjectOverridesAllProperties.cpp
new file mode 100644
index 000000000..ca399a816
--- /dev/null
+++ b/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/PluginScriptableObjectOverridesAllProperties.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "PluginTest.h"
+
+#include <string.h>
+
+using namespace std;
+
+class PluginScriptableObjectOverridesAllProperties : public PluginTest {
+public:
+ PluginScriptableObjectOverridesAllProperties(NPP npp, const string& identifier)
+ : PluginTest(npp, identifier)
+ {
+ }
+
+private:
+ class PluginObject : public Object<PluginObject> {
+ public:
+ PluginObject()
+ {
+ }
+
+ ~PluginObject()
+ {
+ }
+
+ bool hasProperty(NPIdentifier propertyName)
+ {
+ return true;
+ }
+
+ bool getProperty(NPIdentifier propertyName, NPVariant* result)
+ {
+ static const char* message = "My name is ";
+ char* propertyString = pluginTest()->NPN_UTF8FromIdentifier(propertyName);
+
+ int bufferLength = strlen(propertyString) + strlen(message) + 1;
+ char* resultBuffer = static_cast<char*>(pluginTest()->NPN_MemAlloc(bufferLength));
+ snprintf(resultBuffer, bufferLength, "%s%s", message, propertyString);
+
+ STRINGZ_TO_NPVARIANT(resultBuffer, *result);
+
+ return true;
+ }
+ };
+
+ virtual NPError NPP_GetValue(NPPVariable variable, void *value)
+ {
+ if (variable != NPPVpluginScriptableNPObject)
+ return NPERR_GENERIC_ERROR;
+
+ *(NPObject**)value = PluginObject::create(this);
+
+ return NPERR_NO_ERROR;
+ }
+
+};
+
+static PluginTest::Register<PluginScriptableObjectOverridesAllProperties> pluginScriptableObjectOverridesAllProperties("plugin-scriptable-object-overrides-all-properties");
diff --git a/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/SlowNPPNew.cpp b/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/SlowNPPNew.cpp
new file mode 100644
index 000000000..8c80d55a5
--- /dev/null
+++ b/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/SlowNPPNew.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "PluginTest.h"
+
+#include <string.h>
+
+using namespace std;
+
+class SlowNPPNew : public PluginTest {
+public:
+ SlowNPPNew(NPP npp, const string& identifier)
+ : PluginTest(npp, identifier)
+ {
+ }
+
+private:
+ class PluginObject : public Object<PluginObject> {
+ public:
+ PluginObject()
+ {
+ }
+
+ ~PluginObject()
+ {
+ }
+
+ bool hasProperty(NPIdentifier propertyName)
+ {
+ return true;
+ }
+
+ bool getProperty(NPIdentifier propertyName, NPVariant* result)
+ {
+ static const char* message = "My name is ";
+ char* propertyString = pluginTest()->NPN_UTF8FromIdentifier(propertyName);
+
+ int bufferLength = strlen(propertyString) + strlen(message) + 1;
+ char* resultBuffer = static_cast<char*>(pluginTest()->NPN_MemAlloc(bufferLength));
+ snprintf(resultBuffer, bufferLength, "%s%s", message, propertyString);
+
+ STRINGZ_TO_NPVARIANT(resultBuffer, *result);
+
+ return true;
+ }
+ };
+
+ virtual NPError NPP_GetValue(NPPVariable variable, void *value)
+ {
+ if (variable != NPPVpluginScriptableNPObject)
+ return NPERR_GENERIC_ERROR;
+
+ *(NPObject**)value = PluginObject::create(this);
+
+ return NPERR_NO_ERROR;
+ }
+
+ virtual NPError NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData *saved)
+ {
+ usleep(550000);
+ return NPERR_NO_ERROR;
+ }
+};
+
+static PluginTest::Register<SlowNPPNew> slowNPPNew("slow-npp-new");
diff --git a/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/URLRedirect.cpp b/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/URLRedirect.cpp
new file mode 100644
index 000000000..b834703da
--- /dev/null
+++ b/Tools/DumpRenderTree/TestNetscapePlugIn/Tests/URLRedirect.cpp
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "PluginTest.h"
+
+#include <string.h>
+
+using namespace std;
+
+class URLRedirect : public PluginTest {
+public:
+ URLRedirect(NPP npp, const string& identifier)
+ : PluginTest(npp, identifier)
+ {
+ }
+
+ struct Redirect {
+ int redirectsRemaining;
+ bool async;
+ bool hasFired;
+ };
+
+ std::map<void*, Redirect> redirects;
+
+private:
+ // This is the test object.
+ class TestObject : public Object<TestObject> { };
+
+ // This is the scriptable object. It has a single "testObject" property and an "evaluate" function.
+ class ScriptableObject : public Object<ScriptableObject> {
+ public:
+ bool hasMethod(NPIdentifier methodName)
+ {
+ return identifierIs(methodName, "get") || identifierIs(methodName, "getAsync") || identifierIs(methodName, "serviceAsync");
+ }
+
+ bool get(const NPVariant* args, uint32_t argCount, NPVariant* result, bool async)
+ {
+ if (argCount != 3 || !NPVARIANT_IS_STRING(args[0]) || !(NPVARIANT_IS_BOOLEAN(args[1]) || NPVARIANT_IS_DOUBLE(args[1]) || NPVARIANT_IS_INT32(args[1])) || !NPVARIANT_IS_STRING(args[2]))
+ return false;
+
+ const NPString* notifyString = &NPVARIANT_TO_STRING(args[2]);
+ basic_string<NPUTF8> notify(notifyString->UTF8Characters, notifyString->UTF8Length);
+ NPIdentifier notifyMethod = pluginTest()->NPN_GetStringIdentifier(notify.c_str());
+
+ Redirect& redirect = static_cast<URLRedirect*>(pluginTest())->redirects[reinterpret_cast<void*>(notifyMethod)];
+ if (NPVARIANT_IS_DOUBLE(args[1]))
+ redirect.redirectsRemaining = NPVARIANT_TO_DOUBLE(args[1]);
+ else if (NPVARIANT_IS_INT32(args[1]))
+ redirect.redirectsRemaining = NPVARIANT_TO_INT32(args[1]);
+ else if (NPVARIANT_IS_BOOLEAN(args[1]))
+ redirect.redirectsRemaining = NPVARIANT_TO_BOOLEAN(args[1]);
+ redirect.async = async;
+ redirect.hasFired = true;
+
+ const NPString* urlString = &NPVARIANT_TO_STRING(args[0]);
+ basic_string<NPUTF8> url(urlString->UTF8Characters, urlString->UTF8Length);
+
+ pluginTest()->NPN_GetURLNotify(url.c_str(), 0, reinterpret_cast<void*>(notifyMethod));
+
+ VOID_TO_NPVARIANT(*result);
+ return true;
+ }
+
+ bool serviceAsync(const NPVariant* args, uint32_t argCount, NPVariant* result)
+ {
+ if (argCount)
+ return false;
+
+ NPBool seen = 0;
+ URLRedirect* plugin = static_cast<URLRedirect*>(pluginTest());
+ for (auto& redirect : plugin->redirects) {
+ if (redirect.second.hasFired)
+ continue;
+ redirect.second.hasFired = true;
+ plugin->NPN_URLRedirectResponse(redirect.first, redirect.second.redirectsRemaining);
+ if (redirect.second.redirectsRemaining)
+ --redirect.second.redirectsRemaining;
+ seen = 1;
+ }
+
+ BOOLEAN_TO_NPVARIANT(seen, *result);
+ return true;
+ }
+
+ bool invoke(NPIdentifier methodName, const NPVariant* args, uint32_t argCount, NPVariant* result)
+ {
+ if (identifierIs(methodName, "get"))
+ return get(args, argCount, result, false);
+
+ if (identifierIs(methodName, "getAsync"))
+ return get(args, argCount, result, true);
+
+ if (identifierIs(methodName, "serviceAsync"))
+ return serviceAsync(args, argCount, result);
+
+ return false;
+ }
+ };
+
+ virtual NPError NPP_GetValue(NPPVariable variable, void *value)
+ {
+ if (variable != NPPVpluginScriptableNPObject)
+ return NPERR_GENERIC_ERROR;
+
+ *(NPObject**)value = ScriptableObject::create(this);
+
+ return NPERR_NO_ERROR;
+ }
+
+ virtual bool NPP_URLNotify(const char* url, NPReason reason, void* notifyData)
+ {
+ NPVariant args[2];
+
+ NPObject* windowScriptObject;
+ NPN_GetValue(NPNVWindowNPObject, &windowScriptObject);
+
+ NPIdentifier callbackIdentifier = notifyData;
+
+ INT32_TO_NPVARIANT(reason, args[0]);
+ STRINGZ_TO_NPVARIANT(url, args[1]);
+
+ NPVariant browserResult;
+ if (NPN_Invoke(windowScriptObject, callbackIdentifier, args, 2, &browserResult))
+ NPN_ReleaseVariantValue(&browserResult);
+
+ return true;
+ }
+
+ virtual void NPP_URLRedirectNotify(const char*, int32_t, void* notifyData)
+ {
+ Redirect& redirect = redirects[notifyData];
+ if (redirect.async) {
+ redirect.hasFired = false;
+ return;
+ }
+
+ NPN_URLRedirectResponse(notifyData, redirect.redirectsRemaining);
+ if (redirect.redirectsRemaining)
+ --redirect.redirectsRemaining;
+ }
+};
+
+static PluginTest::Register<URLRedirect> urlRedirect("url-redirect");
+
diff --git a/Tools/DumpRenderTree/TestNetscapePlugIn/main.cpp b/Tools/DumpRenderTree/TestNetscapePlugIn/main.cpp
index 85cd41d2c..6a7303f13 100644
--- a/Tools/DumpRenderTree/TestNetscapePlugIn/main.cpp
+++ b/Tools/DumpRenderTree/TestNetscapePlugIn/main.cpp
@@ -41,10 +41,17 @@ extern "C" void GlobalToLocal(Point*);
using namespace std;
+#if defined(__GNUC__)
+#define CRASH() do { \
+ *(int *)(uintptr_t)0xbbadbeef = 0; \
+ __builtin_trap(); /* More reliable, but doesn't say BBADBEEF. */ \
+} while (false)
+#else
#define CRASH() do { \
*(int *)(uintptr_t)0xbbadbeef = 0; \
((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \
-} while(false)
+} while (false)
+#endif
static bool getEntryPointsWasCalled;
static bool initializeWasCalled;
@@ -116,6 +123,7 @@ NPError STDCALL NP_GetEntryPoints(NPPluginFuncs *pluginFuncs)
pluginFuncs->print = NPP_Print;
pluginFuncs->event = NPP_HandleEvent;
pluginFuncs->urlnotify = NPP_URLNotify;
+ pluginFuncs->urlredirectnotify = NPP_URLRedirectNotify;
pluginFuncs->getvalue = NPP_GetValue;
pluginFuncs->setvalue = NPP_SetValue;
@@ -348,29 +356,30 @@ NPError NPP_SetWindow(NPP instance, NPWindow *window)
{
PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
- if (obj) {
- obj->lastWindow = *window;
+ if (!obj)
+ return NPERR_GENERIC_ERROR;
- if (obj->logSetWindow) {
- pluginLog(instance, "NPP_SetWindow: %d %d", (int)window->width, (int)window->height);
- obj->logSetWindow = FALSE;
- executeScript(obj, "testRunner.notifyDone();");
- }
+ obj->lastWindow = *window;
- if (obj->onSetWindow)
- executeScript(obj, obj->onSetWindow);
+ if (obj->logSetWindow) {
+ pluginLog(instance, "NPP_SetWindow: %d %d", (int)window->width, (int)window->height);
+ obj->logSetWindow = FALSE;
+ executeScript(obj, "testRunner.notifyDone();");
+ }
- if (obj->testWindowOpen) {
- testWindowOpen(instance);
- obj->testWindowOpen = FALSE;
- }
+ if (obj->onSetWindow)
+ executeScript(obj, obj->onSetWindow);
- if (obj->testKeyboardFocusForPlugins) {
- obj->eventLogging = true;
- executeScript(obj, "eventSender.keyDown('A');");
- }
+ if (obj->testWindowOpen) {
+ testWindowOpen(instance);
+ obj->testWindowOpen = FALSE;
}
-
+
+ if (obj->testKeyboardFocusForPlugins) {
+ obj->eventLogging = true;
+ executeScript(obj, "eventSender.keyDown('A');");
+ }
+
return obj->pluginTest->NPP_SetWindow(window);
}
@@ -799,6 +808,12 @@ void NPP_URLNotify(NPP instance, const char *url, NPReason reason, void *notifyD
handleCallback(obj, url, reason, notifyData);
}
+void NPP_URLRedirectNotify(NPP instance, const char *url, int32_t status, void *notifyData)
+{
+ PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
+ obj->pluginTest->NPP_URLRedirectNotify(url, status, notifyData);
+}
+
NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value)
{
#ifdef XP_UNIX
diff --git a/Tools/DumpRenderTree/TestRunner.cpp b/Tools/DumpRenderTree/TestRunner.cpp
index 7b249770e..b5270dc46 100644
--- a/Tools/DumpRenderTree/TestRunner.cpp
+++ b/Tools/DumpRenderTree/TestRunner.cpp
@@ -11,7 +11,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -59,7 +59,7 @@ const unsigned TestRunner::viewHeight = 600;
const unsigned TestRunner::w3cSVGViewWidth = 480;
const unsigned TestRunner::w3cSVGViewHeight = 360;
-TestRunner::TestRunner(const std::string& testPathOrURL, const std::string& expectedPixelHash)
+TestRunner::TestRunner(const std::string& testURL, const std::string& expectedPixelHash)
: m_disallowIncreaseForApplicationCacheQuota(false)
, m_dumpApplicationCacheDelegateCallbacks(false)
, m_dumpAsAudio(false)
@@ -112,15 +112,16 @@ TestRunner::TestRunner(const std::string& testPathOrURL, const std::string& expe
, m_hasPendingWebNotificationClick(false)
, m_databaseDefaultQuota(-1)
, m_databaseMaxQuota(-1)
- , m_testPathOrURL(testPathOrURL)
+ , m_testURL(testURL)
, m_expectedPixelHash(expectedPixelHash)
, m_titleTextDirection("ltr")
+ , m_timeout(0)
{
}
-PassRefPtr<TestRunner> TestRunner::create(const std::string& testPathOrURL, const std::string& expectedPixelHash)
+PassRefPtr<TestRunner> TestRunner::create(const std::string& testURL, const std::string& expectedPixelHash)
{
- return adoptRef(new TestRunner(testPathOrURL, expectedPixelHash));
+ return adoptRef(new TestRunner(testURL, expectedPixelHash));
}
// Static Functions
@@ -466,73 +467,6 @@ static JSValueRef clearAllDatabasesCallback(JSContextRef context, JSObjectRef fu
return JSValueMakeUndefined(context);
}
-static JSValueRef syncLocalStorageCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
-
- controller->syncLocalStorage();
-
- return JSValueMakeUndefined(context);
-}
-
-static JSValueRef observeStorageTrackerNotificationsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
-
- if (argumentCount < 1)
- return JSValueMakeUndefined(context);
-
- unsigned numNotifications = JSValueToNumber(context, arguments[0], exception);
-
- ASSERT(!*exception);
-
- controller->observeStorageTrackerNotifications(numNotifications);
-
- return JSValueMakeUndefined(context);
-}
-
-static JSValueRef deleteAllLocalStorageCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
- controller->deleteAllLocalStorage();
-
- return JSValueMakeUndefined(context);
-}
-
-static JSValueRef deleteLocalStorageForOriginCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
-
- if (argumentCount < 1)
- return JSValueMakeUndefined(context);
-
- JSRetainPtr<JSStringRef> url(Adopt, JSValueToStringCopy(context, arguments[0], exception));
- ASSERT(!*exception);
-
- controller->deleteLocalStorageForOrigin(url.get());
-
- return JSValueMakeUndefined(context);
-}
-
-static JSValueRef localStorageDiskUsageForOriginCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
-
- if (argumentCount < 1)
- return JSValueMakeUndefined(context);
-
- JSRetainPtr<JSStringRef> originURL(Adopt, JSValueToStringCopy(context, arguments[0], exception));
- ASSERT(!*exception);
-
- return JSValueMakeNumber(context, controller->localStorageDiskUsageForOrigin(originURL.get()));
-}
-
-static JSValueRef originsWithLocalStorageCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
- return controller->originsWithLocalStorage(context);
-}
-
static JSValueRef clearBackForwardListCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
// Has mac & windows implementation
@@ -712,6 +646,12 @@ static JSValueRef numberOfPendingGeolocationPermissionRequestsCallback(JSContext
return JSValueMakeNumber(context, controller->numberOfPendingGeolocationPermissionRequests());
}
+static JSValueRef isGeolocationProviderActiveCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
+ return JSValueMakeBoolean(context, controller->isGeolocationProviderActive());
+}
+
static JSValueRef queueBackNavigationCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
// Has mac & windows implementation
@@ -1104,38 +1044,6 @@ static JSValueRef setMockGeolocationPositionUnavailableErrorCallback(JSContextRe
return JSValueMakeUndefined(context);
}
-static JSValueRef addMockSpeechInputResultCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- if (argumentCount < 3)
- return JSValueMakeUndefined(context);
-
- JSRetainPtr<JSStringRef> result(Adopt, JSValueToStringCopy(context, arguments[0], exception));
- ASSERT(!*exception);
-
- double confidence = JSValueToNumber(context, arguments[1], exception);
-
- JSRetainPtr<JSStringRef> language(Adopt, JSValueToStringCopy(context, arguments[2], exception));
- ASSERT(!*exception);
-
- TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
- controller->addMockSpeechInputResult(result.get(), confidence, language.get());
-
- return JSValueMakeUndefined(context);
-}
-
-static JSValueRef setMockSpeechInputDumpRectCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- if (argumentCount < 1)
- return JSValueMakeUndefined(context);
-
- bool dumpRect = JSValueToBoolean(context, arguments[0]);
-
- TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
- controller->setMockSpeechInputDumpRect(dumpRect);
-
- return JSValueMakeUndefined(context);
-}
-
static JSValueRef setNewWindowsCopyBackForwardListCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
// Has mac implementation
@@ -1579,12 +1487,10 @@ static JSValueRef closeWebInspectorCallback(JSContextRef context, JSObjectRef fu
static JSValueRef evaluateInWebInspectorCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
- double callId = JSValueToNumber(context, arguments[0], exception);
- ASSERT(!*exception);
- JSRetainPtr<JSStringRef> script(Adopt, JSValueToStringCopy(context, arguments[1], exception));
+ JSRetainPtr<JSStringRef> script(Adopt, JSValueToStringCopy(context, arguments[0], exception));
ASSERT(!*exception);
- controller->evaluateInWebInspector(static_cast<long>(callId), script.get());
+ controller->evaluateInWebInspector(script.get());
return JSValueMakeUndefined(context);
}
@@ -1884,6 +1790,13 @@ static JSValueRef getTitleTextDirectionCallback(JSContextRef context, JSObjectRe
return JSValueMakeString(context, titleDirection.get());
}
+static JSValueRef getInspectorTestStubURLCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
+{
+ TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
+ JSRetainPtr<JSStringRef> url(Adopt, controller->inspectorTestStubURL());
+ return JSValueMakeString(context, url.get());
+}
+
static bool setGlobalFlagCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
{
TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
@@ -2020,11 +1933,16 @@ static JSValueRef simulateWebNotificationClickCallback(JSContextRef context, JSO
return JSValueMakeUndefined(context);
}
-static JSValueRef numberOfDFGCompiles(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+static JSValueRef failNextNewCodeBlock(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
if (argumentCount < 1)
return JSValueMakeUndefined(context);
+ return JSC::failNextNewCodeBlock(context);
+}
+
+static JSValueRef numberOfDFGCompiles(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
return JSC::numberOfDFGCompiles(context, arguments[0]);
}
@@ -2077,6 +1995,7 @@ JSStaticValue* TestRunner::staticValues()
{ "titleTextDirection", getTitleTextDirectionCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "databaseDefaultQuota", getDatabaseDefaultQuotaCallback, setDatabaseDefaultQuotaCallback, kJSPropertyAttributeNone },
{ "databaseMaxQuota", getDatabaseMaxQuotaCallback, setDatabaseMaxQuotaCallback, kJSPropertyAttributeNone },
+ { "inspectorTestStubURL", getInspectorTestStubURLCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ 0, 0, 0, 0 }
};
return staticValues;
@@ -2133,6 +2052,7 @@ JSStaticFunction* TestRunner::staticFunctions()
{ "originsWithApplicationCache", originsWithApplicationCacheCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "goBack", goBackCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "ignoreLegacyWebNotificationPermissionRequests", ignoreLegacyWebNotificationPermissionRequestsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "isGeolocationProviderActive", isGeolocationProviderActiveCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "isCommandEnabled", isCommandEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "keepWebHistory", keepWebHistoryCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "numberOfPendingGeolocationPermissionRequests", numberOfPendingGeolocationPermissionRequestsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
@@ -2178,8 +2098,6 @@ JSStaticFunction* TestRunner::staticFunctions()
{ "setMockDeviceOrientation", setMockDeviceOrientationCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "setMockGeolocationPositionUnavailableError", setMockGeolocationPositionUnavailableErrorCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "setMockGeolocationPosition", setMockGeolocationPositionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "addMockSpeechInputResult", addMockSpeechInputResultCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "setMockSpeechInputDumpRect", setMockSpeechInputDumpRectCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "setNewWindowsCopyBackForwardList", setNewWindowsCopyBackForwardListCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "setPageVisibility", setPageVisibilityCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "setPOSIXLocale", setPOSIXLocaleCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
@@ -2221,12 +2139,6 @@ JSStaticFunction* TestRunner::staticFunctions()
{ "addOriginAccessWhitelistEntry", addOriginAccessWhitelistEntryCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "setScrollbarPolicy", setScrollbarPolicyCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "authenticateSession", authenticateSessionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "deleteAllLocalStorage", deleteAllLocalStorageCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "syncLocalStorage", syncLocalStorageCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "observeStorageTrackerNotifications", observeStorageTrackerNotificationsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "deleteLocalStorageForOrigin", deleteLocalStorageForOriginCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "localStorageDiskUsageForOrigin", localStorageDiskUsageForOriginCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "originsWithLocalStorage", originsWithLocalStorageCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "setShouldPaintBrokenImage", setShouldPaintBrokenImageCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "setTextDirection", setTextDirectionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "setShouldStayOnPageAfterHandlingBeforeUnload", setShouldStayOnPageAfterHandlingBeforeUnloadCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
@@ -2242,6 +2154,7 @@ JSStaticFunction* TestRunner::staticFunctions()
{ "denyWebNotificationPermission", denyWebNotificationPermissionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "removeAllWebNotificationPermissions", removeAllWebNotificationPermissionsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "simulateWebNotificationClick", simulateWebNotificationClickCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "failNextNewCodeBlock", failNextNewCodeBlock, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "numberOfDFGCompiles", numberOfDFGCompiles, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "neverInlineFunction", neverInlineFunction, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ 0, 0, 0 }
@@ -2252,37 +2165,37 @@ JSStaticFunction* TestRunner::staticFunctions()
void TestRunner::queueLoadHTMLString(JSStringRef content, JSStringRef baseURL)
{
- WorkQueue::shared()->queue(new LoadHTMLStringItem(content, baseURL));
+ WorkQueue::singleton().queue(new LoadHTMLStringItem(content, baseURL));
}
void TestRunner::queueLoadAlternateHTMLString(JSStringRef content, JSStringRef baseURL, JSStringRef unreachableURL)
{
- WorkQueue::shared()->queue(new LoadHTMLStringItem(content, baseURL, unreachableURL));
+ WorkQueue::singleton().queue(new LoadHTMLStringItem(content, baseURL, unreachableURL));
}
void TestRunner::queueBackNavigation(int howFarBack)
{
- WorkQueue::shared()->queue(new BackItem(howFarBack));
+ WorkQueue::singleton().queue(new BackItem(howFarBack));
}
void TestRunner::queueForwardNavigation(int howFarForward)
{
- WorkQueue::shared()->queue(new ForwardItem(howFarForward));
+ WorkQueue::singleton().queue(new ForwardItem(howFarForward));
}
void TestRunner::queueLoadingScript(JSStringRef script)
{
- WorkQueue::shared()->queue(new LoadingScriptItem(script));
+ WorkQueue::singleton().queue(new LoadingScriptItem(script));
}
void TestRunner::queueNonLoadingScript(JSStringRef script)
{
- WorkQueue::shared()->queue(new NonLoadingScriptItem(script));
+ WorkQueue::singleton().queue(new NonLoadingScriptItem(script));
}
void TestRunner::queueReload()
{
- WorkQueue::shared()->queue(new ReloadItem);
+ WorkQueue::singleton().queue(new ReloadItem);
}
void TestRunner::ignoreLegacyWebNotificationPermissionRequests()
@@ -2293,7 +2206,6 @@ void TestRunner::ignoreLegacyWebNotificationPermissionRequests()
void TestRunner::waitToDumpWatchdogTimerFired()
{
const char* message = "FAIL: Timed out waiting for notifyDone to be called\n";
- fprintf(stderr, "%s", message);
fprintf(stdout, "%s", message);
notifyDone();
}
diff --git a/Tools/DumpRenderTree/TestRunner.h b/Tools/DumpRenderTree/TestRunner.h
index 882c0e96c..d51ac6feb 100644
--- a/Tools/DumpRenderTree/TestRunner.h
+++ b/Tools/DumpRenderTree/TestRunner.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.
*
@@ -39,7 +39,7 @@
class TestRunner : public RefCounted<TestRunner> {
public:
- static PassRefPtr<TestRunner> create(const std::string& testPathOrURL, const std::string& expectedPixelHash);
+ static PassRefPtr<TestRunner> create(const std::string& testURL, const std::string& expectedPixelHash);
static const unsigned viewWidth;
static const unsigned viewHeight;
@@ -52,6 +52,8 @@ public:
void makeWindowObject(JSContextRef, JSObjectRef windowObject, JSValueRef* exception);
void addDisallowedURL(JSStringRef url);
+ const std::set<std::string>& allowedHosts() const { return m_allowedHosts; }
+ void setAllowedHosts(std::set<std::string> hosts) { m_allowedHosts = WTFMove(hosts); }
void addURLToRedirect(std::string origin, std::string destination);
const std::string& redirectionDestinationForURL(std::string);
void clearAllApplicationCaches();
@@ -74,6 +76,7 @@ public:
void keepWebHistory();
void notifyDone();
int numberOfPendingGeolocationPermissionRequests();
+ bool isGeolocationProviderActive();
void overridePreference(JSStringRef key, JSStringRef value);
JSStringRef pathToLocalResource(JSContextRef, JSStringRef url);
void queueBackNavigation(int howFarBackward);
@@ -102,8 +105,6 @@ public:
void setMockDeviceOrientation(bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma);
void setMockGeolocationPosition(double latitude, double longitude, double accuracy, bool providesAltitude, double altitude, bool providesAltitudeAccuracy, double altitudeAccuracy, bool providesHeading, double heading, bool providesSpeed, double speed);
void setMockGeolocationPositionUnavailableError(JSStringRef message);
- void addMockSpeechInputResult(JSStringRef result, double confidence, JSStringRef language);
- void setMockSpeechInputDumpRect(bool flag);
void setPersistentUserStyleSheetLocation(JSStringRef path);
void setPluginsEnabled(bool);
void setPopupBlockingEnabled(bool);
@@ -117,7 +118,6 @@ public:
void setXSSAuditorEnabled(bool flag);
void setSpatialNavigationEnabled(bool);
void setScrollbarPolicy(JSStringRef orientation, JSStringRef policy);
- void startSpeechInput(JSContextRef inputElement);
#if PLATFORM(IOS)
void setTelephoneNumberParsingEnabled(bool enable);
void setPagePaused(bool paused);
@@ -288,7 +288,7 @@ public:
bool useDeferredFrameLoading() const { return m_useDeferredFrameLoading; }
void setUseDeferredFrameLoading(bool flag) { m_useDeferredFrameLoading = flag; }
- const std::string& testPathOrURL() const { return m_testPathOrURL; }
+ const std::string& testURL() const { return m_testURL; }
const std::string& expectedPixelHash() const { return m_expectedPixelHash; }
const std::vector<char>& audioResult() const { return m_audioResult; }
@@ -307,7 +307,9 @@ public:
void setDeveloperExtrasEnabled(bool);
void showWebInspector();
void closeWebInspector();
- void evaluateInWebInspector(long callId, JSStringRef script);
+ void evaluateInWebInspector(JSStringRef script);
+ JSStringRef inspectorTestStubURL();
+
void evaluateScriptInIsolatedWorld(unsigned worldID, JSObjectRef globalObject, JSStringRef script);
void evaluateScriptInIsolatedWorldAndReturnValue(unsigned worldID, JSObjectRef globalObject, JSStringRef script);
@@ -336,13 +338,6 @@ public:
// Simulate a request an embedding application could make, populating per-session credential storage.
void authenticateSession(JSStringRef url, JSStringRef username, JSStringRef password);
- JSValueRef originsWithLocalStorage(JSContextRef);
- void deleteAllLocalStorage();
- void deleteLocalStorageForOrigin(JSStringRef originIdentifier);
- long long localStorageDiskUsageForOrigin(JSStringRef originIdentifier);
- void observeStorageTrackerNotifications(unsigned number);
- void syncLocalStorage();
-
void setShouldPaintBrokenImage(bool);
bool shouldPaintBrokenImage() const { return m_shouldPaintBrokenImage; }
@@ -359,8 +354,10 @@ public:
bool hasPendingWebNotificationClick() const { return m_hasPendingWebNotificationClick; }
+ void setCustomTimeout(int duration) { m_timeout = duration; }
+
private:
- TestRunner(const std::string& testPathOrURL, const std::string& expectedPixelHash);
+ TestRunner(const std::string& testURL, const std::string& expectedPixelHash);
void setGeolocationPermissionCommon(bool allow);
@@ -421,19 +418,22 @@ private:
std::string m_authenticationUsername;
std::string m_authenticationPassword;
- std::string m_testPathOrURL;
+ std::string m_testURL;
std::string m_expectedPixelHash; // empty string if no hash
std::string m_titleTextDirection;
std::set<std::string> m_willSendRequestClearHeaders;
+ std::set<std::string> m_allowedHosts;
std::vector<char> m_audioResult;
std::map<std::string, std::string> m_URLsToRedirect;
-
+
static JSClassRef getJSClass();
static JSStaticValue* staticValues();
static JSStaticFunction* staticFunctions();
+
+ int m_timeout;
};
#endif // TestRunner_h
diff --git a/Tools/DumpRenderTree/WorkQueue.cpp b/Tools/DumpRenderTree/WorkQueue.cpp
index 0106fbac1..097f4cdd2 100644
--- a/Tools/DumpRenderTree/WorkQueue.cpp
+++ b/Tools/DumpRenderTree/WorkQueue.cpp
@@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -31,6 +31,7 @@
#include "WorkQueueItem.h"
#include <wtf/Assertions.h>
+#include <wtf/NeverDestroyed.h>
static const unsigned queueLength = 1024;
@@ -38,9 +39,9 @@ static WorkQueueItem* theQueue[queueLength];
static unsigned startOfQueue;
static unsigned endOfQueue;
-WorkQueue* WorkQueue::shared()
+WorkQueue& WorkQueue::singleton()
{
- static WorkQueue* sharedInstance = new WorkQueue;
+ static NeverDestroyed<WorkQueue> sharedInstance;
return sharedInstance;
}
diff --git a/Tools/DumpRenderTree/WorkQueue.h b/Tools/DumpRenderTree/WorkQueue.h
index 649c6c1f5..0697e7c3e 100644
--- a/Tools/DumpRenderTree/WorkQueue.h
+++ b/Tools/DumpRenderTree/WorkQueue.h
@@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -29,11 +29,15 @@
#ifndef WorkQueue_h
#define WorkQueue_h
+#include <wtf/Forward.h>
+
class WorkQueueItem;
class WorkQueue {
+friend class WTF::NeverDestroyed<WorkQueue>;
+
public:
- static WorkQueue* shared();
+ static WorkQueue& singleton();
void queue(WorkQueueItem*);
WorkQueueItem* dequeue();
diff --git a/Tools/DumpRenderTree/WorkQueueItem.h b/Tools/DumpRenderTree/WorkQueueItem.h
index 08fc2208b..6a49f593f 100644
--- a/Tools/DumpRenderTree/WorkQueueItem.h
+++ b/Tools/DumpRenderTree/WorkQueueItem.h
@@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
diff --git a/Tools/DumpRenderTree/atk/AccessibilityCallbacks.h b/Tools/DumpRenderTree/atk/AccessibilityCallbacks.h
deleted file mode 100644
index 0feef55c8..000000000
--- a/Tools/DumpRenderTree/atk/AccessibilityCallbacks.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2011 Igalia S.L.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef AccessibilityCallbacks_h
-#define AccessibilityCallbacks_h
-
-#if HAVE(ACCESSIBILITY)
-
-#include "AccessibilityNotificationHandlerAtk.h"
-#include "AccessibilityUIElement.h"
-
-void connectAccessibilityCallbacks();
-bool disconnectAccessibilityCallbacks();
-void addAccessibilityNotificationHandler(AccessibilityNotificationHandler*);
-void removeAccessibilityNotificationHandler(AccessibilityNotificationHandler*);
-
-#endif // HAVE(ACCESSIBILITY)
-
-#endif // AccessibilityCallbacks_h
diff --git a/Tools/DumpRenderTree/atk/AccessibilityCallbacksAtk.cpp b/Tools/DumpRenderTree/atk/AccessibilityCallbacksAtk.cpp
deleted file mode 100644
index 01f6651b4..000000000
--- a/Tools/DumpRenderTree/atk/AccessibilityCallbacksAtk.cpp
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * Copyright (C) 2011 Igalia S.L.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "AccessibilityCallbacks.h"
-
-#if HAVE(ACCESSIBILITY)
-
-#include "AccessibilityController.h"
-#include "AccessibilityNotificationHandlerAtk.h"
-#include "DumpRenderTree.h"
-#include "JSRetainPtr.h"
-#include <atk/atk.h>
-#include <wtf/gobject/GUniquePtr.h>
-
-#if PLATFORM(GTK)
-#include "WebCoreSupport/DumpRenderTreeSupportGtk.h"
-#include <webkit/webkit.h>
-#endif
-
-#if PLATFORM(EFL)
-#include "DumpRenderTreeChrome.h"
-#include "WebCoreSupport/DumpRenderTreeSupportEfl.h"
-#endif
-
-typedef HashMap<PlatformUIElement, AccessibilityNotificationHandler*> NotificationHandlersMap;
-
-static guint stateChangeListenerId = 0;
-static guint focusEventListenerId = 0;
-static guint activeDescendantChangedListenerId = 0;
-static guint childrenChangedListenerId = 0;
-static guint propertyChangedListenerId = 0;
-static guint visibleDataChangedListenerId = 0;
-static guint loadCompleteListenerId = 0;
-// Up to 2014 it was obligatory to mirror the changes from
-// WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.cpp,
-// but the habit has been dropped: https://bugs.webkit.org/show_bug.cgi?id=132527#c6
-static NotificationHandlersMap notificationHandlers;
-static AccessibilityNotificationHandler* globalNotificationHandler = 0;
-
-extern bool loggingAccessibilityEvents;
-
-static void printAccessibilityEvent(AtkObject* accessible, const gchar* signalName, const gchar* signalValue)
-{
- // Do not handle state-change:defunct signals, as the AtkObject
- // associated to them will not be valid at this point already.
- if (!signalName || !g_strcmp0(signalName, "state-change:defunct"))
- return;
-
- if (!accessible || !ATK_IS_OBJECT(accessible))
- return;
-
- const gchar* objectName = atk_object_get_name(accessible);
- AtkRole objectRole = atk_object_get_role(accessible);
-
- // Try to always provide a name to be logged for the object.
- if (!objectName || *objectName == '\0')
- objectName = "(No name)";
-
- GUniquePtr<gchar> signalNameAndValue(signalValue ? g_strdup_printf("%s = %s", signalName, signalValue) : g_strdup(signalName));
- printf("Accessibility object emitted \"%s\" / Name: \"%s\" / Role: %d\n", signalNameAndValue.get(), objectName, objectRole);
-}
-
-static gboolean axObjectEventListener(GSignalInvocationHint *signalHint, guint numParamValues, const GValue *paramValues, gpointer data)
-{
- // At least we should receive the instance emitting the signal.
- if (numParamValues < 1)
- return true;
-
- AtkObject* accessible = ATK_OBJECT(g_value_get_object(&paramValues[0]));
- if (!accessible || !ATK_IS_OBJECT(accessible))
- return true;
-
- GSignalQuery signalQuery;
- GUniquePtr<gchar> signalName;
- GUniquePtr<gchar> signalValue;
- String notificationName;
-
- g_signal_query(signalHint->signal_id, &signalQuery);
-
- if (!g_strcmp0(signalQuery.signal_name, "state-change")) {
- signalName.reset(g_strdup_printf("state-change:%s", g_value_get_string(&paramValues[1])));
- signalValue.reset(g_strdup_printf("%d", g_value_get_boolean(&paramValues[2])));
- if (!g_strcmp0(g_value_get_string(&paramValues[1]), "checked"))
- notificationName = "CheckedStateChanged";
- else if (!g_strcmp0(g_value_get_string(&paramValues[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(&paramValues[1])));
- if (g_value_get_boolean(&paramValues[1]))
- notificationName = "AXFocusedUIElementChanged";
- } else if (!g_strcmp0(signalQuery.signal_name, "children-changed")) {
- const gchar* childrenChangedDetail = g_quark_to_string(signalHint->detail);
- signalName.reset(g_strdup_printf("children-changed:%s", childrenChangedDetail));
- signalValue.reset(g_strdup_printf("%d", g_value_get_uint(&paramValues[1])));
- notificationName = !g_strcmp0(childrenChangedDetail, "add") ? "AXChildrenAdded" : "AXChildrenRemoved";
- } else if (!g_strcmp0(signalQuery.signal_name, "property-change")) {
- signalName.reset(g_strdup_printf("property-change:%s", g_quark_to_string(signalHint->detail)));
- if (!g_strcmp0(g_quark_to_string(signalHint->detail), "accessible-value"))
- notificationName = "AXValueChanged";
- } else if (!g_strcmp0(signalQuery.signal_name, "load-complete"))
- notificationName = "AXLoadComplete";
- else
- signalName.reset(g_strdup(signalQuery.signal_name));
-
- if (loggingAccessibilityEvents)
- printAccessibilityEvent(accessible, signalName.get(), signalValue.get());
-
-#if PLATFORM(GTK)
- JSGlobalContextRef jsContext = webkit_web_frame_get_global_context(mainFrame);
-#elif PLATFORM(EFL)
- JSGlobalContextRef jsContext = DumpRenderTreeSupportEfl::globalContextRefForFrame(browser->mainFrame());
-#else
- JSContextRef jsContext = 0;
-#endif
- if (!jsContext)
- return true;
-
- if (notificationName.length()) {
- JSRetainPtr<JSStringRef> jsNotificationEventName(Adopt, JSStringCreateWithUTF8CString(notificationName.utf8().data()));
- JSValueRef notificationNameArgument = JSValueMakeString(jsContext, jsNotificationEventName.get());
- NotificationHandlersMap::iterator elementNotificationHandler = notificationHandlers.find(accessible);
- if (elementNotificationHandler != notificationHandlers.end()) {
- // Listener for one element just gets one argument, the notification name.
- JSObjectCallAsFunction(jsContext, elementNotificationHandler->value->notificationFunctionCallback(), 0, 1, &notificationNameArgument, 0);
- }
-
- if (globalNotificationHandler) {
- // A global listener gets the element and the notification name as arguments.
- JSValueRef arguments[2];
- arguments[0] = AccessibilityUIElement::makeJSAccessibilityUIElement(jsContext, AccessibilityUIElement(accessible));
- arguments[1] = notificationNameArgument;
- JSObjectCallAsFunction(jsContext, globalNotificationHandler->notificationFunctionCallback(), 0, 2, arguments, 0);
- }
- }
-
- return true;
-}
-
-void connectAccessibilityCallbacks()
-{
- // Ensure no callbacks are connected before.
- if (!disconnectAccessibilityCallbacks())
- return;
-
- // Ensure that accessibility is initialized for the WebView by querying for
- // the root accessible object, which will create the full hierarchy.
-#if PLATFORM(GTK)
- DumpRenderTreeSupportGtk::getRootAccessibleElement(mainFrame);
-#elif PLATFORM(EFL)
- DumpRenderTreeSupportEfl::rootAccessibleElement(browser->mainFrame());
-#endif
-
- // Add global listeners for AtkObject's signals.
- stateChangeListenerId = atk_add_global_event_listener(axObjectEventListener, "ATK:AtkObject:state-change");
- focusEventListenerId = atk_add_global_event_listener(axObjectEventListener, "ATK:AtkObject:focus-event");
- activeDescendantChangedListenerId = atk_add_global_event_listener(axObjectEventListener, "ATK:AtkObject:active-descendant-changed");
- childrenChangedListenerId = atk_add_global_event_listener(axObjectEventListener, "ATK:AtkObject:children-changed");
- propertyChangedListenerId = atk_add_global_event_listener(axObjectEventListener, "ATK:AtkObject:property-change");
- visibleDataChangedListenerId = atk_add_global_event_listener(axObjectEventListener, "ATK:AtkObject:visible-data-changed");
- loadCompleteListenerId = atk_add_global_event_listener(axObjectEventListener, "ATK:AtkDocument:load-complete");
-
- // Ensure the Atk interface types are registered, otherwise
- // the AtkDocument signal handlers below won't get registered.
- GObject* dummyAxObject = G_OBJECT(g_object_new(ATK_TYPE_OBJECT, 0));
- AtkObject* dummyNoOpAxObject = atk_no_op_object_new(dummyAxObject);
- g_object_unref(G_OBJECT(dummyNoOpAxObject));
- g_object_unref(dummyAxObject);
-}
-
-bool disconnectAccessibilityCallbacks()
-{
- // Only disconnect if logging is off and there is no notification handler.
- if (loggingAccessibilityEvents || !notificationHandlers.isEmpty() || globalNotificationHandler)
- return false;
-
- // AtkObject signals.
- if (stateChangeListenerId) {
- atk_remove_global_event_listener(stateChangeListenerId);
- stateChangeListenerId = 0;
- }
- if (focusEventListenerId) {
- atk_remove_global_event_listener(focusEventListenerId);
- focusEventListenerId = 0;
- }
- if (activeDescendantChangedListenerId) {
- atk_remove_global_event_listener(activeDescendantChangedListenerId);
- activeDescendantChangedListenerId = 0;
- }
- if (childrenChangedListenerId) {
- atk_remove_global_event_listener(childrenChangedListenerId);
- childrenChangedListenerId = 0;
- }
- if (propertyChangedListenerId) {
- atk_remove_global_event_listener(propertyChangedListenerId);
- propertyChangedListenerId = 0;
- }
- if (visibleDataChangedListenerId) {
- atk_remove_global_event_listener(visibleDataChangedListenerId);
- visibleDataChangedListenerId = 0;
- }
- if (loadCompleteListenerId) {
- atk_remove_global_event_listener(loadCompleteListenerId);
- loadCompleteListenerId = 0;
- }
-
- return true;
-}
-
-void addAccessibilityNotificationHandler(AccessibilityNotificationHandler* notificationHandler)
-{
- if (!notificationHandler)
- return;
-
-#if PLATFORM(GTK)
- JSGlobalContextRef jsContext = webkit_web_frame_get_global_context(mainFrame);
-#elif PLATFORM(EFL)
- JSGlobalContextRef jsContext = DumpRenderTreeSupportEfl::globalContextRefForFrame(browser->mainFrame());
-#else
- JSContextRef jsContext = 0;
-#endif
- if (!jsContext)
- return;
-
- JSValueProtect(jsContext, notificationHandler->notificationFunctionCallback());
- // Check if this notification handler is related to a specific element.
- if (notificationHandler->platformElement()) {
- NotificationHandlersMap::iterator currentNotificationHandler = notificationHandlers.find(notificationHandler->platformElement());
- if (currentNotificationHandler != notificationHandlers.end()) {
- ASSERT(currentNotificationHandler->value->platformElement());
- JSValueUnprotect(jsContext, currentNotificationHandler->value->notificationFunctionCallback());
- notificationHandlers.remove(currentNotificationHandler->value->platformElement());
- }
- notificationHandlers.add(notificationHandler->platformElement(), notificationHandler);
- } else {
- if (globalNotificationHandler)
- JSValueUnprotect(jsContext, globalNotificationHandler->notificationFunctionCallback());
- globalNotificationHandler = notificationHandler;
- }
-
- connectAccessibilityCallbacks();
-}
-
-void removeAccessibilityNotificationHandler(AccessibilityNotificationHandler* notificationHandler)
-{
- if (!notificationHandler)
- return;
-
-#if PLATFORM(GTK)
- JSGlobalContextRef jsContext = webkit_web_frame_get_global_context(mainFrame);
-#elif PLATFORM(EFL)
- JSGlobalContextRef jsContext = DumpRenderTreeSupportEfl::globalContextRefForFrame(browser->mainFrame());
-#else
- JSGlobalContextRef jsContext = 0;
-#endif
- if (!jsContext)
- return;
-
- if (globalNotificationHandler == notificationHandler) {
- JSValueUnprotect(jsContext, globalNotificationHandler->notificationFunctionCallback());
- globalNotificationHandler = 0;
- } else if (notificationHandler->platformElement()) {
- NotificationHandlersMap::iterator removeNotificationHandler = notificationHandlers.find(notificationHandler->platformElement());
- if (removeNotificationHandler != notificationHandlers.end()) {
- JSValueUnprotect(jsContext, removeNotificationHandler->value->notificationFunctionCallback());
- notificationHandlers.remove(removeNotificationHandler);
- }
- }
-}
-
-#endif
diff --git a/Tools/DumpRenderTree/atk/AccessibilityControllerAtk.cpp b/Tools/DumpRenderTree/atk/AccessibilityControllerAtk.cpp
deleted file mode 100644
index d8d0fc96c..000000000
--- a/Tools/DumpRenderTree/atk/AccessibilityControllerAtk.cpp
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2008, 2009, 2010 Apple Inc. All Rights Reserved.
- * Copyright (C) 2009 Jan Michael Alonzo
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "AccessibilityController.h"
-
-#if HAVE(ACCESSIBILITY)
-
-#include "AccessibilityCallbacks.h"
-#include "AccessibilityUIElement.h"
-#include "DumpRenderTree.h"
-
-#include <atk/atk.h>
-
-bool loggingAccessibilityEvents = false;
-
-AccessibilityController::AccessibilityController()
- : m_globalNotificationHandler(nullptr)
-{
-}
-
-AccessibilityController::~AccessibilityController()
-{
-}
-
-AccessibilityUIElement AccessibilityController::elementAtPoint(int x, int y)
-{
- // FIXME: implement
- return nullptr;
-}
-
-void AccessibilityController::platformResetToConsistentState()
-{
-}
-
-void AccessibilityController::setLogFocusEvents(bool)
-{
-}
-
-void AccessibilityController::setLogScrollingStartEvents(bool)
-{
-}
-
-void AccessibilityController::setLogValueChangeEvents(bool)
-{
-}
-
-void AccessibilityController::setLogAccessibilityEvents(bool logAccessibilityEvents)
-{
- if (logAccessibilityEvents == loggingAccessibilityEvents)
- return;
-
- if (!logAccessibilityEvents) {
- loggingAccessibilityEvents = false;
- disconnectAccessibilityCallbacks();
- return;
- }
-
- connectAccessibilityCallbacks();
- loggingAccessibilityEvents = true;
-}
-
-bool AccessibilityController::addNotificationListener(JSObjectRef functionCallback)
-{
- if (!functionCallback)
- return false;
-
- // Only one global notification listener.
- if (m_globalNotificationHandler)
- return false;
-
- m_globalNotificationHandler = AccessibilityNotificationHandler::create();
- m_globalNotificationHandler->setNotificationFunctionCallback(functionCallback);
-
- return true;
-}
-
-void AccessibilityController::removeNotificationListener()
-{
- // Programmers should not be trying to remove a listener that's already removed.
- ASSERT(m_globalNotificationHandler);
-
- m_globalNotificationHandler = nullptr;
-}
-
-JSRetainPtr<JSStringRef> AccessibilityController::platformName() const
-{
- JSRetainPtr<JSStringRef> platformName(Adopt, JSStringCreateWithUTF8CString("atk"));
- return platformName;
-}
-
-AtkObject* AccessibilityController::childElementById(AtkObject* parent, const char* id)
-{
- if (!ATK_IS_OBJECT(parent))
- return nullptr;
-
- bool parentFound = false;
- AtkAttributeSet* attributeSet(atk_object_get_attributes(parent));
- for (AtkAttributeSet* attributes = attributeSet; attributes; attributes = attributes->next) {
- AtkAttribute* attribute = static_cast<AtkAttribute*>(attributes->data);
- if (!strcmp(attribute->name, "html-id")) {
- if (!strcmp(attribute->value, id))
- parentFound = true;
- break;
- }
- }
- atk_attribute_set_free(attributeSet);
-
- if (parentFound)
- return parent;
-
- int childCount = atk_object_get_n_accessible_children(parent);
- for (int i = 0; i < childCount; i++) {
- AtkObject* result = childElementById(atk_object_ref_accessible_child(parent, i), id);
- if (ATK_IS_OBJECT(result))
- return result;
- }
-
- return nullptr;
-}
-
-#endif
diff --git a/Tools/DumpRenderTree/atk/AccessibilityNotificationHandlerAtk.cpp b/Tools/DumpRenderTree/atk/AccessibilityNotificationHandlerAtk.cpp
deleted file mode 100644
index 4565d5506..000000000
--- a/Tools/DumpRenderTree/atk/AccessibilityNotificationHandlerAtk.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2013 Samsung Electronics Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "AccessibilityNotificationHandlerAtk.h"
-
-#if HAVE(ACCESSIBILITY)
-
-#include "AccessibilityCallbacks.h"
-
-AccessibilityNotificationHandler::AccessibilityNotificationHandler(void)
- : m_platformElement(nullptr)
- , m_notificationFunctionCallback(nullptr)
-{
-}
-
-AccessibilityNotificationHandler::~AccessibilityNotificationHandler()
-{
- removeAccessibilityNotificationHandler(this);
- disconnectAccessibilityCallbacks();
-}
-
-void AccessibilityNotificationHandler::setNotificationFunctionCallback(JSObjectRef notificationFunctionCallback)
-{
- if (!notificationFunctionCallback) {
- removeAccessibilityNotificationHandler(this);
- disconnectAccessibilityCallbacks();
- return;
- }
-
- if (m_notificationFunctionCallback)
- removeAccessibilityNotificationHandler(this);
-
- m_notificationFunctionCallback = notificationFunctionCallback;
- connectAccessibilityCallbacks();
- addAccessibilityNotificationHandler(this);
-}
-
-#endif // HAVE(ACCESSIBILITY)
diff --git a/Tools/DumpRenderTree/atk/AccessibilityNotificationHandlerAtk.h b/Tools/DumpRenderTree/atk/AccessibilityNotificationHandlerAtk.h
deleted file mode 100644
index 9018e7290..000000000
--- a/Tools/DumpRenderTree/atk/AccessibilityNotificationHandlerAtk.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2013 Samsung Electronics Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef AccessibilityNotificationHandlerAtk_h
-#define AccessibilityNotificationHandlerAtk_h
-
-#if HAVE(ACCESSIBILITY)
-
-#include <JavaScriptCore/JSObjectRef.h>
-#include <atk/atk.h>
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefCounted.h>
-
-class AccessibilityNotificationHandler : public RefCounted<AccessibilityNotificationHandler> {
-public:
- static PassRefPtr<AccessibilityNotificationHandler> create()
- {
- return adoptRef(new AccessibilityNotificationHandler());
- }
- AccessibilityNotificationHandler(void);
- ~AccessibilityNotificationHandler();
-
- void setPlatformElement(AtkObject* platformElement) { m_platformElement = platformElement; }
- AtkObject* platformElement(void) const { return m_platformElement; }
- void setNotificationFunctionCallback(JSObjectRef);
- JSObjectRef notificationFunctionCallback(void) const { return m_notificationFunctionCallback; }
-
-private:
- AtkObject* m_platformElement;
- JSObjectRef m_notificationFunctionCallback;
-};
-
-#endif // HAVE(ACCESSIBILITY)
-
-#endif // AccessibilityNotificationHandlerAtk_h
diff --git a/Tools/DumpRenderTree/atk/AccessibilityUIElementAtk.cpp b/Tools/DumpRenderTree/atk/AccessibilityUIElementAtk.cpp
deleted file mode 100644
index 41317bdd1..000000000
--- a/Tools/DumpRenderTree/atk/AccessibilityUIElementAtk.cpp
+++ /dev/null
@@ -1,1604 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
- * Copyright (C) 2009 Jan Michael Alonzo
- * Copyright (C) 2013 Samsung Electronics. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "AccessibilityUIElement.h"
-
-#if HAVE(ACCESSIBILITY)
-
-#include "AccessibilityNotificationHandlerAtk.h"
-#include <JavaScriptCore/JSStringRef.h>
-#include <JavaScriptCore/OpaqueJSString.h>
-#include <atk/atk.h>
-#include <wtf/Assertions.h>
-#include <wtf/gobject/GRefPtr.h>
-#include <wtf/gobject/GUniquePtr.h>
-#include <wtf/text/CString.h>
-#include <wtf/text/StringBuilder.h>
-#include <wtf/text/WTFString.h>
-#include <wtf/unicode/CharacterNames.h>
-
-namespace {
-
-enum AtkAttributeType {
- ObjectAttributeType,
- TextAttributeType
-};
-
-enum AttributeDomain {
- CoreDomain = 0,
- AtkDomain
-};
-
-enum AttributesIndex {
- // Attribute names.
- InvalidNameIndex = 0,
- PlaceholderNameIndex,
- SortNameIndex,
-
- // Attribute values.
- SortAscendingValueIndex,
- SortDescendingValueIndex,
- SortUnknownValueIndex,
-
- NumberOfAttributes
-};
-
-// Attribute names & Values (keep on sync with enum AttributesIndex).
-const String attributesMap[][2] = {
- // Attribute names.
- { "AXInvalid", "invalid" },
- { "AXPlaceholderValue", "placeholder-text" } ,
- { "AXSortDirection", "sort" },
-
- // Attribute values.
- { "AXAscendingSortDirection", "ascending" },
- { "AXDescendingSortDirection", "descending" },
- { "AXUnknownSortDirection", "unknown" }
-};
-
-#if ATK_CHECK_VERSION(2, 11, 3)
-const char* landmarkStringBanner = "AXLandmarkBanner";
-const char* landmarkStringComplementary = "AXLandmarkComplementary";
-const char* landmarkStringContentinfo = "AXLandmarkContentInfo";
-const char* landmarkStringMain = "AXLandmarkMain";
-const char* landmarkStringNavigation = "AXLandmarkNavigation";
-const char* landmarkStringSearch = "AXLandmarkSearch";
-#endif
-
-String jsStringToWTFString(JSStringRef attribute)
-{
- size_t bufferSize = JSStringGetMaximumUTF8CStringSize(attribute);
- GUniquePtr<gchar> buffer(static_cast<gchar*>(g_malloc(bufferSize)));
- JSStringGetUTF8CString(attribute, buffer.get(), bufferSize);
-
- return String::fromUTF8(buffer.get());
-}
-
-String coreAttributeToAtkAttribute(JSStringRef attribute)
-{
- String attributeString = jsStringToWTFString(attribute);
- for (int i = 0; i < NumberOfAttributes; ++i) {
- if (attributesMap[i][CoreDomain] == attributeString)
- return attributesMap[i][AtkDomain];
- }
-
- return attributeString;
-}
-
-String atkAttributeValueToCoreAttributeValue(AtkAttributeType type, const String& id, const String& value)
-{
- if (type == ObjectAttributeType) {
- // We need to translate ATK values exposed for 'aria-sort' (e.g. 'ascending')
- // into those expected by the layout tests (e.g. 'AXAscendingSortDirection').
- if (id == attributesMap[SortNameIndex][AtkDomain] && !value.isEmpty()) {
- if (value == attributesMap[SortAscendingValueIndex][AtkDomain])
- return attributesMap[SortAscendingValueIndex][CoreDomain];
- if (value == attributesMap[SortDescendingValueIndex][AtkDomain])
- return attributesMap[SortDescendingValueIndex][CoreDomain];
-
- return attributesMap[SortUnknownValueIndex][CoreDomain];
- }
- } else if (type == TextAttributeType) {
- // In case of 'aria-invalid' when the attribute empty or has "false" for ATK
- // it should not be mapped at all, but layout tests will expect 'false'.
- if (id == attributesMap[InvalidNameIndex][AtkDomain] && value.isEmpty())
- return "false";
- }
-
- return value;
-}
-
-AtkAttributeSet* getAttributeSet(AtkObject* accessible, AtkAttributeType type)
-{
- if (type == ObjectAttributeType)
- return atk_object_get_attributes(accessible);
-
- if (type == TextAttributeType) {
- if (!ATK_IS_TEXT(accessible))
- return nullptr;
-
- return atk_text_get_default_attributes(ATK_TEXT(accessible));
- }
-
- ASSERT_NOT_REACHED();
- return nullptr;
-}
-
-String getAttributeSetValueForId(AtkObject* accessible, AtkAttributeType type, String id)
-{
- AtkAttributeSet* attributeSet = getAttributeSet(accessible, type);
- if (!attributeSet)
- return String();
-
- String attributeValue;
- for (AtkAttributeSet* attributes = attributeSet; attributes; attributes = attributes->next) {
- AtkAttribute* atkAttribute = static_cast<AtkAttribute*>(attributes->data);
- if (id == atkAttribute->name) {
- attributeValue = String::fromUTF8(atkAttribute->value);
- break;
- }
- }
- atk_attribute_set_free(attributeSet);
-
- return atkAttributeValueToCoreAttributeValue(type, id, attributeValue);
-}
-
-String getAtkAttributeSetAsString(AtkObject* accessible, AtkAttributeType type)
-{
- AtkAttributeSet* attributeSet = getAttributeSet(accessible, type);
- if (!attributeSet)
- return String();
-
- StringBuilder builder;
- for (AtkAttributeSet* attributes = attributeSet; attributes; attributes = attributes->next) {
- AtkAttribute* attribute = static_cast<AtkAttribute*>(attributes->data);
- GUniquePtr<gchar> attributeData(g_strconcat(attribute->name, ":", attribute->value, NULL));
- builder.append(attributeData.get());
- if (attributes->next)
- builder.append(", ");
- }
- atk_attribute_set_free(attributeSet);
-
- return builder.toString();
-}
-
-const char* roleToString(AtkObject* object)
-{
- AtkRole role = atk_object_get_role(object);
-
-#if ATK_CHECK_VERSION(2, 11, 3)
- if (role == ATK_ROLE_LANDMARK) {
- String xmlRolesValue = getAttributeSetValueForId(object, ObjectAttributeType, "xml-roles");
- if (equalIgnoringCase(xmlRolesValue, "banner"))
- return landmarkStringBanner;
- if (equalIgnoringCase(xmlRolesValue, "complementary"))
- return landmarkStringComplementary;
- if (equalIgnoringCase(xmlRolesValue, "contentinfo"))
- return landmarkStringContentinfo;
- if (equalIgnoringCase(xmlRolesValue, "main"))
- return landmarkStringMain;
- if (equalIgnoringCase(xmlRolesValue, "navigation"))
- return landmarkStringNavigation;
- if (equalIgnoringCase(xmlRolesValue, "search"))
- return landmarkStringSearch;
- }
-#endif
-
- switch (role) {
- case ATK_ROLE_ALERT:
- return "AXAlert";
- case ATK_ROLE_DIALOG:
- return "AXDialog";
- case ATK_ROLE_CANVAS:
- return "AXCanvas";
- case ATK_ROLE_CHECK_BOX:
- return "AXCheckBox";
- case ATK_ROLE_COLOR_CHOOSER:
- return "AXColorWell";
- case ATK_ROLE_COLUMN_HEADER:
- return "AXColumnHeader";
- case ATK_ROLE_COMBO_BOX:
- return "AXComboBox";
- case ATK_ROLE_COMMENT:
- return "AXComment";
- case ATK_ROLE_DOCUMENT_FRAME:
- return "AXDocument";
- case ATK_ROLE_DOCUMENT_WEB:
- return "AXWebArea";
- case ATK_ROLE_EMBEDDED:
- return "AXEmbedded";
- case ATK_ROLE_ENTRY:
- return "AXTextField";
- case ATK_ROLE_FOOTER:
- return "AXFooter";
- case ATK_ROLE_FORM:
- return "AXForm";
- case ATK_ROLE_GROUPING:
- return "AXGroup";
- case ATK_ROLE_HEADING:
- return "AXHeading";
- case ATK_ROLE_IMAGE:
- return "AXImage";
- case ATK_ROLE_IMAGE_MAP:
- return "AXImageMap";
- case ATK_ROLE_LABEL:
- return "AXLabel";
- case ATK_ROLE_LINK:
- return "AXLink";
- case ATK_ROLE_LIST:
- return "AXList";
- case ATK_ROLE_LIST_BOX:
- return "AXListBox";
- case ATK_ROLE_LIST_ITEM:
- return "AXListItem";
- case ATK_ROLE_MENU:
- return "AXMenu";
- case ATK_ROLE_MENU_BAR:
- return "AXMenuBar";
- case ATK_ROLE_MENU_ITEM:
- return "AXMenuItem";
- case ATK_ROLE_PAGE_TAB:
- return "AXTab";
- case ATK_ROLE_PAGE_TAB_LIST:
- return "AXTabGroup";
- case ATK_ROLE_PANEL:
- return "AXGroup";
- case ATK_ROLE_PARAGRAPH:
- return "AXParagraph";
- case ATK_ROLE_PASSWORD_TEXT:
- return "AXPasswordField";
- case ATK_ROLE_PROGRESS_BAR:
- return "AXProgressIndicator";
- case ATK_ROLE_PUSH_BUTTON:
- return "AXButton";
- case ATK_ROLE_RADIO_BUTTON:
- return "AXRadioButton";
- case ATK_ROLE_RADIO_MENU_ITEM:
- return "AXRadioMenuItem";
- case ATK_ROLE_ROW_HEADER:
- return "AXRowHeader";
- case ATK_ROLE_CHECK_MENU_ITEM:
- return "AXCheckMenuItem";
- case ATK_ROLE_RULER:
- return "AXRuler";
- case ATK_ROLE_SCROLL_BAR:
- return "AXScrollBar";
- case ATK_ROLE_SCROLL_PANE:
- return "AXScrollArea";
- case ATK_ROLE_SECTION:
- return "AXSection";
- case ATK_ROLE_SEPARATOR:
- return "AXSeparator";
- case ATK_ROLE_SLIDER:
- return "AXSlider";
- case ATK_ROLE_SPIN_BUTTON:
- return "AXSpinButton";
- case ATK_ROLE_STATUSBAR:
- return "AXStatusBar";
- case ATK_ROLE_TABLE:
- return "AXTable";
- case ATK_ROLE_TABLE_CELL:
- return "AXCell";
- case ATK_ROLE_TABLE_COLUMN_HEADER:
- return "AXColumnHeader";
- case ATK_ROLE_TABLE_ROW:
- return "AXRow";
- case ATK_ROLE_TABLE_ROW_HEADER:
- return "AXRowHeader";
- case ATK_ROLE_TOGGLE_BUTTON:
- return "AXToggleButton";
- case ATK_ROLE_TOOL_BAR:
- return "AXToolbar";
- case ATK_ROLE_TOOL_TIP:
- return "AXUserInterfaceTooltip";
- case ATK_ROLE_TREE:
- return "AXTree";
- case ATK_ROLE_TREE_TABLE:
- return "AXTreeGrid";
- case ATK_ROLE_TREE_ITEM:
- return "AXTreeItem";
- case ATK_ROLE_WINDOW:
- return "AXWindow";
- case ATK_ROLE_UNKNOWN:
- return "AXUnknown";
-#if ATK_CHECK_VERSION(2, 11, 3)
- case ATK_ROLE_ARTICLE:
- return "AXArticle";
- case ATK_ROLE_DEFINITION:
- return "AXDefinition";
- case ATK_ROLE_LOG:
- return "AXLog";
- case ATK_ROLE_MARQUEE:
- return "AXMarquee";
- case ATK_ROLE_MATH:
- return "AXMath";
- case ATK_ROLE_TIMER:
- return "AXTimer";
-#endif
-#if ATK_CHECK_VERSION(2, 11, 4)
- case ATK_ROLE_DESCRIPTION_LIST:
- return "AXDescriptionList";
- case ATK_ROLE_DESCRIPTION_TERM:
- return "AXDescriptionTerm";
- case ATK_ROLE_DESCRIPTION_VALUE:
- return "AXDescriptionValue";
-#endif
- default:
- // We want to distinguish ATK_ROLE_UNKNOWN from a known AtkRole which
- // our DRT isn't properly handling.
- return "FIXME not identified";
- }
-}
-
-inline gchar* replaceCharactersForResults(gchar* str)
-{
- String uString = String::fromUTF8(str);
-
- // The object replacement character is passed along to ATs so we need to be
- // able to test for their presence and do so without causing test failures.
- uString.replace(objectReplacementCharacter, "<obj>");
-
- // The presence of newline characters in accessible text of a single object
- // is appropriate, but it makes test results (especially the accessible tree)
- // harder to read.
- uString.replace("\n", "<\\n>");
-
- return g_strdup(uString.utf8().data());
-}
-
-bool checkElementState(PlatformUIElement element, AtkStateType stateType)
-{
- if (!ATK_IS_OBJECT(element))
- return false;
-
- GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(element)));
- return atk_state_set_contains_state(stateSet.get(), stateType);
-}
-
-String attributesOfElement(AccessibilityUIElement* element)
-{
- StringBuilder builder;
-
- builder.append(String::format("%s\n", element->role()->string().utf8().data()));
-
- // For the parent we print its role and its name, if available.
- builder.append("AXParent: ");
- AccessibilityUIElement parent = element->parentElement();
- if (AtkObject* atkParent = parent.platformUIElement()) {
- builder.append(roleToString(atkParent));
- const char* parentName = atk_object_get_name(atkParent);
- if (parentName && g_utf8_strlen(parentName, -1))
- builder.append(String::format(": %s", parentName));
- } else
- builder.append("(null)");
- builder.append("\n");
-
- builder.append(String::format("AXChildren: %d\n", element->childrenCount()));
- builder.append(String::format("AXPosition: { %f, %f }\n", element->x(), element->y()));
- builder.append(String::format("AXSize: { %f, %f }\n", element->width(), element->height()));
-
- String title = element->title()->string();
- if (!title.isEmpty())
- builder.append(String::format("%s\n", title.utf8().data()));
-
- String description = element->description()->string();
- if (!description.isEmpty())
- builder.append(String::format("%s\n", description.utf8().data()));
-
- String value = element->stringValue()->string();
- if (!value.isEmpty())
- builder.append(String::format("%s\n", value.utf8().data()));
-
- builder.append(String::format("AXFocusable: %d\n", element->isFocusable()));
- builder.append(String::format("AXFocused: %d\n", element->isFocused()));
- builder.append(String::format("AXSelectable: %d\n", element->isSelectable()));
- builder.append(String::format("AXSelected: %d\n", element->isSelected()));
- builder.append(String::format("AXMultiSelectable: %d\n", element->isMultiSelectable()));
- builder.append(String::format("AXEnabled: %d\n", element->isEnabled()));
- builder.append(String::format("AXExpanded: %d\n", element->isExpanded()));
- builder.append(String::format("AXRequired: %d\n", element->isRequired()));
- builder.append(String::format("AXChecked: %d\n", element->isChecked()));
-
- String url = element->url()->string();
- if (!url.isEmpty())
- builder.append(String::format("%s\n", url.utf8().data()));
-
- // We append the ATK specific attributes as a single line at the end.
- builder.append("AXPlatformAttributes: ");
- builder.append(getAtkAttributeSetAsString(element->platformUIElement(), ObjectAttributeType));
-
- return builder.toString();
-}
-
-static JSStringRef createStringWithAttributes(const Vector<AccessibilityUIElement>& elements)
-{
- StringBuilder builder;
-
- for (Vector<AccessibilityUIElement>::const_iterator it = elements.begin(); it != elements.end(); ++it) {
- builder.append(attributesOfElement(const_cast<AccessibilityUIElement*>(it)));
- builder.append("\n------------\n");
- }
-
- return JSStringCreateWithUTF8CString(builder.toString().utf8().data());
-}
-
-static Vector<AccessibilityUIElement> getRowHeaders(AtkTable* accessible)
-{
- Vector<AccessibilityUIElement> rowHeaders;
-
- int rowsCount = atk_table_get_n_rows(accessible);
- for (int row = 0; row < rowsCount; ++row)
- rowHeaders.append(AccessibilityUIElement(atk_table_get_row_header(accessible, row)));
-
- return rowHeaders;
-}
-
-static Vector<AccessibilityUIElement> getColumnHeaders(AtkTable* accessible)
-{
- Vector<AccessibilityUIElement> columnHeaders;
-
- int columnsCount = atk_table_get_n_columns(accessible);
- for (int column = 0; column < columnsCount; ++column)
- columnHeaders.append(AccessibilityUIElement(atk_table_get_column_header(accessible, column)));
-
- return columnHeaders;
-}
-
-static Vector<AccessibilityUIElement> getVisibleCells(AccessibilityUIElement* element)
-{
- Vector<AccessibilityUIElement> visibleCells;
-
- AtkTable* accessible = ATK_TABLE(element->platformUIElement());
- int rowsCount = atk_table_get_n_rows(accessible);
- int columnsCount = atk_table_get_n_columns(accessible);
-
- for (int row = 0; row < rowsCount; ++row) {
- for (int column = 0; column < columnsCount; ++column)
- visibleCells.append(element->cellForColumnAndRow(column, row));
- }
-
- return visibleCells;
-}
-
-} // namespace
-
-JSStringRef indexRangeInTable(PlatformUIElement element, bool isRowRange)
-{
- GUniquePtr<gchar> rangeString(g_strdup("{0, 0}"));
-
- if (!ATK_IS_OBJECT(element))
- return JSStringCreateWithUTF8CString(rangeString.get());
-
- AtkObject* axTable = atk_object_get_parent(ATK_OBJECT(element));
- if (!axTable || !ATK_IS_TABLE(axTable))
- return JSStringCreateWithUTF8CString(rangeString.get());
-
- // Look for the cell in the table.
- gint indexInParent = atk_object_get_index_in_parent(ATK_OBJECT(element));
- if (indexInParent == -1)
- return JSStringCreateWithUTF8CString(rangeString.get());
-
- int row = -1;
- int column = -1;
- row = atk_table_get_row_at_index(ATK_TABLE(axTable), indexInParent);
- column = atk_table_get_column_at_index(ATK_TABLE(axTable), indexInParent);
-
- // Get the actual values, if row and columns are valid values.
- if (row != -1 && column != -1) {
- int base = 0;
- int length = 0;
- if (isRowRange) {
- base = row;
- length = atk_table_get_row_extent_at(ATK_TABLE(axTable), row, column);
- } else {
- base = column;
- length = atk_table_get_column_extent_at(ATK_TABLE(axTable), row, column);
- }
- rangeString.reset(g_strdup_printf("{%d, %d}", base, length));
- }
-
- return JSStringCreateWithUTF8CString(rangeString.get());
-}
-
-void alterCurrentValue(PlatformUIElement element, int factor)
-{
- if (!ATK_IS_VALUE(element))
- return;
-
- GValue currentValue = G_VALUE_INIT;
- atk_value_get_current_value(ATK_VALUE(element), &currentValue);
-
- GValue increment = G_VALUE_INIT;
- atk_value_get_minimum_increment(ATK_VALUE(element), &increment);
-
- GValue newValue = G_VALUE_INIT;
- g_value_init(&newValue, G_TYPE_FLOAT);
-
- g_value_set_float(&newValue, g_value_get_float(&currentValue) + factor * g_value_get_float(&increment));
- atk_value_set_current_value(ATK_VALUE(element), &newValue);
-
- g_value_unset(&newValue);
- g_value_unset(&increment);
- g_value_unset(&currentValue);
-}
-
-AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element)
- : m_element(element)
-{
- if (m_element)
- g_object_ref(m_element);
-}
-
-AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other)
- : m_element(other.m_element)
-{
- if (m_element)
- g_object_ref(m_element);
-}
-
-AccessibilityUIElement::~AccessibilityUIElement()
-{
- if (m_element)
- g_object_unref(m_element);
-}
-
-void AccessibilityUIElement::getLinkedUIElements(Vector<AccessibilityUIElement>& elements)
-{
- // FIXME: implement
-}
-
-void AccessibilityUIElement::getDocumentLinks(Vector<AccessibilityUIElement>&)
-{
- // FIXME: implement
-}
-
-void AccessibilityUIElement::getChildren(Vector<AccessibilityUIElement>& children)
-{
- if (!ATK_IS_OBJECT(m_element))
- return;
-
- int count = childrenCount();
- for (int i = 0; i < count; i++) {
- AtkObject* child = atk_object_ref_accessible_child(ATK_OBJECT(m_element), i);
- children.append(AccessibilityUIElement(child));
- }
-}
-
-void AccessibilityUIElement::getChildrenWithRange(Vector<AccessibilityUIElement>& elementVector, unsigned start, unsigned end)
-{
- if (!ATK_IS_OBJECT(m_element))
- return;
-
- for (unsigned i = start; i < end; i++) {
- AtkObject* child = atk_object_ref_accessible_child(ATK_OBJECT(m_element), i);
- elementVector.append(AccessibilityUIElement(child));
- }
-}
-
-int AccessibilityUIElement::rowCount()
-{
- if (!ATK_IS_TABLE(m_element))
- return 0;
-
- return atk_table_get_n_rows(ATK_TABLE(m_element));
-}
-
-int AccessibilityUIElement::columnCount()
-{
- if (!ATK_IS_TABLE(m_element))
- return 0;
-
- return atk_table_get_n_columns(ATK_TABLE(m_element));
-}
-
-int AccessibilityUIElement::childrenCount()
-{
- if (!ATK_IS_OBJECT(m_element))
- return 0;
-
- return atk_object_get_n_accessible_children(ATK_OBJECT(m_element));
-}
-
-AccessibilityUIElement AccessibilityUIElement::elementAtPoint(int x, int y)
-{
- if (!ATK_IS_COMPONENT(m_element))
- return nullptr;
-
- GRefPtr<AtkObject> objectAtPoint = adoptGRef(atk_component_ref_accessible_at_point(ATK_COMPONENT(m_element), x, y, ATK_XY_WINDOW));
- return AccessibilityUIElement(objectAtPoint ? objectAtPoint.get() : m_element);
-}
-
-AccessibilityUIElement AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
-{
- // FIXME: implement
- return nullptr;
-}
-
-AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index)
-{
- if (!ATK_IS_OBJECT(m_element))
- return nullptr;
-
- Vector<AccessibilityUIElement> children;
- getChildrenWithRange(children, index, index + 1);
-
- if (children.size() == 1)
- return children.at(0);
-
- return nullptr;
-}
-
-unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element)
-{
- // FIXME: implement
- return 0;
-}
-
-JSStringRef AccessibilityUIElement::allAttributes()
-{
- if (!ATK_IS_OBJECT(m_element))
- return JSStringCreateWithCharacters(0, 0);
-
- return JSStringCreateWithUTF8CString(attributesOfElement(this).utf8().data());
-}
-
-JSStringRef AccessibilityUIElement::attributesOfLinkedUIElements()
-{
- // FIXME: implement
- return JSStringCreateWithCharacters(0, 0);
-}
-
-JSStringRef AccessibilityUIElement::attributesOfDocumentLinks()
-{
- // FIXME: implement
- return JSStringCreateWithCharacters(0, 0);
-}
-
-AccessibilityUIElement AccessibilityUIElement::titleUIElement()
-{
- if (!ATK_IS_OBJECT(m_element))
- return nullptr;
-
- AtkRelationSet* set = atk_object_ref_relation_set(ATK_OBJECT(m_element));
- if (!set)
- return nullptr;
-
- AtkObject* target = nullptr;
- int count = atk_relation_set_get_n_relations(set);
- for (int i = 0; i < count; i++) {
- AtkRelation* relation = atk_relation_set_get_relation(set, i);
- if (atk_relation_get_relation_type(relation) == ATK_RELATION_LABELLED_BY) {
- GPtrArray* targetList = atk_relation_get_target(relation);
- if (targetList->len)
- target = static_cast<AtkObject*>(g_ptr_array_index(targetList, 0));
- }
- }
-
- g_object_unref(set);
- return target ? AccessibilityUIElement(target) : nullptr;
-}
-
-AccessibilityUIElement AccessibilityUIElement::parentElement()
-{
- if (!ATK_IS_OBJECT(m_element))
- return nullptr;
-
- AtkObject* parent = atk_object_get_parent(ATK_OBJECT(m_element));
- return parent ? AccessibilityUIElement(parent) : nullptr;
-}
-
-JSStringRef AccessibilityUIElement::attributesOfChildren()
-{
- if (!ATK_IS_OBJECT(m_element))
- return JSStringCreateWithCharacters(0, 0);
-
- Vector<AccessibilityUIElement> children;
- getChildren(children);
-
- return createStringWithAttributes(children);
-}
-
-JSStringRef AccessibilityUIElement::parameterizedAttributeNames()
-{
- // FIXME: implement
- return JSStringCreateWithCharacters(0, 0);
-}
-
-JSStringRef AccessibilityUIElement::role()
-{
- if (!ATK_IS_OBJECT(m_element))
- return JSStringCreateWithCharacters(0, 0);
-
- if (!atk_object_get_role(ATK_OBJECT(m_element)))
- return JSStringCreateWithCharacters(0, 0);
-
- GUniquePtr<char> roleStringWithPrefix(g_strdup_printf("AXRole: %s", roleToString(ATK_OBJECT(m_element))));
- return JSStringCreateWithUTF8CString(roleStringWithPrefix.get());
-}
-
-JSStringRef AccessibilityUIElement::subrole()
-{
- return nullptr;
-}
-
-JSStringRef AccessibilityUIElement::roleDescription()
-{
- return nullptr;
-}
-
-JSStringRef AccessibilityUIElement::title()
-{
- if (!ATK_IS_OBJECT(m_element))
- return JSStringCreateWithCharacters(0, 0);
-
- const gchar* name = atk_object_get_name(ATK_OBJECT(m_element));
- GUniquePtr<gchar> axTitle(g_strdup_printf("AXTitle: %s", name ? name : ""));
-
- return JSStringCreateWithUTF8CString(axTitle.get());
-}
-
-JSStringRef AccessibilityUIElement::description()
-{
- if (!ATK_IS_OBJECT(m_element))
- return JSStringCreateWithCharacters(0, 0);
-
- const gchar* description = atk_object_get_description(ATK_OBJECT(m_element));
- if (!description)
- return JSStringCreateWithCharacters(0, 0);
-
- GUniquePtr<gchar> axDesc(g_strdup_printf("AXDescription: %s", description));
-
- return JSStringCreateWithUTF8CString(axDesc.get());
-}
-
-JSStringRef AccessibilityUIElement::stringValue()
-{
- if (!ATK_IS_TEXT(m_element))
- return JSStringCreateWithCharacters(0, 0);
-
- GUniquePtr<gchar> text(atk_text_get_text(ATK_TEXT(m_element), 0, -1));
- GUniquePtr<gchar> textWithReplacedCharacters(replaceCharactersForResults(text.get()));
- GUniquePtr<gchar> axValue(g_strdup_printf("AXValue: %s", textWithReplacedCharacters.get()));
-
- return JSStringCreateWithUTF8CString(axValue.get());
-}
-
-JSStringRef AccessibilityUIElement::language()
-{
- if (!ATK_IS_OBJECT(m_element))
- return JSStringCreateWithCharacters(0, 0);
-
- const gchar* locale = atk_object_get_object_locale(ATK_OBJECT(m_element));
- if (!locale)
- return JSStringCreateWithCharacters(0, 0);
-
- GUniquePtr<char> axValue(g_strdup_printf("AXLanguage: %s", locale));
- return JSStringCreateWithUTF8CString(axValue.get());
-}
-
-JSStringRef AccessibilityUIElement::helpText() const
-{
- if (!ATK_IS_OBJECT(m_element))
- return JSStringCreateWithCharacters(0, 0);
-
- AtkRelationSet* relationSet = atk_object_ref_relation_set(ATK_OBJECT(m_element));
- if (!relationSet)
- return nullptr;
-
- AtkRelation* relation = atk_relation_set_get_relation_by_type(relationSet, ATK_RELATION_DESCRIBED_BY);
- if (!relation)
- return nullptr;
-
- GPtrArray* targetList = atk_relation_get_target(relation);
- if (!targetList || !targetList->len)
- return nullptr;
-
- StringBuilder builder;
- builder.append("AXHelp: ");
-
- for (int targetCount = 0; targetCount < targetList->len; targetCount++) {
- if (AtkObject* target = static_cast<AtkObject*>(g_ptr_array_index(targetList, targetCount))) {
- GUniquePtr<gchar> text(atk_text_get_text(ATK_TEXT(target), 0, -1));
- if (!builder.isEmpty())
- builder.append(" ");
- builder.append(text.get());
- }
- }
-
- g_object_unref(relationSet);
-
- return JSStringCreateWithUTF8CString(builder.toString().utf8().data());
-
-}
-
-double AccessibilityUIElement::x()
-{
- if (!ATK_IS_COMPONENT(m_element))
- return 0;
-
- int x, y;
- atk_component_get_position(ATK_COMPONENT(m_element), &x, &y, ATK_XY_SCREEN);
-
- return x;
-}
-
-double AccessibilityUIElement::y()
-{
- if (!ATK_IS_COMPONENT(m_element))
- return 0;
-
- int x, y;
- atk_component_get_position(ATK_COMPONENT(m_element), &x, &y, ATK_XY_SCREEN);
-
- return y;
-}
-
-double AccessibilityUIElement::width()
-{
- if (!ATK_IS_COMPONENT(m_element))
- return 0;
-
- int width, height;
- atk_component_get_size(ATK_COMPONENT(m_element), &width, &height);
-
- return width;
-}
-
-double AccessibilityUIElement::height()
-{
- if (!ATK_IS_COMPONENT(m_element))
- return 0;
-
- int width, height;
- atk_component_get_size(ATK_COMPONENT(m_element), &width, &height);
-
- return height;
-}
-
-double AccessibilityUIElement::clickPointX()
-{
- if (!ATK_IS_COMPONENT(m_element))
- return 0;
-
- int x, y;
- atk_component_get_position(ATK_COMPONENT(m_element), &x, &y, ATK_XY_WINDOW);
-
- int width, height;
- atk_component_get_size(ATK_COMPONENT(m_element), &width, &height);
-
- return x + width / 2.0;
-}
-
-double AccessibilityUIElement::clickPointY()
-{
- if (!ATK_IS_COMPONENT(m_element))
- return 0;
-
- int x, y;
- atk_component_get_position(ATK_COMPONENT(m_element), &x, &y, ATK_XY_WINDOW);
-
- int width, height;
- atk_component_get_size(ATK_COMPONENT(m_element), &width, &height);
-
- return y + height / 2.0;
-}
-
-JSStringRef AccessibilityUIElement::orientation() const
-{
- if (!ATK_IS_OBJECT(m_element))
- return JSStringCreateWithCharacters(0, 0);
-
- const char* axOrientation = nullptr;
- if (checkElementState(m_element, ATK_STATE_HORIZONTAL))
- axOrientation = "AXOrientation: AXHorizontalOrientation";
- else if (checkElementState(m_element, ATK_STATE_VERTICAL))
- axOrientation = "AXOrientation: AXVerticalOrientation";
-
- if (!axOrientation)
- return JSStringCreateWithCharacters(0, 0);
-
- return JSStringCreateWithUTF8CString(axOrientation);
-}
-
-double AccessibilityUIElement::intValue() const
-{
- if (!ATK_IS_OBJECT(m_element))
- return 0;
-
- if (ATK_IS_VALUE(m_element)) {
- GValue value = G_VALUE_INIT;
- atk_value_get_current_value(ATK_VALUE(m_element), &value);
- if (!G_VALUE_HOLDS_FLOAT(&value))
- return 0;
- return g_value_get_float(&value);
- }
-
- // Consider headings as an special case when returning the "int value" of
- // an AccessibilityUIElement, so we can reuse some tests to check the level
- // both for HTML headings and objects with the aria-level attribute.
- if (atk_object_get_role(ATK_OBJECT(m_element)) == ATK_ROLE_HEADING) {
- String headingLevel = getAttributeSetValueForId(ATK_OBJECT(m_element), ObjectAttributeType, "level");
- bool ok;
- double headingLevelValue = headingLevel.toDouble(&ok);
- if (ok)
- return headingLevelValue;
- }
-
- return 0;
-}
-
-double AccessibilityUIElement::minValue()
-{
- if (!ATK_IS_VALUE(m_element))
- return 0;
-
- GValue value = G_VALUE_INIT;
- atk_value_get_minimum_value(ATK_VALUE(m_element), &value);
- if (!G_VALUE_HOLDS_FLOAT(&value))
- return 0;
- return g_value_get_float(&value);
-}
-
-double AccessibilityUIElement::maxValue()
-{
- if (!ATK_IS_VALUE(m_element))
- return 0;
-
- GValue value = G_VALUE_INIT;
- atk_value_get_maximum_value(ATK_VALUE(m_element), &value);
- if (!G_VALUE_HOLDS_FLOAT(&value))
- return 0;
- return g_value_get_float(&value);
-}
-
-JSStringRef AccessibilityUIElement::valueDescription()
-{
- // FIXME: implement after it has been implemented in ATK.
- // See: https://bugzilla.gnome.org/show_bug.cgi?id=684576
- return JSStringCreateWithCharacters(0, 0);
-}
-
-bool AccessibilityUIElement::isEnabled()
-{
- return checkElementState(m_element, ATK_STATE_ENABLED);
-}
-
-int AccessibilityUIElement::insertionPointLineNumber()
-{
- // FIXME: implement
- return 0;
-}
-
-bool AccessibilityUIElement::isPressActionSupported()
-{
- if (!ATK_IS_ACTION(m_element))
- return false;
-
- const gchar* actionName = atk_action_get_name(ATK_ACTION(m_element), 0);
- return equalIgnoringCase(actionName, String("press")) || equalIgnoringCase(actionName, String("jump"));
-}
-
-bool AccessibilityUIElement::isIncrementActionSupported()
-{
- // FIXME: implement
- return false;
-}
-
-bool AccessibilityUIElement::isDecrementActionSupported()
-{
- // FIXME: implement
- return false;
-}
-
-bool AccessibilityUIElement::isRequired() const
-{
- return checkElementState(m_element, ATK_STATE_REQUIRED);
-}
-
-bool AccessibilityUIElement::isFocused() const
-{
- if (!ATK_IS_OBJECT(m_element))
- return false;
-
- GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
- gboolean isFocused = atk_state_set_contains_state(stateSet.get(), ATK_STATE_FOCUSED);
-
- return isFocused;
-}
-
-bool AccessibilityUIElement::isSelected() const
-{
- return checkElementState(m_element, ATK_STATE_SELECTED);
-}
-
-int AccessibilityUIElement::hierarchicalLevel() const
-{
- // FIXME: implement
- return 0;
-}
-
-bool AccessibilityUIElement::ariaIsGrabbed() const
-{
- return false;
-}
-
-JSStringRef AccessibilityUIElement::ariaDropEffects() const
-{
- return nullptr;
-}
-
-bool AccessibilityUIElement::isExpanded() const
-{
- if (!ATK_IS_OBJECT(m_element))
- return false;
-
- GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
- gboolean isExpanded = atk_state_set_contains_state(stateSet.get(), ATK_STATE_EXPANDED);
-
- return isExpanded;
-}
-
-bool AccessibilityUIElement::isChecked() const
-{
- if (!ATK_IS_OBJECT(m_element))
- return false;
-
- GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
- gboolean isChecked = atk_state_set_contains_state(stateSet.get(), ATK_STATE_CHECKED);
-
- return isChecked;
-}
-
-bool AccessibilityUIElement::isIndeterminate() const
-{
- if (!ATK_IS_OBJECT(m_element))
- return false;
-
- GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
- return atk_state_set_contains_state(stateSet.get(), ATK_STATE_INDETERMINATE);
-}
-
-JSStringRef AccessibilityUIElement::attributesOfColumnHeaders()
-{
- if (!ATK_IS_TABLE(m_element))
- return JSStringCreateWithCharacters(0, 0);
-
- Vector<AccessibilityUIElement> columnHeaders = getColumnHeaders(ATK_TABLE(m_element));
- return createStringWithAttributes(columnHeaders);
-}
-
-JSStringRef AccessibilityUIElement::attributesOfRowHeaders()
-{
- if (!ATK_IS_TABLE(m_element))
- return JSStringCreateWithCharacters(0, 0);
-
- Vector<AccessibilityUIElement> rowHeaders = getRowHeaders(ATK_TABLE(m_element));
- return createStringWithAttributes(rowHeaders);
-}
-
-JSStringRef AccessibilityUIElement::attributesOfColumns()
-{
- // FIXME: implement
- return JSStringCreateWithCharacters(0, 0);
-}
-
-JSStringRef AccessibilityUIElement::attributesOfRows()
-{
- // FIXME: implement
- return JSStringCreateWithCharacters(0, 0);
-}
-
-JSStringRef AccessibilityUIElement::attributesOfVisibleCells()
-{
- if (!ATK_IS_TABLE(m_element))
- return JSStringCreateWithCharacters(0, 0);
-
- Vector<AccessibilityUIElement> visibleCells = getVisibleCells(this);
- return createStringWithAttributes(visibleCells);
-}
-
-JSStringRef AccessibilityUIElement::attributesOfHeader()
-{
- // FIXME: implement
- return JSStringCreateWithCharacters(0, 0);
-}
-
-int AccessibilityUIElement::indexInTable()
-{
- // FIXME: implement
- return 0;
-}
-
-JSStringRef AccessibilityUIElement::rowIndexRange()
-{
- // Range in table for rows.
- return indexRangeInTable(m_element, true);
-}
-
-JSStringRef AccessibilityUIElement::columnIndexRange()
-{
- // Range in table for columns.
- return indexRangeInTable(m_element, false);
-}
-
-int AccessibilityUIElement::lineForIndex(int index)
-{
- if (!ATK_IS_TEXT(m_element))
- return -1;
-
- if (index < 0 || index > atk_text_get_character_count(ATK_TEXT(m_element)))
- return -1;
-
- GUniquePtr<gchar> text(atk_text_get_text(ATK_TEXT(m_element), 0, index));
- int lineNo = 0;
- for (gchar* offset = text.get(); *offset; ++offset) {
- if (*offset == '\n')
- ++lineNo;
- }
-
- return lineNo;
-}
-
-JSStringRef AccessibilityUIElement::boundsForRange(unsigned location, unsigned length)
-{
- // FIXME: implement
- return JSStringCreateWithCharacters(0, 0);
-}
-
-JSStringRef AccessibilityUIElement::stringForRange(unsigned location, unsigned length)
-{
- if (!ATK_IS_TEXT(m_element))
- return JSStringCreateWithCharacters(0, 0);
-
- String string = atk_text_get_text(ATK_TEXT(m_element), location, location + length);
- return JSStringCreateWithUTF8CString(string.utf8().data());
-}
-
-JSStringRef AccessibilityUIElement::attributedStringForRange(unsigned, unsigned)
-{
- // FIXME: implement
- return JSStringCreateWithCharacters(0, 0);
-}
-
-bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned location, unsigned length)
-{
- // FIXME: implement
- return false;
-}
-
-unsigned AccessibilityUIElement::uiElementCountForSearchPredicate(JSContextRef context, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly)
-{
- // FIXME: implement
- return 0;
-}
-
-AccessibilityUIElement AccessibilityUIElement::uiElementForSearchPredicate(JSContextRef context, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly)
-{
- // FIXME: implement
- return nullptr;
-}
-
-AccessibilityUIElement AccessibilityUIElement::cellForColumnAndRow(unsigned column, unsigned row)
-{
- if (!ATK_IS_TABLE(m_element))
- return nullptr;
-
- // Adopt the AtkObject representing the cell because
- // at_table_ref_at() transfers full ownership.
- GRefPtr<AtkObject> foundCell = adoptGRef(atk_table_ref_at(ATK_TABLE(m_element), row, column));
- return foundCell ? AccessibilityUIElement(foundCell.get()) : nullptr;
-}
-
-JSStringRef AccessibilityUIElement::selectedTextRange()
-{
- if (!ATK_IS_TEXT(m_element))
- return JSStringCreateWithCharacters(0, 0);
-
- gint start, end;
- g_free(atk_text_get_selection(ATK_TEXT(m_element), 0, &start, &end));
-
- GUniquePtr<gchar> selection(g_strdup_printf("{%d, %d}", start, end - start));
- return JSStringCreateWithUTF8CString(selection.get());
-}
-
-void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length)
-{
- if (!ATK_IS_TEXT(m_element))
- return;
-
- atk_text_set_selection(ATK_TEXT(m_element), 0, location, location + length);
-}
-
-JSStringRef AccessibilityUIElement::stringAttributeValue(JSStringRef attribute)
-{
- if (!ATK_IS_OBJECT(m_element))
- return JSStringCreateWithCharacters(0, 0);
-
- String atkAttributeName = coreAttributeToAtkAttribute(attribute);
-
- // Try object attributes first.
- String attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element), ObjectAttributeType, atkAttributeName);
-
- // Try text attributes if the requested one was not found and we have an AtkText object.
- if (attributeValue.isEmpty() && ATK_IS_TEXT(m_element))
- attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element), TextAttributeType, atkAttributeName);
-
- // Additional check to make sure that the exposure of the state ATK_STATE_INVALID_ENTRY
- // is consistent with the exposure of aria-invalid as a text attribute, if present.
- if (atkAttributeName == attributesMap[InvalidNameIndex][AtkDomain]) {
- bool isInvalidState = checkElementState(m_element, ATK_STATE_INVALID_ENTRY);
- if (attributeValue.isEmpty())
- return JSStringCreateWithUTF8CString(isInvalidState ? "true" : "false");
-
- // If the text attribute was there, check that it's consistent with
- // what the state says or force the test to fail otherwise.
- bool isAriaInvalid = attributeValue != "false";
- if (isInvalidState != isAriaInvalid)
- return JSStringCreateWithCharacters(0, 0);
- }
-
- return JSStringCreateWithUTF8CString(attributeValue.utf8().data());
-}
-
-double AccessibilityUIElement::numberAttributeValue(JSStringRef attribute)
-{
- // FIXME: implement
- return 0;
-}
-
-bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute)
-{
- // FIXME: implement
- return false;
-}
-
-bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute)
-{
- if (!ATK_IS_OBJECT(m_element))
- return false;
-
- String attributeString = jsStringToWTFString(attribute);
- if (attributeString == "AXValue")
- return checkElementState(m_element, ATK_STATE_EDITABLE);
-
- return false;
-}
-
-bool AccessibilityUIElement::isAttributeSupported(JSStringRef attribute)
-{
- if (!ATK_IS_OBJECT(m_element))
- return false;
-
- String atkAttributeName = coreAttributeToAtkAttribute(attribute);
- if (atkAttributeName.isEmpty())
- return false;
-
- // For now, an attribute is supported whether it's exposed as a object or a text attribute.
- String attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element), ObjectAttributeType, atkAttributeName);
- if (attributeValue.isEmpty())
- attributeValue = getAttributeSetValueForId(ATK_OBJECT(m_element), TextAttributeType, atkAttributeName);
-
- return !attributeValue.isEmpty();
-}
-
-void AccessibilityUIElement::increment()
-{
- alterCurrentValue(m_element, 1);
-}
-
-void AccessibilityUIElement::decrement()
-{
- alterCurrentValue(m_element, -1);
-}
-
-void AccessibilityUIElement::press()
-{
- if (!ATK_IS_ACTION(m_element))
- return;
-
- // Only one action per object is supported so far.
- atk_action_do_action(ATK_ACTION(m_element), 0);
-}
-
-void AccessibilityUIElement::showMenu()
-{
- // FIXME: implement
-}
-
-AccessibilityUIElement AccessibilityUIElement::disclosedRowAtIndex(unsigned index)
-{
- return nullptr;
-}
-
-AccessibilityUIElement AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
-{
- return nullptr;
-}
-
-AccessibilityUIElement AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index)
-{
- if (!ATK_IS_OBJECT(m_element))
- return nullptr;
-
- AtkRelationSet* relationSet = atk_object_ref_relation_set(ATK_OBJECT(m_element));
- if (!relationSet)
- return nullptr;
-
- AtkRelation* relation = atk_relation_set_get_relation_by_type(relationSet, ATK_RELATION_FLOWS_TO);
- if (!relation)
- return nullptr;
-
- GPtrArray* targetList = atk_relation_get_target(relation);
- if (!targetList || !targetList->len || index >= targetList->len)
- return nullptr;
-
- g_object_unref(relationSet);
-
- AtkObject* target = static_cast<AtkObject*>(g_ptr_array_index(targetList, index));
- return target ? AccessibilityUIElement(target) : nullptr;
-}
-
-AccessibilityUIElement AccessibilityUIElement::selectedRowAtIndex(unsigned index)
-{
- return nullptr;
-}
-
-AccessibilityUIElement AccessibilityUIElement::rowAtIndex(unsigned index)
-{
- return nullptr;
-}
-
-AccessibilityUIElement AccessibilityUIElement::disclosedByRow()
-{
- return nullptr;
-}
-
-JSStringRef AccessibilityUIElement::accessibilityValue() const
-{
- // FIXME: implement
- return JSStringCreateWithCharacters(0, 0);
-}
-
-JSStringRef AccessibilityUIElement::documentEncoding()
-{
- if (!ATK_IS_DOCUMENT(m_element))
- return JSStringCreateWithCharacters(0, 0);
-
- AtkRole role = atk_object_get_role(ATK_OBJECT(m_element));
- if (role != ATK_ROLE_DOCUMENT_FRAME)
- return JSStringCreateWithCharacters(0, 0);
-
- return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element), "Encoding"));
-}
-
-JSStringRef AccessibilityUIElement::documentURI()
-{
- if (!ATK_IS_DOCUMENT(m_element))
- return JSStringCreateWithCharacters(0, 0);
-
- AtkRole role = atk_object_get_role(ATK_OBJECT(m_element));
- if (role != ATK_ROLE_DOCUMENT_FRAME)
- return JSStringCreateWithCharacters(0, 0);
-
- return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element), "URI"));
-}
-
-JSStringRef AccessibilityUIElement::url()
-{
- if (!ATK_IS_HYPERLINK_IMPL(m_element))
- return JSStringCreateWithCharacters(0, 0);
-
- AtkHyperlink* hyperlink = atk_hyperlink_impl_get_hyperlink(ATK_HYPERLINK_IMPL(m_element));
- GUniquePtr<char> hyperlinkURI(atk_hyperlink_get_uri(hyperlink, 0));
-
- // Build the result string, stripping the absolute URL paths if present.
- char* localURI = g_strstr_len(hyperlinkURI.get(), -1, "LayoutTests");
- String axURL = String::format("AXURL: %s", localURI ? localURI : hyperlinkURI.get());
- return JSStringCreateWithUTF8CString(axURL.utf8().data());
-}
-
-bool AccessibilityUIElement::addNotificationListener(JSObjectRef functionCallback)
-{
- if (!functionCallback)
- return false;
-
- // Only one notification listener per element.
- if (m_notificationHandler)
- return false;
-
- m_notificationHandler = AccessibilityNotificationHandler::create();
- m_notificationHandler->setPlatformElement(platformUIElement());
- m_notificationHandler->setNotificationFunctionCallback(functionCallback);
-
- return true;
-}
-
-void AccessibilityUIElement::removeNotificationListener()
-{
- // Programmers should not be trying to remove a listener that's already removed.
- ASSERT(m_notificationHandler);
-
- m_notificationHandler = nullptr;
-}
-
-bool AccessibilityUIElement::isFocusable() const
-{
- if (!ATK_IS_OBJECT(m_element))
- return false;
-
- GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
- gboolean isFocusable = atk_state_set_contains_state(stateSet.get(), ATK_STATE_FOCUSABLE);
-
- return isFocusable;
-}
-
-bool AccessibilityUIElement::isSelectable() const
-{
- return checkElementState(m_element, ATK_STATE_SELECTABLE);
-}
-
-bool AccessibilityUIElement::isMultiSelectable() const
-{
- return checkElementState(m_element, ATK_STATE_MULTISELECTABLE);
-}
-
-bool AccessibilityUIElement::isSelectedOptionActive() const
-{
- return checkElementState(m_element, ATK_STATE_ACTIVE);
-}
-
-bool AccessibilityUIElement::isVisible() const
-{
- // FIXME: implement
- return false;
-}
-
-bool AccessibilityUIElement::isOffScreen() const
-{
- // FIXME: implement
- return false;
-}
-
-bool AccessibilityUIElement::isCollapsed() const
-{
- // FIXME: implement
- return false;
-}
-
-bool AccessibilityUIElement::isIgnored() const
-{
- // FIXME: implement
- return false;
-}
-
-bool AccessibilityUIElement::hasPopup() const
-{
- if (!ATK_IS_OBJECT(m_element))
- return false;
-
- String hasPopupValue = getAttributeSetValueForId(ATK_OBJECT(m_element), ObjectAttributeType, "haspopup");
- return equalIgnoringCase(hasPopupValue, "true");
-}
-
-void AccessibilityUIElement::takeFocus()
-{
- // FIXME: implement
-}
-
-void AccessibilityUIElement::takeSelection()
-{
- // FIXME: implement
-}
-
-void AccessibilityUIElement::addSelection()
-{
- // FIXME: implement
-}
-
-void AccessibilityUIElement::removeSelection()
-{
- // FIXME: implement
-}
-
-void AccessibilityUIElement::scrollToMakeVisible()
-{
- // FIXME: implement
-}
-
-void AccessibilityUIElement::scrollToMakeVisibleWithSubFocus(int x, int y, int width, int height)
-{
- // FIXME: implement
-}
-
-void AccessibilityUIElement::scrollToGlobalPoint(int x, int y)
-{
- // FIXME: implement
-}
-
-JSStringRef AccessibilityUIElement::classList() const
-{
- // FIXME: implement
- return nullptr;
-}
-
-JSStringRef stringAtOffset(PlatformUIElement element, AtkTextBoundary boundary, int offset)
-{
- if (!ATK_IS_TEXT(element))
- return JSStringCreateWithCharacters(0, 0);
-
- gint startOffset, endOffset;
- StringBuilder builder;
-
-#if ATK_CHECK_VERSION(2, 10, 0)
- AtkTextGranularity granularity;
- switch (boundary) {
- case ATK_TEXT_BOUNDARY_CHAR:
- granularity = ATK_TEXT_GRANULARITY_CHAR;
- break;
- case ATK_TEXT_BOUNDARY_WORD_START:
- granularity = ATK_TEXT_GRANULARITY_WORD;
- break;
- case ATK_TEXT_BOUNDARY_LINE_START:
- granularity = ATK_TEXT_GRANULARITY_LINE;
- break;
- case ATK_TEXT_BOUNDARY_SENTENCE_START:
- granularity = ATK_TEXT_GRANULARITY_SENTENCE;
- break;
- default:
- return JSStringCreateWithCharacters(0, 0);
- }
-
- builder.append(atk_text_get_string_at_offset(ATK_TEXT(element), offset, granularity, &startOffset, &endOffset));
-#else
- builder.append(atk_text_get_text_at_offset(ATK_TEXT(element), offset, boundary, &startOffset, &endOffset));
-#endif
- builder.append(String::format(", %i, %i", startOffset, endOffset));
- return JSStringCreateWithUTF8CString(builder.toString().utf8().data());
-}
-
-JSStringRef AccessibilityUIElement::characterAtOffset(int offset)
-{
- return stringAtOffset(m_element, ATK_TEXT_BOUNDARY_CHAR, offset);
-}
-
-JSStringRef AccessibilityUIElement::wordAtOffset(int offset)
-{
- return stringAtOffset(m_element, ATK_TEXT_BOUNDARY_WORD_START, offset);
-}
-
-JSStringRef AccessibilityUIElement::lineAtOffset(int offset)
-{
- return stringAtOffset(m_element, ATK_TEXT_BOUNDARY_LINE_START, offset);
-}
-
-JSStringRef AccessibilityUIElement::sentenceAtOffset(int offset)
-{
- return stringAtOffset(m_element, ATK_TEXT_BOUNDARY_SENTENCE_START, offset);
-}
-
-#endif
diff --git a/Tools/DumpRenderTree/cairo/PixelDumpSupportCairo.cpp b/Tools/DumpRenderTree/cairo/PixelDumpSupportCairo.cpp
index fe6046c68..9c8931075 100644
--- a/Tools/DumpRenderTree/cairo/PixelDumpSupportCairo.cpp
+++ b/Tools/DumpRenderTree/cairo/PixelDumpSupportCairo.cpp
@@ -12,7 +12,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
diff --git a/Tools/DumpRenderTree/cairo/PixelDumpSupportCairo.h b/Tools/DumpRenderTree/cairo/PixelDumpSupportCairo.h
index 071e874d0..a2fac882b 100644
--- a/Tools/DumpRenderTree/cairo/PixelDumpSupportCairo.h
+++ b/Tools/DumpRenderTree/cairo/PixelDumpSupportCairo.h
@@ -11,7 +11,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
diff --git a/Tools/DumpRenderTree/config.h b/Tools/DumpRenderTree/config.h
index ddb1d5195..9e0fe4fd4 100644
--- a/Tools/DumpRenderTree/config.h
+++ b/Tools/DumpRenderTree/config.h
@@ -20,16 +20,11 @@
#define Config_H
-#if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H
-#if defined(BUILDING_WITH_CMAKE)
+#if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H && defined(BUILDING_WITH_CMAKE)
#include "cmakeconfig.h"
-#else
-#include "autotoolsconfig.h"
-#endif
#endif
-#include <wtf/Platform.h>
-#include <wtf/ExportMacros.h>
+#include <WebCore/PlatformExportMacros.h>
#include <runtime/JSExportMacros.h>
#ifdef __cplusplus
@@ -38,39 +33,25 @@
#include <wtf/FastMalloc.h>
#endif
-#if PLATFORM(MAC)
-#define WTF_USE_CF 1
-
-// FIXME: These can be removed after sufficient time has passed since the removal of BUILDING_ON / TARGETING macros.
-
-#define ERROR_PLEASE_COMPARE_WITH_MAC_OS_X_VERSION_MIN_REQUIRED 0 / 0
-#define ERROR_PLEASE_COMPARE_WITH_MAC_OS_X_VERSION_MAX_ALLOWED 0 / 0
-
-#define BUILDING_ON_LEOPARD ERROR_PLEASE_COMPARE_WITH_MAC_OS_X_VERSION_MIN_REQUIRED
-#define BUILDING_ON_SNOW_LEOPARD ERROR_PLEASE_COMPARE_WITH_MAC_OS_X_VERSION_MIN_REQUIRED
-#define BUILDING_ON_LION ERROR_PLEASE_COMPARE_WITH_MAC_OS_X_VERSION_MIN_REQUIRED
-
-#define TARGETING_LEOPARD ERROR_PLEASE_COMPARE_WITH_MAC_OS_X_VERSION_MAX_ALLOWED
-#define TARGETING_SNOW_LEOPARD ERROR_PLEASE_COMPARE_WITH_MAC_OS_X_VERSION_MAX_ALLOWED
-#define TARGETING_LION ERROR_PLEASE_COMPARE_WITH_MAC_OS_X_VERSION_MAX_ALLOWED
-
-#endif // PLATFORM(MAC)
+#if PLATFORM(COCOA)
+#define USE_CF 1
+#endif
#if PLATFORM(WIN)
-#define WTF_USE_CF 1
+#define USE_CF 1
#if PLATFORM(WIN_CAIRO)
-#define WTF_USE_CAIRO 1
-#define WTF_USE_CURL 1
+#define USE_CAIRO 1
+#define USE_CURL 1
#else
-#define WTF_USE_CG 1
-#define WTF_USE_CFNETWORK 1
+#define USE_CG 1
+#define USE_CFNETWORK 1
#endif
#undef _WIN32_WINNT
-#define _WIN32_WINNT 0x0502
+#define _WIN32_WINNT 0x601
#undef WINVER
-#define WINVER 0x0502
+#define WINVER 0x0601
#undef _WINSOCKAPI_
#define _WINSOCKAPI_ // Prevent inclusion of winsock.h in windows.h
diff --git a/Tools/DumpRenderTree/gtk/AccessibilityControllerGtk.cpp b/Tools/DumpRenderTree/gtk/AccessibilityControllerGtk.cpp
deleted file mode 100644
index 7ee1d9460..000000000
--- a/Tools/DumpRenderTree/gtk/AccessibilityControllerGtk.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2008, 2009, 2010 Apple Inc. All Rights Reserved.
- * Copyright (C) 2009 Jan Michael Alonzo
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if HAVE(ACCESSIBILITY)
-
-#include "AccessibilityController.h"
-
-#include "AccessibilityCallbacks.h"
-#include "AccessibilityUIElement.h"
-#include "DumpRenderTree.h"
-#include "WebCoreSupport/DumpRenderTreeSupportGtk.h"
-
-#include <atk/atk.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-#include <wtf/gobject/GUniquePtr.h>
-
-AccessibilityUIElement AccessibilityController::focusedElement()
-{
- AtkObject* accessible = DumpRenderTreeSupportGtk::getFocusedAccessibleElement(mainFrame);
- if (!accessible)
- return 0;
-
- return AccessibilityUIElement(accessible);
-}
-
-AccessibilityUIElement AccessibilityController::rootElement()
-{
- AtkObject* accessible = DumpRenderTreeSupportGtk::getRootAccessibleElement(mainFrame);
- if (!accessible)
- return 0;
-
- return AccessibilityUIElement(accessible);
-}
-
-AccessibilityUIElement AccessibilityController::accessibleElementById(JSStringRef id)
-{
- AtkObject* root = DumpRenderTreeSupportGtk::getRootAccessibleElement(mainFrame);
- if (!root)
- return 0;
-
- size_t bufferSize = JSStringGetMaximumUTF8CStringSize(id);
- GUniquePtr<gchar> idBuffer(static_cast<gchar*>(g_malloc(bufferSize)));
- JSStringGetUTF8CString(id, idBuffer.get(), bufferSize);
-
- AtkObject* result = childElementById(root, idBuffer.get());
- if (ATK_IS_OBJECT(result))
- return AccessibilityUIElement(result);
-
- return 0;
-
-}
-
-#endif // HAVE(ACCESSIBILITY)
diff --git a/Tools/DumpRenderTree/gtk/DumpRenderTree.cpp b/Tools/DumpRenderTree/gtk/DumpRenderTree.cpp
deleted file mode 100644
index 73d710a04..000000000
--- a/Tools/DumpRenderTree/gtk/DumpRenderTree.cpp
+++ /dev/null
@@ -1,1557 +0,0 @@
-/*
- * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
- * Copyright (C) 2008 Alp Toker <alp@nuanti.com>
- * Copyright (C) 2009 Jan Alonzo <jmalonzo@gmail.com>
- * Copyright (C) 2010, 2011 Igalia S.L.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "DumpRenderTree.h"
-
-#include "AccessibilityController.h"
-#include "EditingCallbacks.h"
-#include "EventSender.h"
-#include "GCController.h"
-#include "PixelDumpSupport.h"
-#include "SelfScrollingWebKitWebView.h"
-#include "TestRunner.h"
-#include "TextInputController.h"
-#include "WebCoreSupport/DumpRenderTreeSupportGtk.h"
-#include "WebCoreTestSupport.h"
-#include "WorkQueue.h"
-#include "WorkQueueItem.h"
-#include <JavaScriptCore/JavaScript.h>
-#include <WebCore/platform/network/soup/GUniquePtrSoup.h>
-#include <cassert>
-#include <cstdlib>
-#include <cstring>
-#include <getopt.h>
-#include <gtk/gtk.h>
-#include <locale.h>
-#include <webkit/webkit.h>
-#include <wtf/Assertions.h>
-#include <wtf/gobject/GlibUtilities.h>
-#include <wtf/text/WTFString.h>
-
-#if PLATFORM(X11)
-#include <fontconfig/fontconfig.h>
-#endif
-
-
-using namespace std;
-
-extern "C" {
-// This API is not yet public.
-extern gchar* webkit_web_history_item_get_target(WebKitWebHistoryItem*);
-extern gboolean webkit_web_history_item_is_target_item(WebKitWebHistoryItem*);
-extern GList* webkit_web_history_item_get_children(WebKitWebHistoryItem*);
-extern void webkit_web_settings_add_extra_plugin_directory(WebKitWebView* view, const gchar* directory);
-extern gchar* webkit_web_frame_get_response_mime_type(WebKitWebFrame* frame);
-}
-
-volatile bool done;
-static bool printSeparators;
-static int dumpPixelsForAllTests = false;
-static bool dumpPixelsForCurrentTest;
-static int dumpTree = 1;
-static int useTimeoutWatchdog = 1;
-
-#if HAVE(ACCESSIBILITY)
-AccessibilityController* axController = 0;
-#endif
-RefPtr<TestRunner> gTestRunner;
-static GCController* gcController = 0;
-static WebKitWebView* webView;
-static GtkWidget* window;
-static GtkWidget* container;
-static GtkWidget* webInspectorWindow;
-WebKitWebFrame* mainFrame = 0;
-WebKitWebFrame* topLoadingFrame = 0;
-guint waitToDumpWatchdog = 0;
-bool waitForPolicy = false;
-
-// This is a list of opened webviews
-GSList* webViewList = 0;
-
-// current b/f item at the end of the previous test
-static WebKitWebHistoryItem* prevTestBFItem = NULL;
-
-const unsigned historyItemIndent = 8;
-
-static void runTest(const string& inputLine);
-
-static void didRunInsecureContent(WebKitWebFrame*, WebKitSecurityOrigin*, const char* url);
-
-static bool shouldLogFrameLoadDelegates(const string& pathOrURL)
-{
- return pathOrURL.find("loading/") != string::npos;
-}
-
-static bool shouldOpenWebInspector(const string& pathOrURL)
-{
- return pathOrURL.find("inspector/") != string::npos;
-}
-
-static bool shouldDumpAsText(const string& pathOrURL)
-{
- return pathOrURL.find("dumpAsText/") != string::npos;
-}
-
-static bool shouldEnableDeveloperExtras(const string& pathOrURL)
-{
- return true;
-}
-
-void dumpFrameScrollPosition(WebKitWebFrame* frame)
-{
- WebKitDOMDocument* document = webkit_web_frame_get_dom_document(frame);
- if (!document)
- return;
-
- WebKitDOMDOMWindow* domWindow = webkit_dom_document_get_default_view(document);
- if (!domWindow)
- return;
-
- glong x = webkit_dom_dom_window_get_page_x_offset(domWindow);
- glong y = webkit_dom_dom_window_get_page_y_offset(domWindow);
-
- if (abs(x) > 0 || abs(y) > 0) {
- if (webkit_web_frame_get_parent(frame))
- printf("frame '%s' ", webkit_web_frame_get_name(frame));
- printf("scrolled to %ld,%ld\n", x, y);
- }
-
- if (gTestRunner->dumpChildFrameScrollPositions()) {
- GSList* children = DumpRenderTreeSupportGtk::getFrameChildren(frame);
- for (GSList* child = children; child; child = g_slist_next(child))
- dumpFrameScrollPosition(static_cast<WebKitWebFrame*>(child->data));
- g_slist_free(children);
- }
-}
-
-void displayWebView()
-{
- DumpRenderTreeSupportGtk::forceWebViewPaint(webView);
- DumpRenderTreeSupportGtk::setTracksRepaints(mainFrame, true);
- DumpRenderTreeSupportGtk::resetTrackedRepaints(mainFrame);
-}
-
-static void appendString(gchar*& target, const gchar* string)
-{
- gchar* oldString = target;
- target = g_strconcat(target, string, NULL);
- g_free(oldString);
-}
-
-static void initializeGtkFontSettings(const char* testURL)
-{
- GtkSettings* settings = gtk_settings_get_default();
- if (!settings)
- return;
- g_object_set(settings,
- "gtk-xft-dpi", 98304, // This is 96 * 1024 or 96 DPI according to the GTK+ docs.
- "gtk-xft-antialias", 1,
- "gtk-xft-hinting", 0,
- "gtk-font-name", "Liberation Sans 12",
- "gtk-icon-theme-name", "gnome",
- NULL);
- gdk_screen_set_resolution(gdk_screen_get_default(), 96.0);
-
- // One test needs subpixel anti-aliasing turned on, but generally we
- // want all text in other tests to use to grayscale anti-aliasing.
- if (testURL && strstr(testURL, "xsettings_antialias_settings.html"))
- g_object_set(settings, "gtk-xft-rgba", "rgb", NULL);
- else
- g_object_set(settings, "gtk-xft-rgba", "none", NULL);
-}
-
-CString getTopLevelPath()
-{
- if (const gchar* topLevel = g_getenv("WEBKIT_TOP_LEVEL"))
- return topLevel;
-
- g_setenv("WEBKIT_TOP_LEVEL", TOP_LEVEL_DIR, FALSE);
- return TOP_LEVEL_DIR;
-}
-
-CString getOutputDir()
-{
- const char* webkitOutputDir = g_getenv("WEBKIT_OUTPUTDIR");
- if (webkitOutputDir)
- return webkitOutputDir;
-
- CString topLevelPath = getTopLevelPath();
- GUniquePtr<char> outputDir(g_build_filename(topLevelPath.data(), "WebKitBuild", NULL));
- return outputDir.get();
-}
-
-static CString getFontsPath()
-{
- CString webkitOutputDir = getOutputDir();
- GUniquePtr<char> fontsPath(g_build_filename(webkitOutputDir.data(), "Dependencies", "Root", "webkitgtk-test-fonts", NULL));
- if (g_file_test(fontsPath.get(), static_cast<GFileTest>(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
- return fontsPath.get();
-
- // Try alternative fonts path.
- fontsPath.reset(g_build_filename(webkitOutputDir.data(), "webkitgtk-test-fonts", NULL));
- if (g_file_test(fontsPath.get(), static_cast<GFileTest>(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
- return fontsPath.get();
-
- return CString();
-}
-
-static void initializeFonts(const char* testURL = 0)
-{
-#if PLATFORM(X11)
- initializeGtkFontSettings(testURL);
-
- FcInit();
-
- // If a test resulted a font being added or removed via the @font-face rule, then
- // we want to reset the FontConfig configuration to prevent it from affecting other tests.
- static int numFonts = 0;
- FcFontSet* appFontSet = FcConfigGetFonts(0, FcSetApplication);
- if (appFontSet && numFonts && appFontSet->nfont == numFonts)
- return;
-
- // Load our configuration file, which sets up proper aliases for family
- // names like sans, serif and monospace.
- FcConfig* config = FcConfigCreate();
- GUniquePtr<gchar> fontConfigFilename(g_build_filename(FONTS_CONF_DIR, "fonts.conf", nullptr));
- if (!FcConfigParseAndLoad(config, reinterpret_cast<FcChar8*>(fontConfigFilename.get()), true))
- g_error("Couldn't load font configuration file from: %s", fontConfigFilename.get());
-
- CString fontsPath = getFontsPath();
- if (fontsPath.isNull())
- g_error("Could not locate test fonts at $WEBKIT_TOP_LEVEL/WebKitBuild/Dependencies/Root/webkitgtk-test-fonts. "
- "WEBKIT_TOP_LEVEL is your WebKit checkout by default, and can be overridden by setting it as an environment variable.");
-
- GUniquePtr<GDir> fontsDirectory(g_dir_open(fontsPath.data(), 0, nullptr));
- while (const char* directoryEntry = g_dir_read_name(fontsDirectory.get())) {
- if (!g_str_has_suffix(directoryEntry, ".ttf") && !g_str_has_suffix(directoryEntry, ".otf"))
- continue;
- GUniquePtr<gchar> fontPath(g_build_filename(fontsPath.data(), directoryEntry, nullptr));
- if (!FcConfigAppFontAddFile(config, reinterpret_cast<const FcChar8*>(fontPath.get())))
- g_error("Could not load font at %s!", fontPath.get());
-
- }
-
- // Ahem is used by many layout tests.
- GUniquePtr<gchar> ahemFontFilename(g_build_filename(FONTS_CONF_DIR, "AHEM____.TTF", nullptr));
- if (!FcConfigAppFontAddFile(config, reinterpret_cast<FcChar8*>(ahemFontFilename.get())))
- g_error("Could not load font at %s!", ahemFontFilename.get());
-
- for (int i = 1; i <= 9; i++) {
- GUniquePtr<gchar> fontFilename(g_strdup_printf("WebKitWeightWatcher%i00.ttf", i));
- GUniquePtr<gchar> fontPath(g_build_filename(FONTS_CONF_DIR, "..", "..", "fonts", fontFilename.get(), nullptr));
- if (!FcConfigAppFontAddFile(config, reinterpret_cast<FcChar8*>(fontPath.get())))
- g_error("Could not load font at %s!", fontPath.get());
- }
-
- // A font with no valid Fontconfig encoding to test https://bugs.webkit.org/show_bug.cgi?id=47452
- GUniquePtr<gchar> fontWithNoValidEncodingFilename(g_build_filename(FONTS_CONF_DIR, "FontWithNoValidEncoding.fon", nullptr));
- if (!FcConfigAppFontAddFile(config, reinterpret_cast<FcChar8*>(fontWithNoValidEncodingFilename.get())))
- g_error("Could not load font at %s!", fontWithNoValidEncodingFilename.get());
-
- if (!FcConfigSetCurrent(config))
- g_error("Could not set the current font configuration!");
-
- numFonts = FcConfigGetFonts(config, FcSetApplication)->nfont;
-#endif
-}
-
-static gchar* dumpFramesAsText(WebKitWebFrame* frame)
-{
- gchar* result = 0;
-
- // Add header for all but the main frame.
- bool isMainFrame = (webkit_web_view_get_main_frame(webView) == frame);
-
- CString innerText = DumpRenderTreeSupportGtk::getInnerText(frame);
- if (isMainFrame)
- result = g_strdup_printf("%s\n", innerText.data());
- else {
- const gchar* frameName = webkit_web_frame_get_name(frame);
- result = g_strdup_printf("\n--------\nFrame: '%s'\n--------\n%s\n", frameName, innerText.data());
- }
-
- if (gTestRunner->dumpChildFramesAsText()) {
- GSList* children = DumpRenderTreeSupportGtk::getFrameChildren(frame);
- for (GSList* child = children; child; child = g_slist_next(child)) {
- GUniquePtr<gchar> childData(dumpFramesAsText(static_cast<WebKitWebFrame*>(child->data)));
- appendString(result, childData.get());
- }
- g_slist_free(children);
- }
-
- return result;
-}
-
-static gint compareHistoryItems(gpointer* item1, gpointer* item2)
-{
- GUniquePtr<gchar> firstItemTarget(webkit_web_history_item_get_target(WEBKIT_WEB_HISTORY_ITEM(item1)));
- GUniquePtr<gchar> secondItemTarget(webkit_web_history_item_get_target(WEBKIT_WEB_HISTORY_ITEM(item2)));
- return g_ascii_strcasecmp(firstItemTarget.get(), secondItemTarget.get());
-}
-
-static void dumpHistoryItem(WebKitWebHistoryItem* item, int indent, bool current)
-{
- ASSERT(item != NULL);
- int start = 0;
- g_object_ref(item);
- if (current) {
- printf("curr->");
- start = 6;
- }
- for (int i = start; i < indent; i++)
- putchar(' ');
-
- // normalize file URLs.
- const gchar* uri = webkit_web_history_item_get_uri(item);
- gchar* uriScheme = g_uri_parse_scheme(uri);
- if (g_strcmp0(uriScheme, "file") == 0) {
- gchar* pos = g_strstr_len(uri, -1, "/LayoutTests/");
- if (!pos) {
- g_free(uriScheme);
- return;
- }
-
- GString* result = g_string_sized_new(strlen(uri));
- result = g_string_append(result, "(file test):");
- result = g_string_append(result, pos + strlen("/LayoutTests/"));
- printf("%s", result->str);
- g_string_free(result, TRUE);
- } else
- printf("%s", uri);
-
- g_free(uriScheme);
-
- GUniquePtr<gchar> target(webkit_web_history_item_get_target(item));
- if (target.get() && strlen(target.get()) > 0)
- printf(" (in frame \"%s\")", target.get());
- if (webkit_web_history_item_is_target_item(item))
- printf(" **nav target**");
- putchar('\n');
-
- if (GList* kids = webkit_web_history_item_get_children(item)) {
- // must sort to eliminate arbitrary result ordering which defeats reproducible testing
- for (GList* kid = g_list_sort(kids, (GCompareFunc) compareHistoryItems); kid; kid = g_list_next(kid)) {
- WebKitWebHistoryItem* item = WEBKIT_WEB_HISTORY_ITEM(kid->data);
- dumpHistoryItem(item, indent + 4, FALSE);
- g_object_unref(item);
- }
- g_list_free(kids);
- }
- g_object_unref(item);
-}
-
-static void dumpBackForwardListForWebView(WebKitWebView* view)
-{
- printf("\n============== Back Forward List ==============\n");
- WebKitWebBackForwardList* bfList = webkit_web_view_get_back_forward_list(view);
-
- // Print out all items in the list after prevTestBFItem, which was from the previous test
- // Gather items from the end of the list, the print them out from oldest to newest
- GList* itemsToPrint = NULL;
- gint forwardListCount = webkit_web_back_forward_list_get_forward_length(bfList);
- for (int i = forwardListCount; i > 0; i--) {
- WebKitWebHistoryItem* item = webkit_web_back_forward_list_get_nth_item(bfList, i);
- // something is wrong if the item from the last test is in the forward part of the b/f list
- ASSERT(item != prevTestBFItem);
- g_object_ref(item);
- itemsToPrint = g_list_prepend(itemsToPrint, item);
- }
-
- WebKitWebHistoryItem* currentItem = webkit_web_back_forward_list_get_current_item(bfList);
- g_object_ref(currentItem);
- itemsToPrint = g_list_prepend(itemsToPrint, currentItem);
-
- gint backListCount = webkit_web_back_forward_list_get_back_length(bfList);
- for (int i = -1; i >= -(backListCount); i--) {
- WebKitWebHistoryItem* item = webkit_web_back_forward_list_get_nth_item(bfList, i);
- if (item == prevTestBFItem)
- break;
- g_object_ref(item);
- itemsToPrint = g_list_prepend(itemsToPrint, item);
- }
-
- for (GList* itemToPrint = itemsToPrint; itemToPrint; itemToPrint = g_list_next(itemToPrint)) {
- WebKitWebHistoryItem* item = WEBKIT_WEB_HISTORY_ITEM(itemToPrint->data);
- dumpHistoryItem(item, historyItemIndent, item == currentItem);
- g_object_unref(item);
- }
-
- g_list_free(itemsToPrint);
- printf("===============================================\n");
-}
-
-static void dumpBackForwardListForAllWebViews()
-{
- // Dump the back forward list of the main WebView first
- dumpBackForwardListForWebView(webView);
-
- // The view list is prepended. Reverse the list so we get the order right.
- for (GSList* currentView = g_slist_reverse(webViewList); currentView; currentView = g_slist_next(currentView))
- dumpBackForwardListForWebView(WEBKIT_WEB_VIEW(currentView->data));
-}
-
-void setWaitToDumpWatchdog(guint timer)
-{
- waitToDumpWatchdog = timer;
-}
-
-bool shouldSetWaitToDumpWatchdog()
-{
- return !waitToDumpWatchdog && useTimeoutWatchdog;
-}
-
-CString soupURIToStringPreservingPassword(SoupURI* soupURI)
-{
- if (!soupURI->password) {
- GUniquePtr<char> uriString(soup_uri_to_string(soupURI, FALSE));
- return uriString.get();
- }
-
- // soup_uri_to_string does not insert the password into the string, so we need to create the
- // URI string and then reinsert any credentials that were present in the SoupURI. All tests that
- // use URL-embedded credentials use HTTP, so it's safe here.
- GUniquePtr<char> password(soupURI->password);
- GUniquePtr<char> user(soupURI->user);
- soupURI->password = 0;
- soupURI->user = 0;
-
- GUniquePtr<char> uriString(soup_uri_to_string(soupURI, FALSE));
- String absoluteURIWithoutCredentialString = String::fromUTF8(uriString.get());
- String protocolAndCredential = String::format("http://%s:%s@", user ? user.get() : "", password.get());
- return absoluteURIWithoutCredentialString.replace("http://", protocolAndCredential).utf8();
-}
-
-static void invalidateAnyPreviousWaitToDumpWatchdog()
-{
- if (waitToDumpWatchdog) {
- g_source_remove(waitToDumpWatchdog);
- waitToDumpWatchdog = 0;
- }
-
- waitForPolicy = false;
-}
-
-static void resetDefaultsToConsistentValues()
-{
- WebKitWebSettings* settings = webkit_web_view_get_settings(webView);
- GUniquePtr<gchar> localStoragePath(g_build_filename(g_get_user_data_dir(), "DumpRenderTreeGtk", "databases", nullptr));
- g_object_set(G_OBJECT(settings),
- "enable-accelerated-compositing", FALSE,
- "enable-private-browsing", FALSE,
- "enable-developer-extras", FALSE,
- "enable-spell-checking", TRUE,
- "enable-html5-database", TRUE,
- "enable-html5-local-storage", TRUE,
- "html5-local-storage-database-path", localStoragePath.get(),
- "enable-xss-auditor", FALSE,
- "enable-spatial-navigation", FALSE,
- "javascript-can-access-clipboard", TRUE,
- "javascript-can-open-windows-automatically", TRUE,
- "enable-offline-web-application-cache", TRUE,
- "enable-universal-access-from-file-uris", TRUE,
- "enable-file-access-from-file-uris", TRUE,
- "enable-scripts", TRUE,
- "enable-dom-paste", TRUE,
- "default-font-family", "Times",
- "monospace-font-family", "Courier",
- "serif-font-family", "Times",
- "sans-serif-font-family", "Helvetica",
- "cursive-font-family", "cursive",
- "fantasy-font-family", "fantasy",
- "default-font-size", 12,
- "default-monospace-font-size", 10,
- "minimum-font-size", 0,
- "enable-caret-browsing", FALSE,
- "enable-page-cache", FALSE,
- "auto-resize-window", TRUE,
- "auto-load-images", TRUE,
- "enable-java-applet", FALSE,
- "enable-plugins", TRUE,
- "enable-hyperlink-auditing", FALSE,
- "editing-behavior", WEBKIT_EDITING_BEHAVIOR_UNIX,
- "enable-fullscreen", TRUE,
- "enable-mediasource", TRUE,
- NULL);
- webkit_web_view_set_settings(webView, settings);
- webkit_set_cache_model(WEBKIT_CACHE_MODEL_DOCUMENT_BROWSER);
-
- DumpRenderTreeSupportGtk::clearMainFrameName(mainFrame);
- DumpRenderTreeSupportGtk::scalePageBy(webView, 1, 0, 0);
-
- WebKitWebInspector* inspector = webkit_web_view_get_inspector(webView);
- g_object_set(G_OBJECT(inspector), "javascript-profiling-enabled", FALSE, NULL);
-
- webkit_web_view_set_zoom_level(webView, 1.0);
-
- DumpRenderTreeSupportGtk::resetOriginAccessWhiteLists();
-
- WebKitWebBackForwardList* list = webkit_web_view_get_back_forward_list(webView);
- webkit_web_back_forward_list_clear(list);
-
- SoupSession* session = webkit_get_default_session();
- SoupCookieJar* jar = reinterpret_cast<SoupCookieJar*>(soup_session_get_feature(session, SOUP_TYPE_COOKIE_JAR));
-
- // We only create the jar when the soup backend needs to do
- // HTTP. Should we initialize it earlier, perhaps?
- if (jar)
- g_object_set(G_OBJECT(jar), SOUP_COOKIE_JAR_ACCEPT_POLICY, SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY, NULL);
-
- setlocale(LC_ALL, "");
-
- DumpRenderTreeSupportGtk::setLinksIncludedInFocusChain(true);
- webkit_icon_database_set_path(webkit_get_icon_database(), 0);
- DumpRenderTreeSupportGtk::setDefersLoading(webView, false);
- DumpRenderTreeSupportGtk::setSerializeHTTPLoads(false);
-
-#if HAVE(ACCESSIBILITY)
- if (axController)
- axController->resetToConsistentState();
-#endif
-
- DumpRenderTreeSupportGtk::clearOpener(mainFrame);
- DumpRenderTreeSupportGtk::setTracksRepaints(mainFrame, false);
-
- DumpRenderTreeSupportGtk::resetGeolocationClientMock(webView);
-
- DumpRenderTreeSupportGtk::setCSSGridLayoutEnabled(webView, false);
- DumpRenderTreeSupportGtk::setCSSRegionsEnabled(webView, true);
- DumpRenderTreeSupportGtk::setExperimentalContentSecurityPolicyFeaturesEnabled(true);
- DumpRenderTreeSupportGtk::setSeamlessIFramesEnabled(true);
- DumpRenderTreeSupportGtk::setShadowDOMEnabled(true);
-
- if (gTestRunner) {
- gTestRunner->setAuthenticationPassword("");
- gTestRunner->setAuthenticationUsername("");
- gTestRunner->setHandlesAuthenticationChallenges(false);
- }
-
- gtk_widget_set_direction(GTK_WIDGET(webView), GTK_TEXT_DIR_NONE);
-}
-
-static bool useLongRunningServerMode(int argc, char *argv[])
-{
- // This assumes you've already called getopt_long
- return (argc == optind+1 && !strcmp(argv[optind], "-"));
-}
-
-static void runTestingServerLoop()
-{
- // When DumpRenderTree runs in server mode, we just wait around for file names
- // to be passed to us and read each in turn, passing the results back to the client
- char filenameBuffer[2048];
- while (fgets(filenameBuffer, sizeof(filenameBuffer), stdin)) {
- char* newLineCharacter = strchr(filenameBuffer, '\n');
- if (newLineCharacter)
- *newLineCharacter = '\0';
-
- if (!strlen(filenameBuffer))
- continue;
-
- runTest(filenameBuffer);
- }
-}
-
-static void initializeGlobalsFromCommandLineOptions(int argc, char *argv[])
-{
- struct option options[] = {
- {"notree", no_argument, &dumpTree, false},
- {"pixel-tests", no_argument, &dumpPixelsForAllTests, true},
- {"tree", no_argument, &dumpTree, true},
- {"no-timeout", no_argument, &useTimeoutWatchdog, false},
- {NULL, 0, NULL, 0}
- };
-
- int option;
- while ((option = getopt_long(argc, (char * const *)argv, "", options, NULL)) != -1) {
- switch (option) {
- case '?': // unknown or ambiguous option
- case ':': // missing argument
- exit(1);
- break;
- }
- }
-}
-
-
-void dump()
-{
- invalidateAnyPreviousWaitToDumpWatchdog();
-
- // Grab widget focus before dumping the contents of a widget, in
- // case it was lost in the course of the test.
- gtk_widget_grab_focus(GTK_WIDGET(webView));
-
- if (dumpTree) {
- char* result = 0;
- gchar* responseMimeType = webkit_web_frame_get_response_mime_type(mainFrame);
-
- if (g_str_equal(responseMimeType, "text/plain")) {
- gTestRunner->setDumpAsText(true);
- gTestRunner->setGeneratePixelResults(false);
- }
- g_free(responseMimeType);
-
- if (gTestRunner->dumpAsText())
- result = dumpFramesAsText(mainFrame);
- else {
- // Widget resizing is done asynchronously in GTK+. We pump the main
- // loop here, to flush any pending resize requests. This prevents
- // timing issues which affect the size of elements in the output.
- // We only enable this workaround for tests that print the render tree
- // because this seems to break some dumpAsText tests: see bug 39988
- // After fixing that test, we should apply this approach to all dumps.
- while (gtk_events_pending())
- gtk_main_iteration();
-
- result = g_strdup(DumpRenderTreeSupportGtk::dumpRenderTree(mainFrame).data());
- }
-
- if (!result) {
- const char* errorMessage;
- if (gTestRunner->dumpAsText())
- errorMessage = "[documentElement innerText]";
- else if (gTestRunner->dumpDOMAsWebArchive())
- errorMessage = "[[mainFrame DOMDocument] webArchive]";
- else if (gTestRunner->dumpSourceAsWebArchive())
- errorMessage = "[[mainFrame dataSource] webArchive]";
- else
- errorMessage = "[mainFrame renderTreeAsExternalRepresentation]";
- printf("ERROR: nil result from %s", errorMessage);
- } else {
- printf("%s", result);
- g_free(result);
- if (!gTestRunner->dumpAsText() && !gTestRunner->dumpDOMAsWebArchive() && !gTestRunner->dumpSourceAsWebArchive())
- dumpFrameScrollPosition(mainFrame);
-
- if (gTestRunner->dumpBackForwardList())
- dumpBackForwardListForAllWebViews();
- }
-
- if (printSeparators) {
- puts("#EOF"); // terminate the content block
- fputs("#EOF\n", stderr);
- fflush(stdout);
- fflush(stderr);
- }
- }
-
- if (dumpPixelsForCurrentTest
- && gTestRunner->generatePixelResults()
- && !gTestRunner->dumpDOMAsWebArchive()
- && !gTestRunner->dumpSourceAsWebArchive()) {
- DumpRenderTreeSupportGtk::forceWebViewPaint(webView);
- dumpWebViewAsPixelsAndCompareWithExpected(gTestRunner->expectedPixelHash());
- }
-
- // FIXME: call displayWebView here when we support --paint
-
- done = true;
- gtk_main_quit();
-}
-
-static CString temporaryDatabaseDirectory()
-{
- const char* directoryFromEnvironment = g_getenv("DUMPRENDERTREE_TEMP");
- if (directoryFromEnvironment)
- return directoryFromEnvironment;
- GUniquePtr<char> fallback(g_build_filename(g_get_user_data_dir(), "gtkwebkitdrt", "databases", NULL));
- return fallback.get();
-}
-
-static void setDefaultsToConsistentStateValuesForTesting()
-{
- resetDefaultsToConsistentValues();
-
-#if PLATFORM(X11)
- webkit_web_settings_add_extra_plugin_directory(webView, TEST_PLUGIN_DIR);
-#endif
-
- webkit_set_web_database_directory_path(temporaryDatabaseDirectory().data());
-
-#if defined(GTK_API_VERSION_2)
- gtk_rc_parse_string("style \"nix_scrollbar_spacing\" "
- "{ "
- " GtkScrolledWindow::scrollbar-spacing = 0 "
- "} "
- "class \"GtkWidget\" style \"nix_scrollbar_spacing\"");
-
-#else
- GtkCssProvider* cssProvider = gtk_css_provider_new();
- gtk_css_provider_load_from_data(cssProvider,
- "@binding-set NoKeyboardNavigation { "
- " unbind \"<shift>F10\"; "
- "} "
- " * { "
- " -GtkScrolledWindow-scrollbar-spacing: 0;"
- " gtk-key-bindings: NoKeyboardNavigation; "
- "} ",
- -1, 0);
- gtk_style_context_add_provider_for_screen(gdk_display_get_default_screen(gdk_display_get_default()),
- GTK_STYLE_PROVIDER(cssProvider),
- GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
- g_object_unref(cssProvider);
-#endif
-}
-
-static void sendPixelResultsEOF()
-{
- puts("#EOF");
-
- fflush(stdout);
- fflush(stderr);
-}
-
-static void runTest(const string& inputLine)
-{
- ASSERT(!inputLine.empty());
-
- TestCommand command = parseInputLine(inputLine);
- string& testURL = command.pathOrURL;
- dumpPixelsForCurrentTest = command.shouldDumpPixels || dumpPixelsForAllTests;
-
- // Convert the path into a full file URL if it does not look
- // like an HTTP/S URL (doesn't start with http:// or https://).
- if (testURL.find("http://") && testURL.find("https://")) {
- GFile* testFile = g_file_new_for_path(testURL.c_str());
- gchar* testURLCString = g_file_get_uri(testFile);
- testURL = testURLCString;
- g_free(testURLCString);
- g_object_unref(testFile);
- }
-
- resetDefaultsToConsistentValues();
-
- gTestRunner = TestRunner::create(testURL, command.expectedPixelHash);
- topLoadingFrame = 0;
- done = false;
-
- gTestRunner->setIconDatabaseEnabled(false);
-
- if (shouldLogFrameLoadDelegates(testURL))
- gTestRunner->setDumpFrameLoadCallbacks(true);
-
- if (shouldEnableDeveloperExtras(testURL)) {
- gTestRunner->setDeveloperExtrasEnabled(true);
- if (shouldOpenWebInspector(testURL))
- gTestRunner->showWebInspector();
- if (shouldDumpAsText(testURL)) {
- gTestRunner->setDumpAsText(true);
- gTestRunner->setGeneratePixelResults(false);
- }
- }
-
- WorkQueue::shared()->clear();
- WorkQueue::shared()->setFrozen(false);
-
- bool isSVGW3CTest = (testURL.find("svg/W3C-SVG-1.1") != string::npos);
- GtkAllocation size;
- size.x = size.y = 0;
- size.width = isSVGW3CTest ? TestRunner::w3cSVGViewWidth : TestRunner::viewWidth;
- size.height = isSVGW3CTest ? TestRunner::w3cSVGViewHeight : TestRunner::viewHeight;
- gtk_window_resize(GTK_WINDOW(window), size.width, size.height);
- gtk_widget_size_allocate(container, &size);
-
- if (prevTestBFItem)
- g_object_unref(prevTestBFItem);
- WebKitWebBackForwardList* bfList = webkit_web_view_get_back_forward_list(webView);
- prevTestBFItem = webkit_web_back_forward_list_get_current_item(bfList);
- if (prevTestBFItem)
- g_object_ref(prevTestBFItem);
-
- initializeFonts(testURL.c_str());
-
- // Focus the web view before loading the test to avoid focusing problems
- gtk_widget_grab_focus(GTK_WIDGET(webView));
- webkit_web_view_open(webView, testURL.c_str());
-
- gtk_main();
-
- // If developer extras enabled Web Inspector may have been open by the test.
- if (shouldEnableDeveloperExtras(testURL)) {
- gTestRunner->closeWebInspector();
- gTestRunner->setDeveloperExtrasEnabled(false);
- }
-
- // Also check if we still have opened webViews and free them.
- if (gTestRunner->closeRemainingWindowsWhenComplete() || webViewList) {
- while (webViewList) {
- g_object_unref(WEBKIT_WEB_VIEW(webViewList->data));
- webViewList = g_slist_next(webViewList);
- }
- g_slist_free(webViewList);
- webViewList = 0;
- }
-
- WebCoreTestSupport::resetInternalsObject(webkit_web_frame_get_global_context(mainFrame));
- DumpRenderTreeSupportGtk::clearMemoryCache();
- DumpRenderTreeSupportGtk::clearApplicationCache();
-
- // A blank load seems to be necessary to reset state after certain tests.
- webkit_web_view_open(webView, "about:blank");
-
- gTestRunner.clear();
-
- // terminate the (possibly empty) pixels block after all the state reset
- sendPixelResultsEOF();
-}
-
-void webViewLoadStarted(WebKitWebView* view, WebKitWebFrame* frame, void*)
-{
- // Make sure we only set this once per test. If it gets cleared, and then set again, we might
- // end up doing two dumps for one test.
- if (!topLoadingFrame && !done)
- topLoadingFrame = frame;
-}
-
-static gboolean processWork(void* data)
-{
- // if we finish all the commands, we're ready to dump state
- if (WorkQueue::shared()->processWork() && !gTestRunner->waitToDump())
- dump();
-
- return FALSE;
-}
-
-static char* getFrameNameSuitableForTestResult(WebKitWebView* view, WebKitWebFrame* frame)
-{
- char* frameName = g_strdup(webkit_web_frame_get_name(frame));
-
- if (frame == webkit_web_view_get_main_frame(view)) {
- // This is a bit strange. Shouldn't web_frame_get_name return NULL?
- if (frameName && (frameName[0] != '\0')) {
- char* tmp = g_strdup_printf("main frame \"%s\"", frameName);
- g_free(frameName);
- frameName = tmp;
- } else {
- g_free(frameName);
- frameName = g_strdup("main frame");
- }
- } else if (!frameName || (frameName[0] == '\0')) {
- g_free(frameName);
- frameName = g_strdup("frame (anonymous)");
- } else {
- char* tmp = g_strdup_printf("frame \"%s\"", frameName);
- g_free(frameName);
- frameName = tmp;
- }
-
- return frameName;
-}
-
-static void webViewLoadFinished(WebKitWebView* view, WebKitWebFrame* frame, void*)
-{
- // The deprecated "load-finished" signal is triggered by postProgressFinishedNotification(),
- // so we can use it here in the DRT to provide the correct dump.
- if (frame != topLoadingFrame)
- return;
- if (gTestRunner->dumpProgressFinishedCallback())
- printf("postProgressFinishedNotification\n");
-}
-
-static gboolean webViewLoadError(WebKitWebView*, WebKitWebFrame*, gchar*, gpointer, gpointer)
-{
- return TRUE; // Return true here to disable the default error page.
-}
-
-static void webViewDocumentLoadFinished(WebKitWebView* view, WebKitWebFrame* frame, void*)
-{
- if (!done && gTestRunner->dumpFrameLoadCallbacks()) {
- char* frameName = getFrameNameSuitableForTestResult(view, frame);
- printf("%s - didFinishDocumentLoadForFrame\n", frameName);
- g_free(frameName);
- } else if (!done) {
- guint pendingFrameUnloadEvents = DumpRenderTreeSupportGtk::getPendingUnloadEventCount(frame);
- if (pendingFrameUnloadEvents) {
- char* frameName = getFrameNameSuitableForTestResult(view, frame);
- printf("%s - has %u onunload handler(s)\n", frameName, pendingFrameUnloadEvents);
- g_free(frameName);
- }
- }
-}
-
-static void webViewOnloadEvent(WebKitWebView* view, WebKitWebFrame* frame, void*)
-{
- if (!done && gTestRunner->dumpFrameLoadCallbacks()) {
- char* frameName = getFrameNameSuitableForTestResult(view, frame);
- printf("%s - didHandleOnloadEventsForFrame\n", frameName);
- g_free(frameName);
- }
-}
-
-static void addControllerToWindow(JSContextRef context, JSObjectRef windowObject, const char* controllerName, JSValueRef controller)
-{
- JSStringRef controllerNameStr = JSStringCreateWithUTF8CString(controllerName);
- JSObjectSetProperty(context, windowObject, controllerNameStr, controller, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, 0);
- JSStringRelease(controllerNameStr);
-}
-
-static void webViewWindowObjectCleared(WebKitWebView* view, WebKitWebFrame* frame, JSGlobalContextRef context, JSObjectRef windowObject, gpointer data)
-{
- JSValueRef exception = 0;
- ASSERT(gTestRunner);
-
- gTestRunner->makeWindowObject(context, windowObject, &exception);
- ASSERT(!exception);
-
- gcController->makeWindowObject(context, windowObject, &exception);
- ASSERT(!exception);
-
-#if HAVE(ACCESSIBILITY)
- axController->makeWindowObject(context, windowObject, &exception);
- ASSERT(!exception);
-#endif
-
- addControllerToWindow(context, windowObject, "eventSender", makeEventSender(context, !webkit_web_frame_get_parent(frame)));
- addControllerToWindow(context, windowObject, "textInputController", makeTextInputController(context));
- WebCoreTestSupport::injectInternalsObject(context);
-}
-
-static gboolean webViewConsoleMessage(WebKitWebView* view, const gchar* message, unsigned int line, const gchar* sourceId, gpointer data)
-{
- gchar* testMessage = 0;
- const gchar* uriScheme;
-
- // Tests expect only the filename part of local URIs
- uriScheme = g_strstr_len(message, -1, "file://");
- if (uriScheme) {
- GString* tempString = g_string_sized_new(strlen(message));
- gchar* filename = g_strrstr(uriScheme, G_DIR_SEPARATOR_S);
-
- if (filename) {
- // If the path is a lone slash, keep it to avoid empty output.
- if (strlen(filename) > 1)
- filename += strlen(G_DIR_SEPARATOR_S);
- tempString = g_string_append_len(tempString, message, (uriScheme - message));
- tempString = g_string_append_len(tempString, filename, strlen(filename));
- testMessage = g_string_free(tempString, FALSE);
- }
- }
-
- fprintf(stdout, "CONSOLE MESSAGE: ");
- if (line)
- fprintf(stdout, "line %d: ", line);
- fprintf(stdout, "%s\n", testMessage ? testMessage : message);
- g_free(testMessage);
-
- return TRUE;
-}
-
-
-static gboolean webViewScriptAlert(WebKitWebView* view, WebKitWebFrame* frame, const gchar* message, gpointer data)
-{
- fprintf(stdout, "ALERT: %s\n", message);
- fflush(stdout);
- return TRUE;
-}
-
-static gboolean webViewScriptPrompt(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message, const gchar* defaultValue, gchar** value, gpointer data)
-{
- fprintf(stdout, "PROMPT: %s, default text: %s\n", message, defaultValue);
- *value = g_strdup(defaultValue);
- return TRUE;
-}
-
-static gboolean webViewScriptConfirm(WebKitWebView* view, WebKitWebFrame* frame, const gchar* message, gboolean* didConfirm, gpointer data)
-{
- fprintf(stdout, "CONFIRM: %s\n", message);
- *didConfirm = TRUE;
- return TRUE;
-}
-
-static void webViewTitleChanged(WebKitWebView* view, WebKitWebFrame* frame, const gchar* title, gpointer data)
-{
- if (gTestRunner->dumpFrameLoadCallbacks() && !done) {
- GUniquePtr<char> frameName(getFrameNameSuitableForTestResult(view, frame));
- printf("%s - didReceiveTitle: %s\n", frameName.get(), title ? title : "");
- }
-
- if (gTestRunner->dumpTitleChanges() && !done)
- printf("TITLE CHANGED: '%s'\n", title ? title : "");
-}
-
-static bool webViewNavigationPolicyDecisionRequested(WebKitWebView* view, WebKitWebFrame* frame,
- WebKitNetworkRequest* request,
- WebKitWebNavigationAction* navAction,
- WebKitWebPolicyDecision* policyDecision)
-{
- // Use the default handler if we're not waiting for policy,
- // i.e., TestRunner::waitForPolicyDelegate
- if (!waitForPolicy)
- return FALSE;
-
- gchar* typeDescription;
- WebKitWebNavigationReason reason;
- g_object_get(G_OBJECT(navAction), "reason", &reason, NULL);
-
- switch(reason) {
- case WEBKIT_WEB_NAVIGATION_REASON_LINK_CLICKED:
- typeDescription = g_strdup("link clicked");
- break;
- case WEBKIT_WEB_NAVIGATION_REASON_FORM_SUBMITTED:
- typeDescription = g_strdup("form submitted");
- break;
- case WEBKIT_WEB_NAVIGATION_REASON_BACK_FORWARD:
- typeDescription = g_strdup("back/forward");
- break;
- case WEBKIT_WEB_NAVIGATION_REASON_RELOAD:
- typeDescription = g_strdup("reload");
- break;
- case WEBKIT_WEB_NAVIGATION_REASON_FORM_RESUBMITTED:
- typeDescription = g_strdup("form resubmitted");
- break;
- case WEBKIT_WEB_NAVIGATION_REASON_OTHER:
- typeDescription = g_strdup("other");
- break;
- default:
- typeDescription = g_strdup("illegal value");
- }
-
- printf("Policy delegate: attempt to load %s with navigation type '%s'\n", webkit_network_request_get_uri(request), typeDescription);
- g_free(typeDescription);
-
- webkit_web_policy_decision_ignore(policyDecision);
- gTestRunner->notifyDone();
-
- return TRUE;
-}
-
-static void webViewStatusBarTextChanged(WebKitWebView* view, const gchar* message, gpointer data)
-{
- // Are we doing anything wrong? One test that does not call
- // dumpStatusCallbacks gets true here
- if (gTestRunner->dumpStatusCallbacks())
- printf("UI DELEGATE STATUS CALLBACK: setStatusText:%s\n", message);
-}
-
-static gboolean webViewClose(WebKitWebView* view)
-{
- ASSERT(view);
-
- webViewList = g_slist_remove(webViewList, view);
- g_object_unref(view);
-
- return TRUE;
-}
-
-static void databaseQuotaExceeded(WebKitWebView* view, WebKitWebFrame* frame, WebKitWebDatabase *database)
-{
- ASSERT(view);
- ASSERT(frame);
- ASSERT(database);
-
- WebKitSecurityOrigin* origin = webkit_web_database_get_security_origin(database);
- if (gTestRunner->dumpDatabaseCallbacks()) {
- printf("UI DELEGATE DATABASE CALLBACK: exceededDatabaseQuotaForSecurityOrigin:{%s, %s, %i} database:%s\n",
- webkit_security_origin_get_protocol(origin),
- webkit_security_origin_get_host(origin),
- webkit_security_origin_get_port(origin),
- webkit_web_database_get_name(database));
- }
- webkit_security_origin_set_web_database_quota(origin, 5 * 1024 * 1024);
-}
-
-static bool
-geolocationPolicyDecisionRequested(WebKitWebView*, WebKitWebFrame*, WebKitGeolocationPolicyDecision* decision)
-{
- if (!gTestRunner->isGeolocationPermissionSet())
- return FALSE;
- if (gTestRunner->geolocationPermission())
- webkit_geolocation_policy_allow(decision);
- else
- webkit_geolocation_policy_deny(decision);
-
- return TRUE;
-}
-
-
-static WebKitWebView* webViewCreate(WebKitWebView*, WebKitWebFrame*);
-
-static gboolean webInspectorShowWindow(WebKitWebInspector*, gpointer data)
-{
- gtk_window_set_default_size(GTK_WINDOW(webInspectorWindow), TestRunner::viewWidth, TestRunner::viewHeight);
- gtk_widget_show_all(webInspectorWindow);
- return TRUE;
-}
-
-static gboolean webInspectorCloseWindow(WebKitWebInspector*, gpointer data)
-{
- gtk_widget_destroy(webInspectorWindow);
- webInspectorWindow = 0;
- return TRUE;
-}
-
-static WebKitWebView* webInspectorInspectWebView(WebKitWebInspector*, gpointer data)
-{
- webInspectorWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-
- GtkWidget* webView = self_scrolling_webkit_web_view_new();
- gtk_container_add(GTK_CONTAINER(webInspectorWindow),
- webView);
-
- return WEBKIT_WEB_VIEW(webView);
-}
-
-static void topLoadingFrameLoadFinished()
-{
- topLoadingFrame = 0;
- WorkQueue::shared()->setFrozen(true); // first complete load freezes the queue for the rest of this test
- if (gTestRunner->waitToDump())
- return;
-
- if (WorkQueue::shared()->count())
- g_idle_add_full(G_PRIORITY_DEFAULT, processWork, 0, 0);
- else
- dump();
-}
-
-static void webFrameLoadStatusNotified(WebKitWebFrame* frame, gpointer user_data)
-{
- WebKitLoadStatus loadStatus = webkit_web_frame_get_load_status(frame);
-
- if (gTestRunner->dumpFrameLoadCallbacks()) {
- GUniquePtr<char> frameName(getFrameNameSuitableForTestResult(webkit_web_frame_get_web_view(frame), frame));
-
- switch (loadStatus) {
- case WEBKIT_LOAD_PROVISIONAL:
- if (!done)
- printf("%s - didStartProvisionalLoadForFrame\n", frameName.get());
- break;
- case WEBKIT_LOAD_COMMITTED:
- if (!done)
- printf("%s - didCommitLoadForFrame\n", frameName.get());
- break;
- case WEBKIT_LOAD_FINISHED:
- if (!done)
- printf("%s - didFinishLoadForFrame\n", frameName.get());
- break;
- case WEBKIT_LOAD_FAILED:
- if (!done)
- printf("%s - didFailLoadWithError\n", frameName.get());
- break;
- default:
- break;
- }
- }
-
- if ((loadStatus == WEBKIT_LOAD_FINISHED || loadStatus == WEBKIT_LOAD_FAILED)
- && frame == topLoadingFrame)
- topLoadingFrameLoadFinished();
-}
-
-static void frameCreatedCallback(WebKitWebView* webView, WebKitWebFrame* webFrame, gpointer user_data)
-{
- g_signal_connect(webFrame, "notify::load-status", G_CALLBACK(webFrameLoadStatusNotified), NULL);
- g_signal_connect(webFrame, "insecure-content-run", G_CALLBACK(didRunInsecureContent), NULL);
-}
-
-static String pathFromSoupURI(SoupURI* uri)
-{
- if (!uri)
- return "(null)";
-
- if (!g_str_equal(uri->scheme, "file"))
- return soupURIToStringPreservingPassword(uri).data();
-
- String pathString = uri->path;
- GUniquePtr<gchar> pathBasename(g_path_get_basename(pathString.utf8().data()));
-
- WebKitWebFrame* mainFrame = webkit_web_view_get_main_frame(webView);
- GUniquePtr<SoupURI> mainFrameUri(soup_uri_new(webkit_web_frame_get_uri(mainFrame)));
-
- String mainFrameUriPathString = mainFrameUri.get()->path;
- String basePath = mainFrameUriPathString.substring(0, mainFrameUriPathString.reverseFind('/') + 1);
-
- if (!basePath.isEmpty() && pathString.startsWith(basePath))
- return pathString.substring(basePath.length());
-
- return pathBasename.get();
-}
-
-static CString convertSoupMessageToURLPath(SoupMessage* soupMessage)
-{
- if (!soupMessage)
- return CString("(null)");
- if (SoupURI* requestURI = soup_message_get_uri(soupMessage))
- return pathFromSoupURI(requestURI).utf8();
- return CString("(null)");
-}
-
-static CString convertNetworkRequestToURLPath(WebKitNetworkRequest* request)
-{
- return convertSoupMessageToURLPath(webkit_network_request_get_message(request));
-}
-
-static CString convertWebResourceToURLPath(WebKitWebResource* webResource)
-{
- GUniquePtr<SoupURI> uri(soup_uri_new(webkit_web_resource_get_uri(webResource)));
- return pathFromSoupURI(uri.get()).utf8();
-}
-
-static CString urlSuitableForTestResult(const char* uriString)
-{
- if (!g_str_has_prefix(uriString, "file://"))
- return CString(uriString);
-
- GUniquePtr<gchar> basename(g_path_get_basename(uriString));
- return CString(basename.get());
-}
-
-static CString descriptionSuitableForTestResult(SoupURI* uri)
-{
- if (!uri)
- return CString("(null)");
-
- GUniquePtr<char> uriString(soup_uri_to_string(uri, false));
- return urlSuitableForTestResult(uriString.get());
-}
-
-static CString descriptionSuitableForTestResult(GError* error, WebKitWebResource* webResource)
-{
- const gchar* errorDomain = g_quark_to_string(error->domain);
- CString resourceURIString(urlSuitableForTestResult(webkit_web_resource_get_uri(webResource)));
-
- if (g_str_equal(errorDomain, "webkit-network-error-quark") || g_str_equal(errorDomain, "soup_http_error_quark"))
- errorDomain = "NSURLErrorDomain";
-
- if (g_str_equal(errorDomain, "WebKitPolicyError"))
- errorDomain = "WebKitErrorDomain";
-
- // TODO: the other ports get the failingURL from the ResourceError
- GUniquePtr<char> errorString(g_strdup_printf("<NSError domain %s, code %d, failing URL \"%s\">",
- errorDomain, error->code, resourceURIString.data()));
- return CString(errorString.get());
-}
-
-static CString descriptionSuitableForTestResult(WebKitNetworkRequest* request)
-{
- SoupMessage* soupMessage = webkit_network_request_get_message(request);
-
- if (!soupMessage)
- return CString("(null)");
-
- SoupURI* mainDocumentURI = soup_message_get_first_party(soupMessage);
- CString mainDocumentURIString(descriptionSuitableForTestResult(mainDocumentURI));
- CString path(convertNetworkRequestToURLPath(request));
- GUniquePtr<char> description(g_strdup_printf("<NSURLRequest URL %s, main document URL %s, http method %s>",
- path.data(), mainDocumentURIString.data(), soupMessage->method));
- return CString(description.get());
-}
-
-static CString descriptionSuitableForTestResult(WebKitNetworkResponse* response)
-{
- if (!response)
- return CString("(null)");
-
- int statusCode = 0;
- CString responseURIString(urlSuitableForTestResult(webkit_network_response_get_uri(response)));
- SoupMessage* soupMessage = webkit_network_response_get_message(response);
- CString path;
-
- if (soupMessage) {
- statusCode = soupMessage->status_code;
- path = convertSoupMessageToURLPath(soupMessage);
- } else
- path = CString("(null)");
-
- GUniquePtr<char> description(g_strdup_printf("<NSURLResponse %s, http status code %d>", path.data(), statusCode));
- return CString(description.get());
-}
-
-static void willSendRequestCallback(WebKitWebView* webView, WebKitWebFrame* webFrame, WebKitWebResource* resource, WebKitNetworkRequest* request, WebKitNetworkResponse* response)
-{
-
-
- if (!done && gTestRunner->willSendRequestReturnsNull()) {
- // As requested by the TestRunner, don't perform the request.
- webkit_network_request_set_uri(request, "about:blank");
- return;
- }
-
- if (!done && gTestRunner->dumpResourceLoadCallbacks())
- printf("%s - willSendRequest %s redirectResponse %s\n",
- convertNetworkRequestToURLPath(request).data(),
- descriptionSuitableForTestResult(request).data(),
- descriptionSuitableForTestResult(response).data());
-
- SoupMessage* soupMessage = webkit_network_request_get_message(request);
- SoupURI* uri = soup_uri_new(webkit_network_request_get_uri(request));
-
- if (SOUP_URI_IS_VALID(uri)) {
- GUniquePtr<char> uriString(soup_uri_to_string(uri, FALSE));
-
- if (SOUP_URI_VALID_FOR_HTTP(uri) && g_strcmp0(uri->host, "127.0.0.1")
- && g_strcmp0(uri->host, "255.255.255.255")
- && g_ascii_strncasecmp(uri->host, "localhost", 9)) {
- printf("Blocked access to external URL %s\n", uriString.get());
- // Cancel load of blocked resource to avoid potential
- // network-related timeouts in tests.
- webkit_network_request_set_uri(request, "about:blank");
- soup_uri_free(uri);
- return;
- }
-
- const string& destination = gTestRunner->redirectionDestinationForURL(uriString.get());
- if (!destination.empty())
- webkit_network_request_set_uri(request, destination.c_str());
- }
-
- if (uri)
- soup_uri_free(uri);
-
- if (soupMessage) {
- const set<string>& clearHeaders = gTestRunner->willSendRequestClearHeaders();
- for (set<string>::const_iterator header = clearHeaders.begin(); header != clearHeaders.end(); ++header)
- soup_message_headers_remove(soupMessage->request_headers, header->c_str());
- }
-}
-
-
-static void didReceiveResponse(WebKitWebView* webView, WebKitWebFrame*, WebKitWebResource* webResource, WebKitNetworkResponse* response)
-{
- if (!done && gTestRunner->dumpResourceLoadCallbacks()) {
- CString responseDescription(descriptionSuitableForTestResult(response));
- CString path(convertWebResourceToURLPath(webResource));
- printf("%s - didReceiveResponse %s\n", path.data(), responseDescription.data());
- }
-
- // TODO: add "has MIME type" whenever dumpResourceResponseMIMETypes() is supported.
- // See https://bugs.webkit.org/show_bug.cgi?id=58222.
-}
-
-static void didFinishLoading(WebKitWebView* webView, WebKitWebFrame* webFrame, WebKitWebResource* webResource)
-{
- if (!done && gTestRunner->dumpResourceLoadCallbacks())
- printf("%s - didFinishLoading\n", convertWebResourceToURLPath(webResource).data());
-}
-
-static void didFailLoadingWithError(WebKitWebView* webView, WebKitWebFrame* webFrame, WebKitWebResource* webResource, GError* webError)
-{
- if (!done && gTestRunner->dumpResourceLoadCallbacks()) {
- CString webErrorString(descriptionSuitableForTestResult(webError, webResource));
- printf("%s - didFailLoadingWithError: %s\n", convertWebResourceToURLPath(webResource).data(),
- webErrorString.data());
- }
-}
-
-static void didRunInsecureContent(WebKitWebFrame*, WebKitSecurityOrigin*, const char* url)
-{
- if (!done && gTestRunner->dumpFrameLoadCallbacks())
- printf("didRunInsecureContent\n");
-}
-
-static gboolean webViewRunFileChooser(WebKitWebView*, WebKitFileChooserRequest*)
-{
- // We return TRUE to not propagate the event further so the
- // default file chooser dialog is not shown.
- return TRUE;
-}
-
-static void frameLoadEventCallback(WebKitWebFrame* frame, DumpRenderTreeSupportGtk::FrameLoadEvent event, const char* url)
-{
- if (done || !gTestRunner->dumpFrameLoadCallbacks())
- return;
-
- GUniquePtr<char> frameName(getFrameNameSuitableForTestResult(webkit_web_frame_get_web_view(frame), frame));
- switch (event) {
- case DumpRenderTreeSupportGtk::WillPerformClientRedirectToURL:
- ASSERT(url);
- printf("%s - willPerformClientRedirectToURL: %s \n", frameName.get(), url);
- break;
- case DumpRenderTreeSupportGtk::DidCancelClientRedirect:
- printf("%s - didCancelClientRedirectForFrame\n", frameName.get());
- break;
- case DumpRenderTreeSupportGtk::DidReceiveServerRedirectForProvisionalLoad:
- printf("%s - didReceiveServerRedirectForProvisionalLoadForFrame\n", frameName.get());
- break;
- case DumpRenderTreeSupportGtk::DidDisplayInsecureContent:
- printf ("didDisplayInsecureContent\n");
- break;
- case DumpRenderTreeSupportGtk::DidDetectXSS:
- printf ("didDetectXSS\n");
- break;
- default:
- ASSERT_NOT_REACHED();
- }
-}
-
-static bool authenticationCallback(CString& username, CString& password, WebKitWebResource* webResource)
-{
- CString description(convertWebResourceToURLPath(webResource));
-
- if (!gTestRunner->handlesAuthenticationChallenges()) {
- printf("%s - didReceiveAuthenticationChallenge - Simulating cancelled authentication sheet\n", description.data());
- return false;
- }
-
- username = gTestRunner->authenticationUsername().c_str();
- password = gTestRunner->authenticationPassword().c_str();
- printf("%s - didReceiveAuthenticationChallenge - Responding with %s:%s\n", description.data(), username.data(), password.data());
- return true;
-}
-
-static WebKitWebView* createWebView()
-{
- // It is important to declare DRT is running early so when creating
- // web view mock clients are used instead of proper ones.
- DumpRenderTreeSupportGtk::setDumpRenderTreeModeEnabled(true);
-
- DumpRenderTreeSupportGtk::setFrameLoadEventCallback(frameLoadEventCallback);
- DumpRenderTreeSupportGtk::setAuthenticationCallback(authenticationCallback);
-
- WebKitWebView* view = WEBKIT_WEB_VIEW(self_scrolling_webkit_web_view_new());
-
- g_object_connect(G_OBJECT(view),
- "signal::load-started", webViewLoadStarted, 0,
- "signal::load-finished", webViewLoadFinished, 0,
- "signal::load-error", webViewLoadError, 0,
- "signal::window-object-cleared", webViewWindowObjectCleared, 0,
- "signal::console-message", webViewConsoleMessage, 0,
- "signal::script-alert", webViewScriptAlert, 0,
- "signal::script-prompt", webViewScriptPrompt, 0,
- "signal::script-confirm", webViewScriptConfirm, 0,
- "signal::title-changed", webViewTitleChanged, 0,
- "signal::navigation-policy-decision-requested", webViewNavigationPolicyDecisionRequested, 0,
- "signal::status-bar-text-changed", webViewStatusBarTextChanged, 0,
- "signal::create-web-view", webViewCreate, 0,
- "signal::close-web-view", webViewClose, 0,
- "signal::database-quota-exceeded", databaseQuotaExceeded, 0,
- "signal::document-load-finished", webViewDocumentLoadFinished, 0,
- "signal::geolocation-policy-decision-requested", geolocationPolicyDecisionRequested, 0,
- "signal::onload-event", webViewOnloadEvent, 0,
- "signal::drag-begin", dragBeginCallback, 0,
- "signal::drag-end", dragEndCallback, 0,
- "signal::drag-failed", dragFailedCallback, 0,
- "signal::frame-created", frameCreatedCallback, 0,
- "signal::resource-request-starting", willSendRequestCallback, 0,
- "signal::resource-response-received", didReceiveResponse, 0,
- "signal::resource-load-finished", didFinishLoading, 0,
- "signal::resource-load-failed", didFailLoadingWithError, 0,
- "signal::run-file-chooser", webViewRunFileChooser, 0,
- NULL);
- connectEditingCallbacks(view);
-
- WebKitWebInspector* inspector = webkit_web_view_get_inspector(view);
- g_object_connect(G_OBJECT(inspector),
- "signal::inspect-web-view", webInspectorInspectWebView, 0,
- "signal::show-window", webInspectorShowWindow, 0,
- "signal::close-window", webInspectorCloseWindow, 0,
- NULL);
-
- if (webView) {
- WebKitWebSettings* settings = webkit_web_view_get_settings(webView);
- webkit_web_view_set_settings(view, settings);
- }
-
- // frame-created is not issued for main frame. That's why we must do this here
- WebKitWebFrame* frame = webkit_web_view_get_main_frame(view);
- g_signal_connect(frame, "notify::load-status", G_CALLBACK(webFrameLoadStatusNotified), NULL);
- g_signal_connect(frame, "insecure-content-run", G_CALLBACK(didRunInsecureContent), NULL);
-
- return view;
-}
-
-static WebKitWebView* webViewCreate(WebKitWebView* view, WebKitWebFrame* frame)
-{
- if (!gTestRunner->canOpenWindows())
- return 0;
-
- // Make sure that waitUntilDone has been called.
- ASSERT(gTestRunner->waitToDump());
-
- WebKitWebView* newWebView = createWebView();
- g_object_ref_sink(G_OBJECT(newWebView));
- webViewList = g_slist_prepend(webViewList, newWebView);
- return newWebView;
-}
-
-static void logHandler(const gchar* domain, GLogLevelFlags level, const gchar* message, gpointer data)
-{
- if (level < G_LOG_LEVEL_DEBUG)
- fprintf(stderr, "%s\n", message);
-}
-
-int main(int argc, char* argv[])
-{
- gtk_init(&argc, &argv);
-
- // Some plugins might try to use the GLib logger for printing debug
- // messages. This will cause tests to fail because of unexpected output.
- // We squelch all debug messages sent to the logger.
- g_log_set_default_handler(logHandler, 0);
-
- initializeGlobalsFromCommandLineOptions(argc, argv);
- initializeFonts();
-
- window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-#ifdef GTK_API_VERSION_2
- container = gtk_hbox_new(TRUE, 0);
-#else
- container = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
- gtk_box_set_homogeneous(GTK_BOX(container), TRUE);
-#endif
- gtk_container_add(GTK_CONTAINER(window), container);
- gtk_widget_show_all(window);
-
- webView = createWebView();
- gtk_box_pack_start(GTK_BOX(container), GTK_WIDGET(webView), TRUE, TRUE, 0);
- gtk_widget_realize(GTK_WIDGET(webView));
- gtk_widget_show_all(container);
- mainFrame = webkit_web_view_get_main_frame(webView);
-
- setDefaultsToConsistentStateValuesForTesting();
-
- gcController = new GCController();
-#if HAVE(ACCESSIBILITY)
- axController = new AccessibilityController();
-#endif
-
- if (useLongRunningServerMode(argc, argv)) {
- printSeparators = true;
- runTestingServerLoop();
- } else {
- printSeparators = (optind < argc-1 || (dumpPixelsForCurrentTest && dumpTree));
- for (int i = optind; i != argc; ++i)
- runTest(argv[i]);
- }
-
- delete gcController;
- gcController = 0;
-
-#if HAVE(ACCESSIBILITY)
- delete axController;
- axController = 0;
-#endif
-
- gtk_widget_destroy(window);
-
- return 0;
-}
diff --git a/Tools/DumpRenderTree/gtk/DumpRenderTreeGtk.h b/Tools/DumpRenderTree/gtk/DumpRenderTreeGtk.h
deleted file mode 100644
index 4b33458f3..000000000
--- a/Tools/DumpRenderTree/gtk/DumpRenderTreeGtk.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef DumpRenderTreeGtk_h
-#define DumpRenderTreeGtk_h
-
-#include <JavaScriptCore/JSBase.h>
-#include <glib.h>
-#include <libsoup/soup.h>
-#include <webkit/webkitdefines.h>
-#include <wtf/text/CString.h>
-
-extern WebKitWebFrame* mainFrame;
-extern WebKitWebFrame* topLoadingFrame;
-extern bool waitForPolicy;
-extern GSList* webViewList;
-
-gchar* JSStringCopyUTF8CString(JSStringRef jsString);
-CString getTopLevelPath();
-
-void setWaitToDumpWatchdog(guint timer);
-bool shouldSetWaitToDumpWatchdog();
-CString soupURIToStringPreservingPassword(SoupURI* soupURI);
-
-#endif // DumpRenderTreeGtk_h
diff --git a/Tools/DumpRenderTree/gtk/EditingCallbacks.cpp b/Tools/DumpRenderTree/gtk/EditingCallbacks.cpp
deleted file mode 100644
index 3c08f80b3..000000000
--- a/Tools/DumpRenderTree/gtk/EditingCallbacks.cpp
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright (C) 2010 Igalia S.L.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "EditingCallbacks.h"
-
-#include "DumpRenderTree.h"
-#include "TestRunner.h"
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-#include <wtf/gobject/GUniquePtr.h>
-#include <wtf/text/CString.h>
-
-static CString dumpNodePath(WebKitDOMNode* node)
-{
- GUniquePtr<gchar> nodeName(webkit_dom_node_get_node_name(node));
- GString* path = g_string_new(nodeName.get());
-
- WebKitDOMNode* parent = webkit_dom_node_get_parent_node(node);
- while (parent) {
- GUniquePtr<gchar> parentName(webkit_dom_node_get_node_name(parent));
-
- g_string_append(path, " > ");
- g_string_append(path, parentName.get());
- parent = webkit_dom_node_get_parent_node(parent);
- }
-
- GUniquePtr<gchar> pathBuffer(g_string_free(path, FALSE));
- return pathBuffer.get();
-}
-
-static CString dumpRange(WebKitDOMRange* range)
-{
- if (!range)
- return "(null)";
-
- GUniquePtr<gchar> dump(g_strdup_printf("range from %li of %s to %li of %s",
- webkit_dom_range_get_start_offset(range, 0),
- dumpNodePath(webkit_dom_range_get_start_container(range, 0)).data(),
- webkit_dom_range_get_end_offset(range, 0),
- dumpNodePath(webkit_dom_range_get_end_container(range, 0)).data()));
-
- return dump.get();
-}
-
-static const char* insertActionString(WebKitInsertAction action)
-{
- switch (action) {
- case WEBKIT_INSERT_ACTION_TYPED:
- return "WebViewInsertActionTyped";
- case WEBKIT_INSERT_ACTION_PASTED:
- return "WebViewInsertActionPasted";
- case WEBKIT_INSERT_ACTION_DROPPED:
- return "WebViewInsertActionDropped";
- }
- ASSERT_NOT_REACHED();
- return "WebViewInsertActionTyped";
-}
-
-static const char* selectionAffinityString(WebKitSelectionAffinity affinity)
-{
- switch (affinity) {
- case WEBKIT_SELECTION_AFFINITY_UPSTREAM:
- return "NSSelectionAffinityUpstream";
- case WEBKIT_SELECTION_AFFINITY_DOWNSTREAM:
- return "NSSelectionAffinityDownstream";
- }
- ASSERT_NOT_REACHED();
- return "NSSelectionAffinityUpstream";
-}
-
-gboolean shouldBeginEditing(WebKitWebView* webView, WebKitDOMRange* range)
-{
- if (!done && gTestRunner->dumpEditingCallbacks())
- printf("EDITING DELEGATE: shouldBeginEditingInDOMRange:%s\n", dumpRange(range).data());
- return TRUE;
-}
-
-gboolean shouldEndEditing(WebKitWebView* webView, WebKitDOMRange* range)
-{
- if (!done && gTestRunner->dumpEditingCallbacks())
- printf("EDITING DELEGATE: shouldEndEditingInDOMRange:%s\n", dumpRange(range).data());
- return TRUE;
-}
-
-gboolean shouldInsertNode(WebKitWebView* webView, WebKitDOMNode* node, WebKitDOMRange* range, WebKitInsertAction action)
-{
- if (!done && gTestRunner->dumpEditingCallbacks()) {
- printf("EDITING DELEGATE: shouldInsertNode:%s replacingDOMRange:%s givenAction:%s\n",
- dumpNodePath(node).data(), dumpRange(range).data(), insertActionString(action));
- }
- return TRUE;
-}
-
-gboolean shouldInsertText(WebKitWebView* webView, const gchar* text, WebKitDOMRange* range, WebKitInsertAction action)
-{
- if (!done && gTestRunner->dumpEditingCallbacks()) {
- printf("EDITING DELEGATE: shouldInsertText:%s replacingDOMRange:%s givenAction:%s\n",
- text, dumpRange(range).data(), insertActionString(action));
- }
- return TRUE;
-}
-
-gboolean shouldDeleteRange(WebKitWebView* webView, WebKitDOMRange* range)
-{
- if (!done && gTestRunner->dumpEditingCallbacks())
- printf("EDITING DELEGATE: shouldDeleteDOMRange:%s\n", dumpRange(range).data());
- return TRUE;
-}
-
-gboolean shouldShowDeleteInterfaceForElement(WebKitWebView* webView, WebKitDOMHTMLElement* element)
-{
- return FALSE;
-}
-
-gboolean shouldChangeSelectedRange(WebKitWebView* webView, WebKitDOMRange* fromRange, WebKitDOMRange* toRange, WebKitSelectionAffinity affinity, gboolean stillSelecting)
-{
- if (!done && gTestRunner->dumpEditingCallbacks()) {
- printf("EDITING DELEGATE: shouldChangeSelectedDOMRange:%s toDOMRange:%s affinity:%s stillSelecting:%s\n",
- dumpRange(fromRange).data(), dumpRange(toRange).data(), selectionAffinityString(affinity),
- stillSelecting ? "TRUE" : "FALSE");
- }
- return TRUE;
-}
-
-gboolean shouldApplyStyle(WebKitWebView* webView, WebKitDOMCSSStyleDeclaration* style, WebKitDOMRange* range)
-{
- if (!done && gTestRunner->dumpEditingCallbacks()) {
- GUniquePtr<gchar> styleText(webkit_dom_css_style_declaration_get_css_text(style));
- printf("EDITING DELEGATE: shouldApplyStyle:%s toElementsInDOMRange:%s\n",
- styleText.get(), dumpRange(range).data());
- }
- return TRUE;
-}
-
-void editingBegan(WebKitWebView*)
-{
- if (!done && gTestRunner->dumpEditingCallbacks())
- printf("EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification\n");
-}
-
-void userChangedContents(WebKitWebView*)
-{
- if (!done && gTestRunner->dumpEditingCallbacks())
- printf("EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification\n");
-}
-
-void editingEnded(WebKitWebView*)
-{
- if (!done && gTestRunner->dumpEditingCallbacks())
- printf("EDITING DELEGATE: webViewDidEndEditing:WebViewDidEndEditingNotification\n");
-}
-
-void selectionChanged(WebKitWebView*)
-{
- if (!done && gTestRunner->dumpEditingCallbacks())
- printf("EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification\n");
-}
-
-void connectEditingCallbacks(WebKitWebView* webView)
-{
- g_object_connect(G_OBJECT(webView),
- "signal::should-begin-editing", shouldBeginEditing, 0,
- "signal::should-end-editing", shouldEndEditing, 0,
- "signal::should-insert-node", shouldInsertNode, 0,
- "signal::should-insert-text", shouldInsertText, 0,
- "signal::should-delete-range", shouldDeleteRange, 0,
- "signal::should-show-delete-interface-for-element", shouldShowDeleteInterfaceForElement, 0,
- "signal::should-change-selected-range", shouldChangeSelectedRange, 0,
- "signal::should-apply-style", shouldApplyStyle, 0,
- "signal::editing-began", editingBegan, 0,
- "signal::user-changed-contents", userChangedContents, 0,
- "signal::editing-ended", editingEnded, 0,
- "signal::selection-changed", selectionChanged, 0,
- NULL);
-}
-
diff --git a/Tools/DumpRenderTree/gtk/EditingCallbacks.h b/Tools/DumpRenderTree/gtk/EditingCallbacks.h
deleted file mode 100644
index 7a9514917..000000000
--- a/Tools/DumpRenderTree/gtk/EditingCallbacks.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2010 Igalia S.L.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef EditingCallbacks_h
-#define EditingCallbacks_h
-
-typedef struct _WebKitWebView WebKitWebView;
-void connectEditingCallbacks(WebKitWebView*);
-
-#endif
diff --git a/Tools/DumpRenderTree/gtk/EventSender.cpp b/Tools/DumpRenderTree/gtk/EventSender.cpp
deleted file mode 100644
index bd8e4fb8f..000000000
--- a/Tools/DumpRenderTree/gtk/EventSender.cpp
+++ /dev/null
@@ -1,1004 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2009 Zan Dobersek <zandobersek@gmail.com>
- * Copyright (C) 2009 Holger Hans Peter Freyther
- * Copyright (C) 2010 Igalia S.L.
- * Copyright (C) 2012 ChangSeok Oh <shivamidow@gmail.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "EventSender.h"
-
-#include "DumpRenderTree.h"
-#include "WebCoreSupport/DumpRenderTreeSupportGtk.h"
-#include <GRefPtrGtk.h>
-#include <GtkVersioning.h>
-#include <JavaScriptCore/JSObjectRef.h>
-#include <JavaScriptCore/JSRetainPtr.h>
-#include <JavaScriptCore/JSStringRef.h>
-#include <cstring>
-#include <gdk/gdk.h>
-#include <gdk/gdkkeysyms.h>
-#include <webkit/webkitwebframe.h>
-#include <webkit/webkitwebview.h>
-#include <wtf/ASCIICType.h>
-#include <wtf/Platform.h>
-#include <wtf/gobject/GUniquePtr.h>
-#include <wtf/text/CString.h>
-
-extern "C" {
- extern GtkMenu* webkit_web_view_get_context_menu(WebKitWebView*);
-}
-
-static bool dragMode;
-static int timeOffset = 0;
-
-static int lastMousePositionX;
-static int lastMousePositionY;
-static int lastClickPositionX;
-static int lastClickPositionY;
-static int lastClickTimeOffset;
-static int lastClickButton;
-static unsigned buttonCurrentlyDown;
-static int clickCount;
-GdkDragContext* currentDragSourceContext;
-
-struct DelayedMessage {
- GdkEvent* event;
- gulong delay;
-};
-
-static DelayedMessage msgQueue[1024];
-
-static unsigned endOfQueue;
-static unsigned startOfQueue;
-
-static const float zoomMultiplierRatio = 1.2f;
-
-// WebCore and layout tests assume this value.
-static const float pixelsPerScrollTick = 40;
-
-// Key event location code defined in DOM Level 3.
-enum KeyLocationCode {
- DOM_KEY_LOCATION_STANDARD = 0x00,
- DOM_KEY_LOCATION_LEFT = 0x01,
- DOM_KEY_LOCATION_RIGHT = 0x02,
- DOM_KEY_LOCATION_NUMPAD = 0x03
-};
-
-static void sendOrQueueEvent(GdkEvent*, bool = true);
-static void dispatchEvent(GdkEvent* event);
-static guint getStateFlags();
-
-static JSValueRef getDragModeCallback(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
-{
- return JSValueMakeBoolean(context, dragMode);
-}
-
-static bool setDragModeCallback(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
-{
- dragMode = JSValueToBoolean(context, value);
- return true;
-}
-
-static JSValueRef leapForwardCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- if (argumentCount > 0) {
- msgQueue[endOfQueue].delay = JSValueToNumber(context, arguments[0], exception);
- timeOffset += msgQueue[endOfQueue].delay;
- ASSERT(!exception || !*exception);
- }
-
- return JSValueMakeUndefined(context);
-}
-
-bool prepareMouseButtonEvent(GdkEvent* event, int eventSenderButtonNumber, guint modifiers)
-{
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- if (!view)
- return false;
-
- // The logic for mapping EventSender button numbers to GDK button
- // numbers originates from the Windows EventSender.
- int gdkButtonNumber = 3;
- if (eventSenderButtonNumber >= 0 && eventSenderButtonNumber <= 2)
- gdkButtonNumber = eventSenderButtonNumber + 1;
-
- // fast/events/mouse-click-events expects the 4th button
- // to be event->button = 1, so send a middle-button event.
- else if (eventSenderButtonNumber == 3)
- gdkButtonNumber = 2;
-
- event->button.button = gdkButtonNumber;
- event->button.x = lastMousePositionX;
- event->button.y = lastMousePositionY;
- event->button.window = gtk_widget_get_window(GTK_WIDGET(view));
- g_object_ref(event->button.window);
- event->button.device = getDefaultGDKPointerDevice(event->button.window);
- event->button.state = modifiers | getStateFlags();
- event->button.time = GDK_CURRENT_TIME;
- event->button.axes = 0;
-
- int xRoot, yRoot;
- gdk_window_get_root_coords(gtk_widget_get_window(GTK_WIDGET(view)), lastMousePositionX, lastMousePositionY, &xRoot, &yRoot);
- event->button.x_root = xRoot;
- event->button.y_root = yRoot;
-
- return true;
-}
-
-static JSValueRef getMenuItemTitleCallback(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
-{
- GtkWidget* widget = GTK_WIDGET(JSObjectGetPrivate(object));
- CString label;
- if (GTK_IS_SEPARATOR_MENU_ITEM(widget))
- label = "<separator>";
- else
- label = gtk_menu_item_get_label(GTK_MENU_ITEM(widget));
-
- JSRetainPtr<JSStringRef> itemText(Adopt, JSStringCreateWithUTF8CString(label.data()));
- return JSValueMakeString(context, itemText.get());
-}
-
-static bool setMenuItemTitleCallback(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
-{
- return true;
-}
-
-static JSValueRef menuItemClickCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- GtkMenuItem* item = GTK_MENU_ITEM(JSObjectGetPrivate(thisObject));
- gtk_menu_item_activate(item);
- return JSValueMakeUndefined(context);
-}
-
-static JSStaticFunction staticMenuItemFunctions[] = {
- { "click", menuItemClickCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { 0, 0, 0 }
-};
-
-static JSStaticValue staticMenuItemValues[] = {
- { "title", getMenuItemTitleCallback, setMenuItemTitleCallback, kJSPropertyAttributeNone },
- { 0, 0, 0, 0 }
-};
-
-static JSClassRef getMenuItemClass()
-{
- static JSClassRef menuItemClass = 0;
-
- if (!menuItemClass) {
- JSClassDefinition classDefinition = {
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- classDefinition.staticFunctions = staticMenuItemFunctions;
- classDefinition.staticValues = staticMenuItemValues;
-
- menuItemClass = JSClassCreate(&classDefinition);
- }
-
- return menuItemClass;
-}
-
-
-static JSValueRef contextClickCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- GdkEvent* pressEvent = gdk_event_new(GDK_BUTTON_PRESS);
-
- if (!prepareMouseButtonEvent(pressEvent, 2, 0)) {
- gdk_event_free(pressEvent);
- return JSObjectMakeArray(context, 0, 0, 0);
- }
-
- GdkEvent* releaseEvent = gdk_event_copy(pressEvent);
- sendOrQueueEvent(pressEvent);
-
- JSValueRef valueRef = JSObjectMakeArray(context, 0, 0, 0);
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- GtkMenu* gtkMenu = webkit_web_view_get_context_menu(view);
- if (gtkMenu) {
- GUniquePtr<GList> items(gtk_container_get_children(GTK_CONTAINER(gtkMenu)));
- JSValueRef arrayValues[g_list_length(items.get())];
- int index = 0;
- for (GList* item = g_list_first(items.get()); item; item = g_list_next(item)) {
- arrayValues[index] = JSObjectMake(context, getMenuItemClass(), item->data);
- index++;
- }
- if (index)
- valueRef = JSObjectMakeArray(context, index - 1, arrayValues, 0);
- }
-
- releaseEvent->type = GDK_BUTTON_RELEASE;
- sendOrQueueEvent(releaseEvent);
- return valueRef;
-}
-
-static gboolean sendClick(gpointer)
-{
- GdkEvent* pressEvent = gdk_event_new(GDK_BUTTON_PRESS);
-
- if (!prepareMouseButtonEvent(pressEvent, 1, 0)) {
- gdk_event_free(pressEvent);
- return FALSE;
- }
-
- GdkEvent* releaseEvent = gdk_event_copy(pressEvent);
- dispatchEvent(pressEvent);
- releaseEvent->type = GDK_BUTTON_RELEASE;
- dispatchEvent(releaseEvent);
-
- return FALSE;
-}
-
-static JSValueRef scheduleAsynchronousClickCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- g_idle_add_full(G_PRIORITY_DEFAULT, sendClick, 0, 0);
- return JSValueMakeUndefined(context);
-}
-
-static void updateClickCount(int button)
-{
- if (lastClickPositionX != lastMousePositionX
- || lastClickPositionY != lastMousePositionY
- || lastClickButton != button
- || timeOffset - lastClickTimeOffset >= 1)
- clickCount = 1;
- else
- clickCount++;
-}
-
-static guint gdkModifierFromJSValue(JSContextRef context, const JSValueRef value)
-{
- JSStringRef string = JSValueToStringCopy(context, value, 0);
- guint gdkModifier = 0;
- if (JSStringIsEqualToUTF8CString(string, "ctrlKey")
- || JSStringIsEqualToUTF8CString(string, "addSelectionKey"))
- gdkModifier = GDK_CONTROL_MASK;
- else if (JSStringIsEqualToUTF8CString(string, "shiftKey")
- || JSStringIsEqualToUTF8CString(string, "rangeSelectionKey"))
- gdkModifier = GDK_SHIFT_MASK;
- else if (JSStringIsEqualToUTF8CString(string, "altKey"))
- gdkModifier = GDK_MOD1_MASK;
-
- // Currently the metaKey as defined in WebCore/platform/gtk/PlatformMouseEventGtk.cpp
- // is GDK_META_MASK. This code must be kept in sync with that file.
- else if (JSStringIsEqualToUTF8CString(string, "metaKey"))
- gdkModifier = GDK_META_MASK;
-
- JSStringRelease(string);
- return gdkModifier;
-}
-
-static guint gdkModifersFromJSValue(JSContextRef context, const JSValueRef modifiers)
-{
- // The value may either be a string with a single modifier or an array of modifiers.
- if (JSValueIsString(context, modifiers))
- return gdkModifierFromJSValue(context, modifiers);
-
- JSObjectRef modifiersArray = JSValueToObject(context, modifiers, 0);
- if (!modifiersArray)
- return 0;
-
- guint gdkModifiers = 0;
- JSRetainPtr<JSStringRef> lengthProperty(Adopt, JSStringCreateWithUTF8CString("length"));
- int modifiersCount = JSValueToNumber(context, JSObjectGetProperty(context, modifiersArray, lengthProperty.get(), 0), 0);
- for (int i = 0; i < modifiersCount; ++i)
- gdkModifiers |= gdkModifierFromJSValue(context, JSObjectGetPropertyAtIndex(context, modifiersArray, i, 0));
- return gdkModifiers;
-}
-
-static JSValueRef mouseDownCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- int button = 0;
- if (argumentCount == 1) {
- button = static_cast<int>(JSValueToNumber(context, arguments[0], exception));
- g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
- }
- guint modifiers = argumentCount >= 2 ? gdkModifersFromJSValue(context, arguments[1]) : 0;
-
- GdkEvent* event = gdk_event_new(GDK_BUTTON_PRESS);
- if (!prepareMouseButtonEvent(event, button, modifiers)) {
- gdk_event_free(event);
- return JSValueMakeUndefined(context);
- }
-
- // If the same mouse button is already in the down position don't send another event as it may confuse Xvfb.
- if (buttonCurrentlyDown == event->button.button) {
- gdk_event_free(event);
- return JSValueMakeUndefined(context);
- }
-
- buttonCurrentlyDown = event->button.button;
-
- // Normally GDK will send both GDK_BUTTON_PRESS and GDK_2BUTTON_PRESS for
- // the second button press during double-clicks. WebKit GTK+ selectively
- // ignores the first GDK_BUTTON_PRESS of that pair using gdk_event_peek.
- // Since our events aren't ever going onto the GDK event queue, WebKit won't
- // be able to filter out the first GDK_BUTTON_PRESS, so we just don't send
- // it here. Eventually this code should probably figure out a way to get all
- // appropriate events onto the event queue and this work-around should be
- // removed.
- updateClickCount(event->button.button);
- if (clickCount == 2)
- event->type = GDK_2BUTTON_PRESS;
- else if (clickCount == 3)
- event->type = GDK_3BUTTON_PRESS;
-
- sendOrQueueEvent(event);
- return JSValueMakeUndefined(context);
-}
-
-static guint getStateFlags()
-{
- if (buttonCurrentlyDown == 1)
- return GDK_BUTTON1_MASK;
- if (buttonCurrentlyDown == 2)
- return GDK_BUTTON2_MASK;
- if (buttonCurrentlyDown == 3)
- return GDK_BUTTON3_MASK;
- return 0;
-}
-
-static JSValueRef mouseUpCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- int button = 0;
- if (argumentCount == 1) {
- button = static_cast<int>(JSValueToNumber(context, arguments[0], exception));
- g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
- }
- guint modifiers = argumentCount >= 2 ? gdkModifersFromJSValue(context, arguments[1]) : 0;
-
- GdkEvent* event = gdk_event_new(GDK_BUTTON_RELEASE);
- if (!prepareMouseButtonEvent(event, button, modifiers)) {
- gdk_event_free(event);
- return JSValueMakeUndefined(context);
- }
-
- lastClickPositionX = lastMousePositionX;
- lastClickPositionY = lastMousePositionY;
- lastClickButton = buttonCurrentlyDown;
- lastClickTimeOffset = timeOffset;
- buttonCurrentlyDown = 0;
-
- sendOrQueueEvent(event);
- return JSValueMakeUndefined(context);
-}
-
-static JSValueRef mouseMoveToCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- if (!view)
- return JSValueMakeUndefined(context);
-
- if (argumentCount < 2)
- return JSValueMakeUndefined(context);
-
- lastMousePositionX = (int)JSValueToNumber(context, arguments[0], exception);
- g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
- lastMousePositionY = (int)JSValueToNumber(context, arguments[1], exception);
- g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
-
- GdkEvent* event = gdk_event_new(GDK_MOTION_NOTIFY);
- event->motion.x = lastMousePositionX;
- event->motion.y = lastMousePositionY;
-
- event->motion.time = GDK_CURRENT_TIME;
- event->motion.window = gtk_widget_get_window(GTK_WIDGET(view));
- g_object_ref(event->motion.window);
- event->button.device = getDefaultGDKPointerDevice(event->motion.window);
-
- guint modifiers = argumentCount >= 3 ? gdkModifersFromJSValue(context, arguments[2]) : 0;
- event->motion.state = modifiers | getStateFlags();
- event->motion.axes = 0;
-
- int xRoot, yRoot;
- gdk_window_get_root_coords(gtk_widget_get_window(GTK_WIDGET(view)), lastMousePositionX, lastMousePositionY, &xRoot, &yRoot);
- event->motion.x_root = xRoot;
- event->motion.y_root = yRoot;
-
- sendOrQueueEvent(event, false);
- return JSValueMakeUndefined(context);
-}
-
-static JSValueRef mouseScrollByCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- if (!view)
- return JSValueMakeUndefined(context);
-
- if (argumentCount < 2)
- return JSValueMakeUndefined(context);
-
- int horizontal = (int)JSValueToNumber(context, arguments[0], exception);
- g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
- int vertical = (int)JSValueToNumber(context, arguments[1], exception);
- g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
-
- // Copy behaviour of Qt and EFL - just return in case of (0,0) mouse scroll
- if (!horizontal && !vertical)
- return JSValueMakeUndefined(context);
-
- GdkEvent* event = gdk_event_new(GDK_SCROLL);
- event->scroll.x = lastMousePositionX;
- event->scroll.y = lastMousePositionY;
- event->scroll.time = GDK_CURRENT_TIME;
- event->scroll.window = gtk_widget_get_window(GTK_WIDGET(view));
- g_object_ref(event->scroll.window);
-
- // GTK+ only supports one tick in each scroll event that is not smooth. For the cases of more than one direction,
- // and more than one step in a direction, we can only use smooth events, supported from Gtk 3.3.18.
-#if GTK_CHECK_VERSION(3, 3, 18)
- if ((horizontal && vertical) || horizontal > 1 || horizontal < -1 || vertical > 1 || vertical < -1) {
- event->scroll.direction = GDK_SCROLL_SMOOTH;
- event->scroll.delta_x = -horizontal;
- event->scroll.delta_y = -vertical;
-
- sendOrQueueEvent(event);
- return JSValueMakeUndefined(context);
- }
-#else
- g_return_val_if_fail((!vertical || !horizontal), JSValueMakeUndefined(context));
-#endif
-
- if (horizontal < 0)
- event->scroll.direction = GDK_SCROLL_RIGHT;
- else if (horizontal > 0)
- event->scroll.direction = GDK_SCROLL_LEFT;
- else if (vertical < 0)
- event->scroll.direction = GDK_SCROLL_DOWN;
- else if (vertical > 0)
- event->scroll.direction = GDK_SCROLL_UP;
- else
- g_assert_not_reached();
-
- sendOrQueueEvent(event);
- return JSValueMakeUndefined(context);
-}
-
-static JSValueRef continuousMouseScrollByCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
-#if GTK_CHECK_VERSION(3, 3, 18)
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- if (!view)
- return JSValueMakeUndefined(context);
-
- if (argumentCount < 2)
- return JSValueMakeUndefined(context);
-
- int horizontal = JSValueToNumber(context, arguments[0], exception);
- g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
- int vertical = JSValueToNumber(context, arguments[1], exception);
- g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
-
- // We do not yet support continuous scrolling by page.
- if (argumentCount >= 3 && JSValueToBoolean(context, arguments[2]))
- return JSValueMakeUndefined(context);
-
- GdkEvent* event = gdk_event_new(GDK_SCROLL);
- event->scroll.x = lastMousePositionX;
- event->scroll.y = lastMousePositionY;
- event->scroll.time = GDK_CURRENT_TIME;
- event->scroll.window = gtk_widget_get_window(GTK_WIDGET(view));
- g_object_ref(event->scroll.window);
-
- event->scroll.direction = GDK_SCROLL_SMOOTH;
- event->scroll.delta_x = -horizontal / pixelsPerScrollTick;
- event->scroll.delta_y = -vertical / pixelsPerScrollTick;
-
- sendOrQueueEvent(event);
-#endif
- return JSValueMakeUndefined(context);
-}
-
-static void dragWithFilesDragDataGetCallback(GtkWidget*, GdkDragContext*, GtkSelectionData *data, guint, guint, gpointer userData)
-{
- gtk_selection_data_set_uris(data, static_cast<gchar**>(userData));
-}
-
-static void dragWithFilesDragEndCallback(GtkWidget* widget, GdkDragContext*, gpointer userData)
-{
- g_signal_handlers_disconnect_by_func(widget, reinterpret_cast<void*>(dragWithFilesDragEndCallback), userData);
- g_signal_handlers_disconnect_by_func(widget, reinterpret_cast<void*>(dragWithFilesDragDataGetCallback), userData);
- g_strfreev(static_cast<gchar**>(userData));
-}
-
-static JSValueRef beginDragWithFilesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- if (argumentCount < 1)
- return JSValueMakeUndefined(context);
-
- JSObjectRef filesArray = JSValueToObject(context, arguments[0], exception);
- ASSERT(!exception || !*exception);
-
- const gchar* mainFrameURI = webkit_web_frame_get_uri(mainFrame);
- GRefPtr<GFile> testFile(adoptGRef(g_file_new_for_uri(mainFrameURI)));
- GRefPtr<GFile> parentDirectory(g_file_get_parent(testFile.get()));
- if (!parentDirectory)
- return JSValueMakeUndefined(context);
-
- // If this is an HTTP test, we still need to pass a local file path
- // to WebCore. Even though the file doesn't exist, this should be fine
- // for most tests.
- GUniquePtr<gchar> scheme(g_file_get_uri_scheme(parentDirectory.get()));
- if (g_str_equal(scheme.get(), "http") || g_str_equal(scheme.get(), "https")) {
- GUniquePtr<gchar> currentDirectory(g_get_current_dir());
- parentDirectory = adoptGRef(g_file_new_for_path(currentDirectory.get()));
- }
-
- JSStringRef lengthProperty = JSStringCreateWithUTF8CString("length");
- int filesArrayLength = JSValueToNumber(context, JSObjectGetProperty(context, filesArray, lengthProperty, 0), 0);
- JSStringRelease(lengthProperty);
-
- gchar** draggedFilesURIList = g_new0(gchar*, filesArrayLength + 1);
- for (int i = 0; i < filesArrayLength; ++i) {
- JSStringRef filenameString = JSValueToStringCopy(context,
- JSObjectGetPropertyAtIndex(context, filesArray, i, 0), 0);
- size_t bufferSize = JSStringGetMaximumUTF8CStringSize(filenameString);
- GUniquePtr<gchar> filenameBuffer(static_cast<gchar*>(g_malloc(bufferSize)));
- JSStringGetUTF8CString(filenameString, filenameBuffer.get(), bufferSize);
- JSStringRelease(filenameString);
-
- GRefPtr<GFile> dragFile(g_file_get_child(parentDirectory.get(), filenameBuffer.get()));
- draggedFilesURIList[i] = g_file_get_uri(dragFile.get());
- }
-
- GtkWidget* view = GTK_WIDGET(webkit_web_frame_get_web_view(mainFrame));
- g_object_connect(G_OBJECT(view),
- "signal::drag-end", dragWithFilesDragEndCallback, draggedFilesURIList,
- "signal::drag-data-get", dragWithFilesDragDataGetCallback, draggedFilesURIList,
- NULL);
-
- GdkEvent event;
- GdkWindow* viewGDKWindow = gtk_widget_get_window(view);
- memset(&event, 0, sizeof(event));
- event.type = GDK_MOTION_NOTIFY;
- event.motion.x = lastMousePositionX;
- event.motion.y = lastMousePositionY;
- event.motion.time = GDK_CURRENT_TIME;
- event.motion.window = viewGDKWindow;
- event.motion.device = getDefaultGDKPointerDevice(viewGDKWindow);
- event.motion.state = GDK_BUTTON1_MASK;
-
- int xRoot, yRoot;
- gdk_window_get_root_coords(viewGDKWindow, lastMousePositionX, lastMousePositionY, &xRoot, &yRoot);
- event.motion.x_root = xRoot;
- event.motion.y_root = yRoot;
-
- GtkTargetList* targetList = gtk_target_list_new(0, 0);
- gtk_target_list_add_uri_targets(targetList, 0);
- gtk_drag_begin(view, targetList, GDK_ACTION_COPY, 1, &event);
- gtk_target_list_unref(targetList);
-
- return JSValueMakeUndefined(context);
-}
-
-static void sendOrQueueEvent(GdkEvent* event, bool shouldReplaySavedEvents)
-{
- // Mouse move events are queued if the previous event was queued or if a
- // delay was set up by leapForward().
- if ((dragMode && buttonCurrentlyDown) || endOfQueue != startOfQueue || msgQueue[endOfQueue].delay) {
- msgQueue[endOfQueue++].event = event;
-
- if (shouldReplaySavedEvents)
- replaySavedEvents();
-
- return;
- }
-
- dispatchEvent(event);
-}
-
-static void dispatchEvent(GdkEvent* event)
-{
- DumpRenderTreeSupportGtk::layoutFrame(mainFrame);
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- if (!view) {
- gdk_event_free(event);
- return;
- }
-
- // The widget focus may have been lost in the course of the test,
- // so force another explicit focus grab here.
- gtk_widget_grab_focus(GTK_WIDGET(view));
- gtk_main_do_event(event);
-
- if (!currentDragSourceContext) {
- gdk_event_free(event);
- return;
- }
-
- if (event->type == GDK_MOTION_NOTIFY) {
- // WebKit has called gtk_drag_start(), but because the main loop isn't
- // running GDK internals don't know that the drag has started yet. Pump
- // the main loop a little bit so that GDK is in the correct state.
- while (gtk_events_pending())
- gtk_main_iteration();
-
- // Simulate a drag motion on the top-level GDK window.
- GtkWidget* parentWidget = gtk_widget_get_parent(GTK_WIDGET(view));
- GdkWindow* parentWidgetWindow = gtk_widget_get_window(parentWidget);
- gdk_drag_motion(currentDragSourceContext, parentWidgetWindow, GDK_DRAG_PROTO_XDND,
- event->motion.x_root, event->motion.y_root,
- gdk_drag_context_get_selected_action(currentDragSourceContext),
- gdk_drag_context_get_actions(currentDragSourceContext),
- GDK_CURRENT_TIME);
-
- } else if (currentDragSourceContext && event->type == GDK_BUTTON_RELEASE) {
- // We've released the mouse button, we should just be able to spin the
- // event loop here and have GTK+ send the appropriate notifications for
- // the end of the drag.
- while (gtk_events_pending())
- gtk_main_iteration();
- }
-
- gdk_event_free(event);
-}
-
-void replaySavedEvents()
-{
- // First send all the events that are ready to be sent
- while (startOfQueue < endOfQueue) {
- if (msgQueue[startOfQueue].delay) {
- g_usleep(msgQueue[startOfQueue].delay * 1000);
- msgQueue[startOfQueue].delay = 0;
- }
-
- dispatchEvent(msgQueue[startOfQueue++].event);
- }
-
- startOfQueue = 0;
- endOfQueue = 0;
-}
-
-static GdkEvent* createKeyPressEvent(JSContextRef context, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- g_return_val_if_fail(argumentCount >= 1, 0);
- guint modifiers = argumentCount >= 2 ? gdkModifersFromJSValue(context, arguments[1]) : 0;
-
- // handle location argument.
- int location = DOM_KEY_LOCATION_STANDARD;
- if (argumentCount > 2)
- location = (int)JSValueToNumber(context, arguments[2], exception);
-
- JSStringRef character = JSValueToStringCopy(context, arguments[0], exception);
- g_return_val_if_fail((!exception || !*exception), 0);
-
- int gdkKeySym = GDK_VoidSymbol;
- if (location == DOM_KEY_LOCATION_NUMPAD) {
- if (JSStringIsEqualToUTF8CString(character, "leftArrow"))
- gdkKeySym = GDK_KP_Left;
- else if (JSStringIsEqualToUTF8CString(character, "rightArrow"))
- gdkKeySym = GDK_KP_Right;
- else if (JSStringIsEqualToUTF8CString(character, "upArrow"))
- gdkKeySym = GDK_KP_Up;
- else if (JSStringIsEqualToUTF8CString(character, "downArrow"))
- gdkKeySym = GDK_KP_Down;
- else if (JSStringIsEqualToUTF8CString(character, "pageUp"))
- gdkKeySym = GDK_KP_Page_Up;
- else if (JSStringIsEqualToUTF8CString(character, "pageDown"))
- gdkKeySym = GDK_KP_Page_Down;
- else if (JSStringIsEqualToUTF8CString(character, "home"))
- gdkKeySym = GDK_KP_Home;
- else if (JSStringIsEqualToUTF8CString(character, "end"))
- gdkKeySym = GDK_KP_End;
- else if (JSStringIsEqualToUTF8CString(character, "insert"))
- gdkKeySym = GDK_KP_Insert;
- else if (JSStringIsEqualToUTF8CString(character, "delete"))
- gdkKeySym = GDK_KP_Delete;
- else
- // If we get some other key specified with the numpad location,
- // crash here, so we add it sooner rather than later.
- g_assert_not_reached();
- } else {
- if (JSStringIsEqualToUTF8CString(character, "leftArrow"))
- gdkKeySym = GDK_Left;
- else if (JSStringIsEqualToUTF8CString(character, "rightArrow"))
- gdkKeySym = GDK_Right;
- else if (JSStringIsEqualToUTF8CString(character, "upArrow"))
- gdkKeySym = GDK_Up;
- else if (JSStringIsEqualToUTF8CString(character, "downArrow"))
- gdkKeySym = GDK_Down;
- else if (JSStringIsEqualToUTF8CString(character, "pageUp"))
- gdkKeySym = GDK_Page_Up;
- else if (JSStringIsEqualToUTF8CString(character, "pageDown"))
- gdkKeySym = GDK_Page_Down;
- else if (JSStringIsEqualToUTF8CString(character, "home"))
- gdkKeySym = GDK_Home;
- else if (JSStringIsEqualToUTF8CString(character, "end"))
- gdkKeySym = GDK_End;
- else if (JSStringIsEqualToUTF8CString(character, "insert"))
- gdkKeySym = GDK_Insert;
- else if (JSStringIsEqualToUTF8CString(character, "delete"))
- gdkKeySym = GDK_Delete;
- else if (JSStringIsEqualToUTF8CString(character, "printScreen"))
- gdkKeySym = GDK_Print;
- else if (JSStringIsEqualToUTF8CString(character, "menu"))
- gdkKeySym = GDK_Menu;
- else if (JSStringIsEqualToUTF8CString(character, "F1"))
- gdkKeySym = GDK_F1;
- else if (JSStringIsEqualToUTF8CString(character, "F2"))
- gdkKeySym = GDK_F2;
- else if (JSStringIsEqualToUTF8CString(character, "F3"))
- gdkKeySym = GDK_F3;
- else if (JSStringIsEqualToUTF8CString(character, "F4"))
- gdkKeySym = GDK_F4;
- else if (JSStringIsEqualToUTF8CString(character, "F5"))
- gdkKeySym = GDK_F5;
- else if (JSStringIsEqualToUTF8CString(character, "F6"))
- gdkKeySym = GDK_F6;
- else if (JSStringIsEqualToUTF8CString(character, "F7"))
- gdkKeySym = GDK_F7;
- else if (JSStringIsEqualToUTF8CString(character, "F8"))
- gdkKeySym = GDK_F8;
- else if (JSStringIsEqualToUTF8CString(character, "F9"))
- gdkKeySym = GDK_F9;
- else if (JSStringIsEqualToUTF8CString(character, "F10"))
- gdkKeySym = GDK_F10;
- else if (JSStringIsEqualToUTF8CString(character, "F11"))
- gdkKeySym = GDK_F11;
- else if (JSStringIsEqualToUTF8CString(character, "F12"))
- gdkKeySym = GDK_F12;
- else if (JSStringIsEqualToUTF8CString(character, "leftAlt"))
- gdkKeySym = GDK_Alt_L;
- else if (JSStringIsEqualToUTF8CString(character, "leftControl"))
- gdkKeySym = GDK_Control_L;
- else if (JSStringIsEqualToUTF8CString(character, "leftShift"))
- gdkKeySym = GDK_Shift_L;
- else if (JSStringIsEqualToUTF8CString(character, "rightAlt"))
- gdkKeySym = GDK_Alt_R;
- else if (JSStringIsEqualToUTF8CString(character, "rightControl"))
- gdkKeySym = GDK_Control_R;
- else if (JSStringIsEqualToUTF8CString(character, "rightShift"))
- gdkKeySym = GDK_Shift_R;
- else {
- int charCode = JSStringGetCharactersPtr(character)[0];
- if (charCode == '\n' || charCode == '\r')
- gdkKeySym = GDK_Return;
- else if (charCode == '\t')
- gdkKeySym = GDK_Tab;
- else if (charCode == '\x8')
- gdkKeySym = GDK_BackSpace;
- else {
- gdkKeySym = gdk_unicode_to_keyval(charCode);
- if (WTF::isASCIIUpper(charCode))
- modifiers |= GDK_SHIFT_MASK;
- }
- }
- }
- JSStringRelease(character);
-
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- g_return_val_if_fail(view, 0);
-
- GdkEvent* pressEvent = gdk_event_new(GDK_KEY_PRESS);
- pressEvent->key.keyval = gdkKeySym;
- pressEvent->key.state = modifiers;
- pressEvent->key.window = gtk_widget_get_window(GTK_WIDGET(view));
- g_object_ref(pressEvent->key.window);
-#ifndef GTK_API_VERSION_2
- gdk_event_set_device(pressEvent, getDefaultGDKPointerDevice(pressEvent->key.window));
-#endif
-
- // When synthesizing an event, an invalid hardware_keycode value
- // can cause it to be badly processed by Gtk+.
- GUniqueOutPtr<GdkKeymapKey> keys;
- gint nKeys;
- if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), gdkKeySym, &keys.outPtr(), &nKeys))
- pressEvent->key.hardware_keycode = keys.get()[0].keycode;
-
- return pressEvent;
-}
-
-static void sendKeyDown(GdkEvent* pressEvent)
-{
- g_return_if_fail(pressEvent);
- GdkEvent* releaseEvent = gdk_event_copy(pressEvent);
- releaseEvent->type = GDK_KEY_RELEASE;
-
- dispatchEvent(pressEvent);
- dispatchEvent(releaseEvent);
-
- DumpRenderTreeSupportGtk::deliverAllMutationsIfNecessary();
-}
-
-static JSValueRef keyDownCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- GdkEvent* pressEvent = createKeyPressEvent(context, argumentCount, arguments, exception);
- sendKeyDown(pressEvent);
-
- return JSValueMakeUndefined(context);
-}
-
-static void zoomIn(gboolean fullContentsZoom)
-{
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- if (!view)
- return;
-
- webkit_web_view_set_full_content_zoom(view, fullContentsZoom);
- gfloat currentZoom = webkit_web_view_get_zoom_level(view);
- webkit_web_view_set_zoom_level(view, currentZoom * zoomMultiplierRatio);
-}
-
-static void zoomOut(gboolean fullContentsZoom)
-{
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- if (!view)
- return;
-
- webkit_web_view_set_full_content_zoom(view, fullContentsZoom);
- gfloat currentZoom = webkit_web_view_get_zoom_level(view);
- webkit_web_view_set_zoom_level(view, currentZoom / zoomMultiplierRatio);
-}
-
-static JSValueRef textZoomInCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- zoomIn(FALSE);
- return JSValueMakeUndefined(context);
-}
-
-static JSValueRef textZoomOutCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- zoomOut(FALSE);
- return JSValueMakeUndefined(context);
-}
-
-static JSValueRef zoomPageInCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- zoomIn(TRUE);
- return JSValueMakeUndefined(context);
-}
-
-static JSValueRef zoomPageOutCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- zoomOut(TRUE);
- return JSValueMakeUndefined(context);
-}
-
-static JSValueRef scalePageByCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- if (argumentCount < 3)
- return JSValueMakeUndefined(context);
-
- float scaleFactor = JSValueToNumber(context, arguments[0], exception);
- float x = JSValueToNumber(context, arguments[1], exception);
- float y = JSValueToNumber(context, arguments[2], exception);
-
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- if (!view)
- return JSValueMakeUndefined(context);
-
- DumpRenderTreeSupportGtk::scalePageBy(view, scaleFactor, x, y);
-
- return JSValueMakeUndefined(context);
-}
-
-static gboolean sendAsynchronousKeyDown(gpointer userData)
-{
- sendKeyDown(static_cast<GdkEvent*>(userData));
- return FALSE;
-}
-
-static JSValueRef scheduleAsynchronousKeyDownCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- GdkEvent* pressEvent = createKeyPressEvent(context, argumentCount, arguments, exception);
- if (pressEvent)
- g_idle_add_full(G_PRIORITY_DEFAULT, sendAsynchronousKeyDown, static_cast<gpointer>(pressEvent), 0);
-
- return JSValueMakeUndefined(context);
-}
-
-static JSValueRef clearTouchPointsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- return JSValueMakeUndefined(context);
-}
-
-static JSStaticFunction staticFunctions[] = {
- { "mouseScrollBy", mouseScrollByCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "continuousMouseScrollBy", continuousMouseScrollByCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "contextClick", contextClickCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "mouseDown", mouseDownCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "mouseUp", mouseUpCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "mouseMoveTo", mouseMoveToCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "beginDragWithFiles", beginDragWithFilesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "leapForward", leapForwardCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "keyDown", keyDownCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "textZoomIn", textZoomInCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "textZoomOut", textZoomOutCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "zoomPageIn", zoomPageInCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "zoomPageOut", zoomPageOutCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "scheduleAsynchronousClick", scheduleAsynchronousClickCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "scalePageBy", scalePageByCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "scheduleAsynchronousKeyDown", scheduleAsynchronousKeyDownCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
-
- { 0, 0, 0 }
-};
-
-static JSStaticValue staticValues[] = {
- { "dragMode", getDragModeCallback, setDragModeCallback, kJSPropertyAttributeNone },
- { 0, 0, 0, 0 }
-};
-
-static JSClassRef getClass(JSContextRef context)
-{
- static JSClassRef eventSenderClass = 0;
-
- if (!eventSenderClass) {
- JSClassDefinition classDefinition = {
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- classDefinition.staticFunctions = staticFunctions;
- classDefinition.staticValues = staticValues;
-
- eventSenderClass = JSClassCreate(&classDefinition);
- }
-
- return eventSenderClass;
-}
-
-JSObjectRef makeEventSender(JSContextRef context, bool isTopFrame)
-{
- if (isTopFrame) {
- dragMode = true;
-
- // Fly forward in time one second when the main frame loads. This will
- // ensure that when a test begins clicking in the same location as
- // a previous test, those clicks won't be interpreted as continuations
- // of the previous test's click sequences.
- timeOffset += 1000;
-
- lastMousePositionX = lastMousePositionY = 0;
- lastClickPositionX = lastClickPositionY = 0;
- lastClickTimeOffset = 0;
- lastClickButton = 0;
- buttonCurrentlyDown = 0;
- clickCount = 0;
-
- endOfQueue = 0;
- startOfQueue = 0;
-
- currentDragSourceContext = 0;
- }
-
- return JSObjectMake(context, getClass(context), 0);
-}
-
-void dragBeginCallback(GtkWidget*, GdkDragContext* context, gpointer)
-{
- currentDragSourceContext = context;
-}
-
-void dragEndCallback(GtkWidget*, GdkDragContext* context, gpointer)
-{
- currentDragSourceContext = 0;
-}
-
-gboolean dragFailedCallback(GtkWidget*, GdkDragContext* context, gpointer)
-{
- // Return TRUE here to disable the stupid GTK+ drag failed animation,
- // which introduces asynchronous behavior into our drags.
- return TRUE;
-}
diff --git a/Tools/DumpRenderTree/gtk/EventSender.h b/Tools/DumpRenderTree/gtk/EventSender.h
deleted file mode 100644
index f440f0d3d..000000000
--- a/Tools/DumpRenderTree/gtk/EventSender.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
- * Copyright (C) 2009 Holger Hans Peter Freyther
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef EventSender_h
-#define EventSender_h
-
-typedef const struct OpaqueJSContext* JSContextRef;
-typedef struct OpaqueJSValue* JSObjectRef;
-
-JSObjectRef makeEventSender(JSContextRef context, bool isTopFrame);
-void replaySavedEvents();
-void dragBeginCallback(GtkWidget*, GdkDragContext*, gpointer);
-void dragEndCallback(GtkWidget*, GdkDragContext*, gpointer);
-gboolean dragFailedCallback(GtkWidget*, GdkDragContext*, gpointer);
-
-#endif
diff --git a/Tools/DumpRenderTree/gtk/GCControllerGtk.cpp b/Tools/DumpRenderTree/gtk/GCControllerGtk.cpp
deleted file mode 100644
index 4eb5d6ec9..000000000
--- a/Tools/DumpRenderTree/gtk/GCControllerGtk.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "GCController.h"
-
-#include "WebCoreSupport/DumpRenderTreeSupportGtk.h"
-
-#include <glib.h>
-#include <webkit/webkit.h>
-
-void GCController::collect() const
-{
- DumpRenderTreeSupportGtk::gcCollectJavascriptObjects();
-}
-
-void GCController::collectOnAlternateThread(bool waitUntilDone) const
-{
- DumpRenderTreeSupportGtk::gcCollectJavascriptObjectsOnAlternateThread(waitUntilDone);
-}
-
-size_t GCController::getJSObjectCount() const
-{
- return DumpRenderTreeSupportGtk::gcCountJavascriptObjects();
-}
diff --git a/Tools/DumpRenderTree/gtk/PixelDumpSupportGtk.cpp b/Tools/DumpRenderTree/gtk/PixelDumpSupportGtk.cpp
deleted file mode 100644
index 0a800ec13..000000000
--- a/Tools/DumpRenderTree/gtk/PixelDumpSupportGtk.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2009 Zan Dobersek <zandobersek@gmail.com>
- * Copyright (C) 2010 Igalia S.L.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#include "DumpRenderTree.h"
-#include "GtkVersioning.h"
-#include "PixelDumpSupportCairo.h"
-#include "WebCoreSupport/DumpRenderTreeSupportGtk.h"
-#include <webkit/webkit.h>
-
-static void paintOverlay(cairo_surface_t* surface)
-{
- cairo_t* context = cairo_create(surface);
-
- // Paint a transparent black overlay from which the repainted rectangles are then cleared.
- // The alpha component of the overlay should have a value of 0.66, as on other ports.
- cairo_set_source_rgba(context, 0.0, 0.0, 0.0, 0.66);
- cairo_rectangle(context, 0, 0, cairo_image_surface_get_width(surface), cairo_image_surface_get_height(surface));
- cairo_fill(context);
-
- GSList* trackedRectsList = DumpRenderTreeSupportGtk::trackedRepaintRects(mainFrame);
- for (GSList* listElement = trackedRectsList; listElement; listElement = g_slist_next(listElement)) {
- GdkRectangle* rect = static_cast<GdkRectangle*>(listElement->data);
-
- cairo_set_operator(context, CAIRO_OPERATOR_CLEAR);
- cairo_rectangle(context, rect->x, rect->y, rect->width, rect->height);
- cairo_fill(context);
- }
-
- g_slist_free_full(trackedRectsList, g_free);
- cairo_destroy(context);
-}
-
-static void fillRepaintOverlayIntoContext(cairo_t* context, gint width, gint height)
-{
- cairo_surface_t* overlaySurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
- paintOverlay(overlaySurface);
-
- cairo_set_source_surface(context, overlaySurface, 0, 0);
- cairo_rectangle(context, 0, 0, width, height);
- cairo_fill(context);
-
- cairo_surface_destroy(overlaySurface);
-}
-
-PassRefPtr<BitmapContext> createBitmapContextFromWebView(bool, bool, bool, bool drawSelectionRect)
-{
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- GtkWidget* viewContainer = gtk_widget_get_parent(GTK_WIDGET(view));
- gint width, height;
-#ifdef GTK_API_VERSION_2
- GdkPixmap* pixmap = gtk_widget_get_snapshot(viewContainer, 0);
- gdk_pixmap_get_size(pixmap, &width, &height);
-#else
- width = gtk_widget_get_allocated_width(viewContainer);
- height = gtk_widget_get_allocated_height(viewContainer);
-#endif
-
- while (gtk_events_pending())
- gtk_main_iteration();
-
- cairo_surface_t* imageSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
- cairo_t* context = cairo_create(imageSurface);
-
-#ifdef GTK_API_VERSION_2
- gdk_cairo_set_source_pixmap(context, pixmap, 0, 0);
- cairo_paint(context);
- g_object_unref(pixmap);
-#else
- gtk_widget_draw(viewContainer, context);
-#endif
-
- if (DumpRenderTreeSupportGtk::isTrackingRepaints(mainFrame))
- fillRepaintOverlayIntoContext(context, width, height);
-
- if (drawSelectionRect) {
- cairo_rectangle_int_t rectangle;
- DumpRenderTreeSupportGtk::rectangleForSelection(mainFrame, &rectangle);
-
- cairo_set_line_width(context, 1.0);
- cairo_rectangle(context, rectangle.x, rectangle.y, rectangle.width, rectangle.height);
- cairo_set_source_rgba(context, 1.0, 0.0, 0.0, 1.0);
- cairo_stroke(context);
- }
-
- cairo_surface_destroy(imageSurface);
- return BitmapContext::createByAdoptingBitmapAndContext(0, context);
-}
diff --git a/Tools/DumpRenderTree/gtk/SelfScrollingWebKitWebView.cpp b/Tools/DumpRenderTree/gtk/SelfScrollingWebKitWebView.cpp
deleted file mode 100644
index d77cfd5f1..000000000
--- a/Tools/DumpRenderTree/gtk/SelfScrollingWebKitWebView.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2011 Igalia S.L.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "SelfScrollingWebKitWebView.h"
-
-#include <webkit/webkit.h>
-
-G_BEGIN_DECLS
-
-#ifdef GTK_API_VERSION_2
-static void sizeRequestMethod(GtkWidget*, GtkRequisition*);
-#else
-static void getPreferredSizeMethod(GtkWidget*, gint* minimum, gint* natural);
-#endif
-
-G_DEFINE_TYPE(SelfScrollingWebKitWebView, self_scrolling_webkit_web_view, WEBKIT_TYPE_WEB_VIEW)
-
-static void self_scrolling_webkit_web_view_class_init(SelfScrollingWebKitWebViewClass* klass)
-{
- GtkWidgetClass* widgetClass = GTK_WIDGET_CLASS(klass);
-#ifdef GTK_API_VERSION_2
- widgetClass->size_request = sizeRequestMethod;
-#else
- widgetClass->get_preferred_width = getPreferredSizeMethod;
- widgetClass->get_preferred_height = getPreferredSizeMethod;
-#endif
-}
-
-static void self_scrolling_webkit_web_view_init(SelfScrollingWebKitWebView* webView)
-{
-}
-
-GtkWidget* self_scrolling_webkit_web_view_new()
-{
- return GTK_WIDGET(g_object_new(self_scrolling_webkit_web_view_get_type(), "self-scrolling", TRUE, NULL));
-}
-
-#ifdef GTK_API_VERSION_2
-static void sizeRequestMethod(GtkWidget*, GtkRequisition* requisition)
-{
- requisition->width = 1;
- requisition->height = 1;
-}
-#else
-static void getPreferredSizeMethod(GtkWidget*, gint* minimum, gint* natural)
-{
- *minimum = 1;
- *natural = 1;
-}
-#endif
-
-G_END_DECLS
diff --git a/Tools/DumpRenderTree/gtk/SelfScrollingWebKitWebView.h b/Tools/DumpRenderTree/gtk/SelfScrollingWebKitWebView.h
deleted file mode 100644
index 648d38c97..000000000
--- a/Tools/DumpRenderTree/gtk/SelfScrollingWebKitWebView.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2011 Igalia S.L.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef SelfScrollingWebKitWebView_h
-#define SelfScrollingWebKitWebView_h
-
-#include <webkit/webkit.h>
-
-G_BEGIN_DECLS
-
-typedef struct _SelfScrollingWebKitWebView SelfScrollingWebKitWebView;
-typedef struct _SelfScrollingWebKitWebViewClass SelfScrollingWebKitWebViewClass;
-
-struct _SelfScrollingWebKitWebView {
- WebKitWebView web_view;
-};
-
-struct _SelfScrollingWebKitWebViewClass {
- WebKitWebViewClass parent_class;
-};
-
-GtkWidget* self_scrolling_webkit_web_view_new();
-
-G_END_DECLS
-
-#endif // SelfScrollingWebKitWebView_h
diff --git a/Tools/DumpRenderTree/gtk/TestRunnerGtk.cpp b/Tools/DumpRenderTree/gtk/TestRunnerGtk.cpp
deleted file mode 100644
index c0b2deca2..000000000
--- a/Tools/DumpRenderTree/gtk/TestRunnerGtk.cpp
+++ /dev/null
@@ -1,914 +0,0 @@
-/*
- * Copyright (C) 2007, 2012 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
- * Copyright (C) 2008 Nuanti Ltd.
- * Copyright (C) 2009 Jan Michael Alonzo <jmalonzo@gmail.com>
- * Copyright (C) 2009,2011 Collabora Ltd.
- * Copyright (C) 2010 Joone Hur <joone@kldp.org>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "TestRunner.h"
-
-#include "DumpRenderTree.h"
-#include "WebCoreSupport/DumpRenderTreeSupportGtk.h"
-#include "WorkQueue.h"
-#include "WorkQueueItem.h"
-#include <JavaScriptCore/JSRetainPtr.h>
-#include <JavaScriptCore/JSStringRef.h>
-#include <cstring>
-#include <iostream>
-#include <sstream>
-#include <stdio.h>
-#include <glib.h>
-#include <libsoup/soup.h>
-#include <webkit/webkit.h>
-#include <wtf/gobject/GUniquePtr.h>
-#include <wtf/text/WTFString.h>
-
-extern "C" {
-void webkit_web_inspector_execute_script(WebKitWebInspector* inspector, long callId, const gchar* script);
-}
-
-TestRunner::~TestRunner()
-{
- // FIXME: implement
-}
-
-void TestRunner::addDisallowedURL(JSStringRef url)
-{
- // FIXME: implement
-}
-
-void TestRunner::clearBackForwardList()
-{
- WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame);
- WebKitWebBackForwardList* list = webkit_web_view_get_back_forward_list(webView);
- WebKitWebHistoryItem* item = webkit_web_back_forward_list_get_current_item(list);
- g_object_ref(item);
-
- // We clear the history by setting the back/forward list's capacity to 0
- // then restoring it back and adding back the current item.
- gint limit = webkit_web_back_forward_list_get_limit(list);
- webkit_web_back_forward_list_set_limit(list, 0);
- webkit_web_back_forward_list_set_limit(list, limit);
- webkit_web_back_forward_list_add_item(list, item);
- webkit_web_back_forward_list_go_to_item(list, item);
- g_object_unref(item);
-}
-
-JSStringRef TestRunner::copyDecodedHostName(JSStringRef name)
-{
- // FIXME: implement
- return 0;
-}
-
-JSStringRef TestRunner::copyEncodedHostName(JSStringRef name)
-{
- // FIXME: implement
- return 0;
-}
-
-void TestRunner::dispatchPendingLoadRequests()
-{
- // FIXME: Implement for testing fix for 6727495
-}
-
-void TestRunner::display()
-{
- displayWebView();
-}
-
-void TestRunner::keepWebHistory()
-{
- // FIXME: implement
-}
-
-size_t TestRunner::webHistoryItemCount()
-{
- WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame);
- WebKitWebBackForwardList* list = webkit_web_view_get_back_forward_list(webView);
-
- if (!list)
- return -1;
-
- // We do not add the current page to the total count as it's not
- // considered in DRT tests
- return webkit_web_back_forward_list_get_back_length(list) +
- webkit_web_back_forward_list_get_forward_length(list);
-}
-
-void TestRunner::notifyDone()
-{
- if (m_waitToDump && !topLoadingFrame && !WorkQueue::shared()->count())
- dump();
- m_waitToDump = false;
- waitForPolicy = false;
-}
-
-JSStringRef TestRunner::pathToLocalResource(JSContextRef context, JSStringRef url)
-{
- GUniquePtr<char> urlCString(JSStringCopyUTF8CString(url));
- if (!g_str_has_prefix(urlCString.get(), "file:///tmp/LayoutTests/"))
- return JSStringRetain(url);
-
- const char* layoutTestsSuffix = urlCString.get() + strlen("file:///tmp/");
- GUniquePtr<char> testPath(g_build_filename(getTopLevelPath().data(), layoutTestsSuffix, nullptr));
- GUniquePtr<char> testURI(g_filename_to_uri(testPath.get(), 0, 0));
- return JSStringCreateWithUTF8CString(testURI.get());
-}
-
-void TestRunner::queueLoad(JSStringRef url, JSStringRef target)
-{
- GUniquePtr<gchar> relativeURL(JSStringCopyUTF8CString(url));
- SoupURI* baseURI = soup_uri_new(webkit_web_frame_get_uri(mainFrame));
- SoupURI* absoluteURI = soup_uri_new_with_base(baseURI, relativeURL.get());
- soup_uri_free(baseURI);
-
- if (!absoluteURI) {
- WorkQueue::shared()->queue(new LoadItem(url, target));
- return;
- }
-
- CString absoluteURIString = soupURIToStringPreservingPassword(absoluteURI);
- JSRetainPtr<JSStringRef> absoluteURL(Adopt, JSStringCreateWithUTF8CString(absoluteURIString.data()));
- WorkQueue::shared()->queue(new LoadItem(absoluteURL.get(), target));
- soup_uri_free(absoluteURI);
-}
-
-void TestRunner::setAcceptsEditing(bool acceptsEditing)
-{
- WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame);
- webkit_web_view_set_editable(webView, acceptsEditing);
-}
-
-void TestRunner::setAlwaysAcceptCookies(bool alwaysAcceptCookies)
-{
- SoupSession* session = webkit_get_default_session();
- SoupCookieJar* jar = reinterpret_cast<SoupCookieJar*>(soup_session_get_feature(session, SOUP_TYPE_COOKIE_JAR));
-
- /* If the jar was not created - we create it on demand, i.e, just
- in case we have HTTP requests - then we must create it here in
- order to set the proper accept policy */
- if (!jar) {
- jar = soup_cookie_jar_new();
- soup_session_add_feature(session, SOUP_SESSION_FEATURE(jar));
- g_object_unref(jar);
- }
-
- SoupCookieJarAcceptPolicy policy;
-
- if (alwaysAcceptCookies)
- policy = SOUP_COOKIE_JAR_ACCEPT_ALWAYS;
- else
- policy = SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY;
-
- g_object_set(G_OBJECT(jar), SOUP_COOKIE_JAR_ACCEPT_POLICY, policy, NULL);
-}
-
-void TestRunner::setCustomPolicyDelegate(bool setDelegate, bool permissive)
-{
- // FIXME: implement
-}
-
-void TestRunner::waitForPolicyDelegate()
-{
- waitForPolicy = true;
- setWaitToDump(true);
-}
-
-void TestRunner::setScrollbarPolicy(JSStringRef orientation, JSStringRef policy)
-{
- // FIXME: implement
-}
-
-void TestRunner::addOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef protocol, JSStringRef host, bool includeSubdomains)
-{
- gchar* sourceOriginGChar = JSStringCopyUTF8CString(sourceOrigin);
- gchar* protocolGChar = JSStringCopyUTF8CString(protocol);
- gchar* hostGChar = JSStringCopyUTF8CString(host);
- DumpRenderTreeSupportGtk::whiteListAccessFromOrigin(sourceOriginGChar, protocolGChar, hostGChar, includeSubdomains);
- g_free(sourceOriginGChar);
- g_free(protocolGChar);
- g_free(hostGChar);
-}
-
-void TestRunner::removeOriginAccessWhitelistEntry(JSStringRef sourceOrigin, JSStringRef protocol, JSStringRef host, bool includeSubdomains)
-{
- GUniquePtr<gchar> sourceOriginGChar(JSStringCopyUTF8CString(sourceOrigin));
- GUniquePtr<gchar> protocolGChar(JSStringCopyUTF8CString(protocol));
- GUniquePtr<gchar> hostGChar(JSStringCopyUTF8CString(host));
- DumpRenderTreeSupportGtk::removeWhiteListAccessFromOrigin(sourceOriginGChar.get(), protocolGChar.get(), hostGChar.get(), includeSubdomains);
-}
-
-void TestRunner::setMainFrameIsFirstResponder(bool flag)
-{
- // FIXME: implement
-}
-
-void TestRunner::setTabKeyCyclesThroughElements(bool cycles)
-{
- WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame);
- WebKitWebSettings* settings = webkit_web_view_get_settings(webView);
- g_object_set(G_OBJECT(settings), "tab-key-cycles-through-elements", cycles, NULL);
-}
-
-void TestRunner::setUseDashboardCompatibilityMode(bool flag)
-{
- // FIXME: implement
-}
-
-static gchar* userStyleSheet = NULL;
-static gboolean userStyleSheetEnabled = TRUE;
-
-void TestRunner::setUserStyleSheetEnabled(bool flag)
-{
- userStyleSheetEnabled = flag;
-
- WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame);
- WebKitWebSettings* settings = webkit_web_view_get_settings(webView);
- if (flag && userStyleSheet)
- g_object_set(G_OBJECT(settings), "user-stylesheet-uri", userStyleSheet, NULL);
- else
- g_object_set(G_OBJECT(settings), "user-stylesheet-uri", "", NULL);
-}
-
-void TestRunner::setUserStyleSheetLocation(JSStringRef path)
-{
- g_free(userStyleSheet);
- userStyleSheet = JSStringCopyUTF8CString(path);
- if (userStyleSheetEnabled)
- setUserStyleSheetEnabled(true);
-}
-
-void TestRunner::setValueForUser(JSContextRef context, JSValueRef nodeObject, JSStringRef value)
-{
- DumpRenderTreeSupportGtk::setValueForUser(context, nodeObject, value);
-}
-
-void TestRunner::setViewModeMediaFeature(JSStringRef mode)
-{
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- ASSERT(view);
-
- char* viewMode = JSStringCopyUTF8CString(mode);
-
- if (!g_strcmp0(viewMode, "windowed"))
- webkit_web_view_set_view_mode(view, WEBKIT_WEB_VIEW_VIEW_MODE_WINDOWED);
- else if (!g_strcmp0(viewMode, "floating"))
- webkit_web_view_set_view_mode(view, WEBKIT_WEB_VIEW_VIEW_MODE_FLOATING);
- else if (!g_strcmp0(viewMode, "fullscreen"))
- webkit_web_view_set_view_mode(view, WEBKIT_WEB_VIEW_VIEW_MODE_FULLSCREEN);
- else if (!g_strcmp0(viewMode, "maximized"))
- webkit_web_view_set_view_mode(view, WEBKIT_WEB_VIEW_VIEW_MODE_MAXIMIZED);
- else if (!g_strcmp0(viewMode, "minimized"))
- webkit_web_view_set_view_mode(view, WEBKIT_WEB_VIEW_VIEW_MODE_MINIMIZED);
-
- g_free(viewMode);
-}
-
-void TestRunner::setWindowIsKey(bool windowIsKey)
-{
- // FIXME: implement
-}
-
-static gboolean waitToDumpWatchdogFired(void*)
-{
- setWaitToDumpWatchdog(0);
- gTestRunner->waitToDumpWatchdogTimerFired();
- return FALSE;
-}
-
-void TestRunner::setWaitToDump(bool waitUntilDone)
-{
- static const int timeoutSeconds = 30;
-
- m_waitToDump = waitUntilDone;
- if (m_waitToDump && shouldSetWaitToDumpWatchdog()) {
- guint id = g_timeout_add_seconds(timeoutSeconds, waitToDumpWatchdogFired, 0);
- g_source_set_name_by_id(id, "[WebKit] waitToDumpWatchdogFired");
- setWaitToDumpWatchdog(id);
- }
-}
-
-int TestRunner::windowCount()
-{
- // +1 -> including the main view
- return g_slist_length(webViewList) + 1;
-}
-
-void TestRunner::setPrivateBrowsingEnabled(bool flag)
-{
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- ASSERT(view);
-
- WebKitWebSettings* settings = webkit_web_view_get_settings(view);
- g_object_set(G_OBJECT(settings), "enable-private-browsing", flag, NULL);
-}
-
-void TestRunner::setJavaScriptCanAccessClipboard(bool flag)
-{
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- ASSERT(view);
-
- WebKitWebSettings* settings = webkit_web_view_get_settings(view);
- g_object_set(G_OBJECT(settings), "javascript-can-access-clipboard", flag, NULL);
-}
-
-void TestRunner::setXSSAuditorEnabled(bool flag)
-{
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- ASSERT(view);
-
- WebKitWebSettings* settings = webkit_web_view_get_settings(view);
- g_object_set(G_OBJECT(settings), "enable-xss-auditor", flag, NULL);
-}
-
-void TestRunner::setSpatialNavigationEnabled(bool flag)
-{
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- ASSERT(view);
-
- WebKitWebSettings* settings = webkit_web_view_get_settings(view);
- g_object_set(G_OBJECT(settings), "enable-spatial-navigation", flag, NULL);
-}
-
-void TestRunner::setAllowUniversalAccessFromFileURLs(bool flag)
-{
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- ASSERT(view);
-
- WebKitWebSettings* settings = webkit_web_view_get_settings(view);
- g_object_set(G_OBJECT(settings), "enable-universal-access-from-file-uris", flag, NULL);
-}
-
-void TestRunner::setAllowFileAccessFromFileURLs(bool flag)
-{
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- ASSERT(view);
-
- WebKitWebSettings* settings = webkit_web_view_get_settings(view);
- g_object_set(G_OBJECT(settings), "enable-file-access-from-file-uris", flag, NULL);
-}
-
-void TestRunner::setAuthorAndUserStylesEnabled(bool flag)
-{
- // FIXME: implement
-}
-
-void TestRunner::setMockDeviceOrientation(bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma)
-{
- // FIXME: Implement for DeviceOrientation layout tests.
- // See https://bugs.webkit.org/show_bug.cgi?id=30335.
-}
-
-void TestRunner::setMockGeolocationPosition(double latitude, double longitude, double accuracy, bool, double, bool, double, bool, double, bool, double)
-{
- WebKitWebView* view = WEBKIT_WEB_VIEW(g_slist_nth_data(webViewList, 0));
- if (!view)
- view = webkit_web_frame_get_web_view(mainFrame);
- ASSERT(view);
-
- DumpRenderTreeSupportGtk::setMockGeolocationPosition(view, latitude, longitude, accuracy);
-}
-
-void TestRunner::setMockGeolocationPositionUnavailableError(JSStringRef message)
-{
- WebKitWebView* view = WEBKIT_WEB_VIEW(g_slist_nth_data(webViewList, 0));
- if (!view)
- view = webkit_web_frame_get_web_view(mainFrame);
- ASSERT(view);
-
- GUniquePtr<gchar> cMessage(JSStringCopyUTF8CString(message));
- DumpRenderTreeSupportGtk::setMockGeolocationPositionUnavailableError(view, cMessage.get());
-}
-
-void TestRunner::setGeolocationPermission(bool allow)
-{
- setGeolocationPermissionCommon(allow);
- WebKitWebView* view = WEBKIT_WEB_VIEW(g_slist_nth_data(webViewList, 0));
- if (!view)
- view = webkit_web_frame_get_web_view(mainFrame);
- ASSERT(view);
-
- DumpRenderTreeSupportGtk::setMockGeolocationPermission(view, allow);
-}
-
-int TestRunner::numberOfPendingGeolocationPermissionRequests()
-{
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- if (!view)
- view = webkit_web_frame_get_web_view(mainFrame);
- ASSERT(view);
-
- return DumpRenderTreeSupportGtk::numberOfPendingGeolocationPermissionRequests(view);
-}
-
-void TestRunner::addMockSpeechInputResult(JSStringRef result, double confidence, JSStringRef language)
-{
- // FIXME: Implement for speech input layout tests.
- // See https://bugs.webkit.org/show_bug.cgi?id=39485.
-}
-
-void TestRunner::setMockSpeechInputDumpRect(bool flag)
-{
- // FIXME: Implement for speech input layout tests.
- // See https://bugs.webkit.org/show_bug.cgi?id=39485.
-}
-
-void TestRunner::startSpeechInput(JSContextRef inputElement)
-{
- // FIXME: Implement for speech input layout tests.
- // See https://bugs.webkit.org/show_bug.cgi?id=39485.
-}
-
-void TestRunner::setIconDatabaseEnabled(bool enabled)
-{
- WebKitIconDatabase* database = webkit_get_icon_database();
- if (enabled) {
- GUniquePtr<gchar> iconDatabasePath(g_build_filename(g_get_tmp_dir(), "DumpRenderTree", "icondatabase", nullptr));
- webkit_icon_database_set_path(database, iconDatabasePath.get());
- } else
- webkit_icon_database_set_path(database, 0);
-}
-
-void TestRunner::setPopupBlockingEnabled(bool flag)
-{
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- ASSERT(view);
-
- WebKitWebSettings* settings = webkit_web_view_get_settings(view);
- g_object_set(G_OBJECT(settings), "javascript-can-open-windows-automatically", !flag, NULL);
-
-}
-
-void TestRunner::setPluginsEnabled(bool flag)
-{
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- ASSERT(view);
-
- WebKitWebSettings* settings = webkit_web_view_get_settings(view);
- g_object_set(G_OBJECT(settings), "enable-plugins", flag, NULL);
-}
-
-void TestRunner::execCommand(JSStringRef name, JSStringRef value)
-{
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- ASSERT(view);
-
- gchar* cName = JSStringCopyUTF8CString(name);
- gchar* cValue = JSStringCopyUTF8CString(value);
- DumpRenderTreeSupportGtk::executeCoreCommandByName(view, cName, cValue);
- g_free(cName);
- g_free(cValue);
-}
-
-bool TestRunner::findString(JSContextRef context, JSStringRef target, JSObjectRef optionsArray)
-{
- WebKitFindOptions findOptions = 0;
- WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame);
- ASSERT(webView);
-
- JSRetainPtr<JSStringRef> lengthPropertyName(Adopt, JSStringCreateWithUTF8CString("length"));
- JSValueRef lengthValue = JSObjectGetProperty(context, optionsArray, lengthPropertyName.get(), 0);
- if (!JSValueIsNumber(context, lengthValue))
- return false;
-
- GUniquePtr<gchar> targetString(JSStringCopyUTF8CString(target));
-
- size_t length = static_cast<size_t>(JSValueToNumber(context, lengthValue, 0));
- for (size_t i = 0; i < length; ++i) {
- JSValueRef value = JSObjectGetPropertyAtIndex(context, optionsArray, i, 0);
- if (!JSValueIsString(context, value))
- continue;
-
- JSRetainPtr<JSStringRef> optionName(Adopt, JSValueToStringCopy(context, value, 0));
-
- if (JSStringIsEqualToUTF8CString(optionName.get(), "CaseInsensitive"))
- findOptions |= WebKit::WebFindOptionsCaseInsensitive;
- else if (JSStringIsEqualToUTF8CString(optionName.get(), "AtWordStarts"))
- findOptions |= WebKit::WebFindOptionsAtWordStarts;
- else if (JSStringIsEqualToUTF8CString(optionName.get(), "TreatMedialCapitalAsWordStart"))
- findOptions |= WebKit::WebFindOptionsTreatMedialCapitalAsWordStart;
- else if (JSStringIsEqualToUTF8CString(optionName.get(), "Backwards"))
- findOptions |= WebKit::WebFindOptionsBackwards;
- else if (JSStringIsEqualToUTF8CString(optionName.get(), "WrapAround"))
- findOptions |= WebKit::WebFindOptionsWrapAround;
- else if (JSStringIsEqualToUTF8CString(optionName.get(), "StartInSelection"))
- findOptions |= WebKit::WebFindOptionsStartInSelection;
- }
-
- return DumpRenderTreeSupportGtk::findString(webView, targetString.get(), findOptions);
-}
-
-bool TestRunner::isCommandEnabled(JSStringRef name)
-{
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- ASSERT(view);
-
- gchar* cName = JSStringCopyUTF8CString(name);
- bool result = DumpRenderTreeSupportGtk::isCommandEnabled(view, cName);
- g_free(cName);
- return result;
-}
-
-void TestRunner::setCacheModel(int cacheModel)
-{
- // These constants are derived from the Mac cache model enum in Source/WebKit/mac/WebView/WebPreferences.h.
- switch (cacheModel) {
- case 0:
- webkit_set_cache_model(WEBKIT_CACHE_MODEL_DOCUMENT_VIEWER);
- break;
- case 1:
- webkit_set_cache_model(WEBKIT_CACHE_MODEL_DOCUMENT_BROWSER);
- break;
- case 2:
- webkit_set_cache_model(WEBKIT_CACHE_MODEL_WEB_BROWSER);
- break;
- default:
- ASSERT_NOT_REACHED();
- }
-}
-
-void TestRunner::setPersistentUserStyleSheetLocation(JSStringRef jsURL)
-{
- // FIXME: implement
-}
-
-void TestRunner::clearPersistentUserStyleSheet()
-{
- // FIXME: implement
-}
-
-void TestRunner::clearAllApplicationCaches()
-{
- // FIXME: Implement to support application cache quotas.
-}
-
-void TestRunner::clearApplicationCacheForOrigin(OpaqueJSString*)
-{
- // FIXME: Implement to support deleting all application caches for an origin.
-}
-
-long long TestRunner::localStorageDiskUsageForOrigin(JSStringRef originIdentifier)
-{
- // FIXME: Implement to support getting disk usage in bytes for an origin.
- return 0;
-}
-
-JSValueRef TestRunner::originsWithApplicationCache(JSContextRef context)
-{
- // FIXME: Implement to get origins that contain application caches.
- return JSValueMakeUndefined(context);
-}
-
-long long TestRunner::applicationCacheDiskUsageForOrigin(JSStringRef name)
-{
- // FIXME: implement
- return 0;
-}
-
-void TestRunner::clearAllDatabases()
-{
- webkit_remove_all_web_databases();
-}
-
-void TestRunner::setDatabaseQuota(unsigned long long quota)
-{
- WebKitSecurityOrigin* origin = webkit_web_frame_get_security_origin(mainFrame);
- webkit_security_origin_set_web_database_quota(origin, quota);
-}
-
-JSValueRef TestRunner::originsWithLocalStorage(JSContextRef context)
-{
- // FIXME: implement
- return JSValueMakeUndefined(context);
-}
-
-void TestRunner::deleteAllLocalStorage()
-{
- // FIXME: implement
-}
-
-void TestRunner::deleteLocalStorageForOrigin(JSStringRef originIdentifier)
-{
- // FIXME: implement
-}
-
-void TestRunner::observeStorageTrackerNotifications(unsigned number)
-{
- // FIXME: implement
-}
-
-void TestRunner::syncLocalStorage()
-{
- // FIXME: implement
-}
-
-void TestRunner::setDomainRelaxationForbiddenForURLScheme(bool forbidden, JSStringRef scheme)
-{
- GUniquePtr<gchar> urlScheme(JSStringCopyUTF8CString(scheme));
- DumpRenderTreeSupportGtk::setDomainRelaxationForbiddenForURLScheme(forbidden, urlScheme.get());
-}
-
-void TestRunner::goBack()
-{
- WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame);
- webkit_web_view_go_back(webView);
-}
-
-void TestRunner::setDefersLoading(bool defers)
-{
- WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame);
- DumpRenderTreeSupportGtk::setDefersLoading(webView, defers);
-}
-
-void TestRunner::setAppCacheMaximumSize(unsigned long long size)
-{
- webkit_application_cache_set_maximum_size(size);
-}
-
-static gboolean booleanFromValue(gchar* value)
-{
- return !g_ascii_strcasecmp(value, "true") || !g_ascii_strcasecmp(value, "1");
-}
-
-void TestRunner::overridePreference(JSStringRef key, JSStringRef value)
-{
- GUniquePtr<gchar> originalName(JSStringCopyUTF8CString(key));
- GUniquePtr<gchar> valueAsString(JSStringCopyUTF8CString(value));
-
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- ASSERT(view);
-
- // This transformation could be handled by a hash table (and it once was), but
- // having it prominent, makes it easier for people from other ports to keep the
- // list up to date.
- const gchar* propertyName = 0;
- if (g_str_equal(originalName.get(), "WebKitJavaScriptEnabled"))
- propertyName = "enable-scripts";
- else if (g_str_equal(originalName.get(), "WebKitDefaultFontSize"))
- propertyName = "default-font-size";
- else if (g_str_equal(originalName.get(), "WebKitEnableCaretBrowsing"))
- propertyName = "enable-caret-browsing";
- else if (g_str_equal(originalName.get(), "WebKitUsesPageCachePreferenceKey"))
- propertyName = "enable-page-cache";
- else if (g_str_equal(originalName.get(), "WebKitPluginsEnabled"))
- propertyName = "enable-plugins";
- else if (g_str_equal(originalName.get(), "WebKitHyperlinkAuditingEnabled"))
- propertyName = "enable-hyperlink-auditing";
- else if (g_str_equal(originalName.get(), "WebKitWebGLEnabled"))
- propertyName = "enable-webgl";
- else if (g_str_equal(originalName.get(), "WebKitWebAudioEnabled"))
- propertyName = "enable-webaudio";
- else if (g_str_equal(originalName.get(), "WebKitDisplayImagesKey"))
- propertyName = "auto-load-images";
- else if (g_str_equal(originalName.get(), "WebKitShouldRespectImageOrientation"))
- propertyName = "respect-image-orientation";
- else if (g_str_equal(originalName.get(), "WebKitMediaSourceEnabled"))
- propertyName = "enable-mediasource";
- else if (g_str_equal(originalName.get(), "WebKitTabToLinksPreferenceKey")) {
- DumpRenderTreeSupportGtk::setLinksIncludedInFocusChain(booleanFromValue(valueAsString.get()));
- return;
- } else if (g_str_equal(originalName.get(), "WebKitPageCacheSupportsPluginsPreferenceKey")) {
- DumpRenderTreeSupportGtk::setPageCacheSupportsPlugins(webkit_web_frame_get_web_view(mainFrame), booleanFromValue(valueAsString.get()));
- return;
- } else if (g_str_equal(originalName.get(), "WebKitCSSGridLayoutEnabled")) {
- DumpRenderTreeSupportGtk::setCSSGridLayoutEnabled(webkit_web_frame_get_web_view(mainFrame), booleanFromValue(valueAsString.get()));
- return;
- } else if (g_str_equal(originalName.get(), "WebKitCSSRegionsEnabled")) {
- DumpRenderTreeSupportGtk::setCSSRegionsEnabled(webkit_web_frame_get_web_view(mainFrame), booleanFromValue(valueAsString.get()));
- return;
- } else {
- fprintf(stderr, "TestRunner::overridePreference tried to override "
- "unknown preference '%s'.\n", originalName.get());
- return;
- }
-
- WebKitWebSettings* settings = webkit_web_view_get_settings(view);
- GParamSpec* pspec = g_object_class_find_property(G_OBJECT_CLASS(
- WEBKIT_WEB_SETTINGS_GET_CLASS(settings)), propertyName);
- GValue currentPropertyValue = { 0, { { 0 } } };
- g_value_init(&currentPropertyValue, pspec->value_type);
-
- if (G_VALUE_HOLDS_STRING(&currentPropertyValue))
- g_object_set(settings, propertyName, valueAsString.get(), NULL);
- else if (G_VALUE_HOLDS_BOOLEAN(&currentPropertyValue))
- g_object_set(G_OBJECT(settings), propertyName, booleanFromValue(valueAsString.get()), NULL);
- else if (G_VALUE_HOLDS_INT(&currentPropertyValue))
- g_object_set(G_OBJECT(settings), propertyName, atoi(valueAsString.get()), NULL);
- else if (G_VALUE_HOLDS_FLOAT(&currentPropertyValue)) {
- gfloat newValue = g_ascii_strtod(valueAsString.get(), 0);
- g_object_set(G_OBJECT(settings), propertyName, newValue, NULL);
- } else
- fprintf(stderr, "TestRunner::overridePreference failed to override "
- "preference '%s'.\n", originalName.get());
-}
-
-void TestRunner::addUserScript(JSStringRef source, bool runAtStart, bool allFrames)
-{
- GUniquePtr<gchar> sourceCode(JSStringCopyUTF8CString(source));
- DumpRenderTreeSupportGtk::addUserScript(mainFrame, sourceCode.get(), runAtStart, allFrames);
-}
-
-void TestRunner::addUserStyleSheet(JSStringRef source, bool allFrames)
-{
- GUniquePtr<gchar> sourceCode(JSStringCopyUTF8CString(source));
- DumpRenderTreeSupportGtk::addUserStyleSheet(mainFrame, sourceCode.get(), allFrames);
- // FIXME: needs more investigation why userscripts/user-style-top-frame-only.html fails when allFrames is false.
-
-}
-
-void TestRunner::setDeveloperExtrasEnabled(bool enabled)
-{
- WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame);
- WebKitWebSettings* webSettings = webkit_web_view_get_settings(webView);
-
- g_object_set(webSettings, "enable-developer-extras", enabled, NULL);
-}
-
-void TestRunner::showWebInspector()
-{
- WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame);
- WebKitWebInspector* inspector = webkit_web_view_get_inspector(webView);
-
- webkit_web_inspector_show(inspector);
-}
-
-void TestRunner::closeWebInspector()
-{
- WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame);
- WebKitWebInspector* inspector = webkit_web_view_get_inspector(webView);
-
- webkit_web_inspector_close(inspector);
-}
-
-void TestRunner::evaluateInWebInspector(long callId, JSStringRef script)
-{
- WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame);
- WebKitWebInspector* inspector = webkit_web_view_get_inspector(webView);
- char* scriptString = JSStringCopyUTF8CString(script);
-
- webkit_web_inspector_execute_script(inspector, callId, scriptString);
- g_free(scriptString);
-}
-
-void TestRunner::evaluateScriptInIsolatedWorldAndReturnValue(unsigned worldID, JSObjectRef globalObject, JSStringRef script)
-{
- // FIXME: Implement this.
-}
-
-void TestRunner::evaluateScriptInIsolatedWorld(unsigned worldID, JSObjectRef globalObject, JSStringRef script)
-{
- // FIXME: Implement this.
-}
-
-void TestRunner::removeAllVisitedLinks()
-{
- // FIXME: Implement this.
-}
-
-bool TestRunner::callShouldCloseOnWebView()
-{
- return DumpRenderTreeSupportGtk::shouldClose(mainFrame);
-}
-
-void TestRunner::apiTestNewWindowDataLoadBaseURL(JSStringRef utf8Data, JSStringRef baseURL)
-{
-
-}
-
-void TestRunner::apiTestGoToCurrentBackForwardItem()
-{
-
-}
-
-void TestRunner::setWebViewEditable(bool)
-{
-}
-
-void TestRunner::authenticateSession(JSStringRef, JSStringRef, JSStringRef)
-{
-}
-
-void TestRunner::abortModal()
-{
-}
-
-void TestRunner::setSerializeHTTPLoads(bool serialize)
-{
- DumpRenderTreeSupportGtk::setSerializeHTTPLoads(serialize);
-}
-
-void TestRunner::setTextDirection(JSStringRef direction)
-{
- GUniquePtr<gchar> writingDirection(JSStringCopyUTF8CString(direction));
-
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- ASSERT(view);
-
- if (g_str_equal(writingDirection.get(), "auto"))
- gtk_widget_set_direction(GTK_WIDGET(view), GTK_TEXT_DIR_NONE);
- else if (g_str_equal(writingDirection.get(), "ltr"))
- gtk_widget_set_direction(GTK_WIDGET(view), GTK_TEXT_DIR_LTR);
- else if (g_str_equal(writingDirection.get(), "rtl"))
- gtk_widget_set_direction(GTK_WIDGET(view), GTK_TEXT_DIR_RTL);
- else
- fprintf(stderr, "TestRunner::setTextDirection called with unknown direction: '%s'.\n", writingDirection.get());
-}
-
-void TestRunner::addChromeInputField()
-{
-}
-
-void TestRunner::removeChromeInputField()
-{
-}
-
-void TestRunner::focusWebView()
-{
-}
-
-void TestRunner::setBackingScaleFactor(double)
-{
-}
-
-void TestRunner::grantWebNotificationPermission(JSStringRef origin)
-{
-}
-
-void TestRunner::denyWebNotificationPermission(JSStringRef jsOrigin)
-{
-}
-
-void TestRunner::removeAllWebNotificationPermissions()
-{
-}
-
-void TestRunner::simulateWebNotificationClick(JSValueRef jsNotification)
-{
-}
-
-void TestRunner::simulateLegacyWebNotificationClick(JSStringRef title)
-{
-}
-
-void TestRunner::resetPageVisibility()
-{
- WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame);
- DumpRenderTreeSupportGtk::setPageVisibility(webView, WebCore::PageVisibilityStateVisible, true);
-}
-
-void TestRunner::setPageVisibility(const char* visibility)
-{
- WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame);
- String visibilityString(visibility);
- WebCore::PageVisibilityState visibilityState = WebCore::PageVisibilityStateVisible;
-
- if (visibilityString == "visible")
- visibilityState = WebCore::PageVisibilityStateVisible;
- else if (visibilityString == "hidden")
- visibilityState = WebCore::PageVisibilityStateHidden;
- else
- return;
-
- DumpRenderTreeSupportGtk::setPageVisibility(webView, visibilityState, false);
-}
-
-void TestRunner::setAutomaticLinkDetectionEnabled(bool)
-{
- // FIXME: Implement this.
-}
-
-void TestRunner::setStorageDatabaseIdleInterval(double)
-{
- // FIXME: Implement this.
-}
-
-void TestRunner::closeIdleLocalStorageDatabases()
-{
-}
diff --git a/Tools/DumpRenderTree/gtk/TextInputController.cpp b/Tools/DumpRenderTree/gtk/TextInputController.cpp
deleted file mode 100644
index aee5597ed..000000000
--- a/Tools/DumpRenderTree/gtk/TextInputController.cpp
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright (C) 2011 Igalia S.L.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "TextInputController.h"
-
-#include "DumpRenderTree.h"
-#include "WebCoreSupport/DumpRenderTreeSupportGtk.h"
-#include <GUniquePtrGtk.h>
-#include <JavaScriptCore/JSObjectRef.h>
-#include <JavaScriptCore/JSRetainPtr.h>
-#include <JavaScriptCore/JSStringRef.h>
-#include <cstring>
-#include <webkit/webkit.h>
-
-static JSValueRef setMarkedTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- ASSERT(view);
- if (argumentCount < 3)
- return JSValueMakeUndefined(context);
-
- JSStringRef string = JSValueToStringCopy(context, arguments[0], exception);
- ASSERT(!exception || !*exception);
-
- size_t bufferSize = JSStringGetMaximumUTF8CStringSize(string);
- GUniquePtr<gchar> stringBuffer(static_cast<gchar*>(g_malloc(bufferSize)));
- JSStringGetUTF8CString(string, stringBuffer.get(), bufferSize);
- JSStringRelease(string);
-
- int start = static_cast<int>(JSValueToNumber(context, arguments[1], exception));
- ASSERT(!exception || !*exception);
-
- int length = static_cast<int>(JSValueToNumber(context, arguments[2], exception));
- ASSERT(!exception || !*exception);
-
- DumpRenderTreeSupportGtk::setComposition(view, stringBuffer.get(), start, length);
- return JSValueMakeUndefined(context);
-}
-
-static JSValueRef hasMarkedTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- ASSERT(view);
- return JSValueMakeBoolean(context, DumpRenderTreeSupportGtk::hasComposition(view));
-}
-
-static JSValueRef markedRangeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- ASSERT(view);
-
- int start, length;
- if (!DumpRenderTreeSupportGtk::compositionRange(view, &start, &length))
- return JSValueMakeUndefined(context);
-
- JSValueRef arrayValues[2];
- arrayValues[0] = JSValueMakeNumber(context, start);
- arrayValues[1] = JSValueMakeNumber(context, length);
- JSObjectRef arrayObject = JSObjectMakeArray(context, 2, arrayValues, exception);
- ASSERT(!exception || !*exception);
- return arrayObject;
-}
-
-static JSValueRef insertTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- ASSERT(view);
-
- if (argumentCount < 1)
- return JSValueMakeUndefined(context);
-
- JSStringRef string = JSValueToStringCopy(context, arguments[0], exception);
- ASSERT(!exception || !*exception);
-
- size_t bufferSize = JSStringGetMaximumUTF8CStringSize(string);
- GUniquePtr<gchar> stringBuffer(static_cast<gchar*>(g_malloc(bufferSize)));
- JSStringGetUTF8CString(string, stringBuffer.get(), bufferSize);
- JSStringRelease(string);
-
- DumpRenderTreeSupportGtk::confirmComposition(view, stringBuffer.get());
- return JSValueMakeUndefined(context);
-}
-
-static JSValueRef unmarkTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- ASSERT(view);
-
- DumpRenderTreeSupportGtk::confirmComposition(view, 0);
- return JSValueMakeUndefined(context);
-}
-
-static JSValueRef firstRectForCharacterRangeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- ASSERT(view);
- if (argumentCount < 2)
- return JSValueMakeUndefined(context);
-
- int location = static_cast<int>(JSValueToNumber(context, arguments[0], exception));
- ASSERT(!exception || !*exception);
-
- int length = static_cast<int>(JSValueToNumber(context, arguments[1], exception));
- ASSERT(!exception || !*exception);
-
- cairo_rectangle_int_t rect;
- if (!DumpRenderTreeSupportGtk::firstRectForCharacterRange(view, location, length, &rect))
- return JSValueMakeUndefined(context);
-
- JSValueRef arrayValues[4];
- arrayValues[0] = JSValueMakeNumber(context, rect.x);
- arrayValues[1] = JSValueMakeNumber(context, rect.y);
- arrayValues[2] = JSValueMakeNumber(context, rect.width);
- arrayValues[3] = JSValueMakeNumber(context, rect.height);
- JSObjectRef arrayObject = JSObjectMakeArray(context, 4, arrayValues, exception);
- ASSERT(!exception || !*exception);
-
- return arrayObject;
-}
-
-static JSValueRef selectedRangeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- ASSERT(view);
-
- int start, length;
- if (!DumpRenderTreeSupportGtk::selectedRange(view, &start, &length))
- return JSValueMakeUndefined(context);
-
- JSValueRef arrayValues[2];
- arrayValues[0] = JSValueMakeNumber(context, start);
- arrayValues[1] = JSValueMakeNumber(context, length);
- JSObjectRef arrayObject = JSObjectMakeArray(context, 2, arrayValues, exception);
- ASSERT(!exception || !*exception);
-
- return arrayObject;
-}
-
-static JSValueRef doCommandCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
- ASSERT(view);
- if (argumentCount < 1)
- return JSValueMakeUndefined(context);
-
- JSStringRef string = JSValueToStringCopy(context, arguments[0], exception);
- ASSERT(!exception || !*exception);
-
- size_t bufferSize = JSStringGetMaximumUTF8CStringSize(string);
- GUniquePtr<gchar> stringBuffer(static_cast<gchar*>(g_malloc(bufferSize)));
- JSStringGetUTF8CString(string, stringBuffer.get(), bufferSize);
- JSStringRelease(string);
-
- DumpRenderTreeSupportGtk::doCommand(view, stringBuffer.get());
- return JSValueMakeUndefined(context);
-}
-
-static JSStaticFunction staticFunctions[] = {
- { "setMarkedText", setMarkedTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "hasMarkedText", hasMarkedTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "markedRange", markedRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "insertText", insertTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "unmarkText", unmarkTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "firstRectForCharacterRange", firstRectForCharacterRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "selectedRange", selectedRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "doCommand", doCommandCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { 0, 0, 0 }
-};
-
-static JSClassRef getClass(JSContextRef context)
-{
- static JSClassRef textInputControllerClass = 0;
-
- if (!textInputControllerClass) {
- JSClassDefinition classDefinition = {
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- classDefinition.staticFunctions = staticFunctions;
-
- textInputControllerClass = JSClassCreate(&classDefinition);
- }
-
- return textInputControllerClass;
-}
-
-JSObjectRef makeTextInputController(JSContextRef context)
-{
- return JSObjectMake(context, getClass(context), 0);
-}
diff --git a/Tools/DumpRenderTree/gtk/WorkQueueItemGtk.cpp b/Tools/DumpRenderTree/gtk/WorkQueueItemGtk.cpp
deleted file mode 100644
index 95461276e..000000000
--- a/Tools/DumpRenderTree/gtk/WorkQueueItemGtk.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2007 Alp Toker <alp@atoker.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "WorkQueueItem.h"
-
-#include "DumpRenderTree.h"
-
-#include <JavaScriptCore/JSStringRef.h>
-#include <string.h>
-#include <webkit/webkit.h>
-#include <wtf/gobject/GUniquePtr.h>
-
-// Returns a newly allocated UTF-8 character buffer which must be freed with g_free()
-gchar* JSStringCopyUTF8CString(JSStringRef jsString)
-{
- size_t dataSize = JSStringGetMaximumUTF8CStringSize(jsString);
- gchar* utf8 = (gchar*)g_malloc(dataSize);
- JSStringGetUTF8CString(jsString, utf8, dataSize);
-
- return utf8;
-}
-
-bool LoadItem::invoke() const
-{
- gchar* targetString = JSStringCopyUTF8CString(m_target.get());
-
- WebKitWebFrame* targetFrame;
- if (!strlen(targetString))
- targetFrame = mainFrame;
- else
- targetFrame = webkit_web_frame_find_frame(mainFrame, targetString);
- g_free(targetString);
-
- gchar* urlString = JSStringCopyUTF8CString(m_url.get());
- WebKitNetworkRequest* request = webkit_network_request_new(urlString);
- g_free(urlString);
- webkit_web_frame_load_request(targetFrame, request);
- g_object_unref(request);
-
- return true;
-}
-
-bool LoadHTMLStringItem::invoke() const
-{
- GUniquePtr<gchar> content(JSStringCopyUTF8CString(m_content.get()));
- GUniquePtr<gchar> baseURL(JSStringCopyUTF8CString(m_baseURL.get()));
-
- if (m_unreachableURL) {
- GUniquePtr<gchar> unreachableURL(JSStringCopyUTF8CString(m_unreachableURL.get()));
- webkit_web_frame_load_alternate_string(mainFrame, content.get(), baseURL.get(), unreachableURL.get());
- return true;
- }
- webkit_web_frame_load_string(mainFrame, content.get(), 0, 0, baseURL.get());
- return true;
-}
-
-bool ReloadItem::invoke() const
-{
- webkit_web_frame_reload(mainFrame);
- return true;
-}
-
-bool ScriptItem::invoke() const
-{
- WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame);
- gchar* scriptString = JSStringCopyUTF8CString(m_script.get());
- webkit_web_view_execute_script(webView, scriptString);
- g_free(scriptString);
- return true;
-}
-
-bool BackForwardItem::invoke() const
-{
- WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame);
- if (m_howFar == 1)
- webkit_web_view_go_forward(webView);
- else if (m_howFar == -1)
- webkit_web_view_go_back(webView);
- else {
- WebKitWebBackForwardList* webBackForwardList = webkit_web_view_get_back_forward_list(webView);
- WebKitWebHistoryItem* item = webkit_web_back_forward_list_get_nth_item(webBackForwardList, m_howFar);
- webkit_web_view_go_to_back_forward_item(webView, item);
- }
- return true;
-}
diff --git a/Tools/GNUmakefile.am b/Tools/GNUmakefile.am
deleted file mode 100644
index 115e09bfc..000000000
--- a/Tools/GNUmakefile.am
+++ /dev/null
@@ -1,277 +0,0 @@
-noinst_PROGRAMS += \
- Programs/ImageDiff
-
-if ENABLE_WEBKIT1
-noinst_PROGRAMS += \
- Programs/DumpRenderTree
-endif
-
-# libWebCoreInternals
-# We must split off the window.internals implementation into a separate
-# convenience library because it requires a different include path order
-# to prefer the WebCore config.h over the DumpRenderTree config.h
-noinst_LTLIBRARIES += libWebCoreInternals.la
-libWebCoreInternals_la_SOURCES = \
- Source/WebCore/bindings/js/JSDOMWrapper.cpp \
- Source/WebCore/bindings/js/JSDOMWrapper.h \
- Source/WebCore/testing/MallocStatistics.h \
- Source/WebCore/testing/MemoryInfo.h \
- Source/WebCore/testing/Internals.cpp \
- Source/WebCore/testing/Internals.h \
- Source/WebCore/testing/InternalSettings.cpp \
- Source/WebCore/testing/InternalSettings.h \
- Source/WebCore/testing/TypeConversions.h \
- Source/WebCore/testing/js/WebCoreTestSupport.cpp \
- Source/WebCore/testing/js/WebCoreTestSupport.h
-
-libwebcoreinternals_built_sources += \
- DerivedSources/WebCore/InternalSettingsGenerated.cpp \
- DerivedSources/WebCore/InternalSettingsGenerated.h \
- DerivedSources/WebCore/JSMallocStatistics.cpp \
- DerivedSources/WebCore/JSMallocStatistics.h \
- DerivedSources/WebCore/JSMemoryInfo.cpp \
- DerivedSources/WebCore/JSMemoryInfo.h \
- DerivedSources/WebCore/JSInternals.cpp \
- DerivedSources/WebCore/JSInternals.h \
- DerivedSources/WebCore/JSInternalSettings.cpp \
- DerivedSources/WebCore/JSInternalSettings.h \
- DerivedSources/WebCore/JSInternalSettingsGenerated.cpp \
- DerivedSources/WebCore/JSInternalSettingsGenerated.h \
- DerivedSources/WebCore/JSTypeConversions.cpp \
- DerivedSources/WebCore/JSTypeConversions.h
-
-nodist_libWebCoreInternals_la_SOURCES = $(libwebcoreinternals_built_sources)
-BUILT_SOURCES += $(libwebcoreinternals_built_sources)
-
-libWebCoreInternals_la_CPPFLAGS = \
- $(global_cppflags) \
- $(platform_cppflags) \
- $(platformgtk_cppflags) \
- $(webcore_cppflags) \
- $(webcoregtk_cppflags) \
- $(javascriptcore_cppflags) \
- $(CAIRO_CFLAGS) \
- $(FREETYPE_CFLAGS) \
- $(LIBSOUP_CFLAGS) \
- $(PANGO_CFLAGS) \
- -I$(top_builddir)/DerivedSources \
- -I$(top_builddir)/DerivedSources/WebCore
-
-libWebCoreInternals_la_CXXFLAGS = \
- $(global_cxxflags) \
- $(libWebCoreInternals_la_CFLAGS)
-
-libWebCoreInternals_la_CFLAGS = \
- -fno-strict-aliasing \
- $(javascriptcore_cflags)
-
-# DumpRenderTree
-Programs_DumpRenderTree_CPPFLAGS = \
- $(global_cppflags) \
- -DTOP_LEVEL_DIR=\"${shell pwd}/${srcdir}\" \
- -I$(srcdir)/Tools/DumpRenderTree \
- -I$(srcdir)/Tools/DumpRenderTree/atk \
- -I$(srcdir)/Tools/DumpRenderTree/cairo \
- -I$(srcdir)/Tools/DumpRenderTree/gtk \
- -I$(srcdir)/Source/WebKit/gtk \
- -I$(srcdir)/Source/WebCore/platform/gtk \
- -I$(srcdir)/Source/WebCore/testing/js \
- -I$(top_builddir)/DerivedSources \
- -I$(top_builddir)/Source/WebKit/gtk \
- $(javascriptcore_cppflags) \
- $(platform_cppflags) \
- $(platformgtk_cppflags) \
- $(webcore_cppflags)
-
-if TARGET_X11_OR_WAYLAND
-Programs_DumpRenderTree_CPPFLAGS += \
- -DTEST_PLUGIN_DIR=\"${shell pwd}/${top_builddir}/TestNetscapePlugin/.libs\" \
- -DFONTS_CONF_DIR=\"${shell pwd}/${srcdir}/Tools/DumpRenderTree/gtk/fonts\"
-endif
-
-Programs_DumpRenderTree_SOURCES = \
- Source/WebCore/platform/gtk/GtkVersioning.c \
- Tools/DumpRenderTree/DumpRenderTree.h \
- Tools/DumpRenderTree/DumpRenderTreeCommon.cpp \
- Tools/DumpRenderTree/DumpRenderTreePrefix.h \
- Tools/DumpRenderTree/AccessibilityController.cpp \
- Tools/DumpRenderTree/AccessibilityController.h \
- Tools/DumpRenderTree/AccessibilityTextMarker.cpp \
- Tools/DumpRenderTree/AccessibilityTextMarker.h \
- Tools/DumpRenderTree/AccessibilityUIElement.cpp \
- Tools/DumpRenderTree/AccessibilityUIElement.h \
- Tools/DumpRenderTree/CyclicRedundancyCheck.cpp \
- Tools/DumpRenderTree/CyclicRedundancyCheck.h \
- Tools/DumpRenderTree/GCController.cpp \
- Tools/DumpRenderTree/GCController.h \
- Tools/DumpRenderTree/JavaScriptThreading.h \
- Tools/DumpRenderTree/TestRunner.cpp \
- Tools/DumpRenderTree/TestRunner.h \
- Tools/DumpRenderTree/PixelDumpSupport.cpp \
- Tools/DumpRenderTree/PixelDumpSupport.h \
- Tools/DumpRenderTree/WorkQueue.cpp \
- Tools/DumpRenderTree/WorkQueue.h \
- Tools/DumpRenderTree/WorkQueueItem.h \
- Tools/DumpRenderTree/config.h \
- Tools/DumpRenderTree/atk/AccessibilityCallbacks.h \
- Tools/DumpRenderTree/atk/AccessibilityCallbacksAtk.cpp \
- Tools/DumpRenderTree/atk/AccessibilityControllerAtk.cpp \
- Tools/DumpRenderTree/atk/AccessibilityNotificationHandlerAtk.cpp \
- Tools/DumpRenderTree/atk/AccessibilityNotificationHandlerAtk.h \
- Tools/DumpRenderTree/atk/AccessibilityUIElementAtk.cpp \
- Tools/DumpRenderTree/cairo/PixelDumpSupportCairo.cpp \
- Tools/DumpRenderTree/cairo/PixelDumpSupportCairo.h \
- Tools/DumpRenderTree/gtk/AccessibilityControllerGtk.cpp \
- Tools/DumpRenderTree/gtk/DumpRenderTree.cpp \
- Tools/DumpRenderTree/gtk/DumpRenderTreeGtk.h \
- Tools/DumpRenderTree/gtk/EditingCallbacks.h \
- Tools/DumpRenderTree/gtk/EditingCallbacks.cpp \
- Tools/DumpRenderTree/gtk/EventSender.h \
- Tools/DumpRenderTree/gtk/EventSender.cpp \
- Tools/DumpRenderTree/gtk/GCControllerGtk.cpp \
- Tools/DumpRenderTree/gtk/TestRunnerGtk.cpp \
- Tools/DumpRenderTree/gtk/PixelDumpSupportGtk.cpp \
- Tools/DumpRenderTree/gtk/SelfScrollingWebKitWebView.cpp \
- Tools/DumpRenderTree/gtk/SelfScrollingWebKitWebView.h \
- Tools/DumpRenderTree/gtk/TextInputController.h \
- Tools/DumpRenderTree/gtk/TextInputController.cpp \
- Tools/DumpRenderTree/gtk/WorkQueueItemGtk.cpp
-
-Programs_DumpRenderTree_CXXFLAGS = \
- $(global_cxxflags) \
- $(Programs_DumpRenderTree_CFLAGS)
-
-Programs_DumpRenderTree_CFLAGS = \
- -fno-strict-aliasing \
- $(global_cflags) \
- $(CAIRO_CFLAGS) \
- $(GTK_CFLAGS) \
- $(LIBSOUP_CFLAGS)
-
-Programs_DumpRenderTree_LDADD = \
- libjavascriptcoregtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \
- libwebkitgtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \
- libPlatform.la \
- libPlatformGtk.la \
- libWebCorePlatform.la \
- libWebCoreModules.la \
- libWebCoreInternals.la \
- $(CAIRO_LIBS) \
- $(GTK_LIBS) \
- $(GLIB_LIBS) \
- $(LIBSOUP_LIBS) \
- $(FREETYPE_LIBS) \
- $(WINMM_LIBS) \
- $(XRENDER_LIBS) \
- $(XT_LIBS)
-
-Programs_DumpRenderTree_LDFLAGS = \
- -no-install
-
-# ImageDiff
-Programs_ImageDiff_CPPFLAGS = $(global_cppflags)
-
-Programs_ImageDiff_SOURCES = \
- Tools/ImageDiff/gtk/ImageDiff.cpp
-
-Programs_ImageDiff_CXXFLAGS = \
- $(global_cxxflags) \
- $(global_cppflags) \
- $(Programs_ImageDiff_CFLAGS)
-
-Programs_ImageDiff_CFLAGS = \
- -fno-strict-aliasing \
- $(global_cflags) \
- $(GTK_CFLAGS)
-
-Programs_ImageDiff_LDADD = \
- $(GTK_LIBS)
-
-Programs_ImageDiff_LDFLAGS = \
- -no-install
-
-# clean target
-CLEANFILES += \
- Programs/DumpRenderTree \
- Programs/GtkLauncher \
- Programs/ImageDiff
-
-if TARGET_X11
-
-# Build TestNetscapePlugin only for X11
-# since we don't support plugins for non-X11 builds at the moment.
-noinst_LTLIBRARIES += \
- TestNetscapePlugin/libTestNetscapePlugin.la
-
-TestNetscapePlugin_libTestNetscapePlugin_la_CPPFLAGS = \
- -I$(srcdir)/Tools/DumpRenderTree \
- -I$(srcdir)/Source/WebCore \
- -I$(srcdir)/Source/WebCore/bridge \
- -I$(srcdir)/Source/WebCore/plugins \
- -I$(srcdir)/Tools/DumpRenderTree/TestNetscapePlugIn \
- -I$(srcdir)/Tools/DumpRenderTree/TestNetscapePlugIn/unix/ForwardingHeaders \
- $(global_cppflags) \
- $(javascriptcore_cppflags) \
- -Wno-missing-format-attribute
-
-# For the Gtk port we want to use XP_UNIX both on X11 and Mac
-if !TARGET_WIN32
-TestNetscapePlugin_libTestNetscapePlugin_la_CPPFLAGS += -DXP_UNIX
-endif
-
-# Add MOZ_X11 only for X11 targets
-if TARGET_X11
-TestNetscapePlugin_libTestNetscapePlugin_la_CPPFLAGS += -DMOZ_X11
-endif
-
-TestNetscapePlugin_libTestNetscapePlugin_la_SOURCES = \
- Tools/DumpRenderTree/TestNetscapePlugIn/Tests/DocumentOpenInDestroyStream.cpp \
- Tools/DumpRenderTree/TestNetscapePlugIn/Tests/EvaluateJSAfterRemovingPluginElement.cpp \
- Tools/DumpRenderTree/TestNetscapePlugIn/Tests/FormValue.cpp \
- Tools/DumpRenderTree/TestNetscapePlugIn/Tests/GetURLNotifyWithURLThatFailsToLoad.cpp \
- Tools/DumpRenderTree/TestNetscapePlugIn/Tests/GetURLWithJavaScriptURL.cpp \
- Tools/DumpRenderTree/TestNetscapePlugIn/Tests/GetURLWithJavaScriptURLDestroyingPlugin.cpp \
- Tools/DumpRenderTree/TestNetscapePlugIn/Tests/GetUserAgentWithNullNPPFromNPPNew.cpp \
- Tools/DumpRenderTree/TestNetscapePlugIn/Tests/LogNPPSetWindow.cpp \
- Tools/DumpRenderTree/TestNetscapePlugIn/Tests/NPDeallocateCalledBeforeNPShutdown.cpp \
- Tools/DumpRenderTree/TestNetscapePlugIn/Tests/NPPNewFails.cpp \
- Tools/DumpRenderTree/TestNetscapePlugIn/Tests/NPPSetWindowCalledDuringDestruction.cpp \
- Tools/DumpRenderTree/TestNetscapePlugIn/Tests/NPRuntimeCallsWithNullNPP.cpp \
- Tools/DumpRenderTree/TestNetscapePlugIn/Tests/NPRuntimeObjectFromDestroyedPlugin.cpp \
- Tools/DumpRenderTree/TestNetscapePlugIn/Tests/NPRuntimeRemoveProperty.cpp \
- Tools/DumpRenderTree/TestNetscapePlugIn/Tests/NullNPPGetValuePointer.cpp \
- Tools/DumpRenderTree/TestNetscapePlugIn/Tests/PassDifferentNPPStruct.cpp \
- Tools/DumpRenderTree/TestNetscapePlugIn/Tests/PluginScriptableNPObjectInvokeDefault.cpp \
- Tools/DumpRenderTree/TestNetscapePlugIn/Tests/PrivateBrowsing.cpp \
- Tools/DumpRenderTree/TestNetscapePlugIn/Tests/ToStringAndValueOfObject.cpp \
- Tools/DumpRenderTree/TestNetscapePlugIn/Tests/x11/CallInvalidateRectWithNullNPPArgument.cpp \
- Tools/DumpRenderTree/TestNetscapePlugIn/PluginTest.cpp \
- Tools/DumpRenderTree/TestNetscapePlugIn/PluginTest.h \
- Tools/DumpRenderTree/TestNetscapePlugIn/PluginObject.cpp \
- Tools/DumpRenderTree/TestNetscapePlugIn/PluginObject.h \
- Tools/DumpRenderTree/TestNetscapePlugIn/TestObject.cpp \
- Tools/DumpRenderTree/TestNetscapePlugIn/TestObject.h \
- Tools/DumpRenderTree/TestNetscapePlugIn/main.cpp \
- Tools/DumpRenderTree/TestNetscapePlugIn/unix/ForwardingHeaders/WebKit/npapi.h \
- Tools/DumpRenderTree/TestNetscapePlugIn/unix/ForwardingHeaders/WebKit/npfunctions.h \
- Tools/DumpRenderTree/TestNetscapePlugIn/unix/ForwardingHeaders/WebKit/npruntime.h
-
-TestNetscapePlugin_libTestNetscapePlugin_la_LDFLAGS = \
- -rpath ${shell pwd}/$(top_builddir)/../unix/TestNetscapePlugin/.libs \
- $(no_undefined) \
- -avoid-version \
- -module
-
-CLEANFILES += TestNetscapePlugin/libTestNetscapePlugin.la
-endif
-
-check-local:
- $(top_srcdir)/Tools/Scripts/run-gtk-tests --timeout=-1
- $(top_srcdir)/Tools/gtk/check-for-webkitdom-api-breaks
-
-EXTRA_DIST += \
- Tools/jhbuild/jhbuildutils.py \
- Tools/Scripts/VCSUtils.pm \
- Tools/Scripts/run-gtk-tests \
- Tools/Scripts/webkit-build-directory \
- Tools/Scripts/webkitdirs.pm
diff --git a/Tools/GtkLauncher/GNUmakefile.am b/Tools/GtkLauncher/GNUmakefile.am
deleted file mode 100644
index 31ca2fba9..000000000
--- a/Tools/GtkLauncher/GNUmakefile.am
+++ /dev/null
@@ -1,42 +0,0 @@
-if ENABLE_WEBKIT1
-noinst_PROGRAMS += \
- Programs/GtkLauncher
-endif
-
-# GtkLauncher
-Programs_GtkLauncher_CPPFLAGS = \
- -I$(srcdir)/Source/WebKit/gtk \
- -I$(srcdir)/Source/WebCore/platform/network/soup/cache/ \
- -I$(top_builddir)/Source/WebKit/gtk \
- -I$(top_builddir)/DerivedSources \
- -DWEBKIT_EXEC_PATH=\"${shell pwd}/$(top_builddir)/Programs/\" \
- $(global_cppflags) \
- $(javascriptcore_cppflags)
-
-Programs_GtkLauncher_SOURCES = \
- Tools/GtkLauncher/LauncherInspectorWindow.c \
- Tools/GtkLauncher/LauncherInspectorWindow.h \
- Tools/GtkLauncher/main.c
-
-Programs_GtkLauncher_CFLAGS = \
- -ansi \
- -fno-strict-aliasing \
- $(global_cflags) \
- $(FREETYPE_CFLAGS) \
- $(GTK_CFLAGS) \
- $(LIBSOUP_CFLAGS) \
- $(GSTREAMER_CFLAGS)
-
-Programs_GtkLauncher_LDADD = \
- libwebkitgtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \
- libjavascriptcoregtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \
- $(FREETYPE_LIBS) \
- $(GTK_LIBS) \
- $(GLIB_LIBS) \
- $(LIBSOUP_LIBS) \
- $(WINMM_LIBS) \
- $(GSTREAMER_LIBS)
-
-Programs_GtkLauncher_LDFLAGS = \
- -no-install
-
diff --git a/Tools/GtkLauncher/LauncherInspectorWindow.c b/Tools/GtkLauncher/LauncherInspectorWindow.c
deleted file mode 100644
index 8ee9fcfb4..000000000
--- a/Tools/GtkLauncher/LauncherInspectorWindow.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2012 Igalia S.L.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 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 "LauncherInspectorWindow.h"
-
-struct _LauncherInspectorWindow {
- GtkWindow parent;
-
- WebKitWebInspector *inspector;
- GtkWidget *webView;
-};
-
-struct _LauncherInspectorWindowClass {
- GtkWindowClass parent;
-};
-
-G_DEFINE_TYPE(LauncherInspectorWindow, launcher_inspector_window, GTK_TYPE_WINDOW)
-
-static void launcherInspectorWindowFinalize(GObject *gObject)
-{
- LauncherInspectorWindow *inspectorWindow = LAUNCHER_INSPECTOR_WINDOW(gObject);
- if (inspectorWindow->inspector)
- g_object_unref(inspectorWindow->inspector);
-
- G_OBJECT_CLASS(launcher_inspector_window_parent_class)->finalize(gObject);
-}
-
-static void launcher_inspector_window_init(LauncherInspectorWindow *inspectorWindow)
-{
- gtk_window_set_title(GTK_WINDOW(inspectorWindow), "Web Inspector");
- gtk_window_set_default_size(GTK_WINDOW(inspectorWindow), 800, 600);
-}
-
-static void launcher_inspector_window_class_init(LauncherInspectorWindowClass *klass)
-{
- GObjectClass *gobjectClass = G_OBJECT_CLASS(klass);
- gobjectClass->finalize = launcherInspectorWindowFinalize;
-}
-
-static void inspectedURIChanged(WebKitWebInspector *inspector, GParamSpec *paramSpec, LauncherInspectorWindow *inspectorWindow)
-{
- gchar *title = g_strdup_printf("Web Inspector - %s", webkit_web_inspector_get_inspected_uri(inspector));
- gtk_window_set_title(GTK_WINDOW(inspectorWindow), title);
- g_free(title);
-}
-
-static gboolean showInspectorWindow(WebKitWebInspector *inspector, LauncherInspectorWindow *inspectorWindow)
-{
- gtk_widget_show(GTK_WIDGET(inspectorWindow));
- return TRUE;
-}
-
-static gboolean closeInspectorWindow(WebKitWebInspector *inspector, LauncherInspectorWindow *inspectorWindow)
-{
- gtk_widget_hide(GTK_WIDGET(inspectorWindow));
- return TRUE;
-}
-
-static void inspectorWindowDestroyed(gpointer inspector, GObject* inspectorWindow)
-{
- g_signal_handlers_disconnect_by_data(inspector, inspectorWindow);
-}
-
-GtkWidget *launcherInspectorWindowNew(WebKitWebInspector *inspector, GtkWindow *parent)
-{
- LauncherInspectorWindow *inspectorWindow = LAUNCHER_INSPECTOR_WINDOW(g_object_new(LAUNCHER_TYPE_INSPECTOR_WINDOW, "type", GTK_WINDOW_TOPLEVEL, NULL));
- inspectorWindow->inspector = g_object_ref(inspector);
- inspectorWindow->webView = webkit_web_view_new();
- gtk_window_set_transient_for(GTK_WINDOW(inspectorWindow), parent);
-
- GtkWidget *scrolledWindow = gtk_scrolled_window_new(NULL, NULL);
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledWindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- gtk_container_add(GTK_CONTAINER(scrolledWindow), inspectorWindow->webView);
- gtk_widget_show(inspectorWindow->webView);
-
- gtk_container_add(GTK_CONTAINER(inspectorWindow), scrolledWindow);
- gtk_widget_show(scrolledWindow);
-
- g_signal_connect(inspector, "notify::inspected-uri", G_CALLBACK(inspectedURIChanged), inspectorWindow);
- g_signal_connect(inspector, "show-window", G_CALLBACK(showInspectorWindow), inspectorWindow);
- g_signal_connect(inspector, "close-window", G_CALLBACK(closeInspectorWindow), inspectorWindow);
-
- g_object_weak_ref(G_OBJECT(inspectorWindow), inspectorWindowDestroyed, inspector);
-
- return GTK_WIDGET(inspectorWindow);
-}
-
-WebKitWebView *launcherInspectorWindowGetWebView(LauncherInspectorWindow *inspectorWindow)
-{
- g_return_val_if_fail(LAUNCHER_IS_INSPECTOR_WINDOW(inspectorWindow), 0);
-
- return WEBKIT_WEB_VIEW(inspectorWindow->webView);
-}
diff --git a/Tools/GtkLauncher/main.c b/Tools/GtkLauncher/main.c
deleted file mode 100644
index c1b74814a..000000000
--- a/Tools/GtkLauncher/main.c
+++ /dev/null
@@ -1,564 +0,0 @@
-/*
- * Copyright (C) 2006, 2007 Apple Inc.
- * Copyright (C) 2007 Alp Toker <alp@atoker.com>
- * Copyright (C) 2011 Lukasz Slachciak
- *
- * 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 COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H
-#ifdef BUILDING_WITH_CMAKE
-#include "cmakeconfig.h"
-#else
-#include "autotoolsconfig.h"
-#endif
-#endif
-
-#include "LauncherInspectorWindow.h"
-#include <errno.h>
-#include <gdk/gdkkeysyms.h>
-#ifdef WTF_USE_GSTREAMER
-#include <gst/gst.h>
-#endif
-#include <gtk/gtk.h>
-#include <stdlib.h>
-#include <string.h>
-#include <webkit/webkit.h>
-
-static gint windowCount = 0;
-
-static GtkWidget* createWindow(WebKitWebView** outWebView);
-
-static void activateUriEntryCb(GtkWidget* entry, gpointer data)
-{
- WebKitWebView *webView = g_object_get_data(G_OBJECT(entry), "web-view");
- const gchar* uri = gtk_entry_get_text(GTK_ENTRY(entry));
- g_assert(uri);
- gtk_entry_set_icon_from_pixbuf(GTK_ENTRY(entry), GTK_ENTRY_ICON_PRIMARY, 0);
- webkit_web_view_load_uri(webView, uri);
-}
-
-static void updateTitle(GtkWindow* window, WebKitWebView* webView)
-{
- GString *string = g_string_new(webkit_web_view_get_title(webView));
- gdouble loadProgress = webkit_web_view_get_progress(webView) * 100;
- g_string_append(string, " - WebKit Launcher");
- if (loadProgress < 100)
- g_string_append_printf(string, " (%f%%)", loadProgress);
- gchar *title = g_string_free(string, FALSE);
- gtk_window_set_title(window, title);
- g_free(title);
-}
-
-static void linkHoverCb(WebKitWebView* page, const gchar* title, const gchar* link, GtkStatusbar* statusbar)
-{
- guint statusContextId =
- GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(statusbar), "link-hover-context"));
- /* underflow is allowed */
- gtk_statusbar_pop(statusbar, statusContextId);
- if (link)
- gtk_statusbar_push(statusbar, statusContextId, link);
-}
-
-static void notifyTitleCb(WebKitWebView* webView, GParamSpec* pspec, GtkWidget* window)
-{
- updateTitle(GTK_WINDOW(window), webView);
-}
-
-static void notifyLoadStatusCb(WebKitWebView* webView, GParamSpec* pspec, GtkWidget* uriEntry)
-{
- if (webkit_web_view_get_load_status(webView) == WEBKIT_LOAD_COMMITTED) {
- WebKitWebFrame *frame = webkit_web_view_get_main_frame(webView);
- const gchar *uri = webkit_web_frame_get_uri(frame);
- if (uri)
- gtk_entry_set_text(GTK_ENTRY(uriEntry), uri);
- }
-}
-
-static void notifyProgressCb(WebKitWebView* webView, GParamSpec* pspec, GtkWidget* window)
-{
- updateTitle(GTK_WINDOW(window), webView);
-}
-
-static void destroyCb(GtkWidget* widget, GtkWidget* window)
-{
- if (g_atomic_int_dec_and_test(&windowCount))
- gtk_main_quit();
-}
-
-static void goBackCb(GtkWidget* widget, WebKitWebView* webView)
-{
- webkit_web_view_go_back(webView);
-}
-
-static void goForwardCb(GtkWidget* widget, WebKitWebView* webView)
-{
- webkit_web_view_go_forward(webView);
-}
-
-static void reloadCb(GtkWidget* widget, WebKitWebView* webView)
-{
- webkit_web_view_reload(webView);
-}
-
-static WebKitWebView*
-createWebViewCb(WebKitWebView* webView, WebKitWebFrame* web_frame, GtkWidget* window)
-{
- WebKitWebView *newWebView;
- createWindow(&newWebView);
- webkit_web_view_set_settings(newWebView, webkit_web_view_get_settings(webView));
- return newWebView;
-}
-
-static gboolean webViewReadyCb(WebKitWebView* webView, GtkWidget* window)
-{
- gtk_widget_grab_focus(GTK_WIDGET(webView));
- gtk_widget_show_all(window);
- return FALSE;
-}
-
-static gboolean closeWebViewCb(WebKitWebView* webView, GtkWidget* window)
-{
- gtk_widget_destroy(window);
- return TRUE;
-}
-
-static gboolean webViewFullscreenMessageWindowClose(GtkWidget *dialog)
-{
- if (GTK_IS_WIDGET(dialog))
- gtk_widget_destroy(dialog);
- return FALSE;
-}
-
-static gboolean webViewWindowStateEvent(GtkWidget *widget, GdkEventWindowState *event, WebKitWebView *webView)
-{
- if (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) {
- WebKitWebFrame *frame = webkit_web_view_get_main_frame(webView);
- const gchar *uri = webkit_web_frame_get_uri(frame);
- GtkWidget *window = gtk_widget_get_toplevel(GTK_WIDGET(webView));
- if (!gtk_widget_is_toplevel(window) || !GTK_IS_WINDOW(window) || GTK_IS_OFFSCREEN_WINDOW(window))
- window = 0;
-
- GtkWidget *dialog = gtk_message_dialog_new(window ? GTK_WINDOW(window) : 0,
- GTK_DIALOG_MODAL,
- GTK_MESSAGE_INFO,
- GTK_BUTTONS_CLOSE,
- "%s is now full screen. Press ESC or f to exit.", uri);
- g_signal_connect_swapped(dialog, "response", G_CALLBACK(gtk_widget_destroy), dialog);
- guint id = g_timeout_add(1500, (GSourceFunc) webViewFullscreenMessageWindowClose, dialog);
- g_source_set_name_by_id(id, "[WebKit] webViewFullscreenMessageWindowClose");
- gtk_dialog_run(GTK_DIALOG(dialog));
- }
- return TRUE;
-}
-
-static void hideWidget(GtkWidget* widget, gpointer data)
-{
- if (!GTK_IS_SCROLLED_WINDOW(widget))
- gtk_widget_hide(widget);
-}
-
-static void showWidget(GtkWidget* widget, gpointer data)
-{
- if (!GTK_IS_SCROLLED_WINDOW(widget))
- gtk_widget_show(widget);
-}
-
-static gboolean webViewEnteringFullScreen(WebKitWebView *webView, GObject *element, GtkWidget* vbox)
-{
- WebKitWebFrame *frame = webkit_web_view_get_main_frame(webView);
- const gchar *uri = webkit_web_frame_get_uri(frame);
- GtkWidget *window = gtk_widget_get_toplevel(GTK_WIDGET(webView));
- if (!gtk_widget_is_toplevel(window) || !GTK_IS_WINDOW(window) || GTK_IS_OFFSCREEN_WINDOW(window))
- window = 0;
-
- GtkWidget *dialog = gtk_message_dialog_new(window ? GTK_WINDOW(window) : 0,
- GTK_DIALOG_MODAL,
- GTK_MESSAGE_INFO,
- GTK_BUTTONS_YES_NO,
- "Allow full screen display of %s ?", uri);
- gint result = gtk_dialog_run(GTK_DIALOG(dialog));
- if (result == GTK_RESPONSE_YES) {
- gtk_container_foreach(GTK_CONTAINER(vbox), (GtkCallback) hideWidget, NULL);
- gtk_widget_destroy(GTK_WIDGET(dialog));
- return FALSE;
- }
- gtk_widget_destroy(GTK_WIDGET(dialog));
- return TRUE;
-}
-
-static gboolean webViewLeavingFullScreen(WebKitWebView *webView, GObject *element, GtkWidget* vbox)
-{
- GtkWidget *window = gtk_widget_get_toplevel(GTK_WIDGET(webView));
- if (gtk_widget_is_toplevel(window) && GTK_IS_WINDOW(window) && !GTK_IS_OFFSCREEN_WINDOW(window))
- g_signal_handlers_disconnect_by_func(window, G_CALLBACK(webViewWindowStateEvent), webView);
- gtk_container_foreach(GTK_CONTAINER(vbox), (GtkCallback) showWidget, NULL);
- return FALSE;
-}
-
-static void iconLoadedCb(WebKitWebView* webView, const char* iconURI, GtkWidget* uriEntry)
-{
- GdkPixbuf *icon = webkit_web_view_try_get_favicon_pixbuf(webView, 16, 16);
- if (!icon)
- return;
-
- gtk_entry_set_icon_from_pixbuf(GTK_ENTRY(uriEntry), GTK_ENTRY_ICON_PRIMARY, icon);
- g_object_unref(icon);
-}
-
-static GtkWidget *inspectorInspectWebViewCb(WebKitWebInspector *inspector, WebKitWebView *webView, GtkWindow* window)
-{
- GtkWidget *inspectorWindow = launcherInspectorWindowNew(inspector, window);
- return GTK_WIDGET(launcherInspectorWindowGetWebView(LAUNCHER_INSPECTOR_WINDOW(inspectorWindow)));
-}
-
-static GtkWidget* createBrowser(GtkWidget* window, GtkWidget* uriEntry, GtkWidget* statusbar, WebKitWebView* webView, GtkWidget* vbox)
-{
- char *iconDatabasePath;
- GtkWidget *scrolledWindow = gtk_scrolled_window_new(NULL, NULL);
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledWindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-
- gtk_container_add(GTK_CONTAINER(scrolledWindow), GTK_WIDGET(webView));
-
- iconDatabasePath = g_build_filename(g_get_user_cache_dir(), "GtkLauncher", "icondatabase", NULL);
- webkit_favicon_database_set_path(webkit_get_favicon_database(), iconDatabasePath);
- g_free(iconDatabasePath);
-
- g_signal_connect(webView, "notify::title", G_CALLBACK(notifyTitleCb), window);
- g_signal_connect(webView, "notify::load-status", G_CALLBACK(notifyLoadStatusCb), uriEntry);
- g_signal_connect(webView, "notify::progress", G_CALLBACK(notifyProgressCb), window);
- g_signal_connect(webView, "icon-loaded", G_CALLBACK(iconLoadedCb), uriEntry);
- g_signal_connect(webView, "hovering-over-link", G_CALLBACK(linkHoverCb), statusbar);
- g_signal_connect(webView, "create-web-view", G_CALLBACK(createWebViewCb), window);
- g_signal_connect(webView, "web-view-ready", G_CALLBACK(webViewReadyCb), window);
- g_signal_connect(webView, "close-web-view", G_CALLBACK(closeWebViewCb), window);
- g_signal_connect(webView, "entering-fullscreen", G_CALLBACK(webViewEnteringFullScreen), vbox);
- g_signal_connect(webView, "leaving-fullscreen", G_CALLBACK(webViewLeavingFullScreen), vbox);
- g_signal_connect(webkit_web_view_get_inspector(webView), "inspect-web-view", G_CALLBACK(inspectorInspectWebViewCb), window);
-
- return scrolledWindow;
-}
-
-static GtkWidget* createStatusbar()
-{
- GtkStatusbar *statusbar = GTK_STATUSBAR(gtk_statusbar_new());
- guint statusContextId = gtk_statusbar_get_context_id(statusbar, "Link Hover");
- g_object_set_data(G_OBJECT(statusbar), "link-hover-context",
- GUINT_TO_POINTER(statusContextId));
-
- return GTK_WIDGET(statusbar);
-}
-
-static GtkWidget* createToolbar(GtkWidget* window, GtkWidget* uriEntry, WebKitWebView* webView)
-{
- GtkWidget *toolbar = gtk_toolbar_new();
-
- gtk_orientable_set_orientation(GTK_ORIENTABLE(toolbar), GTK_ORIENTATION_HORIZONTAL);
- gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_BOTH_HORIZ);
-
- GtkToolItem *item;
-
- /* Keyboard accelerators */
- GtkAccelGroup *accelGroup = gtk_accel_group_new();
- gtk_window_add_accel_group(GTK_WINDOW(window), accelGroup);
-
- /* the back button */
- item = gtk_tool_button_new_from_stock(GTK_STOCK_GO_BACK);
- g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(goBackCb), webView);
- gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
-
- /* The forward button */
- item = gtk_tool_button_new_from_stock(GTK_STOCK_GO_FORWARD);
- g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(goForwardCb), webView);
- gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
-
- /* The reload button */
- item = gtk_tool_button_new_from_stock(GTK_STOCK_REFRESH);
- g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(reloadCb), webView);
- gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
- gtk_widget_add_accelerator(GTK_WIDGET(item), "clicked", accelGroup, GDK_KEY_F5, 0, GTK_ACCEL_VISIBLE);
-
- /* The URL entry */
- item = gtk_tool_item_new();
- gtk_tool_item_set_expand(item, TRUE);
- gtk_container_add(GTK_CONTAINER(item), uriEntry);
- g_signal_connect(G_OBJECT(uriEntry), "activate", G_CALLBACK(activateUriEntryCb), NULL);
- gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
-
- /* The go button */
- g_object_set_data(G_OBJECT(uriEntry), "web-view", webView);
- item = gtk_tool_button_new_from_stock(GTK_STOCK_OK);
- g_signal_connect_swapped(G_OBJECT(item), "clicked", G_CALLBACK(activateUriEntryCb), (gpointer)uriEntry);
- gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
-
- return toolbar;
-}
-
-static GtkWidget* createWindow(WebKitWebView** outWebView)
-{
- WebKitWebView *webView;
- GtkWidget *vbox;
- GtkWidget *window;
- GtkWidget *uriEntry;
- GtkWidget *statusbar;
-
- g_atomic_int_inc(&windowCount);
-
- window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);
- gtk_widget_set_name(window, "GtkLauncher");
-
- webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- uriEntry = gtk_entry_new();
-
-#ifdef GTK_API_VERSION_2
- vbox = gtk_vbox_new(FALSE, 0);
-#else
- vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
-#endif
- statusbar = createStatusbar();
- gtk_box_pack_start(GTK_BOX(vbox), createToolbar(window, uriEntry, webView), FALSE, FALSE, 0);
- gtk_box_pack_start(GTK_BOX(vbox), createBrowser(window, uriEntry, statusbar, webView, vbox), TRUE, TRUE, 0);
- gtk_box_pack_start(GTK_BOX(vbox), statusbar, FALSE, FALSE, 0);
-
- gtk_container_add(GTK_CONTAINER(window), vbox);
-
- g_signal_connect(window, "destroy", G_CALLBACK(destroyCb), NULL);
-
- if (outWebView)
- *outWebView = webView;
-
- return window;
-}
-
-static gchar* filenameToURL(const char* filename)
-{
- if (!g_file_test(filename, G_FILE_TEST_EXISTS))
- return NULL;
-
- GFile *gfile = g_file_new_for_path(filename);
- gchar *fileURL = g_file_get_uri(gfile);
- g_object_unref(gfile);
-
- return fileURL;
-}
-
-static gboolean parseOptionEntryCallback(const gchar *optionNameFull, const gchar *value, WebKitWebSettings *webSettings, GError **error)
-{
- if (strlen(optionNameFull) <= 2) {
- g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, "Invalid option %s", optionNameFull);
- return FALSE;
- }
-
- /* We have two -- in option name so remove them. */
- const gchar *optionName = optionNameFull + 2;
- GParamSpec *spec = g_object_class_find_property(G_OBJECT_GET_CLASS(webSettings), optionName);
- if (!spec) {
- g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, "Cannot find web settings for option %s", optionNameFull);
- return FALSE;
- }
-
- switch (G_PARAM_SPEC_VALUE_TYPE(spec)) {
- case G_TYPE_BOOLEAN: {
- gboolean propertyValue = TRUE;
- if (value && g_ascii_strcasecmp(value, "true") && strcmp(value, "1"))
- propertyValue = FALSE;
- g_object_set(G_OBJECT(webSettings), optionName, propertyValue, NULL);
- break;
- }
- case G_TYPE_STRING:
- g_object_set(G_OBJECT(webSettings), optionName, value, NULL);
- break;
- case G_TYPE_INT: {
- glong propertyValue;
- gchar *end;
-
- errno = 0;
- propertyValue = g_ascii_strtoll(value, &end, 0);
- if (errno == ERANGE || propertyValue > G_MAXINT || propertyValue < G_MININT) {
- g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "Integer value '%s' for %s out of range", value, optionNameFull);
- return FALSE;
- }
- if (errno || value == end) {
- g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "Cannot parse integer value '%s' for %s", value, optionNameFull);
- return FALSE;
- }
- g_object_set(G_OBJECT(webSettings), optionName, propertyValue, NULL);
- break;
- }
- case G_TYPE_FLOAT: {
- gdouble propertyValue;
- gchar *end;
-
- errno = 0;
- propertyValue = g_ascii_strtod(value, &end);
- if (errno == ERANGE || propertyValue > G_MAXFLOAT || propertyValue < G_MINFLOAT) {
- g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "Float value '%s' for %s out of range", value, optionNameFull);
- return FALSE;
- }
- if (errno || value == end) {
- g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, "Cannot parse float value '%s' for %s", value, optionNameFull);
- return FALSE;
- }
- g_object_set(G_OBJECT(webSettings), optionName, propertyValue, NULL);
- break;
- }
- default:
- g_assert_not_reached();
- }
-
- return TRUE;
-}
-
-static gboolean isValidParameterType(GType gParamType)
-{
- return (gParamType == G_TYPE_BOOLEAN || gParamType == G_TYPE_STRING || gParamType == G_TYPE_INT
- || gParamType == G_TYPE_FLOAT);
-}
-
-static GOptionEntry* getOptionEntriesFromWebKitWebSettings(WebKitWebSettings *webSettings)
-{
- GParamSpec **propertySpecs;
- GOptionEntry *optionEntries;
- guint numProperties, numEntries, i;
-
- propertySpecs = g_object_class_list_properties(G_OBJECT_GET_CLASS(webSettings), &numProperties);
- if (!propertySpecs)
- return NULL;
-
- optionEntries = g_new0(GOptionEntry, numProperties + 1);
- numEntries = 0;
- for (i = 0; i < numProperties; i++) {
- GParamSpec *param = propertySpecs[i];
-
- /* Fill in structures only for writable and not construct-only properties. */
- if (!param || !(param->flags & G_PARAM_WRITABLE) || (param->flags & G_PARAM_CONSTRUCT_ONLY))
- continue;
-
- GType gParamType = G_PARAM_SPEC_VALUE_TYPE(param);
- if (!isValidParameterType(gParamType))
- continue;
-
- GOptionEntry *optionEntry = &optionEntries[numEntries++];
- optionEntry->long_name = g_param_spec_get_name(param);
-
- /* There is no easy way to figure our short name for generated option entries.
- optionEntry.short_name=*/
- /* For bool arguments "enable" type make option argument not required. */
- if (gParamType == G_TYPE_BOOLEAN && (strstr(optionEntry->long_name, "enable")))
- optionEntry->flags = G_OPTION_FLAG_OPTIONAL_ARG;
- optionEntry->arg = G_OPTION_ARG_CALLBACK;
- optionEntry->arg_data = parseOptionEntryCallback;
- optionEntry->description = g_param_spec_get_blurb(param);
- optionEntry->arg_description = g_type_name(gParamType);
- }
- g_free(propertySpecs);
-
- return optionEntries;
-}
-
-static gboolean addWebSettingsGroupToContext(GOptionContext *context, WebKitWebSettings* webkitSettings)
-{
- GOptionEntry *optionEntries = getOptionEntriesFromWebKitWebSettings(webkitSettings);
- if (!optionEntries)
- return FALSE;
-
- GOptionGroup *webSettingsGroup = g_option_group_new("websettings",
- "WebKitWebSettings writable properties for default WebKitWebView",
- "WebKitWebSettings properties",
- webkitSettings,
- NULL);
- g_option_group_add_entries(webSettingsGroup, optionEntries);
- g_free(optionEntries);
-
- /* Option context takes ownership of the group. */
- g_option_context_add_group(context, webSettingsGroup);
-
- return TRUE;
-}
-
-int main(int argc, char* argv[])
-{
- WebKitWebSettings *webkitSettings = 0;
- const gchar **uriArguments = 0;
- const GOptionEntry commandLineOptions[] =
- {
- { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &uriArguments, 0, "[URL]" },
- { 0, 0, 0, 0, 0, 0, 0 }
- };
-
- gtk_init(&argc, &argv);
-
- GOptionContext *context = g_option_context_new(0);
- g_option_context_add_main_entries(context, commandLineOptions, 0);
- g_option_context_add_group(context, gtk_get_option_group(TRUE));
-#ifdef WTF_USE_GSTREAMER
- g_option_context_add_group(context, gst_init_get_option_group());
-#endif
- webkitSettings = webkit_web_settings_new();
- g_object_set(webkitSettings, "enable-developer-extras", TRUE, NULL);
- if (!addWebSettingsGroupToContext(context, webkitSettings)) {
- g_object_unref(webkitSettings);
- webkitSettings = 0;
- }
-
- GError *error = 0;
- if (!g_option_context_parse(context, &argc, &argv, &error)) {
- g_printerr("Cannot parse arguments: %s\n", error->message);
- g_error_free(error);
- g_option_context_free(context);
-
- return 1;
- }
- g_option_context_free(context);
-
-#ifdef SOUP_TYPE_PROXY_RESOLVER_DEFAULT
- soup_session_add_feature_by_type(webkit_get_default_session(), SOUP_TYPE_PROXY_RESOLVER_DEFAULT);
-#else
- const char *httpProxy = g_getenv("http_proxy");
- if (httpProxy) {
- SoupURI *proxyUri = soup_uri_new(httpProxy);
- g_object_set(webkit_get_default_session(), SOUP_SESSION_PROXY_URI, proxyUri, NULL);
- soup_uri_free(proxyUri);
- }
-#endif
-
- WebKitWebView *webView;
- GtkWidget *main_window = createWindow(&webView);
-
- if (webkitSettings) {
- webkit_web_view_set_settings(WEBKIT_WEB_VIEW(webView), webkitSettings);
- g_object_unref(webkitSettings);
- }
-
- const gchar *uri = (uriArguments ? uriArguments[0] : "http://www.google.com/");
- gchar *fileURL = filenameToURL(uri);
-
- webkit_web_view_load_uri(webView, fileURL ? fileURL : uri);
- g_free(fileURL);
-
- gtk_widget_grab_focus(GTK_WIDGET(webView));
- gtk_widget_show_all(main_window);
- gtk_main();
-
- return 0;
-}
diff --git a/Tools/ImageDiff/CMakeLists.txt b/Tools/ImageDiff/CMakeLists.txt
new file mode 100644
index 000000000..6ce4ed522
--- /dev/null
+++ b/Tools/ImageDiff/CMakeLists.txt
@@ -0,0 +1,20 @@
+set(IMAGE_DIFF_DIR "${TOOLS_DIR}/ImageDiff")
+
+set(IMAGE_DIFF_INCLUDE_DIRECTORIES
+ ${CMAKE_BINARY_DIR}
+ ${WTF_DIR}
+)
+
+set(IMAGE_DIFF_SYSTEM_INCLUDE_DIRECTORIES "")
+
+set(IMAGE_DIFF_LIBRARIES
+ WTF
+)
+
+WEBKIT_INCLUDE_CONFIG_FILES_IF_EXISTS()
+
+include_directories(${IMAGE_DIFF_INCLUDE_DIRECTORIES})
+include_directories(SYSTEM ${IMAGE_DIFF_SYSTEM_INCLUDE_DIRECTORIES})
+add_executable(ImageDiff ${IMAGE_DIFF_SOURCES})
+target_link_libraries(ImageDiff ${IMAGE_DIFF_LIBRARIES})
+set_target_properties(ImageDiff PROPERTIES FOLDER "Tools")
diff --git a/Tools/ImageDiff/PlatformGTK.cmake b/Tools/ImageDiff/PlatformGTK.cmake
new file mode 100644
index 000000000..8b37ca08b
--- /dev/null
+++ b/Tools/ImageDiff/PlatformGTK.cmake
@@ -0,0 +1,11 @@
+set(IMAGE_DIFF_SOURCES
+ ${IMAGE_DIFF_DIR}/gtk/ImageDiff.cpp
+)
+
+list(APPEND IMAGE_DIFF_SYSTEM_INCLUDE_DIRECTORIES
+ ${GTK_INCLUDE_DIRS}
+)
+
+list(APPEND IMAGE_DIFF_LIBRARIES
+ ${GTK_LIBRARIES}
+)
diff --git a/Tools/ImageDiff/gtk/ImageDiff.cpp b/Tools/ImageDiff/gtk/ImageDiff.cpp
index 2cb9f3bce..5a128d1e3 100644
--- a/Tools/ImageDiff/gtk/ImageDiff.cpp
+++ b/Tools/ImageDiff/gtk/ImageDiff.cpp
@@ -11,7 +11,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -30,6 +30,7 @@
#include <algorithm>
#include <cmath>
#include <cstdio>
+#include <cstdlib>
#include <cstring>
#include <gdk/gdk.h>
@@ -63,23 +64,27 @@ GdkPixbuf* readPixbufFromStdin(long imageSize)
}
gdk_pixbuf_loader_close(loader, 0);
- GdkPixbuf* decodedImage = gdk_pixbuf_loader_get_pixbuf(loader);
- g_object_ref(decodedImage);
+ GdkPixbuf* decodedImage = GDK_PIXBUF(g_object_ref(gdk_pixbuf_loader_get_pixbuf(loader)));
+ g_object_unref(loader);
return decodedImage;
}
-GdkPixbuf* differenceImageFromDifferenceBuffer(unsigned char* buffer, int width, int height)
+GdkPixbuf* differenceImageFromDifferenceBuffer(unsigned char* buffer, int width, int height, float maxDistance)
{
GdkPixbuf* image = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height);
if (!image)
return image;
+ bool shouldNormalize = maxDistance > 0 && maxDistance < 1;
int rowStride = gdk_pixbuf_get_rowstride(image);
unsigned char* diffPixels = gdk_pixbuf_get_pixels(image);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
unsigned char* diffPixel = diffPixels + (y * rowStride) + (x * 3);
- diffPixel[0] = diffPixel[1] = diffPixel[2] = *buffer++;
+ unsigned char bufferPixel = *buffer++;
+ if (shouldNormalize)
+ bufferPixel /= maxDistance;
+ diffPixel[0] = diffPixel[1] = diffPixel[2] = bufferPixel;
}
}
@@ -140,7 +145,7 @@ float calculateDifference(GdkPixbuf* baselineImage, GdkPixbuf* actualImage, GdkP
else {
difference = roundf(difference * 100.0f) / 100.0f;
difference = max(difference, 0.01f); // round to 2 decimal places
- *differenceImage = differenceImageFromDifferenceBuffer(diffBuffer, width, height);
+ *differenceImage = differenceImageFromDifferenceBuffer(diffBuffer, width, height, maxDistance);
}
free(diffBuffer);
diff --git a/Tools/MiniBrowser/Configurations/MiniBrowserCFLite.vsprops b/Tools/MiniBrowser/Configurations/MiniBrowserCFLite.vsprops
new file mode 100644
index 000000000..0882216a5
--- /dev/null
+++ b/Tools/MiniBrowser/Configurations/MiniBrowserCFLite.vsprops
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="MiniBrowserCFLite"
+ >
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="shlwapi.lib WebKit$(WebKitDLLConfigSuffix).lib CFLite$(LibraryConfigSuffix).lib"
+ />
+</VisualStudioPropertySheet>
diff --git a/Tools/MiniBrowser/Configurations/MiniBrowserCommon.vsprops b/Tools/MiniBrowser/Configurations/MiniBrowserCommon.vsprops
new file mode 100644
index 000000000..51275c7a9
--- /dev/null
+++ b/Tools/MiniBrowser/Configurations/MiniBrowserCommon.vsprops
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="MiniBrowserCommon"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="&quot;$(ConfigurationBuildDir)\Include&quot;;&quot;$(WebKitLibrariesDir)\Include&quot;"
+ UsePrecompiledHeader="2"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)\$(ProjectName)$(WebKitConfigSuffix).dll"
+ />
+</VisualStudioPropertySheet>
diff --git a/Tools/MiniBrowser/Configurations/MiniBrowserCoreFoundation.vsprops b/Tools/MiniBrowser/Configurations/MiniBrowserCoreFoundation.vsprops
new file mode 100644
index 000000000..deaa89bc9
--- /dev/null
+++ b/Tools/MiniBrowser/Configurations/MiniBrowserCoreFoundation.vsprops
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="MiniBrowserCoreFoundation"
+ >
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="shlwapi.lib WebKit$(WebKitDLLConfigSuffix).lib CoreFoundation$(LibraryConfigSuffix).lib CFNetwork$(LibraryConfigSuffix).lib"
+ />
+</VisualStudioPropertySheet>
diff --git a/Tools/MiniBrowser/Configurations/MiniBrowserDebug.vsprops b/Tools/MiniBrowser/Configurations/MiniBrowserDebug.vsprops
new file mode 100644
index 000000000..33f4e05dd
--- /dev/null
+++ b/Tools/MiniBrowser/Configurations/MiniBrowserDebug.vsprops
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="MiniBrowserDebug"
+ InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;.\MiniBrowserCoreFoundation.vsprops;.\MiniBrowserCommon.vsprops"
+ >
+</VisualStudioPropertySheet>
diff --git a/Tools/MiniBrowser/Configurations/MiniBrowserDebugAll.vsprops b/Tools/MiniBrowser/Configurations/MiniBrowserDebugAll.vsprops
new file mode 100644
index 000000000..981e59aa8
--- /dev/null
+++ b/Tools/MiniBrowser/Configurations/MiniBrowserDebugAll.vsprops
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="MiniBrowserDebugAll"
+ InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\debug_all.vsprops;.\MiniBrowserCoreFoundation.vsprops;.\MiniBrowserCommon.vsprops"
+ >
+</VisualStudioPropertySheet>
diff --git a/Tools/MiniBrowser/Configurations/MiniBrowserDebugCairoCFLite.vsprops b/Tools/MiniBrowser/Configurations/MiniBrowserDebugCairoCFLite.vsprops
new file mode 100644
index 000000000..485031283
--- /dev/null
+++ b/Tools/MiniBrowser/Configurations/MiniBrowserDebugCairoCFLite.vsprops
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="MiniBrowserDebugCairoCFLite"
+ InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\debug_wincairo.vsprops;.\MiniBrowserCFLite.vsprops;.\MiniBrowserCommon.vsprops"
+ >
+</VisualStudioPropertySheet>
diff --git a/Tools/MiniBrowser/Configurations/MiniBrowserLauncherCommon.vsprops b/Tools/MiniBrowser/Configurations/MiniBrowserLauncherCommon.vsprops
new file mode 100644
index 000000000..742780daf
--- /dev/null
+++ b/Tools/MiniBrowser/Configurations/MiniBrowserLauncherCommon.vsprops
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="MiniBrowserLauncherCommon"
+ >
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="shlwapi.lib"
+ OutputFile="$(OutDir)\MiniBrowser$(WebKitConfigSuffix).exe"
+ ProgramDatabaseFile="$(TargetDir)$(TargetName)Launcher.pdb"
+ />
+</VisualStudioPropertySheet>
diff --git a/Tools/MiniBrowser/Configurations/MiniBrowserLauncherDebug.vsprops b/Tools/MiniBrowser/Configurations/MiniBrowserLauncherDebug.vsprops
new file mode 100644
index 000000000..1f30791da
--- /dev/null
+++ b/Tools/MiniBrowser/Configurations/MiniBrowserLauncherDebug.vsprops
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="MiniBrowserLauncherDebug"
+ InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;.\MiniBrowserLauncherCommon.vsprops"
+ >
+</VisualStudioPropertySheet>
diff --git a/Tools/MiniBrowser/Configurations/MiniBrowserLauncherDebugAll.vsprops b/Tools/MiniBrowser/Configurations/MiniBrowserLauncherDebugAll.vsprops
new file mode 100644
index 000000000..ff91b6f2b
--- /dev/null
+++ b/Tools/MiniBrowser/Configurations/MiniBrowserLauncherDebugAll.vsprops
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="MiniBrowserLauncherDebugAll"
+ InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\debug_all.vsprops;.\MiniBrowserLauncherCommon.vsprops"
+ >
+</VisualStudioPropertySheet>
diff --git a/Tools/MiniBrowser/Configurations/MiniBrowserLauncherDebugCairoCFLite.vsprops b/Tools/MiniBrowser/Configurations/MiniBrowserLauncherDebugCairoCFLite.vsprops
new file mode 100644
index 000000000..fb4922093
--- /dev/null
+++ b/Tools/MiniBrowser/Configurations/MiniBrowserLauncherDebugCairoCFLite.vsprops
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="MiniBrowserDebugCairoCFLite"
+ InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;.\MiniBrowserLauncherCommon.vsprops"
+ >
+</VisualStudioPropertySheet>
diff --git a/Tools/MiniBrowser/Configurations/MiniBrowserLauncherProduction.vsprops b/Tools/MiniBrowser/Configurations/MiniBrowserLauncherProduction.vsprops
new file mode 100644
index 000000000..6a725b5cc
--- /dev/null
+++ b/Tools/MiniBrowser/Configurations/MiniBrowserLauncherProduction.vsprops
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="MiniBrowserLauncherProduction"
+ InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\releaseproduction.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\production.vsprops;.\MiniBrowserLauncherCommon.vsprops"
+ >
+</VisualStudioPropertySheet>
diff --git a/Tools/MiniBrowser/Configurations/MiniBrowserLauncherRelease.vsprops b/Tools/MiniBrowser/Configurations/MiniBrowserLauncherRelease.vsprops
new file mode 100644
index 000000000..023632587
--- /dev/null
+++ b/Tools/MiniBrowser/Configurations/MiniBrowserLauncherRelease.vsprops
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="MiniBrowserLauncherRelease"
+ InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\releaseproduction.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;.\MiniBrowserLauncherCommon.vsprops"
+ >
+</VisualStudioPropertySheet>
diff --git a/Tools/MiniBrowser/Configurations/MiniBrowserLauncherReleaseCairoCFLite.vsprops b/Tools/MiniBrowser/Configurations/MiniBrowserLauncherReleaseCairoCFLite.vsprops
new file mode 100644
index 000000000..b5919fe1b
--- /dev/null
+++ b/Tools/MiniBrowser/Configurations/MiniBrowserLauncherReleaseCairoCFLite.vsprops
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="MiniBrowserLauncherReleaseCairoCFLite"
+ InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\releaseproduction.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;.\MiniBrowserLauncherCommon.vsprops"
+ >
+</VisualStudioPropertySheet>
diff --git a/Tools/MiniBrowser/Configurations/MiniBrowserProduction.vsprops b/Tools/MiniBrowser/Configurations/MiniBrowserProduction.vsprops
new file mode 100644
index 000000000..165a3aab1
--- /dev/null
+++ b/Tools/MiniBrowser/Configurations/MiniBrowserProduction.vsprops
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="MiniBrowserProduction"
+ InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\releaseproduction.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\production.vsprops;.\MiniBrowserCoreFoundation.vsprops;.\MiniBrowserCommon.vsprops"
+ >
+</VisualStudioPropertySheet>
diff --git a/Tools/MiniBrowser/Configurations/MiniBrowserRelease.vsprops b/Tools/MiniBrowser/Configurations/MiniBrowserRelease.vsprops
new file mode 100644
index 000000000..8bc9a13ca
--- /dev/null
+++ b/Tools/MiniBrowser/Configurations/MiniBrowserRelease.vsprops
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="MiniBrowserRelease"
+ InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\releaseproduction.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;.\MiniBrowserCoreFoundation.vsprops;.\MiniBrowserCommon.vsprops"
+ >
+</VisualStudioPropertySheet>
diff --git a/Tools/MiniBrowser/Configurations/MiniBrowserReleaseCairoCFLite.vsprops b/Tools/MiniBrowser/Configurations/MiniBrowserReleaseCairoCFLite.vsprops
new file mode 100644
index 000000000..8253f930d
--- /dev/null
+++ b/Tools/MiniBrowser/Configurations/MiniBrowserReleaseCairoCFLite.vsprops
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="MiniBrowserReleaseCairoCFLite"
+ InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\releaseproduction.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\WinCairo.vsprops;.\MiniBrowserCFLite.vsprops;.\MiniBrowserCommon.vsprops"
+ >
+</VisualStudioPropertySheet>
diff --git a/Tools/MiniBrowser/MBToolbarItem.h b/Tools/MiniBrowser/MBToolbarItem.h
new file mode 100644
index 000000000..9971d4c10
--- /dev/null
+++ b/Tools/MiniBrowser/MBToolbarItem.h
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+@interface MBToolbarItem : NSToolbarItem
+@end
diff --git a/Tools/MiniBrowser/MiniBrowserWebProcessPlugIn.h b/Tools/MiniBrowser/MiniBrowserWebProcessPlugIn.h
new file mode 100644
index 000000000..ff16bf5dc
--- /dev/null
+++ b/Tools/MiniBrowser/MiniBrowserWebProcessPlugIn.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#import <WebKit/WKWebProcessPlugIn.h>
+
+#if WK_API_ENABLED
+
+@interface MiniBrowserWebProcessPlugIn : NSObject <WKWebProcessPlugIn>
+
+@end
+
+#endif // WK_API_ENABLED
diff --git a/Tools/MiniBrowser/gtk/BrowserDownloadsBar.c b/Tools/MiniBrowser/gtk/BrowserDownloadsBar.c
index 5f0e620e5..b0ec3ce14 100644
--- a/Tools/MiniBrowser/gtk/BrowserDownloadsBar.c
+++ b/Tools/MiniBrowser/gtk/BrowserDownloadsBar.c
@@ -23,6 +23,7 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "cmakeconfig.h"
#include "BrowserDownloadsBar.h"
#include <glib/gi18n.h>
diff --git a/Tools/MiniBrowser/gtk/BrowserSearchBar.c b/Tools/MiniBrowser/gtk/BrowserSearchBar.c
index 7585b564d..22930c4c5 100644
--- a/Tools/MiniBrowser/gtk/BrowserSearchBar.c
+++ b/Tools/MiniBrowser/gtk/BrowserSearchBar.c
@@ -23,9 +23,9 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "cmakeconfig.h"
#include "BrowserSearchBar.h"
-
static const char *searchEntryFailedStyle = "GtkEntry#searchEntry {background-color: #ff6666;}";
struct _BrowserSearchBar {
@@ -63,7 +63,7 @@ static void doSearch(BrowserSearchBar *searchBar)
if (!gtk_entry_get_icon_stock(entry, GTK_ENTRY_ICON_SECONDARY))
gtk_entry_set_icon_from_stock(entry, GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
- WebKitFindOptions options = WEBKIT_FIND_OPTIONS_NONE;
+ WebKitFindOptions options = WEBKIT_FIND_OPTIONS_WRAP_AROUND;
if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(searchBar->caseCheckButton)))
options |= WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE;
if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(searchBar->begginigWordCheckButton)))
@@ -274,9 +274,13 @@ void browser_search_bar_open(BrowserSearchBar *searchBar)
{
g_return_if_fail(BROWSER_IS_SEARCH_BAR(searchBar));
+ GtkEntry *entry = GTK_ENTRY(searchBar->entry);
+
gtk_widget_show(GTK_WIDGET(searchBar));
- gtk_widget_grab_focus(GTK_WIDGET(searchBar->entry));
- gtk_editable_select_region(GTK_EDITABLE(searchBar->entry), 0, -1);
+ gtk_widget_grab_focus(GTK_WIDGET(entry));
+ gtk_editable_select_region(GTK_EDITABLE(entry), 0, -1);
+ if (gtk_entry_get_text_length(entry))
+ doSearch(searchBar);
}
void browser_search_bar_close(BrowserSearchBar *searchBar)
diff --git a/Tools/MiniBrowser/gtk/BrowserWindow.c b/Tools/MiniBrowser/gtk/BrowserWindow.c
index b8a0d056c..1f73f6f9c 100644
--- a/Tools/MiniBrowser/gtk/BrowserWindow.c
+++ b/Tools/MiniBrowser/gtk/BrowserWindow.c
@@ -25,6 +25,9 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
+#if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H && defined(BUILDING_WITH_CMAKE)
+#include "cmakeconfig.h"
+#endif
#include "BrowserWindow.h"
#include "BrowserDownloadsBar.h"
@@ -50,18 +53,25 @@ struct _BrowserWindow {
GtkWidget *forwardItem;
GtkWidget *zoomInItem;
GtkWidget *zoomOutItem;
+ GtkWidget *boldItem;
+ GtkWidget *italicItem;
+ GtkWidget *underlineItem;
+ GtkWidget *strikethroughItem;
GtkWidget *statusLabel;
GtkWidget *settingsDialog;
WebKitWebView *webView;
GtkWidget *downloadsBar;
BrowserSearchBar *searchBar;
gboolean searchBarVisible;
+ gboolean inspectorWindowIsVisible;
+ gboolean fullScreenIsEnabled;
GdkPixbuf *favicon;
GtkWidget *reloadOrStopButton;
GtkWidget *fullScreenMessageLabel;
GtkWindow *parentWindow;
guint fullScreenMessageLabelId;
guint resetEntryProgressTimeoutId;
+ gchar *sessionFile;
};
struct _BrowserWindowClass {
@@ -72,6 +82,7 @@ static const char *defaultWindowTitle = "WebKitGTK+ MiniBrowser";
static const char *miniBrowserAboutScheme = "minibrowser-about";
static const gdouble minimumZoomLevel = 0.5;
static const gdouble maximumZoomLevel = 3;
+static const gdouble defaultZoomLevel = 1;
static const gdouble zoomStep = 1.2;
static gint windowCount = 0;
@@ -249,7 +260,7 @@ static void backForwadlistChanged(WebKitBackForwardList *backForwadlist, WebKitB
browserWindowUpdateNavigationActions(window, backForwadlist);
}
-static void geolocationRequestDialogCallback(GtkDialog *dialog, gint response, WebKitPermissionRequest *request)
+static void permissionRequestDialogCallback(GtkDialog *dialog, gint response, WebKitPermissionRequest *request)
{
switch (response) {
case GTK_RESPONSE_YES:
@@ -344,7 +355,7 @@ static gboolean webViewLeaveFullScreen(WebKitWebView *webView, BrowserWindow *wi
return FALSE;
}
-static GtkWidget *webViewCreate(WebKitWebView *webView, BrowserWindow *window)
+static GtkWidget *webViewCreate(WebKitWebView *webView, WebKitNavigationAction *navigation, BrowserWindow *window)
{
WebKitWebView *newWebView = WEBKIT_WEB_VIEW(webkit_web_view_new_with_related_view(webView));
webkit_web_view_set_settings(newWebView, webkit_web_view_get_settings(webView));
@@ -362,19 +373,37 @@ static gboolean webViewLoadFailed(WebKitWebView *webView, WebKitLoadEvent loadEv
return FALSE;
}
+static gboolean webViewLoadFailedWithTLSerrors(WebKitWebView *webView, const char *failingURI, GTlsCertificate *certificate, GTlsCertificateFlags errors, BrowserWindow *window)
+{
+ GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, "%s", "Invalid TLS Certificate");
+ gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), "Failed to load %s: Do you want to continue ignoring the TLS errors?", failingURI);
+ int response = gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+
+ if (response == GTK_RESPONSE_YES) {
+ SoupURI *uri = soup_uri_new(failingURI);
+ webkit_web_context_allow_tls_certificate_for_host(webkit_web_view_get_context(webView), certificate, uri->host);
+ soup_uri_free(uri);
+ webkit_web_view_load_uri(webView, failingURI);
+ }
+
+ return TRUE;
+}
+
static gboolean webViewDecidePolicy(WebKitWebView *webView, WebKitPolicyDecision *decision, WebKitPolicyDecisionType decisionType, BrowserWindow *window)
{
switch (decisionType) {
case WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION: {
- WebKitNavigationPolicyDecision *navigationDecision = WEBKIT_NAVIGATION_POLICY_DECISION(decision);
- if (webkit_navigation_policy_decision_get_navigation_type(navigationDecision) != WEBKIT_NAVIGATION_TYPE_LINK_CLICKED
- || webkit_navigation_policy_decision_get_mouse_button(navigationDecision) != GDK_BUTTON_MIDDLE)
+ WebKitNavigationAction *navigationAction = webkit_navigation_policy_decision_get_navigation_action(WEBKIT_NAVIGATION_POLICY_DECISION(decision));
+ if (webkit_navigation_action_get_navigation_type(navigationAction) != WEBKIT_NAVIGATION_TYPE_LINK_CLICKED
+ || webkit_navigation_action_get_mouse_button(navigationAction) != GDK_BUTTON_MIDDLE)
return FALSE;
// Opening a new window if link clicked with the middle button.
WebKitWebView *newWebView = WEBKIT_WEB_VIEW(webkit_web_view_new_with_context(webkit_web_view_get_context(webView)));
GtkWidget *newWindow = browser_window_new(newWebView, GTK_WINDOW(window));
- webkit_web_view_load_request(newWebView, webkit_navigation_policy_decision_get_request(navigationDecision));
+ webkit_web_view_load_request(newWebView, webkit_navigation_action_get_request(navigationAction));
gtk_widget_show(newWindow);
webkit_policy_decision_ignore(decision);
@@ -402,19 +431,46 @@ static gboolean webViewDecidePolicy(WebKitWebView *webView, WebKitPolicyDecision
static gboolean webViewDecidePermissionRequest(WebKitWebView *webView, WebKitPermissionRequest *request, BrowserWindow *window)
{
- if (!WEBKIT_IS_GEOLOCATION_PERMISSION_REQUEST(request))
+ const gchar *dialog_title = NULL;
+ const gchar *dialog_message = NULL;
+ const gchar *dialog_message_format = NULL;
+
+ if (WEBKIT_IS_GEOLOCATION_PERMISSION_REQUEST(request)) {
+ dialog_title = "Geolocation request";
+ dialog_message_format = "%s";
+ dialog_message = "Allow geolocation request?";
+ } else if (WEBKIT_IS_NOTIFICATION_PERMISSION_REQUEST(request)) {
+ dialog_title = "Notification request";
+ dialog_message_format = "%s";
+ dialog_message = "Allow notifications request?";
+ } else if (WEBKIT_IS_USER_MEDIA_PERMISSION_REQUEST(request)) {
+ dialog_message_format = "Allow access to %s device?";
+ gboolean is_for_audio_device = webkit_user_media_permission_is_for_audio_device(WEBKIT_USER_MEDIA_PERMISSION_REQUEST(request));
+ gboolean is_for_video_device = webkit_user_media_permission_is_for_video_device(WEBKIT_USER_MEDIA_PERMISSION_REQUEST(request));
+ dialog_title = "UserMedia request";
+ if (is_for_audio_device) {
+ if (is_for_video_device)
+ dialog_message = "audio/video";
+ else
+ dialog_message = "audio";
+ } else if (is_for_video_device)
+ dialog_message = "video";
+ } else if (WEBKIT_IS_INSTALL_MISSING_MEDIA_PLUGINS_PERMISSION_REQUEST(request)) {
+ dialog_title = "Media plugin missing request";
+ dialog_message_format = "The media backend was unable to find a plugin to play the requested media:\n%s.\nAllow to search and install the missing plugin?";
+ dialog_message = webkit_install_missing_media_plugins_permission_request_get_description(WEBKIT_INSTALL_MISSING_MEDIA_PLUGINS_PERMISSION_REQUEST(request));
+ } else
return FALSE;
GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(window),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_QUESTION,
- GTK_BUTTONS_YES_NO,
- "Geolocation request");
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_YES_NO,
+ "%s", dialog_title);
- gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), "Allow geolocation request?");
- g_signal_connect(dialog, "response", G_CALLBACK(geolocationRequestDialogCallback), g_object_ref(request));
+ gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), dialog_message_format, dialog_message);
+ g_signal_connect(dialog, "response", G_CALLBACK(permissionRequestDialogCallback), g_object_ref(request));
gtk_widget_show(dialog);
-
return TRUE;
}
@@ -439,6 +495,84 @@ static gboolean browserWindowCanZoomOut(BrowserWindow *window)
return zoomLevel > minimumZoomLevel;
}
+static gboolean browserWindowZoomIn(BrowserWindow *window)
+{
+ if (browserWindowCanZoomIn(window)) {
+ gdouble zoomLevel = webkit_web_view_get_zoom_level(window->webView) * zoomStep;
+ webkit_web_view_set_zoom_level(window->webView, zoomLevel);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean browserWindowZoomOut(BrowserWindow *window)
+{
+ if (browserWindowCanZoomOut(window)) {
+ gdouble zoomLevel = webkit_web_view_get_zoom_level(window->webView) / zoomStep;
+ webkit_web_view_set_zoom_level(window->webView, zoomLevel);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean scrollEventCallback(WebKitWebView *webView, const GdkEventScroll *event, BrowserWindow *window)
+{
+ GdkModifierType mod = gtk_accelerator_get_default_mod_mask();
+
+ if ((event->state & mod) != GDK_CONTROL_MASK)
+ return FALSE;
+
+ if (event->delta_y < 0)
+ return browserWindowZoomIn(window);
+
+ return browserWindowZoomOut(window);
+}
+
+#if GTK_CHECK_VERSION(3, 12, 0)
+static void colorChooserRGBAChanged(GtkColorChooser *colorChooser, GParamSpec *paramSpec, WebKitColorChooserRequest *request)
+{
+ GdkRGBA rgba;
+ gtk_color_chooser_get_rgba(colorChooser, &rgba);
+ webkit_color_chooser_request_set_rgba(request, &rgba);
+}
+
+static void popoverColorClosed(GtkWidget *popover, WebKitColorChooserRequest *request)
+{
+ webkit_color_chooser_request_finish(request);
+}
+
+static void colorChooserRequestFinished(WebKitColorChooserRequest *request, GtkWidget *popover)
+{
+ g_object_unref(request);
+ gtk_widget_destroy(popover);
+}
+
+static gboolean runColorChooserCallback(WebKitWebView *webView, WebKitColorChooserRequest *request, BrowserWindow *window)
+{
+ GtkWidget *popover = gtk_popover_new(GTK_WIDGET(webView));
+
+ GdkRectangle rectangle;
+ webkit_color_chooser_request_get_element_rectangle(request, &rectangle);
+ gtk_popover_set_pointing_to(GTK_POPOVER(popover), &rectangle);
+
+ GtkWidget *colorChooser = gtk_color_chooser_widget_new();
+ GdkRGBA rgba;
+ webkit_color_chooser_request_get_rgba(request, &rgba);
+ gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(colorChooser), &rgba);
+ g_signal_connect(colorChooser, "notify::rgba", G_CALLBACK(colorChooserRGBAChanged), request);
+ gtk_container_add(GTK_CONTAINER(popover), colorChooser);
+ gtk_widget_show(colorChooser);
+
+ g_object_ref(request);
+ g_signal_connect_object(popover, "hide", G_CALLBACK(popoverColorClosed), request, 0);
+ g_signal_connect_object(request, "finished", G_CALLBACK(colorChooserRequestFinished), popover, 0);
+
+ gtk_widget_show(popover);
+
+ return TRUE;
+}
+#endif /* GTK_CHECK_VERSION(3, 12, 0) */
+
static void browserWindowUpdateZoomActions(BrowserWindow *window)
{
gtk_widget_set_sensitive(window->zoomInItem, browserWindowCanZoomIn(window));
@@ -483,16 +617,31 @@ static void webViewIsLoadingChanged(GObject *object, GParamSpec *paramSpec, Brow
gtk_tool_button_set_stock_id(GTK_TOOL_BUTTON(window->reloadOrStopButton), isLoading ? GTK_STOCK_STOP : GTK_STOCK_REFRESH);
}
+static gboolean inspectorWasOpenedInAnotherWindow(WebKitWebInspector *inspectorWindow, BrowserWindow *window)
+{
+ window->inspectorWindowIsVisible = TRUE;
+ return FALSE;
+}
+
+static gboolean inspectorWasClosed(WebKitWebInspector *inspectorWindow, BrowserWindow *window)
+{
+ window->inspectorWindowIsVisible = FALSE;
+ return FALSE;
+}
+
static void zoomInCallback(BrowserWindow *window)
{
- gdouble zoomLevel = webkit_web_view_get_zoom_level(window->webView) * zoomStep;
- webkit_web_view_set_zoom_level(window->webView, zoomLevel);
+ browserWindowZoomIn(window);
}
static void zoomOutCallback(BrowserWindow *window)
{
- gdouble zoomLevel = webkit_web_view_get_zoom_level(window->webView) / zoomStep;
- webkit_web_view_set_zoom_level(window->webView, zoomLevel);
+ browserWindowZoomOut(window);
+}
+
+static void defaultZoomCallback(BrowserWindow *window)
+{
+ webkit_web_view_set_zoom_level(window->webView, defaultZoomLevel);
}
static void searchCallback(BrowserWindow *window)
@@ -500,6 +649,118 @@ static void searchCallback(BrowserWindow *window)
browser_search_bar_open(window->searchBar);
}
+static gboolean toggleWebInspector(BrowserWindow *window, gpointer user_data)
+{
+ WebKitWebInspector *inspectorWindow;
+
+ inspectorWindow = webkit_web_view_get_inspector(WEBKIT_WEB_VIEW(window->webView));
+ if (!window->inspectorWindowIsVisible) {
+ webkit_web_inspector_show(inspectorWindow);
+ window->inspectorWindowIsVisible = TRUE;
+ } else
+ webkit_web_inspector_close(inspectorWindow);
+
+ return TRUE;
+}
+
+static void reloadPage(BrowserWindow *window, gpointer user_data)
+{
+ webkit_web_view_reload(window->webView);
+}
+
+static void reloadPageIgnoringCache(BrowserWindow *window, gpointer user_data)
+{
+ webkit_web_view_reload_bypass_cache(window->webView);
+}
+
+static void stopPageLoad(BrowserWindow *window, gpointer user_data)
+{
+ if (gtk_widget_get_visible(GTK_WIDGET(window->searchBar)))
+ browser_search_bar_close(window->searchBar);
+ else if (webkit_web_view_is_loading(window->webView))
+ webkit_web_view_stop_loading(window->webView);
+}
+
+static void loadHomePage(BrowserWindow *window, gpointer user_data)
+{
+ webkit_web_view_load_uri(window->webView, BROWSER_DEFAULT_URL);
+}
+
+static gboolean toggleFullScreen(BrowserWindow *window, gpointer user_data)
+{
+ if (!window->fullScreenIsEnabled) {
+ gtk_window_fullscreen(GTK_WINDOW(window));
+ gtk_widget_hide(window->toolbar);
+ window->fullScreenIsEnabled = TRUE;
+ } else {
+ gtk_window_unfullscreen(GTK_WINDOW(window));
+ gtk_widget_show(window->toolbar);
+ window->fullScreenIsEnabled = FALSE;
+ }
+ return TRUE;
+}
+
+static void editingCommandCallback(GtkWidget*widget, BrowserWindow *window)
+{
+ webkit_web_view_execute_editing_command(window->webView, gtk_widget_get_name(widget));
+}
+
+static void insertImageCommandCallback(GtkWidget*widget, BrowserWindow *window)
+{
+ GtkWidget *fileChooser = gtk_file_chooser_dialog_new("Insert Image", GTK_WINDOW(window), GTK_FILE_CHOOSER_ACTION_OPEN,
+ "Cancel", GTK_RESPONSE_CANCEL, "Open", GTK_RESPONSE_ACCEPT, NULL);
+
+ GtkFileFilter *filter = gtk_file_filter_new();
+ gtk_file_filter_set_name(filter, "Images");
+ gtk_file_filter_add_pixbuf_formats(filter);
+ gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(fileChooser), filter);
+
+ if (gtk_dialog_run(GTK_DIALOG(fileChooser)) == GTK_RESPONSE_ACCEPT) {
+ char *uri = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(fileChooser));
+ if (uri) {
+ webkit_web_view_execute_editing_command_with_argument(window->webView, WEBKIT_EDITING_COMMAND_INSERT_IMAGE, uri);
+ g_free(uri);
+ }
+ }
+
+ gtk_widget_destroy(fileChooser);
+}
+
+static void insertLinkCommandCallback(GtkWidget*widget, BrowserWindow *window)
+{
+ GtkWidget *dialog = gtk_dialog_new_with_buttons("Insert Link", GTK_WINDOW(window), GTK_DIALOG_MODAL, "Insert", GTK_RESPONSE_ACCEPT, NULL);
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
+ GtkWidget *entry = gtk_entry_new();
+ gtk_entry_set_placeholder_text(GTK_ENTRY(entry), "URL");
+ gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
+ gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), entry);
+ gtk_widget_show(entry);
+
+ if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
+ const char *url = gtk_entry_get_text(GTK_ENTRY(entry));
+ if (url && *url)
+ webkit_web_view_execute_editing_command_with_argument(window->webView, WEBKIT_EDITING_COMMAND_CREATE_LINK, url);
+ }
+
+ gtk_widget_destroy(dialog);
+}
+
+static void browserWindowEditingCommandToggleButtonSetActive(BrowserWindow *window, GtkWidget *button, gboolean active)
+{
+ g_signal_handlers_block_by_func(button, G_CALLBACK(editingCommandCallback), window);
+ gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(button), active);
+ g_signal_handlers_unblock_by_func(button, G_CALLBACK(editingCommandCallback), window);
+}
+
+static void typingAttributesChanged(WebKitEditorState *editorState, GParamSpec *spec, BrowserWindow *window)
+{
+ unsigned typingAttributes = webkit_editor_state_get_typing_attributes(editorState);
+ browserWindowEditingCommandToggleButtonSetActive(window, window->boldItem, typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD);
+ browserWindowEditingCommandToggleButtonSetActive(window, window->italicItem, typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC);
+ browserWindowEditingCommandToggleButtonSetActive(window, window->underlineItem, typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE);
+ browserWindowEditingCommandToggleButtonSetActive(window, window->strikethroughItem, typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH);
+}
+
static void browserWindowFinalize(GObject *gObject)
{
BrowserWindow *window = BROWSER_WINDOW(gObject);
@@ -519,6 +780,8 @@ static void browserWindowFinalize(GObject *gObject)
if (window->resetEntryProgressTimeoutId)
g_source_remove(window->resetEntryProgressTimeoutId);
+ g_free(window->sessionFile);
+
G_OBJECT_CLASS(browser_window_parent_class)->finalize(gObject);
if (g_atomic_int_dec_and_test(&windowCount))
@@ -551,6 +814,138 @@ static void browserWindowSetProperty(GObject *object, guint propId, const GValue
}
}
+static void browserWindowSetupEditorToolbar(BrowserWindow *window)
+{
+ GtkWidget *toolbar = gtk_toolbar_new();
+ gtk_orientable_set_orientation(GTK_ORIENTABLE(toolbar), GTK_ORIENTATION_HORIZONTAL);
+ gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_BOTH_HORIZ);
+
+ GtkToolItem *item = gtk_toggle_tool_button_new_from_stock(GTK_STOCK_BOLD);
+ window->boldItem = GTK_WIDGET(item);
+ gtk_widget_set_name(GTK_WIDGET(item), "Bold");
+ g_signal_connect(G_OBJECT(item), "toggled", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_toggle_tool_button_new_from_stock(GTK_STOCK_ITALIC);
+ window->italicItem = GTK_WIDGET(item);
+ gtk_widget_set_name(GTK_WIDGET(item), "Italic");
+ g_signal_connect(G_OBJECT(item), "toggled", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_toggle_tool_button_new_from_stock(GTK_STOCK_UNDERLINE);
+ window->underlineItem = GTK_WIDGET(item);
+ gtk_widget_set_name(GTK_WIDGET(item), "Underline");
+ g_signal_connect(G_OBJECT(item), "toggled", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_toggle_tool_button_new_from_stock(GTK_STOCK_STRIKETHROUGH);
+ gtk_widget_set_name(GTK_WIDGET(item), "Strikethrough");
+ window->strikethroughItem = GTK_WIDGET(item);
+ g_signal_connect(G_OBJECT(item), "toggled", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_separator_tool_item_new();
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_tool_button_new_from_stock(GTK_STOCK_CUT);
+ gtk_widget_set_name(GTK_WIDGET(item), WEBKIT_EDITING_COMMAND_CUT);
+ g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_tool_button_new_from_stock(GTK_STOCK_COPY);
+ gtk_widget_set_name(GTK_WIDGET(item), WEBKIT_EDITING_COMMAND_COPY);
+ g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_tool_button_new_from_stock(GTK_STOCK_PASTE);
+ gtk_widget_set_name(GTK_WIDGET(item), WEBKIT_EDITING_COMMAND_PASTE);
+ g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_separator_tool_item_new();
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_tool_button_new_from_stock(GTK_STOCK_UNDO);
+ gtk_widget_set_name(GTK_WIDGET(item), WEBKIT_EDITING_COMMAND_UNDO);
+ g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_tool_button_new_from_stock(GTK_STOCK_REDO);
+ gtk_widget_set_name(GTK_WIDGET(item), WEBKIT_EDITING_COMMAND_REDO);
+ g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_separator_tool_item_new();
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_radio_tool_button_new_from_stock(NULL, GTK_STOCK_JUSTIFY_LEFT);
+ GSList *justifyRadioGroup = gtk_radio_tool_button_get_group(GTK_RADIO_TOOL_BUTTON(item));
+ gtk_widget_set_name(GTK_WIDGET(item), "JustifyLeft");
+ g_signal_connect(G_OBJECT(item), "toggled", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_radio_tool_button_new_from_stock(justifyRadioGroup, GTK_STOCK_JUSTIFY_CENTER);
+ justifyRadioGroup = gtk_radio_tool_button_get_group(GTK_RADIO_TOOL_BUTTON(item));
+ gtk_widget_set_name(GTK_WIDGET(item), "JustifyCenter");
+ g_signal_connect(G_OBJECT(item), "toggled", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_radio_tool_button_new_from_stock(justifyRadioGroup, GTK_STOCK_JUSTIFY_RIGHT);
+ gtk_widget_set_name(GTK_WIDGET(item), "JustifyRight");
+ g_signal_connect(G_OBJECT(item), "toggled", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_separator_tool_item_new();
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_tool_button_new_from_stock(GTK_STOCK_INDENT);
+ gtk_widget_set_name(GTK_WIDGET(item), "Indent");
+ g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_tool_button_new_from_stock(GTK_STOCK_UNINDENT);
+ gtk_widget_set_name(GTK_WIDGET(item), "Outdent");
+ g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_separator_tool_item_new();
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_tool_button_new(NULL, NULL);
+ gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(item), "insert-image");
+ g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(insertImageCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_tool_button_new(NULL, NULL);
+ gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(item), "insert-link");
+ g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(insertLinkCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ gtk_box_pack_start(GTK_BOX(window->mainBox), toolbar, FALSE, FALSE, 0);
+ gtk_widget_show(toolbar);
+}
+
static void browser_window_init(BrowserWindow *window)
{
g_atomic_int_inc(&windowCount);
@@ -567,6 +962,58 @@ static void browser_window_init(BrowserWindow *window)
window->accelGroup = gtk_accel_group_new();
gtk_window_add_accel_group(GTK_WINDOW(window), window->accelGroup);
+ /* Global accelerators */
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_I, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(toggleWebInspector), window, NULL));
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_F12, 0, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(toggleWebInspector), window, NULL));
+
+ /* Reload page */
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_F5, 0, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(reloadPage), window, NULL));
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_R, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(reloadPage), window, NULL));
+
+ /* Reload page ignoring cache */
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_F5, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(reloadPageIgnoringCache), window, NULL));
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_R, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(reloadPageIgnoringCache), window, NULL));
+
+ /* Stop page load */
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_F6, 0, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(stopPageLoad), window, NULL));
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_Escape, 0, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(stopPageLoad), window, NULL));
+
+ /* Load home page */
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_Home, GDK_MOD1_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(loadHomePage), window, NULL));
+
+ /* Zoom in, zoom out and default zoom*/
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_equal, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(zoomInCallback), window, NULL));
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_KP_Add, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(zoomInCallback), window, NULL));
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_minus, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(zoomOutCallback), window, NULL));
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_KP_Subtract, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(zoomOutCallback), window, NULL));
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_0, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(defaultZoomCallback), window, NULL));
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_KP_0, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(defaultZoomCallback), window, NULL));
+
+ /* Toggle fullscreen */
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_F11, 0, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(toggleFullScreen), window, NULL));
+
+ /* Quit */
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_Q, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(gtk_widget_destroy), window, NULL));
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_W, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(gtk_widget_destroy), window, NULL));
+
GtkWidget *toolbar = gtk_toolbar_new();
window->toolbar = toolbar;
gtk_orientable_set_orientation(GTK_ORIENTABLE(toolbar), GTK_ORIENTATION_HORIZONTAL);
@@ -609,6 +1056,12 @@ static void browser_window_init(BrowserWindow *window)
gtk_widget_add_accelerator(GTK_WIDGET(item), "clicked", window->accelGroup, GDK_KEY_F, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
gtk_widget_show(GTK_WIDGET(item));
+ item = gtk_tool_button_new_from_stock(GTK_STOCK_HOME);
+ g_signal_connect_swapped(item, "clicked", G_CALLBACK(loadHomePage), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_add_accelerator(GTK_WIDGET(item), "clicked", window->accelGroup, GDK_KEY_Home, GDK_MOD1_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_show(GTK_WIDGET(item));
+
item = gtk_tool_item_new();
gtk_tool_item_set_expand(item, TRUE);
gtk_container_add(GTK_CONTAINER(item), window->uriEntry);
@@ -637,12 +1090,18 @@ static void browserWindowConstructed(GObject *gObject)
BrowserWindow *window = BROWSER_WINDOW(gObject);
browserWindowUpdateZoomActions(window);
+ if (webkit_web_view_is_editable(window->webView)) {
+ browserWindowSetupEditorToolbar(window);
+ g_signal_connect(webkit_web_view_get_editor_state(window->webView), "notify::typing-attributes", G_CALLBACK(typingAttributesChanged), window);
+ }
g_signal_connect(window->webView, "notify::uri", G_CALLBACK(webViewURIChanged), window);
g_signal_connect(window->webView, "notify::estimated-load-progress", G_CALLBACK(webViewLoadProgressChanged), window);
g_signal_connect(window->webView, "notify::title", G_CALLBACK(webViewTitleChanged), window);
g_signal_connect(window->webView, "create", G_CALLBACK(webViewCreate), window);
+ g_signal_connect(window->webView, "close", G_CALLBACK(webViewClose), window);
g_signal_connect(window->webView, "load-failed", G_CALLBACK(webViewLoadFailed), window);
+ g_signal_connect(window->webView, "load-failed-with-tls-errors", G_CALLBACK(webViewLoadFailedWithTLSerrors), window);
g_signal_connect(window->webView, "decide-policy", G_CALLBACK(webViewDecidePolicy), window);
g_signal_connect(window->webView, "permission-request", G_CALLBACK(webViewDecidePermissionRequest), window);
g_signal_connect(window->webView, "mouse-target-changed", G_CALLBACK(webViewMouseTargetChanged), window);
@@ -651,6 +1110,10 @@ static void browserWindowConstructed(GObject *gObject)
g_signal_connect(window->webView, "enter-fullscreen", G_CALLBACK(webViewEnterFullScreen), window);
g_signal_connect(window->webView, "leave-fullscreen", G_CALLBACK(webViewLeaveFullScreen), window);
g_signal_connect(window->webView, "notify::is-loading", G_CALLBACK(webViewIsLoadingChanged), window);
+ g_signal_connect(window->webView, "scroll-event", G_CALLBACK(scrollEventCallback), window);
+#if GTK_CHECK_VERSION(3, 12, 0)
+ g_signal_connect(window->webView, "run-color-chooser", G_CALLBACK(runColorChooserCallback), window);
+#endif
g_signal_connect(webkit_web_view_get_context(window->webView), "download-started", G_CALLBACK(downloadStarted), window);
@@ -661,6 +1124,10 @@ static void browserWindowConstructed(GObject *gObject)
WebKitBackForwardList *backForwadlist = webkit_web_view_get_back_forward_list(window->webView);
g_signal_connect(backForwadlist, "changed", G_CALLBACK(backForwadlistChanged), window);
+ WebKitWebInspector *inspectorWindow = webkit_web_view_get_inspector(WEBKIT_WEB_VIEW(window->webView));
+ g_signal_connect(inspectorWindow, "open-window", G_CALLBACK(inspectorWasOpenedInAnotherWindow), window);
+ g_signal_connect(inspectorWindow, "closed", G_CALLBACK(inspectorWasClosed), window);
+
GtkWidget *overlay = gtk_overlay_new();
gtk_box_pack_start(GTK_BOX(window->mainBox), overlay, TRUE, TRUE, 0);
gtk_widget_show(overlay);
@@ -682,6 +1149,29 @@ static void browserWindowConstructed(GObject *gObject)
gtk_widget_set_no_show_all(window->fullScreenMessageLabel, TRUE);
gtk_overlay_add_overlay(GTK_OVERLAY(overlay), window->fullScreenMessageLabel);
gtk_widget_show(GTK_WIDGET(window->webView));
+
+ if (webkit_web_view_is_editable(window->webView))
+ webkit_web_view_load_html(window->webView, "<html></html>", "file:///");
+}
+
+static void browserWindowSaveSession(BrowserWindow *window)
+{
+ if (!window->sessionFile)
+ return;
+
+ WebKitWebViewSessionState *state = webkit_web_view_get_session_state(window->webView);
+ GBytes *bytes = webkit_web_view_session_state_serialize(state);
+ webkit_web_view_session_state_unref(state);
+ g_file_set_contents(window->sessionFile, g_bytes_get_data(bytes, NULL), g_bytes_get_size(bytes), NULL);
+ g_bytes_unref(bytes);
+}
+
+static gboolean browserWindowDeleteEvent(GtkWidget *widget, GdkEventAny* event)
+{
+ BrowserWindow *window = BROWSER_WINDOW(widget);
+ browserWindowSaveSession(window);
+ webkit_web_view_try_close(window->webView);
+ return TRUE;
}
static void browser_window_class_init(BrowserWindowClass *klass)
@@ -693,6 +1183,9 @@ static void browser_window_class_init(BrowserWindowClass *klass)
gobjectClass->set_property = browserWindowSetProperty;
gobjectClass->finalize = browserWindowFinalize;
+ GtkWidgetClass *widgetClass = GTK_WIDGET_CLASS(klass);
+ widgetClass->delete_event = browserWindowDeleteEvent;
+
g_object_class_install_property(gobjectClass,
PROP_VIEW,
g_param_spec_object("view",
@@ -739,3 +1232,53 @@ void browser_window_load_uri(BrowserWindow *window, const char *uri)
webkit_web_view_run_javascript(window->webView, strstr(uri, "javascript:"), NULL, NULL, NULL);
}
+
+void browser_window_load_session(BrowserWindow *window, const char *sessionFile)
+{
+ g_return_if_fail(BROWSER_IS_WINDOW(window));
+ g_return_if_fail(sessionFile);
+
+ window->sessionFile = g_strdup(sessionFile);
+ gchar *data = NULL;
+ gsize dataLength;
+ if (g_file_get_contents(sessionFile, &data, &dataLength, NULL)) {
+ GBytes *bytes = g_bytes_new_take(data, dataLength);
+ WebKitWebViewSessionState *state = webkit_web_view_session_state_new(bytes);
+ g_bytes_unref(bytes);
+
+ if (state) {
+ webkit_web_view_restore_session_state(window->webView, state);
+ webkit_web_view_session_state_unref(state);
+ }
+ }
+
+ WebKitBackForwardList *bfList = webkit_web_view_get_back_forward_list(window->webView);
+ WebKitBackForwardListItem *item = webkit_back_forward_list_get_current_item(bfList);
+ if (item)
+ webkit_web_view_go_to_back_forward_list_item(window->webView, item);
+ else
+ webkit_web_view_load_uri(window->webView, BROWSER_DEFAULT_URL);
+
+}
+
+void browser_window_set_background_color(BrowserWindow *window, GdkRGBA *rgba)
+{
+ g_return_if_fail(BROWSER_IS_WINDOW(window));
+ g_return_if_fail(rgba);
+
+ GdkRGBA viewRGBA;
+ webkit_web_view_get_background_color(window->webView, &viewRGBA);
+ if (gdk_rgba_equal(rgba, &viewRGBA))
+ return;
+
+ if (rgba->alpha < 1) {
+ GdkVisual *rgbaVisual = gdk_screen_get_rgba_visual(gtk_window_get_screen(GTK_WINDOW(window)));
+ if (!rgbaVisual)
+ return;
+
+ gtk_widget_set_visual(GTK_WIDGET(window), rgbaVisual);
+ gtk_widget_set_app_paintable(GTK_WIDGET(window), TRUE);
+ }
+
+ webkit_web_view_set_background_color(window->webView, rgba);
+}
diff --git a/Tools/MiniBrowser/gtk/BrowserWindow.h b/Tools/MiniBrowser/gtk/BrowserWindow.h
index 66675462f..97ae7b92f 100644
--- a/Tools/MiniBrowser/gtk/BrowserWindow.h
+++ b/Tools/MiniBrowser/gtk/BrowserWindow.h
@@ -37,6 +37,7 @@ G_BEGIN_DECLS
#define BROWSER_IS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), BROWSER_TYPE_WINDOW))
#define BROWSER_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), BROWSER_TYPE_WINDOW))
#define BROWSER_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), BROWSER_TYPE_WINDOW, BrowserWindowClass))
+#define BROWSER_DEFAULT_URL "http://www.webkitgtk.org/"
typedef struct _BrowserWindow BrowserWindow;
typedef struct _BrowserWindowClass BrowserWindowClass;
@@ -46,6 +47,8 @@ GType browser_window_get_type(void);
GtkWidget* browser_window_new(WebKitWebView*, GtkWindow*);
WebKitWebView* browser_window_get_view(BrowserWindow*);
void browser_window_load_uri(BrowserWindow *, const char *uri);
+void browser_window_load_session(BrowserWindow *, const char *sessionFile);
+void browser_window_set_background_color(BrowserWindow*, GdkRGBA*);
G_END_DECLS
diff --git a/Tools/MiniBrowser/gtk/CMakeLists.txt b/Tools/MiniBrowser/gtk/CMakeLists.txt
new file mode 100644
index 000000000..94eecfa13
--- /dev/null
+++ b/Tools/MiniBrowser/gtk/CMakeLists.txt
@@ -0,0 +1,63 @@
+set(MINIBROWSER_DIR "${TOOLS_DIR}/MiniBrowser/gtk")
+set(DERIVED_SOURCES_MINIBROWSER_DIR "${CMAKE_BINARY_DIR}/DerivedSources/MiniBrowser")
+
+file(MAKE_DIRECTORY ${DERIVED_SOURCES_MINIBROWSER_DIR})
+
+set(MiniBrowser_SOURCES
+ ${DERIVED_SOURCES_MINIBROWSER_DIR}/BrowserMarshal.c
+ ${MINIBROWSER_DIR}/BrowserCellRendererVariant.c
+ ${MINIBROWSER_DIR}/BrowserCellRendererVariant.h
+ ${MINIBROWSER_DIR}/BrowserDownloadsBar.c
+ ${MINIBROWSER_DIR}/BrowserDownloadsBar.h
+ ${MINIBROWSER_DIR}/BrowserSearchBar.c
+ ${MINIBROWSER_DIR}/BrowserSearchBar.h
+ ${MINIBROWSER_DIR}/BrowserSettingsDialog.c
+ ${MINIBROWSER_DIR}/BrowserSettingsDialog.h
+ ${MINIBROWSER_DIR}/BrowserWindow.c
+ ${MINIBROWSER_DIR}/BrowserWindow.h
+ ${MINIBROWSER_DIR}/main.c
+)
+
+set(MiniBrowser_INCLUDE_DIRECTORIES
+ ${CMAKE_BINARY_DIR}
+ ${DERIVED_SOURCES_MINIBROWSER_DIR}
+ ${DERIVED_SOURCES_WEBKIT2GTK_DIR}
+ ${FORWARDING_HEADERS_WEBKIT2GTK_DIR}
+ ${FORWARDING_HEADERS_DIR}
+ ${CMAKE_SOURCE_DIR}/Source
+)
+
+set(MiniBrowser_SYSTEM_INCLUDE_DIRECTORIES
+ ${GTK3_INCLUDE_DIRS}
+ ${GLIB_INCLUDE_DIRS}
+ ${LIBSOUP_INCLUDE_DIRS}
+)
+
+set(MiniBrowser_LIBRARIES
+ ${JavaScriptCore_LIBRARY_NAME}
+ WebKit2
+ ${GTK3_LIBRARIES}
+ ${GLIB_LIBRARIES}
+)
+
+add_custom_command(
+ OUTPUT ${DERIVED_SOURCES_MINIBROWSER_DIR}/BrowserMarshal.c
+ ${DERIVED_SOURCES_MINIBROWSER_DIR}/BrowserMarshal.h
+ MAIN_DEPENDENCY ${MINIBROWSER_DIR}/browser-marshal.list
+ COMMAND glib-genmarshal --prefix=browser_marshal ${MINIBROWSER_DIR}/browser-marshal.list --body > ${DERIVED_SOURCES_MINIBROWSER_DIR}/BrowserMarshal.c
+ COMMAND glib-genmarshal --prefix=browser_marshal ${MINIBROWSER_DIR}/browser-marshal.list --header > ${DERIVED_SOURCES_MINIBROWSER_DIR}/BrowserMarshal.h
+ VERBATIM)
+
+if (DEVELOPER_MODE)
+ add_definitions(-DWEBKIT_INJECTED_BUNDLE_PATH="${CMAKE_LIBRARY_OUTPUT_DIRECTORY}")
+endif ()
+
+add_definitions(-DGDK_VERSION_MIN_REQUIRED=GDK_VERSION_3_6)
+
+include_directories(${MiniBrowser_INCLUDE_DIRECTORIES})
+include_directories(SYSTEM ${MiniBrowser_SYSTEM_INCLUDE_DIRECTORIES})
+add_executable(MiniBrowser ${MiniBrowser_SOURCES})
+target_link_libraries(MiniBrowser ${MiniBrowser_LIBRARIES})
+set_target_properties(MiniBrowser PROPERTIES FOLDER "Tools")
+
+install(TARGETS MiniBrowser DESTINATION "${EXEC_INSTALL_DIR}")
diff --git a/Tools/MiniBrowser/gtk/GNUmakefile.am b/Tools/MiniBrowser/gtk/GNUmakefile.am
deleted file mode 100644
index 8bdbdd33e..000000000
--- a/Tools/MiniBrowser/gtk/GNUmakefile.am
+++ /dev/null
@@ -1,75 +0,0 @@
-if ENABLE_WEBKIT2
-noinst_PROGRAMS += \
- Programs/MiniBrowser
-endif
-
-Programs_MiniBrowser_CPPFLAGS = \
- -I$(srcdir)/Source \
- -I$(top_builddir)/DerivedSources/WebKit2 \
- -I$(top_builddir)/DerivedSources/WebKit2/webkit2gtk \
- -I$(top_builddir)/DerivedSources/WebKit2/webkit2gtk/include \
- -DWEBKIT_EXEC_PATH=\"${shell pwd}/$(top_builddir)/Programs/\" \
- -DWEBKIT_INJECTED_BUNDLE_PATH=\"${shell pwd}/$(top_builddir)/.libs\" \
- -DGDK_VERSION_MIN_REQUIRED=GDK_VERSION_3_6 \
- $(global_cppflags) \
- $(javascriptcore_cppflags) \
- $(FREETYPE_CFLAGS) \
- $(GLIB_CFLAGS) \
- $(GTK_CFLAGS) \
- $(LIBSOUP_CFLAGS)
-
-Programs_MiniBrowser_SOURCES = \
- Tools/MiniBrowser/gtk/BrowserCellRendererVariant.h \
- Tools/MiniBrowser/gtk/BrowserCellRendererVariant.c \
- Tools/MiniBrowser/gtk/BrowserDownloadsBar.h \
- Tools/MiniBrowser/gtk/BrowserDownloadsBar.c \
- Tools/MiniBrowser/gtk/BrowserSearchBar.h \
- Tools/MiniBrowser/gtk/BrowserSearchBar.c \
- Tools/MiniBrowser/gtk/BrowserSettingsDialog.h \
- Tools/MiniBrowser/gtk/BrowserSettingsDialog.c \
- Tools/MiniBrowser/gtk/BrowserWindow.h \
- Tools/MiniBrowser/gtk/BrowserWindow.c \
- Tools/MiniBrowser/gtk/main.c
-
-minibrowser_built_sources += \
- DerivedSources/WebKit2/BrowserMarshal.h \
- DerivedSources/WebKit2/BrowserMarshal.c
-nodist_Programs_MiniBrowser_SOURCES = \
- $(minibrowser_built_sources)
-
-Programs_MiniBrowser_LDADD = \
- libwebkit2gtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \
- $(FREETYPE_LIBS) \
- $(GLIB_LIBS) \
- $(GTK_LIBS) \
- $(LIBSOUP_LIBS)
-
-Programs_MiniBrowser_LDFLAGS = \
- -no-install
-
-CLEANFILES += \
- $(top_builddir)/Programs/MiniBrowser \
- $(minibrowser_built_sources) \
- $(top_builddir)/stamp-mini-browser-marshal.h \
- $(top_builddir)/stamp-mini-browser-marshal.c
-
-BUILT_SOURCES += $(minibrowser_built_sources)
-
-minibrowser_marshal_list = $(srcdir)/Tools/MiniBrowser/gtk/browser-marshal.list
-
-$(GENSOURCES_WEBKIT2)/BrowserMarshal.h: stamp-mini-browser-marshal.h
- @true
-$(GENSOURCES_WEBKIT2)/BrowserMarshal.c: stamp-mini-browser-marshal.c
- @true
-
-stamp-mini-browser-marshal.c: $(minibrowser_marshal_list)
- $(AM_V_GEN)$(GLIB_GENMARSHAL) --prefix=browser_marshal $(minibrowser_marshal_list) --body > $(GENSOURCES_WEBKIT2)/BrowserMarshal.c && \
- echo timestamp > $(@F)
-
-stamp-mini-browser-marshal.h: $(minibrowser_marshal_list)
- $(AM_V_GEN)$(GLIB_GENMARSHAL) --prefix=browser_marshal $(minibrowser_marshal_list) --header > $(GENSOURCES_WEBKIT2)/BrowserMarshal.h && \
- echo timestamp > $(@F)
-
-EXTRA_DIST += \
- $(srcdir)/Tools/MiniBrowser/gtk/browser-marshal.list
-
diff --git a/Tools/MiniBrowser/gtk/main.c b/Tools/MiniBrowser/gtk/main.c
index e383fda83..85e21a101 100644
--- a/Tools/MiniBrowser/gtk/main.c
+++ b/Tools/MiniBrowser/gtk/main.c
@@ -12,10 +12,10 @@
* 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 COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -25,6 +25,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "cmakeconfig.h"
+
#include "BrowserWindow.h"
#include <errno.h>
#include <gtk/gtk.h>
@@ -35,6 +37,10 @@
static const gchar **uriArguments = NULL;
static const char *miniBrowserAboutScheme = "minibrowser-about";
+static GdkRGBA *backgroundColor;
+static gboolean editorMode;
+static const char *sessionFile;
+static char *geometry;
typedef enum {
MINI_BROWSER_ERROR_INVALID_ABOUT_PATH
@@ -54,24 +60,52 @@ static gchar *argumentToURL(const char *filename)
return fileURL;
}
-static void createBrowserWindow(const gchar *uri, WebKitSettings *webkitSettings)
+static void createBrowserWindow(const gchar *uri, WebKitSettings *webkitSettings, gboolean shouldLoadSession)
{
GtkWidget *webView = webkit_web_view_new();
+ if (editorMode)
+ webkit_web_view_set_editable(WEBKIT_WEB_VIEW(webView), TRUE);
GtkWidget *mainWindow = browser_window_new(WEBKIT_WEB_VIEW(webView), NULL);
- gchar *url = argumentToURL(uri);
+ if (backgroundColor)
+ browser_window_set_background_color(BROWSER_WINDOW(mainWindow), backgroundColor);
+ if (geometry)
+ gtk_window_parse_geometry(GTK_WINDOW(mainWindow), geometry);
if (webkitSettings)
webkit_web_view_set_settings(WEBKIT_WEB_VIEW(webView), webkitSettings);
- browser_window_load_uri(BROWSER_WINDOW(mainWindow), url);
- g_free(url);
+ if (!editorMode) {
+ if (shouldLoadSession && sessionFile)
+ browser_window_load_session(BROWSER_WINDOW(mainWindow), sessionFile);
+ else {
+ gchar *url = argumentToURL(uri);
+ browser_window_load_uri(BROWSER_WINDOW(mainWindow), url);
+ g_free(url);
+ }
+ }
gtk_widget_grab_focus(webView);
gtk_widget_show(mainWindow);
}
+static gboolean parseBackgroundColor(const char *optionName, const char *value, gpointer data, GError **error)
+{
+ GdkRGBA rgba;
+ if (gdk_rgba_parse(&rgba, value)) {
+ backgroundColor = gdk_rgba_copy(&rgba);
+ return TRUE;
+ }
+
+ g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, "Failed to parse '%s' as RGBA color", value);
+ return FALSE;
+}
+
static const GOptionEntry commandLineOptions[] =
{
+ { "bg-color", 0, 0, G_OPTION_ARG_CALLBACK, parseBackgroundColor, "Background color", NULL },
+ { "editor-mode", 'e', 0, G_OPTION_ARG_NONE, &editorMode, "Run in editor mode", NULL },
+ { "session-file", 's', 0, G_OPTION_ARG_FILENAME, &sessionFile, "Session file", "FILE" },
+ { "geometry", 'g', 0, G_OPTION_ARG_STRING, &geometry, "Set the size and position of the window (WIDTHxHEIGHT+X+Y)", "GEOMETRY" },
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &uriArguments, 0, "[URL…]" },
{ 0, 0, 0, 0, 0, 0, 0 }
};
@@ -238,12 +272,13 @@ aboutURISchemeRequestCallback(WebKitURISchemeRequest *request, gpointer userData
int main(int argc, char *argv[])
{
gtk_init(&argc, &argv);
+#if ENABLE_DEVELOPER_MODE
+ g_setenv("WEBKIT_INJECTED_BUNDLE_PATH", WEBKIT_INJECTED_BUNDLE_PATH, FALSE);
+#endif
- const gchar *multiprocess = g_getenv("MINIBROWSER_MULTIPROCESS");
- if (multiprocess && *multiprocess) {
- webkit_web_context_set_process_model(webkit_web_context_get_default(),
- WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES);
- }
+ const gchar *singleprocess = g_getenv("MINIBROWSER_SINGLEPROCESS");
+ webkit_web_context_set_process_model(webkit_web_context_get_default(), (singleprocess && *singleprocess) ?
+ WEBKIT_PROCESS_MODEL_SHARED_SECONDARY_PROCESS : WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES);
GOptionContext *context = g_option_context_new(NULL);
g_option_context_add_main_entries(context, commandLineOptions, 0);
@@ -265,8 +300,6 @@ int main(int argc, char *argv[])
}
g_option_context_free (context);
- g_setenv("WEBKIT_INJECTED_BUNDLE_PATH", WEBKIT_INJECTED_BUNDLE_PATH, FALSE);
-
// Enable the favicon database, by specifying the default directory.
webkit_web_context_set_favicon_database_directory(webkit_web_context_get_default(), NULL);
@@ -276,9 +309,9 @@ int main(int argc, char *argv[])
int i;
for (i = 0; uriArguments[i]; i++)
- createBrowserWindow(uriArguments[i], webkitSettings);
+ createBrowserWindow(uriArguments[i], webkitSettings, FALSE);
} else
- createBrowserWindow("http://www.webkitgtk.org/", webkitSettings);
+ createBrowserWindow(BROWSER_DEFAULT_URL, webkitSettings, TRUE);
g_clear_object(&webkitSettings);
diff --git a/Tools/Scripts/VCSUtils.pm b/Tools/Scripts/VCSUtils.pm
new file mode 100644
index 000000000..214150d12
--- /dev/null
+++ b/Tools/Scripts/VCSUtils.pm
@@ -0,0 +1,2338 @@
+# Copyright (C) 2007-2013, 2015 Apple Inc. All rights reserved.
+# Copyright (C) 2009, 2010 Chris Jerdonek (chris.jerdonek@gmail.com)
+# Copyright (C) 2010, 2011 Research In Motion Limited. All rights reserved.
+# Copyright (C) 2012 Daniel Bates (dbates@intudata.com)
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the name of Apple Inc. ("Apple") nor the names of
+# its contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Module to share code to work with various version control systems.
+package VCSUtils;
+
+use strict;
+use warnings;
+
+use Cwd qw(); # "qw()" prevents warnings about redefining getcwd() with "use POSIX;"
+use English; # for $POSTMATCH, etc.
+use File::Basename;
+use File::Spec;
+use POSIX;
+use Term::ANSIColor qw(colored);
+
+BEGIN {
+ use Exporter ();
+ our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
+ $VERSION = 1.00;
+ @ISA = qw(Exporter);
+ @EXPORT = qw(
+ &applyGitBinaryPatchDelta
+ &callSilently
+ &canonicalizePath
+ &changeLogEmailAddress
+ &changeLogName
+ &chdirReturningRelativePath
+ &decodeGitBinaryChunk
+ &decodeGitBinaryPatch
+ &determineSVNRoot
+ &determineVCSRoot
+ &escapeSubversionPath
+ &exitStatus
+ &fixChangeLogPatch
+ &gitBranch
+ &gitDirectory
+ &gitTreeDirectory
+ &gitdiff2svndiff
+ &isGit
+ &isGitSVN
+ &isGitBranchBuild
+ &isGitDirectory
+ &isGitSVNDirectory
+ &isSVN
+ &isSVNDirectory
+ &isSVNVersion16OrNewer
+ &makeFilePathRelative
+ &mergeChangeLogs
+ &normalizePath
+ &parseChunkRange
+ &parseFirstEOL
+ &parsePatch
+ &pathRelativeToSVNRepositoryRootForPath
+ &possiblyColored
+ &prepareParsedPatch
+ &removeEOL
+ &runCommand
+ &runPatchCommand
+ &scmMoveOrRenameFile
+ &scmToggleExecutableBit
+ &setChangeLogDateAndReviewer
+ &svnRevisionForDirectory
+ &svnStatus
+ &toWindowsLineEndings
+ &gitCommitForSVNRevision
+ &listOfChangedFilesBetweenRevisions
+ &unixPath
+ );
+ %EXPORT_TAGS = ( );
+ @EXPORT_OK = ();
+}
+
+our @EXPORT_OK;
+
+my $gitBranch;
+my $gitRoot;
+my $isGit;
+my $isGitSVN;
+my $isGitBranchBuild;
+my $isSVN;
+my $svnVersion;
+
+# Project time zone for Cupertino, CA, US
+my $changeLogTimeZone = "PST8PDT";
+
+my $unifiedDiffStartRegEx = qr#^--- ([abc]\/)?([^\r\n]+)#;
+my $gitDiffStartRegEx = qr#^diff --git [^\r\n]+#;
+my $gitDiffStartWithPrefixRegEx = qr#^diff --git \w/(.+) \w/([^\r\n]+)#; # We suppose that --src-prefix and --dst-prefix don't contain a non-word character (\W) and end with '/'.
+my $gitDiffStartWithoutPrefixNoSpaceRegEx = qr#^diff --git (\S+) (\S+)$#;
+my $svnDiffStartRegEx = qr#^Index: ([^\r\n]+)#;
+my $gitDiffStartWithoutPrefixSourceDirectoryPrefixRegExp = qr#^diff --git ([^/]+/)#;
+my $svnPropertiesStartRegEx = qr#^Property changes on: ([^\r\n]+)#; # $1 is normally the same as the index path.
+my $svnPropertyStartRegEx = qr#^(Modified|Name|Added|Deleted): ([^\r\n]+)#; # $2 is the name of the property.
+my $svnPropertyValueStartRegEx = qr#^\s*(\+|-|Merged|Reverse-merged)\s*([^\r\n]+)#; # $2 is the start of the property's value (which may span multiple lines).
+my $svnPropertyValueNoNewlineRegEx = qr#\ No newline at end of property#;
+
+# This method is for portability. Return the system-appropriate exit
+# status of a child process.
+#
+# Args: pass the child error status returned by the last pipe close,
+# for example "$?".
+sub exitStatus($)
+{
+ my ($returnvalue) = @_;
+ if (isWindows()) {
+ return $returnvalue >> 8;
+ }
+ if (!WIFEXITED($returnvalue)) {
+ return 254;
+ }
+ return WEXITSTATUS($returnvalue);
+}
+
+# Call a function while suppressing STDERR, and return the return values
+# as an array.
+sub callSilently($@) {
+ my ($func, @args) = @_;
+
+ # The following pattern was taken from here:
+ # http://www.sdsc.edu/~moreland/courses/IntroPerl/docs/manual/pod/perlfunc/open.html
+ #
+ # Also see this Perl documentation (search for "open OLDERR"):
+ # http://perldoc.perl.org/functions/open.html
+ open(OLDERR, ">&STDERR");
+ close(STDERR);
+ my @returnValue = &$func(@args);
+ open(STDERR, ">&OLDERR");
+ close(OLDERR);
+
+ return @returnValue;
+}
+
+sub toWindowsLineEndings
+{
+ my ($text) = @_;
+ $text =~ s/\n/\r\n/g;
+ return $text;
+}
+
+# Note, this method will not error if the file corresponding to the $source path does not exist.
+sub scmMoveOrRenameFile
+{
+ my ($source, $destination) = @_;
+ return if ! -e $source;
+ if (isSVN()) {
+ my $escapedDestination = escapeSubversionPath($destination);
+ my $escapedSource = escapeSubversionPath($source);
+ system("svn", "move", $escapedSource, $escapedDestination);
+ } elsif (isGit()) {
+ system("git", "mv", $source, $destination);
+ }
+}
+
+# Note, this method will not error if the file corresponding to the path does not exist.
+sub scmToggleExecutableBit
+{
+ my ($path, $executableBitDelta) = @_;
+ return if ! -e $path;
+ if ($executableBitDelta == 1) {
+ scmAddExecutableBit($path);
+ } elsif ($executableBitDelta == -1) {
+ scmRemoveExecutableBit($path);
+ }
+}
+
+sub scmAddExecutableBit($)
+{
+ my ($path) = @_;
+
+ if (isSVN()) {
+ my $escapedPath = escapeSubversionPath($path);
+ system("svn", "propset", "svn:executable", "on", $escapedPath) == 0 or die "Failed to run 'svn propset svn:executable on $escapedPath'.";
+ } elsif (isGit()) {
+ chmod(0755, $path);
+ }
+}
+
+sub scmRemoveExecutableBit($)
+{
+ my ($path) = @_;
+
+ if (isSVN()) {
+ my $escapedPath = escapeSubversionPath($path);
+ system("svn", "propdel", "svn:executable", $escapedPath) == 0 or die "Failed to run 'svn propdel svn:executable $escapedPath'.";
+ } elsif (isGit()) {
+ chmod(0664, $path);
+ }
+}
+
+sub isGitDirectory($)
+{
+ my ($dir) = @_;
+ return system("cd $dir && git rev-parse > " . File::Spec->devnull() . " 2>&1") == 0;
+}
+
+sub isGit()
+{
+ return $isGit if defined $isGit;
+
+ $isGit = isGitDirectory(".");
+ return $isGit;
+}
+
+sub isGitSVNDirectory($)
+{
+ my ($directory) = @_;
+
+ my $savedWorkingDirectory = Cwd::getcwd();
+ chdir($directory);
+
+ # There doesn't seem to be an officially documented way to determine
+ # if you're in a git-svn checkout. The best suggestions seen so far
+ # all use something like the following:
+ my $output = `git config --get svn-remote.svn.fetch 2>& 1`;
+ $isGitSVN = exitStatus($?) == 0 && $output ne "";
+ chdir($savedWorkingDirectory);
+ return $isGitSVN;
+}
+
+sub isGitSVN()
+{
+ return $isGitSVN if defined $isGitSVN;
+
+ $isGitSVN = isGitSVNDirectory(".");
+ return $isGitSVN;
+}
+
+sub gitDirectory()
+{
+ chomp(my $result = `git rev-parse --git-dir`);
+ return $result;
+}
+
+sub gitTreeDirectory()
+{
+ chomp(my $result = `git rev-parse --show-toplevel`);
+ return $result;
+}
+
+sub gitBisectStartBranch()
+{
+ my $bisectStartFile = File::Spec->catfile(gitDirectory(), "BISECT_START");
+ if (!-f $bisectStartFile) {
+ return "";
+ }
+ open(BISECT_START, $bisectStartFile) or die "Failed to open $bisectStartFile: $!";
+ chomp(my $result = <BISECT_START>);
+ close(BISECT_START);
+ return $result;
+}
+
+sub gitBranch()
+{
+ unless (defined $gitBranch) {
+ chomp($gitBranch = `git symbolic-ref -q HEAD`);
+ my $hasDetachedHead = exitStatus($?);
+ if ($hasDetachedHead) {
+ # We may be in a git bisect session.
+ $gitBranch = gitBisectStartBranch();
+ }
+ $gitBranch =~ s#^refs/heads/##;
+ $gitBranch = "" if $gitBranch eq "master";
+ }
+
+ return $gitBranch;
+}
+
+sub isGitBranchBuild()
+{
+ my $branch = gitBranch();
+ chomp(my $override = `git config --bool branch.$branch.webKitBranchBuild`);
+ return 1 if $override eq "true";
+ return 0 if $override eq "false";
+
+ unless (defined $isGitBranchBuild) {
+ chomp(my $gitBranchBuild = `git config --bool core.webKitBranchBuild`);
+ $isGitBranchBuild = $gitBranchBuild eq "true";
+ }
+
+ return $isGitBranchBuild;
+}
+
+sub isSVNDirectory($)
+{
+ my ($dir) = @_;
+ return system("cd $dir && svn info > " . File::Spec->devnull() . " 2>&1") == 0;
+}
+
+sub isSVN()
+{
+ return $isSVN if defined $isSVN;
+
+ $isSVN = isSVNDirectory(".");
+ return $isSVN;
+}
+
+sub svnVersion()
+{
+ return $svnVersion if defined $svnVersion;
+
+ if (!isSVN()) {
+ $svnVersion = 0;
+ } else {
+ chomp($svnVersion = `svn --version --quiet`);
+ }
+ return $svnVersion;
+}
+
+sub isSVNVersion16OrNewer()
+{
+ my $version = svnVersion();
+ return "v$version" ge v1.6;
+}
+
+sub chdirReturningRelativePath($)
+{
+ my ($directory) = @_;
+ my $previousDirectory = Cwd::getcwd();
+ chdir $directory;
+ my $newDirectory = Cwd::getcwd();
+ return "." if $newDirectory eq $previousDirectory;
+ return File::Spec->abs2rel($previousDirectory, $newDirectory);
+}
+
+sub determineSVNRoot()
+{
+ my $last = '';
+ my $path = '.';
+ my $parent = '..';
+ my $repositoryRoot;
+ my $repositoryUUID;
+ while (1) {
+ my $thisRoot;
+ my $thisUUID;
+ my $escapedPath = escapeSubversionPath($path);
+ # Ignore error messages in case we've run past the root of the checkout.
+ open INFO, "svn info '$escapedPath' 2> " . File::Spec->devnull() . " |" or die;
+ while (<INFO>) {
+ if (/^Repository Root: (.+)/) {
+ $thisRoot = $1;
+ }
+ if (/^Repository UUID: (.+)/) {
+ $thisUUID = $1;
+ }
+ if ($thisRoot && $thisUUID) {
+ local $/ = undef;
+ <INFO>; # Consume the rest of the input.
+ }
+ }
+ close INFO;
+
+ # It's possible (e.g. for developers of some ports) to have a WebKit
+ # checkout in a subdirectory of another checkout. So abort if the
+ # repository root or the repository UUID suddenly changes.
+ last if !$thisUUID;
+ $repositoryUUID = $thisUUID if !$repositoryUUID;
+ last if $thisUUID ne $repositoryUUID;
+
+ last if !$thisRoot;
+ $repositoryRoot = $thisRoot if !$repositoryRoot;
+ last if $thisRoot ne $repositoryRoot;
+
+ $last = $path;
+ $path = File::Spec->catdir($parent, $path);
+ }
+
+ return File::Spec->rel2abs($last);
+}
+
+sub determineVCSRoot()
+{
+ if (isGit()) {
+ # This is the working tree root. If WebKit is a submodule,
+ # then the relevant metadata directory is somewhere else.
+ return gitTreeDirectory();
+ }
+
+ if (!isSVN()) {
+ # Some users have a workflow where svn-create-patch, svn-apply and
+ # svn-unapply are used outside of multiple svn working directores,
+ # so warn the user and assume Subversion is being used in this case.
+ warn "Unable to determine VCS root for '" . Cwd::getcwd() . "'; assuming Subversion";
+ $isSVN = 1;
+ }
+
+ return determineSVNRoot();
+}
+
+sub isWindows()
+{
+ return ($^O eq "MSWin32") || 0;
+}
+
+sub svnRevisionForDirectory($)
+{
+ my ($dir) = @_;
+ my $revision;
+
+ if (isSVNDirectory($dir)) {
+ my $escapedDir = escapeSubversionPath($dir);
+ my $command = "svn info $escapedDir | grep Revision:";
+ $command = "LC_ALL=C $command" if !isWindows();
+ my $svnInfo = `$command`;
+ ($revision) = ($svnInfo =~ m/Revision: (\d+).*/g);
+ } elsif (isGitDirectory($dir)) {
+ my $command = "git log --grep=\"git-svn-id: \" -n 1 | grep git-svn-id:";
+ $command = "LC_ALL=C $command" if !isWindows();
+ $command = "cd $dir && $command";
+ my $gitLog = `$command`;
+ ($revision) = ($gitLog =~ m/ +git-svn-id: .+@(\d+) /g);
+ }
+ if (!defined($revision)) {
+ $revision = "unknown";
+ warn "Unable to determine current SVN revision in $dir";
+ }
+ return $revision;
+}
+
+sub pathRelativeToSVNRepositoryRootForPath($)
+{
+ my ($file) = @_;
+ my $relativePath = File::Spec->abs2rel($file);
+
+ my $svnInfo;
+ if (isSVN()) {
+ my $escapedRelativePath = escapeSubversionPath($relativePath);
+ my $command = "svn info $escapedRelativePath";
+ $command = "LC_ALL=C $command" if !isWindows();
+ $svnInfo = `$command`;
+ } elsif (isGit()) {
+ my $command = "git svn info $relativePath";
+ $command = "LC_ALL=C $command" if !isWindows();
+ $svnInfo = `$command`;
+ }
+
+ $svnInfo =~ /.*^URL: (.*?)$/m;
+ my $svnURL = $1;
+
+ $svnInfo =~ /.*^Repository Root: (.*?)$/m;
+ my $repositoryRoot = $1;
+
+ $svnURL =~ s/$repositoryRoot\///;
+ return $svnURL;
+}
+
+sub makeFilePathRelative($)
+{
+ my ($path) = @_;
+ return $path unless isGit();
+
+ unless (defined $gitRoot) {
+ chomp($gitRoot = `git rev-parse --show-cdup`);
+ }
+ return $gitRoot . $path;
+}
+
+sub normalizePath($)
+{
+ my ($path) = @_;
+ if (isWindows()) {
+ $path =~ s/\//\\/g;
+ } else {
+ $path =~ s/\\/\//g;
+ }
+ return $path;
+}
+
+sub unixPath($)
+{
+ my ($path) = @_;
+ $path =~ s/\\/\//g;
+ return $path;
+}
+
+sub possiblyColored($$)
+{
+ my ($colors, $string) = @_;
+
+ if (-t STDOUT) {
+ return colored([$colors], $string);
+ } else {
+ return $string;
+ }
+}
+
+sub adjustPathForRecentRenamings($)
+{
+ my ($fullPath) = @_;
+
+ $fullPath =~ s|WebCore/webaudio|WebCore/Modules/webaudio|g;
+ $fullPath =~ s|JavaScriptCore/wtf|WTF/wtf|g;
+ $fullPath =~ s|test_expectations.txt|TestExpectations|g;
+
+ return $fullPath;
+}
+
+sub canonicalizePath($)
+{
+ my ($file) = @_;
+
+ # Remove extra slashes and '.' directories in path
+ $file = File::Spec->canonpath($file);
+
+ # Remove '..' directories in path
+ my @dirs = ();
+ foreach my $dir (File::Spec->splitdir($file)) {
+ if ($dir eq '..' && $#dirs >= 0 && $dirs[$#dirs] ne '..') {
+ pop(@dirs);
+ } else {
+ push(@dirs, $dir);
+ }
+ }
+ return ($#dirs >= 0) ? File::Spec->catdir(@dirs) : ".";
+}
+
+sub removeEOL($)
+{
+ my ($line) = @_;
+ return "" unless $line;
+
+ $line =~ s/[\r\n]+$//g;
+ return $line;
+}
+
+sub parseFirstEOL($)
+{
+ my ($fileHandle) = @_;
+
+ # Make input record separator the new-line character to simplify regex matching below.
+ my $savedInputRecordSeparator = $INPUT_RECORD_SEPARATOR;
+ $INPUT_RECORD_SEPARATOR = "\n";
+ my $firstLine = <$fileHandle>;
+ $INPUT_RECORD_SEPARATOR = $savedInputRecordSeparator;
+
+ return unless defined($firstLine);
+
+ my $eol;
+ if ($firstLine =~ /\r\n/) {
+ $eol = "\r\n";
+ } elsif ($firstLine =~ /\r/) {
+ $eol = "\r";
+ } elsif ($firstLine =~ /\n/) {
+ $eol = "\n";
+ }
+ return $eol;
+}
+
+sub firstEOLInFile($)
+{
+ my ($file) = @_;
+ my $eol;
+ if (open(FILE, $file)) {
+ $eol = parseFirstEOL(*FILE);
+ close(FILE);
+ }
+ return $eol;
+}
+
+# Parses a chunk range line into its components.
+#
+# A chunk range line has the form: @@ -L_1,N_1 +L_2,N_2 @@, where the pairs (L_1, N_1),
+# (L_2, N_2) are ranges that represent the starting line number and line count in the
+# original file and new file, respectively.
+#
+# Note, some versions of GNU diff may omit the comma and trailing line count (e.g. N_1),
+# in which case the omitted line count defaults to 1. For example, GNU diff may output
+# @@ -1 +1 @@, which is equivalent to @@ -1,1 +1,1 @@.
+#
+# This subroutine returns undef if given an invalid or malformed chunk range.
+#
+# Args:
+# $line: the line to parse.
+# $chunkSentinel: the sentinel that surrounds the chunk range information (defaults to "@@").
+#
+# Returns $chunkRangeHashRef
+# $chunkRangeHashRef: a hash reference representing the parts of a chunk range, as follows--
+# startingLine: the starting line in the original file.
+# lineCount: the line count in the original file.
+# newStartingLine: the new starting line in the new file.
+# newLineCount: the new line count in the new file.
+sub parseChunkRange($;$)
+{
+ my ($line, $chunkSentinel) = @_;
+ $chunkSentinel = "@@" if !$chunkSentinel;
+ my $chunkRangeRegEx = qr#^\Q$chunkSentinel\E -(\d+)(,(\d+))? \+(\d+)(,(\d+))? \Q$chunkSentinel\E#;
+ if ($line !~ /$chunkRangeRegEx/) {
+ return;
+ }
+ my %chunkRange;
+ $chunkRange{startingLine} = $1;
+ $chunkRange{lineCount} = defined($2) ? $3 : 1;
+ $chunkRange{newStartingLine} = $4;
+ $chunkRange{newLineCount} = defined($5) ? $6 : 1;
+ return \%chunkRange;
+}
+
+sub svnStatus($)
+{
+ my ($fullPath) = @_;
+ my $escapedFullPath = escapeSubversionPath($fullPath);
+ my $svnStatus;
+ open SVN, "svn status --non-interactive --non-recursive '$escapedFullPath' |" or die;
+ if (-d $fullPath) {
+ # When running "svn stat" on a directory, we can't assume that only one
+ # status will be returned (since any files with a status below the
+ # directory will be returned), and we can't assume that the directory will
+ # be first (since any files with unknown status will be listed first).
+ my $normalizedFullPath = File::Spec->catdir(File::Spec->splitdir($fullPath));
+ while (<SVN>) {
+ # Input may use a different EOL sequence than $/, so avoid chomp.
+ $_ = removeEOL($_);
+ my $normalizedStatPath = File::Spec->catdir(File::Spec->splitdir(substr($_, 7)));
+ if ($normalizedFullPath eq $normalizedStatPath) {
+ $svnStatus = "$_\n";
+ last;
+ }
+ }
+ # Read the rest of the svn command output to avoid a broken pipe warning.
+ local $/ = undef;
+ <SVN>;
+ }
+ else {
+ # Files will have only one status returned.
+ $svnStatus = removeEOL(<SVN>) . "\n";
+ }
+ close SVN;
+ return $svnStatus;
+}
+
+# Return whether the given file mode is executable in the source control
+# sense. We make this determination based on whether the executable bit
+# is set for "others" rather than the stronger condition that it be set
+# for the user, group, and others. This is sufficient for distinguishing
+# the default behavior in Git and SVN.
+#
+# Args:
+# $fileMode: A number or string representing a file mode in octal notation.
+sub isExecutable($)
+{
+ my $fileMode = shift;
+
+ return $fileMode % 2;
+}
+
+# Parse the Git diff header start line.
+#
+# Args:
+# $line: "diff --git" line.
+#
+# Returns the path of the target file.
+sub parseGitDiffStartLine($)
+{
+ my $line = shift;
+ $_ = $line;
+ if (/$gitDiffStartWithPrefixRegEx/ || /$gitDiffStartWithoutPrefixNoSpaceRegEx/) {
+ return $2;
+ }
+ # Assume the diff was generated with --no-prefix (e.g. git diff --no-prefix).
+ if (!/$gitDiffStartWithoutPrefixSourceDirectoryPrefixRegExp/) {
+ # FIXME: Moving top directory file is not supported (e.g diff --git A.txt B.txt).
+ die("Could not find '/' in \"diff --git\" line: \"$line\"; only non-prefixed git diffs (i.e. not generated with --no-prefix) that move a top-level directory file are supported.");
+ }
+ my $pathPrefix = $1;
+ if (!/^diff --git \Q$pathPrefix\E.+ (\Q$pathPrefix\E.+)$/) {
+ # FIXME: Moving a file through sub directories of top directory is not supported (e.g diff --git A/B.txt C/B.txt).
+ die("Could not find '/' in \"diff --git\" line: \"$line\"; only non-prefixed git diffs (i.e. not generated with --no-prefix) that move a file between top-level directories are supported.");
+ }
+ return $1;
+}
+
+# Parse the next Git diff header from the given file handle, and advance
+# the handle so the last line read is the first line after the header.
+#
+# This subroutine dies if given leading junk.
+#
+# Args:
+# $fileHandle: advanced so the last line read from the handle is the first
+# line of the header to parse. This should be a line
+# beginning with "diff --git".
+# $line: the line last read from $fileHandle
+#
+# Returns ($headerHashRef, $lastReadLine):
+# $headerHashRef: a hash reference representing a diff header, as follows--
+# copiedFromPath: the path from which the file was copied or moved if
+# the diff is a copy or move.
+# executableBitDelta: the value 1 or -1 if the executable bit was added or
+# removed, respectively. New and deleted files have
+# this value only if the file is executable, in which
+# case the value is 1 and -1, respectively.
+# indexPath: the path of the target file.
+# isBinary: the value 1 if the diff is for a binary file.
+# isDeletion: the value 1 if the diff is a file deletion.
+# isCopyWithChanges: the value 1 if the file was copied or moved and
+# the target file was changed in some way after being
+# copied or moved (e.g. if its contents or executable
+# bit were changed).
+# isNew: the value 1 if the diff is for a new file.
+# shouldDeleteSource: the value 1 if the file was copied or moved and
+# the source file was deleted -- i.e. if the copy
+# was actually a move.
+# svnConvertedText: the header text with some lines converted to SVN
+# format. Git-specific lines are preserved.
+# $lastReadLine: the line last read from $fileHandle.
+sub parseGitDiffHeader($$)
+{
+ my ($fileHandle, $line) = @_;
+
+ $_ = $line;
+
+ my $indexPath;
+ if (/$gitDiffStartRegEx/) {
+ # Use $POSTMATCH to preserve the end-of-line character.
+ my $eol = $POSTMATCH;
+
+ # The first and second paths can differ in the case of copies
+ # and renames. We use the second file path because it is the
+ # destination path.
+ $indexPath = adjustPathForRecentRenamings(parseGitDiffStartLine($_));
+
+ $_ = "Index: $indexPath$eol"; # Convert to SVN format.
+ } else {
+ die("Could not parse leading \"diff --git\" line: \"$line\".");
+ }
+
+ my $copiedFromPath;
+ my $foundHeaderEnding;
+ my $isBinary;
+ my $isDeletion;
+ my $isNew;
+ my $newExecutableBit = 0;
+ my $oldExecutableBit = 0;
+ my $shouldDeleteSource = 0;
+ my $similarityIndex = 0;
+ my $svnConvertedText;
+ while (1) {
+ # Temporarily strip off any end-of-line characters to simplify
+ # regex matching below.
+ s/([\n\r]+)$//;
+ my $eol = $1;
+
+ if (/^(deleted file|old) mode (\d+)/) {
+ $oldExecutableBit = (isExecutable($2) ? 1 : 0);
+ $isDeletion = 1 if $1 eq "deleted file";
+ } elsif (/^new( file)? mode (\d+)/) {
+ $newExecutableBit = (isExecutable($2) ? 1 : 0);
+ $isNew = 1 if $1;
+ } elsif (/^similarity index (\d+)%/) {
+ $similarityIndex = $1;
+ } elsif (/^copy from ([^\t\r\n]+)/) {
+ $copiedFromPath = $1;
+ } elsif (/^rename from ([^\t\r\n]+)/) {
+ # FIXME: Record this as a move rather than as a copy-and-delete.
+ # This will simplify adding rename support to svn-unapply.
+ # Otherwise, the hash for a deletion would have to know
+ # everything about the file being deleted in order to
+ # support undoing itself. Recording as a move will also
+ # permit us to use "svn move" and "git move".
+ $copiedFromPath = $1;
+ $shouldDeleteSource = 1;
+ } elsif (/^--- \S+/) {
+ # Convert to SVN format.
+ # We emit the suffix "\t(revision 0)" to handle $indexPath which contains a space character.
+ # The patch(1) command thinks a file path is characters before a tab.
+ # This suffix make our diff more closely match the SVN diff format.
+ $_ = "--- $indexPath\t(revision 0)";
+ } elsif (/^\+\+\+ \S+/) {
+ # Convert to SVN format.
+ # We emit the suffix "\t(working copy)" to handle $indexPath which contains a space character.
+ # The patch(1) command thinks a file path is characters before a tab.
+ # This suffix make our diff more closely match the SVN diff format.
+ $_ = "+++ $indexPath\t(working copy)";
+ $foundHeaderEnding = 1;
+ } elsif (/^GIT binary patch$/ ) {
+ $isBinary = 1;
+ $foundHeaderEnding = 1;
+ # The "git diff" command includes a line of the form "Binary files
+ # <path1> and <path2> differ" if the --binary flag is not used.
+ } elsif (/^Binary files / ) {
+ die("Error: the Git diff contains a binary file without the binary data in ".
+ "line: \"$_\". Be sure to use the --binary flag when invoking \"git diff\" ".
+ "with diffs containing binary files.");
+ }
+
+ $svnConvertedText .= "$_$eol"; # Also restore end-of-line characters.
+
+ $_ = <$fileHandle>; # Not defined if end-of-file reached.
+
+ last if (!defined($_) || /$gitDiffStartRegEx/ || $foundHeaderEnding);
+ }
+
+ my $executableBitDelta = $newExecutableBit - $oldExecutableBit;
+
+ my %header;
+
+ $header{copiedFromPath} = $copiedFromPath if $copiedFromPath;
+ $header{executableBitDelta} = $executableBitDelta if $executableBitDelta;
+ $header{indexPath} = $indexPath;
+ $header{isBinary} = $isBinary if $isBinary;
+ $header{isCopyWithChanges} = 1 if ($copiedFromPath && ($similarityIndex != 100 || $executableBitDelta));
+ $header{isDeletion} = $isDeletion if $isDeletion;
+ $header{isNew} = $isNew if $isNew;
+ $header{shouldDeleteSource} = $shouldDeleteSource if $shouldDeleteSource;
+ $header{svnConvertedText} = $svnConvertedText;
+
+ return (\%header, $_);
+}
+
+# Parse the next SVN diff header from the given file handle, and advance
+# the handle so the last line read is the first line after the header.
+#
+# This subroutine dies if given leading junk or if it could not detect
+# the end of the header block.
+#
+# Args:
+# $fileHandle: advanced so the last line read from the handle is the first
+# line of the header to parse. This should be a line
+# beginning with "Index:".
+# $line: the line last read from $fileHandle
+#
+# Returns ($headerHashRef, $lastReadLine):
+# $headerHashRef: a hash reference representing a diff header, as follows--
+# copiedFromPath: the path from which the file was copied if the diff
+# is a copy.
+# indexPath: the path of the target file, which is the path found in
+# the "Index:" line.
+# isBinary: the value 1 if the diff is for a binary file.
+# isNew: the value 1 if the diff is for a new file.
+# sourceRevision: the revision number of the source, if it exists. This
+# is the same as the revision number the file was copied
+# from, in the case of a file copy.
+# svnConvertedText: the header text converted to a header with the paths
+# in some lines corrected.
+# $lastReadLine: the line last read from $fileHandle.
+sub parseSvnDiffHeader($$)
+{
+ my ($fileHandle, $line) = @_;
+
+ $_ = $line;
+
+ my $indexPath;
+ if (/$svnDiffStartRegEx/) {
+ $indexPath = adjustPathForRecentRenamings($1);
+ } else {
+ die("First line of SVN diff does not begin with \"Index \": \"$_\"");
+ }
+
+ my $copiedFromPath;
+ my $foundHeaderEnding;
+ my $isBinary;
+ my $isNew;
+ my $sourceRevision;
+ my $svnConvertedText;
+ while (1) {
+ # Temporarily strip off any end-of-line characters to simplify
+ # regex matching below.
+ s/([\n\r]+)$//;
+ my $eol = $1;
+
+ # Fix paths on "---" and "+++" lines to match the leading
+ # index line.
+ if (s/^--- [^\t\n\r]+/--- $indexPath/) {
+ # ---
+ if (/^--- .+\(revision (\d+)\)/) {
+ $sourceRevision = $1;
+ $isNew = 1 if !$sourceRevision; # if revision 0.
+ if (/\(from (\S+):(\d+)\)$/) {
+ # The "from" clause is created by svn-create-patch, in
+ # which case there is always also a "revision" clause.
+ $copiedFromPath = $1;
+ die("Revision number \"$2\" in \"from\" clause does not match " .
+ "source revision number \"$sourceRevision\".") if ($2 != $sourceRevision);
+ }
+ }
+ } elsif (s/^\+\+\+ [^\t\n\r]+/+++ $indexPath/ || $isBinary && /^$/) {
+ $foundHeaderEnding = 1;
+ } elsif (/^Cannot display: file marked as a binary type.$/) {
+ $isBinary = 1;
+ # SVN 1.7 has an unusual display format for a binary diff. It repeats the first
+ # two lines of the diff header. For example:
+ # Index: test_file.swf
+ # ===================================================================
+ # Cannot display: file marked as a binary type.
+ # svn:mime-type = application/octet-stream
+ # Index: test_file.swf
+ # ===================================================================
+ # --- test_file.swf
+ # +++ test_file.swf
+ #
+ # ...
+ # Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+ # Therefore, we continue reading the diff header until we either encounter a line
+ # that begins with "+++" (SVN 1.7 or greater) or an empty line (SVN version less
+ # than 1.7).
+ }
+
+ $svnConvertedText .= "$_$eol"; # Also restore end-of-line characters.
+
+ $_ = <$fileHandle>; # Not defined if end-of-file reached.
+
+ last if (!defined($_) || !$isBinary && /$svnDiffStartRegEx/ || $foundHeaderEnding);
+ }
+
+ if (!$foundHeaderEnding) {
+ die("Did not find end of header block corresponding to index path \"$indexPath\".");
+ }
+
+ my %header;
+
+ $header{copiedFromPath} = $copiedFromPath if $copiedFromPath;
+ $header{indexPath} = $indexPath;
+ $header{isBinary} = $isBinary if $isBinary;
+ $header{isNew} = $isNew if $isNew;
+ $header{sourceRevision} = $sourceRevision if $sourceRevision;
+ $header{svnConvertedText} = $svnConvertedText;
+
+ return (\%header, $_);
+}
+
+# Parse the next Unified diff header from the given file handle, and advance
+# the handle so the last line read is the first line after the header.
+#
+# This subroutine dies if given leading junk.
+#
+# Args:
+# $fileHandle: advanced so the last line read from the handle is the first
+# line of the header to parse. This should be a line
+# beginning with "Index:".
+# $line: the line last read from $fileHandle
+#
+# Returns ($headerHashRef, $lastReadLine):
+# $headerHashRef: a hash reference representing a diff header, as follows--
+# indexPath: the path of the target file, which is the path found in
+# the "Index:" line.
+# isNew: the value 1 if the diff is for a new file.
+# isDeletion: the value 1 if the diff is a file deletion.
+# svnConvertedText: the header text converted to a header with the paths
+# in some lines corrected.
+# $lastReadLine: the line last read from $fileHandle.
+sub parseUnifiedDiffHeader($$)
+{
+ my ($fileHandle, $line) = @_;
+
+ $_ = $line;
+
+ my $currentPosition = tell($fileHandle);
+ my $indexLine;
+ my $indexPath;
+ if (/$unifiedDiffStartRegEx/) {
+ # Use $POSTMATCH to preserve the end-of-line character.
+ my $eol = $POSTMATCH;
+
+ $indexPath = $2;
+
+ # In the case of an addition, we look at the next line for the index path
+ if ($indexPath eq "/dev/null") {
+ $_ = <$fileHandle>;
+ if (/^\+\+\+ ([abc]\/)?([^\t\n\r]+)/) {
+ $indexPath = $2;
+ } else {
+ die "Unrecognized unified diff format.";
+ }
+ $_ = $line;
+ }
+
+ $indexLine = "Index: $indexPath$eol"; # Convert to SVN format.
+ } else {
+ die("Could not parse leading \"---\" line: \"$line\".");
+ }
+
+ seek($fileHandle, $currentPosition, 0);
+
+ my $isDeletion;
+ my $isHeaderEnding;
+ my $isNew;
+ my $svnConvertedText = $indexLine;
+ while (1) {
+ # Temporarily strip off any end-of-line characters to simplify
+ # regex matching below.
+ s/([\n\r]+)$//;
+ my $eol = $1;
+
+ if (/^--- \/dev\/null/) {
+ $isNew = 1;
+ } elsif (/^\+\+\+ \/dev\/null/) {
+ $isDeletion = 1;
+ }
+
+ if (/^(---|\+\+\+) ([abc]\/)?([^\t\n\r]+)/) {
+ if ($1 eq "---") {
+ my $prependText = "";
+ $prependText = "new file mode 100644\n" if $isNew;
+ $_ = "${prependText}index 0000000..0000000\n$1 $3";
+ } else {
+ $_ = "$1 $3";
+ $isHeaderEnding = 1;
+ }
+ }
+
+ $svnConvertedText .= "$_$eol"; # Also restore end-of-line characters.
+
+ $currentPosition = tell($fileHandle);
+ $_ = <$fileHandle>; # Not defined if end-of-file reached.
+ last if (!defined($_) || /$unifiedDiffStartRegEx/ || $isHeaderEnding);
+ }
+
+ my %header;
+
+ $header{indexPath} = $indexPath;
+ $header{isDeletion} = $isDeletion if $isDeletion;
+ $header{isNew} = $isNew if $isNew;
+ $header{svnConvertedText} = $svnConvertedText;
+
+ return (\%header, $_);
+}
+
+# Parse the next diff header from the given file handle, and advance
+# the handle so the last line read is the first line after the header.
+#
+# This subroutine dies if given leading junk or if it could not detect
+# the end of the header block.
+#
+# Args:
+# $fileHandle: advanced so the last line read from the handle is the first
+# line of the header to parse. For SVN-formatted diffs, this
+# is a line beginning with "Index:". For Git, this is a line
+# beginning with "diff --git".
+# $line: the line last read from $fileHandle
+#
+# Returns ($headerHashRef, $lastReadLine):
+# $headerHashRef: a hash reference representing a diff header
+# copiedFromPath: the path from which the file was copied if the diff
+# is a copy.
+# executableBitDelta: the value 1 or -1 if the executable bit was added or
+# removed, respectively. New and deleted files have
+# this value only if the file is executable, in which
+# case the value is 1 and -1, respectively.
+# indexPath: the path of the target file.
+# isBinary: the value 1 if the diff is for a binary file.
+# isGit: the value 1 if the diff is Git-formatted.
+# isSvn: the value 1 if the diff is SVN-formatted.
+# sourceRevision: the revision number of the source, if it exists. This
+# is the same as the revision number the file was copied
+# from, in the case of a file copy.
+# svnConvertedText: the header text with some lines converted to SVN
+# format. Git-specific lines are preserved.
+# $lastReadLine: the line last read from $fileHandle.
+sub parseDiffHeader($$)
+{
+ my ($fileHandle, $line) = @_;
+
+ my $header; # This is a hash ref.
+ my $isGit;
+ my $isSvn;
+ my $isUnified;
+ my $lastReadLine;
+
+ if ($line =~ $svnDiffStartRegEx) {
+ $isSvn = 1;
+ ($header, $lastReadLine) = parseSvnDiffHeader($fileHandle, $line);
+ } elsif ($line =~ $gitDiffStartRegEx) {
+ $isGit = 1;
+ ($header, $lastReadLine) = parseGitDiffHeader($fileHandle, $line);
+ } elsif ($line =~ $unifiedDiffStartRegEx) {
+ $isUnified = 1;
+ ($header, $lastReadLine) = parseUnifiedDiffHeader($fileHandle, $line);
+ } else {
+ die("First line of diff does not begin with \"Index:\" or \"diff --git\": \"$line\"");
+ }
+
+ $header->{isGit} = $isGit if $isGit;
+ $header->{isSvn} = $isSvn if $isSvn;
+ $header->{isUnified} = $isUnified if $isUnified;
+
+ return ($header, $lastReadLine);
+}
+
+# FIXME: The %diffHash "object" should not have an svnConvertedText property.
+# Instead, the hash object should store its information in a
+# structured way as properties. This should be done in a way so
+# that, if necessary, the text of an SVN or Git patch can be
+# reconstructed from the information in those hash properties.
+#
+# A %diffHash is a hash representing a source control diff of a single
+# file operation (e.g. a file modification, copy, or delete).
+#
+# These hashes appear, for example, in the parseDiff(), parsePatch(),
+# and prepareParsedPatch() subroutines of this package.
+#
+# The corresponding values are--
+#
+# copiedFromPath: the path from which the file was copied if the diff
+# is a copy.
+# executableBitDelta: the value 1 or -1 if the executable bit was added or
+# removed from the target file, respectively.
+# indexPath: the path of the target file. For SVN-formatted diffs,
+# this is the same as the path in the "Index:" line.
+# isBinary: the value 1 if the diff is for a binary file.
+# isDeletion: the value 1 if the diff is known from the header to be a deletion.
+# isGit: the value 1 if the diff is Git-formatted.
+# isNew: the value 1 if the dif is known from the header to be a new file.
+# isSvn: the value 1 if the diff is SVN-formatted.
+# sourceRevision: the revision number of the source, if it exists. This
+# is the same as the revision number the file was copied
+# from, in the case of a file copy.
+# svnConvertedText: the diff with some lines converted to SVN format.
+# Git-specific lines are preserved.
+
+# Parse one diff from a patch file created by svn-create-patch, and
+# advance the file handle so the last line read is the first line
+# of the next header block.
+#
+# This subroutine preserves any leading junk encountered before the header.
+#
+# Composition of an SVN diff
+#
+# There are three parts to an SVN diff: the header, the property change, and
+# the binary contents, in that order. Either the header or the property change
+# may be ommitted, but not both. If there are binary changes, then you always
+# have all three.
+#
+# Args:
+# $fileHandle: a file handle advanced to the first line of the next
+# header block. Leading junk is okay.
+# $line: the line last read from $fileHandle.
+# $optionsHashRef: a hash reference representing optional options to use
+# when processing a diff.
+# shouldNotUseIndexPathEOL: whether to use the line endings in the diff instead
+# instead of the line endings in the target file; the
+# value of 1 if svnConvertedText should use the line
+# endings in the diff.
+#
+# Returns ($diffHashRefs, $lastReadLine):
+# $diffHashRefs: A reference to an array of references to %diffHash hashes.
+# See the %diffHash documentation above.
+# $lastReadLine: the line last read from $fileHandle
+sub parseDiff($$;$)
+{
+ # FIXME: Adjust this method so that it dies if the first line does not
+ # match the start of a diff. This will require a change to
+ # parsePatch() so that parsePatch() skips over leading junk.
+ my ($fileHandle, $line, $optionsHashRef) = @_;
+
+ my $headerStartRegEx = $svnDiffStartRegEx; # SVN-style header for the default
+
+ my $headerHashRef; # Last header found, as returned by parseDiffHeader().
+ my $svnPropertiesHashRef; # Last SVN properties diff found, as returned by parseSvnDiffProperties().
+ my $svnText;
+ my $indexPathEOL;
+ my $numTextChunks = 0;
+ while (defined($line)) {
+ if (!$headerHashRef && ($line =~ $gitDiffStartRegEx)) {
+ # Then assume all diffs in the patch are Git-formatted. This
+ # block was made to be enterable at most once since we assume
+ # all diffs in the patch are formatted the same (SVN or Git).
+ $headerStartRegEx = $gitDiffStartRegEx;
+ }
+
+ if (!$headerHashRef && ($line =~ $unifiedDiffStartRegEx)) {
+ $headerStartRegEx = $unifiedDiffStartRegEx;
+ }
+
+ if ($line =~ $svnPropertiesStartRegEx) {
+ my $propertyPath = $1;
+ if ($svnPropertiesHashRef || $headerHashRef && ($propertyPath ne $headerHashRef->{indexPath})) {
+ # This is the start of the second diff in the while loop, which happens to
+ # be a property diff. If $svnPropertiesHasRef is defined, then this is the
+ # second consecutive property diff, otherwise it's the start of a property
+ # diff for a file that only has property changes.
+ last;
+ }
+ ($svnPropertiesHashRef, $line) = parseSvnDiffProperties($fileHandle, $line);
+ next;
+ }
+ if ($line !~ $headerStartRegEx) {
+ # Then we are in the body of the diff.
+ my $isChunkRange = defined(parseChunkRange($line));
+ $numTextChunks += 1 if $isChunkRange;
+ my $nextLine = <$fileHandle>;
+ my $willAddNewLineAtEndOfFile = defined($nextLine) && $nextLine =~ /^\\ No newline at end of file$/;
+ if ($willAddNewLineAtEndOfFile) {
+ # Diff(1) always emits a LF character preceeding the line "\ No newline at end of file".
+ # We must preserve both the added LF character and the line ending of this sentinel line
+ # or patch(1) will complain.
+ $svnText .= $line . $nextLine;
+ $line = <$fileHandle>;
+ next;
+ }
+ if ($indexPathEOL && !$isChunkRange) {
+ # The chunk range is part of the body of the diff, but its line endings should't be
+ # modified or patch(1) will complain. So, we only modify non-chunk range lines.
+ $line =~ s/\r\n|\r|\n/$indexPathEOL/g;
+ }
+ $svnText .= $line;
+ $line = $nextLine;
+ next;
+ } # Otherwise, we found a diff header.
+
+ if ($svnPropertiesHashRef || $headerHashRef) {
+ # Then either we just processed an SVN property change or this
+ # is the start of the second diff header of this while loop.
+ last;
+ }
+
+ ($headerHashRef, $line) = parseDiffHeader($fileHandle, $line);
+ if (!$optionsHashRef || !$optionsHashRef->{shouldNotUseIndexPathEOL}) {
+ # FIXME: We shouldn't query the file system (via firstEOLInFile()) to determine the
+ # line endings of the file indexPath. Instead, either the caller to parseDiff()
+ # should provide this information or parseDiff() should take a delegate that it
+ # can use to query for this information.
+ $indexPathEOL = firstEOLInFile($headerHashRef->{indexPath}) if !$headerHashRef->{isNew} && !$headerHashRef->{isBinary};
+ }
+
+ $svnText .= $headerHashRef->{svnConvertedText};
+ }
+
+ my @diffHashRefs;
+
+ if ($headerHashRef->{shouldDeleteSource}) {
+ my %deletionHash;
+ $deletionHash{indexPath} = $headerHashRef->{copiedFromPath};
+ $deletionHash{isDeletion} = 1;
+ push @diffHashRefs, \%deletionHash;
+ }
+ if ($headerHashRef->{copiedFromPath}) {
+ my %copyHash;
+ $copyHash{copiedFromPath} = $headerHashRef->{copiedFromPath};
+ $copyHash{indexPath} = $headerHashRef->{indexPath};
+ $copyHash{sourceRevision} = $headerHashRef->{sourceRevision} if $headerHashRef->{sourceRevision};
+ if ($headerHashRef->{isSvn}) {
+ $copyHash{executableBitDelta} = $svnPropertiesHashRef->{executableBitDelta} if $svnPropertiesHashRef->{executableBitDelta};
+ }
+ push @diffHashRefs, \%copyHash;
+ }
+
+ # Note, the order of evaluation for the following if conditional has been explicitly chosen so that
+ # it evaluates to false when there is no headerHashRef (e.g. a property change diff for a file that
+ # only has property changes).
+ if ($headerHashRef->{isCopyWithChanges} || (%$headerHashRef && !$headerHashRef->{copiedFromPath})) {
+ # Then add the usual file modification.
+ my %diffHash;
+ # FIXME: We should expand this code to support other properties. In the future,
+ # parseSvnDiffProperties may return a hash whose keys are the properties.
+ if ($headerHashRef->{isSvn}) {
+ # SVN records the change to the executable bit in a separate property change diff
+ # that follows the contents of the diff, except for binary diffs. For binary
+ # diffs, the property change diff follows the diff header.
+ $diffHash{executableBitDelta} = $svnPropertiesHashRef->{executableBitDelta} if $svnPropertiesHashRef->{executableBitDelta};
+ } elsif ($headerHashRef->{isGit}) {
+ # Git records the change to the executable bit in the header of a diff.
+ $diffHash{executableBitDelta} = $headerHashRef->{executableBitDelta} if $headerHashRef->{executableBitDelta};
+ }
+ $diffHash{indexPath} = $headerHashRef->{indexPath};
+ $diffHash{isBinary} = $headerHashRef->{isBinary} if $headerHashRef->{isBinary};
+ $diffHash{isDeletion} = $headerHashRef->{isDeletion} if $headerHashRef->{isDeletion};
+ $diffHash{isGit} = $headerHashRef->{isGit} if $headerHashRef->{isGit};
+ $diffHash{isNew} = $headerHashRef->{isNew} if $headerHashRef->{isNew};
+ $diffHash{isSvn} = $headerHashRef->{isSvn} if $headerHashRef->{isSvn};
+ if (!$headerHashRef->{copiedFromPath}) {
+ # If the file was copied, then we have already incorporated the
+ # sourceRevision information into the change.
+ $diffHash{sourceRevision} = $headerHashRef->{sourceRevision} if $headerHashRef->{sourceRevision};
+ }
+ # FIXME: Remove the need for svnConvertedText. See the %diffHash
+ # code comments above for more information.
+ #
+ # Note, we may not always have SVN converted text since we intend
+ # to deprecate it in the future. For example, a property change
+ # diff for a file that only has property changes will not return
+ # any SVN converted text.
+ $diffHash{svnConvertedText} = $svnText if $svnText;
+ $diffHash{numTextChunks} = $numTextChunks if $svnText && !$headerHashRef->{isBinary};
+ push @diffHashRefs, \%diffHash;
+ }
+
+ if (!%$headerHashRef && $svnPropertiesHashRef) {
+ # A property change diff for a file that only has property changes.
+ my %propertyChangeHash;
+ $propertyChangeHash{executableBitDelta} = $svnPropertiesHashRef->{executableBitDelta} if $svnPropertiesHashRef->{executableBitDelta};
+ $propertyChangeHash{indexPath} = $svnPropertiesHashRef->{propertyPath};
+ $propertyChangeHash{isSvn} = 1;
+ push @diffHashRefs, \%propertyChangeHash;
+ }
+
+ return (\@diffHashRefs, $line);
+}
+
+# Parse an SVN property change diff from the given file handle, and advance
+# the handle so the last line read is the first line after this diff.
+#
+# For the case of an SVN binary diff, the binary contents will follow the
+# the property changes.
+#
+# This subroutine dies if the first line does not begin with "Property changes on"
+# or if the separator line that follows this line is missing.
+#
+# Args:
+# $fileHandle: advanced so the last line read from the handle is the first
+# line of the footer to parse. This line begins with
+# "Property changes on".
+# $line: the line last read from $fileHandle.
+#
+# Returns ($propertyHashRef, $lastReadLine):
+# $propertyHashRef: a hash reference representing an SVN diff footer.
+# propertyPath: the path of the target file.
+# executableBitDelta: the value 1 or -1 if the executable bit was added or
+# removed from the target file, respectively.
+# $lastReadLine: the line last read from $fileHandle.
+sub parseSvnDiffProperties($$)
+{
+ my ($fileHandle, $line) = @_;
+
+ $_ = $line;
+
+ my %footer;
+ if (/$svnPropertiesStartRegEx/) {
+ $footer{propertyPath} = $1;
+ } else {
+ die("Failed to find start of SVN property change, \"Property changes on \": \"$_\"");
+ }
+
+ # We advance $fileHandle two lines so that the next line that
+ # we process is $svnPropertyStartRegEx in a well-formed footer.
+ # A well-formed footer has the form:
+ # Property changes on: FileA
+ # ___________________________________________________________________
+ # Added: svn:executable
+ # + *
+ $_ = <$fileHandle>; # Not defined if end-of-file reached.
+ my $separator = "_" x 67;
+ if (defined($_) && /^$separator[\r\n]+$/) {
+ $_ = <$fileHandle>;
+ } else {
+ die("Failed to find separator line: \"$_\".");
+ }
+
+ # FIXME: We should expand this to support other SVN properties
+ # (e.g. return a hash of property key-values that represents
+ # all properties).
+ #
+ # Notice, we keep processing until we hit end-of-file or some
+ # line that does not resemble $svnPropertyStartRegEx, such as
+ # the empty line that precedes the start of the binary contents
+ # of a patch, or the start of the next diff (e.g. "Index:").
+ my $propertyHashRef;
+ while (defined($_) && /$svnPropertyStartRegEx/) {
+ ($propertyHashRef, $_) = parseSvnProperty($fileHandle, $_);
+ if ($propertyHashRef->{name} eq "svn:executable") {
+ # Notice, for SVN properties, propertyChangeDelta is always non-zero
+ # because a property can only be added or removed.
+ $footer{executableBitDelta} = $propertyHashRef->{propertyChangeDelta};
+ }
+ }
+
+ return(\%footer, $_);
+}
+
+# Parse the next SVN property from the given file handle, and advance the handle so the last
+# line read is the first line after the property.
+#
+# This subroutine dies if the first line is not a valid start of an SVN property,
+# or the property is missing a value, or the property change type (e.g. "Added")
+# does not correspond to the property value type (e.g. "+").
+#
+# Args:
+# $fileHandle: advanced so the last line read from the handle is the first
+# line of the property to parse. This should be a line
+# that matches $svnPropertyStartRegEx.
+# $line: the line last read from $fileHandle.
+#
+# Returns ($propertyHashRef, $lastReadLine):
+# $propertyHashRef: a hash reference representing a SVN property.
+# name: the name of the property.
+# value: the last property value. For instance, suppose the property is "Modified".
+# Then it has both a '-' and '+' property value in that order. Therefore,
+# the value of this key is the value of the '+' property by ordering (since
+# it is the last value).
+# propertyChangeDelta: the value 1 or -1 if the property was added or
+# removed, respectively.
+# $lastReadLine: the line last read from $fileHandle.
+sub parseSvnProperty($$)
+{
+ my ($fileHandle, $line) = @_;
+
+ $_ = $line;
+
+ my $propertyName;
+ my $propertyChangeType;
+ if (/$svnPropertyStartRegEx/) {
+ $propertyChangeType = $1;
+ $propertyName = $2;
+ } else {
+ die("Failed to find SVN property: \"$_\".");
+ }
+
+ $_ = <$fileHandle>; # Not defined if end-of-file reached.
+
+ if (defined($_) && defined(parseChunkRange($_, "##"))) {
+ # FIXME: We should validate the chunk range line that is part of an SVN 1.7
+ # property diff. For now, we ignore this line.
+ $_ = <$fileHandle>;
+ }
+
+ # The "svn diff" command neither inserts newline characters between property values
+ # nor between successive properties.
+ #
+ # As of SVN 1.7, "svn diff" may insert "\ No newline at end of property" after a
+ # property value that doesn't end in a newline.
+ #
+ # FIXME: We do not support property values that contain tailing newline characters
+ # as it is difficult to disambiguate these trailing newlines from the empty
+ # line that precedes the contents of a binary patch.
+ my $propertyValue;
+ my $propertyValueType;
+ while (defined($_) && /$svnPropertyValueStartRegEx/) {
+ # Note, a '-' property may be followed by a '+' property in the case of a "Modified"
+ # or "Name" property. We only care about the ending value (i.e. the '+' property)
+ # in such circumstances. So, we take the property value for the property to be its
+ # last parsed property value.
+ #
+ # FIXME: We may want to consider strictly enforcing a '-', '+' property ordering or
+ # add error checking to prevent '+', '+', ..., '+' and other invalid combinations.
+ $propertyValueType = $1;
+ ($propertyValue, $_) = parseSvnPropertyValue($fileHandle, $_);
+ $_ = <$fileHandle> if defined($_) && /$svnPropertyValueNoNewlineRegEx/;
+ }
+
+ if (!$propertyValue) {
+ die("Failed to find the property value for the SVN property \"$propertyName\": \"$_\".");
+ }
+
+ my $propertyChangeDelta;
+ if ($propertyValueType eq "+" || $propertyValueType eq "Merged") {
+ $propertyChangeDelta = 1;
+ } elsif ($propertyValueType eq "-" || $propertyValueType eq "Reverse-merged") {
+ $propertyChangeDelta = -1;
+ } else {
+ die("Not reached.");
+ }
+
+ # We perform a simple validation that an "Added" or "Deleted" property
+ # change type corresponds with a "+" and "-" value type, respectively.
+ my $expectedChangeDelta;
+ if ($propertyChangeType eq "Added") {
+ $expectedChangeDelta = 1;
+ } elsif ($propertyChangeType eq "Deleted") {
+ $expectedChangeDelta = -1;
+ }
+
+ if ($expectedChangeDelta && $propertyChangeDelta != $expectedChangeDelta) {
+ die("The final property value type found \"$propertyValueType\" does not " .
+ "correspond to the property change type found \"$propertyChangeType\".");
+ }
+
+ my %propertyHash;
+ $propertyHash{name} = $propertyName;
+ $propertyHash{propertyChangeDelta} = $propertyChangeDelta;
+ $propertyHash{value} = $propertyValue;
+ return (\%propertyHash, $_);
+}
+
+# Parse the value of an SVN property from the given file handle, and advance
+# the handle so the last line read is the first line after the property value.
+#
+# This subroutine dies if the first line is an invalid SVN property value line
+# (i.e. a line that does not begin with " +" or " -").
+#
+# Args:
+# $fileHandle: advanced so the last line read from the handle is the first
+# line of the property value to parse. This should be a line
+# beginning with " +" or " -".
+# $line: the line last read from $fileHandle.
+#
+# Returns ($propertyValue, $lastReadLine):
+# $propertyValue: the value of the property.
+# $lastReadLine: the line last read from $fileHandle.
+sub parseSvnPropertyValue($$)
+{
+ my ($fileHandle, $line) = @_;
+
+ $_ = $line;
+
+ my $propertyValue;
+ my $eol;
+ if (/$svnPropertyValueStartRegEx/) {
+ $propertyValue = $2; # Does not include the end-of-line character(s).
+ $eol = $POSTMATCH;
+ } else {
+ die("Failed to find property value beginning with '+', '-', 'Merged', or 'Reverse-merged': \"$_\".");
+ }
+
+ while (<$fileHandle>) {
+ if (/^[\r\n]+$/ || /$svnPropertyValueStartRegEx/ || /$svnPropertyStartRegEx/ || /$svnPropertyValueNoNewlineRegEx/) {
+ # Note, we may encounter an empty line before the contents of a binary patch.
+ # Also, we check for $svnPropertyValueStartRegEx because a '-' property may be
+ # followed by a '+' property in the case of a "Modified" or "Name" property.
+ # We check for $svnPropertyStartRegEx because it indicates the start of the
+ # next property to parse.
+ last;
+ }
+
+ # Temporarily strip off any end-of-line characters. We add the end-of-line characters
+ # from the previously processed line to the start of this line so that the last line
+ # of the property value does not end in end-of-line characters.
+ s/([\n\r]+)$//;
+ $propertyValue .= "$eol$_";
+ $eol = $1;
+ }
+
+ return ($propertyValue, $_);
+}
+
+# Parse a patch file created by svn-create-patch.
+#
+# Args:
+# $fileHandle: A file handle to the patch file that has not yet been
+# read from.
+# $optionsHashRef: a hash reference representing optional options to use
+# when processing a diff.
+# shouldNotUseIndexPathEOL: whether to use the line endings in the diff instead
+# instead of the line endings in the target file; the
+# value of 1 if svnConvertedText should use the line
+# endings in the diff.
+#
+# Returns:
+# @diffHashRefs: an array of diff hash references.
+# See the %diffHash documentation above.
+sub parsePatch($;$)
+{
+ my ($fileHandle, $optionsHashRef) = @_;
+
+ my $newDiffHashRefs;
+ my @diffHashRefs; # return value
+
+ my $line = <$fileHandle>;
+
+ while (defined($line)) { # Otherwise, at EOF.
+
+ ($newDiffHashRefs, $line) = parseDiff($fileHandle, $line, $optionsHashRef);
+
+ push @diffHashRefs, @$newDiffHashRefs;
+ }
+
+ return @diffHashRefs;
+}
+
+# Prepare the results of parsePatch() for use in svn-apply and svn-unapply.
+#
+# Args:
+# $shouldForce: Whether to continue processing if an unexpected
+# state occurs.
+# @diffHashRefs: An array of references to %diffHashes.
+# See the %diffHash documentation above.
+#
+# Returns $preparedPatchHashRef:
+# copyDiffHashRefs: A reference to an array of the $diffHashRefs in
+# @diffHashRefs that represent file copies. The original
+# ordering is preserved.
+# nonCopyDiffHashRefs: A reference to an array of the $diffHashRefs in
+# @diffHashRefs that do not represent file copies.
+# The original ordering is preserved.
+# sourceRevisionHash: A reference to a hash of source path to source
+# revision number.
+sub prepareParsedPatch($@)
+{
+ my ($shouldForce, @diffHashRefs) = @_;
+
+ my %copiedFiles;
+
+ # Return values
+ my @copyDiffHashRefs = ();
+ my @nonCopyDiffHashRefs = ();
+ my %sourceRevisionHash = ();
+ for my $diffHashRef (@diffHashRefs) {
+ my $copiedFromPath = $diffHashRef->{copiedFromPath};
+ my $indexPath = $diffHashRef->{indexPath};
+ my $sourceRevision = $diffHashRef->{sourceRevision};
+ my $sourcePath;
+
+ if (defined($copiedFromPath)) {
+ # Then the diff is a copy operation.
+ $sourcePath = $copiedFromPath;
+
+ # FIXME: Consider printing a warning or exiting if
+ # exists($copiedFiles{$indexPath}) is true -- i.e. if
+ # $indexPath appears twice as a copy target.
+ $copiedFiles{$indexPath} = $sourcePath;
+
+ push @copyDiffHashRefs, $diffHashRef;
+ } else {
+ # Then the diff is not a copy operation.
+ $sourcePath = $indexPath;
+
+ push @nonCopyDiffHashRefs, $diffHashRef;
+ }
+
+ if (defined($sourceRevision)) {
+ if (exists($sourceRevisionHash{$sourcePath}) &&
+ ($sourceRevisionHash{$sourcePath} != $sourceRevision)) {
+ if (!$shouldForce) {
+ die "Two revisions of the same file required as a source:\n".
+ " $sourcePath:$sourceRevisionHash{$sourcePath}\n".
+ " $sourcePath:$sourceRevision";
+ }
+ }
+ $sourceRevisionHash{$sourcePath} = $sourceRevision;
+ }
+ }
+
+ my %preparedPatchHash;
+
+ $preparedPatchHash{copyDiffHashRefs} = \@copyDiffHashRefs;
+ $preparedPatchHash{nonCopyDiffHashRefs} = \@nonCopyDiffHashRefs;
+ $preparedPatchHash{sourceRevisionHash} = \%sourceRevisionHash;
+
+ return \%preparedPatchHash;
+}
+
+# Return localtime() for the project's time zone, given an integer time as
+# returned by Perl's time() function.
+sub localTimeInProjectTimeZone($)
+{
+ my $epochTime = shift;
+
+ # Change the time zone temporarily for the localtime() call.
+ my $savedTimeZone = $ENV{'TZ'};
+ $ENV{'TZ'} = $changeLogTimeZone;
+ my @localTime = localtime($epochTime);
+ if (defined $savedTimeZone) {
+ $ENV{'TZ'} = $savedTimeZone;
+ } else {
+ delete $ENV{'TZ'};
+ }
+
+ return @localTime;
+}
+
+# Set the reviewer and date in a ChangeLog patch, and return the new patch.
+#
+# Args:
+# $patch: a ChangeLog patch as a string.
+# $reviewer: the name of the reviewer, or undef if the reviewer should not be set.
+# $epochTime: an integer time as returned by Perl's time() function.
+sub setChangeLogDateAndReviewer($$$)
+{
+ my ($patch, $reviewer, $epochTime) = @_;
+
+ my @localTime = localTimeInProjectTimeZone($epochTime);
+ my $newDate = strftime("%Y-%m-%d", @localTime);
+
+ my $firstChangeLogLineRegEx = qr#(\n\+)\d{4}-[^-]{2}-[^-]{2}( )#;
+ $patch =~ s/$firstChangeLogLineRegEx/$1$newDate$2/;
+
+ if (defined($reviewer)) {
+ # We include a leading plus ("+") in the regular expression to make
+ # the regular expression less likely to match text in the leading junk
+ # for the patch, if the patch has leading junk.
+ $patch =~ s/(\n\+.*)NOBODY \(OOPS!\)/$1$reviewer/;
+ }
+
+ return $patch;
+}
+
+# If possible, returns a ChangeLog patch equivalent to the given one,
+# but with the newest ChangeLog entry inserted at the top of the
+# file -- i.e. no leading context and all lines starting with "+".
+#
+# If given a patch string not representable as a patch with the above
+# properties, it returns the input back unchanged.
+#
+# WARNING: This subroutine can return an inequivalent patch string if
+# both the beginning of the new ChangeLog file matches the beginning
+# of the source ChangeLog, and the source beginning was modified.
+# Otherwise, it is guaranteed to return an equivalent patch string,
+# if it returns.
+#
+# Applying this subroutine to ChangeLog patches allows svn-apply to
+# insert new ChangeLog entries at the top of the ChangeLog file.
+# svn-apply uses patch with --fuzz=3 to do this. We need to apply
+# this subroutine because the diff(1) command is greedy when matching
+# lines. A new ChangeLog entry with the same date and author as the
+# previous will match and cause the diff to have lines of starting
+# context.
+#
+# This subroutine has unit tests in VCSUtils_unittest.pl.
+#
+# Returns $changeLogHashRef:
+# $changeLogHashRef: a hash reference representing a change log patch.
+# patch: a ChangeLog patch equivalent to the given one, but with the
+# newest ChangeLog entry inserted at the top of the file, if possible.
+sub fixChangeLogPatch($)
+{
+ my $patch = shift; # $patch will only contain patch fragments for ChangeLog.
+
+ $patch =~ s|test_expectations.txt:|TestExpectations:|g;
+
+ $patch =~ /(\r?\n)/;
+ my $lineEnding = $1;
+ my @lines = split(/$lineEnding/, $patch);
+
+ my $i = 0; # We reuse the same index throughout.
+
+ # Skip to beginning of first chunk.
+ for (; $i < @lines; ++$i) {
+ if (substr($lines[$i], 0, 1) eq "@") {
+ last;
+ }
+ }
+ my $chunkStartIndex = ++$i;
+ my %changeLogHashRef;
+
+ # Optimization: do not process if new lines already begin the chunk.
+ if (substr($lines[$i], 0, 1) eq "+") {
+ $changeLogHashRef{patch} = $patch;
+ return \%changeLogHashRef;
+ }
+
+ # Skip to first line of newly added ChangeLog entry.
+ # For example, +2009-06-03 Eric Seidel <eric@webkit.org>
+ my $dateStartRegEx = '^\+(\d{4}-\d{2}-\d{2})' # leading "+" and date
+ . '\s+(.+)\s+' # name
+ . '<([^<>]+)>$'; # e-mail address
+
+ for (; $i < @lines; ++$i) {
+ my $line = $lines[$i];
+ my $firstChar = substr($line, 0, 1);
+ if ($line =~ /$dateStartRegEx/) {
+ last;
+ } elsif ($firstChar eq " " or $firstChar eq "+") {
+ next;
+ }
+ $changeLogHashRef{patch} = $patch; # Do not change if, for example, "-" or "@" found.
+ return \%changeLogHashRef;
+ }
+ if ($i >= @lines) {
+ $changeLogHashRef{patch} = $patch; # Do not change if date not found.
+ return \%changeLogHashRef;
+ }
+ my $dateStartIndex = $i;
+
+ # Rewrite overlapping lines to lead with " ".
+ my @overlappingLines = (); # These will include a leading "+".
+ for (; $i < @lines; ++$i) {
+ my $line = $lines[$i];
+ if (substr($line, 0, 1) ne "+") {
+ last;
+ }
+ push(@overlappingLines, $line);
+ $lines[$i] = " " . substr($line, 1);
+ }
+
+ # Remove excess ending context, if necessary.
+ my $shouldTrimContext = 1;
+ for (; $i < @lines; ++$i) {
+ my $firstChar = substr($lines[$i], 0, 1);
+ if ($firstChar eq " ") {
+ next;
+ } elsif ($firstChar eq "@") {
+ last;
+ }
+ $shouldTrimContext = 0; # For example, if "+" or "-" encountered.
+ last;
+ }
+ my $deletedLineCount = 0;
+ if ($shouldTrimContext) { # Also occurs if end of file reached.
+ splice(@lines, $i - @overlappingLines, @overlappingLines);
+ $deletedLineCount = @overlappingLines;
+ }
+
+ # Work backwards, shifting overlapping lines towards front
+ # while checking that patch stays equivalent.
+ for ($i = $dateStartIndex - 1; @overlappingLines && $i >= $chunkStartIndex; --$i) {
+ my $line = $lines[$i];
+ if (substr($line, 0, 1) ne " ") {
+ next;
+ }
+ my $text = substr($line, 1);
+ my $newLine = pop(@overlappingLines);
+ if ($text ne substr($newLine, 1)) {
+ $changeLogHashRef{patch} = $patch; # Unexpected difference.
+ return \%changeLogHashRef;
+ }
+ $lines[$i] = "+$text";
+ }
+
+ # If @overlappingLines > 0, this is where we make use of the
+ # assumption that the beginning of the source file was not modified.
+ splice(@lines, $chunkStartIndex, 0, @overlappingLines);
+
+ # Update the date start index as it may have changed after shifting
+ # the overlapping lines towards the front.
+ for ($i = $chunkStartIndex; $i < $dateStartIndex; ++$i) {
+ $dateStartIndex = $i if $lines[$i] =~ /$dateStartRegEx/;
+ }
+ splice(@lines, $chunkStartIndex, $dateStartIndex - $chunkStartIndex); # Remove context of later entry.
+ $deletedLineCount += $dateStartIndex - $chunkStartIndex;
+
+ # Update the initial chunk range.
+ my $chunkRangeHashRef = parseChunkRange($lines[$chunkStartIndex - 1]);
+ if (!$chunkRangeHashRef) {
+ # FIXME: Handle errors differently from ChangeLog files that
+ # are okay but should not be altered. That way we can find out
+ # if improvements to the script ever become necessary.
+ $changeLogHashRef{patch} = $patch; # Error: unexpected patch string format.
+ return \%changeLogHashRef;
+ }
+ my $oldSourceLineCount = $chunkRangeHashRef->{lineCount};
+ my $oldTargetLineCount = $chunkRangeHashRef->{newLineCount};
+
+ my $sourceLineCount = $oldSourceLineCount + @overlappingLines - $deletedLineCount;
+ my $targetLineCount = $oldTargetLineCount + @overlappingLines - $deletedLineCount;
+ $lines[$chunkStartIndex - 1] = "@@ -1,$sourceLineCount +1,$targetLineCount @@";
+
+ $changeLogHashRef{patch} = join($lineEnding, @lines) . "\n"; # patch(1) expects an extra trailing newline.
+ return \%changeLogHashRef;
+}
+
+# This is a supporting method for runPatchCommand.
+#
+# Arg: the optional $args parameter passed to runPatchCommand (can be undefined).
+#
+# Returns ($patchCommand, $isForcing).
+#
+# This subroutine has unit tests in VCSUtils_unittest.pl.
+sub generatePatchCommand($)
+{
+ my ($passedArgsHashRef) = @_;
+
+ my $argsHashRef = { # Defaults
+ ensureForce => 0,
+ shouldReverse => 0,
+ options => []
+ };
+
+ # Merges hash references. It's okay here if passed hash reference is undefined.
+ @{$argsHashRef}{keys %{$passedArgsHashRef}} = values %{$passedArgsHashRef};
+
+ my $ensureForce = $argsHashRef->{ensureForce};
+ my $shouldReverse = $argsHashRef->{shouldReverse};
+ my $options = $argsHashRef->{options};
+
+ if (! $options) {
+ $options = [];
+ } else {
+ $options = [@{$options}]; # Copy to avoid side effects.
+ }
+
+ my $isForcing = 0;
+ if (grep /^--force$/, @{$options}) {
+ $isForcing = 1;
+ } elsif ($ensureForce) {
+ push @{$options}, "--force";
+ $isForcing = 1;
+ }
+
+ if ($shouldReverse) { # No check: --reverse should never be passed explicitly.
+ push @{$options}, "--reverse";
+ }
+
+ @{$options} = sort(@{$options}); # For easier testing.
+
+ my $patchCommand = join(" ", "patch -p0", @{$options});
+
+ return ($patchCommand, $isForcing);
+}
+
+# Apply the given patch using the patch(1) command.
+#
+# On success, return the resulting exit status. Otherwise, exit with the
+# exit status. If "--force" is passed as an option, however, then never
+# exit and always return the exit status.
+#
+# Args:
+# $patch: a patch string.
+# $repositoryRootPath: an absolute path to the repository root.
+# $pathRelativeToRoot: the path of the file to be patched, relative to the
+# repository root. This should normally be the path
+# found in the patch's "Index:" line. It is passed
+# explicitly rather than reparsed from the patch
+# string for optimization purposes.
+# This is used only for error reporting. The
+# patch command gleans the actual file to patch
+# from the patch string.
+# $args: a reference to a hash of optional arguments. The possible
+# keys are --
+# ensureForce: whether to ensure --force is passed (defaults to 0).
+# shouldReverse: whether to pass --reverse (defaults to 0).
+# options: a reference to an array of options to pass to the
+# patch command. The subroutine passes the -p0 option
+# no matter what. This should not include --reverse.
+#
+# This subroutine has unit tests in VCSUtils_unittest.pl.
+sub runPatchCommand($$$;$)
+{
+ my ($patch, $repositoryRootPath, $pathRelativeToRoot, $args) = @_;
+
+ my ($patchCommand, $isForcing) = generatePatchCommand($args);
+
+ # Temporarily change the working directory since the path found
+ # in the patch's "Index:" line is relative to the repository root
+ # (i.e. the same as $pathRelativeToRoot).
+ my $cwd = Cwd::getcwd();
+ chdir $repositoryRootPath;
+
+ open PATCH, "| $patchCommand" or die "Could not call \"$patchCommand\" for file \"$pathRelativeToRoot\": $!";
+ print PATCH $patch;
+ close PATCH;
+ my $exitStatus = exitStatus($?);
+
+ chdir $cwd;
+
+ if ($exitStatus && !$isForcing) {
+ print "Calling \"$patchCommand\" for file \"$pathRelativeToRoot\" returned " .
+ "status $exitStatus. Pass --force to ignore patch failures.\n";
+ exit $exitStatus;
+ }
+
+ return $exitStatus;
+}
+
+# Merge ChangeLog patches using a three-file approach.
+#
+# This is used by resolve-ChangeLogs when it's operated as a merge driver
+# and when it's used to merge conflicts after a patch is applied or after
+# an svn update.
+#
+# It's also used for traditional rejected patches.
+#
+# Args:
+# $fileMine: The merged version of the file. Also known in git as the
+# other branch's version (%B) or "ours".
+# For traditional patch rejects, this is the *.rej file.
+# $fileOlder: The base version of the file. Also known in git as the
+# ancestor version (%O) or "base".
+# For traditional patch rejects, this is the *.orig file.
+# $fileNewer: The current version of the file. Also known in git as the
+# current version (%A) or "theirs".
+# For traditional patch rejects, this is the original-named
+# file.
+#
+# Returns 1 if merge was successful, else 0.
+sub mergeChangeLogs($$$)
+{
+ my ($fileMine, $fileOlder, $fileNewer) = @_;
+
+ my $traditionalReject = $fileMine =~ /\.rej$/ ? 1 : 0;
+
+ local $/ = undef;
+
+ my $patch;
+ if ($traditionalReject) {
+ open(DIFF, "<", $fileMine) or die $!;
+ $patch = <DIFF>;
+ close(DIFF);
+ rename($fileMine, "$fileMine.save");
+ rename($fileOlder, "$fileOlder.save");
+ } else {
+ open(DIFF, "diff -u -a --binary \"$fileOlder\" \"$fileMine\" |") or die $!;
+ $patch = <DIFF>;
+ close(DIFF);
+ }
+
+ unlink("${fileNewer}.orig");
+ unlink("${fileNewer}.rej");
+
+ open(PATCH, "| patch --force --fuzz=3 --binary \"$fileNewer\" > " . File::Spec->devnull()) or die $!;
+ if ($traditionalReject) {
+ print PATCH $patch;
+ } else {
+ my $changeLogHash = fixChangeLogPatch($patch);
+ print PATCH $changeLogHash->{patch};
+ }
+ close(PATCH);
+
+ my $result = !exitStatus($?);
+
+ # Refuse to merge the patch if it did not apply cleanly
+ if (-e "${fileNewer}.rej") {
+ unlink("${fileNewer}.rej");
+ if (-f "${fileNewer}.orig") {
+ unlink($fileNewer);
+ rename("${fileNewer}.orig", $fileNewer);
+ }
+ } else {
+ unlink("${fileNewer}.orig");
+ }
+
+ if ($traditionalReject) {
+ rename("$fileMine.save", $fileMine);
+ rename("$fileOlder.save", $fileOlder);
+ }
+
+ return $result;
+}
+
+sub gitConfig($)
+{
+ return unless isGit();
+
+ my ($config) = @_;
+
+ my $result = `git config $config`;
+ chomp $result;
+ return $result;
+}
+
+sub changeLogNameError($)
+{
+ my ($message) = @_;
+ print STDERR "$message\nEither:\n";
+ print STDERR " set CHANGE_LOG_NAME in your environment\n";
+ print STDERR " OR pass --name= on the command line\n";
+ print STDERR " OR set REAL_NAME in your environment";
+ print STDERR " OR git users can set 'git config user.name'\n";
+ exit(1);
+}
+
+sub changeLogName()
+{
+ my $name = $ENV{CHANGE_LOG_NAME} || $ENV{REAL_NAME} || gitConfig("user.name");
+ if (not $name and !isWindows()) {
+ $name = (split /\s*,\s*/, (getpwuid $<)[6])[0];
+ }
+
+ changeLogNameError("Failed to determine ChangeLog name.") unless $name;
+ # getpwuid seems to always succeed on windows, returning the username instead of the full name. This check will catch that case.
+ changeLogNameError("'$name' does not contain a space! ChangeLogs should contain your full name.") unless ($name =~ /\S\s\S/);
+
+ return $name;
+}
+
+sub changeLogEmailAddressError($)
+{
+ my ($message) = @_;
+ print STDERR "$message\nEither:\n";
+ print STDERR " set CHANGE_LOG_EMAIL_ADDRESS in your environment\n";
+ print STDERR " OR pass --email= on the command line\n";
+ print STDERR " OR set EMAIL_ADDRESS in your environment\n";
+ print STDERR " OR git users can set 'git config user.email'\n";
+ exit(1);
+}
+
+sub changeLogEmailAddress()
+{
+ my $emailAddress = $ENV{CHANGE_LOG_EMAIL_ADDRESS} || $ENV{EMAIL_ADDRESS} || gitConfig("user.email");
+
+ changeLogEmailAddressError("Failed to determine email address for ChangeLog.") unless $emailAddress;
+ changeLogEmailAddressError("Email address '$emailAddress' does not contain '\@' and is likely invalid.") unless ($emailAddress =~ /\@/);
+
+ return $emailAddress;
+}
+
+# http://tools.ietf.org/html/rfc1924
+sub decodeBase85($)
+{
+ my ($encoded) = @_;
+ my %table;
+ my @characters = ('0'..'9', 'A'..'Z', 'a'..'z', '!', '#', '$', '%', '&', '(', ')', '*', '+', '-', ';', '<', '=', '>', '?', '@', '^', '_', '`', '{', '|', '}', '~');
+ for (my $i = 0; $i < 85; $i++) {
+ $table{$characters[$i]} = $i;
+ }
+
+ my $decoded = '';
+ my @encodedChars = $encoded =~ /./g;
+
+ for (my $encodedIter = 0; defined($encodedChars[$encodedIter]);) {
+ my $digit = 0;
+ for (my $i = 0; $i < 5; $i++) {
+ $digit *= 85;
+ my $char = $encodedChars[$encodedIter];
+ $digit += $table{$char};
+ $encodedIter++;
+ }
+
+ for (my $i = 0; $i < 4; $i++) {
+ $decoded .= chr(($digit >> (3 - $i) * 8) & 255);
+ }
+ }
+
+ return $decoded;
+}
+
+sub decodeGitBinaryChunk($$)
+{
+ my ($contents, $fullPath) = @_;
+
+ # Load this module lazily in case the user don't have this module
+ # and won't handle git binary patches.
+ require Compress::Zlib;
+
+ my $encoded = "";
+ my $compressedSize = 0;
+ while ($contents =~ /^([A-Za-z])(.*)$/gm) {
+ my $line = $2;
+ next if $line eq "";
+ die "$fullPath: unexpected size of a line: $&" if length($2) % 5 != 0;
+ my $actualSize = length($2) / 5 * 4;
+ my $encodedExpectedSize = ord($1);
+ my $expectedSize = $encodedExpectedSize <= ord("Z") ? $encodedExpectedSize - ord("A") + 1 : $encodedExpectedSize - ord("a") + 27;
+
+ die "$fullPath: unexpected size of a line: $&" if int(($expectedSize + 3) / 4) * 4 != $actualSize;
+ $compressedSize += $expectedSize;
+ $encoded .= $line;
+ }
+
+ my $compressed = decodeBase85($encoded);
+ $compressed = substr($compressed, 0, $compressedSize);
+ return Compress::Zlib::uncompress($compressed);
+}
+
+sub decodeGitBinaryPatch($$)
+{
+ my ($contents, $fullPath) = @_;
+
+ # Git binary patch has two chunks. One is for the normal patching
+ # and another is for the reverse patching.
+ #
+ # Each chunk a line which starts from either "literal" or "delta",
+ # followed by a number which specifies decoded size of the chunk.
+ #
+ # Then, content of the chunk comes. To decode the content, we
+ # need decode it with base85 first, and then zlib.
+ my $gitPatchRegExp = '(literal|delta) ([0-9]+)\n([A-Za-z0-9!#$%&()*+-;<=>?@^_`{|}~\\n]*?)\n\n';
+ if ($contents !~ m"\nGIT binary patch\n$gitPatchRegExp$gitPatchRegExp(\Z|-- \n)") {
+ return ();
+ }
+
+ my $binaryChunkType = $1;
+ my $binaryChunkExpectedSize = $2;
+ my $encodedChunk = $3;
+ my $reverseBinaryChunkType = $4;
+ my $reverseBinaryChunkExpectedSize = $5;
+ my $encodedReverseChunk = $6;
+
+ my $binaryChunk = decodeGitBinaryChunk($encodedChunk, $fullPath);
+ my $binaryChunkActualSize = length($binaryChunk);
+ my $reverseBinaryChunk = decodeGitBinaryChunk($encodedReverseChunk, $fullPath);
+ my $reverseBinaryChunkActualSize = length($reverseBinaryChunk);
+
+ die "$fullPath: unexpected size of the first chunk (expected $binaryChunkExpectedSize but was $binaryChunkActualSize" if ($binaryChunkType eq "literal" and $binaryChunkExpectedSize != $binaryChunkActualSize);
+ die "$fullPath: unexpected size of the second chunk (expected $reverseBinaryChunkExpectedSize but was $reverseBinaryChunkActualSize" if ($reverseBinaryChunkType eq "literal" and $reverseBinaryChunkExpectedSize != $reverseBinaryChunkActualSize);
+
+ return ($binaryChunkType, $binaryChunk, $reverseBinaryChunkType, $reverseBinaryChunk);
+}
+
+sub readByte($$)
+{
+ my ($data, $location) = @_;
+
+ # Return the byte at $location in $data as a numeric value.
+ return ord(substr($data, $location, 1));
+}
+
+# The git binary delta format is undocumented, except in code:
+# - https://github.com/git/git/blob/master/delta.h:get_delta_hdr_size is the source
+# of the algorithm in decodeGitBinaryPatchDeltaSize.
+# - https://github.com/git/git/blob/master/patch-delta.c:patch_delta is the source
+# of the algorithm in applyGitBinaryPatchDelta.
+sub decodeGitBinaryPatchDeltaSize($)
+{
+ my ($binaryChunk) = @_;
+
+ # Source and destination buffer sizes are stored in 7-bit chunks at the
+ # start of the binary delta patch data. The highest bit in each byte
+ # except the last is set; the remaining 7 bits provide the next
+ # chunk of the size. The chunks are stored in ascending significance
+ # order.
+ my $cmd;
+ my $size = 0;
+ my $shift = 0;
+ for (my $i = 0; $i < length($binaryChunk);) {
+ $cmd = readByte($binaryChunk, $i++);
+ $size |= ($cmd & 0x7f) << $shift;
+ $shift += 7;
+ if (!($cmd & 0x80)) {
+ return ($size, $i);
+ }
+ }
+}
+
+sub applyGitBinaryPatchDelta($$)
+{
+ my ($binaryChunk, $originalContents) = @_;
+
+ # Git delta format consists of two headers indicating source buffer size
+ # and result size, then a series of commands. Each command is either
+ # a copy-from-old-version (the 0x80 bit is set) or a copy-from-delta
+ # command. Commands are applied sequentially to generate the result.
+ #
+ # A copy-from-old-version command encodes an offset and size to copy
+ # from in subsequent bits, while a copy-from-delta command consists only
+ # of the number of bytes to copy from the delta.
+
+ # We don't use these values, but we need to know how big they are so that
+ # we can skip to the diff data.
+ my ($size, $bytesUsed) = decodeGitBinaryPatchDeltaSize($binaryChunk);
+ $binaryChunk = substr($binaryChunk, $bytesUsed);
+ ($size, $bytesUsed) = decodeGitBinaryPatchDeltaSize($binaryChunk);
+ $binaryChunk = substr($binaryChunk, $bytesUsed);
+
+ my $out = "";
+ for (my $i = 0; $i < length($binaryChunk); ) {
+ my $cmd = ord(substr($binaryChunk, $i++, 1));
+ if ($cmd & 0x80) {
+ # Extract an offset and size from the delta data, then copy
+ # $size bytes from $offset in the original data into the output.
+ my $offset = 0;
+ my $size = 0;
+ if ($cmd & 0x01) { $offset = readByte($binaryChunk, $i++); }
+ if ($cmd & 0x02) { $offset |= readByte($binaryChunk, $i++) << 8; }
+ if ($cmd & 0x04) { $offset |= readByte($binaryChunk, $i++) << 16; }
+ if ($cmd & 0x08) { $offset |= readByte($binaryChunk, $i++) << 24; }
+ if ($cmd & 0x10) { $size = readByte($binaryChunk, $i++); }
+ if ($cmd & 0x20) { $size |= readByte($binaryChunk, $i++) << 8; }
+ if ($cmd & 0x40) { $size |= readByte($binaryChunk, $i++) << 16; }
+ if ($size == 0) { $size = 0x10000; }
+ $out .= substr($originalContents, $offset, $size);
+ } elsif ($cmd) {
+ # Copy $cmd bytes from the delta data into the output.
+ $out .= substr($binaryChunk, $i, $cmd);
+ $i += $cmd;
+ } else {
+ die "unexpected delta opcode 0";
+ }
+ }
+
+ return $out;
+}
+
+sub escapeSubversionPath($)
+{
+ my ($path) = @_;
+ $path .= "@" if $path =~ /@/;
+ return $path;
+}
+
+sub runCommand(@)
+{
+ my @args = @_;
+ my $pid = open(CHILD, "-|");
+ if (!defined($pid)) {
+ die "Failed to fork(): $!";
+ }
+ if ($pid) {
+ # Parent process
+ my $childStdout;
+ while (<CHILD>) {
+ $childStdout .= $_;
+ }
+ close(CHILD);
+ my %childOutput;
+ $childOutput{exitStatus} = exitStatus($?);
+ $childOutput{stdout} = $childStdout if $childStdout;
+ return \%childOutput;
+ }
+ # Child process
+ # FIXME: Consider further hardening of this function, including sanitizing the environment.
+ exec { $args[0] } @args or die "Failed to exec(): $!";
+}
+
+sub gitCommitForSVNRevision
+{
+ my ($svnRevision) = @_;
+ my $command = "git svn find-rev r" . $svnRevision;
+ $command = "LC_ALL=C $command" if !isWindows();
+ my $gitHash = `$command`;
+ if (!defined($gitHash)) {
+ $gitHash = "unknown";
+ warn "Unable to determine GIT commit from SVN revision";
+ } else {
+ chop($gitHash);
+ }
+ return $gitHash;
+}
+
+sub listOfChangedFilesBetweenRevisions
+{
+ my ($sourceDir, $firstRevision, $lastRevision) = @_;
+ my $command;
+
+ if ($firstRevision eq "unknown" or $lastRevision eq "unknown") {
+ return ();
+ }
+
+ # Some VCS functions don't work from within the build dir, so always
+ # go to the source dir first.
+ my $cwd = Cwd::getcwd();
+ chdir $sourceDir;
+
+ if (isGit()) {
+ my $firstCommit = gitCommitForSVNRevision($firstRevision);
+ my $lastCommit = gitCommitForSVNRevision($lastRevision);
+ $command = "git diff --name-status $firstCommit..$lastCommit";
+ } elsif (isSVN()) {
+ $command = "svn diff --summarize -r $firstRevision:$lastRevision";
+ }
+
+ my @result = ();
+
+ if ($command) {
+ my $diffOutput = `$command`;
+ $diffOutput =~ s/^[A-Z]\s+//gm;
+ @result = split(/[\r\n]+/, $diffOutput);
+ }
+
+ chdir $cwd;
+
+ return @result;
+}
+
+
+1;
diff --git a/Tools/Scripts/run-gtk-tests b/Tools/Scripts/run-gtk-tests
new file mode 100755
index 000000000..752d4893e
--- /dev/null
+++ b/Tools/Scripts/run-gtk-tests
@@ -0,0 +1,468 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2011, 2012 Igalia S.L.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public License
+# along with this library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+import subprocess
+import os
+import sys
+import optparse
+import re
+from signal import alarm, signal, SIGALRM, SIGKILL, SIGSEGV
+from gi.repository import Gio, GLib
+
+top_level_directory = os.path.normpath(os.path.join(os.path.dirname(__file__), "..", ".."))
+sys.path.append(os.path.join(top_level_directory, "Tools", "jhbuild"))
+sys.path.append(os.path.join(top_level_directory, "Tools", "gtk"))
+import common
+import jhbuildutils
+
+class SkippedTest:
+ ENTIRE_SUITE = None
+
+ def __init__(self, test, test_case, reason, bug, build_type=None):
+ self.test = test
+ self.test_case = test_case
+ self.reason = reason
+ self.bug = bug
+ self.build_type = build_type
+
+ def __str__(self):
+ skipped_test_str = "%s" % self.test
+
+ if not(self.skip_entire_suite()):
+ skipped_test_str += " [%s]" % self.test_case
+
+ skipped_test_str += ": %s (https://bugs.webkit.org/show_bug.cgi?id=%d)" % (self.reason, self.bug)
+ return skipped_test_str
+
+ def skip_entire_suite(self):
+ return self.test_case == SkippedTest.ENTIRE_SUITE
+
+ def skip_for_build_type(self, build_type):
+ if self.build_type is None:
+ return True;
+
+ return self.build_type == build_type
+
+class TestTimeout(Exception):
+ pass
+
+class TestRunner:
+ TEST_DIRS = [ "WebKit2Gtk", "WebKit2", "JavaScriptCore", "WTF", "WebCore" ]
+
+ SKIPPED = [
+ SkippedTest("WebKit2Gtk/TestUIClient", "/webkit2/WebKitWebView/mouse-target", "Test times out after r150890", 117689),
+ SkippedTest("WebKit2Gtk/TestCookieManager", "/webkit2/WebKitCookieManager/persistent-storage", "Test is flaky", 134580),
+ SkippedTest("WebKit2Gtk/TestWebViewEditor", "/webkit2/WebKitWebView/editable/editable", "Test hits an assertion in Debug builds", 151654, "Debug"),
+ SkippedTest("WebKit2Gtk/TestWebExtensions", "/webkit2/WebKitWebView/install-missing-plugins-permission-request", "Test times out", 147822),
+ SkippedTest("WebKit2/TestWebKit2", "WebKit2.MouseMoveAfterCrash", "Test is flaky", 85066),
+ SkippedTest("WebKit2/TestWebKit2", "WebKit2.NewFirstVisuallyNonEmptyLayoutForImages", "Test is flaky", 85066),
+ SkippedTest("WebKit2/TestWebKit2", "WebKit2.NewFirstVisuallyNonEmptyLayoutFrames", "Test fails", 85037),
+ SkippedTest("WebKit2/TestWebKit2", "WebKit2.SpacebarScrolling", "Test fails", 84961),
+ SkippedTest("WebKit2/TestWebKit2", "WebKit2.WKConnection", "Tests fail and time out out", 84959),
+ SkippedTest("WebKit2/TestWebKit2", "WebKit2.ForceRepaint", "Test times out", 105532),
+ SkippedTest("WebKit2/TestWebKit2", "WebKit2.ReloadPageAfterCrash", "Test flakily times out", 110129),
+ SkippedTest("WebKit2/TestWebKit2", "WebKit2.DidAssociateFormControls", "Test times out", 120302),
+ SkippedTest("WebKit2/TestWebKit2", "WebKit2.InjectedBundleFrameHitTest", "Test times out", 120303),
+ SkippedTest("WebKit2/TestWebKit2", "WebKit2.TerminateTwice", "Test causes crash on the next test", 121970),
+ SkippedTest("WebKit2/TestWebKit2", "WebKit2.GeolocationTransitionToHighAccuracy", "Test causes crash on the next test", 125068),
+ SkippedTest("WebKit2/TestWebKit2", "WebKit2.GeolocationTransitionToLowAccuracy", "Test causes crash on the next test", 125068),
+ SkippedTest("WebKit2/UserMedia", "WebKit2.UserMediaBasic", "We will not test by default until the upgrade gstreamer to 1.9", 153540),
+ ]
+
+ SLOW = [
+ "WTF_Lock.ContendedShortSection",
+ "WTF_WordLock.ContendedShortSection"
+ ]
+
+ def __init__(self, options, tests=[]):
+ self._options = options
+
+ self._build_type = "Debug" if self._options.debug else "Release"
+ common.set_build_types((self._build_type,))
+
+ self._programs_path = common.binary_build_path()
+ self._tests = self._get_tests(tests)
+ self._skipped_tests = [skipped for skipped in TestRunner.SKIPPED if skipped.skip_for_build_type(self._build_type)]
+ self._disabled_tests = []
+
+ # These SPI daemons need to be active for the accessibility tests to work.
+ self._spi_registryd = None
+ self._spi_bus_launcher = None
+
+ def _test_programs_base_dir(self):
+ return os.path.join(self._programs_path, "TestWebKitAPI")
+
+ def _get_tests_from_dir(self, test_dir):
+ if not os.path.isdir(test_dir):
+ return []
+
+ tests = []
+ for test_file in os.listdir(test_dir):
+ if not test_file.lower().startswith("test"):
+ continue
+ test_path = os.path.join(test_dir, test_file)
+ if os.path.isfile(test_path) and os.access(test_path, os.X_OK):
+ tests.append(test_path)
+ return tests
+
+ def _get_tests(self, initial_tests):
+ tests = []
+ for test in initial_tests:
+ if os.path.isdir(test):
+ tests.extend(self._get_tests_from_dir(test))
+ else:
+ tests.append(test)
+ if tests:
+ return tests
+
+ tests = []
+ for test_dir in self.TEST_DIRS:
+ absolute_test_dir = os.path.join(self._test_programs_base_dir(), test_dir)
+ tests.extend(self._get_tests_from_dir(absolute_test_dir))
+ return tests
+
+ def _lookup_atspi2_binary(self, filename):
+ exec_prefix = common.pkg_config_file_variable('atspi-2', 'exec_prefix')
+ if not exec_prefix:
+ return None
+ for path in ['libexec', 'lib/at-spi2-core', 'lib32/at-spi2-core', 'lib64/at-spi2-core']:
+ filepath = os.path.join(exec_prefix, path, filename)
+ if os.path.isfile(filepath):
+ return filepath
+
+ return None
+
+ def _start_accessibility_daemons(self):
+ spi_bus_launcher_path = self._lookup_atspi2_binary('at-spi-bus-launcher')
+ spi_registryd_path = self._lookup_atspi2_binary('at-spi2-registryd')
+ if not spi_bus_launcher_path or not spi_registryd_path:
+ return False
+
+ try:
+ self._spi_bus_launcher = subprocess.Popen([spi_bus_launcher_path], env=self._test_env)
+ except:
+ sys.stderr.write("Failed to launch the accessibility bus\n")
+ sys.stderr.flush()
+ return False
+
+ # We need to wait until the SPI bus is launched before trying to start the SPI
+ # registry, so we spin a main loop until the bus name appears on DBus.
+ loop = GLib.MainLoop()
+ Gio.bus_watch_name(Gio.BusType.SESSION, 'org.a11y.Bus', Gio.BusNameWatcherFlags.NONE,
+ lambda *args: loop.quit(), None)
+ loop.run()
+
+ try:
+ self._spi_registryd = subprocess.Popen([spi_registryd_path], env=self._test_env)
+ except:
+ sys.stderr.write("Failed to launch the accessibility registry\n")
+ sys.stderr.flush()
+ return False
+
+ return True
+
+ def _run_xvfb(self):
+ self._xvfb = None
+ if not self._options.use_xvfb:
+ return True
+
+ self._test_env["DISPLAY"] = self._options.display
+
+ try:
+ self._xvfb = subprocess.Popen(["Xvfb", self._options.display, "-screen", "0", "800x600x24", "-nolisten", "tcp"],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ except Exception as e:
+ sys.stderr.write("Failed to run Xvfb: %s\n" % e)
+ sys.stderr.flush()
+ return False
+
+ return True
+
+ def _setup_testing_environment(self):
+ self._test_env = os.environ
+ self._test_env['GSETTINGS_BACKEND'] = 'memory'
+ self._test_env["TEST_WEBKIT_API_WEBKIT2_RESOURCES_PATH"] = common.top_level_path("Tools", "TestWebKitAPI", "Tests", "WebKit2")
+ self._test_env["TEST_WEBKIT_API_WEBKIT2_INJECTED_BUNDLE_PATH"] = common.library_build_path()
+ self._test_env["WEBKIT_EXEC_PATH"] = self._programs_path
+ self._test_env["OWR_USE_TEST_SOURCES"] = '1'
+
+ if not self._run_xvfb():
+ return False
+
+ # If we cannot start the accessibility daemons, we can just skip the accessibility tests.
+ if not self._start_accessibility_daemons():
+ print "Could not start accessibility bus, so disabling TestWebKitAccessibility"
+ self._disabled_tests.append("WebKit2APITests/TestWebKitAccessibility")
+ return True
+
+ def _tear_down_testing_environment(self):
+ if self._spi_registryd:
+ self._spi_registryd.terminate()
+ if self._spi_bus_launcher:
+ self._spi_bus_launcher.terminate()
+ if self._xvfb:
+ self._xvfb.terminate()
+
+ def _test_cases_to_skip(self, test_program):
+ if self._options.skipped_action != 'skip':
+ return []
+
+ test_cases = []
+ for skipped in self._skipped_tests:
+ if test_program.endswith(skipped.test) and not skipped.skip_entire_suite():
+ test_cases.append(skipped.test_case)
+ return test_cases
+
+ def _should_run_test_program(self, test_program):
+ for disabled_test in self._disabled_tests:
+ if test_program.endswith(disabled_test):
+ return False
+
+ if self._options.skipped_action != 'skip':
+ return True
+
+ for skipped in self._skipped_tests:
+ if test_program.endswith(skipped.test) and skipped.skip_entire_suite():
+ return False
+ return True
+
+ def _get_child_pid_from_test_output(self, output):
+ if not output:
+ return -1
+ match = re.search(r'\(pid=(?P<child_pid>[0-9]+)\)', output)
+ if not match:
+ return -1
+ return int(match.group('child_pid'))
+
+ def _kill_process(self, pid):
+ try:
+ os.kill(pid, SIGKILL)
+ except OSError:
+ # Process already died.
+ pass
+
+ def _run_test_command(self, command, timeout=-1):
+ def alarm_handler(signum, frame):
+ raise TestTimeout
+
+ child_pid = [-1]
+ def parse_line(line, child_pid = child_pid):
+ if child_pid[0] == -1:
+ child_pid[0] = self._get_child_pid_from_test_output(line)
+
+ sys.stdout.write(line)
+
+ def waitpid(pid):
+ while True:
+ try:
+ return os.waitpid(pid, 0)
+ except (OSError, IOError) as e:
+ if e.errno == errno.EINTR:
+ continue
+ raise
+
+ def return_code_from_exit_status(status):
+ if os.WIFSIGNALED(status):
+ return -os.WTERMSIG(status)
+ elif os.WIFEXITED(status):
+ return os.WEXITSTATUS(status)
+ else:
+ # Should never happen
+ raise RuntimeError("Unknown child exit status!")
+
+ pid, fd = os.forkpty()
+ if pid == 0:
+ os.execvpe(command[0], command, self._test_env)
+ sys.exit(0)
+
+ if timeout > 0:
+ signal(SIGALRM, alarm_handler)
+ alarm(timeout)
+
+ try:
+ common.parse_output_lines(fd, parse_line)
+ if timeout > 0:
+ alarm(0)
+ except TestTimeout:
+ self._kill_process(pid)
+ if child_pid[0] > 0:
+ self._kill_process(child_pid[0])
+ raise
+
+ try:
+ dummy, status = waitpid(pid)
+ except OSError as e:
+ if e.errno != errno.ECHILD:
+ raise
+ # This happens if SIGCLD is set to be ignored or waiting
+ # for child processes has otherwise been disabled for our
+ # process. This child is dead, we can't get the status.
+ status = 0
+
+ return return_code_from_exit_status(status)
+
+ def _run_test_glib(self, test_program):
+ tester_command = ['gtester', '-k']
+ if self._options.verbose:
+ tester_command.append('--verbose')
+ for test_case in self._test_cases_to_skip(test_program):
+ tester_command.extend(['-s', test_case])
+ tester_command.append(test_program)
+
+ return self._run_test_command(tester_command, self._options.timeout)
+
+ def _get_tests_from_google_test_suite(self, test_program):
+ try:
+ output = subprocess.check_output([test_program, '--gtest_list_tests'])
+ except subprocess.CalledProcessError:
+ sys.stderr.write("ERROR: could not list available tests for binary %s.\n" % (test_program))
+ sys.stderr.flush()
+ return 1
+
+ skipped_test_cases = self._test_cases_to_skip(test_program)
+
+ tests = []
+ prefix = None
+ for line in output.split('\n'):
+ if not line.startswith(' '):
+ prefix = line
+ continue
+ else:
+ test_name = prefix + line.strip()
+ if not test_name in skipped_test_cases:
+ tests.append(test_name)
+ return tests
+
+ def _run_google_test(self, test_program, subtest):
+ test_command = [test_program, '--gtest_filter=%s' % (subtest)]
+ timeout = self._options.timeout
+ if subtest in TestRunner.SLOW:
+ timeout *= 5
+
+ status = self._run_test_command(test_command, timeout)
+ if status == -SIGSEGV:
+ sys.stdout.write("**CRASH** %s\n" % subtest)
+ sys.stdout.flush()
+ return status
+
+ def _run_google_test_suite(self, test_program):
+ retcode = 0
+ for subtest in self._get_tests_from_google_test_suite(test_program):
+ if self._run_google_test(test_program, subtest):
+ retcode = 1
+ return retcode
+
+ def _run_test(self, test_program):
+ basedir = os.path.basename(os.path.dirname(test_program))
+ if basedir in ["WebKit2Gtk", "WebKitGtk"]:
+ return self._run_test_glib(test_program)
+
+ if basedir in ["WebKit2", "JavaScriptCore", "WTF", "WebCore", "WebCoreGtk"]:
+ return self._run_google_test_suite(test_program)
+
+ return 1
+
+ def run_tests(self):
+ if not self._tests:
+ sys.stderr.write("ERROR: tests not found in %s.\n" % (self._test_programs_base_dir()))
+ sys.stderr.flush()
+ return 1
+
+ if not self._setup_testing_environment():
+ return 1
+
+ # Remove skipped tests now instead of when we find them, because
+ # some tests might be skipped while setting up the test environment.
+ self._tests = [test for test in self._tests if self._should_run_test_program(test)]
+
+ crashed_tests = []
+ failed_tests = []
+ timed_out_tests = []
+ try:
+ for test in self._tests:
+ exit_status_code = 0
+ try:
+ exit_status_code = self._run_test(test)
+ except TestTimeout:
+ sys.stdout.write("TEST: %s: TIMEOUT\n" % test)
+ sys.stdout.flush()
+ timed_out_tests.append(test)
+
+ if exit_status_code == -SIGSEGV:
+ sys.stdout.write("TEST: %s: CRASHED\n" % test)
+ sys.stdout.flush()
+ crashed_tests.append(test)
+ elif exit_status_code != 0:
+ failed_tests.append(test)
+ finally:
+ self._tear_down_testing_environment()
+
+ if failed_tests:
+ names = [test.replace(self._test_programs_base_dir(), '', 1) for test in failed_tests]
+ sys.stdout.write("Tests failed (%d): %s\n" % (len(names), ", ".join(names)))
+ sys.stdout.flush()
+
+ if crashed_tests:
+ names = [test.replace(self._test_programs_base_dir(), '', 1) for test in crashed_tests]
+ sys.stdout.write("Tests that crashed (%d): %s\n" % (len(names), ", ".join(names)))
+ sys.stdout.flush()
+
+ if timed_out_tests:
+ names = [test.replace(self._test_programs_base_dir(), '', 1) for test in timed_out_tests]
+ sys.stdout.write("Tests that timed out (%d): %s\n" % (len(names), ", ".join(names)))
+ sys.stdout.flush()
+
+ if self._skipped_tests and self._options.skipped_action == 'skip':
+ sys.stdout.write("Tests skipped (%d):\n%s\n" %
+ (len(self._skipped_tests),
+ "\n".join([str(skipped) for skipped in self._skipped_tests])))
+ sys.stdout.flush()
+
+ return len(failed_tests) + len(timed_out_tests)
+
+if __name__ == "__main__":
+ if not jhbuildutils.enter_jhbuild_environment_if_available("gtk"):
+ print "***"
+ print "*** Warning: jhbuild environment not present. Run update-webkitgtk-libs before build-webkit to ensure proper testing."
+ print "***"
+
+ option_parser = optparse.OptionParser(usage='usage: %prog [options] [test...]')
+ option_parser.add_option('-r', '--release',
+ action='store_true', dest='release',
+ help='Run in Release')
+ option_parser.add_option('-d', '--debug',
+ action='store_true', dest='debug',
+ help='Run in Debug')
+ option_parser.add_option('-v', '--verbose',
+ action='store_true', dest='verbose',
+ help='Run gtester in verbose mode')
+ option_parser.add_option('--display', action='store', dest='display', default=':55',
+ help='Display to run Xvfb')
+ option_parser.add_option('--skipped', action='store', dest='skipped_action',
+ choices=['skip', 'ignore', 'only'], default='skip',
+ metavar='skip|ignore|only',
+ help='Specifies how to treat the skipped tests')
+ option_parser.add_option('-t', '--timeout',
+ action='store', type='int', dest='timeout', default=10,
+ help='Time in seconds until a test times out')
+ option_parser.add_option('--no-xvfb', action='store_false', dest='use_xvfb', default=True,
+ help='Do not run tests under Xvfb')
+ options, args = option_parser.parse_args()
+
+ sys.exit(TestRunner(options, args).run_tests())
diff --git a/Tools/Scripts/webkit-build-directory b/Tools/Scripts/webkit-build-directory
new file mode 100755
index 000000000..5bac3708a
--- /dev/null
+++ b/Tools/Scripts/webkit-build-directory
@@ -0,0 +1,84 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) 2010 Google Inc. All rights reserved.
+# Copyright (C) 2013, 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.
+# 3. Neither the name of Apple Inc. ("Apple") nor the names of
+# its contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# A script to expose WebKit's build directory detection logic to non-perl scripts.
+
+use FindBin;
+use Getopt::Long;
+
+use lib $FindBin::Bin;
+use webkitdirs;
+
+my $showConfigurationDirectory = 0;
+my $showExecutablePath = 0;
+my $showHelp = 0;
+my $showTopLevelDirectory = 0;
+
+
+my $programName = basename($0);
+my $usage = <<EOF;
+Usage: $programName [options]
+ --configuration Show the build directory for a specific configuration (e.g. Debug, Release. Defaults to the active configuration set by set-webkit-configuration)
+ --executablePath Show the path to the executables produced by a specific build configuration. This differs from --configuration on Windows.
+ -h|--help Show this help message
+ --top-level Show the top-level build directory
+
+ --efl Find the build directory for the EFL port
+ --gtk Find the build directory for the GTK+ port
+ --wincairo Find the build directory for using Cairo (rather than CoreGraphics) on Windows
+
+Either --configuration or --top-level is required.
+EOF
+
+setConfiguration(); # Figure out from the command line if we're --debug or --release or the default.
+
+# FIXME: Check if extra flags are valid or not.
+Getopt::Long::Configure('pass_through'); # Let --blackberry, etc... be handled by webkitdirs
+my $getOptionsResult = GetOptions(
+ 'configuration' => \$showConfigurationDirectory,
+ 'executablePath' => \$showExecutablePath,
+ 'top-level' => \$showTopLevelDirectory,
+ 'help|h' => \$showHelp,
+);
+
+if (!$getOptionsResult || $showHelp) {
+ print STDERR $usage;
+ exit 1;
+}
+
+if (!$showConfigurationDirectory && !$showTopLevelDirectory && !$showExecutablePath) {
+ print baseProductDir() . "\n";
+ print productDir() . "\n";
+} elsif ($showTopLevelDirectory) {
+ print baseProductDir() . "\n";
+} elsif ($showExecutablePath) {
+ print executableProductDir() . "\n";
+} else {
+ print productDir() . "\n";
+}
diff --git a/Tools/Scripts/webkitdirs.pm b/Tools/Scripts/webkitdirs.pm
new file mode 100755
index 000000000..179764407
--- /dev/null
+++ b/Tools/Scripts/webkitdirs.pm
@@ -0,0 +1,2649 @@
+# Copyright (C) 2005-2007, 2010-2016 Apple Inc. All rights reserved.
+# Copyright (C) 2009 Google Inc. All rights reserved.
+# Copyright (C) 2011 Research In Motion Limited. All rights reserved.
+# Copyright (C) 2013 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.
+# 3. Neither the name of Apple Inc. ("Apple") nor the names of
+# its contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Module to share code to get to WebKit directories.
+
+use strict;
+use version;
+use warnings;
+use Config;
+use Cwd qw(realpath);
+use Digest::MD5 qw(md5_hex);
+use FindBin;
+use File::Basename;
+use File::Find;
+use File::Path qw(make_path mkpath rmtree);
+use File::Spec;
+use File::stat;
+use List::Util;
+use POSIX;
+use Time::HiRes qw(usleep);
+use VCSUtils;
+
+BEGIN {
+ use Exporter ();
+ our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
+ $VERSION = 1.00;
+ @ISA = qw(Exporter);
+ @EXPORT = qw(
+ &XcodeCoverageSupportOptions
+ &XcodeOptionString
+ &XcodeOptionStringNoConfig
+ &XcodeOptions
+ &XcodeStaticAnalyzerOption
+ &appDisplayNameFromBundle
+ &appendToEnvironmentVariableList
+ &baseProductDir
+ &chdirWebKit
+ &checkFrameworks
+ &cmakeBasedPortArguments
+ &currentSVNRevision
+ &debugSafari
+ &executableProductDir
+ &findOrCreateSimulatorForIOSDevice
+ &iosSimulatorDeviceByName
+ &nmPath
+ &passedConfiguration
+ &prependToEnvironmentVariableList
+ &printHelpAndExitForRunAndDebugWebKitAppIfNeeded
+ &productDir
+ &quitIOSSimulator
+ &relaunchIOSSimulator
+ &restartIOSSimulatorDevice
+ &runIOSWebKitApp
+ &runMacWebKitApp
+ &safariPath
+ &iosVersion
+ &setConfiguration
+ &setupMacWebKitEnvironment
+ &sharedCommandLineOptions
+ &sharedCommandLineOptionsUsage
+ &shutDownIOSSimulatorDevice
+ &willUseIOSDeviceSDK
+ &willUseIOSSimulatorSDK
+ SIMULATOR_DEVICE_SUFFIX_FOR_WEBKIT_DEVELOPMENT
+ USE_OPEN_COMMAND
+ );
+ %EXPORT_TAGS = ( );
+ @EXPORT_OK = ();
+}
+
+# Ports
+use constant {
+ AppleWin => "AppleWin",
+ GTK => "GTK",
+ Efl => "Efl",
+ iOS => "iOS",
+ Mac => "Mac",
+ WinCairo => "WinCairo",
+ Unknown => "Unknown"
+};
+
+use constant USE_OPEN_COMMAND => 1; # Used in runMacWebKitApp().
+use constant INCLUDE_OPTIONS_FOR_DEBUGGING => 1;
+use constant SIMULATOR_DEVICE_STATE_SHUTDOWN => "1";
+use constant SIMULATOR_DEVICE_STATE_BOOTED => "3";
+use constant SIMULATOR_DEVICE_SUFFIX_FOR_WEBKIT_DEVELOPMENT => "For WebKit Development";
+
+# See table "Certificate types and names" on <https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/AppDistributionGuide/MaintainingCertificates/MaintainingCertificates.html#//apple_ref/doc/uid/TP40012582-CH31-SW41>.
+use constant IOS_DEVELOPMENT_CERTIFICATE_NAME_PREFIX => "iPhone Developer: ";
+
+our @EXPORT_OK;
+
+my $architecture;
+my $asanIsEnabled;
+my $numberOfCPUs;
+my $maxCPULoad;
+my $baseProductDir;
+my @baseProductDirOption;
+my $configuration;
+my $xcodeSDK;
+my $configurationForVisualStudio;
+my $configurationProductDir;
+my $sourceDir;
+my $currentSVNRevision;
+my $debugger;
+my $didLoadIPhoneSimulatorNotification;
+my $nmPath;
+my $osXVersion;
+my $iosVersion;
+my $generateDsym;
+my $isCMakeBuild;
+my $isWin64;
+my $isInspectorFrontend;
+my $portName;
+my $shouldUseGuardMalloc;
+my $shouldNotUseNinja;
+my $xcodeVersion;
+
+my $unknownPortProhibited = 0;
+
+# Variables for Win32 support
+my $programFilesPath;
+my $vcBuildPath;
+my $vsInstallDir;
+my $msBuildInstallDir;
+my $vsVersion;
+my $windowsSourceDir;
+my $winVersion;
+my $willUseVCExpressWhenBuilding = 0;
+
+# Defined in VCSUtils.
+sub exitStatus($);
+
+sub findMatchingArguments($$);
+sub hasArgument($$);
+
+sub determineSourceDir
+{
+ return if $sourceDir;
+ $sourceDir = $FindBin::Bin;
+ $sourceDir =~ s|/+$||; # Remove trailing '/' as we would die later
+
+ # walks up path checking each directory to see if it is the main WebKit project dir,
+ # defined by containing Sources, WebCore, and WebKit
+ until ((-d File::Spec->catdir($sourceDir, "Source") && -d File::Spec->catdir($sourceDir, "Source", "WebCore") && -d File::Spec->catdir($sourceDir, "Source", "WebKit")) || (-d File::Spec->catdir($sourceDir, "Internal") && -d File::Spec->catdir($sourceDir, "OpenSource")))
+ {
+ if ($sourceDir !~ s|/[^/]+$||) {
+ die "Could not find top level webkit directory above source directory using FindBin.\n";
+ }
+ }
+
+ $sourceDir = File::Spec->catdir($sourceDir, "OpenSource") if -d File::Spec->catdir($sourceDir, "OpenSource");
+}
+
+sub currentPerlPath()
+{
+ my $thisPerl = $^X;
+ if ($^O ne 'VMS') {
+ $thisPerl .= $Config{_exe} unless $thisPerl =~ m/$Config{_exe}$/i;
+ }
+ return $thisPerl;
+}
+
+# used for scripts which are stored in a non-standard location
+sub setSourceDir($)
+{
+ ($sourceDir) = @_;
+}
+
+sub determineNinjaVersion
+{
+ chomp(my $ninjaVersion = `ninja --version`);
+ return $ninjaVersion;
+}
+
+sub determineXcodeVersion
+{
+ return if defined $xcodeVersion;
+ my $xcodebuildVersionOutput = `xcodebuild -version`;
+ $xcodeVersion = ($xcodebuildVersionOutput =~ /Xcode ([0-9](\.[0-9]+)*)/) ? $1 : "3.0";
+}
+
+sub readXcodeUserDefault($)
+{
+ my ($unprefixedKey) = @_;
+
+ determineXcodeVersion();
+
+ my $xcodeDefaultsDomain = (eval "v$xcodeVersion" lt v4) ? "com.apple.Xcode" : "com.apple.dt.Xcode";
+ my $xcodeDefaultsPrefix = (eval "v$xcodeVersion" lt v4) ? "PBX" : "IDE";
+ my $devnull = File::Spec->devnull();
+
+ my $value = `defaults read $xcodeDefaultsDomain ${xcodeDefaultsPrefix}${unprefixedKey} 2> ${devnull}`;
+ return if $?;
+
+ chomp $value;
+ return $value;
+}
+
+sub determineBaseProductDir
+{
+ return if defined $baseProductDir;
+ determineSourceDir();
+
+ my $setSharedPrecompsDir;
+ $baseProductDir = $ENV{"WEBKIT_OUTPUTDIR"};
+
+ if (!defined($baseProductDir) and isAppleMacWebKit()) {
+ # Silently remove ~/Library/Preferences/xcodebuild.plist which can
+ # cause build failure. The presence of
+ # ~/Library/Preferences/xcodebuild.plist can prevent xcodebuild from
+ # respecting global settings such as a custom build products directory
+ # (<rdar://problem/5585899>).
+ my $personalPlistFile = $ENV{HOME} . "/Library/Preferences/xcodebuild.plist";
+ if (-e $personalPlistFile) {
+ unlink($personalPlistFile) || die "Could not delete $personalPlistFile: $!";
+ }
+
+ determineXcodeVersion();
+
+ if (eval "v$xcodeVersion" ge v4) {
+ my $buildLocationStyle = join '', readXcodeUserDefault("BuildLocationStyle");
+ if ($buildLocationStyle eq "Custom") {
+ my $buildLocationType = join '', readXcodeUserDefault("CustomBuildLocationType");
+ # FIXME: Read CustomBuildIntermediatesPath and set OBJROOT accordingly.
+ $baseProductDir = readXcodeUserDefault("CustomBuildProductsPath") if $buildLocationType eq "Absolute";
+ }
+
+ # DeterminedByTargets corresponds to a setting of "Legacy" in Xcode.
+ # It is the only build location style for which SHARED_PRECOMPS_DIR is not
+ # overridden when building from within Xcode.
+ $setSharedPrecompsDir = 1 if $buildLocationStyle ne "DeterminedByTargets";
+ }
+
+ if (!defined($baseProductDir)) {
+ $baseProductDir = join '', readXcodeUserDefault("ApplicationwideBuildSettings");
+ $baseProductDir = $1 if $baseProductDir =~ /SYMROOT\s*=\s*\"(.*?)\";/s;
+ }
+
+ undef $baseProductDir unless $baseProductDir =~ /^\//;
+ }
+
+ if (!defined($baseProductDir)) { # Port-specific checks failed, use default
+ $baseProductDir = File::Spec->catdir($sourceDir, "WebKitBuild");
+ }
+
+ if (isGit() && isGitBranchBuild()) {
+ my $branch = gitBranch();
+ $baseProductDir = "$baseProductDir/$branch";
+ }
+
+ if (isAppleMacWebKit()) {
+ $baseProductDir =~ s|^\Q$(SRCROOT)/..\E$|$sourceDir|;
+ $baseProductDir =~ s|^\Q$(SRCROOT)/../|$sourceDir/|;
+ $baseProductDir =~ s|^~/|$ENV{HOME}/|;
+ die "Can't handle Xcode product directory with a ~ in it.\n" if $baseProductDir =~ /~/;
+ die "Can't handle Xcode product directory with a variable in it.\n" if $baseProductDir =~ /\$/;
+ @baseProductDirOption = ("SYMROOT=$baseProductDir", "OBJROOT=$baseProductDir");
+ push(@baseProductDirOption, "SHARED_PRECOMPS_DIR=${baseProductDir}/PrecompiledHeaders") if $setSharedPrecompsDir;
+ }
+
+ if (isCygwin()) {
+ my $dosBuildPath = `cygpath --windows \"$baseProductDir\"`;
+ chomp $dosBuildPath;
+ $ENV{"WEBKIT_OUTPUTDIR"} = $dosBuildPath;
+ my $unixBuildPath = `cygpath --unix \"$baseProductDir\"`;
+ chomp $unixBuildPath;
+ $baseProductDir = $dosBuildPath;
+ }
+}
+
+sub setBaseProductDir($)
+{
+ ($baseProductDir) = @_;
+}
+
+sub determineConfiguration
+{
+ return if defined $configuration;
+ determineBaseProductDir();
+ if (open CONFIGURATION, "$baseProductDir/Configuration") {
+ $configuration = <CONFIGURATION>;
+ close CONFIGURATION;
+ }
+ if ($configuration) {
+ chomp $configuration;
+ # compatibility for people who have old Configuration files
+ $configuration = "Release" if $configuration eq "Deployment";
+ $configuration = "Debug" if $configuration eq "Development";
+ } else {
+ $configuration = "Release";
+ }
+}
+
+sub determineArchitecture
+{
+ return if defined $architecture;
+ # make sure $architecture is defined in all cases
+ $architecture = "";
+
+ determineBaseProductDir();
+ determineXcodeSDK();
+
+ if (isAppleMacWebKit()) {
+ if (open ARCHITECTURE, "$baseProductDir/Architecture") {
+ $architecture = <ARCHITECTURE>;
+ close ARCHITECTURE;
+ }
+ if ($architecture) {
+ chomp $architecture;
+ } else {
+ if (not defined $xcodeSDK or $xcodeSDK =~ /^(\/$|macosx)/) {
+ my $supports64Bit = `sysctl -n hw.optional.x86_64`;
+ chomp $supports64Bit;
+ $architecture = 'x86_64' if $supports64Bit;
+ } elsif ($xcodeSDK =~ /^iphonesimulator/) {
+ $architecture = 'x86_64';
+ } elsif ($xcodeSDK =~ /^iphoneos/) {
+ $architecture = 'armv7';
+ }
+ }
+ } elsif (isCMakeBuild()) {
+ my $host_processor = "";
+ if (open my $cmake_sysinfo, "cmake --system-information |") {
+ while (<$cmake_sysinfo>) {
+ next unless index($_, 'CMAKE_SYSTEM_PROCESSOR') == 0;
+ if (/^CMAKE_SYSTEM_PROCESSOR \"([^"]+)\"/) {
+ $architecture = $1;
+ $architecture = 'x86_64' if $architecture eq 'amd64';
+ last;
+ }
+ }
+ close $cmake_sysinfo;
+ }
+ }
+
+ if (!isAnyWindows()) {
+ if (!$architecture) {
+ # Fall back to output of `arch', if it is present.
+ $architecture = `arch`;
+ chomp $architecture;
+ }
+
+ if (!$architecture) {
+ # Fall back to output of `uname -m', if it is present.
+ $architecture = `uname -m`;
+ chomp $architecture;
+ }
+ }
+
+ $architecture = 'x86_64' if ($architecture =~ /amd64/ && isBSD());
+}
+
+sub determineASanIsEnabled
+{
+ return if defined $asanIsEnabled;
+ determineBaseProductDir();
+
+ $asanIsEnabled = 0;
+ my $asanConfigurationValue;
+
+ if (open ASAN, "$baseProductDir/ASan") {
+ $asanConfigurationValue = <ASAN>;
+ close ASAN;
+ chomp $asanConfigurationValue;
+ $asanIsEnabled = 1 if $asanConfigurationValue eq "YES";
+ }
+}
+
+sub determineNumberOfCPUs
+{
+ return if defined $numberOfCPUs;
+ if (defined($ENV{NUMBER_OF_PROCESSORS})) {
+ $numberOfCPUs = $ENV{NUMBER_OF_PROCESSORS};
+ } elsif (isLinux()) {
+ # First try the nproc utility, if it exists. If we get no
+ # results fall back to just interpretting /proc directly.
+ chomp($numberOfCPUs = `nproc --all 2> /dev/null`);
+ if ($numberOfCPUs eq "") {
+ $numberOfCPUs = (grep /processor/, `cat /proc/cpuinfo`);
+ }
+ } elsif (isAnyWindows()) {
+ # Assumes cygwin
+ $numberOfCPUs = `ls /proc/registry/HKEY_LOCAL_MACHINE/HARDWARE/DESCRIPTION/System/CentralProcessor | wc -w`;
+ } elsif (isDarwin() || isBSD()) {
+ chomp($numberOfCPUs = `sysctl -n hw.ncpu`);
+ }
+}
+
+sub determineMaxCPULoad
+{
+ return if defined $maxCPULoad;
+ if (defined($ENV{MAX_CPU_LOAD})) {
+ $maxCPULoad = $ENV{MAX_CPU_LOAD};
+ }
+}
+
+sub jscPath($)
+{
+ my ($productDir) = @_;
+ my $jscName = "jsc";
+ $jscName .= "_debug" if configuration() eq "Debug_All";
+ $jscName .= ".exe" if (isAnyWindows());
+ return "$productDir/$jscName" if -e "$productDir/$jscName";
+ return "$productDir/JavaScriptCore.framework/Resources/$jscName";
+}
+
+sub argumentsForConfiguration()
+{
+ determineConfiguration();
+ determineArchitecture();
+ determineXcodeSDK();
+
+ my @args = ();
+ # FIXME: Is it necessary to pass --debug, --release, --32-bit or --64-bit?
+ # These are determined automatically from stored configuration.
+ push(@args, '--debug') if ($configuration =~ "^Debug");
+ push(@args, '--release') if ($configuration =~ "^Release");
+ push(@args, '--device') if (defined $xcodeSDK && $xcodeSDK =~ /^iphoneos/);
+ push(@args, '--ios-simulator') if (defined $xcodeSDK && $xcodeSDK =~ /^iphonesimulator/);
+ push(@args, '--32-bit') if ($architecture ne "x86_64" and !isWin64());
+ push(@args, '--64-bit') if (isWin64());
+ push(@args, '--gtk') if isGtk();
+ push(@args, '--efl') if isEfl();
+ push(@args, '--wincairo') if isWinCairo();
+ push(@args, '--inspector-frontend') if isInspectorFrontend();
+ return @args;
+}
+
+sub determineXcodeSDK
+{
+ return if defined $xcodeSDK;
+ my $sdk;
+ if (checkForArgumentAndRemoveFromARGVGettingValue("--sdk", \$sdk)) {
+ $xcodeSDK = $sdk;
+ }
+ if (checkForArgumentAndRemoveFromARGV("--device")) {
+ my $hasInternalSDK = exitStatus(system("xcrun --sdk iphoneos.internal --show-sdk-version > /dev/null 2>&1")) == 0;
+ $xcodeSDK ||= $hasInternalSDK ? "iphoneos.internal" : "iphoneos";
+ }
+ if (checkForArgumentAndRemoveFromARGV("--ios-simulator")) {
+ $xcodeSDK ||= 'iphonesimulator';
+ }
+}
+
+sub xcodeSDK
+{
+ determineXcodeSDK();
+ return $xcodeSDK;
+}
+
+sub setXcodeSDK($)
+{
+ ($xcodeSDK) = @_;
+}
+
+
+sub xcodeSDKPlatformName()
+{
+ determineXcodeSDK();
+ return "" if !defined $xcodeSDK;
+ return "iphoneos" if $xcodeSDK =~ /iphoneos/i;
+ return "iphonesimulator" if $xcodeSDK =~ /iphonesimulator/i;
+ return "macosx" if $xcodeSDK =~ /macosx/i;
+ die "Couldn't determine platform name from Xcode SDK";
+}
+
+sub XcodeSDKPath
+{
+ determineXcodeSDK();
+
+ die "Can't find the SDK path because no Xcode SDK was specified" if not $xcodeSDK;
+
+ my $sdkPath = `xcrun --sdk $xcodeSDK --show-sdk-path` if $xcodeSDK;
+ die 'Failed to get SDK path from xcrun' if $?;
+ chomp $sdkPath;
+
+ return $sdkPath;
+}
+
+sub xcodeSDKVersion
+{
+ determineXcodeSDK();
+
+ die "Can't find the SDK version because no Xcode SDK was specified" if !$xcodeSDK;
+
+ chomp(my $sdkVersion = `xcrun --sdk $xcodeSDK --show-sdk-version`);
+ die "Failed to get SDK version from xcrun" if exitStatus($?);
+
+ return $sdkVersion;
+}
+
+sub programFilesPath
+{
+ return $programFilesPath if defined $programFilesPath;
+
+ $programFilesPath = $ENV{'PROGRAMFILES(X86)'} || $ENV{'PROGRAMFILES'} || "C:\\Program Files";
+
+ return $programFilesPath;
+}
+
+sub visualStudioInstallDir
+{
+ return $vsInstallDir if defined $vsInstallDir;
+
+ if ($ENV{'VSINSTALLDIR'}) {
+ $vsInstallDir = $ENV{'VSINSTALLDIR'};
+ $vsInstallDir =~ s|[\\/]$||;
+ } else {
+ $vsInstallDir = File::Spec->catdir(programFilesPath(), "Microsoft Visual Studio 14.0");
+ }
+ chomp($vsInstallDir = `cygpath "$vsInstallDir"`) if isCygwin();
+
+ print "Using Visual Studio: $vsInstallDir\n";
+ return $vsInstallDir;
+}
+
+sub msBuildInstallDir
+{
+ return $msBuildInstallDir if defined $msBuildInstallDir;
+
+ $msBuildInstallDir = File::Spec->catdir(programFilesPath(), "MSBuild", "14.0", "Bin");
+
+ chomp($msBuildInstallDir = `cygpath "$msBuildInstallDir"`) if isCygwin();
+
+ print "Using MSBuild: $msBuildInstallDir\n";
+ return $msBuildInstallDir;
+}
+
+sub visualStudioVersion
+{
+ return $vsVersion if defined $vsVersion;
+
+ my $installDir = visualStudioInstallDir();
+
+ $vsVersion = ($installDir =~ /Microsoft Visual Studio ([0-9]+\.[0-9]*)/) ? $1 : "14";
+
+ print "Using Visual Studio $vsVersion\n";
+ return $vsVersion;
+}
+
+sub determineConfigurationForVisualStudio
+{
+ return if defined $configurationForVisualStudio;
+ determineConfiguration();
+ # FIXME: We should detect when Debug_All or Production has been chosen.
+ $configurationForVisualStudio = "/p:Configuration=" . $configuration;
+}
+
+sub usesPerConfigurationBuildDirectory
+{
+ # [Gtk] We don't have Release/Debug configurations in straight
+ # autotool builds (non build-webkit). In this case and if
+ # WEBKIT_OUTPUTDIR exist, use that as our configuration dir. This will
+ # allows us to run run-webkit-tests without using build-webkit.
+ return ($ENV{"WEBKIT_OUTPUTDIR"} && isGtk()) || isAppleWinWebKit();
+}
+
+sub determineConfigurationProductDir
+{
+ return if defined $configurationProductDir;
+ determineBaseProductDir();
+ determineConfiguration();
+ if (isAppleWinWebKit() || isWinCairo()) {
+ $configurationProductDir = File::Spec->catdir($baseProductDir, $configuration);
+ } else {
+ if (usesPerConfigurationBuildDirectory()) {
+ $configurationProductDir = "$baseProductDir";
+ } else {
+ $configurationProductDir = "$baseProductDir/$configuration";
+ $configurationProductDir .= "-" . xcodeSDKPlatformName() if isIOSWebKit();
+ }
+ }
+}
+
+sub setConfigurationProductDir($)
+{
+ ($configurationProductDir) = @_;
+}
+
+sub determineCurrentSVNRevision
+{
+ # We always update the current SVN revision here, and leave the caching
+ # to currentSVNRevision(), so that changes to the SVN revision while the
+ # script is running can be picked up by calling this function again.
+ determineSourceDir();
+ $currentSVNRevision = svnRevisionForDirectory($sourceDir);
+ return $currentSVNRevision;
+}
+
+
+sub chdirWebKit
+{
+ determineSourceDir();
+ chdir $sourceDir or die;
+}
+
+sub baseProductDir
+{
+ determineBaseProductDir();
+ return $baseProductDir;
+}
+
+sub sourceDir
+{
+ determineSourceDir();
+ return $sourceDir;
+}
+
+sub productDir
+{
+ determineConfigurationProductDir();
+ return $configurationProductDir;
+}
+
+sub executableProductDir
+{
+ my $productDirectory = productDir();
+
+ my $binaryDirectory;
+ if (isEfl() || isGtk()) {
+ $binaryDirectory = "bin";
+ } elsif (isAnyWindows()) {
+ $binaryDirectory = isWin64() ? "bin64" : "bin32";
+ } else {
+ return $productDirectory;
+ }
+
+ return File::Spec->catdir($productDirectory, $binaryDirectory);
+}
+
+sub jscProductDir
+{
+ return executableProductDir();
+}
+
+sub configuration()
+{
+ determineConfiguration();
+ return $configuration;
+}
+
+sub asanIsEnabled()
+{
+ determineASanIsEnabled();
+ return $asanIsEnabled;
+}
+
+sub configurationForVisualStudio()
+{
+ determineConfigurationForVisualStudio();
+ return $configurationForVisualStudio;
+}
+
+sub currentSVNRevision
+{
+ determineCurrentSVNRevision() if not defined $currentSVNRevision;
+ return $currentSVNRevision;
+}
+
+sub generateDsym()
+{
+ determineGenerateDsym();
+ return $generateDsym;
+}
+
+sub determineGenerateDsym()
+{
+ return if defined($generateDsym);
+ $generateDsym = checkForArgumentAndRemoveFromARGV("--dsym");
+}
+
+sub hasIOSDevelopmentCertificate()
+{
+ return !exitStatus(system("security find-identity -p codesigning | grep '" . IOS_DEVELOPMENT_CERTIFICATE_NAME_PREFIX . "' > /dev/null 2>&1"));
+}
+
+sub argumentsForXcode()
+{
+ my @args = ();
+ push @args, "DEBUG_INFORMATION_FORMAT=dwarf-with-dsym" if generateDsym();
+ return @args;
+}
+
+sub XcodeOptions
+{
+ determineBaseProductDir();
+ determineConfiguration();
+ determineArchitecture();
+ determineASanIsEnabled();
+ determineXcodeSDK();
+
+ my @options;
+ push @options, "-UseSanitizedBuildSystemEnvironment=YES";
+ push @options, ("-configuration", $configuration);
+ push @options, ("-xcconfig", sourceDir() . "/Tools/asan/asan.xcconfig", "ASAN_IGNORE=" . sourceDir() . "/Tools/asan/webkit-asan-ignore.txt") if $asanIsEnabled;
+ push @options, @baseProductDirOption;
+ push @options, "ARCHS=$architecture" if $architecture;
+ push @options, "SDKROOT=$xcodeSDK" if $xcodeSDK;
+ if (willUseIOSDeviceSDK()) {
+ push @options, "ENABLE_BITCODE=NO";
+ if (hasIOSDevelopmentCertificate()) {
+ # FIXME: May match more than one installed development certificate.
+ push @options, "CODE_SIGN_IDENTITY=" . IOS_DEVELOPMENT_CERTIFICATE_NAME_PREFIX;
+ } else {
+ push @options, "CODE_SIGN_IDENTITY="; # No identity
+ push @options, "CODE_SIGNING_REQUIRED=NO";
+ }
+ }
+ push @options, argumentsForXcode();
+ return @options;
+}
+
+sub XcodeOptionString
+{
+ return join " ", XcodeOptions();
+}
+
+sub XcodeOptionStringNoConfig
+{
+ return join " ", @baseProductDirOption;
+}
+
+sub XcodeCoverageSupportOptions()
+{
+ my @coverageSupportOptions = ();
+ push @coverageSupportOptions, "GCC_GENERATE_TEST_COVERAGE_FILES=YES";
+ push @coverageSupportOptions, "GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES";
+ return @coverageSupportOptions;
+}
+
+sub XcodeStaticAnalyzerOption()
+{
+ return "RUN_CLANG_STATIC_ANALYZER=YES";
+}
+
+my $passedConfiguration;
+my $searchedForPassedConfiguration;
+sub determinePassedConfiguration
+{
+ return if $searchedForPassedConfiguration;
+ $searchedForPassedConfiguration = 1;
+ $passedConfiguration = undef;
+
+ if (checkForArgumentAndRemoveFromARGV("--debug")) {
+ $passedConfiguration = "Debug";
+ } elsif(checkForArgumentAndRemoveFromARGV("--release")) {
+ $passedConfiguration = "Release";
+ } elsif (checkForArgumentAndRemoveFromARGV("--profile") || checkForArgumentAndRemoveFromARGV("--profiling")) {
+ $passedConfiguration = "Profiling";
+ }
+}
+
+sub passedConfiguration
+{
+ determinePassedConfiguration();
+ return $passedConfiguration;
+}
+
+sub setConfiguration
+{
+ setArchitecture();
+
+ if (my $config = shift @_) {
+ $configuration = $config;
+ return;
+ }
+
+ determinePassedConfiguration();
+ $configuration = $passedConfiguration if $passedConfiguration;
+}
+
+
+my $passedArchitecture;
+my $searchedForPassedArchitecture;
+sub determinePassedArchitecture
+{
+ return if $searchedForPassedArchitecture;
+ $searchedForPassedArchitecture = 1;
+
+ $passedArchitecture = undef;
+ if (checkForArgumentAndRemoveFromARGV("--32-bit")) {
+ if (isAppleMacWebKit()) {
+ # PLATFORM_IOS: Don't run `arch` command inside Simulator environment
+ local %ENV = %ENV;
+ delete $ENV{DYLD_ROOT_PATH};
+ delete $ENV{DYLD_FRAMEWORK_PATH};
+
+ $passedArchitecture = `arch`;
+ chomp $passedArchitecture;
+ }
+ }
+}
+
+sub passedArchitecture
+{
+ determinePassedArchitecture();
+ return $passedArchitecture;
+}
+
+sub architecture()
+{
+ determineArchitecture();
+ return $architecture;
+}
+
+sub numberOfCPUs()
+{
+ determineNumberOfCPUs();
+ return $numberOfCPUs;
+}
+
+sub maxCPULoad()
+{
+ determineMaxCPULoad();
+ return $maxCPULoad;
+}
+
+sub setArchitecture
+{
+ if (my $arch = shift @_) {
+ $architecture = $arch;
+ return;
+ }
+
+ determinePassedArchitecture();
+ $architecture = $passedArchitecture if $passedArchitecture;
+}
+
+sub skipSafariExecutableEntitlementChecks
+{
+ return `defaults read /Library/Preferences/org.webkit.BuildConfiguration SkipSafariExecutableEntitlementChecks 2>/dev/null` eq "1\n";
+}
+
+sub executableHasEntitlements
+{
+ my $executablePath = shift;
+ return (`codesign -d --entitlements - $executablePath 2>&1` =~ /<key>/);
+}
+
+sub safariPathFromSafariBundle
+{
+ my ($safariBundle) = @_;
+
+ die "Safari path is only relevant on Apple Mac platform\n" unless isAppleMacWebKit();
+
+ my $safariPath = "$safariBundle/Contents/MacOS/Safari";
+ return $safariPath if skipSafariExecutableEntitlementChecks();
+
+ my $safariForWebKitDevelopmentPath = "$safariBundle/Contents/MacOS/SafariForWebKitDevelopment";
+ return $safariForWebKitDevelopmentPath if -f $safariForWebKitDevelopmentPath && executableHasEntitlements($safariPath);
+
+ return $safariPath;
+}
+
+sub installedSafariPath
+{
+ return safariPathFromSafariBundle("/Applications/Safari.app");
+}
+
+# Locate Safari.
+sub safariPath
+{
+ die "Safari path is only relevant on Apple Mac platform\n" unless isAppleMacWebKit();
+
+ # Use WEBKIT_SAFARI environment variable if present.
+ my $safariBundle = $ENV{WEBKIT_SAFARI};
+ if (!$safariBundle) {
+ determineConfigurationProductDir();
+ # Use Safari.app in product directory if present (good for Safari development team).
+ if (-d "$configurationProductDir/Safari.app") {
+ $safariBundle = "$configurationProductDir/Safari.app";
+ }
+ if (!$safariBundle) {
+ return installedSafariPath();
+ }
+ }
+ my $safariPath = safariPathFromSafariBundle($safariBundle);
+ die "Can't find executable at $safariPath.\n" if !-x $safariPath;
+ return $safariPath;
+}
+
+sub builtDylibPathForName
+{
+ my $libraryName = shift;
+ determineConfigurationProductDir();
+
+ if (isGtk()) {
+ my $extension = isDarwin() ? ".dylib" : ".so";
+ return "$configurationProductDir/lib/libwebkit2gtk-4.0" . $extension;
+ }
+ if (isEfl()) {
+ return "$configurationProductDir/lib/libewebkit2.so";
+ }
+ if (isIOSWebKit()) {
+ return "$configurationProductDir/$libraryName.framework/$libraryName";
+ }
+ if (isAppleMacWebKit()) {
+ return "$configurationProductDir/$libraryName.framework/Versions/A/$libraryName";
+ }
+ if (isAppleWinWebKit()) {
+ if ($libraryName eq "JavaScriptCore") {
+ return "$baseProductDir/lib/$libraryName.lib";
+ } else {
+ return "$baseProductDir/$libraryName.intermediate/$configuration/$libraryName.intermediate/$libraryName.lib";
+ }
+ }
+
+ die "Unsupported platform, can't determine built library locations.\nTry `build-webkit --help` for more information.\n";
+}
+
+# Check to see that all the frameworks are built.
+sub checkFrameworks # FIXME: This is a poor name since only the Mac calls built WebCore a Framework.
+{
+ return if isAnyWindows();
+ my @frameworks = ("JavaScriptCore", "WebCore");
+ push(@frameworks, "WebKit") if isAppleMacWebKit(); # FIXME: This seems wrong, all ports should have a WebKit these days.
+ for my $framework (@frameworks) {
+ my $path = builtDylibPathForName($framework);
+ die "Can't find built framework at \"$path\".\n" unless -e $path;
+ }
+}
+
+sub isInspectorFrontend()
+{
+ determineIsInspectorFrontend();
+ return $isInspectorFrontend;
+}
+
+sub determineIsInspectorFrontend()
+{
+ return if defined($isInspectorFrontend);
+ $isInspectorFrontend = checkForArgumentAndRemoveFromARGV("--inspector-frontend");
+}
+
+sub commandExists($)
+{
+ my $command = shift;
+ my $devnull = File::Spec->devnull();
+
+ if (isAnyWindows()) {
+ return exitStatus(system("where /q $command >$devnull 2>&1")) == 0;
+ }
+ return exitStatus(system("which $command >$devnull 2>&1")) == 0;
+}
+
+sub checkForArgumentAndRemoveFromARGV($)
+{
+ my $argToCheck = shift;
+ return checkForArgumentAndRemoveFromArrayRef($argToCheck, \@ARGV);
+}
+
+sub checkForArgumentAndRemoveFromArrayRefGettingValue($$$)
+{
+ my ($argToCheck, $valueRef, $arrayRef) = @_;
+ my $argumentStartRegEx = qr#^$argToCheck(?:=\S|$)#;
+ my $i = 0;
+ for (; $i < @$arrayRef; ++$i) {
+ last if $arrayRef->[$i] =~ $argumentStartRegEx;
+ }
+ if ($i >= @$arrayRef) {
+ return $$valueRef = undef;
+ }
+ my ($key, $value) = split("=", $arrayRef->[$i]);
+ splice(@$arrayRef, $i, 1);
+ if (defined($value)) {
+ # e.g. --sdk=iphonesimulator
+ return $$valueRef = $value;
+ }
+ return $$valueRef = splice(@$arrayRef, $i, 1); # e.g. --sdk iphonesimulator
+}
+
+sub checkForArgumentAndRemoveFromARGVGettingValue($$)
+{
+ my ($argToCheck, $valueRef) = @_;
+ return checkForArgumentAndRemoveFromArrayRefGettingValue($argToCheck, $valueRef, \@ARGV);
+}
+
+sub findMatchingArguments($$)
+{
+ my ($argToCheck, $arrayRef) = @_;
+ my @matchingIndices;
+ foreach my $index (0 .. $#$arrayRef) {
+ my $opt = $$arrayRef[$index];
+ if ($opt =~ /^$argToCheck$/i ) {
+ push(@matchingIndices, $index);
+ }
+ }
+ return @matchingIndices;
+}
+
+sub hasArgument($$)
+{
+ my ($argToCheck, $arrayRef) = @_;
+ my @matchingIndices = findMatchingArguments($argToCheck, $arrayRef);
+ return scalar @matchingIndices > 0;
+}
+
+sub checkForArgumentAndRemoveFromArrayRef
+{
+ my ($argToCheck, $arrayRef) = @_;
+ my @indicesToRemove = findMatchingArguments($argToCheck, $arrayRef);
+ my $removeOffset = 0;
+ foreach my $index (@indicesToRemove) {
+ splice(@$arrayRef, $index - $removeOffset++, 1);
+ }
+ return scalar @indicesToRemove > 0;
+}
+
+sub prohibitUnknownPort()
+{
+ $unknownPortProhibited = 1;
+}
+
+sub determinePortName()
+{
+ return if defined $portName;
+
+ my %argToPortName = (
+ efl => Efl,
+ gtk => GTK,
+ wincairo => WinCairo
+ );
+
+ for my $arg (sort keys %argToPortName) {
+ if (checkForArgumentAndRemoveFromARGV("--$arg")) {
+ die "Argument '--$arg' conflicts with selected port '$portName'\n"
+ if defined $portName;
+
+ $portName = $argToPortName{$arg};
+ }
+ }
+
+ return if defined $portName;
+
+ # Port was not selected via command line, use appropriate default value
+
+ if (isAnyWindows()) {
+ $portName = AppleWin;
+ } elsif (isDarwin()) {
+ determineXcodeSDK();
+ if (willUseIOSDeviceSDK() || willUseIOSSimulatorSDK()) {
+ $portName = iOS;
+ } else {
+ $portName = Mac;
+ }
+ } else {
+ if ($unknownPortProhibited) {
+ my $portsChoice = join "\n\t", qw(
+ --efl
+ --gtk
+ );
+ die "Please specify which WebKit port to build using one of the following options:"
+ . "\n\t$portsChoice\n";
+ }
+
+ # If script is run without arguments we cannot determine port
+ # TODO: This state should be outlawed
+ $portName = Unknown;
+ }
+}
+
+sub portName()
+{
+ determinePortName();
+ return $portName;
+}
+
+sub isEfl()
+{
+ return portName() eq Efl;
+}
+
+sub isGtk()
+{
+ return portName() eq GTK;
+}
+
+# Determine if this is debian, ubuntu, linspire, or something similar.
+sub isDebianBased()
+{
+ return -e "/etc/debian_version";
+}
+
+sub isFedoraBased()
+{
+ return -e "/etc/fedora-release";
+}
+
+sub isWinCairo()
+{
+ return portName() eq WinCairo;
+}
+
+sub isWin64()
+{
+ determineIsWin64();
+ return $isWin64;
+}
+
+sub determineIsWin64()
+{
+ return if defined($isWin64);
+ $isWin64 = checkForArgumentAndRemoveFromARGV("--64-bit");
+}
+
+sub determineIsWin64FromArchitecture($)
+{
+ my $arch = shift;
+ $isWin64 = ($arch eq "x86_64");
+ return $isWin64;
+}
+
+sub isCygwin()
+{
+ return ($^O eq "cygwin") || 0;
+}
+
+sub isAnyWindows()
+{
+ return isWindows() || isCygwin();
+}
+
+sub determineWinVersion()
+{
+ return if $winVersion;
+
+ if (!isAnyWindows()) {
+ $winVersion = -1;
+ return;
+ }
+
+ my $versionString = `cmd /c ver`;
+ $versionString =~ /(\d)\.(\d)\.(\d+)/;
+
+ $winVersion = {
+ major => $1,
+ minor => $2,
+ build => $3,
+ };
+}
+
+sub winVersion()
+{
+ determineWinVersion();
+ return $winVersion;
+}
+
+sub isWindows7SP0()
+{
+ return isAnyWindows() && winVersion()->{major} == 6 && winVersion()->{minor} == 1 && winVersion()->{build} == 7600;
+}
+
+sub isWindowsVista()
+{
+ return isAnyWindows() && winVersion()->{major} == 6 && winVersion()->{minor} == 0;
+}
+
+sub isWindowsXP()
+{
+ return isAnyWindows() && winVersion()->{major} == 5 && winVersion()->{minor} == 1;
+}
+
+sub isDarwin()
+{
+ return ($^O eq "darwin") || 0;
+}
+
+sub isWindows()
+{
+ return ($^O eq "MSWin32") || 0;
+}
+
+sub isLinux()
+{
+ return ($^O eq "linux") || 0;
+}
+
+sub isBSD()
+{
+ return ($^O eq "freebsd") || ($^O eq "openbsd") || ($^O eq "netbsd") || 0;
+}
+
+sub isARM()
+{
+ return ($Config{archname} =~ /^arm[v\-]/) || ($Config{archname} =~ /^aarch64[v\-]/);
+}
+
+sub isX86_64()
+{
+ return (architecture() eq "x86_64") || 0;
+}
+
+sub isCrossCompilation()
+{
+ my $compiler = "";
+ $compiler = $ENV{'CC'} if (defined($ENV{'CC'}));
+ if ($compiler =~ /gcc/) {
+ my $compiler_options = `$compiler -v 2>&1`;
+ my @host = $compiler_options =~ m/--host=(.*?)\s/;
+ my @target = $compiler_options =~ m/--target=(.*?)\s/;
+
+ return ($host[0] ne "" && $target[0] ne "" && $host[0] ne $target[0]);
+ }
+ return 0;
+}
+
+sub isAppleWebKit()
+{
+ return isAppleMacWebKit() || isAppleWinWebKit();
+}
+
+sub isAppleMacWebKit()
+{
+ return (portName() eq Mac) || isIOSWebKit();
+}
+
+sub isAppleWinWebKit()
+{
+ return portName() eq AppleWin;
+}
+
+sub iOSSimulatorDevicesPath
+{
+ return "$ENV{HOME}/Library/Developer/CoreSimulator/Devices";
+}
+
+sub iOSSimulatorDevices
+{
+ eval "require Foundation";
+ my $devicesPath = iOSSimulatorDevicesPath();
+ opendir(DEVICES, $devicesPath);
+ my @udids = grep {
+ $_ =~ m/[0-9A-F]{8}-([0-9A-F]{4}-){3}[0-9A-F]{12}/;
+ } readdir(DEVICES);
+ close(DEVICES);
+
+ # FIXME: We should parse the device.plist file ourself and map the dictionary keys in it to known
+ # dictionary keys so as to decouple our representation of the plist from the actual structure
+ # of the plist, which may change.
+ my @devices = map {
+ Foundation::perlRefFromObjectRef(NSDictionary->dictionaryWithContentsOfFile_("$devicesPath/$_/device.plist"));
+ } @udids;
+
+ return @devices;
+}
+
+sub createiOSSimulatorDevice
+{
+ my $name = shift;
+ my $deviceTypeId = shift;
+ my $runtimeId = shift;
+
+ my $created = system("xcrun", "--sdk", "iphonesimulator", "simctl", "create", $name, $deviceTypeId, $runtimeId) == 0;
+ die "Couldn't create simulator device: $name $deviceTypeId $runtimeId" if not $created;
+
+ system("xcrun", "--sdk", "iphonesimulator", "simctl", "list");
+
+ print "Waiting for device to be created ...\n";
+ sleep 5;
+ for (my $tries = 0; $tries < 5; $tries++){
+ my @devices = iOSSimulatorDevices();
+ foreach my $device (@devices) {
+ return $device if $device->{name} eq $name and $device->{deviceType} eq $deviceTypeId and $device->{runtime} eq $runtimeId;
+ }
+ sleep 5;
+ }
+ die "Device $name $deviceTypeId $runtimeId wasn't found in " . iOSSimulatorDevicesPath();
+}
+
+sub willUseIOSDeviceSDK()
+{
+ return xcodeSDKPlatformName() eq "iphoneos";
+}
+
+sub willUseIOSSimulatorSDK()
+{
+ return xcodeSDKPlatformName() eq "iphonesimulator";
+}
+
+sub isIOSWebKit()
+{
+ return portName() eq iOS;
+}
+
+sub determineNmPath()
+{
+ return if $nmPath;
+
+ if (isAppleMacWebKit()) {
+ $nmPath = `xcrun -find nm`;
+ chomp $nmPath;
+ }
+ $nmPath = "nm" if !$nmPath;
+}
+
+sub nmPath()
+{
+ determineNmPath();
+ return $nmPath;
+}
+
+sub splitVersionString
+{
+ my $versionString = shift;
+ my @splitVersion = split(/\./, $versionString);
+ @splitVersion >= 2 or die "Invalid version $versionString";
+ $osXVersion = {
+ "major" => $splitVersion[0],
+ "minor" => $splitVersion[1],
+ "subminor" => (defined($splitVersion[2]) ? $splitVersion[2] : 0),
+ };
+}
+
+sub determineOSXVersion()
+{
+ return if $osXVersion;
+
+ if (!isDarwin()) {
+ $osXVersion = -1;
+ return;
+ }
+
+ my $versionString = `sw_vers -productVersion`;
+ $osXVersion = splitVersionString($versionString);
+}
+
+sub osXVersion()
+{
+ determineOSXVersion();
+ return $osXVersion;
+}
+
+sub determineIOSVersion()
+{
+ return if $iosVersion;
+
+ if (!isIOSWebKit()) {
+ $iosVersion = -1;
+ return;
+ }
+
+ my $versionString = xcodeSDKVersion();
+ $iosVersion = splitVersionString($versionString);
+}
+
+sub iosVersion()
+{
+ determineIOSVersion();
+ return $iosVersion;
+}
+
+sub isWindowsNT()
+{
+ return $ENV{'OS'} eq 'Windows_NT';
+}
+
+sub debugger
+{
+ determineDebugger();
+ return $debugger;
+}
+
+sub determineDebugger
+{
+ return if defined($debugger);
+
+ determineXcodeVersion();
+ if (eval "v$xcodeVersion" ge v4.5) {
+ $debugger = "lldb";
+ } else {
+ $debugger = "gdb";
+ }
+
+ if (checkForArgumentAndRemoveFromARGV("--use-lldb")) {
+ $debugger = "lldb";
+ }
+
+ if (checkForArgumentAndRemoveFromARGV("--use-gdb")) {
+ $debugger = "gdb";
+ }
+}
+
+sub appendToEnvironmentVariableList($$)
+{
+ my ($name, $value) = @_;
+
+ if (defined($ENV{$name})) {
+ $ENV{$name} .= $Config{path_sep} . $value;
+ } else {
+ $ENV{$name} = $value;
+ }
+}
+
+sub prependToEnvironmentVariableList($$)
+{
+ my ($name, $value) = @_;
+
+ if (defined($ENV{$name})) {
+ $ENV{$name} = $value . $Config{path_sep} . $ENV{$name};
+ } else {
+ $ENV{$name} = $value;
+ }
+}
+
+sub sharedCommandLineOptions()
+{
+ return (
+ "g|guard-malloc" => \$shouldUseGuardMalloc,
+ );
+}
+
+sub sharedCommandLineOptionsUsage
+{
+ my %opts = @_;
+
+ my %switches = (
+ '-g|--guard-malloc' => 'Use guardmalloc when running executable',
+ );
+
+ my $indent = " " x ($opts{indent} || 2);
+ my $switchWidth = List::Util::max(int($opts{switchWidth}), List::Util::max(map { length($_) } keys %switches) + ($opts{brackets} ? 2 : 0));
+
+ my $result = "Common switches:\n";
+
+ for my $switch (keys %switches) {
+ my $switchName = $opts{brackets} ? "[" . $switch . "]" : $switch;
+ $result .= sprintf("%s%-" . $switchWidth . "s %s\n", $indent, $switchName, $switches{$switch});
+ }
+
+ return $result;
+}
+
+sub setUpGuardMallocIfNeeded
+{
+ if (!isDarwin()) {
+ return;
+ }
+
+ if (!defined($shouldUseGuardMalloc)) {
+ $shouldUseGuardMalloc = checkForArgumentAndRemoveFromARGV("-g") || checkForArgumentAndRemoveFromARGV("--guard-malloc");
+ }
+
+ if ($shouldUseGuardMalloc) {
+ appendToEnvironmentVariableList("DYLD_INSERT_LIBRARIES", "/usr/lib/libgmalloc.dylib");
+ appendToEnvironmentVariableList("__XPC_DYLD_INSERT_LIBRARIES", "/usr/lib/libgmalloc.dylib");
+ }
+}
+
+sub relativeScriptsDir()
+{
+ my $scriptDir = File::Spec->catpath("", File::Spec->abs2rel($FindBin::Bin, getcwd()), "");
+ if ($scriptDir eq "") {
+ $scriptDir = ".";
+ }
+ return $scriptDir;
+}
+
+sub launcherPath()
+{
+ my $relativeScriptsPath = relativeScriptsDir();
+ if (isGtk() || isEfl()) {
+ return "$relativeScriptsPath/run-minibrowser";
+ } elsif (isAppleWebKit()) {
+ return "$relativeScriptsPath/run-safari";
+ }
+}
+
+sub launcherName()
+{
+ if (isGtk() || isEfl()) {
+ return "MiniBrowser";
+ } elsif (isAppleMacWebKit()) {
+ return "Safari";
+ } elsif (isAppleWinWebKit()) {
+ return "MiniBrowser";
+ }
+}
+
+sub checkRequiredSystemConfig
+{
+ if (isDarwin()) {
+ chomp(my $productVersion = `sw_vers -productVersion`);
+ if (eval "v$productVersion" lt v10.7.5) {
+ print "*************************************************************\n";
+ print "Mac OS X Version 10.7.5 or later is required to build WebKit.\n";
+ print "You have " . $productVersion . ", thus the build will most likely fail.\n";
+ print "*************************************************************\n";
+ }
+ my $xcodebuildVersionOutput = `xcodebuild -version`;
+ my $xcodeVersion = ($xcodebuildVersionOutput =~ /Xcode ([0-9](\.[0-9]+)*)/) ? $1 : undef;
+ if (!$xcodeVersion || $xcodeVersion && eval "v$xcodeVersion" lt v4.6) {
+ print "*************************************************************\n";
+ print "Xcode Version 4.6 or later is required to build WebKit.\n";
+ print "You have an earlier version of Xcode, thus the build will\n";
+ print "most likely fail. The latest Xcode is available from the App Store.\n";
+ print "*************************************************************\n";
+ }
+ }
+}
+
+sub determineWindowsSourceDir()
+{
+ return if $windowsSourceDir;
+ $windowsSourceDir = sourceDir();
+ chomp($windowsSourceDir = `cygpath -w '$windowsSourceDir'`) if isCygwin();
+}
+
+sub windowsSourceDir()
+{
+ determineWindowsSourceDir();
+ return $windowsSourceDir;
+}
+
+sub windowsSourceSourceDir()
+{
+ return File::Spec->catdir(windowsSourceDir(), "Source");
+}
+
+sub windowsLibrariesDir()
+{
+ return File::Spec->catdir(windowsSourceDir(), "WebKitLibraries", "win");
+}
+
+sub windowsOutputDir()
+{
+ return File::Spec->catdir(windowsSourceDir(), "WebKitBuild");
+}
+
+sub fontExists($)
+{
+ my $font = shift;
+ my $cmd = "reg query \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts\\" . $font ."\" 2>&1";
+ my $val = `$cmd`;
+ return $? == 0;
+}
+
+sub checkInstalledTools()
+{
+ # environment variables. Avoid until this is corrected.
+ my $pythonVer = `python --version 2>&1`;
+ die "You must have Python installed to build WebKit.\n" if ($?);
+
+ # cURL 7.34.0 has a bug that prevents authentication with opensource.apple.com (and other things using SSL3).
+ my $curlVer = `curl --version 2> NUL`;
+ if (!$? and $curlVer =~ "(.*curl.*)") {
+ $curlVer = $1;
+ if ($curlVer =~ /libcurl\/7\.34\.0/) {
+ print "cURL version 7.34.0 has a bug that prevents authentication with SSL v2 or v3.\n";
+ print "cURL 7.33.0 is known to work. The cURL projects is preparing an update to\n";
+ print "correct this problem.\n\n";
+ die "Please install a working cURL and try again.\n";
+ }
+ }
+
+ # MathML requires fonts that do not ship with Windows (at least through Windows 8). Warn the user if they are missing
+ my @fonts = qw(STIXGeneral-Regular MathJax_Main-Regular);
+ my @missing = ();
+ foreach my $font (@fonts) {
+ push @missing, $font if not fontExists($font);
+ }
+
+ if (scalar @missing > 0) {
+ print "*************************************************************\n";
+ print "Mathematical fonts, such as STIX and MathJax, are needed to\n";
+ print "use the MathML feature. You do not appear to have these fonts\n";
+ print "on your system.\n\n";
+ print "You can download a suitable set of fonts from the following URL:\n";
+ print "https://developer.mozilla.org/Mozilla/MathML_Projects/Fonts\n";
+ print "*************************************************************\n";
+ }
+
+ print "Installed tools are correct for the WebKit build.\n";
+}
+
+sub setupAppleWinEnv()
+{
+ return unless isAppleWinWebKit();
+
+ checkInstalledTools();
+
+ if (isWindowsNT()) {
+ my $restartNeeded = 0;
+ my %variablesToSet = ();
+
+ # FIXME: We should remove this explicit version check for cygwin once we stop supporting Cygwin 1.7.9 or older versions.
+ # https://bugs.webkit.org/show_bug.cgi?id=85791
+ my $uname_version = (POSIX::uname())[2];
+ $uname_version =~ s/\(.*\)//; # Remove the trailing cygwin version, if any.
+ $uname_version =~ s/\-.*$//; # Remove trailing dash-version content, if any
+ if (version->parse($uname_version) < version->parse("1.7.10")) {
+ # Setting the environment variable 'CYGWIN' to 'tty' makes cygwin enable extra support (i.e., termios)
+ # for UNIX-like ttys in the Windows console
+ $variablesToSet{CYGWIN} = "tty" unless $ENV{CYGWIN};
+ }
+
+ # Those environment variables must be set to be able to build inside Visual Studio.
+ $variablesToSet{WEBKIT_LIBRARIES} = windowsLibrariesDir() unless $ENV{WEBKIT_LIBRARIES};
+ $variablesToSet{WEBKIT_OUTPUTDIR} = windowsOutputDir() unless $ENV{WEBKIT_OUTPUTDIR};
+ $variablesToSet{MSBUILDDISABLENODEREUSE} = "1" unless $ENV{MSBUILDDISABLENODEREUSE};
+ $variablesToSet{_IsNativeEnvironment} = "true" unless $ENV{_IsNativeEnvironment};
+ $variablesToSet{PreferredToolArchitecture} = "x64" unless $ENV{PreferredToolArchitecture};
+
+ foreach my $variable (keys %variablesToSet) {
+ print "Setting the Environment Variable '" . $variable . "' to '" . $variablesToSet{$variable} . "'\n\n";
+ my $ret = system "setx", $variable, $variablesToSet{$variable};
+ if ($ret != 0) {
+ system qw(regtool -s set), '\\HKEY_CURRENT_USER\\Environment\\' . $variable, $variablesToSet{$variable};
+ }
+ $restartNeeded ||= $variable eq "WEBKIT_LIBRARIES" || $variable eq "WEBKIT_OUTPUTDIR";
+ }
+
+ if ($restartNeeded) {
+ print "Please restart your computer before attempting to build inside Visual Studio.\n\n";
+ }
+ } else {
+ if (!defined $ENV{'WEBKIT_LIBRARIES'} || !$ENV{'WEBKIT_LIBRARIES'}) {
+ print "Warning: You must set the 'WebKit_Libraries' environment variable\n";
+ print " to be able build WebKit from within Visual Studio 2013 and newer.\n";
+ print " Make sure that 'WebKit_Libraries' points to the\n";
+ print " 'WebKitLibraries/win' directory, not the 'WebKitLibraries/' directory.\n\n";
+ }
+ if (!defined $ENV{'WEBKIT_OUTPUTDIR'} || !$ENV{'WEBKIT_OUTPUTDIR'}) {
+ print "Warning: You must set the 'WebKit_OutputDir' environment variable\n";
+ print " to be able build WebKit from within Visual Studio 2013 and newer.\n\n";
+ }
+ if (!defined $ENV{'MSBUILDDISABLENODEREUSE'} || !$ENV{'MSBUILDDISABLENODEREUSE'}) {
+ print "Warning: You should set the 'MSBUILDDISABLENODEREUSE' environment variable to '1'\n";
+ print " to avoid periodic locked log files when building.\n\n";
+ }
+ }
+ # FIXME (125180): Remove the following temporary 64-bit support once official support is available.
+ if (isWin64() and !$ENV{'WEBKIT_64_SUPPORT'}) {
+ print "Warning: You must set the 'WEBKIT_64_SUPPORT' environment variable\n";
+ print " to be able run WebKit or JavaScriptCore tests.\n\n";
+ }
+}
+
+sub setupCygwinEnv()
+{
+ return if !isAnyWindows();
+ return if $vcBuildPath;
+
+ my $programFilesPath = programFilesPath();
+ my $visualStudioPath = File::Spec->catfile(visualStudioInstallDir(), qw(Common7 IDE devenv.com));
+ if (-e $visualStudioPath) {
+ # Visual Studio is installed;
+ if (visualStudioVersion() eq "12") {
+ $visualStudioPath = File::Spec->catfile(visualStudioInstallDir(), qw(Common7 IDE devenv.exe));
+ }
+ } else {
+ # Visual Studio not found, try VC++ Express
+ $visualStudioPath = File::Spec->catfile(visualStudioInstallDir(), qw(Common7 IDE WDExpress.exe));
+ if (! -e $visualStudioPath) {
+ print "*************************************************************\n";
+ print "Cannot find '$visualStudioPath'\n";
+ print "Please execute the file 'vcvars32.bat' from\n";
+ print "'$programFilesPath\\Microsoft Visual Studio 14.0\\VC\\bin\\'\n";
+ print "to setup the necessary environment variables.\n";
+ print "*************************************************************\n";
+ die;
+ }
+ $willUseVCExpressWhenBuilding = 1;
+ }
+
+ print "Building results into: ", baseProductDir(), "\n";
+ print "WEBKIT_OUTPUTDIR is set to: ", $ENV{"WEBKIT_OUTPUTDIR"}, "\n";
+ print "WEBKIT_LIBRARIES is set to: ", $ENV{"WEBKIT_LIBRARIES"}, "\n";
+ # FIXME (125180): Remove the following temporary 64-bit support once official support is available.
+ print "WEBKIT_64_SUPPORT is set to: ", $ENV{"WEBKIT_64_SUPPORT"}, "\n" if isWin64();
+
+ # We will actually use MSBuild to build WebKit, but we need to find the Visual Studio install (above) to make
+ # sure we use the right options.
+ $vcBuildPath = File::Spec->catfile(msBuildInstallDir(), qw(MSBuild.exe));
+ if (! -e $vcBuildPath) {
+ print "*************************************************************\n";
+ print "Cannot find '$vcBuildPath'\n";
+ print "Please make sure execute that the Microsoft .NET Framework SDK\n";
+ print "is installed on this machine.\n";
+ print "*************************************************************\n";
+ die;
+ }
+}
+
+sub dieIfWindowsPlatformSDKNotInstalled
+{
+ my $registry32Path = "/proc/registry/";
+ my $registry64Path = "/proc/registry64/";
+ my @windowsPlatformSDKRegistryEntries = (
+ "HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SDKs/Windows/v8.0A",
+ "HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SDKs/Windows/v8.0",
+ "HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SDKs/Windows/v7.1A",
+ "HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SDKs/Windows/v7.0A",
+ "HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/MicrosoftSDK/InstalledSDKs/D2FF9F89-8AA2-4373-8A31-C838BF4DBBE1",
+ );
+
+ # FIXME: It would be better to detect whether we are using 32- or 64-bit Windows
+ # and only check the appropriate entry. But for now we just blindly check both.
+ my $recommendedPlatformSDK = $windowsPlatformSDKRegistryEntries[0];
+
+ while (@windowsPlatformSDKRegistryEntries) {
+ my $windowsPlatformSDKRegistryEntry = shift @windowsPlatformSDKRegistryEntries;
+ return if (-e $registry32Path . $windowsPlatformSDKRegistryEntry) || (-e $registry64Path . $windowsPlatformSDKRegistryEntry);
+ }
+
+ print "*************************************************************\n";
+ print "Cannot find registry entry '$recommendedPlatformSDK'.\n";
+ print "Please download and install the Microsoft Windows SDK\n";
+ print "from <http://www.microsoft.com/en-us/download/details.aspx?id=8279>.\n\n";
+ print "Then follow step 2 in the Windows section of the \"Installing Developer\n";
+ print "Tools\" instructions at <http://www.webkit.org/building/tools.html>.\n";
+ print "*************************************************************\n";
+ die;
+}
+
+sub buildXCodeProject($$@)
+{
+ my ($project, $clean, @extraOptions) = @_;
+
+ if ($clean) {
+ push(@extraOptions, "-alltargets");
+ push(@extraOptions, "clean");
+ }
+
+ push(@extraOptions, ("-sdk", xcodeSDK())) if isIOSWebKit();
+
+ chomp($ENV{DSYMUTIL_NUM_THREADS} = `sysctl -n hw.activecpu`);
+ return system "xcodebuild", "-project", "$project.xcodeproj", @extraOptions;
+}
+
+sub usingVisualStudioExpress()
+{
+ setupCygwinEnv();
+ return $willUseVCExpressWhenBuilding;
+}
+
+sub buildVisualStudioProject
+{
+ my ($project, $clean) = @_;
+ setupCygwinEnv();
+
+ my $config = configurationForVisualStudio();
+
+ dieIfWindowsPlatformSDKNotInstalled() if $willUseVCExpressWhenBuilding;
+
+ chomp($project = `cygpath -w "$project"`) if isCygwin();
+
+ my $action = "/t:build";
+ if ($clean) {
+ $action = "/t:clean";
+ }
+
+ my $platform = "/p:Platform=" . (isWin64() ? "x64" : "Win32");
+ my $logPath = File::Spec->catdir($baseProductDir, $configuration);
+ make_path($logPath) unless -d $logPath or $logPath eq ".";
+
+ my $errorLogFile = File::Spec->catfile($logPath, "webkit_errors.log");
+ chomp($errorLogFile = `cygpath -w "$errorLogFile"`) if isCygwin();
+ my $errorLogging = "/flp:LogFile=" . $errorLogFile . ";ErrorsOnly";
+
+ my $warningLogFile = File::Spec->catfile($logPath, "webkit_warnings.log");
+ chomp($warningLogFile = `cygpath -w "$warningLogFile"`) if isCygwin();
+ my $warningLogging = "/flp1:LogFile=" . $warningLogFile . ";WarningsOnly";
+
+ my @command = ($vcBuildPath, "/verbosity:minimal", $project, $action, $config, $platform, "/fl", $errorLogging, "/fl1", $warningLogging);
+ print join(" ", @command), "\n";
+ return system @command;
+}
+
+sub getJhbuildPath()
+{
+ my @jhbuildPath = File::Spec->splitdir(baseProductDir());
+ if (isGit() && isGitBranchBuild() && gitBranch()) {
+ pop(@jhbuildPath);
+ }
+ if (isEfl()) {
+ push(@jhbuildPath, "DependenciesEFL");
+ } elsif (isGtk()) {
+ push(@jhbuildPath, "DependenciesGTK");
+ } else {
+ die "Cannot get JHBuild path for platform that isn't GTK+ or EFL.\n";
+ }
+ return File::Spec->catdir(@jhbuildPath);
+}
+
+sub isCachedArgumentfileOutOfDate($@)
+{
+ my ($filename, $currentContents) = @_;
+
+ if (! -e $filename) {
+ return 1;
+ }
+
+ open(CONTENTS_FILE, $filename);
+ chomp(my $previousContents = <CONTENTS_FILE>);
+ close(CONTENTS_FILE);
+
+ if ($previousContents ne $currentContents) {
+ print "Contents for file $filename have changed.\n";
+ print "Previous contents were: $previousContents\n\n";
+ print "New contents are: $currentContents\n";
+ return 1;
+ }
+
+ return 0;
+}
+
+sub wrapperPrefixIfNeeded()
+{
+ if (isAnyWindows()) {
+ return ();
+ }
+ if (isAppleMacWebKit()) {
+ return ("xcrun");
+ }
+ if (-e getJhbuildPath()) {
+ my @prefix = (File::Spec->catfile(sourceDir(), "Tools", "jhbuild", "jhbuild-wrapper"));
+ if (isEfl()) {
+ push(@prefix, "--efl");
+ } elsif (isGtk()) {
+ push(@prefix, "--gtk");
+ }
+ push(@prefix, "run");
+
+ return @prefix;
+ }
+
+ return ();
+}
+
+sub cmakeCachePath()
+{
+ return File::Spec->catdir(baseProductDir(), configuration(), "CMakeCache.txt");
+}
+
+sub shouldRemoveCMakeCache(@)
+{
+ my ($cacheFilePath, @buildArgs) = @_;
+
+ # We check this first, because we always want to create this file for a fresh build.
+ my $productDir = File::Spec->catdir(baseProductDir(), configuration());
+ my $optionsCache = File::Spec->catdir($productDir, "build-webkit-options.txt");
+ my $joinedBuildArgs = join(" ", @buildArgs);
+ if (isCachedArgumentfileOutOfDate($optionsCache, $joinedBuildArgs)) {
+ File::Path::mkpath($productDir) unless -d $productDir;
+ open(CACHED_ARGUMENTS, ">", $optionsCache);
+ print CACHED_ARGUMENTS $joinedBuildArgs;
+ close(CACHED_ARGUMENTS);
+
+ return 1;
+ }
+
+ my $cmakeCache = cmakeCachePath();
+ unless (-e $cmakeCache) {
+ return 0;
+ }
+
+ my $cacheFileModifiedTime = stat($cmakeCache)->mtime;
+ my $platformConfiguration = File::Spec->catdir(sourceDir(), "Source", "cmake", "Options" . cmakeBasedPortName() . ".cmake");
+ if ($cacheFileModifiedTime < stat($platformConfiguration)->mtime) {
+ return 1;
+ }
+
+ my $globalConfiguration = File::Spec->catdir(sourceDir(), "Source", "cmake", "OptionsCommon.cmake");
+ if ($cacheFileModifiedTime < stat($globalConfiguration)->mtime) {
+ return 1;
+ }
+
+ my $inspectorUserInterfaceDircetory = File::Spec->catdir(sourceDir(), "Source", "WebInspectorUI", "UserInterface");
+ if ($cacheFileModifiedTime < stat($inspectorUserInterfaceDircetory)->mtime) {
+ return 1;
+ }
+
+ return 0;
+}
+
+sub removeCMakeCache(@)
+{
+ my (@buildArgs) = @_;
+ if (shouldRemoveCMakeCache(@buildArgs)) {
+ my $cmakeCache = cmakeCachePath();
+ unlink($cmakeCache) if -e $cmakeCache;
+ }
+}
+
+sub canUseNinja(@)
+{
+ if (!defined($shouldNotUseNinja)) {
+ $shouldNotUseNinja = checkForArgumentAndRemoveFromARGV("--no-ninja");
+ }
+
+ if ($shouldNotUseNinja) {
+ return 0;
+ }
+
+ # Test both ninja and ninja-build. Fedora uses ninja-build and has patched CMake to also call ninja-build.
+ return commandExists("ninja") || commandExists("ninja-build");
+}
+
+sub canUseNinjaGenerator(@)
+{
+ # Check that a Ninja generator is installed
+ my $devnull = File::Spec->devnull();
+ return exitStatus(system("cmake -N -G Ninja >$devnull 2>&1")) == 0;
+}
+
+sub canUseEclipseNinjaGenerator(@)
+{
+ # Check that eclipse and eclipse Ninja generator is installed
+ my $devnull = File::Spec->devnull();
+ return commandExists("eclipse") && exitStatus(system("cmake -N -G 'Eclipse CDT4 - Ninja' >$devnull 2>&1")) == 0;
+}
+
+sub cmakeGeneratedBuildfile(@)
+{
+ my ($willUseNinja) = @_;
+ if ($willUseNinja) {
+ return File::Spec->catfile(baseProductDir(), configuration(), "build.ninja")
+ } elsif (isAnyWindows()) {
+ return File::Spec->catfile(baseProductDir(), configuration(), "WebKit.sln")
+ } else {
+ return File::Spec->catfile(baseProductDir(), configuration(), "Makefile")
+ }
+}
+
+sub generateBuildSystemFromCMakeProject
+{
+ my ($prefixPath, @cmakeArgs) = @_;
+ my $config = configuration();
+ my $port = cmakeBasedPortName();
+ my $buildPath = File::Spec->catdir(baseProductDir(), $config);
+ File::Path::mkpath($buildPath) unless -d $buildPath;
+ my $originalWorkingDirectory = getcwd();
+ chdir($buildPath) or die;
+
+ # We try to be smart about when to rerun cmake, so that we can have faster incremental builds.
+ my $willUseNinja = canUseNinja() && canUseNinjaGenerator();
+ if (-e cmakeCachePath() && -e cmakeGeneratedBuildfile($willUseNinja)) {
+ return 0;
+ }
+
+ my @args;
+ push @args, "-DPORT=\"$port\"";
+ push @args, "-DCMAKE_INSTALL_PREFIX=\"$prefixPath\"" if $prefixPath;
+ push @args, "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON" if isGtk();
+ if ($config =~ /release/i) {
+ push @args, "-DCMAKE_BUILD_TYPE=Release";
+ } elsif ($config =~ /debug/i) {
+ push @args, "-DCMAKE_BUILD_TYPE=Debug";
+ }
+
+ if ($willUseNinja) {
+ push @args, "-G";
+ if (canUseEclipseNinjaGenerator()) {
+ push @args, "'Eclipse CDT4 - Ninja'";
+ } else {
+ push @args, "Ninja";
+ }
+ } elsif (isAnyWindows() && isWin64()) {
+ push @args, '-G "Visual Studio 14 2015 Win64"';
+ }
+
+ # GTK+ has a production mode, but build-webkit should always use developer mode.
+ push @args, "-DDEVELOPER_MODE=ON" if isEfl() || isGtk();
+
+ # Don't warn variables which aren't used by cmake ports.
+ push @args, "--no-warn-unused-cli";
+ push @args, @cmakeArgs if @cmakeArgs;
+
+ my $cmakeSourceDir = isCygwin() ? windowsSourceDir() : sourceDir();
+ push @args, '"' . $cmakeSourceDir . '"';
+
+ # Compiler options to keep floating point values consistent
+ # between 32-bit and 64-bit architectures.
+ determineArchitecture();
+ if ($architecture ne "x86_64" && !isARM() && !isCrossCompilation() && !isAnyWindows()) {
+ $ENV{'CXXFLAGS'} = "-march=pentium4 -msse2 -mfpmath=sse " . ($ENV{'CXXFLAGS'} || "");
+ }
+
+ # We call system("cmake @args") instead of system("cmake", @args) so that @args is
+ # parsed for shell metacharacters.
+ my $wrapper = join(" ", wrapperPrefixIfNeeded()) . " ";
+ my $returnCode = system($wrapper . "cmake @args");
+
+ chdir($originalWorkingDirectory);
+ return $returnCode;
+}
+
+sub buildCMakeGeneratedProject($)
+{
+ my ($makeArgs) = @_;
+ my $config = configuration();
+ my $buildPath = File::Spec->catdir(baseProductDir(), $config);
+ if (! -d $buildPath) {
+ die "Must call generateBuildSystemFromCMakeProject() before building CMake project.";
+ }
+
+ my $command = "cmake";
+ my @args = ("--build", $buildPath, "--config", $config);
+ push @args, ("--", $makeArgs) if $makeArgs;
+
+ # GTK can use a build script to preserve colors and pretty-printing.
+ if (isGtk() && -e "$buildPath/build.sh") {
+ chdir "$buildPath" or die;
+ $command = "$buildPath/build.sh";
+ @args = ($makeArgs);
+ }
+
+ if ($ENV{VERBOSE} && canUseNinja()) {
+ push @args, "-v";
+ push @args, "-d keeprsp" if (version->parse(determineNinjaVersion()) >= version->parse("1.4.0"));
+ }
+
+ # We call system("cmake @args") instead of system("cmake", @args) so that @args is
+ # parsed for shell metacharacters. In particular, $makeArgs may contain such metacharacters.
+ my $wrapper = join(" ", wrapperPrefixIfNeeded()) . " ";
+ return system($wrapper . "$command @args");
+}
+
+sub cleanCMakeGeneratedProject()
+{
+ my $config = configuration();
+ my $buildPath = File::Spec->catdir(baseProductDir(), $config);
+ if (-d $buildPath) {
+ return system("cmake", "--build", $buildPath, "--config", $config, "--target", "clean");
+ }
+ return 0;
+}
+
+sub buildCMakeProjectOrExit($$$@)
+{
+ my ($clean, $prefixPath, $makeArgs, @cmakeArgs) = @_;
+ my $returnCode;
+
+ exit(exitStatus(cleanCMakeGeneratedProject())) if $clean;
+
+ if (isEfl() && checkForArgumentAndRemoveFromARGV("--update-efl")) {
+ system("perl", "$sourceDir/Tools/Scripts/update-webkitefl-libs") == 0 or die $!;
+ }
+
+ if (isGtk() && checkForArgumentAndRemoveFromARGV("--update-gtk")) {
+ system("perl", "$sourceDir/Tools/Scripts/update-webkitgtk-libs") == 0 or die $!;
+ }
+
+ $returnCode = exitStatus(generateBuildSystemFromCMakeProject($prefixPath, @cmakeArgs));
+ exit($returnCode) if $returnCode;
+
+ $returnCode = exitStatus(buildCMakeGeneratedProject($makeArgs));
+ exit($returnCode) if $returnCode;
+ return 0;
+}
+
+sub cmakeBasedPortArguments()
+{
+ return ();
+}
+
+sub cmakeBasedPortName()
+{
+ return ucfirst portName();
+}
+
+sub determineIsCMakeBuild()
+{
+ return if defined($isCMakeBuild);
+ $isCMakeBuild = checkForArgumentAndRemoveFromARGV("--cmake");
+}
+
+sub isCMakeBuild()
+{
+ return 1 unless isAppleMacWebKit();
+ determineIsCMakeBuild();
+ return $isCMakeBuild;
+}
+
+sub promptUser
+{
+ my ($prompt, $default) = @_;
+ my $defaultValue = $default ? "[$default]" : "";
+ print "$prompt $defaultValue: ";
+ chomp(my $input = <STDIN>);
+ return $input ? $input : $default;
+}
+
+sub appleApplicationSupportPath
+{
+ open INSTALL_DIR, "</proc/registry/HKEY_LOCAL_MACHINE/SOFTWARE/Apple\ Inc./Apple\ Application\ Support/InstallDir";
+ my $path = <INSTALL_DIR>;
+ $path =~ s/[\r\n\x00].*//;
+ close INSTALL_DIR;
+
+ my $unixPath = `cygpath -u '$path'`;
+ chomp $unixPath;
+ return $unixPath;
+}
+
+sub setPathForRunningWebKitApp
+{
+ my ($env) = @_;
+
+ if (isAnyWindows()) {
+ my $productBinaryDir = executableProductDir();
+ if (isAppleWinWebKit()) {
+ $env->{PATH} = join(':', $productBinaryDir, appleApplicationSupportPath(), $env->{PATH} || "");
+ } elsif (isWinCairo()) {
+ my $winCairoBin = sourceDir() . "/WebKitLibraries/win/" . (isWin64() ? "bin64/" : "bin32/");
+ my $gstreamerBin = isWin64() ? $ENV{"GSTREAMER_1_0_ROOT_X86_64"} . "bin" : $ENV{"GSTREAMER_1_0_ROOT_X86"} . "bin";
+ $env->{PATH} = join(':', $productBinaryDir, $winCairoBin, $gstreamerBin, $env->{PATH} || "");
+ }
+ }
+}
+
+sub printHelpAndExitForRunAndDebugWebKitAppIfNeeded
+{
+ return unless checkForArgumentAndRemoveFromARGV("--help");
+
+ my ($includeOptionsForDebugging) = @_;
+
+ print STDERR <<EOF;
+Usage: @{[basename($0)]} [options] [args ...]
+ --help Show this help message
+ --no-saved-state Launch the application without state restoration (OS X 10.7 and later)
+ -g|--guard-malloc Enable Guard Malloc (OS X only)
+EOF
+
+ if ($includeOptionsForDebugging) {
+ print STDERR <<EOF;
+ --use-gdb Use GDB (this is the default when using Xcode 4.4 or earlier)
+ --use-lldb Use LLDB (this is the default when using Xcode 4.5 or later)
+EOF
+ }
+
+ exit(1);
+}
+
+sub argumentsForRunAndDebugMacWebKitApp()
+{
+ my @args = ();
+ if (checkForArgumentAndRemoveFromARGV("--no-saved-state")) {
+ push @args, ("-ApplePersistenceIgnoreStateQuietly", "YES");
+ # FIXME: Don't set ApplePersistenceIgnoreState once all supported OS versions respect ApplePersistenceIgnoreStateQuietly (rdar://15032886).
+ push @args, ("-ApplePersistenceIgnoreState", "YES");
+ }
+ unshift @args, @ARGV;
+
+ return @args;
+}
+
+sub setupMacWebKitEnvironment($)
+{
+ my ($dyldFrameworkPath) = @_;
+
+ $dyldFrameworkPath = File::Spec->rel2abs($dyldFrameworkPath);
+
+ prependToEnvironmentVariableList("DYLD_FRAMEWORK_PATH", $dyldFrameworkPath);
+ prependToEnvironmentVariableList("__XPC_DYLD_FRAMEWORK_PATH", $dyldFrameworkPath);
+ $ENV{WEBKIT_UNSET_DYLD_FRAMEWORK_PATH} = "YES";
+
+ setUpGuardMallocIfNeeded();
+}
+
+sub setupIOSWebKitEnvironment($)
+{
+ my ($dyldFrameworkPath) = @_;
+ $dyldFrameworkPath = File::Spec->rel2abs($dyldFrameworkPath);
+
+ prependToEnvironmentVariableList("DYLD_FRAMEWORK_PATH", $dyldFrameworkPath);
+ prependToEnvironmentVariableList("DYLD_LIBRARY_PATH", $dyldFrameworkPath);
+
+ setUpGuardMallocIfNeeded();
+}
+
+sub iosSimulatorApplicationsPath()
+{
+ return File::Spec->catdir(XcodeSDKPath(), "Applications");
+}
+
+sub installedMobileSafariBundle()
+{
+ return File::Spec->catfile(iosSimulatorApplicationsPath(), "MobileSafari.app");
+}
+
+sub mobileSafariBundle()
+{
+ determineConfigurationProductDir();
+
+ # Use MobileSafari.app in product directory if present.
+ if (isAppleMacWebKit() && -d "$configurationProductDir/MobileSafari.app") {
+ return "$configurationProductDir/MobileSafari.app";
+ }
+ return installedMobileSafariBundle();
+}
+
+sub plistPathFromBundle($)
+{
+ my ($appBundle) = @_;
+ return "$appBundle/Info.plist" if -f "$appBundle/Info.plist"; # iOS app bundle
+ return "$appBundle/Contents/Info.plist" if -f "$appBundle/Contents/Info.plist"; # Mac app bundle
+ return "";
+}
+
+sub appIdentifierFromBundle($)
+{
+ my ($appBundle) = @_;
+ my $plistPath = File::Spec->rel2abs(plistPathFromBundle($appBundle)); # defaults(1) will complain if the specified path is not absolute.
+ chomp(my $bundleIdentifier = `defaults read '$plistPath' CFBundleIdentifier 2> /dev/null`);
+ return $bundleIdentifier;
+}
+
+sub appDisplayNameFromBundle($)
+{
+ my ($appBundle) = @_;
+ my $plistPath = File::Spec->rel2abs(plistPathFromBundle($appBundle)); # defaults(1) will complain if the specified path is not absolute.
+ chomp(my $bundleDisplayName = `defaults read '$plistPath' CFBundleDisplayName 2> /dev/null`);
+ return $bundleDisplayName;
+}
+
+sub waitUntilIOSSimulatorDeviceIsInState($$)
+{
+ my ($deviceUDID, $waitUntilState) = @_;
+ my $device = iosSimulatorDeviceByUDID($deviceUDID);
+ while ($device->{state} ne $waitUntilState) {
+ usleep(500 * 1000); # Waiting 500ms between file system polls does not make script run-safari feel sluggish.
+ $device = iosSimulatorDeviceByUDID($deviceUDID);
+ }
+}
+
+sub shutDownIOSSimulatorDevice($)
+{
+ my ($simulatorDevice) = @_;
+ system("xcrun --sdk iphonesimulator simctl shutdown $simulatorDevice->{UDID} > /dev/null 2>&1");
+}
+
+sub restartIOSSimulatorDevice($)
+{
+ my ($simulatorDevice) = @_;
+ shutDownIOSSimulatorDevice($simulatorDevice);
+
+ exitStatus(system("xcrun", "--sdk", "iphonesimulator", "simctl", "boot", $simulatorDevice->{UDID})) == 0 or die "Failed to boot simulator device $simulatorDevice->{UDID}";
+}
+
+sub relaunchIOSSimulator($)
+{
+ my ($simulatedDevice) = @_;
+ quitIOSSimulator($simulatedDevice->{UDID});
+
+ # FIXME: <rdar://problem/20916140> Switch to using CoreSimulator.framework for launching and quitting iOS Simulator
+ my $iosSimulatorBundleID = "com.apple.iphonesimulator";
+ system("open", "-b", $iosSimulatorBundleID, "--args", "-CurrentDeviceUDID", $simulatedDevice->{UDID}) == 0 or die "Failed to open $iosSimulatorBundleID: $!";
+
+ waitUntilIOSSimulatorDeviceIsInState($simulatedDevice->{UDID}, SIMULATOR_DEVICE_STATE_BOOTED);
+}
+
+sub quitIOSSimulator(;$)
+{
+ my ($waitForShutdownOfSimulatedDeviceUDID) = @_;
+ # FIXME: <rdar://problem/20916140> Switch to using CoreSimulator.framework for launching and quitting iOS Simulator
+ exitStatus(system {"osascript"} "osascript", "-e", 'tell application id "com.apple.iphonesimulator" to quit') == 0 or die "Failed to quit iOS Simulator: $!";
+ if (!defined($waitForShutdownOfSimulatedDeviceUDID)) {
+ return;
+ }
+ # FIXME: We assume that $waitForShutdownOfSimulatedDeviceUDID was not booted using the simctl command line tool.
+ # Otherwise we will spin indefinitely since quiting the iOS Simulator will not shutdown this device. We
+ # should add a maximum time limit to wait for a device to shutdown and either return an error or die()
+ # on expiration of the time limit.
+ waitUntilIOSSimulatorDeviceIsInState($waitForShutdownOfSimulatedDeviceUDID, SIMULATOR_DEVICE_STATE_SHUTDOWN);
+}
+
+sub iosSimulatorDeviceByName($)
+{
+ my ($simulatorName) = @_;
+ my $simulatorRuntime = iosSimulatorRuntime();
+ my @devices = iOSSimulatorDevices();
+ for my $device (@devices) {
+ if ($device->{name} eq $simulatorName && $device->{runtime} eq $simulatorRuntime) {
+ return $device;
+ }
+ }
+ return undef;
+}
+
+sub iosSimulatorDeviceByUDID($)
+{
+ my ($simulatedDeviceUDID) = @_;
+ my $devicePlistPath = File::Spec->catfile(iOSSimulatorDevicesPath(), $simulatedDeviceUDID, "device.plist");
+ if (!-f $devicePlistPath) {
+ return;
+ }
+ # FIXME: We should parse the device.plist file ourself and map the dictionary keys in it to known
+ # dictionary keys so as to decouple our representation of the plist from the actual structure
+ # of the plist, which may change.
+ eval "require Foundation";
+ return Foundation::perlRefFromObjectRef(NSDictionary->dictionaryWithContentsOfFile_($devicePlistPath));
+}
+
+sub iosSimulatorRuntime()
+{
+ my $xcodeSDKVersion = xcodeSDKVersion();
+ $xcodeSDKVersion =~ s/\./-/;
+ return "com.apple.CoreSimulator.SimRuntime.iOS-$xcodeSDKVersion";
+}
+
+sub findOrCreateSimulatorForIOSDevice($)
+{
+ my ($simulatorNameSuffix) = @_;
+ my $simulatorName;
+ my $simulatorDeviceType;
+ if (architecture() eq "x86_64") {
+ $simulatorName = "iPhone 5s " . $simulatorNameSuffix;
+ $simulatorDeviceType = "com.apple.CoreSimulator.SimDeviceType.iPhone-5s";
+ } else {
+ $simulatorName = "iPhone 5 " . $simulatorNameSuffix;
+ $simulatorDeviceType = "com.apple.CoreSimulator.SimDeviceType.iPhone-5";
+ }
+ my $simulatedDevice = iosSimulatorDeviceByName($simulatorName);
+ return $simulatedDevice if $simulatedDevice;
+ return createiOSSimulatorDevice($simulatorName, $simulatorDeviceType, iosSimulatorRuntime());
+}
+
+sub isIOSSimulatorSystemInstalledApp($)
+{
+ my ($appBundle) = @_;
+ my $simulatorApplicationsPath = realpath(iosSimulatorApplicationsPath());
+ return substr(realpath($appBundle), 0, length($simulatorApplicationsPath)) eq $simulatorApplicationsPath;
+}
+
+sub hasUserInstalledAppInSimulatorDevice($$)
+{
+ my ($appIdentifier, $simulatedDeviceUDID) = @_;
+ my $userInstalledAppPath = File::Spec->catfile($ENV{HOME}, "Library", "Developer", "CoreSimulator", "Devices", $simulatedDeviceUDID, "data", "Containers", "Bundle", "Application");
+ if (!-d $userInstalledAppPath) {
+ return 0; # No user installed apps.
+ }
+ local @::userInstalledAppBundles;
+ my $wantedFunction = sub {
+ my $file = $_;
+
+ # Ignore hidden files and directories.
+ if ($file =~ /^\../) {
+ $File::Find::prune = 1;
+ return;
+ }
+
+ return if !-d $file || $file !~ /\.app$/;
+ push @::userInstalledAppBundles, $File::Find::name;
+ $File::Find::prune = 1; # Do not traverse contents of app bundle.
+ };
+ find($wantedFunction, $userInstalledAppPath);
+ for my $userInstalledAppBundle (@::userInstalledAppBundles) {
+ if (appIdentifierFromBundle($userInstalledAppBundle) eq $appIdentifier) {
+ return 1; # Has user installed app.
+ }
+ }
+ return 0; # Does not have user installed app.
+}
+
+sub isSimulatorDeviceBooted($)
+{
+ my ($simulatedDeviceUDID) = @_;
+ my $device = iosSimulatorDeviceByUDID($simulatedDeviceUDID);
+ return $device && $device->{state} eq SIMULATOR_DEVICE_STATE_BOOTED;
+}
+
+sub runIOSWebKitAppInSimulator($;$)
+{
+ my ($appBundle, $simulatorOptions) = @_;
+ my $productDir = productDir();
+ my $appDisplayName = appDisplayNameFromBundle($appBundle);
+ my $appIdentifier = appIdentifierFromBundle($appBundle);
+ my $simulatedDevice = findOrCreateSimulatorForIOSDevice(SIMULATOR_DEVICE_SUFFIX_FOR_WEBKIT_DEVELOPMENT);
+ my $simulatedDeviceUDID = $simulatedDevice->{UDID};
+
+ my $willUseSystemInstalledApp = isIOSSimulatorSystemInstalledApp($appBundle);
+ if ($willUseSystemInstalledApp) {
+ if (hasUserInstalledAppInSimulatorDevice($appIdentifier, $simulatedDeviceUDID)) {
+ # Restore the system-installed app in the simulator device corresponding to $appBundle as it
+ # was previously overwritten with a custom built version of the app.
+ # FIXME: Only restore the system-installed version of the app instead of erasing all contents and settings.
+ print "Quitting iOS Simulator...\n";
+ quitIOSSimulator($simulatedDeviceUDID);
+ print "Erasing contents and settings for simulator device \"$simulatedDevice->{name}\".\n";
+ exitStatus(system("xcrun", "--sdk", "iphonesimulator", "simctl", "erase", $simulatedDeviceUDID)) == 0 or die;
+ }
+ # FIXME: We assume that if $simulatedDeviceUDID is not booted then iOS Simulator is not open. However
+ # $simulatedDeviceUDID may have been booted using the simctl command line tool. If $simulatedDeviceUDID
+ # was booted using simctl then we should shutdown the device and launch iOS Simulator to boot it again.
+ if (!isSimulatorDeviceBooted($simulatedDeviceUDID)) {
+ print "Launching iOS Simulator...\n";
+ relaunchIOSSimulator($simulatedDevice);
+ }
+ } else {
+ # FIXME: We should killall(1) any running instances of $appBundle before installing it to ensure
+ # that simctl launch opens the latest installed version of the app. For now we quit and
+ # launch the iOS Simulator again to ensure there are no running instances of $appBundle.
+ print "Quitting and launching iOS Simulator...\n";
+ relaunchIOSSimulator($simulatedDevice);
+
+ print "Installing $appBundle.\n";
+ # Install custom built app, overwriting an app with the same app identifier if one exists.
+ exitStatus(system("xcrun", "--sdk", "iphonesimulator", "simctl", "install", $simulatedDeviceUDID, $appBundle)) == 0 or die;
+
+ }
+
+ $simulatorOptions = {} unless $simulatorOptions;
+
+ my %simulatorENV;
+ %simulatorENV = %{$simulatorOptions->{applicationEnvironment}} if $simulatorOptions->{applicationEnvironment};
+ {
+ local %ENV; # Shadow global-scope %ENV so that changes to it will not be seen outside of this scope.
+ setupIOSWebKitEnvironment($productDir);
+ %simulatorENV = %ENV;
+ }
+ my $applicationArguments = \@ARGV;
+ $applicationArguments = $simulatorOptions->{applicationArguments} if $simulatorOptions && $simulatorOptions->{applicationArguments};
+
+ # Prefix the environment variables with SIMCTL_CHILD_ per `xcrun simctl help launch`.
+ foreach my $key (keys %simulatorENV) {
+ $ENV{"SIMCTL_CHILD_$key"} = $simulatorENV{$key};
+ }
+
+ print "Starting $appDisplayName with DYLD_FRAMEWORK_PATH set to point to built WebKit in $productDir.\n";
+ return exitStatus(system("xcrun", "--sdk", "iphonesimulator", "simctl", "launch", $simulatedDeviceUDID, $appIdentifier, @$applicationArguments));
+}
+
+sub runIOSWebKitApp($)
+{
+ my ($appBundle) = @_;
+ if (willUseIOSDeviceSDK()) {
+ die "Only running Safari in iOS Simulator is supported now.";
+ }
+ if (willUseIOSSimulatorSDK()) {
+ return runIOSWebKitAppInSimulator($appBundle);
+ }
+ die "Not using an iOS SDK."
+}
+
+sub runMacWebKitApp($;$)
+{
+ my ($appPath, $useOpenCommand) = @_;
+ my $productDir = productDir();
+ print "Starting @{[basename($appPath)]} with DYLD_FRAMEWORK_PATH set to point to built WebKit in $productDir.\n";
+
+ local %ENV = %ENV;
+ setupMacWebKitEnvironment($productDir);
+
+ if (defined($useOpenCommand) && $useOpenCommand == USE_OPEN_COMMAND) {
+ return system("open", "-W", "-a", $appPath, "--args", argumentsForRunAndDebugMacWebKitApp());
+ }
+ if (architecture()) {
+ return system "arch", "-" . architecture(), $appPath, argumentsForRunAndDebugMacWebKitApp();
+ }
+ return system { $appPath } $appPath, argumentsForRunAndDebugMacWebKitApp();
+}
+
+sub execMacWebKitAppForDebugging($)
+{
+ my ($appPath) = @_;
+ my $architectureSwitch;
+ my $argumentsSeparator;
+
+ if (debugger() eq "lldb") {
+ $architectureSwitch = "--arch";
+ $argumentsSeparator = "--";
+ } elsif (debugger() eq "gdb") {
+ $architectureSwitch = "-arch";
+ $argumentsSeparator = "--args";
+ } else {
+ die "Unknown debugger $debugger.\n";
+ }
+
+ my $debuggerPath = `xcrun -find $debugger`;
+ chomp $debuggerPath;
+ die "Can't find the $debugger executable.\n" unless -x $debuggerPath;
+
+ my $productDir = productDir();
+ setupMacWebKitEnvironment($productDir);
+
+ my @architectureFlags = ($architectureSwitch, architecture());
+ print "Starting @{[basename($appPath)]} under $debugger with DYLD_FRAMEWORK_PATH set to point to built WebKit in $productDir.\n";
+ exec { $debuggerPath } $debuggerPath, @architectureFlags, $argumentsSeparator, $appPath, argumentsForRunAndDebugMacWebKitApp() or die;
+}
+
+sub debugSafari
+{
+ if (isAppleMacWebKit()) {
+ checkFrameworks();
+ execMacWebKitAppForDebugging(safariPath());
+ }
+
+ return 1; # Unsupported platform; can't debug Safari on this platform.
+}
+
+sub runSafari
+{
+ if (isIOSWebKit()) {
+ return runIOSWebKitApp(mobileSafariBundle());
+ }
+
+ if (isAppleMacWebKit()) {
+ return runMacWebKitApp(safariPath());
+ }
+
+ if (isAppleWinWebKit()) {
+ my $result;
+ my $webKitLauncherPath = File::Spec->catfile(executableProductDir(), "MiniBrowser.exe");
+ return system { $webKitLauncherPath } $webKitLauncherPath, @ARGV;
+ }
+
+ return 1; # Unsupported platform; can't run Safari on this platform.
+}
+
+sub runMiniBrowser
+{
+ if (isAppleMacWebKit()) {
+ return runMacWebKitApp(File::Spec->catfile(productDir(), "MiniBrowser.app", "Contents", "MacOS", "MiniBrowser"));
+ } elsif (isAppleWinWebKit()) {
+ my $result;
+ my $webKitLauncherPath = File::Spec->catfile(executableProductDir(), "MiniBrowser.exe");
+ return system { $webKitLauncherPath } $webKitLauncherPath, @ARGV;
+ }
+
+ return 1;
+}
+
+sub debugMiniBrowser
+{
+ if (isAppleMacWebKit()) {
+ execMacWebKitAppForDebugging(File::Spec->catfile(productDir(), "MiniBrowser.app", "Contents", "MacOS", "MiniBrowser"));
+ }
+
+ return 1;
+}
+
+sub runWebKitTestRunner
+{
+ if (isAppleMacWebKit()) {
+ return runMacWebKitApp(File::Spec->catfile(productDir(), "WebKitTestRunner"));
+ }
+
+ return 1;
+}
+
+sub debugWebKitTestRunner
+{
+ if (isAppleMacWebKit()) {
+ execMacWebKitAppForDebugging(File::Spec->catfile(productDir(), "WebKitTestRunner"));
+ }
+
+ return 1;
+}
+
+sub readRegistryString
+{
+ my ($valueName) = @_;
+ chomp(my $string = `regtool --wow32 get "$valueName"`);
+ return $string;
+}
+
+sub writeRegistryString
+{
+ my ($valueName, $string) = @_;
+
+ my $error = system "regtool", "--wow32", "set", "-s", $valueName, $string;
+
+ # On Windows Vista/7 with UAC enabled, regtool will fail to modify the registry, but will still
+ # return a successful exit code. So we double-check here that the value we tried to write to the
+ # registry was really written.
+ return !$error && readRegistryString($valueName) eq $string;
+}
+
+sub formatBuildTime($)
+{
+ my ($buildTime) = @_;
+
+ my $buildHours = int($buildTime / 3600);
+ my $buildMins = int(($buildTime - $buildHours * 3600) / 60);
+ my $buildSecs = $buildTime - $buildHours * 3600 - $buildMins * 60;
+
+ if ($buildHours) {
+ return sprintf("%dh:%02dm:%02ds", $buildHours, $buildMins, $buildSecs);
+ }
+ return sprintf("%02dm:%02ds", $buildMins, $buildSecs);
+}
+
+sub runSvnUpdateAndResolveChangeLogs(@)
+{
+ my @svnOptions = @_;
+ my $openCommand = "svn update " . join(" ", @svnOptions);
+ open my $update, "$openCommand |" or die "cannot execute command $openCommand";
+ my @conflictedChangeLogs;
+ while (my $line = <$update>) {
+ print $line;
+ $line =~ m/^C\s+(.+?)[\r\n]*$/;
+ if ($1) {
+ my $filename = normalizePath($1);
+ push @conflictedChangeLogs, $filename if basename($filename) eq "ChangeLog";
+ }
+ }
+ close $update or die;
+
+ if (@conflictedChangeLogs) {
+ print "Attempting to merge conflicted ChangeLogs.\n";
+ my $resolveChangeLogsPath = File::Spec->catfile(sourceDir(), "Tools", "Scripts", "resolve-ChangeLogs");
+ (system($resolveChangeLogsPath, "--no-warnings", @conflictedChangeLogs) == 0)
+ or die "Could not open resolve-ChangeLogs script: $!.\n";
+ }
+}
+
+sub runGitUpdate()
+{
+ # Doing a git fetch first allows setups with svn-remote.svn.fetch = trunk:refs/remotes/origin/master
+ # to perform the rebase much much faster.
+ system("git", "fetch");
+ if (isGitSVNDirectory(".")) {
+ system("git", "svn", "rebase") == 0 or die;
+ } else {
+ # This will die if branch.$BRANCHNAME.merge isn't set, which is
+ # almost certainly what we want.
+ system("git", "pull") == 0 or die;
+ }
+}
+
+1;
diff --git a/Tools/TestWebKitAPI/CMakeLists.txt b/Tools/TestWebKitAPI/CMakeLists.txt
new file mode 100644
index 000000000..c505fa25b
--- /dev/null
+++ b/Tools/TestWebKitAPI/CMakeLists.txt
@@ -0,0 +1,228 @@
+set(TESTWEBKITAPI_DIR "${TOOLS_DIR}/TestWebKitAPI")
+set(test_wtf_LIBRARIES
+ WTF${DEBUG_SUFFIX}
+ gtest
+)
+
+set(test_webcore_LIBRARIES
+ WTF${DEBUG_SUFFIX}
+ WebCore${DEBUG_SUFFIX}
+ gtest
+)
+
+set(TestWebKitAPI_LIBRARIES
+ WTF${DEBUG_SUFFIX}
+)
+
+if (ENABLE_WEBKIT2)
+ set(test_webkit2_api_LIBRARIES
+ JavaScriptCore
+ TestWebKitAPIBase
+ WTF
+ WebKit2
+ gtest
+ )
+ list(APPEND TestWebKitAPI_LIBRARIES
+ WebKit2
+ )
+else ()
+ list(APPEND TestWebKitAPI_LIBRARIES
+ WebKit${DEBUG_SUFFIX}
+ )
+endif ()
+
+
+set(TestJavaScriptCore_LIBRARIES
+ JavaScriptCore
+ gtest
+)
+
+set(TestWTF_SOURCES
+ ${TESTWEBKITAPI_DIR}/Counters.cpp
+ ${TESTWEBKITAPI_DIR}/TestsController.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/AtomicString.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/CString.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/Condition.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/CheckedArithmeticOperations.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/DateMath.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/Deque.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/Functional.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/HashCountedSet.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/HashMap.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/HashSet.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/IntegerToStringConversion.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/ListHashSet.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/Lock.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/MD5.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/MathExtras.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/MediaTime.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/MetaAllocator.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/NakedPtr.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/OptionSet.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/ParkingLot.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/RedBlackTree.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/Ref.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/RefPtr.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/SHA1.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/SaturatedArithmeticOperations.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/StringBuilder.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/StringHasher.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/StringImpl.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/StringOperators.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/StringView.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/TemporaryChange.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/Vector.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/WTFString.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/WorkQueue.cpp
+)
+
+WEBKIT_INCLUDE_CONFIG_FILES_IF_EXISTS()
+
+include_directories(
+ ${TESTWEBKITAPI_DIR}
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_SOURCE_DIR}/Source
+ ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}
+ ${DERIVED_SOURCES_WEBCORE_DIR}
+ ${JAVASCRIPTCORE_DIR}
+ ${JAVASCRIPTCORE_DIR}/API
+ ${JAVASCRIPTCORE_DIR}/ForwardingHeaders
+ ${THIRDPARTY_DIR}/gtest/include
+ ${WEBCORE_DIR}/css
+ ${WEBCORE_DIR}/dom
+ ${WEBCORE_DIR}/editing
+ ${WEBCORE_DIR}/loader/cache
+ ${WEBCORE_DIR}/platform
+ ${WEBCORE_DIR}/platform/animation
+ ${WEBCORE_DIR}/platform/graphics
+ ${WEBCORE_DIR}/platform/text
+ ${WEBCORE_DIR}/platform/network
+ ${WEBCORE_DIR}/platform/network/soup
+ ${WEBCORE_DIR}/rendering/style
+ ${WEBKIT2_DIR}/Platform/IPC
+ ${WEBKIT2_DIR}/Shared
+ ${WEBKIT2_DIR}/Shared/API
+ ${WEBKIT2_DIR}/Shared/API/c
+ ${WEBKIT2_DIR}/Shared/Plugins
+ ${WEBKIT2_DIR}/UIProcess
+ ${WEBKIT2_DIR}/UIProcess/API
+ ${WEBKIT2_DIR}/WebProcess/InjectedBundle
+ ${WEBKIT2_DIR}/WebProcess/InjectedBundle/API/c
+ ${WTF_DIR}
+)
+
+if (ENABLE_WEBKIT2)
+ add_library(TestWebKitAPIInjectedBundle SHARED
+ ${bundle_harness_SOURCES}
+ ${TESTWEBKITAPI_DIR}/InjectedBundleController.cpp
+ ${TESTWEBKITAPI_DIR}/InjectedBundleMain.cpp
+ ${TESTWEBKITAPI_DIR}/PlatformUtilities.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/CanHandleRequest_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/DidAssociateFormControls_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/DOMWindowExtensionBasic_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/DOMWindowExtensionNoCache_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/DocumentStartUserScriptAlertCrash_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/HitTestResultNodeHandle_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/InjectedBundleBasic_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/InjectedBundleFrameHitTest_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/LoadCanceledNoServerRedirectCallback_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/MouseMoveAfterCrash_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/ParentFrame_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/ResponsivenessTimerDoesntFireEarly_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/ShouldGoToBackForwardListItem_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/TextFieldDidBeginAndEndEditing_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/UserMessage_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/WillLoad_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/WillSendSubmitEvent_Bundle.cpp
+ )
+
+ target_link_libraries(TestWebKitAPIInjectedBundle ${TestWebKitAPI_LIBRARIES})
+ add_dependencies(TestWebKitAPIInjectedBundle WTF ${ForwardingHeadersForTestWebKitAPI_NAME})
+
+ get_property(TestWebKitAPIInjectedBundle_PATH TARGET TestWebKitAPIInjectedBundle PROPERTY LOCATION)
+endif ()
+
+if (WIN32)
+ add_definitions(-DGTEST_LINKED_AS_SHARED_LIBRARY=0)
+else ()
+ add_definitions(-DGTEST_LINKED_AS_SHARED_LIBRARY=1)
+endif ()
+
+add_definitions(-DGTEST_HAS_RTTI=0
+ -DTEST_WEBKIT2_RESOURCES_DIR=\"${TESTWEBKITAPI_DIR}/Tests/WebKit2\"
+ -DTEST_INJECTED_BUNDLE_PATH=\"${TestWebKitAPIInjectedBundle_PATH}\"
+)
+
+# FIXME: This works around compatibility problems in the old version of the third-pary
+# googletest source code checkout. It should be removed once we upgrade to a newer version.
+if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+ add_definitions(-DGTEST_HAS_TR1_TUPLE=0)
+endif ()
+
+add_executable(TestWTF
+ ${test_main_SOURCES}
+ ${TestWTF_SOURCES}
+)
+
+if (WIN32)
+ add_dependencies(TestWTF TestWTFLib)
+endif ()
+
+target_link_libraries(TestWTF ${test_wtf_LIBRARIES})
+add_dependencies(TestWTF WTF ${ForwardingHeadersForTestWebKitAPI_NAME} ${ForwardingNetworkHeadersForTestWebKitAPI_NAME})
+add_test(TestWTF ${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY_WTF}/TestWTF)
+set_tests_properties(TestWTF PROPERTIES TIMEOUT 60)
+set_target_properties(TestWTF PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY ${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY_WTF}
+)
+
+# FIXME: EFL is the only port that separates the WebCore binaries. Each port ought to do closer to the same thing.
+foreach (testName ${test_webcore_BINARIES})
+ add_executable(${testName} ${test_main_SOURCES} ${TESTWEBKITAPI_DIR}/TestsController.cpp ${TESTWEBKITAPI_DIR}/Tests/WebCore/${testName}.cpp)
+ add_test(${testName} ${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY}/WebCore/${testName})
+ set_tests_properties(${testName} PROPERTIES TIMEOUT 60)
+ target_link_libraries(${testName} ${test_webcore_LIBRARIES})
+ set_target_properties(${testName} PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY ${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY}/WebCore
+ )
+endforeach ()
+
+if (ENABLE_WEBKIT2)
+ add_library(TestWebKitAPIBase
+ ${test_main_SOURCES}
+ ${webkit2_api_harness_SOURCES}
+ ${TESTWEBKITAPI_DIR}/JavaScriptTest.cpp
+ ${TESTWEBKITAPI_DIR}/PlatformUtilities.cpp
+ ${TESTWEBKITAPI_DIR}/TestsController.cpp
+ )
+
+ add_dependencies(TestWebKitAPIBase WebKit2 ${ForwardingHeadersForTestWebKitAPI_NAME} ${ForwardingNetworkHeadersForTestWebKitAPI_NAME})
+
+ foreach (testName ${test_webkit2_api_BINARIES})
+ get_filename_component(testBaseName ${testName} NAME)
+ add_executable(${testBaseName} ${TESTWEBKITAPI_DIR}/Tests/WebKit2/${testName}.cpp)
+ add_test(${testBaseName} ${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY}/WebKit2/${testBaseName})
+ set_tests_properties(${testBaseName} PROPERTIES TIMEOUT 60)
+ target_link_libraries(${testBaseName} ${test_webkit2_api_LIBRARIES})
+ set_target_properties(${testBaseName} PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY ${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY}/WebKit2
+ )
+ endforeach ()
+
+ # We don't run tests that are expected to fail. We could use the WILL_FAIL
+ # property, but it reports failure when the test crashes or timeouts and would
+ # make the bot red.
+ foreach (testName ${test_webkit2_api_fail_BINARIES})
+ add_executable(${testName} ${TESTWEBKITAPI_DIR}/Tests/WebKit2/${testName}.cpp)
+ target_link_libraries(${testName} ${test_webkit2_api_LIBRARIES})
+ set_target_properties(${testName} PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY ${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY}/WebKit2/failure
+ )
+ endforeach ()
+endif ()
diff --git a/Tools/TestWebKitAPI/Configurations/TestWebKitAPICFLite.vsprops b/Tools/TestWebKitAPI/Configurations/TestWebKitAPICFLite.vsprops
new file mode 100644
index 000000000..61b661413
--- /dev/null
+++ b/Tools/TestWebKitAPI/Configurations/TestWebKitAPICFLite.vsprops
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="TestWebKitAPICFLite"
+ >
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="CFLite$(LibraryConfigSuffix).lib"
+ />
+</VisualStudioPropertySheet>
diff --git a/Tools/TestWebKitAPI/Configurations/TestWebKitAPICFNetwork.vsprops b/Tools/TestWebKitAPI/Configurations/TestWebKitAPICFNetwork.vsprops
new file mode 100644
index 000000000..cc25b8669
--- /dev/null
+++ b/Tools/TestWebKitAPI/Configurations/TestWebKitAPICFNetwork.vsprops
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="TestWebKitAPICFNetwork"
+ >
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="CFNetwork$(LibraryConfigSuffix).lib"
+ />
+</VisualStudioPropertySheet>
diff --git a/Tools/TestWebKitAPI/Configurations/TestWebKitAPICommon.vsprops b/Tools/TestWebKitAPI/Configurations/TestWebKitAPICommon.vsprops
new file mode 100644
index 000000000..57ec3506e
--- /dev/null
+++ b/Tools/TestWebKitAPI/Configurations/TestWebKitAPICommon.vsprops
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="TestWebKitAPICommon"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="&quot;$(ProjectDir)&quot;;&quot;$(ProjectDir)\..&quot;;&quot;$(ConfigurationBuildDir)\include&quot;;&quot;$(ConfigurationBuildDir)\include\private\JavaScriptCore&quot;;&quot;$(ConfigurationBuildDir)\include\WebCore\ForwardingHeaders&quot;;&quot;$(ConfigurationBuildDir)\include\private&quot;;&quot;$(WebKitLibrariesDir)\include&quot;;&quot;$(ProjectDir)\..\..\..\Source\ThirdParty\gtest\include&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="WebKit$(WebKitDLLConfigSuffix).lib JavaScriptCore$(WebKitDLLConfigSuffix).lib gtest.lib"
+ SubSystem="1"
+ />
+</VisualStudioPropertySheet>
diff --git a/Tools/TestWebKitAPI/Configurations/TestWebKitAPICoreFoundation.vsprops b/Tools/TestWebKitAPI/Configurations/TestWebKitAPICoreFoundation.vsprops
new file mode 100644
index 000000000..ee139c0bc
--- /dev/null
+++ b/Tools/TestWebKitAPI/Configurations/TestWebKitAPICoreFoundation.vsprops
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="TestWebKitAPICoreFoundation"
+ >
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="CoreFoundation$(LibraryConfigSuffix).lib"
+ />
+</VisualStudioPropertySheet>
diff --git a/Tools/TestWebKitAPI/Configurations/TestWebKitAPIDebug.vsprops b/Tools/TestWebKitAPI/Configurations/TestWebKitAPIDebug.vsprops
new file mode 100644
index 000000000..981225f35
--- /dev/null
+++ b/Tools/TestWebKitAPI/Configurations/TestWebKitAPIDebug.vsprops
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="TestWebKitAPIDebug"
+ InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;.\TestWebKitAPICommon.vsprops;.\TestWebKitAPICoreFoundation.vsprops;.\TestWebKitAPICFNetwork.vsprops"
+ >
+</VisualStudioPropertySheet>
diff --git a/Tools/TestWebKitAPI/Configurations/TestWebKitAPIDebugAll.vsprops b/Tools/TestWebKitAPI/Configurations/TestWebKitAPIDebugAll.vsprops
new file mode 100644
index 000000000..f70863b49
--- /dev/null
+++ b/Tools/TestWebKitAPI/Configurations/TestWebKitAPIDebugAll.vsprops
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="TestWebKitAPIDebugAll"
+ InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\debug_all.vsprops;.\TestWebKitAPICommon.vsprops;.\TestWebKitAPICoreFoundation.vsprops;.\TestWebKitAPICFNetwork.vsprops"
+ >
+</VisualStudioPropertySheet>
diff --git a/Tools/TestWebKitAPI/Configurations/TestWebKitAPIDebugCairoCFLite.vsprops b/Tools/TestWebKitAPI/Configurations/TestWebKitAPIDebugCairoCFLite.vsprops
new file mode 100644
index 000000000..ba38ece12
--- /dev/null
+++ b/Tools/TestWebKitAPI/Configurations/TestWebKitAPIDebugCairoCFLite.vsprops
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="TestWebKitAPIDebugCairoCFLite"
+ InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\debug_wincairo.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\WinCairo.vsprops;..\Configurations\TestWebKitAPICommon.vsprops;..\Configurations\TestWebKitAPICFLite.vsprops"
+ >
+</VisualStudioPropertySheet>
diff --git a/Tools/TestWebKitAPI/Configurations/TestWebKitAPIInjectedBundleCommon.vsprops b/Tools/TestWebKitAPI/Configurations/TestWebKitAPIInjectedBundleCommon.vsprops
new file mode 100644
index 000000000..5e19c4621
--- /dev/null
+++ b/Tools/TestWebKitAPI/Configurations/TestWebKitAPIInjectedBundleCommon.vsprops
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="TestWebKitAPIInjectedBundleCommon"
+ >
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)\$(ProjectName)$(WebKitDLLConfigSuffix).dll"
+ />
+</VisualStudioPropertySheet>
diff --git a/Tools/TestWebKitAPI/Configurations/TestWebKitAPIRelease.vsprops b/Tools/TestWebKitAPI/Configurations/TestWebKitAPIRelease.vsprops
new file mode 100644
index 000000000..e5edd81d8
--- /dev/null
+++ b/Tools/TestWebKitAPI/Configurations/TestWebKitAPIRelease.vsprops
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="TestWebKitAPIRelease"
+ InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\releaseproduction.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;.\TestWebKitAPICommon.vsprops;.\TestWebKitAPICoreFoundation.vsprops;.\TestWebKitAPICFNetwork.vsprops"
+ >
+</VisualStudioPropertySheet>
diff --git a/Tools/TestWebKitAPI/Configurations/TestWebKitAPIReleaseCairoCFLite.vsprops b/Tools/TestWebKitAPI/Configurations/TestWebKitAPIReleaseCairoCFLite.vsprops
new file mode 100644
index 000000000..1b97b644d
--- /dev/null
+++ b/Tools/TestWebKitAPI/Configurations/TestWebKitAPIReleaseCairoCFLite.vsprops
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="TestWebKitAPIReleaseCairoCFLite"
+ InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\releaseproduction.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\WebKitLibraries\win\tools\vsprops\WinCairo.vsprops;..\Configurations\TestWebKitAPICommon.vsprops;..\Configurations\TestWebKitAPICFLite.vsprops"
+ >
+</VisualStudioPropertySheet>
diff --git a/Tools/TestWebKitAPI/Counters.cpp b/Tools/TestWebKitAPI/Counters.cpp
new file mode 100644
index 000000000..87aa4bba2
--- /dev/null
+++ b/Tools/TestWebKitAPI/Counters.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Counters.h"
+
+unsigned CopyMoveCounter::constructionCount = 0;
+unsigned CopyMoveCounter::copyCount = 0;
+unsigned CopyMoveCounter::moveCount = 0;
+
+unsigned ConstructorDestructorCounter::constructionCount = 0;
+unsigned ConstructorDestructorCounter::destructionCount = 0;
diff --git a/Tools/TestWebKitAPI/Counters.h b/Tools/TestWebKitAPI/Counters.h
new file mode 100644
index 000000000..1cfd7b71d
--- /dev/null
+++ b/Tools/TestWebKitAPI/Counters.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Counters_h
+#define Counters_h
+
+struct CopyMoveCounter {
+ static unsigned constructionCount;
+ static unsigned copyCount;
+ static unsigned moveCount;
+
+ struct TestingScope {
+ TestingScope()
+ {
+ constructionCount = 0;
+ copyCount = 0;
+ moveCount = 0;
+ }
+ };
+
+ CopyMoveCounter() { constructionCount++; }
+ CopyMoveCounter(const CopyMoveCounter&) { copyCount++; }
+ CopyMoveCounter& operator=(const CopyMoveCounter&) { copyCount++; return *this; }
+ CopyMoveCounter(CopyMoveCounter&&) { moveCount++; }
+ CopyMoveCounter& operator=(CopyMoveCounter&&) { moveCount++; return *this; }
+};
+
+
+struct ConstructorDestructorCounter {
+ static unsigned constructionCount;
+ static unsigned destructionCount;
+
+ struct TestingScope {
+ TestingScope()
+ {
+ constructionCount = 0;
+ destructionCount = 0;
+ }
+ };
+
+ ConstructorDestructorCounter() { constructionCount++; }
+ ~ConstructorDestructorCounter() { destructionCount++; }
+};
+
+template<typename T>
+struct DeleterCounter {
+ static unsigned deleterCount;
+
+ struct TestingScope {
+ TestingScope()
+ {
+ deleterCount = 0;
+ }
+ };
+
+ void operator()(T* p) const
+ {
+ deleterCount++;
+ delete p;
+ }
+};
+
+template<class T> unsigned DeleterCounter<T>::deleterCount = 0;
+
+#endif // Counters_h
diff --git a/Tools/TestWebKitAPI/ForwardingHeaders/WebCore/LayoutUnit.h b/Tools/TestWebKitAPI/ForwardingHeaders/WebCore/LayoutUnit.h
new file mode 100644
index 000000000..de0a7454e
--- /dev/null
+++ b/Tools/TestWebKitAPI/ForwardingHeaders/WebCore/LayoutUnit.h
@@ -0,0 +1,4 @@
+#ifndef TestWebKitAPI_FWD_LayoutUnit_h
+#define TestWebKitAPI_FWD_LayoutUnit_h
+#include <LayoutUnit.h>
+#endif
diff --git a/Tools/TestWebKitAPI/GNUmakefile.am b/Tools/TestWebKitAPI/GNUmakefile.am
deleted file mode 100644
index 2ea61734d..000000000
--- a/Tools/TestWebKitAPI/GNUmakefile.am
+++ /dev/null
@@ -1,934 +0,0 @@
-noinst_LTLIBRARIES += \
- Libraries/libTestWebKitAPIMain.la
-
-if ENABLE_WEBKIT2
-noinst_LTLIBRARIES += \
- Libraries/libTestWebKit2GtkAPI.la
-endif
-
-Libraries_libTestWebKitAPIMain_la_SOURCES = \
- Tools/TestWebKitAPI/Test.h \
- Tools/TestWebKitAPI/TestsController.cpp \
- Tools/TestWebKitAPI/TestsController.h \
- Tools/TestWebKitAPI/gtk/main.cpp
-
-# Use -isystem gcc flag so that gcc considers gtest headers as system headers.
-# We need this to avoid a lot of compile warnings due to -Wundef.
-# See http://code.google.com/p/googletest/issues/detail?id=258
-Libraries_libTestWebKitAPIMain_la_CPPFLAGS = \
- -isystem $(srcdir)/Source/ThirdParty/gtest/include \
- -I$(srcdir)/Tools/TestWebKitAPI \
- -I$(srcdir)/Source/ThirdParty/gtest/include \
- -I$(top_builddir)/DerivedSources/WebCore/include \
- -I$(top_builddir)/DerivedSources/WebKit2/include \
- $(global_cppflags) \
- $(javascriptcore_cppflags) \
- $(GTK_CFLAGS)
-
-webkitgtk_tests_cflags = \
- -fno-strict-aliasing \
- -DTEST_PLUGIN_DIR=\"${shell pwd}/${top_builddir}/TestNetscapePlugin/.libs\" \
- -I$(srcdir)/Source/JavaScriptCore/ForwardingHeaders \
- -I$(WebKit) \
- -I$(GENSOURCES) \
- -I$(top_builddir)/Source/WebKit/gtk \
- -I$(top_srcdir)/Source/WebCore/bindings \
- -I$(top_srcdir)/Source/WebCore/bindings/gobject \
- $(global_cppflags) \
- $(global_cflags) \
- $(javascriptcore_cppflags) \
- $(FREETYPE_CFLAGS) \
- $(GLIB_CFLAGS) \
- $(GTK_CFLAGS) \
- $(LIBSOUP_CFLAGS) \
- $(XRENDER_CFLAGS) \
- $(XT_CFLAGS)
-
-webkitgtk_tests_ldadd = \
- libjavascriptcoregtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \
- libwebkitgtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \
- $(FREETYPE_LIBS) \
- $(GTK_LIBS) \
- $(GLIB_LIBS) \
- $(LIBSOUP_LIBS) \
- $(XRENDER_LIBS)
-
-webkitgtk_tests_ldflags = \
- -no-install
-
-
-webkit2gtk_tests_cppflags = \
- -DWEBKIT_EXEC_PATH=\"${shell pwd}/$(top_builddir)/Programs\" \
- -DWEBKIT_SRC_DIR=\"${shell pwd}/${srcdir}\" \
- -DWEBKIT_DERIVED_SRC_DIR=\"${shell pwd}/${top_builddir}/DerivedSources\" \
- -DWEBKIT_TEST_PLUGIN_DIR=\"${shell pwd}/${top_builddir}/TestNetscapePlugin/.libs\" \
- -DWEBKIT_TEST_WEB_EXTENSIONS_DIR=\"${shell pwd}/${top_builddir}/Libraries/WebExtensions/.libs\" \
- -DWEBKIT_INJECTED_BUNDLE_PATH=\"${shell pwd}/$(top_builddir)/.libs\" \
- $(javascriptcore_cppflags) \
- -I$(srcdir)/Source \
- -I$(srcdir)/Source/WebKit2 \
- -I$(srcdir)/Source/JavaScriptCore \
- -I$(srcdir)/Tools/TestWebKitAPI/gtk/WebKit2Gtk \
- -I$(top_builddir)/DerivedSources/WebKit2/include \
- -I$(top_builddir)/DerivedSources/WebKit2/webkit2gtk \
- -I$(top_builddir)/DerivedSources/WebKit2/webkit2gtk/include \
- -I$(srcdir)/Source/WebKit2/UIProcess/API/gtk \
- $(global_cppflags) \
- $(FREETYPE_CFLAGS) \
- $(GLIB_CFLAGS) \
- $(GTK_CFLAGS) \
- $(LIBSOUP_CFLAGS)
-
-webkit2gtk_tests_ldadd = \
- Libraries/libTestWebKit2GtkAPI.la \
- libjavascriptcoregtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \
- libwebkit2gtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \
- $(FREETYPE_LIBS) \
- $(GEOCLUE_LIBS) \
- $(GLIB_LIBS) \
- $(GTK_LIBS) \
- $(LIBSOUP_LIBS)
-
-webkit2gtk_tests_ldflags = \
- -no-install
-
-Libraries_libTestWebKit2GtkAPI_la_SOURCES = \
- Tools/TestWebKitAPI/gtk/WebKit2Gtk/LoadTrackingTest.cpp \
- Tools/TestWebKitAPI/gtk/WebKit2Gtk/LoadTrackingTest.h \
- Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.cpp \
- Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.h \
- Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestServer.cpp \
- Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestServer.h \
- Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.cpp \
- Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.h \
- Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.cpp \
- Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.h
-
-Libraries_libTestWebKit2GtkAPI_la_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-
-
-noinst_PROGRAMS += \
- Programs/TestWebKitAPI/WTF/TestWTF \
- Programs/TestWebKitAPI/JavaScriptCore/TestJavaScriptCore \
- Programs/TestWebKitAPI/WebCore/TestWebCore
-
-if ENABLE_WEBKIT1
-noinst_PROGRAMS += \
- Programs/TestWebKitAPI/WebKitGtk/testapplicationcache \
- Programs/TestWebKitAPI/WebKitGtk/testcontextmenu \
- Programs/TestWebKitAPI/WebKitGtk/testdomdocument \
- Programs/TestWebKitAPI/WebKitGtk/testdomdomwindow \
- Programs/TestWebKitAPI/WebKitGtk/testdomnode \
- Programs/TestWebKitAPI/WebKitGtk/testhttpbackend \
- Programs/TestWebKitAPI/WebKitGtk/testfavicondatabase \
- Programs/TestWebKitAPI/WebKitGtk/testloading \
- Programs/TestWebKitAPI/WebKitGtk/testglobals \
- Programs/TestWebKitAPI/WebKitGtk/testmimehandling \
- Programs/TestWebKitAPI/WebKitGtk/testnetworkrequest \
- Programs/TestWebKitAPI/WebKitGtk/testnetworkresponse \
- Programs/TestWebKitAPI/WebKitGtk/testwebframe \
- Programs/TestWebKitAPI/WebKitGtk/testwebbackforwardlist \
- Programs/TestWebKitAPI/WebKitGtk/testwebhistoryitem \
- Programs/TestWebKitAPI/WebKitGtk/testwindow \
- Programs/TestWebKitAPI/WebKitGtk/testdownload \
- Programs/TestWebKitAPI/WebKitGtk/testatk \
- Programs/TestWebKitAPI/WebKitGtk/testatkroles \
- Programs/TestWebKitAPI/WebKitGtk/testhittestresult \
- Programs/TestWebKitAPI/WebKitGtk/testwebinspector \
- Programs/TestWebKitAPI/WebKitGtk/testwebsettings \
- Programs/TestWebKitAPI/WebKitGtk/testwebresource \
- Programs/TestWebKitAPI/WebKitGtk/testwebdatasource \
- Programs/TestWebKitAPI/WebKitGtk/testwebplugindatabase \
- Programs/TestWebKitAPI/WebKitGtk/testwebview \
- Programs/TestWebKitAPI/WebKitGtk/testkeyevents \
- Programs/TestWebKitAPI/WebKitGtk/testcopyandpaste
-endif
-
-if ENABLE_WEBKIT2
-noinst_PROGRAMS += \
- Programs/TestWebKitAPI/WebKit2/TestWebKit2 \
- Programs/TestWebKitAPI/WebKit2Gtk/InspectorTestServer \
- Programs/TestWebKitAPI/WebKit2Gtk/TestAuthentication \
- Programs/TestWebKitAPI/WebKit2Gtk/TestBackForwardList \
- Programs/TestWebKitAPI/WebKit2Gtk/TestContextMenu \
- Programs/TestWebKitAPI/WebKit2Gtk/TestCookieManager \
- Programs/TestWebKitAPI/WebKit2Gtk/TestDOMNode \
- Programs/TestWebKitAPI/WebKit2Gtk/TestDownloads \
- Programs/TestWebKitAPI/WebKit2Gtk/TestFrame \
- Programs/TestWebKitAPI/WebKit2Gtk/TestInspector \
- Programs/TestWebKitAPI/WebKit2Gtk/TestInspectorServer \
- Programs/TestWebKitAPI/WebKit2Gtk/TestLoaderClient \
- Programs/TestWebKitAPI/WebKit2Gtk/TestMultiprocess \
- Programs/TestWebKitAPI/WebKit2Gtk/TestPrinting \
- Programs/TestWebKitAPI/WebKit2Gtk/TestResources \
- Programs/TestWebKitAPI/WebKit2Gtk/TestSSL \
- Programs/TestWebKitAPI/WebKit2Gtk/TestUIClient \
- Programs/TestWebKitAPI/WebKit2Gtk/TestWebExtensions \
- Programs/TestWebKitAPI/WebKit2Gtk/TestWebKitVersion \
- Programs/TestWebKitAPI/WebKit2Gtk/TestWebKitFaviconDatabase \
- Programs/TestWebKitAPI/WebKit2Gtk/TestWebKitFindController \
- Programs/TestWebKitAPI/WebKit2Gtk/TestWebKitPolicyClient \
- Programs/TestWebKitAPI/WebKit2Gtk/TestWebKitSettings \
- Programs/TestWebKitAPI/WebKit2Gtk/TestWebKitWebContext \
- Programs/TestWebKitAPI/WebKit2Gtk/TestWebKitWebView \
- Programs/TestWebKitAPI/WebKit2Gtk/TestWebKitWebViewGroup \
- Programs/TestWebKitAPI/WebKit2Gtk/TestWebViewEditor
-
-if HAVE_ATSPI2
-noinst_PROGRAMS += \
- Programs/TestWebKitAPI/WebKit2Gtk/AccessibilityTestServer \
- Programs/TestWebKitAPI/WebKit2Gtk/TestWebKitAccessibility
-endif
-endif # ENABLE_WEBKIT2
-
-Programs_TestWebKitAPI_WTF_TestWTF_CPPFLAGS = \
- $(Libraries_libTestWebKitAPIMain_la_CPPFLAGS) \
- $(GLIB_LIBS) \
- $(CAIRO_CFLAGS)
-
-Programs_TestWebKitAPI_WTF_TestWTF_CXXFLAGS = \
- -DGTEST_HAS_RTTI=0 \
- $(global_cxxflags)
-
-Programs_TestWebKitAPI_WTF_TestWTF_LDADD = \
- Libraries/libTestWebKitAPIMain.la \
- Libraries/libgtest.la \
- libWTF.la \
- $(GTK_LIBS) \
- $(GLIB_LIBS)
-
-Programs_TestWebKitAPI_WTF_TestWTF_LDFLAGS = \
- -no-install
-
-Programs_TestWebKitAPI_WTF_TestWTF_SOURCES = \
- Tools/TestWebKitAPI/Tests/WTF/AtomicString.cpp \
- Tools/TestWebKitAPI/Tests/WTF/CString.cpp \
- Tools/TestWebKitAPI/Tests/WTF/CheckedArithmeticOperations.cpp \
- Tools/TestWebKitAPI/Tests/WTF/Functional.cpp \
- Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp \
- Tools/TestWebKitAPI/Tests/WTF/HashSet.cpp \
- Tools/TestWebKitAPI/Tests/WTF/IntegerToStringConversion.cpp \
- Tools/TestWebKitAPI/Tests/WTF/ListHashSet.cpp \
- Tools/TestWebKitAPI/Tests/WTF/MD5.cpp \
- Tools/TestWebKitAPI/Tests/WTF/MathExtras.cpp \
- Tools/TestWebKitAPI/Tests/WTF/MediaTime.cpp \
- Tools/TestWebKitAPI/Tests/WTF/MetaAllocator.cpp \
- Tools/TestWebKitAPI/Tests/WTF/MoveOnly.h \
- Tools/TestWebKitAPI/Tests/WTF/RedBlackTree.cpp \
- Tools/TestWebKitAPI/Tests/WTF/Ref.cpp \
- Tools/TestWebKitAPI/Tests/WTF/RefLogger.h \
- Tools/TestWebKitAPI/Tests/WTF/RefPtr.cpp \
- Tools/TestWebKitAPI/Tests/WTF/SHA1.cpp \
- Tools/TestWebKitAPI/Tests/WTF/SaturatedArithmeticOperations.cpp \
- Tools/TestWebKitAPI/Tests/WTF/StringBuilder.cpp \
- Tools/TestWebKitAPI/Tests/WTF/StringHasher.cpp \
- Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp \
- Tools/TestWebKitAPI/Tests/WTF/StringOperators.cpp \
- Tools/TestWebKitAPI/Tests/WTF/TemporaryChange.cpp \
- Tools/TestWebKitAPI/Tests/WTF/Vector.cpp \
- Tools/TestWebKitAPI/Tests/WTF/gobject/GUniquePtr.cpp \
- Tools/TestWebKitAPI/WTFStringUtilities.h
-
-Programs_TestWebKitAPI_JavaScriptCore_TestJavaScriptCore_CPPFLAGS = \
- $(Libraries_libTestWebKitAPIMain_la_CPPFLAGS)
-
-Programs_TestWebKitAPI_JavaScriptCore_TestJavaScriptCore_CXXFLAGS = \
- -DGTEST_HAS_RTTI=0 \
- $(global_cxxflags)
-
-Programs_TestWebKitAPI_JavaScriptCore_TestJavaScriptCore_LDADD = \
- Libraries/libTestWebKitAPIMain.la \
- Libraries/libgtest.la \
- libWTF.la \
- $(GTK_LIBS)
-
-Programs_TestWebKitAPI_JavaScriptCore_TestJavaScriptCore_LDFLAGS = \
- -no-install
-
-Programs_TestWebKitAPI_JavaScriptCore_TestJavaScriptCore_SOURCES = \
- Tools/TestWebKitAPI/Tests/JavaScriptCore/VMInspector.cpp
-
-webcore_layer_deps = \
- libPlatform.la \
- libPlatformGtk.la \
- libWebCorePlatform.la \
- libWebCoreGtk.la \
- libWebCore.la \
- libWebCoreModules.la
-if ENABLE_SVG
-webcore_layer_deps += \
- libWebCoreSVG.la
-endif
-if ENABLE_INDEXED_DATABASE
-webcore_layer_deps += \
- libLevelDB.la
-endif
-if USE_OPENGL
-webcore_layer_deps += \
- libANGLE.la
-endif
-
-webcore_layer_archives = $(foreach lib, $(webcore_layer_deps), $(shell echo $(lib) | sed "s/\(.*\)\.la/.libs\/\1.a/"))
-
-libWebCoreLayer.a: $(webcore_layer_deps)
- $(AM_V_GEN)
- $(AM_V_at)$(shell rm -f $@)
- $(AM_V_at)$(shell find . -name "*.o" > objects_list)
- $(AM_V_at)$(foreach archive, $(webcore_layer_archives), $(shell $(AR) t $(archive) | xargs -n1 basename | xargs -I obj_file grep -F obj_file objects_list | xargs -n50 $(AR) $(AR_FLAGS) $@))
- $(AM_V_at)$(shell rm -f objects_list)
-
-DISTCLEANFILES += \
- $(top_builddir)/libWebCoreLayer.a
-
-Programs_TestWebKitAPI_WebCore_TestWebCore_CPPFLAGS = \
- $(Libraries_libTestWebKitAPIMain_la_CPPFLAGS) \
- $(platform_cppflags) \
- $(platformgtk_cppflags) \
- $(webcore_cppflags) \
- $(webcoregtk_cppflags) \
- $(LIBSOUP_CFLAGS)
-
-Programs_TestWebKitAPI_WebCore_TestWebCore_CXXFLAGS = \
- -DGTEST_HAS_RTTI=0 \
- $(global_cxxflags)
-
-Programs_TestWebKitAPI_WebCore_TestWebCore_LDADD = \
- Libraries/libTestWebKitAPIMain.la \
- Libraries/libgtest.la \
- libjavascriptcoregtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \
- libWTF.la \
- libWebCoreLayer.a \
- $(CAIRO_LIBS) \
- $(FREETYPE_LIBS) \
- $(GAMEPAD_LIBS) \
- $(GEOCLUE_LIBS) \
- $(GLIB_LIBS) \
- $(GSTREAMER_LIBS) \
- $(GTK_LIBS) \
- $(JPEG_LIBS) \
- $(LIBSECRET_LIBS) \
- $(LIBSOUP_LIBS) \
- $(LIBXML_LIBS) \
- $(OPENGL_LIBS) \
- $(PANGO_LIBS) \
- $(PNG_LIBS) \
- $(SQLITE3_LIBS) \
- $(UNICODE_LIBS) \
- $(WEBP_LIBS) \
- $(XRENDER_LIBS) \
- $(XT_LIBS) \
- $(ZLIB_LIBS)
-
-Programs_TestWebKitAPI_WebCore_TestWebCore_LDFLAGS = \
- -no-install
-
-Programs_TestWebKitAPI_WebCore_TestWebCore_SOURCES = \
- Source/WebCore/platform/graphics/IntPoint.cpp \
- Source/WebCore/platform/graphics/IntRect.cpp \
- Source/WebCore/platform/graphics/IntSize.cpp \
- Source/WebCore/platform/graphics/cairo/IntRectCairo.cpp \
- Source/WebCore/platform/graphics/gtk/IntRectGtk.cpp \
- Source/WebCore/platform/gtk/GtkInputMethodFilter.cpp \
- Tools/TestWebKitAPI/config.h \
- Tools/TestWebKitAPI/Tests/gtk/InputMethodFilter.cpp \
- Tools/TestWebKitAPI/Tests/WebCore/gtk/UserAgentQuirks.cpp \
- Tools/TestWebKitAPI/Tests/WebCore/URL.cpp \
- Tools/TestWebKitAPI/Tests/WebCore/LayoutUnit.cpp
-
-Programs_TestWebKitAPI_WebKitGtk_testapplicationcache_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testapplicationcache.c
-Programs_TestWebKitAPI_WebKitGtk_testapplicationcache_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testapplicationcache_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testapplicationcache_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testcontextmenu_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testcontextmenu.c
-Programs_TestWebKitAPI_WebKitGtk_testcontextmenu_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testcontextmenu_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testcontextmenu_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testdomdocument_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testdomdocument.c
-Programs_TestWebKitAPI_WebKitGtk_testdomdocument_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testdomdocument_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testdomdocument_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testdomdomwindow_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testdomdomwindow.c
-Programs_TestWebKitAPI_WebKitGtk_testdomdomwindow_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testdomdomwindow_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testdomdomwindow_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testdomnode_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testdomnode.c
-Programs_TestWebKitAPI_WebKitGtk_testdomnode_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testdomnode_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testdomnode_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testhttpbackend_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testhttpbackend.c
-Programs_TestWebKitAPI_WebKitGtk_testhttpbackend_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testhttpbackend_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testhttpbackend_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testfavicondatabase_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testfavicondatabase.c \
- Tools/TestWebKitAPI/Tests/WebKitGtk/test_utils.c
-Programs_TestWebKitAPI_WebKitGtk_testfavicondatabase_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testfavicondatabase_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testfavicondatabase_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testglobals_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testglobals.c
-Programs_TestWebKitAPI_WebKitGtk_testglobals_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testglobals_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testglobals_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testloading_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testloading.c
-Programs_TestWebKitAPI_WebKitGtk_testloading_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testloading_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testloading_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testmimehandling_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testmimehandling.c \
- Tools/TestWebKitAPI/Tests/WebKitGtk/test_utils.c
-Programs_TestWebKitAPI_WebKitGtk_testmimehandling_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testmimehandling_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testmimehandling_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testnetworkrequest_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testnetworkrequest.c
-Programs_TestWebKitAPI_WebKitGtk_testnetworkrequest_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testnetworkrequest_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testnetworkrequest_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testnetworkresponse_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testnetworkresponse.c
-Programs_TestWebKitAPI_WebKitGtk_testnetworkresponse_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testnetworkresponse_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testnetworkresponse_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testwebframe_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testwebframe.c
-Programs_TestWebKitAPI_WebKitGtk_testwebframe_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testwebframe_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testwebframe_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testwebplugindatabase_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testwebplugindatabase.c
-Programs_TestWebKitAPI_WebKitGtk_testwebplugindatabase_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testwebplugindatabase_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testwebplugindatabase_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testwebbackforwardlist_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testwebbackforwardlist.c
-Programs_TestWebKitAPI_WebKitGtk_testwebbackforwardlist_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testwebbackforwardlist_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testwebbackforwardlist_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testwebhistoryitem_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testwebhistoryitem.c
-Programs_TestWebKitAPI_WebKitGtk_testwebhistoryitem_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testwebhistoryitem_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testwebhistoryitem_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testwindow_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testwindow.c
-Programs_TestWebKitAPI_WebKitGtk_testwindow_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testwindow_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testwindow_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testdownload_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testdownload.c
-Programs_TestWebKitAPI_WebKitGtk_testdownload_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testdownload_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testdownload_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testatk_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testatk.c
-Programs_TestWebKitAPI_WebKitGtk_testatk_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testatk_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testatk_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testatkroles_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testatkroles.c
-Programs_TestWebKitAPI_WebKitGtk_testatkroles_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testatkroles_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testatkroles_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testwebinspector_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testwebinspector.c \
- Tools/TestWebKitAPI/Tests/WebKitGtk/test_utils.c
-Programs_TestWebKitAPI_WebKitGtk_testwebinspector_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testwebinspector_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testwebinspector_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testwebsettings_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testwebsettings.c
-Programs_TestWebKitAPI_WebKitGtk_testwebsettings_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testwebsettings_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testwebsettings_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testwebresource_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testwebresource.c
-Programs_TestWebKitAPI_WebKitGtk_testwebresource_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testwebresource_LDADD = $(webkitgtk_tests_ldadd)
-
-Programs_TestWebKitAPI_WebKitGtk_testwebdatasource_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testwebdatasource.c
-Programs_TestWebKitAPI_WebKitGtk_testwebdatasource_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testwebdatasource_LDADD = $(webkitgtk_tests_ldadd)
-
-Programs_TestWebKitAPI_WebKitGtk_testwebview_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testwebview.c Tools/TestWebKitAPI/Tests/WebKitGtk/test_utils.c
-Programs_TestWebKitAPI_WebKitGtk_testwebview_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testwebview_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testwebview_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testhittestresult_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testhittestresult.c
-Programs_TestWebKitAPI_WebKitGtk_testhittestresult_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testhittestresult_LDADD = $(webkitgtk_tests_ldadd)
-
-Programs_TestWebKitAPI_WebKitGtk_testkeyevents_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testkeyevents.c
-Programs_TestWebKitAPI_WebKitGtk_testkeyevents_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testkeyevents_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testkeyevents_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testcopyandpaste_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testcopyandpaste.c \
- Source/WebCore/platform/gtk/GtkVersioning.c
-Programs_TestWebKitAPI_WebKitGtk_testcopyandpaste_CFLAGS = \
- $(webkitgtk_tests_cflags) \
- -I$(srcdir)/Source/WebCore/platform/gtk \
- -I$(srcdir)/Source/WebCore
-Programs_TestWebKitAPI_WebKitGtk_testcopyandpaste_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testcopyandpaste_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-
-Programs_TestWebKitAPI_WebKit2_TestWebKit2_CPPFLAGS = \
- $(Programs_TestWebKitAPI_WTF_TestWTF_CPPFLAGS) \
- -I$(top_builddir)/DerivedSources/WebKit2/include \
- $(FREETYPE_CFLAGS) \
- $(GLIB_CFLAGS) \
- $(GTK_CFLAGS) \
- $(LIBSOUP_CFLAGS)
-
-Programs_TestWebKitAPI_WebKit2_TestWebKit2_CXXFLAGS = \
- -DGTEST_HAS_RTTI=0 \
- $(global_cxxflags)
-
-Programs_TestWebKitAPI_WebKit2_TestWebKit2_LDADD = \
- Libraries/libTestWebKitAPIMain.la \
- Libraries/libgtest.la \
- libjavascriptcoregtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \
- libwebkit2gtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \
- $(FREETYPE_LIBS) \
- $(GLIB_LIBS) \
- $(GTK_LIBS) \
- $(LIBSOUP_LIBS)
-
-Programs_TestWebKitAPI_WebKit2_TestWebKit2_LDFLAGS = \
- $(Programs_TestWebKitAPI_WTF_TestWTF_LDFLAGS)
-
-Programs_TestWebKitAPI_WebKit2_TestWebKit2_SOURCES = \
- Tools/TestWebKitAPI/config.h \
- Tools/TestWebKitAPI/gtk/PlatformUtilitiesGtk.cpp \
- Tools/TestWebKitAPI/gtk/PlatformWebViewGtk.cpp \
- Tools/TestWebKitAPI/JavaScriptTest.cpp \
- Tools/TestWebKitAPI/JavaScriptTest.h \
- Tools/TestWebKitAPI/PlatformUtilities.cpp \
- Tools/TestWebKitAPI/PlatformUtilities.h \
- Tools/TestWebKitAPI/PlatformWebView.h \
- Tools/TestWebKitAPI/Tests/WebKit2/AboutBlankLoad.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/CanHandleRequest.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/CloseThenTerminate.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/CookieManager.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/DidAssociateFormControls.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/DidNotHandleKeyDown.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/DocumentStartUserScriptAlertCrash.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/DownloadDecideDestinationCrash.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/EvaluateJavaScript.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/FailedLoad.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/Find.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/ForceRepaint.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypeHTML.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypePNG.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/Geolocation.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/HitTestResultNodeHandle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleFrameHitTest.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/LayoutMilestonesWithAllContentInFrame.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/LoadAlternateHTMLStringWithNonDirectoryURL.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/LoadCanceledNoServerRedirectCallback.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/LoadPageOnCrash.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/MouseMoveAfterCrash.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/PageLoadBasic.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/PageLoadDidChangeLocationWithinPageForFrame.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/ParentFrame.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/PreventEmptyUserAgent.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/PrivateBrowsingPushStateNoHistoryCallback.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/ReloadPageAfterCrash.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/ResizeReversePaginatedWebView.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/ResizeWindowAfterCrash.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/ResponsivenessTimerDoesntFireEarly.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/RestoreSessionStateContainingFormData.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/ScrollPinningBehaviors.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/ShouldGoToBackForwardListItem.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/SpacebarScrolling.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/TerminateTwice.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/UserMessage.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/WillLoad.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/WillSendSubmitEvent.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/WKPageGetScaleFactorNotZero.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/WKPreferences.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/WKString.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/WKStringJSString.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/WKURL.cpp
-
-if ENABLE_WEBKIT2
-noinst_LTLIBRARIES += \
- Libraries/libTestWebKitAPIInjectedBundle.la
-endif # ENABLE_WEBKIT2
-
-Libraries_libTestWebKitAPIInjectedBundle_la_SOURCES = \
- Tools/TestWebKitAPI/InjectedBundleController.cpp \
- Tools/TestWebKitAPI/InjectedBundleController.h \
- Tools/TestWebKitAPI/InjectedBundleMain.cpp \
- Tools/TestWebKitAPI/InjectedBundleTest.h \
- Tools/TestWebKitAPI/PlatformUtilities.cpp \
- Tools/TestWebKitAPI/PlatformUtilities.h \
- Tools/TestWebKitAPI/Tests/WebKit2/CanHandleRequest_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/DidAssociateFormControls_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/DocumentStartUserScriptAlertCrash_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/HitTestResultNodeHandle_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleFrameHitTest_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/LoadCanceledNoServerRedirectCallback_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/MouseMoveAfterCrash_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/ParentFrame_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/ResponsivenessTimerDoesntFireEarly_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/ShouldGoToBackForwardListItem_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/UserMessage_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/WillLoad_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/WillSendSubmitEvent_Bundle.cpp \
- Tools/TestWebKitAPI/gtk/InjectedBundleControllerGtk.cpp \
- Tools/TestWebKitAPI/gtk/PlatformUtilitiesGtk.cpp
-
-Libraries_libTestWebKitAPIInjectedBundle_la_LDFLAGS = \
- -rpath ${shell pwd}/$(top_builddir)/Libraries/.libs \
- $(no_undefined) \
- -avoid-version \
- -module
-
-Libraries_libTestWebKitAPIInjectedBundle_la_CPPFLAGS = \
- $(Libraries_libTestWebKitAPIMain_la_CPPFLAGS) \
- -I$(top_builddir)/DerivedSources/InjectedBundle \
- $(GTK_CFLAGS)
-
-Libraries_libTestWebKitAPIInjectedBundle_la_CXXFLAGS = \
- -DGTEST_HAS_RTTI=0 \
- $(global_cxxflags)
-
-Libraries_libTestWebKitAPIInjectedBundle_la_CFLAGS = \
- $(global_cflags)
-
-
-if ENABLE_WEBKIT2
-noinst_LTLIBRARIES += Libraries/WebExtensions/libWebExtensionTest.la
-endif
-
-Libraries_WebExtensions_libWebExtensionTest_la_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp
-
-Libraries_WebExtensions_libWebExtensionTest_la_LDFLAGS = \
- -rpath ${shell pwd}/$(top_builddir)/Libraries/WebExtensions/.libs \
- $(no_undefined) \
- -avoid-version \
- -module
-
-Libraries_WebExtensions_libWebExtensionTest_la_CPPFLAGS = \
- -I$(srcdir)/Source/WebKit2/WebProcess/InjectedBundle/API/gtk \
- -I$(top_builddir)/DerivedSources \
- -I$(top_builddir)/DerivedSources/WebKit2/webkit2extension/include \
- -DWEBKIT2_COMPILATION \
- $(webkit2gtk_tests_cppflags)
-
-Libraries_WebExtensions_libWebExtensionTest_la_CXXFLAGS = \
- $(global_cxxflags)
-
-Libraries_WebExtensions_libWebExtensionTest_la_CFLAGS = \
- $(global_cflags)
-
-
-if ENABLE_WEBKIT2
-noinst_LTLIBRARIES += Libraries/WebExtensions/libWebProcessTest.la
-endif
-
-Libraries_WebExtensions_libWebProcessTest_la_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMNodeTest.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/FrameTest.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebProcessTest.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebProcessTest.h
-
-Libraries_WebExtensions_libWebProcessTest_la_LDFLAGS = \
- -rpath ${shell pwd}/$(top_builddir)/Libraries/WebExtensions/.libs \
- $(no_undefined) \
- -avoid-version \
- -module
-
-Libraries_WebExtensions_libWebProcessTest_la_CPPFLAGS = \
- -I$(srcdir)/Source/WebKit2/WebProcess/InjectedBundle/API/gtk \
- -I$(top_builddir)/DerivedSources \
- -I$(top_builddir)/DerivedSources/WebKit2/webkit2extension/include \
- -DWEBKIT2_COMPILATION \
- $(webkit2gtk_tests_cppflags)
-
-Libraries_WebExtensions_libWebProcessTest_la_CXXFLAGS = \
- $(global_cxxflags)
-
-Libraries_WebExtensions_libWebProcessTest_la_CFLAGS = \
- $(global_cflags)
-
-
-Programs/TestWebKitAPI/WebKit2Gtk/resources/webkit2gtk-tests-resources.gresource: Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/webkit2gtk-tests.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/webkit2gtk-tests.gresource.xml)
- $(AM_V_at)mkdir -p ${GENPROGRAMS}/TestWebKitAPI/WebKit2Gtk/resources
- $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) $<
-
-DISTCLEANFILES += \
- Programs/TestWebKitAPI/WebKit2Gtk/resources/webkit2gtk-tests-resources.gresource
-
-noinst_DATA += \
- Programs/TestWebKitAPI/WebKit2Gtk/resources/webkit2gtk-tests-resources.gresource
-
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitWebContext_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebContext.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitWebContext_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitWebContext_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitWebContext_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitWebView_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitWebView_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitWebView_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitWebView_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestLoaderClient_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestLoaderClient.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestLoaderClient_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestLoaderClient_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestLoaderClient_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestMultiprocess_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestMultiprocess.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestMultiprocess_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestMultiprocess_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestMultiprocess_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitSettings_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitSettings.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitSettings_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitSettings_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitSettings_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_InspectorTestServer_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/InspectorTestServer.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_InspectorTestServer_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_InspectorTestServer_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_InspectorTestServer_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestBackForwardList_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestBackForwardList.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestBackForwardList_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestBackForwardList_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestBackForwardList_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitPolicyClient_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitPolicyClient.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitPolicyClient_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitPolicyClient_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitPolicyClient_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-if HAVE_ATSPI2
-Programs_TestWebKitAPI_WebKit2Gtk_AccessibilityTestServer_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/AccessibilityTestServer.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_AccessibilityTestServer_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_AccessibilityTestServer_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_AccessibilityTestServer_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitAccessibility_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitAccessibility.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitAccessibility_CPPFLAGS = $(webkit2gtk_tests_cppflags) $(ATSPI2_CFLAGS)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitAccessibility_LDADD = $(webkit2gtk_tests_ldadd) $(ATSPI2_LIBS)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitAccessibility_LDFLAGS = $(webkit2gtk_tests_ldflags)
-endif
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestDownloads_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDownloads.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestDownloads_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestDownloads_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestDownloads_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebViewEditor_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebViewEditor.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebViewEditor_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebViewEditor_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebViewEditor_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestPrinting_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestPrinting.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestPrinting_CPPFLAGS = $(webkit2gtk_tests_cppflags) $(GTK_UNIX_PRINTING_CFLAGS)
-Programs_TestWebKitAPI_WebKit2Gtk_TestPrinting_LDADD = $(webkit2gtk_tests_ldadd) $(GTK_UNIX_PRINTING_LIBS)
-Programs_TestWebKitAPI_WebKit2Gtk_TestPrinting_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitFaviconDatabase_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFaviconDatabase.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitFaviconDatabase_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitFaviconDatabase_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitFaviconDatabase_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitFindController_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFindController.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitFindController_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitFindController_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitFindController_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestResources_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestResources.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestResources_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestResources_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestResources_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestCookieManager_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestCookieManager.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestCookieManager_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestCookieManager_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestCookieManager_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestInspector_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestInspector.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestInspector_CPPFLAGS = \
- $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestInspector_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestInspector_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestInspectorServer_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestInspectorServer.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestInspectorServer_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestInspectorServer_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestInspectorServer_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitVersion_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitVersion.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitVersion_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitVersion_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitVersion_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestContextMenu_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestContextMenu.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestContextMenu_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestContextMenu_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestContextMenu_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestSSL_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestSSL.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestSSL_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestSSL_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestSSL_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebExtensions_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebExtensions.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebExtensions_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebExtensions_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebExtensions_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitWebViewGroup_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebViewGroup.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitWebViewGroup_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitWebViewGroup_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitWebViewGroup_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestDOMNode_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMNode.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestDOMNode_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestDOMNode_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestDOMNode_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestFrame_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestFrame.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestFrame_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestFrame_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestFrame_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestAuthentication_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestAuthentication.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestAuthentication_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestAuthentication_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestAuthentication_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestUIClient_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestUIClient.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestUIClient_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestUIClient_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestUIClient_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-
-stamp-testwebkitapi-webcore-forwarding-headers: $(WebKit2)/Scripts/generate-forwarding-headers.pl $(Programs_TestWebKitAPI_WebCore_TestWebCore_SOURCES)
- $(AM_V_GEN)$(PERL) $< $(srcdir)/Tools/TestWebKitAPI/Tests/WebCore $(GENSOURCES_WEBCORE)/include gtk \
- && echo timestamp > $(@F)
-
-stamp-testwebkitapi-webkit2-forwarding-headers: $(WebKit2)/Scripts/generate-forwarding-headers.pl $(Programs_TestWebKitAPI_WebKit2_TestWebKit2_SOURCES) $(Libraries_libTestWebKitAPIInjectedBundle_la_SOURCES)
- $(AM_V_GEN)$(PERL) $< $(srcdir)/Tools/TestWebKitAPI $(GENSOURCES_WEBKIT2)/include gtk \
- && echo timestamp > $(@F)
-
-BUILT_SOURCES += $(top_builddir)/stamp-testwebkitapi-webcore-forwarding-headers
-if ENABLE_WEBKIT2
-BUILT_SOURCES += $(top_builddir)/stamp-testwebkitapi-webkit2-forwarding-headers
-endif # ENABLE_WEBKIT2
-
-
-EXTRA_DIST += \
- Tools/TestWebKitAPI/Tests/WebKit2/18-characters.html \
- Tools/TestWebKitAPI/Tests/WebKit2/file-with-anchor.html \
- Tools/TestWebKitAPI/Tests/WebKit2/find.html \
- Tools/TestWebKitAPI/Tests/WebKit2/icon.png \
- Tools/TestWebKitAPI/Tests/WebKit2/lots-of-iframes.html \
- Tools/TestWebKitAPI/Tests/WebKit2/lots-of-images.html \
- Tools/TestWebKitAPI/Tests/WebKit2/lots-of-text.html \
- Tools/TestWebKitAPI/Tests/WebKit2/mouse-move-listener.html \
- Tools/TestWebKitAPI/Tests/WebKit2/push-state.html \
- Tools/TestWebKitAPI/Tests/WebKit2/simple-accelerated-compositing.html \
- Tools/TestWebKitAPI/Tests/WebKit2/simple-form.html \
- Tools/TestWebKitAPI/Tests/WebKit2/simple.html \
- Tools/TestWebKitAPI/Tests/WebKit2/simple-iframe.html \
- Tools/TestWebKitAPI/Tests/WebKit2/simple-tall.html \
- Tools/TestWebKitAPI/Tests/WebKit2/spacebar-scrolling.html \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/test-cert.pem \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/test-key.pem \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/webkit2gtk-tests.gresource.xml \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/link-title.js \
- Tools/TestWebKitAPI/Tests/WebKitGtk/test_utils.h \
- Tools/TestWebKitAPI/Tests/WebKitGtk/resources/blank.ico \
- Tools/TestWebKitAPI/Tests/WebKitGtk/resources/test.html \
- Tools/TestWebKitAPI/Tests/WebKitGtk/resources/test.ogg \
- Tools/TestWebKitAPI/Tests/WebKitGtk/resources/test.pdf \
- Tools/TestWebKitAPI/Tests/WebKitGtk/resources/test.txt
diff --git a/Tools/TestWebKitAPI/InjectedBundleController.cpp b/Tools/TestWebKitAPI/InjectedBundleController.cpp
index 00b534b0e..53f39a874 100644
--- a/Tools/TestWebKitAPI/InjectedBundleController.cpp
+++ b/Tools/TestWebKitAPI/InjectedBundleController.cpp
@@ -24,6 +24,9 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleController.h"
#include "InjectedBundleTest.h"
@@ -33,7 +36,7 @@
namespace TestWebKitAPI {
-InjectedBundleController& InjectedBundleController::shared()
+InjectedBundleController& InjectedBundleController::singleton()
{
static InjectedBundleController& shared = *new InjectedBundleController;
return shared;
@@ -138,3 +141,5 @@ void InjectedBundleController::registerCreateInjectedBundleTestFunction(const st
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/InjectedBundleController.h b/Tools/TestWebKitAPI/InjectedBundleController.h
index 0ca112584..eaa7f0d17 100644
--- a/Tools/TestWebKitAPI/InjectedBundleController.h
+++ b/Tools/TestWebKitAPI/InjectedBundleController.h
@@ -26,7 +26,7 @@
#ifndef InjectedBundleController_h
#define InjectedBundleController_h
-#include <WebKit2/WKBundle.h>
+#include <WebKit/WKBundle.h>
#include <map>
#include <string>
@@ -36,7 +36,7 @@ class InjectedBundleTest;
class InjectedBundleController {
public:
- static InjectedBundleController& shared();
+ static InjectedBundleController& singleton();
void initialize(WKBundleRef, WKTypeRef);
diff --git a/Tools/TestWebKitAPI/InjectedBundleMain.cpp b/Tools/TestWebKitAPI/InjectedBundleMain.cpp
index 8ad6c2bad..b2537f737 100644
--- a/Tools/TestWebKitAPI/InjectedBundleMain.cpp
+++ b/Tools/TestWebKitAPI/InjectedBundleMain.cpp
@@ -24,8 +24,11 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleController.h"
-#include <WebKit2/WKBundleInitialize.h>
+#include <WebKit/WKBundleInitialize.h>
#if defined(WIN32) || defined(_WIN32)
extern "C" __declspec(dllexport)
@@ -34,5 +37,7 @@ extern "C"
#endif
void WKBundleInitialize(WKBundleRef bundle, WKTypeRef initializationUserData)
{
- TestWebKitAPI::InjectedBundleController::shared().initialize(bundle, initializationUserData);
+ TestWebKitAPI::InjectedBundleController::singleton().initialize(bundle, initializationUserData);
}
+
+#endif
diff --git a/Tools/TestWebKitAPI/InjectedBundleTest.h b/Tools/TestWebKitAPI/InjectedBundleTest.h
index d0f996aff..ad2cb9581 100644
--- a/Tools/TestWebKitAPI/InjectedBundleTest.h
+++ b/Tools/TestWebKitAPI/InjectedBundleTest.h
@@ -48,7 +48,7 @@ public:
public:
Register(const std::string& test)
{
- InjectedBundleController::shared().registerCreateInjectedBundleTestFunction(test, Register::create);
+ InjectedBundleController::singleton().registerCreateInjectedBundleTestFunction(test, Register::create);
}
private:
diff --git a/Tools/TestWebKitAPI/JavaScriptTest.cpp b/Tools/TestWebKitAPI/JavaScriptTest.cpp
index de1848fdc..133d99eee 100644
--- a/Tools/TestWebKitAPI/JavaScriptTest.cpp
+++ b/Tools/TestWebKitAPI/JavaScriptTest.cpp
@@ -24,14 +24,17 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "JavaScriptTest.h"
#include "PlatformUtilities.h"
#include "Test.h"
#include <JavaScriptCore/JSContextRef.h>
#include <JavaScriptCore/JSRetainPtr.h>
-#include <WebKit2/WKRetainPtr.h>
-#include <WebKit2/WKSerializedScriptValue.h>
+#include <WebKit/WKRetainPtr.h>
+#include <WebKit/WKSerializedScriptValue.h>
#include <wtf/StdLibExtras.h>
namespace TestWebKitAPI {
@@ -90,3 +93,5 @@ static void javaScriptCallback(WKSerializedScriptValueRef resultSerializedScript
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/JavaScriptTest.h b/Tools/TestWebKitAPI/JavaScriptTest.h
index c6e79c3b6..c0494b2ca 100644
--- a/Tools/TestWebKitAPI/JavaScriptTest.h
+++ b/Tools/TestWebKitAPI/JavaScriptTest.h
@@ -23,14 +23,9 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#if PLATFORM(MAC)
-#ifdef __OBJC__
-@class WKView;
-@class WebView;
-#else
-class WKView;
-class WebView;
-#endif
+#if PLATFORM(COCOA)
+OBJC_CLASS WKView;
+OBJC_CLASS WebView;
#endif
namespace TestWebKitAPI {
@@ -44,7 +39,7 @@ namespace TestWebKitAPI {
::testing::AssertionResult runJSTest(const char* pageExpr, const char* scriptExpr, const char* expectedResultExpr, WKPageRef, const char* script, const char* expectedResult);
::testing::AssertionResult compareJSResult(const char* script, const char* actualResult, const char* expectedResult);
-#if PLATFORM(MAC)
+#if PLATFORM(COCOA)
::testing::AssertionResult runJSTest(const char* webViewExpr, const char* scriptExpr, const char* expectedResultExpr, WebView *, const char* script, const char* expectedResult);
::testing::AssertionResult runJSTest(const char* viewExpr, const char* scriptExpr, const char* expectedResultExpr, WKView *, const char* script, const char* expectedResult);
#endif
diff --git a/Tools/TestWebKitAPI/PlatformGTK.cmake b/Tools/TestWebKitAPI/PlatformGTK.cmake
new file mode 100644
index 000000000..d7243f970
--- /dev/null
+++ b/Tools/TestWebKitAPI/PlatformGTK.cmake
@@ -0,0 +1,166 @@
+set(TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/TestWebKitAPI")
+set(TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY_WTF "${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY}/WTF")
+
+# This is necessary because it is possible to build TestWebKitAPI with WebKit2
+# disabled and this triggers the inclusion of the WebKit2 headers.
+add_definitions(-DBUILDING_WEBKIT2__)
+
+add_custom_target(TestWebKitAPI-forwarding-headers
+ COMMAND ${PERL_EXECUTABLE} ${WEBKIT2_DIR}/Scripts/generate-forwarding-headers.pl --include-path ${TESTWEBKITAPI_DIR} --output ${FORWARDING_HEADERS_DIR} --platform gtk --platform soup
+ DEPENDS WebKit2-forwarding-headers
+)
+
+set(ForwardingHeadersForTestWebKitAPI_NAME TestWebKitAPI-forwarding-headers)
+
+include_directories(
+ ${FORWARDING_HEADERS_DIR}
+ ${FORWARDING_HEADERS_DIR}/JavaScriptCore
+ ${WEBKIT2_DIR}/UIProcess/API/C/soup
+ ${WEBKIT2_DIR}/UIProcess/API/C/gtk
+ ${WEBKIT2_DIR}/UIProcess/API/gtk
+)
+
+include_directories(SYSTEM
+ ${GDK3_INCLUDE_DIRS}
+ ${GLIB_INCLUDE_DIRS}
+ ${GTK3_INCLUDE_DIRS}
+ ${LIBSOUP_INCLUDE_DIRS}
+)
+
+set(test_main_SOURCES
+ ${TESTWEBKITAPI_DIR}/gtk/main.cpp
+)
+
+set(bundle_harness_SOURCES
+ ${TESTWEBKITAPI_DIR}/gtk/InjectedBundleControllerGtk.cpp
+ ${TESTWEBKITAPI_DIR}/gtk/PlatformUtilitiesGtk.cpp
+)
+
+set(webkit2_api_harness_SOURCES
+ ${TESTWEBKITAPI_DIR}/gtk/PlatformUtilitiesGtk.cpp
+ ${TESTWEBKITAPI_DIR}/gtk/PlatformWebViewGtk.cpp
+)
+
+list(APPEND test_wtf_LIBRARIES
+ ${GDK3_LIBRARIES}
+ ${GTK3_LIBRARIES}
+)
+
+list(APPEND test_webkit2_api_LIBRARIES
+ ${GDK3_LIBRARIES}
+ ${GTK3_LIBRARIES}
+)
+
+list(APPEND test_webcore_LIBRARIES
+ WebCorePlatformGTK
+ ${GDK3_LIBRARIES}
+ ${GTK3_LIBRARIES}
+)
+
+list(APPEND TestWebKitAPI_LIBRARIES
+ ${GDK3_LIBRARIES}
+ ${GTK3_LIBRARIES}
+)
+
+list(APPEND TestJavaScriptCore_LIBRARIES
+ ${GDK3_LIBRARIES}
+ ${GTK3_LIBRARIES}
+)
+
+add_executable(TestWebKit2
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/AboutBlankLoad.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/CanHandleRequest.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/CookieManager.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/DocumentStartUserScriptAlertCrash.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/DOMWindowExtensionBasic.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/DOMWindowExtensionNoCache.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/DownloadDecideDestinationCrash.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/EvaluateJavaScript.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/FailedLoad.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/Find.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/ForceRepaint.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/FrameMIMETypeHTML.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/FrameMIMETypePNG.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/Geolocation.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/HitTestResultNodeHandle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/InjectedBundleBasic.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/InjectedBundleFrameHitTest.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/LoadAlternateHTMLStringWithNonDirectoryURL.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/LoadCanceledNoServerRedirectCallback.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/LoadPageOnCrash.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/MouseMoveAfterCrash.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/PageLoadBasic.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/PageLoadDidChangeLocationWithinPageForFrame.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/ParentFrame.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/PendingAPIRequestURL.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/PreventEmptyUserAgent.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/PrivateBrowsingPushStateNoHistoryCallback.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/ReloadPageAfterCrash.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/ResizeWindowAfterCrash.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/RestoreSessionStateContainingFormData.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/ShouldGoToBackForwardListItem.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/TextFieldDidBeginAndEndEditing.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/UserMedia.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/UserMessage.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/WillSendSubmitEvent.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/WKPageCopySessionStateWithFiltering.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/WKPageGetScaleFactorNotZero.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/WKPreferences.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/WKRetainPtr.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/WKString.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/WKStringJSString.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/WKURL.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/gtk/InputMethodFilter.cpp
+)
+
+target_link_libraries(TestWebKit2 ${test_webkit2_api_LIBRARIES})
+add_test(TestWebKit2 ${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY}/WebKit2/TestWebKit2)
+set_tests_properties(TestWebKit2 PROPERTIES TIMEOUT 60)
+set_target_properties(TestWebKit2 PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY}/WebKit2)
+
+if (ENABLE_SECCOMP_FILTERS)
+ # This test needs to be in its own executable. It's a general test of the
+ # seccomp filter mechanism, and the filters it sets are incompatible with
+ # the correct operation of WebKit and the other tests.
+ add_executable(TestSeccompFilters
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/SeccompFilters.cpp
+ )
+
+ target_link_libraries(TestSeccompFilters ${test_webkit2_api_LIBRARIES})
+ add_test(TestSeccompFilters ${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY}/WebKit2/TestWebKit2)
+ set_tests_properties(TestSeccompFilters PROPERTIES TIMEOUT 5)
+ set_target_properties(TestSeccompFilters PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY}/WebKit2)
+endif ()
+
+set(TestWebCoreGtk_SOURCES
+ ${TESTWEBKITAPI_DIR}/Tests/WebCore/gtk/UserAgentQuirks.cpp
+)
+
+add_executable(TestWebCore
+ ${test_main_SOURCES}
+ ${TestWebCoreGtk_SOURCES}
+ ${TESTWEBKITAPI_DIR}/TestsController.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebCore/LayoutUnit.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebCore/URL.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebCore/SharedBuffer.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebCore/FileSystem.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebCore/PublicSuffix.cpp
+)
+
+target_link_libraries(TestWebCore ${test_webcore_LIBRARIES})
+add_dependencies(TestWebCore ${ForwardingHeadersForTestWebKitAPI_NAME})
+
+add_test(TestWebCore ${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY}/WebCore/TestWebCore)
+set_tests_properties(TestWebCore PROPERTIES TIMEOUT 60)
+set_target_properties(TestWebCore PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY}/WebCore)
+
+list(APPEND TestWTF_SOURCES
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/glib/GUniquePtr.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/glib/WorkQueueGLib.cpp
+)
diff --git a/Tools/TestWebKitAPI/PlatformMac.cmake b/Tools/TestWebKitAPI/PlatformMac.cmake
new file mode 100644
index 000000000..fe6f07e43
--- /dev/null
+++ b/Tools/TestWebKitAPI/PlatformMac.cmake
@@ -0,0 +1,32 @@
+set(TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
+set(TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY_WTF "${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY}")
+
+include_directories(
+ ${DERIVED_SOURCES_DIR}/ForwardingHeaders
+ "${WTF_DIR}/icu"
+)
+
+set(test_main_SOURCES
+ ${TESTWEBKITAPI_DIR}/mac/mainMac.mm
+)
+
+find_library(CARBON_LIBRARY Carbon)
+find_library(COCOA_LIBRARY Cocoa)
+find_library(COREFOUNDATION_LIBRARY CoreFoundation)
+link_directories(${CMAKE_SOURCE_DIR}/WebKitLibraries)
+list(APPEND test_wtf_LIBRARIES
+ ${CARBON_LIBRARY}
+ ${COCOA_LIBRARY}
+ ${COREFOUNDATION_LIBRARY}
+ libicucore.dylib
+)
+
+set(bundle_harness_SOURCES
+ ${TESTWEBKITAPI_DIR}/cocoa/PlatformUtilitiesCocoa.mm
+ ${TESTWEBKITAPI_DIR}/mac/InjectedBundleControllerMac.mm
+ ${TESTWEBKITAPI_DIR}/mac/InstanceMethodSwizzler.mm
+ ${TESTWEBKITAPI_DIR}/mac/PlatformUtilitiesMac.mm
+ ${TESTWEBKITAPI_DIR}/mac/PlatformWebViewMac.mm
+ ${TESTWEBKITAPI_DIR}/mac/SyntheticBackingScaleFactorWindow.m
+ ${TESTWEBKITAPI_DIR}/mac/TestBrowsingContextLoadDelegate.mm
+)
diff --git a/Tools/TestWebKitAPI/PlatformUtilities.cpp b/Tools/TestWebKitAPI/PlatformUtilities.cpp
index cebff7be9..216c70ac2 100644
--- a/Tools/TestWebKitAPI/PlatformUtilities.cpp
+++ b/Tools/TestWebKitAPI/PlatformUtilities.cpp
@@ -24,6 +24,7 @@
*/
#include "config.h"
+
#include "PlatformUtilities.h"
#include <wtf/StdLibExtras.h>
@@ -31,6 +32,8 @@
namespace TestWebKitAPI {
namespace Util {
+#if WK_HAVE_C_SPI
+
WKContextRef createContextWithInjectedBundle()
{
WKRetainPtr<WKStringRef> injectedBundlePath(AdoptWK, createInjectedBundlePath());
@@ -76,14 +79,16 @@ std::string toSTD(WKRetainPtr<WKStringRef> string)
return toSTD(string.get());
}
-std::string toSTD(const char* string)
+WKRetainPtr<WKStringRef> toWK(const char* utf8String)
{
- return std::string(string);
+ return WKRetainPtr<WKStringRef>(AdoptWK, WKStringCreateWithUTF8CString(utf8String));
}
-WKRetainPtr<WKStringRef> toWK(const char* utf8String)
+#endif // WK_HAVE_C_SPI
+
+std::string toSTD(const char* string)
{
- return WKRetainPtr<WKStringRef>(AdoptWK, WKStringCreateWithUTF8CString(utf8String));
+ return std::string(string);
}
} // namespace Util
diff --git a/Tools/TestWebKitAPI/PlatformUtilities.h b/Tools/TestWebKitAPI/PlatformUtilities.h
index 10da84d33..7583e4ee0 100644
--- a/Tools/TestWebKitAPI/PlatformUtilities.h
+++ b/Tools/TestWebKitAPI/PlatformUtilities.h
@@ -26,15 +26,12 @@
#ifndef PlatformUtilities_h
#define PlatformUtilities_h
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKNativeEvent.h>
+#include <WebKit/WKRetainPtr.h>
#include <string>
-#if PLATFORM(MAC)
-#if __OBJC__
-@class NSString;
-#else
-class NSString;
-#endif
+#if USE(FOUNDATION)
+OBJC_CLASS NSString;
#endif
namespace TestWebKitAPI {
@@ -42,12 +39,14 @@ namespace Util {
// Runs a platform runloop until the 'done' is true.
void run(bool* done);
+void sleep(double seconds);
-#if PLATFORM(WIN)
-bool shouldTranslateMessage(const MSG&);
+std::string toSTD(const char*);
+#if USE(FOUNDATION)
+std::string toSTD(NSString *);
#endif
-void sleep(double seconds);
+#if WK_HAVE_C_SPI
WKContextRef createContextWithInjectedBundle();
WKContextRef createContextForInjectedBundleTest(const std::string&, WKTypeRef userData = 0);
@@ -62,13 +61,11 @@ bool isKeyDown(WKNativeEventPtr);
std::string toSTD(WKStringRef);
std::string toSTD(WKRetainPtr<WKStringRef>);
-std::string toSTD(const char*);
-#if PLATFORM(MAC)
-std::string toSTD(NSString *);
-#endif
WKRetainPtr<WKStringRef> toWK(const char* utf8String);
+#endif // WK_HAVE_C_SPI
+
template<typename T, typename U>
static inline ::testing::AssertionResult assertWKStringEqual(const char* expected_expression, const char* actual_expression, T expected, U actual)
{
@@ -78,6 +75,10 @@ static inline ::testing::AssertionResult assertWKStringEqual(const char* expecte
#define EXPECT_WK_STREQ(expected, actual) \
EXPECT_PRED_FORMAT2(TestWebKitAPI::Util::assertWKStringEqual, expected, actual)
+#if WK_API_ENABLED
+extern NSString * const TestPlugInClassNameParameter;
+#endif
+
} // namespace Util
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/PlatformWebView.h b/Tools/TestWebKitAPI/PlatformWebView.h
index 8679fa2c4..6621d92f7 100644
--- a/Tools/TestWebKitAPI/PlatformWebView.h
+++ b/Tools/TestWebKitAPI/PlatformWebView.h
@@ -30,7 +30,11 @@
#include <CoreGraphics/CGGeometry.h>
#endif
-#ifdef __APPLE__
+#if PLATFORM(MAC)
+#include <objc/objc.h>
+#endif
+
+#if defined(__APPLE__) && !PLATFORM(GTK)
#ifdef __OBJC__
@class WKView;
@class NSWindow;
@@ -40,32 +44,24 @@ class NSWindow;
#endif
typedef WKView *PlatformWKView;
typedef NSWindow *PlatformWindow;
-#elif defined(WIN32) || defined(_WIN32)
-typedef WKViewRef PlatformWKView;
-typedef HWND PlatformWindow;
#elif PLATFORM(GTK)
typedef WKViewRef PlatformWKView;
typedef GtkWidget *PlatformWindow;
#elif PLATFORM(EFL)
-typedef struct _Ecore_Evas Ecore_Evas;
-#if USE(EO)
-typedef struct _Eo_Opaque Evas_Object;
-#else
-typedef struct _Evas_Object Evas_Object;
-#endif
typedef Evas_Object* PlatformWKView;
typedef Ecore_Evas* PlatformWindow;
#endif
namespace TestWebKitAPI {
-#if PLATFORM(WIN)
-class WindowMessageObserver;
-#endif
-
class PlatformWebView {
public:
- PlatformWebView(WKContextRef, WKPageGroupRef = 0);
+ explicit PlatformWebView(WKPageConfigurationRef);
+ explicit PlatformWebView(WKContextRef, WKPageGroupRef = 0);
+ explicit PlatformWebView(WKPageRef relatedPage);
+#if PLATFORM(MAC)
+ explicit PlatformWebView(WKContextRef, WKPageGroupRef, Class wkViewSubclass);
+#endif
~PlatformWebView();
WKPageRef page() const;
@@ -77,24 +73,19 @@ public:
void simulateAltKeyPress();
void simulateRightClick(unsigned x, unsigned y);
void simulateMouseMove(unsigned x, unsigned y);
-
-#if PLATFORM(WIN)
- void simulateAKeyDown();
- void setParentWindowMessageObserver(WindowMessageObserver* observer) { m_parentWindowMessageObserver = observer; }
+#if PLATFORM(MAC)
+ void simulateButtonClick(WKEventMouseButton, unsigned x, unsigned y, WKEventModifiers);
#endif
private:
-#if PLATFORM(WIN)
- static void registerWindowClass();
- static LRESULT CALLBACK wndProc(HWND, UINT message, WPARAM, LPARAM);
+#if PLATFORM(MAC)
+ void initialize(WKPageConfigurationRef, Class wkViewSubclass);
+#elif PLATFORM(GTK)
+ void initialize(WKPageConfigurationRef);
#endif
PlatformWKView m_view;
PlatformWindow m_window;
-
-#if PLATFORM(WIN)
- WindowMessageObserver* m_parentWindowMessageObserver;
-#endif
};
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Test.h b/Tools/TestWebKitAPI/Test.h
index ca43924a2..cf44045fb 100644
--- a/Tools/TestWebKitAPI/Test.h
+++ b/Tools/TestWebKitAPI/Test.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 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
@@ -26,6 +26,8 @@
#ifndef Test_h
#define Test_h
+#include <type_traits>
+
namespace TestWebKitAPI {
#define EXPECT_NOT_NULL(expression) \
@@ -40,6 +42,18 @@ namespace TestWebKitAPI {
#define ASSERT_NULL(expression) \
ASSERT_TRUE(!(expression))
+template<typename T>
+static inline ::testing::AssertionResult assertStrongEnum(const char* expected_expression, const char* actual_expression, T expected, T actual)
+{
+ static_assert(std::is_enum<T>::value, "T is not an enum type");
+ typedef typename std::underlying_type<T>::type UnderlyingStorageType;
+ return ::testing::internal::CmpHelperEQ(expected_expression, actual_expression, static_cast<UnderlyingStorageType>(expected), static_cast<UnderlyingStorageType>(actual));
+}
+
+#define EXPECT_STRONG_ENUM_EQ(expected, actual) \
+ EXPECT_PRED_FORMAT2(TestWebKitAPI::assertStrongEnum, expected, actual)
+
+
} // namespace TestWebKitAPI
#endif // Test_h
diff --git a/Tools/TestWebKitAPI/Tests/JavaScriptCore/VMInspector.cpp b/Tools/TestWebKitAPI/Tests/JavaScriptCore/VMInspector.cpp
deleted file mode 100644
index b1c1bacf3..000000000
--- a/Tools/TestWebKitAPI/Tests/JavaScriptCore/VMInspector.cpp
+++ /dev/null
@@ -1,689 +0,0 @@
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#include <interpreter/VMInspector.h>
-#include <stdarg.h>
-#include <stdio.h>
-
-using namespace JSC;
-
-// There's not much we can test for the VMInspector::printf() case except to
-// make sure it does not crash. Unfortunately, we also don't want all the
-// test strings crowding out stdout. So, we forego the printf tests.
-// NOTE that the most interesting part of VMInspector::printf() is the
-// formatting functionality, and it is are already being tested by the
-// fprintf() and sprintf() cases.
-
-
-// The VMInspector::fprintf() test works by printing the string to a temp file,
-// and then reading the file content back into a buffer, which we, in turn,
-// compare against the expected string.
-
-TEST(JSC, VMInspectorFprintf)
-{
-#if ENABLE(VMINSPECTOR)
- char actual[1024];
- char expected[1024];
- const char* format;
- const char* expectedLiteral;
- FILE* file;
- const char* filename = "/tmp/VMInspectorFprintfTest.txt";
- size_t size;
-
-#define OPEN_FILE(file) \
- do { \
- file = fopen(filename, "w"); \
- } while (false)
-
-#define READ_AND_CLOSE_FILE(file, actual) \
- do { \
- fclose(file); \
- file = fopen(filename, "r"); \
- fseek(file, 0, SEEK_END); \
- size = ftell(file); \
- rewind(file); \
- fread(actual, 1, size, file); \
- actual[size] = '\0'; \
- fclose(file); \
- } while (false)
-
- // Testing standard default format specifiers:
- // Note: should work just like sprintf. So, we just compare against that.
- memset(actual, 'z', sizeof(actual));
- // The compiler warning flags are configured to expect a literal string for
- // ::sprintf below. So, use a #define for this one case to keep the
- // compiler happy.
-#undef LITERAL_FORMAT
-#define LITERAL_FORMAT "'%%%%' ==> '%%'\n"
-
- OPEN_FILE(file);
- VMInspector::fprintf(file, LITERAL_FORMAT);
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, LITERAL_FORMAT);
-
-#undef LITERAL_FORMAT
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%c', 'x' ==> '%c'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 'x');
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 'x');
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%*c', 8, 'x' ==> '%*c'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 8, 'x');
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 8, 'x');
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%s', \"hello world\" ==> '%s'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, "hello world");
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, "hello world");
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%*s', 8, \"hello world\" ==> '%*s'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 8, "hello world");
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 8, "hello world");
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%*s', 8, \"hello\" ==> '%*s'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 8, "hello");
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 8, "hello");
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%d', 987654321 ==> '%d'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 987654321);
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 987654321);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%u', 4276543210u ==> '%u'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 4276543210u);
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 4276543210u);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%u', 0xffffffff ==> '%u'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 0xffffffff);
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 0xffffffff);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%x', 0xffffffff ==> '%x'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 0xffffffff);
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 0xffffffff);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%p', (void*)0xabcdbabe ==> '%p'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, (void*)0xabcdbabe);
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, (void*)0xabcdbabe);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%lu', 1234567890987654321ul ==> '%lu'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 1234567890987654321ul);
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 1234567890987654321ul);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%f', 1234.567 ==> '%f'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 1234.567);
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 1234.567);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%.2f', 1234.567 ==> '%.2f'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 1234.567);
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 1234.567);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%10.2f', 1234.567 ==> '%10.2f'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 1234.567);
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 1234.567);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%010.2f', 1234.567 ==> '%010.2f'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 1234.567);
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 1234.567);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- // Bad / weird formats:
- memset(actual, 'z', sizeof(actual));
- format = "'%%5.4', 987654321 ==> '%5.4'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 987654321);
- READ_AND_CLOSE_FILE(file, actual);
- expectedLiteral = "'%5.4', 987654321 ==> 'ERROR @ \"%5.4' \"\n";
- ASSERT_EQ(strcmp(actual, expectedLiteral), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%5.4' '%%d', 987654321, 4 ==> '%5.4' '%d'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 987654321, 4);
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 987654321, 4);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%w' '%%d', 987654321, 6 ==> '%w' '%d'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 987654321, 6);
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 987654321, 6);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
-
- // Testing the %b extension:
- memset(actual, 'z', sizeof(actual));
- OPEN_FILE(file);
- VMInspector::fprintf(file, "'%%b', 0 ==> '%b'\n", 0);
- READ_AND_CLOSE_FILE(file, actual);
- ASSERT_EQ(strcmp(actual, "'%b', 0 ==> 'FALSE'\n"), 0);
-
- memset(actual, 'z', sizeof(actual));
- OPEN_FILE(file);
- VMInspector::fprintf(file, "'%%b', 1 ==> '%b'\n", 1);
- READ_AND_CLOSE_FILE(file, actual);
- ASSERT_EQ(strcmp(actual, "'%b', 1 ==> 'TRUE'\n"), 0);
-
- memset(actual, 'z', sizeof(actual));
- OPEN_FILE(file);
- VMInspector::fprintf(file, "'%%b', -123456789 ==> '%b'\n", -123456789);
- READ_AND_CLOSE_FILE(file, actual);
- ASSERT_EQ(strcmp(actual, "'%b', -123456789 ==> 'TRUE'\n"), 0);
-
- memset(actual, 'z', sizeof(actual));
- OPEN_FILE(file);
- VMInspector::fprintf(file, "'%%b', 123456789 ==> '%b'\n", 123456789);
- READ_AND_CLOSE_FILE(file, actual);
- ASSERT_EQ(strcmp(actual, "'%b', 123456789 ==> 'TRUE'\n"), 0);
-
-
- // Testing the %J<x> extensions:
- String str1("Test WTF String");
- String str2("");
-
- memset(actual, 'z', sizeof(actual));
- OPEN_FILE(file);
- VMInspector::fprintf(file, "'%%Js' is %%s, &str1, str1.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '%Js' is %s\n",
- &str1, str1.isEmpty() ? "EMPTY" : "NOT EMPTY");
- READ_AND_CLOSE_FILE(file, actual);
- expectedLiteral = "'%Js' is %s, &str1, str1.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> 'Test WTF String' is NOT EMPTY\n";
- ASSERT_EQ(strcmp(actual, expectedLiteral), 0);
-
- memset(actual, 'z', sizeof(actual));
- OPEN_FILE(file);
- VMInspector::fprintf(file, "'%%Js' is %%s, &str2, str2.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '%Js' is %s\n",
- &str2, str2.isEmpty() ? "EMPTY" : "NOT EMPTY");
- READ_AND_CLOSE_FILE(file, actual);
- expectedLiteral = "'%Js' is %s, &str2, str2.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '' is EMPTY\n";
- ASSERT_EQ(strcmp(actual, expectedLiteral), 0);
-
- memset(actual, 'z', sizeof(actual));
- OPEN_FILE(file);
- VMInspector::fprintf(file, "'%%J+s' is %%s, &str1, str1.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '%J+s' is %s\n",
- &str1, str1.isEmpty() ? "EMPTY" : "NOT EMPTY");
- READ_AND_CLOSE_FILE(file, actual);
- expectedLiteral = "'%J+s' is %s, &str1, str1.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> 'WTF::String \"Test WTF String\"' is NOT EMPTY\n";
- ASSERT_EQ(strcmp(actual, expectedLiteral), 0);
-
- memset(actual, 'z', sizeof(actual));
- OPEN_FILE(file);
- VMInspector::fprintf(file, "'%%J+s' is %%s, &str2, str2.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '%J+s' is %s\n",
- &str2, str2.isEmpty() ? "EMPTY" : "NOT EMPTY");
- READ_AND_CLOSE_FILE(file, actual);
- expectedLiteral = "'%J+s' is %s, &str2, str2.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> 'WTF::String \"\"' is EMPTY\n";
- ASSERT_EQ(strcmp(actual, expectedLiteral), 0);
-
-#undef OPEN_FILE
-#undef READ_AND_CLOSE_FILE
-
-#endif
-}
-
-
-TEST(JSC, VMInspectorSprintf)
-{
-#if ENABLE(VMINSPECTOR)
- char actual[1024];
- char expected[1024];
- const char* format;
- const char* expectedLiteral;
-
- // Testing standard default format specifiers:
- // Note: should work just like sprintf. So, we just compare against that.
- memset(actual, 'z', sizeof(actual));
- // The compiler warning flags are configured to expect a literal string for
- // ::sprintf below. So, use a #define for this one case to keep the
- // compiler happy.
-#undef LITERAL_FORMAT
-#define LITERAL_FORMAT "'%%%%' ==> '%%'\n"
- VMInspector::sprintf(actual, LITERAL_FORMAT);
- ::sprintf(expected, LITERAL_FORMAT);
-#undef LITERAL_FORMAT
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%c', 'x' ==> '%c'\n";
- VMInspector::sprintf(actual, format, 'x');
- ::sprintf(expected, format, 'x');
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%*c', 8, 'x' ==> '%*c'\n";
- VMInspector::sprintf(actual, format, 8, 'x');
- ::sprintf(expected, format, 8, 'x');
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%s', \"hello world\" ==> '%s'\n";
- VMInspector::sprintf(actual, format, "hello world");
- ::sprintf(expected, format, "hello world");
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%*s', 8, \"hello world\" ==> '%*s'\n";
- VMInspector::sprintf(actual, format, 8, "hello world");
- ::sprintf(expected, format, 8, "hello world");
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%*s', 8, \"hello\" ==> '%*s'\n";
- VMInspector::sprintf(actual, format, 8, "hello");
- ::sprintf(expected, format, 8, "hello");
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%d', 987654321 ==> '%d'\n";
- VMInspector::sprintf(actual, format, 987654321);
- ::sprintf(expected, format, 987654321);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%u', 4276543210u ==> '%u'\n";
- VMInspector::sprintf(actual, format, 4276543210u);
- ::sprintf(expected, format, 4276543210u);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%u', 0xffffffff ==> '%u'\n";
- VMInspector::sprintf(actual, format, 0xffffffff);
- ::sprintf(expected, format, 0xffffffff);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%x', 0xffffffff ==> '%x'\n";
- VMInspector::sprintf(actual, format, 0xffffffff);
- ::sprintf(expected, format, 0xffffffff);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%p', (void*)0xabcdbabe ==> '%p'\n";
- VMInspector::sprintf(actual, format, (void*)0xabcdbabe);
- ::sprintf(expected, format, (void*)0xabcdbabe);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%lu', 1234567890987654321ul ==> '%lu'\n";
- VMInspector::sprintf(actual, format, 1234567890987654321ul);
- ::sprintf(expected, format, 1234567890987654321ul);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%f', 1234.567 ==> '%f'\n";
- VMInspector::sprintf(actual, format, 1234.567);
- ::sprintf(expected, format, 1234.567);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%.2f', 1234.567 ==> '%.2f'\n";
- VMInspector::sprintf(actual, format, 1234.567);
- ::sprintf(expected, format, 1234.567);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%10.2f', 1234.567 ==> '%10.2f'\n";
- VMInspector::sprintf(actual, format, 1234.567);
- ::sprintf(expected, format, 1234.567);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%010.2f', 1234.567 ==> '%010.2f'\n";
- VMInspector::sprintf(actual, format, 1234.567);
- ::sprintf(expected, format, 1234.567);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- // Bad / weird formats:
- memset(actual, 'z', sizeof(actual));
- format = "'%%5.4', 987654321 ==> '%5.4'\n";
- VMInspector::sprintf(actual, format, 987654321);
- expectedLiteral = "'%5.4', 987654321 ==> 'ERROR @ \"%5.4' \"\n";
- ASSERT_EQ(strcmp(actual, expectedLiteral), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%5.4' '%%d', 987654321, 4 ==> '%5.4' '%d'\n";
- VMInspector::sprintf(actual, format, 987654321, 4);
- ::sprintf(expected, format, 987654321, 4);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%w' '%%d', 987654321, 6 ==> '%w' '%d'\n";
- VMInspector::sprintf(actual, format, 987654321, 6);
- ::sprintf(expected, format, 987654321, 6);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
-
- // Testing the %b extension:
- memset(actual, 'z', sizeof(actual));
- VMInspector::sprintf(actual, "'%%b', 0 ==> '%b'\n", 0);
- ASSERT_EQ(strcmp(actual, "'%b', 0 ==> 'FALSE'\n"), 0);
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::sprintf(actual, "'%%b', 1 ==> '%b'\n", 1);
- ASSERT_EQ(strcmp(actual, "'%b', 1 ==> 'TRUE'\n"), 0);
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::sprintf(actual, "'%%b', -123456789 ==> '%b'\n", -123456789);
- ASSERT_EQ(strcmp(actual, "'%b', -123456789 ==> 'TRUE'\n"), 0);
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::sprintf(actual, "'%%b', 123456789 ==> '%b'\n", 123456789);
- ASSERT_EQ(strcmp(actual, "'%b', 123456789 ==> 'TRUE'\n"), 0);
-
-
- // Testing the %J<x> extensions:
- String str1("Test WTF String");
- String str2("");
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::sprintf(actual, "'%%Js' is %%s, &str1, str1.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '%Js' is %s\n",
- &str1, str1.isEmpty() ? "EMPTY" : "NOT EMPTY");
- expectedLiteral = "'%Js' is %s, &str1, str1.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> 'Test WTF String' is NOT EMPTY\n";
- ASSERT_EQ(strcmp(actual, expectedLiteral), 0);
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::sprintf(actual, "'%%Js' is %%s, &str2, str2.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '%Js' is %s\n",
- &str2, str2.isEmpty() ? "EMPTY" : "NOT EMPTY");
- expectedLiteral = "'%Js' is %s, &str2, str2.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '' is EMPTY\n";
- ASSERT_EQ(strcmp(actual, expectedLiteral), 0);
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::sprintf(actual, "'%%J+s' is %%s, &str1, str1.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '%J+s' is %s\n",
- &str1, str1.isEmpty() ? "EMPTY" : "NOT EMPTY");
- expectedLiteral = "'%J+s' is %s, &str1, str1.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> 'WTF::String \"Test WTF String\"' is NOT EMPTY\n";
- ASSERT_EQ(strcmp(actual, expectedLiteral), 0);
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::sprintf(actual, "'%%J+s' is %%s, &str2, str2.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '%J+s' is %s\n",
- &str2, str2.isEmpty() ? "EMPTY" : "NOT EMPTY");
- expectedLiteral = "'%J+s' is %s, &str2, str2.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> 'WTF::String \"\"' is EMPTY\n";
- ASSERT_EQ(strcmp(actual, expectedLiteral), 0);
-#endif
-}
-
-
-TEST(JSC, VMInspectorSnprintf)
-{
-#if ENABLE(VMINSPECTOR)
- char actual[1024];
- char expected[1024];
- const char* format;
- const char* expectedLiteral;
-
- size_t size = 1;
- while (size <= 100) {
-
- // Testing standard default format specifiers:
- // Note: should work just like snprintf. So, we just compare against that.
- memset(actual, 'z', sizeof(actual));
- // The compiler warning flags are configured to expect a literal string for
- // ::snprintf below. So, use a #define for this one case to keep the
- // compiler happy.
-#undef LITERAL_FORMAT
-#define LITERAL_FORMAT "'%%%%' ==> '%%'\n"
- VMInspector::snprintf(actual, size, LITERAL_FORMAT);
- ::snprintf(expected, size, LITERAL_FORMAT);
-#undef LITERAL_FORMAT
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%c', 'x' ==> '%c'\n";
- VMInspector::snprintf(actual, size, format, 'x');
- ::snprintf(expected, size, format, 'x');
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%*c', 8, 'x' ==> '%*c'\n";
- VMInspector::snprintf(actual, size, format, 8, 'x');
- ::snprintf(expected, size, format, 8, 'x');
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%s', \"hello world\" ==> '%s'\n";
- VMInspector::snprintf(actual, size, format, "hello world");
- ::snprintf(expected, size, format, "hello world");
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%*s', 8, \"hello world\" ==> '%*s'\n";
- VMInspector::snprintf(actual, size, format, 8, "hello world");
- ::snprintf(expected, size, format, 8, "hello world");
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%*s', 8, \"hello\" ==> '%*s'\n";
- VMInspector::snprintf(actual, size, format, 8, "hello");
- ::snprintf(expected, size, format, 8, "hello");
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%d', 987654321 ==> '%d'\n";
- VMInspector::snprintf(actual, size, format, 987654321);
- ::snprintf(expected, size, format, 987654321);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%u', 4276543210u ==> '%u'\n";
- VMInspector::snprintf(actual, size, format, 4276543210u);
- ::snprintf(expected, size, format, 4276543210u);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%u', 0xffffffff ==> '%u'\n";
- VMInspector::snprintf(actual, size, format, 0xffffffff);
- ::snprintf(expected, size, format, 0xffffffff);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%x', 0xffffffff ==> '%x'\n";
- VMInspector::snprintf(actual, size, format, 0xffffffff);
- ::snprintf(expected, size, format, 0xffffffff);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%p', (void*)0xabcdbabe ==> '%p'\n";
- VMInspector::snprintf(actual, size, format, (void*)0xabcdbabe);
- ::snprintf(expected, size, format, (void*)0xabcdbabe);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%lu', 1234567890987654321ul ==> '%lu'\n";
- VMInspector::snprintf(actual, size, format, 1234567890987654321ul);
- ::snprintf(expected, size, format, 1234567890987654321ul);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%f', 1234.567 ==> '%f'\n";
- VMInspector::snprintf(actual, size, format, 1234.567);
- ::snprintf(expected, size, format, 1234.567);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%.2f', 1234.567 ==> '%.2f'\n";
- VMInspector::snprintf(actual, size, format, 1234.567);
- ::snprintf(expected, size, format, 1234.567);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%10.2f', 1234.567 ==> '%10.2f'\n";
- VMInspector::snprintf(actual, size, format, 1234.567);
- ::snprintf(expected, size, format, 1234.567);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%010.2f', 1234.567 ==> '%010.2f'\n";
- VMInspector::snprintf(actual, size, format, 1234.567);
- ::snprintf(expected, size, format, 1234.567);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- // Bad / weird formats:
- memset(actual, 'z', sizeof(actual));
- format = "'%%5.4', 987654321 ==> '%5.4'\n";
- VMInspector::snprintf(actual, size, format, 987654321);
- expectedLiteral = "'%5.4', 987654321 ==> 'ERROR @ \"%5.4' \"\n";
- ::snprintf(expected, size, "%s", expectedLiteral);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%5.4' '%%d', 987654321, 4 ==> '%5.4' '%d'\n";
- VMInspector::snprintf(actual, size, format, 987654321, 4);
- ::snprintf(expected, size, format, 987654321, 4);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%w' '%%d', 987654321, 6 ==> '%w' '%d'\n";
- VMInspector::snprintf(actual, size, format, 987654321, 6);
- ::snprintf(expected, size, format, 987654321, 6);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
-
- // Testing the %b extension:
- memset(actual, 'z', sizeof(actual));
- VMInspector::snprintf(actual, size, "'%%b', 0 ==> '%b'\n", 0);
- expectedLiteral = "'%b', 0 ==> 'FALSE'\n";
- ::snprintf(expected, size, "%s", expectedLiteral);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::snprintf(actual, size, "'%%b', 1 ==> '%b'\n", 1);
- expectedLiteral = "'%b', 1 ==> 'TRUE'\n";
- ::snprintf(expected, size, "%s", expectedLiteral);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::snprintf(actual, size, "'%%b', -123456789 ==> '%b'\n", -123456789);
- expectedLiteral = "'%b', -123456789 ==> 'TRUE'\n";
- ::snprintf(expected, size, "%s", expectedLiteral);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::snprintf(actual, size, "'%%b', 123456789 ==> '%b'\n", 123456789);
- expectedLiteral = "'%b', 123456789 ==> 'TRUE'\n";
- ::snprintf(expected, size, "%s", expectedLiteral);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- // Testing the %J<x> extensions:
- String str1("Test WTF String");
- String str2("");
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::snprintf(actual, size, "'%%Js' is %%s, &str1, str1.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '%Js' is %s\n",
- &str1, str1.isEmpty() ? "EMPTY" : "NOT EMPTY");
- expectedLiteral = "'%Js' is %s, &str1, str1.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> 'Test WTF String' is NOT EMPTY\n";
- ::snprintf(expected, size, "%s", expectedLiteral);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::snprintf(actual, size, "'%%Js' is %%s, &str2, str2.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '%Js' is %s\n",
- &str2, str2.isEmpty() ? "EMPTY" : "NOT EMPTY");
- expectedLiteral = "'%Js' is %s, &str2, str2.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '' is EMPTY\n";
- ::snprintf(expected, size, "%s", expectedLiteral);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::snprintf(actual, size, "'%%J+s' is %%s, &str1, str1.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '%J+s' is %s\n",
- &str1, str1.isEmpty() ? "EMPTY" : "NOT EMPTY");
- expectedLiteral = "'%J+s' is %s, &str1, str1.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> 'WTF::String \"Test WTF String\"' is NOT EMPTY\n";
- ::snprintf(expected, size, "%s", expectedLiteral);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::snprintf(actual, size, "'%%J+s' is %%s, &str2, str2.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '%J+s' is %s\n",
- &str2, str2.isEmpty() ? "EMPTY" : "NOT EMPTY");
- expectedLiteral = "'%J+s' is %s, &str2, str2.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> 'WTF::String \"\"' is EMPTY\n";
- ::snprintf(expected, size, "%s", expectedLiteral);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- // Test lower sizes more densely, and then space out to larger sizes.
- // We're doing this because the lower sizes might be interesting, but
- // for expediency, we don't want to test at this fine grain resolution
- // for all possible sizes. Hence, we accelerate the rate once we're
- // pass the interesting small sizes.
- if (size <= 5)
- size++;
- else
- size += 4;
- }
-#endif
-}
diff --git a/Tools/TestWebKitAPI/Tests/WTF/AtomicString.cpp b/Tools/TestWebKitAPI/Tests/WTF/AtomicString.cpp
index 9df71ce44..de962ec42 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/AtomicString.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/AtomicString.cpp
@@ -39,7 +39,6 @@ TEST(WTF, AtomicStringCreationFromLiteral)
const char* programmaticStringData = "Explicit Size Literal";
AtomicString programmaticString(programmaticStringData, strlen(programmaticStringData), AtomicString::ConstructFromLiteral);
ASSERT_EQ(strlen(programmaticStringData), programmaticString.length());
- ASSERT_TRUE(programmaticStringData == programmaticStringData);
ASSERT_TRUE(programmaticString.string().is8Bit());
ASSERT_EQ(programmaticStringData, reinterpret_cast<const char*>(programmaticString.string().characters8()));
}
@@ -54,4 +53,12 @@ TEST(WTF, AtomicStringCreationFromLiteralUniqueness)
ASSERT_EQ(string1.impl(), string3.impl());
}
+TEST(WTF, AtomicStringExistingHash)
+{
+ AtomicString string1("Template Literal", AtomicString::ConstructFromLiteral);
+ ASSERT_EQ(string1.existingHash(), string1.impl()->existingHash());
+ AtomicString string2;
+ ASSERT_EQ(string2.existingHash(), 0u);
+}
+
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/BloomFilter.cpp b/Tools/TestWebKitAPI/Tests/WTF/BloomFilter.cpp
new file mode 100644
index 000000000..802165211
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/BloomFilter.cpp
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "config.h"
+
+#include <wtf/BloomFilter.h>
+#include <wtf/RandomNumber.h>
+#include <wtf/SHA1.h>
+
+namespace TestWebKitAPI {
+
+static Vector<unsigned> generateRandomHashes(size_t hashCount)
+{
+ Vector<unsigned> hashes;
+ for (unsigned i = 0; i < hashCount; ++i)
+ hashes.append(static_cast<unsigned>(randomNumber() * std::numeric_limits<unsigned>::max()));
+ return hashes;
+}
+
+static Vector<SHA1::Digest> generateRandomDigests(size_t hashCount)
+{
+ Vector<SHA1::Digest> hashes;
+ SHA1 sha1;
+ for (unsigned i = 0; i < hashCount; ++i) {
+ double random = randomNumber();
+ sha1.addBytes(reinterpret_cast<uint8_t*>(&random), sizeof(double));
+ SHA1::Digest digest;
+ sha1.computeHash(digest);
+ hashes.append(digest);
+ }
+ return hashes;
+}
+
+TEST(WTF_BloomFilter, Basic)
+{
+ const unsigned hashCount = 1000;
+ auto hashes = generateRandomHashes(hashCount);
+
+ BloomFilter<16> filter;
+ for (auto hash : hashes)
+ filter.add(hash);
+
+ for (auto hash : hashes)
+ EXPECT_TRUE(filter.mayContain(hash));
+
+ auto moreHashes = generateRandomHashes(hashCount);
+ unsigned mayContainCount = 0;
+ for (auto hash : moreHashes)
+ mayContainCount += filter.mayContain(hash) ? 1 : 0;
+ // False positive rate is ~0.09% so this should always be true.
+ EXPECT_TRUE(mayContainCount < hashCount / 10);
+
+ for (auto hash : moreHashes)
+ filter.add(hash);
+
+ for (auto hash : hashes)
+ EXPECT_TRUE(filter.mayContain(hash));
+ for (auto hash : moreHashes)
+ EXPECT_TRUE(filter.mayContain(hash));
+}
+
+TEST(WTF_BloomFilter, BasicDigest)
+{
+ const unsigned hashCount = 1000;
+ auto hashes = generateRandomDigests(hashCount);
+
+ BloomFilter<20> filter;
+ for (auto hash : hashes)
+ filter.add(hash);
+
+ for (auto hash : hashes)
+ EXPECT_TRUE(filter.mayContain(hash));
+
+ auto moreHashes = generateRandomDigests(hashCount);
+ unsigned mayContainCount = 0;
+ for (auto hash : moreHashes)
+ mayContainCount += filter.mayContain(hash) ? 1 : 0;
+ // False positive rate is ~0.000004% so this should always be true.
+ EXPECT_TRUE(mayContainCount < hashCount / 10);
+
+ for (auto hash : moreHashes)
+ filter.add(hash);
+
+ for (auto hash : hashes)
+ EXPECT_TRUE(filter.mayContain(hash));
+ for (auto hash : moreHashes)
+ EXPECT_TRUE(filter.mayContain(hash));
+}
+
+TEST(WTF_BloomFilter, BasicCounting)
+{
+ const unsigned hashCount = 1000;
+ auto hashes = generateRandomHashes(hashCount);
+
+ CountingBloomFilter<16> filter;
+ for (auto hash : hashes)
+ filter.add(hash);
+
+ for (auto hash : hashes)
+ EXPECT_TRUE(filter.mayContain(hash));
+
+ for (auto hash : hashes)
+ filter.add(hash);
+
+ for (auto hash : hashes)
+ EXPECT_TRUE(filter.mayContain(hash));
+
+ for (auto hash : hashes)
+ filter.remove(hash);
+
+ for (auto hash : hashes)
+ EXPECT_TRUE(filter.mayContain(hash));
+
+ auto moreHashes = generateRandomHashes(hashCount);
+ unsigned mayContainCount = 0;
+ for (auto hash : moreHashes)
+ mayContainCount += filter.mayContain(hash) ? 1 : 0;
+ // False positive rate is ~0.09% so this should always be true.
+ EXPECT_TRUE(mayContainCount < hashCount / 10);
+
+ for (auto hash : moreHashes)
+ filter.add(hash);
+ for (auto hash : hashes)
+ filter.remove(hash);
+
+ for (auto hash : moreHashes)
+ EXPECT_TRUE(filter.mayContain(hash));
+
+ for (auto hash : moreHashes)
+ filter.remove(hash);
+
+ for (auto hash : hashes)
+ EXPECT_TRUE(!filter.mayContain(hash));
+ for (auto hash : moreHashes)
+ EXPECT_TRUE(!filter.mayContain(hash));
+}
+
+TEST(WTF_BloomFilter, Clear)
+{
+ const unsigned hashCount = 1000;
+ auto hashes = generateRandomHashes(hashCount);
+
+ BloomFilter<16> filter;
+ for (auto hash : hashes)
+ filter.add(hash);
+
+ filter.clear();
+
+ for (auto hash : hashes)
+ EXPECT_TRUE(!filter.mayContain(hash));
+}
+
+TEST(WTF_BloomFilter, ClearCounting)
+{
+ const unsigned hashCount = 1000;
+ auto hashes = generateRandomHashes(hashCount);
+
+ CountingBloomFilter<16> filter;
+ for (auto hash : hashes)
+ filter.add(hash);
+ for (auto hash : hashes)
+ filter.add(hash);
+
+ filter.clear();
+
+ for (auto hash : hashes)
+ EXPECT_TRUE(!filter.mayContain(hash));
+}
+
+TEST(WTF_BloomFilter, CountingOverflow)
+{
+ const unsigned hashCount = 1000;
+ auto hashes = generateRandomHashes(hashCount);
+
+ CountingBloomFilter<16> filter;
+ for (auto hash : hashes)
+ filter.add(hash);
+
+ for (unsigned i = 0; i < filter.maximumCount() + 100; ++i)
+ filter.add(hashes[0]);
+
+ for (auto hash : hashes)
+ EXPECT_TRUE(filter.mayContain(hash));
+
+ for (auto hash : hashes)
+ filter.remove(hash);
+
+ unsigned mayContainCount = 0;
+ for (auto hash : hashes) {
+ if (hash == hashes[0])
+ EXPECT_TRUE(filter.mayContain(hash));
+ else
+ mayContainCount += filter.mayContain(hash) ? 1 : 0;
+ }
+ // False positive rate should be very low.
+ EXPECT_TRUE(mayContainCount < hashCount / 100);
+
+ for (unsigned i = 0; i < filter.maximumCount() + 100; ++i)
+ filter.remove(hashes[0]);
+
+ // The bucket has overflowed and is stuck.
+ EXPECT_TRUE(filter.mayContain(hashes[0]));
+}
+
+TEST(WTF_BloomFilter, Combine)
+{
+ const unsigned hashCount = 1000;
+ auto hashes = generateRandomHashes(hashCount);
+
+ BloomFilter<16> filter;
+ for (auto hash : hashes)
+ filter.add(hash);
+
+ auto moreHashes = generateRandomHashes(hashCount);
+
+ BloomFilter<16> anotherFilter;
+ for (auto hash : moreHashes)
+ anotherFilter.add(hash);
+
+ filter.add(anotherFilter);
+
+ for (auto hash : hashes)
+ EXPECT_TRUE(filter.mayContain(hash));
+ for (auto hash : moreHashes)
+ EXPECT_TRUE(filter.mayContain(hash));
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WTF/CheckedArithmeticOperations.cpp b/Tools/TestWebKitAPI/Tests/WTF/CheckedArithmeticOperations.cpp
index 77b8ff458..d6b548316 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/CheckedArithmeticOperations.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/CheckedArithmeticOperations.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 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
@@ -28,117 +28,397 @@
namespace TestWebKitAPI {
-#define CheckedArithmeticTest(type, coerceLiteral, MixedSignednessTest) \
+class OverflowCrashLogger {
+protected:
+ void overflowed()
+ {
+ m_overflowCount++;
+ }
+
+ void clearOverflow()
+ {
+ m_overflowCount = 0;
+ }
+
+ static void crash()
+ {
+ s_didCrash = true;
+ }
+
+public:
+ void reset()
+ {
+ m_overflowCount = 0;
+ s_didCrash = false;
+ }
+
+ bool hasOverflowed() const { return m_overflowCount > 0; }
+ int overflowCount() const { return m_overflowCount; }
+
+ bool didCrash() const { return s_didCrash; }
+
+private:
+ int m_overflowCount { 0 };
+ static bool s_didCrash;
+};
+
+bool OverflowCrashLogger::s_didCrash = false;
+
+template <typename type>
+static void resetOverflow(Checked<type, OverflowCrashLogger>& value)
+{
+ value.reset();
+ value = 100;
+ value *= std::numeric_limits<type>::max();
+}
+
+#define CheckedArithmeticTest(type, Coercer, MixedSignednessTester) \
TEST(WTF, Checked_##type) \
{ \
- Checked<type, RecordOverflow> value; \
- EXPECT_EQ(coerceLiteral(0), value.unsafeGet()); \
- EXPECT_EQ(std::numeric_limits<type>::max(), (value + std::numeric_limits<type>::max()).unsafeGet()); \
- EXPECT_EQ(std::numeric_limits<type>::max(), (std::numeric_limits<type>::max() + value).unsafeGet()); \
- EXPECT_EQ(std::numeric_limits<type>::min(), (value + std::numeric_limits<type>::min()).unsafeGet()); \
- EXPECT_EQ(std::numeric_limits<type>::min(), (std::numeric_limits<type>::min() + value).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(0), (value * coerceLiteral(0)).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(0), (coerceLiteral(0) * value).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(0), (value * value).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(0), (value - coerceLiteral(0)).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(0), (coerceLiteral(0) - value).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(0), (value - value).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(0), (value++).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(1), (value--).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(1), (++value).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(0), (--value).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(10), (value += coerceLiteral(10)).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(10), value.unsafeGet()); \
- EXPECT_EQ(coerceLiteral(100), (value *= coerceLiteral(10)).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(100), value.unsafeGet()); \
- EXPECT_EQ(coerceLiteral(0), (value -= coerceLiteral(100)).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(0), value.unsafeGet()); \
- value = 10; \
- EXPECT_EQ(coerceLiteral(10), value.unsafeGet()); \
- EXPECT_EQ(coerceLiteral(0), (value - coerceLiteral(10)).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(10), value.unsafeGet()); \
- value = std::numeric_limits<type>::min(); \
- EXPECT_EQ(true, (Checked<type, RecordOverflow>(value - coerceLiteral(1))).hasOverflowed()); \
- EXPECT_EQ(true, !((value--).hasOverflowed())); \
- EXPECT_EQ(true, value.hasOverflowed()); \
- value = std::numeric_limits<type>::max(); \
- EXPECT_EQ(true, !value.hasOverflowed()); \
- EXPECT_EQ(true, (Checked<type, RecordOverflow>(value + coerceLiteral(1))).hasOverflowed()); \
- EXPECT_EQ(true, !(value++).hasOverflowed()); \
- EXPECT_EQ(true, value.hasOverflowed()); \
- value = std::numeric_limits<type>::max(); \
- EXPECT_EQ(true, (value += coerceLiteral(1)).hasOverflowed()); \
- EXPECT_EQ(true, value.hasOverflowed()); \
- value = 10; \
- type _value = 0; \
- EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(0)).safeGet(_value)); \
- _value = 0; \
- EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(0) * value).safeGet(_value)); \
- _value = 0; \
- EXPECT_EQ(true, CheckedState::DidOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); \
- _value = 0; \
- EXPECT_EQ(true, CheckedState::DidOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * value).safeGet(_value)); \
- value = 0; \
- _value = 0; \
- EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); \
- _value = 0; \
- EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * value).safeGet(_value)); \
- value = 1; \
- _value = 0; \
- EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); \
- _value = 0; \
- EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * value).safeGet(_value)); \
- _value = 0; \
- value = 0; \
- EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); \
- _value = 0; \
- EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * (type)0).safeGet(_value)); \
- _value = 0; \
- value = 1; \
- EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); \
- _value = 0; \
- EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * (type)1).safeGet(_value)); \
- _value = 0; \
- value = 2; \
- EXPECT_EQ(true, CheckedState::DidOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); \
- _value = 0; \
- EXPECT_EQ(true, CheckedState::DidOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * (type)2).safeGet(_value)); \
- value = 10; \
- EXPECT_EQ(true, (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).hasOverflowed()); \
- MixedSignednessTest(EXPECT_EQ(coerceLiteral(0), (value + -10).unsafeGet())); \
- MixedSignednessTest(EXPECT_EQ(0U, (value - 10U).unsafeGet())); \
- MixedSignednessTest(EXPECT_EQ(coerceLiteral(0), (-10 + value).unsafeGet())); \
- MixedSignednessTest(EXPECT_EQ(0U, (10U - value).unsafeGet())); \
- value = std::numeric_limits<type>::min(); \
- MixedSignednessTest(EXPECT_EQ(true, (Checked<type, RecordOverflow>(value - 1)).hasOverflowed())); \
- MixedSignednessTest(EXPECT_EQ(true, !(value--).hasOverflowed())); \
- MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \
- value = std::numeric_limits<type>::max(); \
- MixedSignednessTest(EXPECT_EQ(true, !value.hasOverflowed())); \
- MixedSignednessTest(EXPECT_EQ(true, (Checked<type, RecordOverflow>(value + 1)).hasOverflowed())); \
- MixedSignednessTest(EXPECT_EQ(true, !(value++).hasOverflowed())); \
- MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \
- value = std::numeric_limits<type>::max(); \
- MixedSignednessTest(EXPECT_EQ(true, (value += 1).hasOverflowed())); \
- MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \
- value = std::numeric_limits<type>::min(); \
- MixedSignednessTest(EXPECT_EQ(true, (value - 1U).hasOverflowed())); \
- MixedSignednessTest(EXPECT_EQ(true, !(value--).hasOverflowed())); \
- MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \
- value = std::numeric_limits<type>::max(); \
- MixedSignednessTest(EXPECT_EQ(true, !value.hasOverflowed())); \
- MixedSignednessTest(EXPECT_EQ(true, (Checked<type, RecordOverflow>(value + 1U)).hasOverflowed())); \
- MixedSignednessTest(EXPECT_EQ(true, !(value++).hasOverflowed())); \
- MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \
- value = std::numeric_limits<type>::max(); \
- MixedSignednessTest(EXPECT_EQ(true, (value += 1U).hasOverflowed())); \
- MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \
+ typedef Coercer<type> CoercerType; \
+ typedef MixedSignednessTester<type, CoercerType> MixedSignednessTesterType; \
+ CheckedArithmeticTester<type, CoercerType, MixedSignednessTesterType>::run(); \
}
+
+#define coerceLiteral(x) Coercer::coerce(x)
+
+template <typename type, typename Coercer, typename MixedSignednessTester>
+class CheckedArithmeticTester {
+public:
+ static void run()
+ {
+ Checked<type, RecordOverflow> value;
+ EXPECT_EQ(coerceLiteral(0), value.unsafeGet());
+ EXPECT_EQ(std::numeric_limits<type>::max(), (value + std::numeric_limits<type>::max()).unsafeGet());
+ EXPECT_EQ(std::numeric_limits<type>::max(), (std::numeric_limits<type>::max() + value).unsafeGet());
+ EXPECT_EQ(std::numeric_limits<type>::min(), (value + std::numeric_limits<type>::min()).unsafeGet());
+ EXPECT_EQ(std::numeric_limits<type>::min(), (std::numeric_limits<type>::min() + value).unsafeGet());
+
+ EXPECT_EQ(coerceLiteral(0), (value * coerceLiteral(0)).unsafeGet());
+ EXPECT_EQ(coerceLiteral(0), (coerceLiteral(0) * value).unsafeGet());
+ EXPECT_EQ(coerceLiteral(0), (value * value).unsafeGet());
+ EXPECT_EQ(coerceLiteral(0), (value - coerceLiteral(0)).unsafeGet());
+ EXPECT_EQ(coerceLiteral(0), (coerceLiteral(0) - value).unsafeGet());
+ EXPECT_EQ(coerceLiteral(0), (value - value).unsafeGet());
+ EXPECT_EQ(coerceLiteral(0), (value++).unsafeGet());
+ EXPECT_EQ(coerceLiteral(1), (value--).unsafeGet());
+ EXPECT_EQ(coerceLiteral(1), (++value).unsafeGet());
+ EXPECT_EQ(coerceLiteral(0), (--value).unsafeGet());
+ EXPECT_EQ(coerceLiteral(10), (value += coerceLiteral(10)).unsafeGet());
+ EXPECT_EQ(coerceLiteral(10), value.unsafeGet());
+ EXPECT_EQ(coerceLiteral(100), (value *= coerceLiteral(10)).unsafeGet());
+ EXPECT_EQ(coerceLiteral(100), value.unsafeGet());
+ EXPECT_EQ(coerceLiteral(0), (value -= coerceLiteral(100)).unsafeGet());
+ EXPECT_EQ(coerceLiteral(0), value.unsafeGet());
+ value = 10;
+ EXPECT_EQ(coerceLiteral(10), value.unsafeGet());
+ EXPECT_EQ(coerceLiteral(0), (value - coerceLiteral(10)).unsafeGet());
+ EXPECT_EQ(coerceLiteral(10), value.unsafeGet());
+
+ value = std::numeric_limits<type>::min();
+ EXPECT_EQ(true, (Checked<type, RecordOverflow>(value - coerceLiteral(1))).hasOverflowed());
+ EXPECT_EQ(true, !((value--).hasOverflowed()));
+ EXPECT_EQ(true, value.hasOverflowed());
+ value = std::numeric_limits<type>::max();
+ EXPECT_EQ(true, !value.hasOverflowed());
+ EXPECT_EQ(true, (Checked<type, RecordOverflow>(value + coerceLiteral(1))).hasOverflowed());
+ EXPECT_EQ(true, !(value++).hasOverflowed());
+ EXPECT_EQ(true, value.hasOverflowed());
+ value = std::numeric_limits<type>::max();
+ EXPECT_EQ(true, (value += coerceLiteral(1)).hasOverflowed());
+ EXPECT_EQ(true, value.hasOverflowed());
+
+ value = 10;
+ type _value = 0;
+ EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(0)).safeGet(_value));
+ _value = 0;
+ EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(0) * value).safeGet(_value));
+ _value = 0;
+ EXPECT_EQ(true, CheckedState::DidOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value));
+ _value = 0;
+ EXPECT_EQ(true, CheckedState::DidOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * value).safeGet(_value));
+ value = 0;
+ _value = 0;
+ EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value));
+ _value = 0;
+ EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * value).safeGet(_value));
+ value = 1;
+ _value = 0;
+ EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value));
+ _value = 0;
+ EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * value).safeGet(_value));
+ _value = 0;
+ value = 0;
+ EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value));
+ _value = 0;
+ EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * (type)0).safeGet(_value));
+ _value = 0;
+ value = 1;
+ EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value));
+ _value = 0;
+ EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * (type)1).safeGet(_value));
+ _value = 0;
+ value = 2;
+ EXPECT_EQ(true, CheckedState::DidOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value));
+ _value = 0;
+ EXPECT_EQ(true, CheckedState::DidOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * (type)2).safeGet(_value));
+ value = 10;
+ EXPECT_EQ(true, (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).hasOverflowed());
+
+
+ Checked<type, OverflowCrashLogger> nvalue; // to hold a not overflowed value.
+ Checked<type, OverflowCrashLogger> ovalue; // to hold an overflowed value.
+ bool unused;
+
+ _value = 75;
+ type _largeValue = 100;
+ type _smallValue = 50;
+
+ value = _smallValue;
+ nvalue = _value;
+ ovalue = _value;
+
+ // Make sure the OverflowCrashLogger is working as expected.
+ EXPECT_EQ(false, (ovalue.hasOverflowed()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), ovalue.hasOverflowed()));
+ EXPECT_EQ(false, (resetOverflow(ovalue), ovalue.didCrash()));
+ EXPECT_EQ(true, (unused = (ovalue == ovalue), ovalue.didCrash()));
+ EXPECT_EQ(false, (resetOverflow(ovalue), ovalue.didCrash()));
+
+ EXPECT_EQ(false, nvalue.hasOverflowed());
+ EXPECT_EQ(false, nvalue.didCrash());
+
+ // Test operator== that should not overflow nor crash.
+ EXPECT_EQ(true, (nvalue == nvalue));
+ EXPECT_EQ(true, (nvalue == Checked<type, OverflowCrashLogger>(_value)));
+ EXPECT_EQ(false, (nvalue == value));
+ EXPECT_EQ(true, (nvalue == _value));
+ EXPECT_EQ(false, (nvalue == Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())));
+ EXPECT_EQ(false, (nvalue == std::numeric_limits<type>::max()));
+
+ EXPECT_EQ(false, nvalue.hasOverflowed());
+ EXPECT_EQ(false, nvalue.didCrash());
+
+ // Test operator!= that should not overflow nor crash.
+ EXPECT_EQ(false, (nvalue != nvalue));
+ EXPECT_EQ(false, (nvalue != Checked<type, OverflowCrashLogger>(_value)));
+ EXPECT_EQ(true, (nvalue != value));
+ EXPECT_EQ(false, (nvalue != _value));
+ EXPECT_EQ(true, (nvalue != Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())));
+ EXPECT_EQ(true, (nvalue != std::numeric_limits<type>::max()));
+
+ EXPECT_EQ(false, nvalue.hasOverflowed());
+ EXPECT_EQ(false, nvalue.didCrash());
+
+ // Test operator< that should not overflow nor crash.
+ EXPECT_EQ(false, (nvalue < nvalue));
+ EXPECT_EQ(false, (nvalue < value));
+ EXPECT_EQ(true, (nvalue < Checked<type, OverflowCrashLogger>(_largeValue)));
+ EXPECT_EQ(false, (nvalue < Checked<type, OverflowCrashLogger>(_value)));
+ EXPECT_EQ(false, (nvalue < Checked<type, OverflowCrashLogger>(_smallValue)));
+ EXPECT_EQ(true, (nvalue < _largeValue));
+ EXPECT_EQ(false, (nvalue < _value));
+ EXPECT_EQ(false, (nvalue < _smallValue));
+ EXPECT_EQ(true, (nvalue < Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())));
+ EXPECT_EQ(true, (nvalue < std::numeric_limits<type>::max()));
+
+ EXPECT_EQ(false, nvalue.hasOverflowed());
+ EXPECT_EQ(false, nvalue.didCrash());
+
+ // Test operator<= that should not overflow nor crash.
+ EXPECT_EQ(true, (nvalue <= nvalue));
+ EXPECT_EQ(false, (nvalue <= value));
+ EXPECT_EQ(true, (nvalue <= Checked<type, OverflowCrashLogger>(_largeValue)));
+ EXPECT_EQ(true, (nvalue <= Checked<type, OverflowCrashLogger>(_value)));
+ EXPECT_EQ(false, (nvalue <= Checked<type, OverflowCrashLogger>(_smallValue)));
+ EXPECT_EQ(true, (nvalue <= _largeValue));
+ EXPECT_EQ(true, (nvalue <= _value));
+ EXPECT_EQ(false, (nvalue <= _smallValue));
+ EXPECT_EQ(true, (nvalue <= Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())));
+ EXPECT_EQ(true, (nvalue <= std::numeric_limits<type>::max()));
+
+ EXPECT_EQ(false, nvalue.hasOverflowed());
+ EXPECT_EQ(false, nvalue.didCrash());
+
+ // Test operator> that should not overflow nor crash.
+ EXPECT_EQ(false, (nvalue > nvalue));
+ EXPECT_EQ(true, (nvalue > value));
+ EXPECT_EQ(false, (nvalue > Checked<type, OverflowCrashLogger>(_largeValue)));
+ EXPECT_EQ(false, (nvalue > Checked<type, OverflowCrashLogger>(_value)));
+ EXPECT_EQ(true, (nvalue > Checked<type, OverflowCrashLogger>(_smallValue)));
+ EXPECT_EQ(false, (nvalue > _largeValue));
+ EXPECT_EQ(false, (nvalue > _value));
+ EXPECT_EQ(true, (nvalue > _smallValue));
+ EXPECT_EQ(false, (nvalue > Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())));
+ EXPECT_EQ(false, (nvalue > std::numeric_limits<type>::max()));
+
+ EXPECT_EQ(false, nvalue.hasOverflowed());
+ EXPECT_EQ(false, nvalue.didCrash());
+
+ // Test operator>= that should not overflow nor crash.
+ EXPECT_EQ(true, (nvalue >= nvalue));
+ EXPECT_EQ(true, (nvalue >= value));
+ EXPECT_EQ(false, (nvalue >= Checked<type, OverflowCrashLogger>(_largeValue)));
+ EXPECT_EQ(true, (nvalue >= Checked<type, OverflowCrashLogger>(_value)));
+ EXPECT_EQ(true, (nvalue >= Checked<type, OverflowCrashLogger>(_smallValue)));
+ EXPECT_EQ(false, (nvalue >= _largeValue));
+ EXPECT_EQ(true, (nvalue >= _value));
+ EXPECT_EQ(true, (nvalue >= _smallValue));
+ EXPECT_EQ(false, (nvalue >= Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())));
+ EXPECT_EQ(false, (nvalue >= std::numeric_limits<type>::max()));
+
+ EXPECT_EQ(false, nvalue.hasOverflowed());
+ EXPECT_EQ(false, nvalue.didCrash());
+
+ // Test operator== with an overflowed value.
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue == ovalue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue == Checked<type, OverflowCrashLogger>(_value)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue == value), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue == _value), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue == _value * std::numeric_limits<type>::max()), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue == Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue == std::numeric_limits<type>::max()), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue == nvalue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (nvalue == ovalue), ovalue.didCrash()));
+
+ EXPECT_EQ(false, nvalue.hasOverflowed());
+
+ // Test operator!= with an overflowed value.
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue != ovalue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue != Checked<type, OverflowCrashLogger>(_value)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue != value), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue != _value), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue != _value * std::numeric_limits<type>::max()), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue != Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue != std::numeric_limits<type>::max()), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue != nvalue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (nvalue != ovalue), ovalue.didCrash()));
+
+ EXPECT_EQ(false, nvalue.hasOverflowed());
+
+ // Test operator< with an overflowed value.
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < ovalue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < value), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < Checked<type, OverflowCrashLogger>(_largeValue)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < Checked<type, OverflowCrashLogger>(_value)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < Checked<type, OverflowCrashLogger>(_smallValue)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < _largeValue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < _value), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < _smallValue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < std::numeric_limits<type>::max()), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < nvalue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (nvalue < ovalue), ovalue.didCrash()));
+
+ EXPECT_EQ(false, nvalue.hasOverflowed());
+
+ // Test operator<= with an overflowed value.
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= ovalue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= value), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= Checked<type, OverflowCrashLogger>(_largeValue)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= Checked<type, OverflowCrashLogger>(_value)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= Checked<type, OverflowCrashLogger>(_smallValue)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= _largeValue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= _value), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= _smallValue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= std::numeric_limits<type>::max()), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= nvalue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (nvalue <= ovalue), ovalue.didCrash()));
+
+ EXPECT_EQ(false, nvalue.hasOverflowed());
+
+ // Test operator> with an overflowed value.
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > ovalue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > value), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > Checked<type, OverflowCrashLogger>(_largeValue)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > Checked<type, OverflowCrashLogger>(_value)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > Checked<type, OverflowCrashLogger>(_smallValue)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > _largeValue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > _value), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > _smallValue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > std::numeric_limits<type>::max()), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > nvalue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (nvalue > ovalue), ovalue.didCrash()));
+
+ EXPECT_EQ(false, nvalue.hasOverflowed());
+
+ // Test operator>= with an overflowed value.
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= ovalue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= value), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= Checked<type, OverflowCrashLogger>(_largeValue)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= Checked<type, OverflowCrashLogger>(_value)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= Checked<type, OverflowCrashLogger>(_smallValue)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= _largeValue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= _value), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= _smallValue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= std::numeric_limits<type>::max()), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= nvalue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (nvalue >= ovalue), ovalue.didCrash()));
+
+ EXPECT_EQ(false, nvalue.hasOverflowed());
+
+ MixedSignednessTester::run();
+ }
+};
+
+template <typename type, typename Coercer>
+class AllowMixedSignednessTest {
+public:
+ static void run()
+ {
+ Checked<type, RecordOverflow> value;
+ value = 10;
+
+ EXPECT_EQ(coerceLiteral(0), (value + -10).unsafeGet());
+ EXPECT_EQ(0U, (value - 10U).unsafeGet());
+ EXPECT_EQ(coerceLiteral(0), (-10 + value).unsafeGet());
+ EXPECT_EQ(0U, (10U - value).unsafeGet());
+ value = std::numeric_limits<type>::min();
+ EXPECT_EQ(true, (Checked<type, RecordOverflow>(value - 1)).hasOverflowed());
+ EXPECT_EQ(true, !(value--).hasOverflowed());
+ EXPECT_EQ(true, value.hasOverflowed());
+ value = std::numeric_limits<type>::max();
+ EXPECT_EQ(true, !value.hasOverflowed());
+ EXPECT_EQ(true, (Checked<type, RecordOverflow>(value + 1)).hasOverflowed());
+ EXPECT_EQ(true, !(value++).hasOverflowed());
+ EXPECT_EQ(true, value.hasOverflowed());
+ value = std::numeric_limits<type>::max();
+ EXPECT_EQ(true, (value += 1).hasOverflowed());
+ EXPECT_EQ(true, value.hasOverflowed());
+ value = std::numeric_limits<type>::min();
+ EXPECT_EQ(true, (value - 1U).hasOverflowed());
+ EXPECT_EQ(true, !(value--).hasOverflowed());
+ EXPECT_EQ(true, value.hasOverflowed());
+ value = std::numeric_limits<type>::max();
+ EXPECT_EQ(true, !value.hasOverflowed());
+ EXPECT_EQ(true, (Checked<type, RecordOverflow>(value + 1U)).hasOverflowed());
+ EXPECT_EQ(true, !(value++).hasOverflowed());
+ EXPECT_EQ(true, value.hasOverflowed());
+ value = std::numeric_limits<type>::max();
+ EXPECT_EQ(true, (value += 1U).hasOverflowed());
+ EXPECT_EQ(true, value.hasOverflowed());
+ }
+};
+
+template <typename type, typename Coercer>
+class IgnoreMixedSignednessTest {
+public:
+ static void run() { }
+};
+
+template <typename type> class CoerceLiteralToUnsigned {
+public:
+ static unsigned coerce(type x) { return static_cast<unsigned>(x); }
+};
+
+template <typename type> class CoerceLiteralNop {
+public:
+ static type coerce(type x) { return x; }
+};
-#define CoerceLiteralToUnsigned(x) x##U
-#define CoerceLiteralNop(x) x
-#define AllowMixedSignednessTest(x) x
-#define IgnoreMixedSignednessTest(x)
CheckedArithmeticTest(int8_t, CoerceLiteralNop, IgnoreMixedSignednessTest)
CheckedArithmeticTest(int16_t, CoerceLiteralNop, IgnoreMixedSignednessTest)
CheckedArithmeticTest(int32_t, CoerceLiteralNop, AllowMixedSignednessTest)
@@ -146,4 +426,62 @@ CheckedArithmeticTest(uint32_t, CoerceLiteralToUnsigned, AllowMixedSignednessTes
CheckedArithmeticTest(int64_t, CoerceLiteralNop, IgnoreMixedSignednessTest)
CheckedArithmeticTest(uint64_t, CoerceLiteralToUnsigned, IgnoreMixedSignednessTest)
+TEST(CheckedArithmeticTest, IsInBounds)
+{
+ // bigger precision, signed, signed
+ EXPECT_TRUE(WTF::isInBounds<int32_t>(std::numeric_limits<int16_t>::max()));
+ EXPECT_TRUE(WTF::isInBounds<int32_t>(std::numeric_limits<int16_t>::min()));
+
+ // bigger precision, unsigned, signed
+ EXPECT_TRUE(WTF::isInBounds<uint32_t>(std::numeric_limits<int32_t>::max()));
+ EXPECT_FALSE(WTF::isInBounds<uint32_t>(std::numeric_limits<int16_t>::min()));
+
+ EXPECT_FALSE(WTF::isInBounds<uint32_t>((int32_t)-1));
+ EXPECT_FALSE(WTF::isInBounds<uint16_t>((int32_t)-1));
+ EXPECT_FALSE(WTF::isInBounds<unsigned long>((int)-1));
+
+ EXPECT_TRUE(WTF::isInBounds<uint32_t>((int32_t)1));
+ EXPECT_TRUE(WTF::isInBounds<uint32_t>((int16_t)1));
+ EXPECT_TRUE(WTF::isInBounds<unsigned>((int)1));
+
+ EXPECT_TRUE(WTF::isInBounds<uint32_t>((int32_t)0));
+ EXPECT_TRUE(WTF::isInBounds<uint16_t>((int32_t)0));
+ EXPECT_TRUE(WTF::isInBounds<uint32_t>((int16_t)0));
+ EXPECT_TRUE(WTF::isInBounds<unsigned>((int)0));
+
+ EXPECT_TRUE(WTF::isInBounds<uint32_t>(std::numeric_limits<int32_t>::max()));
+ EXPECT_TRUE(WTF::isInBounds<uint32_t>(std::numeric_limits<int16_t>::max()));
+ EXPECT_TRUE(WTF::isInBounds<unsigned>(std::numeric_limits<int>::max()));
+
+ // bigger precision, signed, unsigned
+ EXPECT_TRUE(WTF::isInBounds<int32_t>(std::numeric_limits<uint16_t>::max()));
+ EXPECT_FALSE(WTF::isInBounds<int32_t>(std::numeric_limits<uint32_t>::max()));
+ EXPECT_TRUE(WTF::isInBounds<int32_t>((uint32_t)0));
+
+ // bigger precision, unsigned, unsigned
+ EXPECT_TRUE(WTF::isInBounds<uint32_t>(std::numeric_limits<uint16_t>::max()));
+ EXPECT_TRUE(WTF::isInBounds<uint32_t>(std::numeric_limits<uint16_t>::min()));
+
+ // lower precision, signed signed
+ EXPECT_FALSE(WTF::isInBounds<int16_t>(std::numeric_limits<int32_t>::max()));
+ EXPECT_FALSE(WTF::isInBounds<int16_t>(std::numeric_limits<int32_t>::min()));
+ EXPECT_TRUE(WTF::isInBounds<int16_t>((int32_t)-1));
+ EXPECT_TRUE(WTF::isInBounds<int16_t>((int32_t)0));
+ EXPECT_TRUE(WTF::isInBounds<int16_t>((int32_t)1));
+ // lower precision, unsigned, signed
+ EXPECT_FALSE(WTF::isInBounds<uint16_t>(std::numeric_limits<int32_t>::max()));
+ EXPECT_FALSE(WTF::isInBounds<uint16_t>(std::numeric_limits<int32_t>::min()));
+ EXPECT_FALSE(WTF::isInBounds<uint16_t>((int32_t)-1));
+ EXPECT_TRUE(WTF::isInBounds<uint16_t>((int32_t)0));
+ EXPECT_TRUE(WTF::isInBounds<uint16_t>((int32_t)1));
+ // lower precision, signed, unsigned
+ EXPECT_FALSE(WTF::isInBounds<int16_t>(std::numeric_limits<uint32_t>::max()));
+ EXPECT_TRUE(WTF::isInBounds<int16_t>((uint32_t)0));
+ EXPECT_TRUE(WTF::isInBounds<int16_t>((uint32_t)1));
+ // lower precision, unsigned, unsigned
+ EXPECT_FALSE(WTF::isInBounds<uint16_t>(std::numeric_limits<uint32_t>::max()));
+ EXPECT_TRUE(WTF::isInBounds<uint16_t>((uint32_t)0));
+ EXPECT_TRUE(WTF::isInBounds<uint16_t>((uint32_t)1));
+}
+
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/Condition.cpp b/Tools/TestWebKitAPI/Tests/WTF/Condition.cpp
new file mode 100644
index 000000000..c450d8953
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/Condition.cpp
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "config.h"
+#include <mutex>
+#include <thread>
+#include <wtf/Condition.h>
+#include <wtf/DataLog.h>
+#include <wtf/Deque.h>
+#include <wtf/Lock.h>
+#include <wtf/StringPrintStream.h>
+#include <wtf/Threading.h>
+#include <wtf/Vector.h>
+
+using namespace WTF;
+
+namespace TestWebKitAPI {
+
+namespace {
+
+const bool verbose = false;
+
+enum NotifyStyle {
+ AlwaysNotifyOne,
+ TacticallyNotifyAll
+};
+
+template<typename Functor>
+void wait(Condition& condition, std::unique_lock<Lock>& locker, const Functor& predicate, std::chrono::microseconds timeout)
+{
+ if (timeout == std::chrono::microseconds::max())
+ condition.wait(locker, predicate);
+ else {
+ // This tests timeouts in the sense that it verifies that we can call wait() again after a
+ // timeout happened. That's a non-trivial piece of functionality since upon timeout the
+ // ParkingLot has to remove us from the queue.
+ while (!predicate())
+ condition.waitFor(locker, timeout, predicate);
+ }
+}
+
+void notify(NotifyStyle notifyStyle, Condition& condition, bool shouldNotify)
+{
+ switch (notifyStyle) {
+ case AlwaysNotifyOne:
+ condition.notifyOne();
+ break;
+ case TacticallyNotifyAll:
+ if (shouldNotify)
+ condition.notifyAll();
+ break;
+ }
+}
+
+void runTest(
+ unsigned numProducers,
+ unsigned numConsumers,
+ unsigned maxQueueSize,
+ unsigned numMessagesPerProducer,
+ NotifyStyle notifyStyle,
+ std::chrono::microseconds timeout = std::chrono::microseconds::max(),
+ std::chrono::microseconds delay = std::chrono::microseconds::zero())
+{
+ Deque<unsigned> queue;
+ bool shouldContinue = true;
+ Lock lock;
+ Condition emptyCondition;
+ Condition fullCondition;
+
+ Vector<ThreadIdentifier> consumerThreads;
+ Vector<ThreadIdentifier> producerThreads;
+
+ Vector<unsigned> received;
+ Lock receivedLock;
+
+ for (unsigned i = numConsumers; i--;) {
+ ThreadIdentifier threadIdentifier = createThread(
+ "Consumer thread",
+ [&] () {
+ for (;;) {
+ unsigned result;
+ unsigned shouldNotify = false;
+ {
+ std::unique_lock<Lock> locker(lock);
+ wait(
+ emptyCondition, locker,
+ [&] () {
+ if (verbose)
+ dataLog(toString(currentThread(), ": Checking consumption predicate with shouldContinue = ", shouldContinue, ", queue.size() == ", queue.size(), "\n"));
+ return !shouldContinue || !queue.isEmpty();
+ },
+ timeout);
+ if (!shouldContinue && queue.isEmpty())
+ return;
+ shouldNotify = queue.size() == maxQueueSize;
+ result = queue.takeFirst();
+ }
+ notify(notifyStyle, fullCondition, shouldNotify);
+
+ {
+ std::lock_guard<Lock> locker(receivedLock);
+ received.append(result);
+ }
+ }
+ });
+ consumerThreads.append(threadIdentifier);
+ }
+
+ std::this_thread::sleep_for(delay);
+
+ for (unsigned i = numProducers; i--;) {
+ ThreadIdentifier threadIdentifier = createThread(
+ "Producer Thread",
+ [&] () {
+ for (unsigned i = 0; i < numMessagesPerProducer; ++i) {
+ bool shouldNotify = false;
+ {
+ std::unique_lock<Lock> locker(lock);
+ wait(
+ fullCondition, locker,
+ [&] () {
+ if (verbose)
+ dataLog(toString(currentThread(), ": Checking production predicate with shouldContinue = ", shouldContinue, ", queue.size() == ", queue.size(), "\n"));
+ return queue.size() < maxQueueSize;
+ },
+ timeout);
+ shouldNotify = queue.isEmpty();
+ queue.append(i);
+ }
+ notify(notifyStyle, emptyCondition, shouldNotify);
+ }
+ });
+ producerThreads.append(threadIdentifier);
+ }
+
+ for (ThreadIdentifier threadIdentifier : producerThreads)
+ waitForThreadCompletion(threadIdentifier);
+
+ {
+ std::lock_guard<Lock> locker(lock);
+ shouldContinue = false;
+ }
+ emptyCondition.notifyAll();
+
+ for (ThreadIdentifier threadIdentifier : consumerThreads)
+ waitForThreadCompletion(threadIdentifier);
+
+ EXPECT_EQ(numProducers * numMessagesPerProducer, received.size());
+ std::sort(received.begin(), received.end());
+ for (unsigned messageIndex = 0; messageIndex < numMessagesPerProducer; ++messageIndex) {
+ for (unsigned producerIndex = 0; producerIndex < numProducers; ++producerIndex)
+ EXPECT_EQ(messageIndex, received[messageIndex * numProducers + producerIndex]);
+ }
+}
+
+} // anonymous namespace
+
+TEST(WTF_Condition, OneProducerOneConsumerOneSlot)
+{
+ runTest(1, 1, 1, 100000, TacticallyNotifyAll);
+}
+
+TEST(WTF_Condition, OneProducerOneConsumerOneSlotTimeout)
+{
+ runTest(
+ 1, 1, 1, 100000, TacticallyNotifyAll,
+ std::chrono::microseconds(10000),
+ std::chrono::microseconds(1000000));
+}
+
+TEST(WTF_Condition, OneProducerOneConsumerHundredSlots)
+{
+ runTest(1, 1, 100, 1000000, TacticallyNotifyAll);
+}
+
+TEST(WTF_Condition, TenProducersOneConsumerOneSlot)
+{
+ runTest(10, 1, 1, 10000, TacticallyNotifyAll);
+}
+
+TEST(WTF_Condition, TenProducersOneConsumerHundredSlotsNotifyAll)
+{
+ runTest(10, 1, 100, 10000, TacticallyNotifyAll);
+}
+
+TEST(WTF_Condition, TenProducersOneConsumerHundredSlotsNotifyOne)
+{
+ runTest(10, 1, 100, 10000, AlwaysNotifyOne);
+}
+
+TEST(WTF_Condition, OneProducerTenConsumersOneSlot)
+{
+ runTest(1, 10, 1, 10000, TacticallyNotifyAll);
+}
+
+TEST(WTF_Condition, OneProducerTenConsumersHundredSlotsNotifyAll)
+{
+ runTest(1, 10, 100, 100000, TacticallyNotifyAll);
+}
+
+TEST(WTF_Condition, OneProducerTenConsumersHundredSlotsNotifyOne)
+{
+ runTest(1, 10, 100, 100000, AlwaysNotifyOne);
+}
+
+TEST(WTF_Condition, TenProducersTenConsumersOneSlot)
+{
+ runTest(10, 10, 1, 50000, TacticallyNotifyAll);
+}
+
+TEST(WTF_Condition, TenProducersTenConsumersHundredSlotsNotifyAll)
+{
+ runTest(10, 10, 100, 50000, TacticallyNotifyAll);
+}
+
+TEST(WTF_Condition, TenProducersTenConsumersHundredSlotsNotifyOne)
+{
+ runTest(10, 10, 100, 50000, AlwaysNotifyOne);
+}
+
+TEST(WTF_Condition, TimeoutTimesOut)
+{
+ Lock lock;
+ Condition condition;
+
+ lock.lock();
+ bool result = condition.waitFor(
+ lock, std::chrono::microseconds(10000), [] () -> bool { return false; });
+ lock.unlock();
+
+ EXPECT_FALSE(result);
+}
+
+} // namespace TestWebKitAPI
+
diff --git a/Tools/TestWebKitAPI/Tests/WTF/DateMath.cpp b/Tools/TestWebKitAPI/Tests/WTF/DateMath.cpp
new file mode 100644
index 000000000..463041d48
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/DateMath.cpp
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "config.h"
+
+#include "Test.h"
+#include <wtf/DateMath.h>
+
+namespace TestWebKitAPI {
+
+// Note: The results of these function look weird if you do not understand the following mappings:
+// dayOfWeek: [0, 6] 0 being Monday, day: [1, 31], month: [0, 11], year: ex: 2011,
+// hours: [0, 23], minutes: [0, 59], seconds: [0, 59], utcOffset: [-720,720].
+
+TEST(WTF_DateMath, dateToDaysFrom1970)
+{
+ EXPECT_EQ(0.0, dateToDaysFrom1970(1970, 0, 1));
+ EXPECT_EQ(157.0, dateToDaysFrom1970(1970, 5, 7));
+ EXPECT_EQ(-145.0, dateToDaysFrom1970(1969, 7, 9));
+ EXPECT_EQ(16322, dateToDaysFrom1970(2014, 8, 9));
+}
+
+
+TEST(WTF_DateMath, isLeapYear)
+{
+ EXPECT_TRUE(isLeapYear(1804));
+ EXPECT_FALSE(isLeapYear(1900));
+ EXPECT_TRUE(isLeapYear(1968));
+ EXPECT_TRUE(isLeapYear(1976));
+ EXPECT_TRUE(isLeapYear(2000));
+ EXPECT_FALSE(isLeapYear(2010));
+ EXPECT_TRUE(isLeapYear(2012));
+ EXPECT_FALSE(isLeapYear(2100));
+}
+
+TEST(WTF_DateMath, msToYear)
+{
+ EXPECT_EQ(1962, msToYear(-220953600000));
+ EXPECT_EQ(1970, msToYear(0));
+ EXPECT_EQ(1970, msToYear(100));
+ EXPECT_EQ(1977, msToYear(220953600000));
+ EXPECT_EQ(2013, msToYear(1365318000000));
+}
+
+TEST(WTF_DateMath, msToDays)
+{
+ EXPECT_EQ(0, msToDays(0));
+ EXPECT_EQ(2557, msToDays(220953600000));
+ EXPECT_EQ(255, msToDays(22095360000));
+ EXPECT_EQ(25, msToDays(2209536000));
+ EXPECT_EQ(2, msToDays(220953600));
+ EXPECT_EQ(0, msToDays(22095360));
+ EXPECT_EQ(0, msToDays(2209536));
+}
+
+TEST(WTF_DateMath, msToMinutes)
+{
+ EXPECT_EQ(0, msToMinutes(0));
+ EXPECT_EQ(0, msToMinutes(220953600000));
+ EXPECT_EQ(36, msToMinutes(22095360000));
+ EXPECT_EQ(36, msToMinutes(22095360000));
+ EXPECT_EQ(45, msToMinutes(2209536000));
+ EXPECT_EQ(22, msToMinutes(220953600));
+ EXPECT_EQ(8, msToMinutes(22095360));
+ EXPECT_EQ(36, msToMinutes(2209536));
+}
+
+TEST(WTF_DateMath, msToHours)
+{
+ EXPECT_EQ(0, msToHours(0));
+ EXPECT_EQ(8, msToHours(220953600000));
+ EXPECT_EQ(17, msToHours(22095360000));
+ EXPECT_EQ(13, msToHours(2209536000));
+ EXPECT_EQ(13, msToHours(220953600));
+ EXPECT_EQ(6, msToHours(22095360));
+ EXPECT_EQ(0, msToHours(2209536));
+}
+
+TEST(WTF_DateMath, dayInYear)
+{
+ EXPECT_EQ(59, dayInYear(2015, 2, 1));
+ EXPECT_EQ(60, dayInYear(2012, 2, 1));
+ EXPECT_EQ(0, dayInYear(2015, 0, 1));
+ EXPECT_EQ(31, dayInYear(2015, 1, 1));
+}
+
+TEST(WTF_DateMath, monthFromDayInYear)
+{
+ EXPECT_EQ(2, monthFromDayInYear(59, false));
+ EXPECT_EQ(1, monthFromDayInYear(59, true));
+ EXPECT_EQ(2, monthFromDayInYear(60, true));
+ EXPECT_EQ(0, monthFromDayInYear(0, false));
+ EXPECT_EQ(0, monthFromDayInYear(0, true));
+ EXPECT_EQ(1, monthFromDayInYear(31, true));
+ EXPECT_EQ(1, monthFromDayInYear(31, false));
+}
+
+TEST(WTF_DateMath, dayInMonthFromDayInYear)
+{
+ EXPECT_EQ(1, dayInMonthFromDayInYear(0, false));
+ EXPECT_EQ(1, dayInMonthFromDayInYear(0, true));
+ EXPECT_EQ(1, dayInMonthFromDayInYear(59, false));
+ EXPECT_EQ(29, dayInMonthFromDayInYear(59, true));
+ EXPECT_EQ(1, dayInMonthFromDayInYear(60, true));
+ EXPECT_EQ(1, dayInMonthFromDayInYear(0, false));
+ EXPECT_EQ(1, dayInMonthFromDayInYear(0, true));
+ EXPECT_EQ(31, dayInMonthFromDayInYear(30, true));
+ EXPECT_EQ(31, dayInMonthFromDayInYear(30, false));
+ EXPECT_EQ(31, dayInMonthFromDayInYear(365, true));
+ EXPECT_EQ(32, dayInMonthFromDayInYear(365, false));
+ EXPECT_EQ(32, dayInMonthFromDayInYear(366, true));
+}
+
+TEST(WTF_DateMath, calculateLocalTimeOffset)
+{
+ // DST Start: April 30, 1967 (02:00 am)
+ LocalTimeOffset dstStart1967 = calculateLocalTimeOffset(-84301200000, WTF::LocalTime);
+ EXPECT_TRUE(dstStart1967.isDST);
+ EXPECT_EQ(-25200000, dstStart1967.offset);
+
+ // November 1, 1967 (02:00 am)
+ LocalTimeOffset dstAlmostEnd1967 = calculateLocalTimeOffset(-68317200000, WTF::LocalTime);
+ EXPECT_TRUE(dstAlmostEnd1967.isDST);
+ EXPECT_EQ(-25200000, dstAlmostEnd1967.offset);
+
+ // DST End: November 11, 1967 (02:00 am)
+ LocalTimeOffset dstEnd1967 = calculateLocalTimeOffset(-67536000000, WTF::LocalTime);
+ EXPECT_FALSE(dstEnd1967.isDST);
+ EXPECT_EQ(-25200000, dstStart1967.offset);
+
+ // DST Start: April 3, 1988 (02:00 am)
+ LocalTimeOffset dstStart1988 = calculateLocalTimeOffset(576054000000, WTF::LocalTime);
+ EXPECT_TRUE(dstStart1988.isDST);
+ EXPECT_EQ(-25200000, dstStart1988.offset);
+
+ // DST End: November 4, 2012 (02:00 am)
+ LocalTimeOffset dstEnd2012 = calculateLocalTimeOffset(1352012400000, WTF::LocalTime);
+ EXPECT_FALSE(dstEnd2012.isDST);
+ EXPECT_EQ(-28800000, dstEnd2012.offset);
+
+ // DST Begin: March 8, 2015
+ LocalTimeOffset dstBegin2015 = calculateLocalTimeOffset(1425801600000, WTF::LocalTime);
+ EXPECT_TRUE(dstBegin2015.isDST);
+ EXPECT_EQ(-25200000, dstBegin2015.offset);
+
+ LocalTimeOffset dstBegin2015UTC = calculateLocalTimeOffset(1425801600000, WTF::UTCTime);
+ EXPECT_FALSE(dstBegin2015UTC.isDST);
+ EXPECT_EQ(-28800000, dstBegin2015UTC.offset);
+
+ // DST End: November 1, 2015
+ LocalTimeOffset dstEnd2015 = calculateLocalTimeOffset(1446361200000, WTF::LocalTime);
+ EXPECT_FALSE(dstEnd2015.isDST);
+ EXPECT_EQ(-28800000, dstEnd2015.offset);
+
+ // DST Begin: March 13, 2016
+ LocalTimeOffset dstBegin2016 = calculateLocalTimeOffset(1458111600000, WTF::LocalTime);
+ EXPECT_TRUE(dstBegin2016.isDST);
+ EXPECT_EQ(-25200000, dstBegin2016.offset);
+
+ // DST End: November 6, 2016
+ LocalTimeOffset dstEnd2016 = calculateLocalTimeOffset(1478415600000, WTF::LocalTime);
+ EXPECT_FALSE(dstEnd2016.isDST);
+ EXPECT_EQ(-28800000, dstEnd2016.offset);
+
+ // DST Begin: March 12, 2017
+ LocalTimeOffset dstBegin2017 = calculateLocalTimeOffset(1489305600000, WTF::LocalTime);
+ EXPECT_TRUE(dstBegin2017.isDST);
+ EXPECT_EQ(-25200000, dstBegin2017.offset);
+
+ // DST End: November 5, 2017
+ LocalTimeOffset dstEnd2017 = calculateLocalTimeOffset(1509865200000, WTF::LocalTime);
+ EXPECT_FALSE(dstEnd2017.isDST);
+ EXPECT_EQ(-28800000, dstEnd2017.offset);
+
+ // DST Begin: March 11, 2018
+ LocalTimeOffset dstBegin2018 = calculateLocalTimeOffset(1520755200000, WTF::LocalTime);
+ EXPECT_TRUE(dstBegin2018.isDST);
+ EXPECT_EQ(-25200000, dstBegin2018.offset);
+
+ // DST End: November 4, 2018
+ LocalTimeOffset dstEnd2018 = calculateLocalTimeOffset(1541314800000, WTF::LocalTime);
+ EXPECT_FALSE(dstEnd2018.isDST);
+ EXPECT_EQ(-28800000, dstEnd2018.offset);
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/Deque.cpp b/Tools/TestWebKitAPI/Tests/WTF/Deque.cpp
new file mode 100644
index 000000000..83f1f82ee
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/Deque.cpp
@@ -0,0 +1,191 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+
+#include "MoveOnly.h"
+#include <wtf/Deque.h>
+
+namespace TestWebKitAPI {
+
+TEST(WTF_Deque, Iterator)
+{
+ Deque<int> deque;
+ deque.append(11);
+ deque.prepend(10);
+ deque.append(12);
+ deque.append(13);
+
+ Deque<int>::iterator it = deque.begin();
+ Deque<int>::iterator end = deque.end();
+ EXPECT_TRUE(end != it);
+
+ EXPECT_EQ(10, *it);
+ ++it;
+ EXPECT_EQ(11, *it);
+ ++it;
+ EXPECT_EQ(12, *it);
+ ++it;
+ EXPECT_EQ(13, *it);
+ ++it;
+
+ EXPECT_TRUE(end == it);
+}
+
+TEST(WTF_Deque, InitializerList)
+{
+ Deque<int> deque = { 1, 2, 3, 4 };
+
+ EXPECT_EQ(4u, deque.size());
+
+ auto it = deque.begin();
+ auto end = deque.end();
+ EXPECT_TRUE(end != it);
+
+ EXPECT_EQ(1, *it);
+ ++it;
+ EXPECT_EQ(2, *it);
+ ++it;
+ EXPECT_EQ(3, *it);
+ ++it;
+ EXPECT_EQ(4, *it);
+ ++it;
+
+ EXPECT_TRUE(end == it);
+}
+
+TEST(WTF, DequeReverseIterator)
+{
+ Deque<int> deque;
+ deque.append(11);
+ deque.prepend(10);
+ deque.append(12);
+ deque.append(13);
+
+ Deque<int>::reverse_iterator it = deque.rbegin();
+ Deque<int>::reverse_iterator end = deque.rend();
+ EXPECT_TRUE(end != it);
+
+ EXPECT_EQ(13, *it);
+ ++it;
+ EXPECT_EQ(12, *it);
+ ++it;
+ EXPECT_EQ(11, *it);
+ ++it;
+ EXPECT_EQ(10, *it);
+ ++it;
+
+ EXPECT_TRUE(end == it);
+}
+
+TEST(WTF_Deque, Remove)
+{
+ Deque<int> deque;
+ deque.append(11);
+ deque.prepend(10);
+ deque.append(12);
+ deque.append(13);
+
+ EXPECT_EQ(10, deque.first());
+ EXPECT_EQ(13, deque.last());
+
+ deque.removeLast();
+ EXPECT_EQ(10, deque.first());
+ EXPECT_EQ(12, deque.last());
+
+ deque.removeFirst();
+ EXPECT_EQ(11, deque.first());
+ EXPECT_EQ(12, deque.last());
+
+ deque.removeFirst();
+ EXPECT_EQ(12, deque.first());
+ EXPECT_EQ(12, deque.last());
+
+ deque.removeLast();
+ EXPECT_TRUE(deque.isEmpty());
+}
+
+TEST(WTF_Deque, MoveOnly)
+{
+ Deque<MoveOnly> deque;
+
+ deque.append(MoveOnly(1));
+ deque.prepend(MoveOnly(0));
+
+ EXPECT_EQ(0U, deque.first().value());
+ EXPECT_EQ(1U, deque.last().value());
+
+ auto first = deque.takeFirst();
+ EXPECT_EQ(0U, first.value());
+
+ auto last = deque.takeLast();
+ EXPECT_EQ(1U, last.value());
+}
+
+TEST(WTF_Deque, MoveConstructor)
+{
+ Deque<MoveOnly, 4> deque;
+
+ for (unsigned i = 0; i < 10; ++i)
+ deque.append(MoveOnly(i));
+
+ EXPECT_EQ(10u, deque.size());
+
+ Deque<MoveOnly, 4> deque2 = WTFMove(deque);
+
+ EXPECT_EQ(10u, deque2.size());
+
+ unsigned i = 0;
+ for (auto& element : deque2) {
+ EXPECT_EQ(i, element.value());
+ ++i;
+ }
+}
+
+TEST(WTF_Deque, MoveAssignmentOperator)
+{
+ Deque<MoveOnly, 4> deque1;
+
+ for (unsigned i = 0; i < 10; ++i)
+ deque1.append(MoveOnly(i));
+
+ EXPECT_EQ(10u, deque1.size());
+
+ Deque<MoveOnly, 4> deque2;
+ for (unsigned i = 0; i < 10; ++i)
+ deque2.append(MoveOnly(i * 2));
+
+ deque1 = WTFMove(deque2);
+
+ EXPECT_EQ(10u, deque2.size());
+
+ unsigned i = 0;
+ for (auto& element : deque1) {
+ EXPECT_EQ(i * 2, element.value());
+ ++i;
+ }
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/HashCountedSet.cpp b/Tools/TestWebKitAPI/Tests/WTF/HashCountedSet.cpp
new file mode 100644
index 000000000..4c1afd105
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/HashCountedSet.cpp
@@ -0,0 +1,468 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 "Counters.h"
+#include "MoveOnly.h"
+#include "RefLogger.h"
+#include <string>
+#include <wtf/HashCountedSet.h>
+#include <wtf/text/StringHash.h>
+
+namespace TestWebKitAPI {
+
+typedef WTF::HashCountedSet<int> IntHashCountedSet;
+
+TEST(WTF_HashCountedSet, HashTableIteratorComparison)
+{
+ IntHashCountedSet hashCountedSet;
+ hashCountedSet.add(1);
+ ASSERT_TRUE(hashCountedSet.begin() != hashCountedSet.end());
+ ASSERT_FALSE(hashCountedSet.begin() == hashCountedSet.end());
+
+ IntHashCountedSet::const_iterator begin = hashCountedSet.begin();
+ ASSERT_TRUE(begin == hashCountedSet.begin());
+ ASSERT_TRUE(hashCountedSet.begin() == begin);
+ ASSERT_TRUE(begin != hashCountedSet.end());
+ ASSERT_TRUE(hashCountedSet.end() != begin);
+ ASSERT_FALSE(begin != hashCountedSet.begin());
+ ASSERT_FALSE(hashCountedSet.begin() != begin);
+ ASSERT_FALSE(begin == hashCountedSet.end());
+ ASSERT_FALSE(hashCountedSet.end() == begin);
+}
+
+struct TestDoubleHashTraits : HashTraits<double> {
+ static const int minimumTableSize = 8;
+};
+
+typedef HashCountedSet<double, DefaultHash<double>::Hash, TestDoubleHashTraits> DoubleHashCountedSet;
+
+static int bucketForKey(double key)
+{
+ return DefaultHash<double>::Hash::hash(key) & (TestDoubleHashTraits::minimumTableSize - 1);
+}
+
+TEST(WTF_HashCountedSet, DoubleHashCollisions)
+{
+ // The "clobber" key here is one that ends up stealing the bucket that the -0 key
+ // originally wants to be in. This makes the 0 and -0 keys collide and the test then
+ // fails unless the FloatHash::equals() implementation can distinguish them.
+ const double clobberKey = 6;
+ const double zeroKey = 0;
+ const double negativeZeroKey = -zeroKey;
+
+ DoubleHashCountedSet hashCountedSet;
+
+ hashCountedSet.add(clobberKey);
+
+ ASSERT_EQ(hashCountedSet.count(clobberKey), 1u);
+ ASSERT_EQ(hashCountedSet.count(zeroKey), 0u);
+ ASSERT_EQ(hashCountedSet.count(negativeZeroKey), 0u);
+
+ hashCountedSet.add(zeroKey);
+ hashCountedSet.add(negativeZeroKey);
+
+ ASSERT_EQ(bucketForKey(clobberKey), bucketForKey(negativeZeroKey));
+ ASSERT_EQ(hashCountedSet.count(clobberKey), 1u);
+ ASSERT_EQ(hashCountedSet.count(zeroKey), 1u);
+ ASSERT_EQ(hashCountedSet.count(negativeZeroKey), 1u);
+
+ hashCountedSet.add(clobberKey);
+ hashCountedSet.add(zeroKey);
+ hashCountedSet.add(negativeZeroKey);
+
+ ASSERT_EQ(hashCountedSet.count(clobberKey), 2u);
+ ASSERT_EQ(hashCountedSet.count(zeroKey), 2u);
+ ASSERT_EQ(hashCountedSet.count(negativeZeroKey), 2u);
+
+ hashCountedSet.add(clobberKey, 12);
+ hashCountedSet.add(zeroKey, 15);
+ hashCountedSet.add(negativeZeroKey, 17);
+
+ ASSERT_EQ(hashCountedSet.count(clobberKey), 14u);
+ ASSERT_EQ(hashCountedSet.count(zeroKey), 17u);
+ ASSERT_EQ(hashCountedSet.count(negativeZeroKey), 19u);
+}
+
+TEST(WTF_HashCountedSet, DoubleHashCollisionsInitialCount)
+{
+ // The "clobber" key here is one that ends up stealing the bucket that the -0 key
+ // originally wants to be in. This makes the 0 and -0 keys collide and the test then
+ // fails unless the FloatHash::equals() implementation can distinguish them.
+ const double clobberKey = 6;
+ const double zeroKey = 0;
+ const double negativeZeroKey = -zeroKey;
+
+ DoubleHashCountedSet hashCountedSet;
+
+ hashCountedSet.add(clobberKey, 5);
+
+ ASSERT_EQ(hashCountedSet.count(clobberKey), 5u);
+ ASSERT_EQ(hashCountedSet.count(zeroKey), 0u);
+ ASSERT_EQ(hashCountedSet.count(negativeZeroKey), 0u);
+
+ hashCountedSet.add(zeroKey, 22);
+ hashCountedSet.add(negativeZeroKey, 0);
+
+ ASSERT_EQ(bucketForKey(clobberKey), bucketForKey(negativeZeroKey));
+ ASSERT_EQ(hashCountedSet.count(clobberKey), 5u);
+ ASSERT_EQ(hashCountedSet.count(zeroKey), 22u);
+ ASSERT_EQ(hashCountedSet.count(negativeZeroKey), 0u);
+
+ hashCountedSet.add(clobberKey);
+ hashCountedSet.add(zeroKey);
+ hashCountedSet.add(negativeZeroKey);
+
+ ASSERT_EQ(hashCountedSet.count(clobberKey), 6u);
+ ASSERT_EQ(hashCountedSet.count(zeroKey), 23u);
+ ASSERT_EQ(hashCountedSet.count(negativeZeroKey), 1u);
+}
+
+
+TEST(WTF_HashCountedSet, MoveOnlyKeys)
+{
+ HashCountedSet<MoveOnly> moveOnlyKeys;
+
+ for (size_t i = 0; i < 100; ++i) {
+ MoveOnly moveOnly(i + 1);
+ moveOnlyKeys.add(WTFMove(moveOnly));
+ }
+
+ for (size_t i = 0; i < 100; ++i) {
+ auto it = moveOnlyKeys.find(MoveOnly(i + 1));
+ ASSERT_FALSE(it == moveOnlyKeys.end());
+ ASSERT_EQ(it->value, 1u);
+ }
+
+ for (size_t i = 0; i < 100; ++i)
+ ASSERT_FALSE(moveOnlyKeys.add(MoveOnly(i + 1)).isNewEntry);
+
+ for (size_t i = 0; i < 100; ++i)
+ ASSERT_FALSE(moveOnlyKeys.remove(MoveOnly(i + 1)));
+
+ for (size_t i = 0; i < 100; ++i)
+ ASSERT_TRUE(moveOnlyKeys.remove(MoveOnly(i + 1)));
+
+ ASSERT_TRUE(moveOnlyKeys.isEmpty());
+}
+
+TEST(WTF_HashCountedSet, MoveOnlyKeysInitialCount)
+{
+ HashCountedSet<MoveOnly> moveOnlyKeys;
+
+ for (size_t i = 0; i < 100; ++i) {
+ MoveOnly moveOnly(i + 1);
+ moveOnlyKeys.add(WTFMove(moveOnly), i + 1);
+ }
+
+ for (size_t i = 0; i < 100; ++i) {
+ auto it = moveOnlyKeys.find(MoveOnly(i + 1));
+ ASSERT_FALSE(it == moveOnlyKeys.end());
+ ASSERT_EQ(it->value, i + 1);
+ }
+
+ for (size_t i = 0; i < 100; ++i)
+ ASSERT_FALSE(moveOnlyKeys.add(MoveOnly(i + 1)).isNewEntry);
+
+ for (size_t i = 0; i < 100; ++i)
+ ASSERT_EQ(moveOnlyKeys.count(MoveOnly(i + 1)), i + 2);
+
+ for (size_t i = 0; i < 100; ++i)
+ ASSERT_FALSE(moveOnlyKeys.remove(MoveOnly(i + 1)));
+
+ for (size_t i = 0; i < 100; ++i)
+ ASSERT_EQ(moveOnlyKeys.count(MoveOnly(i + 1)), i + 1);
+}
+
+TEST(WTF_HashCountedSet, InitializerList)
+{
+ HashCountedSet<String> hashCountedSet = {
+ "one",
+ "two",
+ "three",
+ "four",
+ "four",
+ "four",
+ "four",
+ };
+
+ EXPECT_EQ(4u, hashCountedSet.size());
+
+ EXPECT_EQ(hashCountedSet.count("one"), 1u);
+ EXPECT_EQ(hashCountedSet.count("two"), 1u);
+ EXPECT_EQ(hashCountedSet.count("three"), 1u);
+ EXPECT_EQ(hashCountedSet.count("four"), 4u);
+}
+
+TEST(WTF_HashCountedSet, InitializerListInitialCount)
+{
+ HashCountedSet<String> hashCountedSet = {
+ { String("one"), 1u },
+ { String("two"), 2u },
+ { String("three"), 3u },
+ { String("four"), 4u },
+ };
+
+ EXPECT_EQ(4u, hashCountedSet.size());
+
+ EXPECT_EQ(hashCountedSet.count("one"), 1u);
+ EXPECT_EQ(hashCountedSet.count("two"), 2u);
+ EXPECT_EQ(hashCountedSet.count("three"), 3u);
+ EXPECT_EQ(hashCountedSet.count("four"), 4u);
+}
+
+TEST(WTF_HashCountedSet, UniquePtrKey)
+{
+ ConstructorDestructorCounter::TestingScope scope;
+
+ HashCountedSet<std::unique_ptr<ConstructorDestructorCounter>> hashCountedSet;
+
+ auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+ hashCountedSet.add(WTFMove(uniquePtr));
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+ hashCountedSet.clear();
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashCountedSet, UniquePtrKeyInitialCount)
+{
+ ConstructorDestructorCounter::TestingScope scope;
+
+ HashCountedSet<std::unique_ptr<ConstructorDestructorCounter>> hashCountedSet;
+
+ auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+ hashCountedSet.add(WTFMove(uniquePtr), 12);
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+ hashCountedSet.clear();
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashCountedSet, UniquePtrKey_CustomDeleter)
+{
+ ConstructorDestructorCounter::TestingScope constructorDestructorCounterScope;
+ DeleterCounter<ConstructorDestructorCounter>::TestingScope deleterCounterScope;
+
+ HashCountedSet<std::unique_ptr<ConstructorDestructorCounter, DeleterCounter<ConstructorDestructorCounter>>> hashCountedSet;
+
+ std::unique_ptr<ConstructorDestructorCounter, DeleterCounter<ConstructorDestructorCounter>> uniquePtr(new ConstructorDestructorCounter(), DeleterCounter<ConstructorDestructorCounter>());
+ hashCountedSet.add(WTFMove(uniquePtr));
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+ EXPECT_EQ(0u, DeleterCounter<ConstructorDestructorCounter>::deleterCount);
+
+ hashCountedSet.clear();
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+
+ EXPECT_EQ(1u, DeleterCounter<ConstructorDestructorCounter>::deleterCount);
+}
+
+TEST(WTF_HashCountedSet, UniquePtrKey_FindUsingRawPointer)
+{
+ HashCountedSet<std::unique_ptr<int>> hashCountedSet;
+
+ auto uniquePtr = std::make_unique<int>(5);
+ int* ptr = uniquePtr.get();
+ hashCountedSet.add(WTFMove(uniquePtr));
+
+ auto it = hashCountedSet.find(ptr);
+ ASSERT_TRUE(it != hashCountedSet.end());
+ EXPECT_EQ(ptr, it->key.get());
+ EXPECT_EQ(1u, it->value);
+}
+
+TEST(WTF_HashCountedSet, UniquePtrKey_ContainsUsingRawPointer)
+{
+ HashCountedSet<std::unique_ptr<int>> hashCountedSet;
+
+ auto uniquePtr = std::make_unique<int>(5);
+ int* ptr = uniquePtr.get();
+ hashCountedSet.add(WTFMove(uniquePtr));
+
+ EXPECT_EQ(true, hashCountedSet.contains(ptr));
+}
+
+TEST(WTF_HashCountedSet, UniquePtrKey_GetUsingRawPointer)
+{
+ HashCountedSet<std::unique_ptr<int>> hashCountedSet;
+
+ auto uniquePtr = std::make_unique<int>(5);
+ int* ptr = uniquePtr.get();
+ hashCountedSet.add(WTFMove(uniquePtr));
+
+ int value = hashCountedSet.count(ptr);
+ EXPECT_EQ(1, value);
+}
+
+TEST(WTF_HashCountedSet, UniquePtrKey_RemoveUsingRawPointer)
+{
+ ConstructorDestructorCounter::TestingScope scope;
+
+ HashCountedSet<std::unique_ptr<ConstructorDestructorCounter>> hashCountedSet;
+
+ auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+ ConstructorDestructorCounter* ptr = uniquePtr.get();
+ hashCountedSet.add(WTFMove(uniquePtr));
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+ bool result = hashCountedSet.remove(ptr);
+ EXPECT_EQ(true, result);
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashCountedSet, RefPtrKey_Add)
+{
+ HashCountedSet<RefPtr<RefLogger>> hashCountedSet;
+
+ DerivedRefLogger a("a");
+ RefPtr<RefLogger> ptr(&a);
+ hashCountedSet.add(ptr);
+
+ ASSERT_STREQ("ref(a) ref(a) ", takeLogStr().c_str());
+ EXPECT_EQ(1U, hashCountedSet.count(ptr));
+ EXPECT_EQ(1U, hashCountedSet.count(ptr.get()));
+}
+
+TEST(WTF_HashCountedSet, RefPtrKey_AddUsingRelease)
+{
+ HashCountedSet<RefPtr<RefLogger>> hashCountedSet;
+
+ DerivedRefLogger a("a");
+ RefPtr<RefLogger> ptr(&a);
+ hashCountedSet.add(ptr.release());
+
+ EXPECT_STREQ("ref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashCountedSet, RefPtrKey_AddUsingMove)
+{
+ HashCountedSet<RefPtr<RefLogger>> hashCountedSet;
+
+ DerivedRefLogger a("a");
+ RefPtr<RefLogger> ptr(&a);
+ hashCountedSet.add(WTFMove(ptr));
+
+ EXPECT_STREQ("ref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashCountedSet, RefPtrKey_AddUsingRaw)
+{
+ HashCountedSet<RefPtr<RefLogger>> hashCountedSet;
+
+ DerivedRefLogger a("a");
+ RefPtr<RefLogger> ptr(&a);
+ hashCountedSet.add(ptr.get());
+
+ EXPECT_STREQ("ref(a) ref(a) ", takeLogStr().c_str());
+ EXPECT_EQ(1U, hashCountedSet.count(ptr));
+ EXPECT_EQ(1U, hashCountedSet.count(ptr.get()));
+}
+
+TEST(WTF_HashCountedSet, RefPtrKey_AddKeyAlreadyPresent)
+{
+ HashCountedSet<RefPtr<RefLogger>> hashCountedSet;
+
+ DerivedRefLogger a("a");
+
+ {
+ RefPtr<RefLogger> ptr(&a);
+ hashCountedSet.add(ptr);
+ }
+
+ EXPECT_STREQ("ref(a) ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ RefPtr<RefLogger> ptr2(&a);
+ auto addResult = hashCountedSet.add(ptr2);
+ EXPECT_FALSE(addResult.isNewEntry);
+ }
+
+ EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashCountedSet, RefPtrKey_AddUsingReleaseKeyAlreadyPresent)
+{
+ HashCountedSet<RefPtr<RefLogger>> hashCountedSet;
+
+ DerivedRefLogger a("a");
+
+ {
+ RefPtr<RefLogger> ptr(&a);
+ hashCountedSet.add(ptr);
+ }
+
+ EXPECT_STREQ("ref(a) ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ RefPtr<RefLogger> ptr2(&a);
+ auto addResult = hashCountedSet.add(ptr2.release());
+ EXPECT_FALSE(addResult.isNewEntry);
+ }
+
+ EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashCountedSet, RefPtrKey_AddUsingMoveKeyAlreadyPresent)
+{
+ HashCountedSet<RefPtr<RefLogger>> hashCountedSet;
+
+ DerivedRefLogger a("a");
+
+ {
+ RefPtr<RefLogger> ptr(&a);
+ hashCountedSet.add(ptr);
+ }
+
+ EXPECT_STREQ("ref(a) ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ RefPtr<RefLogger> ptr2(&a);
+ auto addResult = hashCountedSet.add(WTFMove(ptr2));
+ EXPECT_FALSE(addResult.isNewEntry);
+ }
+
+ EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp b/Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp
index d03fb9594..145edae1a 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp
@@ -25,7 +25,9 @@
#include "config.h"
+#include "Counters.h"
#include "MoveOnly.h"
+#include "RefLogger.h"
#include <string>
#include <wtf/HashMap.h>
#include <wtf/text/StringHash.h>
@@ -90,7 +92,7 @@ TEST(WTF_HashMap, MoveOnlyValues)
for (size_t i = 0; i < 100; ++i) {
MoveOnly moveOnly(i + 1);
- moveOnlyValues.set(i + 1, std::move(moveOnly));
+ moveOnlyValues.set(i + 1, WTFMove(moveOnly));
}
for (size_t i = 0; i < 100; ++i) {
@@ -113,7 +115,7 @@ TEST(WTF_HashMap, MoveOnlyKeys)
for (size_t i = 0; i < 100; ++i) {
MoveOnly moveOnly(i + 1);
- moveOnlyKeys.set(std::move(moveOnly), i + 1);
+ moveOnlyKeys.set(WTFMove(moveOnly), i + 1);
}
for (size_t i = 0; i < 100; ++i) {
@@ -139,7 +141,7 @@ TEST(WTF_HashMap, InitializerList)
{ 4, "four" },
};
- EXPECT_EQ(4, map.size());
+ EXPECT_EQ(4u, map.size());
EXPECT_EQ("one", map.get(1));
EXPECT_EQ("two", map.get(2));
@@ -148,4 +150,553 @@ TEST(WTF_HashMap, InitializerList)
EXPECT_EQ(std::string(), map.get(5));
}
+TEST(WTF_HashMap, EfficientGetter)
+{
+ HashMap<unsigned, CopyMoveCounter> map;
+ map.set(1, CopyMoveCounter());
+
+ {
+ CopyMoveCounter::TestingScope scope;
+ map.get(1);
+ EXPECT_EQ(0U, CopyMoveCounter::constructionCount);
+ EXPECT_EQ(1U, CopyMoveCounter::copyCount);
+ EXPECT_EQ(0U, CopyMoveCounter::moveCount);
+ }
+
+ {
+ CopyMoveCounter::TestingScope scope;
+ map.get(2);
+ EXPECT_EQ(1U, CopyMoveCounter::constructionCount);
+ EXPECT_EQ(0U, CopyMoveCounter::copyCount);
+ EXPECT_EQ(1U, CopyMoveCounter::moveCount);
+ }
+}
+
+TEST(WTF_HashMap, UniquePtrKey)
+{
+ ConstructorDestructorCounter::TestingScope scope;
+
+ HashMap<std::unique_ptr<ConstructorDestructorCounter>, int> map;
+
+ auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+ map.add(WTFMove(uniquePtr), 2);
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+ map.clear();
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashMap, UniquePtrKey_CustomDeleter)
+{
+ ConstructorDestructorCounter::TestingScope constructorDestructorCounterScope;
+ DeleterCounter<ConstructorDestructorCounter>::TestingScope deleterCounterScope;
+
+ HashMap<std::unique_ptr<ConstructorDestructorCounter, DeleterCounter<ConstructorDestructorCounter>>, int> map;
+
+ std::unique_ptr<ConstructorDestructorCounter, DeleterCounter<ConstructorDestructorCounter>> uniquePtr(new ConstructorDestructorCounter(), DeleterCounter<ConstructorDestructorCounter>());
+ map.add(WTFMove(uniquePtr), 2);
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+ EXPECT_EQ(0u, DeleterCounter<ConstructorDestructorCounter>::deleterCount);
+
+ map.clear();
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+
+ EXPECT_EQ(1u, DeleterCounter<ConstructorDestructorCounter>::deleterCount);
+}
+
+TEST(WTF_HashMap, UniquePtrKey_FindUsingRawPointer)
+{
+ HashMap<std::unique_ptr<int>, int> map;
+
+ auto uniquePtr = std::make_unique<int>(5);
+ int* ptr = uniquePtr.get();
+ map.add(WTFMove(uniquePtr), 2);
+
+ auto it = map.find(ptr);
+ ASSERT_TRUE(it != map.end());
+ EXPECT_EQ(ptr, it->key.get());
+ EXPECT_EQ(2, it->value);
+}
+
+TEST(WTF_HashMap, UniquePtrKey_ContainsUsingRawPointer)
+{
+ HashMap<std::unique_ptr<int>, int> map;
+
+ auto uniquePtr = std::make_unique<int>(5);
+ int* ptr = uniquePtr.get();
+ map.add(WTFMove(uniquePtr), 2);
+
+ EXPECT_EQ(true, map.contains(ptr));
+}
+
+TEST(WTF_HashMap, UniquePtrKey_GetUsingRawPointer)
+{
+ HashMap<std::unique_ptr<int>, int> map;
+
+ auto uniquePtr = std::make_unique<int>(5);
+ int* ptr = uniquePtr.get();
+ map.add(WTFMove(uniquePtr), 2);
+
+ int value = map.get(ptr);
+ EXPECT_EQ(2, value);
+}
+
+TEST(WTF_HashMap, UniquePtrKey_RemoveUsingRawPointer)
+{
+ ConstructorDestructorCounter::TestingScope scope;
+
+ HashMap<std::unique_ptr<ConstructorDestructorCounter>, int> map;
+
+ auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+ ConstructorDestructorCounter* ptr = uniquePtr.get();
+ map.add(WTFMove(uniquePtr), 2);
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+ bool result = map.remove(ptr);
+ EXPECT_EQ(true, result);
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashMap, UniquePtrKey_TakeUsingRawPointer)
+{
+ ConstructorDestructorCounter::TestingScope scope;
+
+ HashMap<std::unique_ptr<ConstructorDestructorCounter>, int> map;
+
+ auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+ ConstructorDestructorCounter* ptr = uniquePtr.get();
+ map.add(WTFMove(uniquePtr), 2);
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+ int result = map.take(ptr);
+ EXPECT_EQ(2, result);
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashMap, RefPtrKey_Add)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+ RefPtr<RefLogger> ptr(&a);
+ map.add(ptr, 0);
+
+ ASSERT_STREQ("ref(a) ref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, RefPtrKey_AddUsingRelease)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+ RefPtr<RefLogger> ptr(&a);
+ map.add(ptr.release(), 0);
+
+ EXPECT_STREQ("ref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, RefPtrKey_AddUsingMove)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+ RefPtr<RefLogger> ptr(&a);
+ map.add(WTFMove(ptr), 0);
+
+ EXPECT_STREQ("ref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, RefPtrKey_AddUsingRaw)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+ RefPtr<RefLogger> ptr(&a);
+ map.add(ptr.get(), 0);
+
+ EXPECT_STREQ("ref(a) ref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, RefPtrKey_AddKeyAlreadyPresent)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+
+ {
+ RefPtr<RefLogger> ptr(&a);
+ map.add(ptr, 0);
+ }
+
+ EXPECT_STREQ("ref(a) ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ RefPtr<RefLogger> ptr2(&a);
+ auto addResult = map.add(ptr2, 0);
+ EXPECT_FALSE(addResult.isNewEntry);
+ }
+
+ EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, RefPtrKey_AddUsingReleaseKeyAlreadyPresent)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+
+ {
+ RefPtr<RefLogger> ptr(&a);
+ map.add(ptr, 0);
+ }
+
+ EXPECT_STREQ("ref(a) ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ RefPtr<RefLogger> ptr2(&a);
+ auto addResult = map.add(ptr2.release(), 0);
+ EXPECT_FALSE(addResult.isNewEntry);
+ }
+
+ EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, RefPtrKey_AddUsingMoveKeyAlreadyPresent)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+
+ {
+ RefPtr<RefLogger> ptr(&a);
+ map.add(ptr, 0);
+ }
+
+ EXPECT_STREQ("ref(a) ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ RefPtr<RefLogger> ptr2(&a);
+ auto addResult = map.add(WTFMove(ptr2), 0);
+ EXPECT_FALSE(addResult.isNewEntry);
+ }
+
+ EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, RefPtrKey_Set)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+ RefPtr<RefLogger> ptr(&a);
+ map.set(ptr, 0);
+
+ ASSERT_STREQ("ref(a) ref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, RefPtrKey_SetUsingRelease)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+ RefPtr<RefLogger> ptr(&a);
+ map.set(ptr.release(), 0);
+
+ EXPECT_STREQ("ref(a) ", takeLogStr().c_str());
+}
+
+
+TEST(WTF_HashMap, RefPtrKey_SetUsingMove)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+ RefPtr<RefLogger> ptr(&a);
+ map.set(WTFMove(ptr), 0);
+
+ EXPECT_STREQ("ref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, RefPtrKey_SetUsingRaw)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+ RefPtr<RefLogger> ptr(&a);
+ map.set(ptr.get(), 0);
+
+ EXPECT_STREQ("ref(a) ref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, RefPtrKey_SetKeyAlreadyPresent)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+
+ RefPtr<RefLogger> ptr(&a);
+ map.set(ptr, 0);
+
+ EXPECT_STREQ("ref(a) ref(a) ", takeLogStr().c_str());
+
+ {
+ RefPtr<RefLogger> ptr2(&a);
+ auto addResult = map.set(ptr2, 1);
+ EXPECT_FALSE(addResult.isNewEntry);
+ EXPECT_EQ(1, map.get(ptr.get()));
+ }
+
+ EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, RefPtrKey_SetUsingReleaseKeyAlreadyPresent)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+
+ RefPtr<RefLogger> ptr(&a);
+ map.set(ptr, 0);
+
+ EXPECT_STREQ("ref(a) ref(a) ", takeLogStr().c_str());
+
+ {
+ RefPtr<RefLogger> ptr2(&a);
+ auto addResult = map.set(ptr2.release(), 1);
+ EXPECT_FALSE(addResult.isNewEntry);
+ EXPECT_EQ(1, map.get(ptr.get()));
+ }
+
+ EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, RefPtrKey_SetUsingMoveKeyAlreadyPresent)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+
+ RefPtr<RefLogger> ptr(&a);
+ map.set(ptr, 0);
+
+ EXPECT_STREQ("ref(a) ref(a) ", takeLogStr().c_str());
+
+ {
+ RefPtr<RefLogger> ptr2(&a);
+ auto addResult = map.set(WTFMove(ptr2), 1);
+ EXPECT_FALSE(addResult.isNewEntry);
+ EXPECT_EQ(1, map.get(ptr.get()));
+ }
+
+ EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, Ensure)
+{
+ HashMap<unsigned, unsigned> map;
+ {
+ auto addResult = map.ensure(1, [] { return 1; });
+ EXPECT_EQ(1u, addResult.iterator->value);
+ EXPECT_EQ(1u, addResult.iterator->key);
+ EXPECT_TRUE(addResult.isNewEntry);
+ auto addResult2 = map.ensure(1, [] { return 2; });
+ EXPECT_EQ(1u, addResult2.iterator->value);
+ EXPECT_EQ(1u, addResult2.iterator->key);
+ EXPECT_FALSE(addResult2.isNewEntry);
+ }
+}
+
+TEST(WTF_HashMap, Ensure_MoveOnlyValues)
+{
+ HashMap<unsigned, MoveOnly> moveOnlyValues;
+ {
+ auto addResult = moveOnlyValues.ensure(1, [] { return MoveOnly(1); });
+ EXPECT_EQ(1u, addResult.iterator->value.value());
+ EXPECT_EQ(1u, addResult.iterator->key);
+ EXPECT_TRUE(addResult.isNewEntry);
+ auto addResult2 = moveOnlyValues.ensure(1, [] { return MoveOnly(2); });
+ EXPECT_EQ(1u, addResult2.iterator->value.value());
+ EXPECT_EQ(1u, addResult2.iterator->key);
+ EXPECT_FALSE(addResult2.isNewEntry);
+ }
+}
+
+TEST(WTF_HashMap, Ensure_UniquePointer)
+{
+ HashMap<unsigned, std::unique_ptr<unsigned>> map;
+ {
+ auto addResult = map.ensure(1, [] { return std::make_unique<unsigned>(1); });
+ EXPECT_EQ(1u, *map.get(1));
+ EXPECT_EQ(1u, *addResult.iterator->value.get());
+ EXPECT_EQ(1u, addResult.iterator->key);
+ EXPECT_TRUE(addResult.isNewEntry);
+ auto addResult2 = map.ensure(1, [] { return std::make_unique<unsigned>(2); });
+ EXPECT_EQ(1u, *map.get(1));
+ EXPECT_EQ(1u, *addResult2.iterator->value.get());
+ EXPECT_EQ(1u, addResult2.iterator->key);
+ EXPECT_FALSE(addResult2.isNewEntry);
+ }
+}
+
+TEST(WTF_HashMap, Ensure_RefPtr)
+{
+ HashMap<unsigned, RefPtr<RefLogger>> map;
+
+ {
+ DerivedRefLogger a("a");
+
+ map.ensure(1, [&] { return RefPtr<RefLogger>(&a); });
+ EXPECT_STREQ("ref(a) ", takeLogStr().c_str());
+
+ map.ensure(1, [&] { return RefPtr<RefLogger>(&a); });
+ EXPECT_STREQ("", takeLogStr().c_str());
+ }
+}
+
+class ObjectWithRefLogger {
+public:
+ ObjectWithRefLogger(Ref<RefLogger>&& logger)
+ : m_logger(WTFMove(logger))
+ {
+ }
+
+ Ref<RefLogger> m_logger;
+};
+
+
+void testMovingUsingEnsure(Ref<RefLogger>&& logger)
+{
+ HashMap<unsigned, std::unique_ptr<ObjectWithRefLogger>> map;
+
+ map.ensure(1, [&] { return std::make_unique<ObjectWithRefLogger>(WTFMove(logger)); });
+}
+
+void testMovingUsingAdd(Ref<RefLogger>&& logger)
+{
+ HashMap<unsigned, std::unique_ptr<ObjectWithRefLogger>> map;
+
+ auto& slot = map.add(1, nullptr).iterator->value;
+ slot = std::make_unique<ObjectWithRefLogger>(WTFMove(logger));
+}
+
+TEST(WTF_HashMap, Ensure_LambdasCapturingByReference)
+{
+ {
+ DerivedRefLogger a("a");
+ Ref<RefLogger> ref(a);
+ testMovingUsingEnsure(WTFMove(ref));
+
+ EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+ }
+
+ {
+ DerivedRefLogger a("a");
+ Ref<RefLogger> ref(a);
+ testMovingUsingAdd(WTFMove(ref));
+
+ EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+ }
+}
+
+
+TEST(WTF_HashMap, ValueIsDestructedOnRemove)
+{
+ struct DestructorObserver {
+ DestructorObserver() = default;
+
+ DestructorObserver(bool* destructed)
+ : destructed(destructed)
+ {
+ }
+
+ ~DestructorObserver()
+ {
+ if (destructed)
+ *destructed = true;
+ }
+
+ DestructorObserver(DestructorObserver&& other)
+ : destructed(other.destructed)
+ {
+ other.destructed = nullptr;
+ }
+
+ DestructorObserver& operator=(DestructorObserver&& other)
+ {
+ destructed = other.destructed;
+ other.destructed = nullptr;
+ return *this;
+ }
+
+ bool* destructed { nullptr };
+ };
+
+ HashMap<int, DestructorObserver> map;
+
+ bool destructed = false;
+ map.add(5, DestructorObserver { &destructed });
+
+ EXPECT_FALSE(destructed);
+
+ bool removeResult = map.remove(5);
+
+ EXPECT_TRUE(removeResult);
+ EXPECT_TRUE(destructed);
+}
+
+TEST(WTF_HashMap, RefPtrNotZeroedBeforeDeref)
+{
+ struct DerefObserver {
+ NEVER_INLINE void ref()
+ {
+ ++count;
+ }
+ NEVER_INLINE void deref()
+ {
+ --count;
+ observedBucket = bucketAddress->get();
+ }
+ unsigned count { 1 };
+ const RefPtr<DerefObserver>* bucketAddress { nullptr };
+ const DerefObserver* observedBucket { nullptr };
+ };
+
+ auto observer = std::make_unique<DerefObserver>();
+
+ HashMap<RefPtr<DerefObserver>, int> map;
+ map.add(adoptRef(observer.get()), 5);
+
+ auto iterator = map.find(observer.get());
+ EXPECT_TRUE(iterator != map.end());
+
+ observer->bucketAddress = &iterator->key;
+
+ EXPECT_TRUE(observer->observedBucket == nullptr);
+ EXPECT_TRUE(map.remove(observer.get()));
+
+ // It if fine to either leave the old value intact at deletion or already set it to the deleted
+ // value.
+ // A zero would be a incorrect outcome as it would mean we nulled the bucket before an opaque
+ // call.
+ EXPECT_TRUE(observer->observedBucket == observer.get() || observer->observedBucket == RefPtr<DerefObserver>::hashTableDeletedValue());
+ EXPECT_EQ(observer->count, 0u);
+}
+
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/HashSet.cpp b/Tools/TestWebKitAPI/Tests/WTF/HashSet.cpp
index 88e7d075f..1d6ffc039 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/HashSet.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/HashSet.cpp
@@ -25,9 +25,10 @@
#include "config.h"
+#include "Counters.h"
#include "MoveOnly.h"
#include <wtf/HashSet.h>
-
+#include <wtf/RefPtr.h>
namespace TestWebKitAPI {
@@ -43,7 +44,7 @@ void testInitialCapacity()
HashSet<int, DefaultHash<int>::Hash, InitialCapacityTestHashTraits<initialCapacity> > testSet;
// Initial capacity is null.
- ASSERT_EQ(0, testSet.capacity());
+ ASSERT_EQ(0u, testSet.capacity());
// Adding items up to size should never change the capacity.
for (size_t i = 0; i < size; ++i) {
@@ -84,7 +85,7 @@ TEST(WTF_HashSet, MoveOnly)
for (size_t i = 0; i < 100; ++i) {
MoveOnly moveOnly(i + 1);
- hashSet.add(std::move(moveOnly));
+ hashSet.add(WTFMove(moveOnly));
}
for (size_t i = 0; i < 100; ++i)
@@ -96,11 +97,256 @@ TEST(WTF_HashSet, MoveOnly)
EXPECT_TRUE(hashSet.isEmpty());
for (size_t i = 0; i < 100; ++i)
- hashSet.add(std::move(MoveOnly(i + 1)));
+ hashSet.add(MoveOnly(i + 1));
for (size_t i = 0; i < 100; ++i)
EXPECT_TRUE(hashSet.take(MoveOnly(i + 1)) == MoveOnly(i + 1));
+ EXPECT_TRUE(hashSet.isEmpty());
+
+ for (size_t i = 0; i < 100; ++i)
+ hashSet.add(MoveOnly(i + 1));
+
+ HashSet<MoveOnly> secondSet;
+
+ for (size_t i = 0; i < 100; ++i)
+ secondSet.add(hashSet.takeAny());
+
+ EXPECT_TRUE(hashSet.isEmpty());
+
+ for (size_t i = 0; i < 100; ++i)
+ EXPECT_TRUE(secondSet.contains(MoveOnly(i + 1)));
+}
+
+
+TEST(WTF_HashSet, UniquePtrKey)
+{
+ ConstructorDestructorCounter::TestingScope scope;
+
+ HashSet<std::unique_ptr<ConstructorDestructorCounter>> set;
+
+ auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+ set.add(WTFMove(uniquePtr));
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+ set.clear();
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashSet, UniquePtrKey_FindUsingRawPointer)
+{
+ HashSet<std::unique_ptr<int>> set;
+
+ auto uniquePtr = std::make_unique<int>(5);
+ int* ptr = uniquePtr.get();
+ set.add(WTFMove(uniquePtr));
+
+ auto it = set.find(ptr);
+ ASSERT_TRUE(it != set.end());
+ EXPECT_EQ(ptr, it->get());
+ EXPECT_EQ(5, *it->get());
+}
+
+TEST(WTF_HashSet, UniquePtrKey_ContainsUsingRawPointer)
+{
+ HashSet<std::unique_ptr<int>> set;
+
+ auto uniquePtr = std::make_unique<int>(5);
+ int* ptr = uniquePtr.get();
+ set.add(WTFMove(uniquePtr));
+
+ EXPECT_EQ(true, set.contains(ptr));
+}
+
+TEST(WTF_HashSet, UniquePtrKey_RemoveUsingRawPointer)
+{
+ ConstructorDestructorCounter::TestingScope scope;
+
+ HashSet<std::unique_ptr<ConstructorDestructorCounter>> set;
+
+ auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+ ConstructorDestructorCounter* ptr = uniquePtr.get();
+ set.add(WTFMove(uniquePtr));
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+ bool result = set.remove(ptr);
+ EXPECT_EQ(true, result);
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
}
+TEST(WTF_HashSet, UniquePtrKey_TakeUsingRawPointer)
+{
+ ConstructorDestructorCounter::TestingScope scope;
+
+ HashSet<std::unique_ptr<ConstructorDestructorCounter>> set;
+
+ auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+ ConstructorDestructorCounter* ptr = uniquePtr.get();
+ set.add(WTFMove(uniquePtr));
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+ auto result = set.take(ptr);
+ EXPECT_EQ(ptr, result.get());
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+ result = nullptr;
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashSet, CopyEmpty)
+{
+ {
+ HashSet<unsigned> foo;
+ HashSet<unsigned> bar(foo);
+
+ EXPECT_EQ(0u, bar.capacity());
+ EXPECT_EQ(0u, bar.size());
+ }
+ {
+ HashSet<unsigned> foo({ 1, 5, 64, 42 });
+ EXPECT_EQ(4u, foo.size());
+ foo.remove(1);
+ foo.remove(5);
+ foo.remove(42);
+ foo.remove(64);
+ HashSet<unsigned> bar(foo);
+
+ EXPECT_EQ(0u, bar.capacity());
+ EXPECT_EQ(0u, bar.size());
+ }
+}
+
+TEST(WTF_HashSet, CopyAllocateAtLeastMinimumCapacity)
+{
+ HashSet<unsigned> foo({ 42 });
+ EXPECT_EQ(1u, foo.size());
+ HashSet<unsigned> bar(foo);
+
+ EXPECT_EQ(8u, bar.capacity());
+ EXPECT_EQ(1u, bar.size());
+}
+
+TEST(WTF_HashSet, CopyCapacityIsNotOnBoundary)
+{
+ // Starting at 4 because the minimum size is 8.
+ // With a size of 8, a medium load can be up to 3.3333->3.
+ // Adding 1 to 3 would reach max load.
+ // While correct, that's not really what we care about here.
+ for (unsigned size = 4; size < 100; ++size) {
+ HashSet<unsigned> source;
+ for (unsigned i = 1; i < size + 1; ++i)
+ source.add(i);
+
+ HashSet<unsigned> copy1(source);
+ HashSet<unsigned> copy2(source);
+ HashSet<unsigned> copy3(source);
+
+ EXPECT_EQ(size, copy1.size());
+ EXPECT_EQ(size, copy2.size());
+ EXPECT_EQ(size, copy3.size());
+ for (unsigned i = 1; i < size + 1; ++i) {
+ EXPECT_TRUE(copy1.contains(i));
+ EXPECT_TRUE(copy2.contains(i));
+ EXPECT_TRUE(copy3.contains(i));
+ }
+ EXPECT_FALSE(copy1.contains(size + 2));
+ EXPECT_FALSE(copy2.contains(size + 2));
+ EXPECT_FALSE(copy3.contains(size + 2));
+
+ EXPECT_TRUE(copy2.remove(1));
+ EXPECT_EQ(copy1.capacity(), copy2.capacity());
+ EXPECT_FALSE(copy2.contains(1));
+
+ EXPECT_TRUE(copy3.add(size + 2).isNewEntry);
+ EXPECT_EQ(copy1.capacity(), copy3.capacity());
+ EXPECT_TRUE(copy3.contains(size + 2));
+ }
+}
+
+TEST(WTF_HashSet, RefPtrNotZeroedBeforeDeref)
+{
+ struct DerefObserver {
+ NEVER_INLINE void ref()
+ {
+ ++count;
+ }
+ NEVER_INLINE void deref()
+ {
+ --count;
+ observedBucket = bucketAddress->get();
+ }
+ unsigned count { 1 };
+ const RefPtr<DerefObserver>* bucketAddress { nullptr };
+ const DerefObserver* observedBucket { nullptr };
+ };
+
+ auto observer = std::make_unique<DerefObserver>();
+
+ HashSet<RefPtr<DerefObserver>> set;
+ set.add(adoptRef(observer.get()));
+
+ auto iterator = set.find(observer.get());
+ EXPECT_TRUE(iterator != set.end());
+
+ observer->bucketAddress = iterator.get();
+
+ EXPECT_TRUE(observer->observedBucket == nullptr);
+ EXPECT_TRUE(set.remove(observer.get()));
+
+ // It if fine to either leave the old value intact at deletion or already set it to the deleted
+ // value.
+ // A zero would be a incorrect outcome as it would mean we nulled the bucket before an opaque
+ // call.
+ EXPECT_TRUE(observer->observedBucket == observer.get() || observer->observedBucket == RefPtr<DerefObserver>::hashTableDeletedValue());
+ EXPECT_EQ(observer->count, 0u);
+}
+
+
+TEST(WTF_HashSet, UniquePtrNotZeroedBeforeDestructor)
+{
+ struct DestructorObserver {
+ ~DestructorObserver()
+ {
+ observe();
+ }
+ std::function<void()> observe;
+ };
+
+ const std::unique_ptr<DestructorObserver>* bucketAddress = nullptr;
+ const DestructorObserver* observedBucket = nullptr;
+ std::unique_ptr<DestructorObserver> observer(new DestructorObserver { [&]() {
+ observedBucket = bucketAddress->get();
+ }});
+
+ const DestructorObserver* observerAddress = observer.get();
+
+ HashSet<std::unique_ptr<DestructorObserver>> set;
+ auto addResult = set.add(WTFMove(observer));
+
+ EXPECT_TRUE(addResult.isNewEntry);
+ EXPECT_TRUE(observedBucket == nullptr);
+
+ bucketAddress = addResult.iterator.get();
+
+ EXPECT_TRUE(observedBucket == nullptr);
+ EXPECT_TRUE(set.remove(*addResult.iterator));
+
+ EXPECT_TRUE(observedBucket == observerAddress || observedBucket == reinterpret_cast<const DestructorObserver*>(-1));
+}
+
+
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/ListHashSet.cpp b/Tools/TestWebKitAPI/Tests/WTF/ListHashSet.cpp
index a550a845b..d81dcfcfe 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/ListHashSet.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/ListHashSet.cpp
@@ -78,7 +78,7 @@ TEST(WTF_ListHashSet, AppendOrMoveToLastNewItems)
result = list.appendOrMoveToLast(3);
ASSERT_TRUE(result.isNewEntry);
- ASSERT_EQ(list.size(), 3);
+ ASSERT_EQ(list.size(), 3u);
// The list should be in order 1, 2, 3.
ListHashSet<int>::iterator iterator = list.begin();
@@ -99,11 +99,11 @@ TEST(WTF_ListHashSet, AppendOrMoveToLastWithDuplicates)
ASSERT_TRUE(result.isNewEntry);
result = list.appendOrMoveToLast(1);
ASSERT_FALSE(result.isNewEntry);
- ASSERT_EQ(1, list.size());
+ ASSERT_EQ(1u, list.size());
list.add(2);
list.add(3);
- ASSERT_EQ(3, list.size());
+ ASSERT_EQ(3u, list.size());
// Appending 2 move it to the end.
ASSERT_EQ(3, list.last());
@@ -118,7 +118,7 @@ TEST(WTF_ListHashSet, AppendOrMoveToLastWithDuplicates)
ASSERT_FALSE(result.isNewEntry);
result = list.appendOrMoveToLast(1);
ASSERT_FALSE(result.isNewEntry);
- ASSERT_EQ(3, list.size());
+ ASSERT_EQ(3u, list.size());
ListHashSet<int>::iterator iterator = list.begin();
ASSERT_EQ(3, *iterator);
@@ -139,7 +139,7 @@ TEST(WTF_ListHashSet, PrependOrMoveToLastNewItems)
result = list.prependOrMoveToFirst(3);
ASSERT_TRUE(result.isNewEntry);
- ASSERT_EQ(list.size(), 3);
+ ASSERT_EQ(list.size(), 3u);
// The list should be in order 3, 1, 2.
ListHashSet<int>::iterator iterator = list.begin();
@@ -160,11 +160,11 @@ TEST(WTF_ListHashSet, PrependOrMoveToLastWithDuplicates)
ASSERT_TRUE(result.isNewEntry);
result = list.prependOrMoveToFirst(1);
ASSERT_FALSE(result.isNewEntry);
- ASSERT_EQ(1, list.size());
+ ASSERT_EQ(1u, list.size());
list.add(2);
list.add(3);
- ASSERT_EQ(3, list.size());
+ ASSERT_EQ(3u, list.size());
// Prepending 2 move it to the beginning.
ASSERT_EQ(1, list.first());
@@ -179,7 +179,7 @@ TEST(WTF_ListHashSet, PrependOrMoveToLastWithDuplicates)
ASSERT_FALSE(result.isNewEntry);
result = list.prependOrMoveToFirst(3);
ASSERT_FALSE(result.isNewEntry);
- ASSERT_EQ(3, list.size());
+ ASSERT_EQ(3u, list.size());
ListHashSet<int>::iterator iterator = list.begin();
ASSERT_EQ(3, *iterator);
diff --git a/Tools/TestWebKitAPI/Tests/WTF/Lock.cpp b/Tools/TestWebKitAPI/Tests/WTF/Lock.cpp
new file mode 100644
index 000000000..5576302d6
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/Lock.cpp
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "config.h"
+#include <wtf/Lock.h>
+#include <wtf/Threading.h>
+#include <wtf/ThreadingPrimitives.h>
+#include <wtf/WordLock.h>
+
+using namespace WTF;
+
+namespace TestWebKitAPI {
+
+struct LockInspector {
+ template<typename LockType>
+ static bool isFullyReset(LockType& lock)
+ {
+ return lock.isFullyReset();
+ }
+};
+
+template<typename LockType>
+void runLockTest(unsigned numThreadGroups, unsigned numThreadsPerGroup, unsigned workPerCriticalSection, unsigned numIterations)
+{
+ std::unique_ptr<LockType[]> locks = std::make_unique<LockType[]>(numThreadGroups);
+ std::unique_ptr<double[]> words = std::make_unique<double[]>(numThreadGroups);
+ std::unique_ptr<ThreadIdentifier[]> threads = std::make_unique<ThreadIdentifier[]>(numThreadGroups * numThreadsPerGroup);
+
+ for (unsigned threadGroupIndex = numThreadGroups; threadGroupIndex--;) {
+ words[threadGroupIndex] = 0;
+
+ for (unsigned threadIndex = numThreadsPerGroup; threadIndex--;) {
+ threads[threadGroupIndex * numThreadsPerGroup + threadIndex] = createThread(
+ "Lock test thread",
+ [threadGroupIndex, &locks, &words, numIterations, workPerCriticalSection] () {
+ for (unsigned i = numIterations; i--;) {
+ locks[threadGroupIndex].lock();
+ for (unsigned j = workPerCriticalSection; j--;)
+ words[threadGroupIndex]++;
+ locks[threadGroupIndex].unlock();
+ }
+ });
+ }
+ }
+
+ for (unsigned threadIndex = numThreadGroups * numThreadsPerGroup; threadIndex--;)
+ waitForThreadCompletion(threads[threadIndex]);
+
+ double expected = 0;
+ for (uint64_t i = static_cast<uint64_t>(numIterations) * workPerCriticalSection * numThreadsPerGroup; i--;)
+ expected++;
+
+ for (unsigned threadGroupIndex = numThreadGroups; threadGroupIndex--;)
+ EXPECT_EQ(expected, words[threadGroupIndex]);
+
+ // Now test that the locks correctly reset themselves. We expect that if a single thread locks
+ // each of the locks twice in a row, then the lock should be in a pristine state.
+ for (unsigned threadGroupIndex = numThreadGroups; threadGroupIndex--;) {
+ for (unsigned i = 2; i--;) {
+ locks[threadGroupIndex].lock();
+ locks[threadGroupIndex].unlock();
+ }
+
+ EXPECT_EQ(true, LockInspector::isFullyReset(locks[threadGroupIndex]));
+ }
+}
+
+bool skipSlow()
+{
+#if PLATFORM(WIN) && !defined(NDEBUG)
+ return true;
+#else
+ return false;
+#endif
+}
+
+TEST(WTF_WordLock, UncontendedShortSection)
+{
+ runLockTest<WordLock>(1, 1, 1, 10000000);
+}
+
+TEST(WTF_WordLock, UncontendedLongSection)
+{
+ runLockTest<WordLock>(1, 1, 10000, 1000);
+}
+
+TEST(WTF_WordLock, ContendedShortSection)
+{
+ if (skipSlow())
+ return;
+ runLockTest<WordLock>(1, 10, 1, 5000000);
+}
+
+TEST(WTF_WordLock, ContendedLongSection)
+{
+ if (skipSlow())
+ return;
+ runLockTest<WordLock>(1, 10, 10000, 10000);
+}
+
+TEST(WTF_WordLock, ManyContendedShortSections)
+{
+ if (skipSlow())
+ return;
+ runLockTest<WordLock>(10, 10, 1, 500000);
+}
+
+TEST(WTF_WordLock, ManyContendedLongSections)
+{
+ if (skipSlow())
+ return;
+ runLockTest<WordLock>(10, 10, 10000, 500);
+}
+
+TEST(WTF_Lock, UncontendedShortSection)
+{
+ runLockTest<Lock>(1, 1, 1, 10000000);
+}
+
+TEST(WTF_Lock, UncontendedLongSection)
+{
+ runLockTest<Lock>(1, 1, 10000, 1000);
+}
+
+TEST(WTF_Lock, ContendedShortSection)
+{
+ if (skipSlow())
+ return;
+ runLockTest<Lock>(1, 10, 1, 10000000);
+}
+
+TEST(WTF_Lock, ContendedLongSection)
+{
+ if (skipSlow())
+ return;
+ runLockTest<Lock>(1, 10, 10000, 10000);
+}
+
+TEST(WTF_Lock, ManyContendedShortSections)
+{
+ if (skipSlow())
+ return;
+ runLockTest<Lock>(10, 10, 1, 500000);
+}
+
+TEST(WTF_Lock, ManyContendedLongSections)
+{
+ if (skipSlow())
+ return;
+ runLockTest<Lock>(10, 10, 10000, 1000);
+}
+
+TEST(WTF_Lock, ManyContendedLongerSections)
+{
+ if (skipSlow())
+ return;
+ runLockTest<Lock>(10, 10, 100000, 1);
+}
+
+TEST(WTF_Lock, SectionAddressCollision)
+{
+ if (skipSlow())
+ return;
+ runLockTest<Lock>(4, 2, 10000, 2000);
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/MediaTime.cpp b/Tools/TestWebKitAPI/Tests/WTF/MediaTime.cpp
index 8e9b178af..2386143e3 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/MediaTime.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/MediaTime.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.
*
@@ -26,24 +26,14 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#define _USE_MATH_DEFINES 1
#include "config.h"
+#include <limits>
+#include <wtf/MathExtras.h>
#include <wtf/MediaTime.h>
using namespace std;
-#if COMPILER(MSVC)
-// Work around Visual Studio 2008's lack of an INFINITY or NAN definition.
-#include <limits>
-#if !defined(INFINITY)
-#define INFINITY (numeric_limits<double>::infinity())
-#endif
-#if !defined(NAN)
-#define NAN (numeric_limits<double>::quiet_NaN())
-#endif
-#endif
-
namespace WTF {
std::ostream& operator<<(std::ostream& out, const MediaTime& val)
@@ -55,6 +45,8 @@ std::ostream& operator<<(std::ostream& out, const MediaTime& val)
out << "+infinite";
else if (val.isNegativeInfinite())
out << "-infinite";
+ else if (val.hasDoubleValue())
+ out << "double: " << val.toDouble();
else
out << "value: " << val.timeValue() << ", scale: " << val.timeScale();
return out << " }";
@@ -180,13 +172,29 @@ TEST(WTF, MediaTime)
EXPECT_EQ(MediaTime(3, 2).toDouble(), 1.5);
EXPECT_EQ(MediaTime(1, 1 << 16).toFloat(), 1 / pow(2.0f, 16.0f));
EXPECT_EQ(MediaTime(1, 1 << 30).toDouble(), 1 / pow(2.0, 30.0));
- EXPECT_EQ(MediaTime::createWithDouble(M_PI, 1 << 30), MediaTime(3373259426U, 1 << 30));
- EXPECT_EQ(MediaTime::createWithFloat(INFINITY), MediaTime::positiveInfiniteTime());
- EXPECT_EQ(MediaTime::createWithFloat(-INFINITY), MediaTime::negativeInfiniteTime());
- EXPECT_EQ(MediaTime::createWithFloat(NAN), MediaTime::invalidTime());
- EXPECT_EQ(MediaTime::createWithDouble(INFINITY), MediaTime::positiveInfiniteTime());
- EXPECT_EQ(MediaTime::createWithDouble(-INFINITY), MediaTime::negativeInfiniteTime());
- EXPECT_EQ(MediaTime::createWithDouble(NAN), MediaTime::invalidTime());
+ EXPECT_EQ(MediaTime::createWithDouble(piDouble, 1 << 30), MediaTime(3373259426U, 1 << 30));
+
+ EXPECT_EQ(MediaTime::createWithFloat(std::numeric_limits<float>::infinity()), MediaTime::positiveInfiniteTime());
+ EXPECT_EQ(MediaTime::createWithFloat(-std::numeric_limits<float>::infinity()), MediaTime::negativeInfiniteTime());
+ EXPECT_EQ(MediaTime::createWithFloat(std::numeric_limits<float>::quiet_NaN()), MediaTime::invalidTime());
+
+ EXPECT_EQ(MediaTime::createWithDouble(std::numeric_limits<double>::infinity()), MediaTime::positiveInfiniteTime());
+ EXPECT_EQ(MediaTime::createWithDouble(-std::numeric_limits<double>::infinity()), MediaTime::negativeInfiniteTime());
+ EXPECT_EQ(MediaTime::createWithDouble(std::numeric_limits<double>::quiet_NaN()), MediaTime::invalidTime());
+
+ // Floating Point Round Trip
+ EXPECT_EQ(10.0123456789f, MediaTime::createWithFloat(10.0123456789f).toFloat());
+ EXPECT_EQ(10.0123456789, MediaTime::createWithDouble(10.0123456789).toDouble());
+
+ // Floating Point Math
+ EXPECT_EQ(1.5 + 3.3, (MediaTime::createWithDouble(1.5) + MediaTime::createWithDouble(3.3)).toDouble());
+ EXPECT_EQ(1.5 - 3.3, (MediaTime::createWithDouble(1.5) - MediaTime::createWithDouble(3.3)).toDouble());
+ EXPECT_EQ(-3.3, (-MediaTime::createWithDouble(3.3)).toDouble());
+ EXPECT_EQ(3.3 * 2, (MediaTime::createWithDouble(3.3) * 2).toDouble());
+
+ // Floating Point and non-Floating Point math
+ EXPECT_EQ(2.0, (MediaTime::createWithDouble(1.5) + MediaTime(1, 2)).toDouble());
+ EXPECT_EQ(1.0, (MediaTime::createWithDouble(1.5) - MediaTime(1, 2)).toDouble());
// Overflow Behavior
EXPECT_EQ(MediaTime::createWithFloat(pow(2.0f, 64.0f)), MediaTime::positiveInfiniteTime());
diff --git a/Tools/TestWebKitAPI/Tests/WTF/MetaAllocator.cpp b/Tools/TestWebKitAPI/Tests/WTF/MetaAllocator.cpp
index 61c16d1ab..59af4f849 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/MetaAllocator.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/MetaAllocator.cpp
@@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -31,6 +31,10 @@
#include <wtf/MetaAllocator.h>
#include <wtf/Vector.h>
+#if OS(WINDOWS)
+#undef small
+#endif
+
using namespace WTF;
namespace TestWebKitAPI {
diff --git a/Tools/TestWebKitAPI/Tests/WTF/NakedPtr.cpp b/Tools/TestWebKitAPI/Tests/WTF/NakedPtr.cpp
new file mode 100644
index 000000000..f4b4836cd
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/NakedPtr.cpp
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 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. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "RefLogger.h"
+#include <wtf/NakedPtr.h>
+
+namespace TestWebKitAPI {
+
+// For these tests, we need a base class and a derived class. For this purpose,
+// we reuse the RefLogger and DerivedRefLogger classes.
+
+TEST(WTF_NakedPtr, Basic)
+{
+ DerivedRefLogger a("a");
+
+ NakedPtr<RefLogger> empty;
+ ASSERT_EQ(nullptr, empty.get());
+
+ {
+ NakedPtr<RefLogger> ptr(&a);
+ ASSERT_EQ(&a, ptr.get());
+ ASSERT_EQ(&a, &*ptr);
+ ASSERT_EQ(&a.name, &ptr->name);
+ }
+
+ {
+ NakedPtr<RefLogger> ptr = &a;
+ ASSERT_EQ(&a, ptr.get());
+ }
+
+ {
+ NakedPtr<RefLogger> p1 = &a;
+ NakedPtr<RefLogger> p2(p1);
+ ASSERT_EQ(&a, p1.get());
+ ASSERT_EQ(&a, p2.get());
+ }
+
+ {
+ NakedPtr<RefLogger> p1 = &a;
+ NakedPtr<RefLogger> p2 = p1;
+ ASSERT_EQ(&a, p1.get());
+ ASSERT_EQ(&a, p2.get());
+ }
+
+ {
+ NakedPtr<RefLogger> p1 = &a;
+ NakedPtr<RefLogger> p2 = WTFMove(p1);
+ ASSERT_EQ(&a, p1.get());
+ ASSERT_EQ(&a, p2.get());
+ }
+
+ {
+ NakedPtr<RefLogger> p1 = &a;
+ NakedPtr<RefLogger> p2(WTFMove(p1));
+ ASSERT_EQ(&a, p1.get());
+ ASSERT_EQ(&a, p2.get());
+ }
+
+ {
+ NakedPtr<DerivedRefLogger> p1 = &a;
+ NakedPtr<RefLogger> p2 = p1;
+ ASSERT_EQ(&a, p1.get());
+ ASSERT_EQ(&a, p2.get());
+ }
+
+ {
+ NakedPtr<DerivedRefLogger> p1 = &a;
+ NakedPtr<RefLogger> p2 = WTFMove(p1);
+ ASSERT_EQ(&a, p1.get());
+ ASSERT_EQ(&a, p2.get());
+ }
+
+ {
+ NakedPtr<RefLogger> ptr(&a);
+ ASSERT_EQ(&a, ptr.get());
+ ptr.clear();
+ ASSERT_EQ(nullptr, ptr.get());
+ }
+}
+
+TEST(WTF_NakedPtr, Assignment)
+{
+ DerivedRefLogger a("a");
+ RefLogger b("b");
+ DerivedRefLogger c("c");
+
+ {
+ NakedPtr<RefLogger> p1(&a);
+ NakedPtr<RefLogger> p2(&b);
+ ASSERT_EQ(&a, p1.get());
+ ASSERT_EQ(&b, p2.get());
+ p1 = p2;
+ ASSERT_EQ(&b, p1.get());
+ ASSERT_EQ(&b, p2.get());
+ }
+
+ {
+ NakedPtr<RefLogger> ptr(&a);
+ ASSERT_EQ(&a, ptr.get());
+ ptr = &b;
+ ASSERT_EQ(&b, ptr.get());
+ }
+
+ {
+ NakedPtr<RefLogger> ptr(&a);
+ ASSERT_EQ(&a, ptr.get());
+ ptr = nullptr;
+ ASSERT_EQ(nullptr, ptr.get());
+ }
+
+ {
+ NakedPtr<RefLogger> p1(&a);
+ NakedPtr<RefLogger> p2(&b);
+ ASSERT_EQ(&a, p1.get());
+ ASSERT_EQ(&b, p2.get());
+ p1 = WTFMove(p2);
+ ASSERT_EQ(&b, p1.get());
+ ASSERT_EQ(&b, p2.get());
+ }
+
+ {
+ NakedPtr<RefLogger> p1(&a);
+ NakedPtr<DerivedRefLogger> p2(&c);
+ ASSERT_EQ(&a, p1.get());
+ ASSERT_EQ(&c, p2.get());
+ p1 = p2;
+ ASSERT_EQ(&c, p1.get());
+ ASSERT_EQ(&c, p2.get());
+ }
+
+ {
+ NakedPtr<RefLogger> ptr(&a);
+ ASSERT_EQ(&a, ptr.get());
+ ptr = &c;
+ ASSERT_EQ(&c, ptr.get());
+ }
+
+ {
+ NakedPtr<RefLogger> p1(&a);
+ NakedPtr<DerivedRefLogger> p2(&c);
+ ASSERT_EQ(&a, p1.get());
+ ASSERT_EQ(&c, p2.get());
+ p1 = WTFMove(p2);
+ ASSERT_EQ(&c, p1.get());
+ ASSERT_EQ(&c, p2.get());
+ }
+
+ {
+ NakedPtr<RefLogger> ptr(&a);
+ ASSERT_EQ(&a, ptr.get());
+ ptr = ptr;
+ ASSERT_EQ(&a, ptr.get());
+ }
+
+ {
+ NakedPtr<RefLogger> ptr(&a);
+ ASSERT_EQ(&a, ptr.get());
+#if COMPILER(CLANG)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wself-move"
+#endif
+ ptr = WTFMove(ptr);
+#if COMPILER(CLANG)
+#pragma clang diagnostic pop
+#endif
+ ASSERT_EQ(&a, ptr.get());
+ }
+}
+
+TEST(WTF_NakedPtr, Swap)
+{
+ RefLogger a("a");
+ RefLogger b("b");
+
+ {
+ NakedPtr<RefLogger> p1(&a);
+ NakedPtr<RefLogger> p2(&b);
+ ASSERT_EQ(&a, p1.get());
+ ASSERT_EQ(&b, p2.get());
+ p1.swap(p2);
+ ASSERT_EQ(&b, p1.get());
+ ASSERT_EQ(&a, p2.get());
+ }
+
+ {
+ NakedPtr<RefLogger> p1(&a);
+ NakedPtr<RefLogger> p2(&b);
+ ASSERT_EQ(&a, p1.get());
+ ASSERT_EQ(&b, p2.get());
+ std::swap(p1, p2);
+ ASSERT_EQ(&b, p1.get());
+ ASSERT_EQ(&a, p2.get());
+ }
+}
+
+NakedPtr<RefLogger> nakedPtrFoo(RefLogger& logger)
+{
+ return NakedPtr<RefLogger>(&logger);
+}
+
+TEST(WTF_NakedPtr, ReturnValue)
+{
+ DerivedRefLogger a("a");
+
+ {
+ auto ptr = nakedPtrFoo(a);
+ ASSERT_EQ(&a, ptr.get());
+ ASSERT_EQ(&a, &*ptr);
+ ASSERT_EQ(&a.name, &ptr->name);
+ }
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/OptionSet.cpp b/Tools/TestWebKitAPI/Tests/WTF/OptionSet.cpp
new file mode 100644
index 000000000..37efc9939
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/OptionSet.cpp
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "Test.h"
+#include <wtf/OptionSet.h>
+
+namespace TestWebKitAPI {
+
+enum class ExampleFlags : uint64_t {
+ A = 1 << 0,
+ B = 1 << 1,
+ C = 1 << 2,
+ D = 1ULL << 31,
+ E = 1ULL << 63,
+};
+
+TEST(WTF_OptionSet, EmptySet)
+{
+ OptionSet<ExampleFlags> set;
+ EXPECT_TRUE(set.isEmpty());
+ EXPECT_FALSE(set.contains(ExampleFlags::A));
+ EXPECT_FALSE(set.contains(ExampleFlags::B));
+ EXPECT_FALSE(set.contains(ExampleFlags::C));
+ EXPECT_FALSE(set.contains(ExampleFlags::D));
+ EXPECT_FALSE(set.contains(ExampleFlags::E));
+}
+
+TEST(WTF_OptionSet, ContainsOneFlag)
+{
+ OptionSet<ExampleFlags> set = ExampleFlags::A;
+ EXPECT_FALSE(set.isEmpty());
+ EXPECT_TRUE(set.contains(ExampleFlags::A));
+ EXPECT_FALSE(set.contains(ExampleFlags::B));
+ EXPECT_FALSE(set.contains(ExampleFlags::C));
+ EXPECT_FALSE(set.contains(ExampleFlags::D));
+ EXPECT_FALSE(set.contains(ExampleFlags::E));
+}
+
+TEST(WTF_OptionSet, ContainsTwoFlags)
+{
+ OptionSet<ExampleFlags> set { ExampleFlags::A, ExampleFlags::B };
+ EXPECT_FALSE(set.isEmpty());
+ EXPECT_TRUE(set.contains(ExampleFlags::A));
+ EXPECT_TRUE(set.contains(ExampleFlags::B));
+ EXPECT_FALSE(set.contains(ExampleFlags::C));
+ EXPECT_FALSE(set.contains(ExampleFlags::D));
+ EXPECT_FALSE(set.contains(ExampleFlags::E));
+}
+
+TEST(WTF_OptionSet, ContainsTwoFlags2)
+{
+ OptionSet<ExampleFlags> set { ExampleFlags::A, ExampleFlags::D };
+ EXPECT_FALSE(set.isEmpty());
+ EXPECT_TRUE(set.contains(ExampleFlags::A));
+ EXPECT_TRUE(set.contains(ExampleFlags::D));
+ EXPECT_FALSE(set.contains(ExampleFlags::B));
+ EXPECT_FALSE(set.contains(ExampleFlags::C));
+ EXPECT_FALSE(set.contains(ExampleFlags::E));
+}
+
+TEST(WTF_OptionSet, ContainsTwoFlags3)
+{
+ OptionSet<ExampleFlags> set { ExampleFlags::D, ExampleFlags::E };
+ EXPECT_FALSE(set.isEmpty());
+ EXPECT_TRUE(set.contains(ExampleFlags::D));
+ EXPECT_TRUE(set.contains(ExampleFlags::E));
+ EXPECT_FALSE(set.contains(ExampleFlags::A));
+ EXPECT_FALSE(set.contains(ExampleFlags::B));
+ EXPECT_FALSE(set.contains(ExampleFlags::C));
+}
+
+TEST(WTF_OptionSet, OperatorBitwiseOr)
+{
+ OptionSet<ExampleFlags> set = ExampleFlags::A;
+ set |= ExampleFlags::C;
+ EXPECT_TRUE(set.contains(ExampleFlags::A));
+ EXPECT_FALSE(set.contains(ExampleFlags::B));
+ EXPECT_TRUE(set.contains(ExampleFlags::C));
+}
+
+TEST(WTF_OptionSet, EmptyOptionSetToRawValueToOptionSet)
+{
+ OptionSet<ExampleFlags> set;
+ EXPECT_TRUE(set.isEmpty());
+ EXPECT_FALSE(set.contains(ExampleFlags::A));
+ EXPECT_FALSE(set.contains(ExampleFlags::B));
+ EXPECT_FALSE(set.contains(ExampleFlags::C));
+
+ auto set2 = OptionSet<ExampleFlags>::fromRaw(set.toRaw());
+ EXPECT_TRUE(set2.isEmpty());
+ EXPECT_FALSE(set2.contains(ExampleFlags::A));
+ EXPECT_FALSE(set2.contains(ExampleFlags::B));
+ EXPECT_FALSE(set2.contains(ExampleFlags::C));
+}
+
+TEST(WTF_OptionSet, OptionSetThatContainsOneFlagToRawValueToOptionSet)
+{
+ OptionSet<ExampleFlags> set = ExampleFlags::A;
+ EXPECT_FALSE(set.isEmpty());
+ EXPECT_TRUE(set.contains(ExampleFlags::A));
+ EXPECT_FALSE(set.contains(ExampleFlags::B));
+ EXPECT_FALSE(set.contains(ExampleFlags::C));
+ EXPECT_FALSE(set.contains(ExampleFlags::D));
+ EXPECT_FALSE(set.contains(ExampleFlags::E));
+
+ auto set2 = OptionSet<ExampleFlags>::fromRaw(set.toRaw());
+ EXPECT_FALSE(set2.isEmpty());
+ EXPECT_TRUE(set2.contains(ExampleFlags::A));
+ EXPECT_FALSE(set2.contains(ExampleFlags::B));
+ EXPECT_FALSE(set2.contains(ExampleFlags::C));
+ EXPECT_FALSE(set2.contains(ExampleFlags::D));
+ EXPECT_FALSE(set2.contains(ExampleFlags::E));
+}
+
+TEST(WTF_OptionSet, OptionSetThatContainsOneFlagToRawValueToOptionSet2)
+{
+ OptionSet<ExampleFlags> set = ExampleFlags::E;
+ EXPECT_FALSE(set.isEmpty());
+ EXPECT_TRUE(set.contains(ExampleFlags::E));
+ EXPECT_FALSE(set.contains(ExampleFlags::A));
+ EXPECT_FALSE(set.contains(ExampleFlags::B));
+ EXPECT_FALSE(set.contains(ExampleFlags::C));
+ EXPECT_FALSE(set.contains(ExampleFlags::D));
+
+ auto set2 = OptionSet<ExampleFlags>::fromRaw(set.toRaw());
+ EXPECT_FALSE(set2.isEmpty());
+ EXPECT_TRUE(set2.contains(ExampleFlags::E));
+ EXPECT_FALSE(set2.contains(ExampleFlags::A));
+ EXPECT_FALSE(set2.contains(ExampleFlags::B));
+ EXPECT_FALSE(set2.contains(ExampleFlags::C));
+ EXPECT_FALSE(set2.contains(ExampleFlags::D));
+}
+
+TEST(WTF_OptionSet, OptionSetThatContainsTwoFlagsToRawValueToOptionSet)
+{
+ OptionSet<ExampleFlags> set { ExampleFlags::A, ExampleFlags::C };
+ EXPECT_FALSE(set.isEmpty());
+ EXPECT_TRUE(set.contains(ExampleFlags::A));
+ EXPECT_TRUE(set.contains(ExampleFlags::C));
+ EXPECT_FALSE(set.contains(ExampleFlags::B));
+
+ auto set2 = OptionSet<ExampleFlags>::fromRaw(set.toRaw());
+ EXPECT_FALSE(set2.isEmpty());
+ EXPECT_TRUE(set2.contains(ExampleFlags::A));
+ EXPECT_TRUE(set2.contains(ExampleFlags::C));
+ EXPECT_FALSE(set2.contains(ExampleFlags::B));
+}
+
+TEST(WTF_OptionSet, OptionSetThatContainsTwoFlagsToRawValueToOptionSet2)
+{
+ OptionSet<ExampleFlags> set { ExampleFlags::D, ExampleFlags::E };
+ EXPECT_FALSE(set.isEmpty());
+ EXPECT_TRUE(set.contains(ExampleFlags::D));
+ EXPECT_TRUE(set.contains(ExampleFlags::E));
+ EXPECT_FALSE(set.contains(ExampleFlags::A));
+ EXPECT_FALSE(set.contains(ExampleFlags::B));
+ EXPECT_FALSE(set.contains(ExampleFlags::C));
+
+ auto set2 = OptionSet<ExampleFlags>::fromRaw(set.toRaw());
+ EXPECT_FALSE(set2.isEmpty());
+ EXPECT_TRUE(set2.contains(ExampleFlags::D));
+ EXPECT_TRUE(set2.contains(ExampleFlags::E));
+ EXPECT_FALSE(set2.contains(ExampleFlags::A));
+ EXPECT_FALSE(set2.contains(ExampleFlags::B));
+ EXPECT_FALSE(set2.contains(ExampleFlags::C));
+}
+
+TEST(WTF_OptionSet, TwoIteratorsIntoSameOptionSet)
+{
+ OptionSet<ExampleFlags> set { ExampleFlags::C, ExampleFlags::B };
+ OptionSet<ExampleFlags>::iterator it1 = set.begin();
+ OptionSet<ExampleFlags>::iterator it2 = it1;
+ ++it1;
+ EXPECT_STRONG_ENUM_EQ(ExampleFlags::C, *it1);
+ EXPECT_STRONG_ENUM_EQ(ExampleFlags::B, *it2);
+}
+
+TEST(WTF_OptionSet, IterateOverOptionSetThatContainsTwoFlags)
+{
+ OptionSet<ExampleFlags> set { ExampleFlags::A, ExampleFlags::C };
+ OptionSet<ExampleFlags>::iterator it = set.begin();
+ OptionSet<ExampleFlags>::iterator end = set.end();
+ EXPECT_TRUE(it != end);
+ EXPECT_STRONG_ENUM_EQ(ExampleFlags::A, *it);
+ ++it;
+ EXPECT_STRONG_ENUM_EQ(ExampleFlags::C, *it);
+ ++it;
+ EXPECT_TRUE(it == end);
+}
+
+TEST(WTF_OptionSet, IterateOverOptionSetThatContainsFlags2)
+{
+ OptionSet<ExampleFlags> set { ExampleFlags::D, ExampleFlags::E };
+ OptionSet<ExampleFlags>::iterator it = set.begin();
+ OptionSet<ExampleFlags>::iterator end = set.end();
+ EXPECT_TRUE(it != end);
+ EXPECT_STRONG_ENUM_EQ(ExampleFlags::D, *it);
+ ++it;
+ EXPECT_STRONG_ENUM_EQ(ExampleFlags::E, *it);
+ ++it;
+ EXPECT_TRUE(it == end);
+}
+
+TEST(WTF_OptionSet, NextItemAfterLargestIn32BitFlagSet)
+{
+ enum class ThirtyTwoBitFlags : uint32_t {
+ A = 1UL << 31,
+ };
+ OptionSet<ThirtyTwoBitFlags> set { ThirtyTwoBitFlags::A };
+ OptionSet<ThirtyTwoBitFlags>::iterator it = set.begin();
+ OptionSet<ThirtyTwoBitFlags>::iterator end = set.end();
+ EXPECT_TRUE(it != end);
+ ++it;
+ EXPECT_TRUE(it == end);
+}
+
+TEST(WTF_OptionSet, NextItemAfterLargestIn64BitFlagSet)
+{
+ enum class SixtyFourBitFlags : uint64_t {
+ A = 1ULL << 63,
+ };
+ OptionSet<SixtyFourBitFlags> set { SixtyFourBitFlags::A };
+ OptionSet<SixtyFourBitFlags>::iterator it = set.begin();
+ OptionSet<SixtyFourBitFlags>::iterator end = set.end();
+ EXPECT_TRUE(it != end);
+ ++it;
+ EXPECT_TRUE(it == end);
+}
+
+TEST(WTF_OptionSet, IterationOrderTheSameRegardlessOfInsertionOrder)
+{
+ OptionSet<ExampleFlags> set1 = ExampleFlags::C;
+ set1 |= ExampleFlags::A;
+
+ OptionSet<ExampleFlags> set2 = ExampleFlags::A;
+ set2 |= ExampleFlags::C;
+
+ OptionSet<ExampleFlags>::iterator it1 = set1.begin();
+ OptionSet<ExampleFlags>::iterator it2 = set2.begin();
+
+ EXPECT_TRUE(*it1 == *it2);
+ ++it1;
+ ++it2;
+ EXPECT_TRUE(*it1 == *it2);
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/Optional.cpp b/Tools/TestWebKitAPI/Tests/WTF/Optional.cpp
new file mode 100644
index 000000000..a0715fd62
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/Optional.cpp
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <wtf/Optional.h>
+
+namespace TestWebKitAPI {
+
+TEST(WTF_Optional, Disengaged)
+{
+ {
+ Optional<int> optional;
+
+ EXPECT_FALSE(static_cast<bool>(optional));
+ }
+
+ {
+ Optional<int> optional { Nullopt };
+
+ EXPECT_FALSE(static_cast<bool>(optional));
+ }
+}
+
+TEST(WTF_Optional, Engaged)
+{
+ Optional<int> optional { 10 };
+
+ EXPECT_TRUE(static_cast<bool>(optional));
+ EXPECT_EQ(10, optional.value());
+}
+
+TEST(WTF_Optional, Destructor)
+{
+ static bool didCallDestructor = false;
+ struct A {
+ ~A()
+ {
+ EXPECT_FALSE(didCallDestructor);
+ didCallDestructor = true;
+ }
+ };
+
+ {
+ Optional<A> optional { InPlace };
+
+ EXPECT_TRUE(static_cast<bool>(optional));
+ }
+
+ EXPECT_TRUE(didCallDestructor);
+}
+
+TEST(WTF_Optional, Callback)
+{
+ bool called = false;
+ Optional<int> a;
+ int result = a.valueOrCompute([&] {
+ called = true;
+ return 300;
+ });
+ EXPECT_TRUE(called);
+ EXPECT_EQ(result, 300);
+
+ a = 250;
+ called = false;
+ result = a.valueOrCompute([&] {
+ called = true;
+ return 300;
+ });
+ EXPECT_FALSE(called);
+ EXPECT_EQ(result, 250);
+}
+
+TEST(WTF_Optional, Equality)
+{
+ Optional<int> unengaged1;
+ Optional<int> unengaged2;
+
+ Optional<int> engaged1 { 1 };
+ Optional<int> engaged2 { 2 };
+ Optional<int> engagedx2 { 2 };
+
+ EXPECT_TRUE(unengaged1 == unengaged2);
+ EXPECT_FALSE(engaged1 == engaged2);
+ EXPECT_FALSE(engaged1 == unengaged1);
+ EXPECT_TRUE(engaged2 == engagedx2);
+
+ EXPECT_TRUE(unengaged1 == Nullopt);
+ EXPECT_FALSE(engaged1 == Nullopt);
+ EXPECT_TRUE(Nullopt == unengaged1);
+ EXPECT_FALSE(Nullopt == engaged1);
+
+ EXPECT_TRUE(engaged1 == 1);
+ EXPECT_TRUE(1 == engaged1);
+ EXPECT_FALSE(unengaged1 == 1);
+ EXPECT_FALSE(1 == unengaged1);
+}
+
+TEST(WTF_Optional, Inequality)
+{
+ Optional<int> unengaged1;
+ Optional<int> unengaged2;
+
+ Optional<int> engaged1 { 1 };
+ Optional<int> engaged2 { 2 };
+ Optional<int> engagedx2 { 2 };
+
+ EXPECT_FALSE(unengaged1 != unengaged2);
+ EXPECT_TRUE(engaged1 != engaged2);
+ EXPECT_TRUE(engaged1 != unengaged1);
+ EXPECT_FALSE(engaged2 != engagedx2);
+
+ EXPECT_FALSE(unengaged1 != Nullopt);
+ EXPECT_TRUE(engaged1 != Nullopt);
+ EXPECT_FALSE(Nullopt != unengaged1);
+ EXPECT_TRUE(Nullopt != engaged1);
+
+ EXPECT_FALSE(engaged1 != 1);
+ EXPECT_TRUE(engaged1 != 2);
+ EXPECT_FALSE(1 != engaged1);
+ EXPECT_TRUE(2 != engaged1);
+
+ EXPECT_TRUE(unengaged1 != 1);
+ EXPECT_TRUE(1 != unengaged1);
+}
+
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/ParkingLot.cpp b/Tools/TestWebKitAPI/Tests/WTF/ParkingLot.cpp
new file mode 100644
index 000000000..b6a881fe0
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/ParkingLot.cpp
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "config.h"
+#include <condition_variable>
+#include <mutex>
+#include <thread>
+#include <wtf/DataLog.h>
+#include <wtf/HashSet.h>
+#include <wtf/ListDump.h>
+#include <wtf/ParkingLot.h>
+#include <wtf/Threading.h>
+#include <wtf/ThreadingPrimitives.h>
+
+using namespace WTF;
+
+namespace TestWebKitAPI {
+
+namespace {
+
+struct SingleLatchTest {
+ void initialize(unsigned numThreads)
+ {
+ // This implements a fair (FIFO) semaphore, and it starts out unavailable.
+ semaphore.store(0);
+
+ for (unsigned i = numThreads; i--;) {
+ threads.append(
+ createThread(
+ "Parking Test Thread",
+ [&] () {
+ EXPECT_NE(0u, currentThread());
+
+ down();
+
+ std::lock_guard<std::mutex> locker(lock);
+ awake.add(currentThread());
+ lastAwoken = currentThread();
+ condition.notify_one();
+ }));
+ }
+ }
+
+ void unparkOne(unsigned singleUnparkIndex)
+ {
+ EXPECT_EQ(0u, lastAwoken);
+
+ unsigned numWaitingOnAddress = 0;
+ Vector<ThreadIdentifier, 8> queue;
+ ParkingLot::forEach(
+ [&] (ThreadIdentifier threadIdentifier, const void* address) {
+ if (address != &semaphore)
+ return;
+
+ queue.append(threadIdentifier);
+
+ numWaitingOnAddress++;
+ });
+
+ EXPECT_LE(numWaitingOnAddress, threads.size() - singleUnparkIndex);
+
+ up();
+
+ {
+ std::unique_lock<std::mutex> locker(lock);
+ while (awake.size() < singleUnparkIndex + 1)
+ condition.wait(locker);
+ EXPECT_NE(0u, lastAwoken);
+ if (!queue.isEmpty() && queue[0] != lastAwoken) {
+ dataLog("Woke up wrong thread: queue = ", listDump(queue), ", last awoken = ", lastAwoken, "\n");
+ EXPECT_EQ(queue[0], lastAwoken);
+ }
+ lastAwoken = 0;
+ }
+ }
+
+ void finish(unsigned numSingleUnparks)
+ {
+ unsigned numWaitingOnAddress = 0;
+ ParkingLot::forEach(
+ [&] (ThreadIdentifier, const void* address) {
+ if (address != &semaphore)
+ return;
+
+ numWaitingOnAddress++;
+ });
+
+ EXPECT_LE(numWaitingOnAddress, threads.size() - numSingleUnparks);
+
+ semaphore.store(threads.size() - numSingleUnparks);
+ ParkingLot::unparkAll(&semaphore);
+
+ numWaitingOnAddress = 0;
+ ParkingLot::forEach(
+ [&] (ThreadIdentifier, const void* address) {
+ if (address != &semaphore)
+ return;
+
+ numWaitingOnAddress++;
+ });
+
+ EXPECT_EQ(0u, numWaitingOnAddress);
+
+ {
+ std::unique_lock<std::mutex> locker(lock);
+ while (awake.size() < threads.size())
+ condition.wait(locker);
+ }
+
+ for (ThreadIdentifier threadIdentifier : threads)
+ waitForThreadCompletion(threadIdentifier);
+ }
+
+ // Semaphore operations.
+ void down()
+ {
+ for (;;) {
+ int oldSemaphoreValue = semaphore.load();
+ int newSemaphoreValue = oldSemaphoreValue - 1;
+ if (!semaphore.compareExchangeWeak(oldSemaphoreValue, newSemaphoreValue))
+ continue;
+
+ if (oldSemaphoreValue > 0) {
+ // We acquired the semaphore. Done.
+ return;
+ }
+
+ // We need to wait.
+ if (ParkingLot::compareAndPark(&semaphore, newSemaphoreValue)) {
+ // We did wait, and then got woken up. This means that someone who up'd the semaphore
+ // passed ownership onto us.
+ return;
+ }
+
+ // We never parked, because the semaphore value changed. Undo our decrement and try again.
+ for (;;) {
+ int oldSemaphoreValue = semaphore.load();
+ if (semaphore.compareExchangeWeak(oldSemaphoreValue, oldSemaphoreValue + 1))
+ break;
+ }
+ }
+ }
+ void up()
+ {
+ int oldSemaphoreValue;
+ for (;;) {
+ oldSemaphoreValue = semaphore.load();
+ if (semaphore.compareExchangeWeak(oldSemaphoreValue, oldSemaphoreValue + 1))
+ break;
+ }
+
+ // Check if anyone was waiting on the semaphore. If they were, then pass ownership to them.
+ if (oldSemaphoreValue < 0)
+ ParkingLot::unparkOne(&semaphore);
+ }
+
+ Atomic<int> semaphore;
+ std::mutex lock;
+ std::condition_variable condition;
+ HashSet<ThreadIdentifier> awake;
+ Vector<ThreadIdentifier> threads;
+ ThreadIdentifier lastAwoken { 0 };
+};
+
+void runParkingTest(unsigned numLatches, unsigned delay, unsigned numThreads, unsigned numSingleUnparks)
+{
+ std::unique_ptr<SingleLatchTest[]> tests = std::make_unique<SingleLatchTest[]>(numLatches);
+
+ for (unsigned latchIndex = numLatches; latchIndex--;)
+ tests[latchIndex].initialize(numThreads);
+
+ for (unsigned unparkIndex = 0; unparkIndex < numSingleUnparks; ++unparkIndex) {
+ std::this_thread::sleep_for(std::chrono::microseconds(delay));
+ for (unsigned latchIndex = numLatches; latchIndex--;)
+ tests[latchIndex].unparkOne(unparkIndex);
+ }
+
+ for (unsigned latchIndex = numLatches; latchIndex--;)
+ tests[latchIndex].finish(numSingleUnparks);
+}
+
+void repeatParkingTest(unsigned numRepeats, unsigned numLatches, unsigned delay, unsigned numThreads, unsigned numSingleUnparks)
+{
+ while (numRepeats--)
+ runParkingTest(numLatches, delay, numThreads, numSingleUnparks);
+}
+
+} // anonymous namespace
+
+TEST(WTF_ParkingLot, UnparkAllOneFast)
+{
+ repeatParkingTest(10000, 1, 0, 1, 0);
+}
+
+TEST(WTF_ParkingLot, UnparkAllHundredFast)
+{
+ repeatParkingTest(100, 1, 0, 100, 0);
+}
+
+TEST(WTF_ParkingLot, UnparkOneOneFast)
+{
+ repeatParkingTest(1000, 1, 0, 1, 1);
+}
+
+TEST(WTF_ParkingLot, UnparkOneHundredFast)
+{
+ repeatParkingTest(20, 1, 0, 100, 100);
+}
+
+TEST(WTF_ParkingLot, UnparkOneFiftyThenFiftyAllFast)
+{
+ repeatParkingTest(50, 1, 0, 100, 50);
+}
+
+TEST(WTF_ParkingLot, UnparkAllOne)
+{
+ repeatParkingTest(100, 1, 10000, 1, 0);
+}
+
+TEST(WTF_ParkingLot, UnparkAllHundred)
+{
+ repeatParkingTest(100, 1, 10000, 100, 0);
+}
+
+TEST(WTF_ParkingLot, UnparkOneOne)
+{
+ repeatParkingTest(10, 1, 10000, 1, 1);
+}
+
+TEST(WTF_ParkingLot, UnparkOneFifty)
+{
+ repeatParkingTest(1, 1, 10000, 50, 50);
+}
+
+#if !PLATFORM(IOS)
+TEST(WTF_ParkingLot, UnparkOneFiftyThenFiftyAll)
+{
+ repeatParkingTest(2, 1, 10000, 100, 50);
+}
+#endif
+
+TEST(WTF_ParkingLot, HundredUnparkAllOneFast)
+{
+ repeatParkingTest(100, 100, 0, 1, 0);
+}
+
+TEST(WTF_ParkingLot, HundredUnparkAllOne)
+{
+ repeatParkingTest(1, 100, 10000, 1, 0);
+}
+
+} // namespace TestWebKitAPI
+
diff --git a/Tools/TestWebKitAPI/Tests/WTF/RedBlackTree.cpp b/Tools/TestWebKitAPI/Tests/WTF/RedBlackTree.cpp
index 1a1c9fdfc..5e5c8adc4 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/RedBlackTree.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/RedBlackTree.cpp
@@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
diff --git a/Tools/TestWebKitAPI/Tests/WTF/Ref.cpp b/Tools/TestWebKitAPI/Tests/WTF/Ref.cpp
index 1b9eef67a..c35606e23 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/Ref.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/Ref.cpp
@@ -26,7 +26,6 @@
#include "config.h"
#include "RefLogger.h"
-#include <wtf/PassRef.h>
#include <wtf/Ref.h>
#include <wtf/RefPtr.h>
@@ -38,14 +37,14 @@ TEST(WTF_Ref, Basic)
{
Ref<RefLogger> ptr(a);
- ASSERT_EQ(&a, &ptr.get());
+ ASSERT_EQ(&a, ptr.ptr());
ASSERT_EQ(&a.name, &ptr->name);
}
ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
{
Ref<RefLogger> ptr(adoptRef(a));
- ASSERT_EQ(&a, &ptr.get());
+ ASSERT_EQ(&a, ptr.ptr());
ASSERT_EQ(&a.name, &ptr->name);
}
ASSERT_STREQ("deref(a) ", takeLogStr().c_str());
@@ -59,51 +58,51 @@ TEST(WTF_Ref, Assignment)
{
Ref<RefLogger> ptr(a);
- ASSERT_EQ(&a, &ptr.get());
+ ASSERT_EQ(&a, ptr.ptr());
log() << "| ";
ptr = b;
- ASSERT_EQ(&b, &ptr.get());
+ ASSERT_EQ(&b, ptr.ptr());
log() << "| ";
}
ASSERT_STREQ("ref(a) | ref(b) deref(a) | deref(b) ", takeLogStr().c_str());
{
Ref<RefLogger> ptr(a);
- ASSERT_EQ(&a, &ptr.get());
+ ASSERT_EQ(&a, ptr.ptr());
log() << "| ";
ptr = c;
- ASSERT_EQ(&c, &ptr.get());
+ ASSERT_EQ(&c, ptr.ptr());
log() << "| ";
}
ASSERT_STREQ("ref(a) | ref(c) deref(a) | deref(c) ", takeLogStr().c_str());
{
Ref<RefLogger> ptr(a);
- ASSERT_EQ(&a, &ptr.get());
+ ASSERT_EQ(&a, ptr.ptr());
log() << "| ";
ptr = adoptRef(b);
- ASSERT_EQ(&b, &ptr.get());
+ ASSERT_EQ(&b, ptr.ptr());
log() << "| ";
}
ASSERT_STREQ("ref(a) | deref(a) | deref(b) ", takeLogStr().c_str());
{
Ref<RefLogger> ptr(a);
- ASSERT_EQ(&a, &ptr.get());
+ ASSERT_EQ(&a, ptr.ptr());
log() << "| ";
ptr = adoptRef(c);
- ASSERT_EQ(&c, &ptr.get());
+ ASSERT_EQ(&c, ptr.ptr());
log() << "| ";
}
ASSERT_STREQ("ref(a) | deref(a) | deref(c) ", takeLogStr().c_str());
}
-PassRef<RefLogger> passWithPassRef(PassRef<RefLogger> reference)
+static Ref<RefLogger> passWithRef(Ref<RefLogger>&& reference)
{
- return reference;
+ return WTFMove(reference);
}
-RefPtr<RefLogger> passWithPassRefPtr(PassRefPtr<RefLogger> reference)
+static RefPtr<RefLogger> passWithPassRefPtr(PassRefPtr<RefLogger> reference)
{
return reference;
}
@@ -115,32 +114,48 @@ TEST(WTF_Ref, ReturnValue)
DerivedRefLogger c("c");
{
- Ref<RefLogger> ptr(passWithPassRef(a));
- ASSERT_EQ(&a, &ptr.get());
+ Ref<RefLogger> ptr(passWithRef(Ref<RefLogger>(a)));
+ ASSERT_EQ(&a, ptr.ptr());
}
ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
{
Ref<RefLogger> ptr(a);
- ASSERT_EQ(&a, &ptr.get());
+ ASSERT_EQ(&a, ptr.ptr());
log() << "| ";
- ptr = passWithPassRef(b);
- ASSERT_EQ(&b, &ptr.get());
+ ptr = passWithRef(b);
+ ASSERT_EQ(&b, ptr.ptr());
log() << "| ";
}
ASSERT_STREQ("ref(a) | ref(b) deref(a) | deref(b) ", takeLogStr().c_str());
{
- RefPtr<RefLogger> ptr(passWithPassRef(a));
+ RefPtr<RefLogger> ptr(passWithRef(a));
ASSERT_EQ(&a, ptr.get());
}
ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
{
- RefPtr<RefLogger> ptr(passWithPassRefPtr(passWithPassRef(a)));
+ RefPtr<RefLogger> ptr(passWithPassRefPtr(passWithRef(a)));
ASSERT_EQ(&a, ptr.get());
}
ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ RefPtr<DerivedRefLogger> ptr(&a);
+ RefPtr<RefLogger> ptr2(WTFMove(ptr));
+ ASSERT_EQ(nullptr, ptr.get());
+ ASSERT_EQ(&a, ptr2.get());
+ }
+ ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ Ref<DerivedRefLogger> derivedReference(a);
+ Ref<RefLogger> baseReference(passWithRef(derivedReference.copyRef()));
+ ASSERT_EQ(&a, derivedReference.ptr());
+ ASSERT_EQ(&a, baseReference.ptr());
+ }
+ ASSERT_STREQ("ref(a) ref(a) deref(a) deref(a) ", takeLogStr().c_str());
}
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/RefCounter.cpp b/Tools/TestWebKitAPI/Tests/WTF/RefCounter.cpp
new file mode 100644
index 000000000..f8771e0c2
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/RefCounter.cpp
@@ -0,0 +1,158 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+
+#include <wtf/Ref.h>
+#include <wtf/RefCounter.h>
+#include <wtf/text/WTFString.h>
+
+namespace TestWebKitAPI {
+
+static const int CallbackExpected = 0xC0FFEE;
+static const int CallbackNotExpected = 0xDECAF;
+
+enum CounterType { };
+typedef RefCounter::Token<CounterType> TokenType;
+
+TEST(WTF, RefCounter)
+{
+ // RefCounter API is pretty simple, containing the following 4 methods to test:
+ //
+ // 1) RefCounter(std::function<void()>);
+ // 2) ~RefCounter();
+ // 3) Ref<Count> token() const;
+ // 4) unsigned value() const;
+ //
+ // We'll test:
+ // 1) Construction:
+ // 1a) with a callback
+ // 1b) without a callback
+ // 2) Destruction where the RefCounter::Count has:
+ // 2a) a non-zero reference count (Count outlives RefCounter).
+ // 2b) a zero reference count (Count is deleted by RefCounter's destructor).
+ // 3) Call count to ref/deref the Count object, where:
+ // 3a) ref with callback from 0 -> 1.
+ // 3b) ref with callback from 1 -> >1.
+ // 3c) deref with callback from >1 -> 1.
+ // 3d) deref with callback from 1 -> 0.
+ // 3d) deref with callback from 1 -> 0.
+ // 3e) ref with callback from 1 -> >1 AFTER RefCounter has been destroyed.
+ // 3f) deref with callback from >1 -> 1 AFTER RefCounter has been destroyed.
+ // 3g) deref with callback from 1 -> 0 AFTER RefCounter has been destroyed.
+ // 3h) ref without callback
+ // 3i) deref without callback
+ // 3j) ref using a Ref rather than a RefPtr (make sure there is no unnecessary reference count churn).
+ // 3k) deref using a Ref rather than a RefPtr (make sure there is no unnecessary reference count churn).
+ // 4) Test the value of the counter:
+ // 4a) at construction.
+ // 4b) as read within the callback.
+ // 4c) as read after the ref/deref.
+
+ // These values will outlive the following block.
+ int callbackValue = CallbackNotExpected;
+ TokenType incTo1Again;
+
+ {
+ // Testing (1a) - Construction with a callback.
+ RefCounter* counterPtr = nullptr;
+ RefCounter counter([&](bool value) {
+ // Check that the callback is called at the expected times, and the correct number of times.
+ EXPECT_EQ(callbackValue, CallbackExpected);
+ // Value provided should be equal to the counter value.
+ EXPECT_EQ(value, counterPtr->value());
+ // return the value of the counter in the callback.
+ callbackValue = value;
+ });
+ counterPtr = &counter;
+ // Testing (4a) - after construction value() is 0.
+ EXPECT_EQ(0, static_cast<int>(counter.value()));
+
+ // Testing (3a) - ref with callback from 0 -> 1.
+ callbackValue = CallbackExpected;
+ TokenType incTo1(counter.token<CounterType>());
+ // Testing (4b) & (4c) - values within & after callback.
+ EXPECT_EQ(true, callbackValue);
+ EXPECT_EQ(1, static_cast<int>(counter.value()));
+
+ // Testing (3b) - ref with callback from 1 -> 2.
+ TokenType incTo2(incTo1);
+ // Testing (4b) & (4c) - values within & after callback.
+ EXPECT_EQ(2, static_cast<int>(counter.value()));
+
+ // Testing (3c) - deref with callback from >1 -> 1.
+ incTo1 = nullptr;
+ // Testing (4b) & (4c) - values within & after callback.
+ EXPECT_EQ(1, static_cast<int>(counter.value()));
+
+ {
+ // Testing (3j) - ref using a Ref rather than a RefPtr.
+ TokenType incTo2Again(counter.token<CounterType>());
+ // Testing (4b) & (4c) - values within & after callback.
+ EXPECT_EQ(2, static_cast<int>(counter.value()));
+ // Testing (3k) - deref using a Ref rather than a RefPtr.
+ }
+ EXPECT_EQ(1, static_cast<int>(counter.value()));
+ // Testing (4b) & (4c) - values within & after callback.
+
+ // Testing (3d) - deref with callback from 1 -> 0.
+ callbackValue = CallbackExpected;
+ incTo2 = nullptr;
+ // Testing (4b) & (4c) - values within & after callback.
+ EXPECT_EQ(0, callbackValue);
+ EXPECT_EQ(0, static_cast<int>(counter.value()));
+
+ // Testing (2a) - Destruction where the RefCounter::Count has a non-zero reference count.
+ callbackValue = CallbackExpected;
+ incTo1Again = counter.token<CounterType>();
+ EXPECT_EQ(1, callbackValue);
+ EXPECT_EQ(1, static_cast<int>(counter.value()));
+ callbackValue = CallbackNotExpected;
+ }
+
+ // Testing (3e) - ref with callback from 1 -> >1 AFTER RefCounter has been destroyed.
+ TokenType incTo2Again = incTo1Again;
+ // Testing (3f) - deref with callback from >1 -> 1 AFTER RefCounter has been destroyed.
+ incTo1Again = nullptr;
+ // Testing (3g) - deref with callback from 1 -> 0 AFTER RefCounter has been destroyed.
+ incTo2Again = nullptr;
+
+ // Testing (1b) - Construction without a callback.
+ RefCounter counter;
+ // Testing (4a) - after construction value() is 0.
+ EXPECT_EQ(0, static_cast<int>(counter.value()));
+ // Testing (3h) - ref without callback
+ TokenType incTo1(counter.token<CounterType>());
+ // Testing (4c) - value as read after the ref.
+ EXPECT_EQ(1, static_cast<int>(counter.value()));
+ // Testing (3i) - deref without callback
+ incTo1 = nullptr;
+ // Testing (4c) - value as read after the deref.
+ EXPECT_EQ(0, static_cast<int>(counter.value()));
+ // Testing (2b) - Destruction where the RefCounter::Count has a zero reference count.
+ // ... not a lot to test here! - we can at least ensure this code path is run & we don't crash!
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/RefLogger.h b/Tools/TestWebKitAPI/Tests/WTF/RefLogger.h
index 2bb5c36fa..c5cfb071f 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/RefLogger.h
+++ b/Tools/TestWebKitAPI/Tests/WTF/RefLogger.h
@@ -48,7 +48,7 @@ struct RefLogger {
};
struct DerivedRefLogger : RefLogger {
- DerivedRefLogger(const char* name) : RefLogger(name) { }
+ DerivedRefLogger(const char* name) : RefLogger(name) { log().str(""); }
};
}
diff --git a/Tools/TestWebKitAPI/Tests/WTF/RefPtr.cpp b/Tools/TestWebKitAPI/Tests/WTF/RefPtr.cpp
index bc1e1e484..aebe98c48 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/RefPtr.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/RefPtr.cpp
@@ -69,7 +69,7 @@ TEST(WTF_RefPtr, Basic)
{
RefPtr<RefLogger> p1 = &a;
- RefPtr<RefLogger> p2 = std::move(p1);
+ RefPtr<RefLogger> p2 = WTFMove(p1);
ASSERT_EQ(nullptr, p1.get());
ASSERT_EQ(&a, p2.get());
}
@@ -77,7 +77,7 @@ TEST(WTF_RefPtr, Basic)
{
RefPtr<RefLogger> p1 = &a;
- RefPtr<RefLogger> p2(std::move(p1));
+ RefPtr<RefLogger> p2(WTFMove(p1));
ASSERT_EQ(nullptr, p1.get());
ASSERT_EQ(&a, p2.get());
}
@@ -93,7 +93,7 @@ TEST(WTF_RefPtr, Basic)
{
RefPtr<DerivedRefLogger> p1 = &a;
- RefPtr<RefLogger> p2 = std::move(p1);
+ RefPtr<RefLogger> p2 = WTFMove(p1);
ASSERT_EQ(nullptr, p1.get());
ASSERT_EQ(&a, p2.get());
}
@@ -102,7 +102,7 @@ TEST(WTF_RefPtr, Basic)
{
RefPtr<RefLogger> ptr(&a);
ASSERT_EQ(&a, ptr.get());
- ptr.clear();
+ ptr = nullptr;
ASSERT_EQ(nullptr, ptr.get());
}
ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
@@ -120,8 +120,8 @@ TEST(WTF_RefPtr, AssignPassRefToRefPtr)
{
DerivedRefLogger a("a");
{
- PassRef<RefLogger> passRef(a);
- RefPtr<RefLogger> ptr = std::move(passRef);
+ Ref<RefLogger> passRef(a);
+ RefPtr<RefLogger> ptr = WTFMove(passRef);
ASSERT_EQ(&a, ptr.get());
ptr.release();
ASSERT_EQ(nullptr, ptr.get());
@@ -204,7 +204,7 @@ TEST(WTF_RefPtr, Assignment)
ASSERT_EQ(&a, p1.get());
ASSERT_EQ(&b, p2.get());
log() << "| ";
- p1 = std::move(p2);
+ p1 = WTFMove(p2);
ASSERT_EQ(&b, p1.get());
ASSERT_EQ(nullptr, p2.get());
log() << "| ";
@@ -250,7 +250,7 @@ TEST(WTF_RefPtr, Assignment)
ASSERT_EQ(&a, p1.get());
ASSERT_EQ(&c, p2.get());
log() << "| ";
- p1 = std::move(p2);
+ p1 = WTFMove(p2);
ASSERT_EQ(&c, p1.get());
ASSERT_EQ(nullptr, p2.get());
log() << "| ";
@@ -270,7 +270,15 @@ TEST(WTF_RefPtr, Assignment)
{
RefPtr<RefLogger> ptr(&a);
ASSERT_EQ(&a, ptr.get());
- ptr = std::move(ptr);
+#if COMPILER(CLANG)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wself-move"
+#endif
+ ptr = WTFMove(ptr);
+#if COMPILER(CLANG)
+#pragma clang diagnostic pop
+#endif
ASSERT_EQ(&a, ptr.get());
}
ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
diff --git a/Tools/TestWebKitAPI/Tests/WTF/RunLoop.cpp b/Tools/TestWebKitAPI/Tests/WTF/RunLoop.cpp
new file mode 100644
index 000000000..e7e3d9f99
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/RunLoop.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "config.h"
+
+#include "PlatformUtilities.h"
+#include <wtf/RunLoop.h>
+
+namespace TestWebKitAPI {
+
+static bool testFinished;
+static int count = 100;
+
+TEST(WTF_RunLoop, Deadlock)
+{
+ RunLoop::initializeMainRunLoop();
+
+ struct DispatchFromDestructorTester {
+ ~DispatchFromDestructorTester() {
+ RunLoop::main().dispatch([] {
+ if (!(--count))
+ testFinished = true;
+ });
+ }
+ };
+
+ for (int i = 0; i < count; ++i) {
+ auto capture = std::make_shared<DispatchFromDestructorTester>();
+ RunLoop::main().dispatch([capture] { });
+ }
+
+ Util::run(&testFinished);
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/StringBuilder.cpp b/Tools/TestWebKitAPI/Tests/WTF/StringBuilder.cpp
index 9ca5d6ee8..11bf3590e 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/StringBuilder.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/StringBuilder.cpp
@@ -38,14 +38,17 @@ static void expectBuilderContent(const String& expected, const StringBuilder& bu
{
// Not using builder.toString() or builder.toStringPreserveCapacity() because they all
// change internal state of builder.
- EXPECT_EQ(expected, String(builder.deprecatedCharacters(), builder.length()));
+ if (builder.is8Bit())
+ EXPECT_EQ(expected, String(builder.characters8(), builder.length()));
+ else
+ EXPECT_EQ(expected, String(builder.characters16(), builder.length()));
}
void expectEmpty(const StringBuilder& builder)
{
EXPECT_EQ(0U, builder.length());
EXPECT_TRUE(builder.isEmpty());
- EXPECT_EQ(0, builder.deprecatedCharacters());
+ EXPECT_EQ(0, builder.characters8());
}
TEST(StringBuilderTest, DefaultConstructor)
@@ -72,20 +75,20 @@ TEST(StringBuilderTest, Append)
StringBuilder builder1;
builder.append("", 0);
expectBuilderContent("0123456789abcdefg#", builder);
- builder1.append(builder.deprecatedCharacters(), builder.length());
+ builder1.append(builder.characters8(), builder.length());
builder1.append("XYZ");
- builder.append(builder1.deprecatedCharacters(), builder1.length());
+ builder.append(builder1.characters8(), builder1.length());
expectBuilderContent("0123456789abcdefg#0123456789abcdefg#XYZ", builder);
StringBuilder builder2;
builder2.reserveCapacity(100);
builder2.append("xyz");
- const UChar* characters = builder2.deprecatedCharacters();
+ const LChar* characters = builder2.characters8();
builder2.append("0123456789");
- ASSERT_EQ(characters, builder2.deprecatedCharacters());
+ ASSERT_EQ(characters, builder2.characters8());
builder2.toStringPreserveCapacity(); // Test after reifyString with buffer preserved.
builder2.append("abcd");
- ASSERT_EQ(characters, builder2.deprecatedCharacters());
+ ASSERT_EQ(characters, builder2.characters8());
// Test appending UChar32 characters to StringBuilder.
StringBuilder builderForUChar32Append;
@@ -140,7 +143,7 @@ TEST(StringBuilderTest, ToStringPreserveCapacity)
ASSERT_EQ(capacity, builder.capacity());
ASSERT_EQ(String("0123456789"), string);
ASSERT_EQ(string.impl(), builder.toStringPreserveCapacity().impl());
- ASSERT_EQ(string.deprecatedCharacters(), builder.deprecatedCharacters());
+ ASSERT_EQ(string.characters8(), builder.characters8());
// Changing the StringBuilder should not affect the original result of toStringPreserveCapacity().
builder.append("abcdefghijklmnopqrstuvwxyz");
@@ -151,7 +154,7 @@ TEST(StringBuilderTest, ToStringPreserveCapacity)
capacity = builder.capacity();
string = builder.toStringPreserveCapacity();
ASSERT_EQ(capacity, builder.capacity());
- ASSERT_EQ(string.deprecatedCharacters(), builder.deprecatedCharacters());
+ ASSERT_EQ(string.characters8(), builder.characters8());
ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyz"), string);
builder.append("ABC");
ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyz"), string);
@@ -160,7 +163,7 @@ TEST(StringBuilderTest, ToStringPreserveCapacity)
capacity = builder.capacity();
String string1 = builder.toStringPreserveCapacity();
ASSERT_EQ(capacity, builder.capacity());
- ASSERT_EQ(string1.deprecatedCharacters(), builder.deprecatedCharacters());
+ ASSERT_EQ(string1.characters8(), builder.characters8());
ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyzABC"), string1);
string1.append("DEF");
ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyzABC"), builder.toStringPreserveCapacity());
@@ -170,7 +173,7 @@ TEST(StringBuilderTest, ToStringPreserveCapacity)
capacity = builder.capacity();
string1 = builder.toStringPreserveCapacity();
ASSERT_EQ(capacity, builder.capacity());
- ASSERT_EQ(string.deprecatedCharacters(), builder.deprecatedCharacters());
+ ASSERT_EQ(string.characters8(), builder.characters8());
builder.resize(10);
builder.append("###");
ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyzABC"), string1);
diff --git a/Tools/TestWebKitAPI/Tests/WTF/StringHasher.cpp b/Tools/TestWebKitAPI/Tests/WTF/StringHasher.cpp
index a4d223c99..739a8190e 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/StringHasher.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/StringHasher.cpp
@@ -25,7 +25,7 @@
#include "config.h"
-#include <wtf/StringHasher.h>
+#include <wtf/Hasher.h>
namespace TestWebKitAPI {
diff --git a/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp b/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp
index d5804f6b4..01f36f7b6 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp
@@ -25,7 +25,7 @@
#include "config.h"
-#include <wtf/text/StringImpl.h>
+#include <wtf/text/SymbolImpl.h>
#include <wtf/text/WTFString.h>
namespace TestWebKitAPI {
@@ -55,17 +55,6 @@ TEST(WTF, StringImplCreationFromLiteral)
ASSERT_TRUE(programmaticStringNoLength->is8Bit());
}
-TEST(WTF, StringImplFromLiteralLoop16BitConversion)
-{
- RefPtr<StringImpl> controlString = StringImpl::create("Template Literal");
- for (size_t i = 0; i < 10; ++i) {
- RefPtr<StringImpl> string = StringImpl::createFromLiteral("Template Literal");
-
- ASSERT_EQ(0, memcmp(controlString->deprecatedCharacters(), string->deprecatedCharacters(), controlString->length() * sizeof(UChar)));
- ASSERT_TRUE(string->has16BitShadow());
- }
-}
-
TEST(WTF, StringImplReplaceWithLiteral)
{
RefPtr<StringImpl> testStringImpl = StringImpl::createFromLiteral("1224");
@@ -110,4 +99,451 @@ TEST(WTF, StringImplReplaceWithLiteral)
ASSERT_TRUE(equal(testStringImpl.get(), "r555sum555"));
}
+TEST(WTF, StringImplEqualIgnoringASCIICaseBasic)
+{
+ RefPtr<StringImpl> a = StringImpl::createFromLiteral("aBcDeFG");
+ RefPtr<StringImpl> b = StringImpl::createFromLiteral("ABCDEFG");
+ RefPtr<StringImpl> c = StringImpl::createFromLiteral("abcdefg");
+ const char d[] = "aBcDeFG";
+ RefPtr<StringImpl> empty = StringImpl::create(reinterpret_cast<const LChar*>(""));
+ RefPtr<StringImpl> shorter = StringImpl::createFromLiteral("abcdef");
+ RefPtr<StringImpl> different = StringImpl::createFromLiteral("abcrefg");
+
+ // Identity.
+ ASSERT_TRUE(equalIgnoringASCIICase(a.get(), a.get()));
+ ASSERT_TRUE(equalIgnoringASCIICase(b.get(), b.get()));
+ ASSERT_TRUE(equalIgnoringASCIICase(c.get(), c.get()));
+ ASSERT_TRUE(equalIgnoringASCIICase(a.get(), d));
+ ASSERT_TRUE(equalIgnoringASCIICase(b.get(), d));
+ ASSERT_TRUE(equalIgnoringASCIICase(c.get(), d));
+
+ // Transitivity.
+ ASSERT_TRUE(equalIgnoringASCIICase(a.get(), b.get()));
+ ASSERT_TRUE(equalIgnoringASCIICase(b.get(), c.get()));
+ ASSERT_TRUE(equalIgnoringASCIICase(a.get(), c.get()));
+
+ // Negative cases.
+ ASSERT_FALSE(equalIgnoringASCIICase(a.get(), empty.get()));
+ ASSERT_FALSE(equalIgnoringASCIICase(b.get(), empty.get()));
+ ASSERT_FALSE(equalIgnoringASCIICase(c.get(), empty.get()));
+ ASSERT_FALSE(equalIgnoringASCIICase(a.get(), shorter.get()));
+ ASSERT_FALSE(equalIgnoringASCIICase(b.get(), shorter.get()));
+ ASSERT_FALSE(equalIgnoringASCIICase(c.get(), shorter.get()));
+ ASSERT_FALSE(equalIgnoringASCIICase(a.get(), different.get()));
+ ASSERT_FALSE(equalIgnoringASCIICase(b.get(), different.get()));
+ ASSERT_FALSE(equalIgnoringASCIICase(c.get(), different.get()));
+ ASSERT_FALSE(equalIgnoringASCIICase(empty.get(), d));
+ ASSERT_FALSE(equalIgnoringASCIICase(shorter.get(), d));
+ ASSERT_FALSE(equalIgnoringASCIICase(different.get(), d));
+}
+
+TEST(WTF, StringImplEqualIgnoringASCIICaseWithNull)
+{
+ RefPtr<StringImpl> reference = StringImpl::createFromLiteral("aBcDeFG");
+ StringImpl* nullStringImpl = nullptr;
+ ASSERT_FALSE(equalIgnoringASCIICase(nullStringImpl, reference.get()));
+ ASSERT_FALSE(equalIgnoringASCIICase(reference.get(), nullStringImpl));
+ ASSERT_TRUE(equalIgnoringASCIICase(nullStringImpl, nullStringImpl));
+}
+
+TEST(WTF, StringImplEqualIgnoringASCIICaseWithEmpty)
+{
+ RefPtr<StringImpl> a = StringImpl::create(reinterpret_cast<const LChar*>(""));
+ RefPtr<StringImpl> b = StringImpl::create(reinterpret_cast<const LChar*>(""));
+ ASSERT_TRUE(equalIgnoringASCIICase(a.get(), b.get()));
+ ASSERT_TRUE(equalIgnoringASCIICase(b.get(), a.get()));
+}
+
+static RefPtr<StringImpl> stringFromUTF8(const char* characters)
+{
+ return String::fromUTF8(characters).impl();
+}
+
+TEST(WTF, StringImplEqualIgnoringASCIICaseWithLatin1Characters)
+{
+ RefPtr<StringImpl> a = stringFromUTF8("aBcéeFG");
+ RefPtr<StringImpl> b = stringFromUTF8("ABCÉEFG");
+ RefPtr<StringImpl> c = stringFromUTF8("ABCéEFG");
+ RefPtr<StringImpl> d = stringFromUTF8("abcéefg");
+ const char e[] = "aBcéeFG";
+
+ // Identity.
+ ASSERT_TRUE(equalIgnoringASCIICase(a.get(), a.get()));
+ ASSERT_TRUE(equalIgnoringASCIICase(b.get(), b.get()));
+ ASSERT_TRUE(equalIgnoringASCIICase(c.get(), c.get()));
+ ASSERT_TRUE(equalIgnoringASCIICase(d.get(), d.get()));
+
+ // All combination.
+ ASSERT_FALSE(equalIgnoringASCIICase(a.get(), b.get()));
+ ASSERT_TRUE(equalIgnoringASCIICase(a.get(), c.get()));
+ ASSERT_TRUE(equalIgnoringASCIICase(a.get(), d.get()));
+ ASSERT_FALSE(equalIgnoringASCIICase(b.get(), c.get()));
+ ASSERT_FALSE(equalIgnoringASCIICase(b.get(), d.get()));
+ ASSERT_TRUE(equalIgnoringASCIICase(c.get(), d.get()));
+ ASSERT_FALSE(equalIgnoringASCIICase(a.get(), e));
+ ASSERT_FALSE(equalIgnoringASCIICase(b.get(), e));
+ ASSERT_FALSE(equalIgnoringASCIICase(c.get(), e));
+ ASSERT_FALSE(equalIgnoringASCIICase(d.get(), e));
+}
+
+TEST(WTF, StringImplFindIgnoringASCIICaseBasic)
+{
+ RefPtr<StringImpl> referenceA = stringFromUTF8("aBcéeFG");
+ RefPtr<StringImpl> referenceB = stringFromUTF8("ABCÉEFG");
+
+ // Search the exact string.
+ EXPECT_EQ(static_cast<size_t>(0), referenceA->findIgnoringASCIICase(referenceA.get()));
+ EXPECT_EQ(static_cast<size_t>(0), referenceB->findIgnoringASCIICase(referenceB.get()));
+
+ // A and B are distinct by the non-ascii character é/É.
+ EXPECT_EQ(static_cast<size_t>(notFound), referenceA->findIgnoringASCIICase(referenceB.get()));
+ EXPECT_EQ(static_cast<size_t>(notFound), referenceB->findIgnoringASCIICase(referenceA.get()));
+
+ // Find the prefix.
+ EXPECT_EQ(static_cast<size_t>(0), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("a").get()));
+ EXPECT_EQ(static_cast<size_t>(0), referenceA->findIgnoringASCIICase(stringFromUTF8("abcé").get()));
+ EXPECT_EQ(static_cast<size_t>(0), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("A").get()));
+ EXPECT_EQ(static_cast<size_t>(0), referenceA->findIgnoringASCIICase(stringFromUTF8("ABCé").get()));
+ EXPECT_EQ(static_cast<size_t>(0), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("a").get()));
+ EXPECT_EQ(static_cast<size_t>(0), referenceB->findIgnoringASCIICase(stringFromUTF8("abcÉ").get()));
+ EXPECT_EQ(static_cast<size_t>(0), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("A").get()));
+ EXPECT_EQ(static_cast<size_t>(0), referenceB->findIgnoringASCIICase(stringFromUTF8("ABCÉ").get()));
+
+ // Not a prefix.
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("x").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("accé").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("abcÉ").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("X").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("ABDé").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("ABCÉ").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("y").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("accÉ").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("abcé").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("Y").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("ABdÉ").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("ABCé").get()));
+
+ // Find the infix.
+ EXPECT_EQ(static_cast<size_t>(2), referenceA->findIgnoringASCIICase(stringFromUTF8("cée").get()));
+ EXPECT_EQ(static_cast<size_t>(3), referenceA->findIgnoringASCIICase(stringFromUTF8("ée").get()));
+ EXPECT_EQ(static_cast<size_t>(2), referenceA->findIgnoringASCIICase(stringFromUTF8("cé").get()));
+ EXPECT_EQ(static_cast<size_t>(2), referenceA->findIgnoringASCIICase(stringFromUTF8("c").get()));
+ EXPECT_EQ(static_cast<size_t>(3), referenceA->findIgnoringASCIICase(stringFromUTF8("é").get()));
+ EXPECT_EQ(static_cast<size_t>(2), referenceA->findIgnoringASCIICase(stringFromUTF8("Cée").get()));
+ EXPECT_EQ(static_cast<size_t>(3), referenceA->findIgnoringASCIICase(stringFromUTF8("éE").get()));
+ EXPECT_EQ(static_cast<size_t>(2), referenceA->findIgnoringASCIICase(stringFromUTF8("Cé").get()));
+ EXPECT_EQ(static_cast<size_t>(2), referenceA->findIgnoringASCIICase(stringFromUTF8("C").get()));
+
+ EXPECT_EQ(static_cast<size_t>(2), referenceB->findIgnoringASCIICase(stringFromUTF8("cÉe").get()));
+ EXPECT_EQ(static_cast<size_t>(3), referenceB->findIgnoringASCIICase(stringFromUTF8("Ée").get()));
+ EXPECT_EQ(static_cast<size_t>(2), referenceB->findIgnoringASCIICase(stringFromUTF8("cÉ").get()));
+ EXPECT_EQ(static_cast<size_t>(2), referenceB->findIgnoringASCIICase(stringFromUTF8("c").get()));
+ EXPECT_EQ(static_cast<size_t>(3), referenceB->findIgnoringASCIICase(stringFromUTF8("É").get()));
+ EXPECT_EQ(static_cast<size_t>(2), referenceB->findIgnoringASCIICase(stringFromUTF8("CÉe").get()));
+ EXPECT_EQ(static_cast<size_t>(3), referenceB->findIgnoringASCIICase(stringFromUTF8("ÉE").get()));
+ EXPECT_EQ(static_cast<size_t>(2), referenceB->findIgnoringASCIICase(stringFromUTF8("CÉ").get()));
+ EXPECT_EQ(static_cast<size_t>(2), referenceB->findIgnoringASCIICase(stringFromUTF8("C").get()));
+
+ // Not an infix.
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("céd").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("Ée").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("bé").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("x").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("É").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("CÉe").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("éd").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("CÉ").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("Y").get()));
+
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("cée").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("Éc").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("cé").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("W").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("é").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("bÉe").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("éE").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("BÉ").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("z").get()));
+
+ // Find the suffix.
+ EXPECT_EQ(static_cast<size_t>(6), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("g").get()));
+ EXPECT_EQ(static_cast<size_t>(4), referenceA->findIgnoringASCIICase(stringFromUTF8("efg").get()));
+ EXPECT_EQ(static_cast<size_t>(3), referenceA->findIgnoringASCIICase(stringFromUTF8("éefg").get()));
+ EXPECT_EQ(static_cast<size_t>(6), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("G").get()));
+ EXPECT_EQ(static_cast<size_t>(4), referenceA->findIgnoringASCIICase(stringFromUTF8("EFG").get()));
+ EXPECT_EQ(static_cast<size_t>(3), referenceA->findIgnoringASCIICase(stringFromUTF8("éEFG").get()));
+
+ EXPECT_EQ(static_cast<size_t>(6), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("g").get()));
+ EXPECT_EQ(static_cast<size_t>(4), referenceB->findIgnoringASCIICase(stringFromUTF8("efg").get()));
+ EXPECT_EQ(static_cast<size_t>(3), referenceB->findIgnoringASCIICase(stringFromUTF8("Éefg").get()));
+ EXPECT_EQ(static_cast<size_t>(6), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("G").get()));
+ EXPECT_EQ(static_cast<size_t>(4), referenceB->findIgnoringASCIICase(stringFromUTF8("EFG").get()));
+ EXPECT_EQ(static_cast<size_t>(3), referenceB->findIgnoringASCIICase(stringFromUTF8("ÉEFG").get()));
+
+ // Not a suffix.
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("X").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("edg").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("Éefg").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("w").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("dFG").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("ÉEFG").get()));
+
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("Z").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("ffg").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("éefg").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("r").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("EgG").get()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("éEFG").get()));
+}
+
+TEST(WTF, StringImplFindIgnoringASCIICaseWithValidOffset)
+{
+ RefPtr<StringImpl> reference = stringFromUTF8("ABCÉEFGaBcéeFG");
+ EXPECT_EQ(static_cast<size_t>(0), reference->findIgnoringASCIICase(stringFromUTF8("ABC").get(), 0));
+ EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(stringFromUTF8("ABC").get(), 1));
+ EXPECT_EQ(static_cast<size_t>(0), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").get(), 0));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").get(), 1));
+ EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(stringFromUTF8("ABCé").get(), 0));
+ EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(stringFromUTF8("ABCé").get(), 1));
+}
+
+TEST(WTF, StringImplFindIgnoringASCIICaseWithInvalidOffset)
+{
+ RefPtr<StringImpl> reference = stringFromUTF8("ABCÉEFGaBcéeFG");
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABC").get(), 15));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABC").get(), 16));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").get(), 17));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").get(), 42));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").get(), std::numeric_limits<unsigned>::max()));
+}
+
+TEST(WTF, StringImplFindIgnoringASCIICaseOnNull)
+{
+ RefPtr<StringImpl> reference = stringFromUTF8("ABCÉEFG");
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 0));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 3));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 7));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 8));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 42));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr, std::numeric_limits<unsigned>::max()));
+}
+
+TEST(WTF, StringImplFindIgnoringASCIICaseOnEmpty)
+{
+ RefPtr<StringImpl> reference = stringFromUTF8("ABCÉEFG");
+ RefPtr<StringImpl> empty = StringImpl::create(reinterpret_cast<const LChar*>(""));
+ EXPECT_EQ(static_cast<size_t>(0), reference->findIgnoringASCIICase(empty.get()));
+ EXPECT_EQ(static_cast<size_t>(0), reference->findIgnoringASCIICase(empty.get(), 0));
+ EXPECT_EQ(static_cast<size_t>(3), reference->findIgnoringASCIICase(empty.get(), 3));
+ EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(empty.get(), 7));
+ EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(empty.get(), 8));
+ EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(empty.get(), 42));
+ EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(empty.get(), std::numeric_limits<unsigned>::max()));
+}
+
+TEST(WTF, StringImplFindIgnoringASCIICaseWithPatternLongerThanReference)
+{
+ RefPtr<StringImpl> reference = stringFromUTF8("ABCÉEFG");
+ RefPtr<StringImpl> pattern = stringFromUTF8("XABCÉEFG");
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(pattern.get()));
+ EXPECT_EQ(static_cast<size_t>(1), pattern->findIgnoringASCIICase(reference.get()));
+}
+
+TEST(WTF, StringImplStartsWithIgnoringASCIICaseBasic)
+{
+ RefPtr<StringImpl> reference = stringFromUTF8("aBcéX");
+ RefPtr<StringImpl> referenceEquivalent = stringFromUTF8("AbCéx");
+
+ // Identity.
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(reference.get()));
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*reference.get()));
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(referenceEquivalent.get()));
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*referenceEquivalent.get()));
+ ASSERT_TRUE(referenceEquivalent->startsWithIgnoringASCIICase(reference.get()));
+ ASSERT_TRUE(referenceEquivalent->startsWithIgnoringASCIICase(*reference.get()));
+ ASSERT_TRUE(referenceEquivalent->startsWithIgnoringASCIICase(referenceEquivalent.get()));
+ ASSERT_TRUE(referenceEquivalent->startsWithIgnoringASCIICase(*referenceEquivalent.get()));
+
+ // Proper prefixes.
+ RefPtr<StringImpl> aLower = StringImpl::createFromLiteral("a");
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(aLower.get()));
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*aLower.get()));
+ RefPtr<StringImpl> aUpper = StringImpl::createFromLiteral("A");
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(aUpper.get()));
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*aUpper.get()));
+
+ RefPtr<StringImpl> abcLower = StringImpl::createFromLiteral("abc");
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(abcLower.get()));
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*abcLower.get()));
+ RefPtr<StringImpl> abcUpper = StringImpl::createFromLiteral("ABC");
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(abcUpper.get()));
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*abcUpper.get()));
+
+ RefPtr<StringImpl> abcAccentLower = stringFromUTF8("abcé");
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(abcAccentLower.get()));
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*abcAccentLower.get()));
+ RefPtr<StringImpl> abcAccentUpper = stringFromUTF8("ABCé");
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(abcAccentUpper.get()));
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*abcAccentUpper.get()));
+
+ // Negative cases.
+ RefPtr<StringImpl> differentFirstChar = stringFromUTF8("bBcéX");
+ RefPtr<StringImpl> differentFirstCharProperPrefix = stringFromUTF8("CBcé");
+ ASSERT_FALSE(reference->startsWithIgnoringASCIICase(differentFirstChar.get()));
+ ASSERT_FALSE(reference->startsWithIgnoringASCIICase(*differentFirstChar.get()));
+ ASSERT_FALSE(reference->startsWithIgnoringASCIICase(differentFirstCharProperPrefix.get()));
+ ASSERT_FALSE(reference->startsWithIgnoringASCIICase(*differentFirstCharProperPrefix.get()));
+
+ RefPtr<StringImpl> uppercaseAccent = stringFromUTF8("aBcÉX");
+ RefPtr<StringImpl> uppercaseAccentProperPrefix = stringFromUTF8("aBcÉX");
+ ASSERT_FALSE(reference->startsWithIgnoringASCIICase(uppercaseAccent.get()));
+ ASSERT_FALSE(reference->startsWithIgnoringASCIICase(*uppercaseAccent.get()));
+ ASSERT_FALSE(reference->startsWithIgnoringASCIICase(uppercaseAccentProperPrefix.get()));
+ ASSERT_FALSE(reference->startsWithIgnoringASCIICase(*uppercaseAccentProperPrefix.get()));
+}
+
+TEST(WTF, StringImplStartsWithIgnoringASCIICaseWithNull)
+{
+ RefPtr<StringImpl> reference = StringImpl::createFromLiteral("aBcDeFG");
+ ASSERT_FALSE(reference->startsWithIgnoringASCIICase(nullptr));
+
+ RefPtr<StringImpl> empty = StringImpl::create(reinterpret_cast<const LChar*>(""));
+ ASSERT_FALSE(empty->startsWithIgnoringASCIICase(nullptr));
+}
+
+TEST(WTF, StringImplStartsWithIgnoringASCIICaseWithEmpty)
+{
+ RefPtr<StringImpl> reference = StringImpl::createFromLiteral("aBcDeFG");
+ RefPtr<StringImpl> empty = StringImpl::create(reinterpret_cast<const LChar*>(""));
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(empty.get()));
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*empty.get()));
+ ASSERT_TRUE(empty->startsWithIgnoringASCIICase(empty.get()));
+ ASSERT_TRUE(empty->startsWithIgnoringASCIICase(*empty.get()));
+ ASSERT_FALSE(empty->startsWithIgnoringASCIICase(reference.get()));
+ ASSERT_FALSE(empty->startsWithIgnoringASCIICase(*reference.get()));
+}
+
+TEST(WTF, StringImplEndsWithIgnoringASCIICaseBasic)
+{
+ RefPtr<StringImpl> reference = stringFromUTF8("XÉCbA");
+ RefPtr<StringImpl> referenceEquivalent = stringFromUTF8("xÉcBa");
+
+ // Identity.
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(reference.get()));
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*reference.get()));
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(referenceEquivalent.get()));
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*referenceEquivalent.get()));
+ ASSERT_TRUE(referenceEquivalent->endsWithIgnoringASCIICase(reference.get()));
+ ASSERT_TRUE(referenceEquivalent->endsWithIgnoringASCIICase(*reference.get()));
+ ASSERT_TRUE(referenceEquivalent->endsWithIgnoringASCIICase(referenceEquivalent.get()));
+ ASSERT_TRUE(referenceEquivalent->endsWithIgnoringASCIICase(*referenceEquivalent.get()));
+
+ // Proper suffixes.
+ RefPtr<StringImpl> aLower = StringImpl::createFromLiteral("a");
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(aLower.get()));
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*aLower.get()));
+ RefPtr<StringImpl> aUpper = StringImpl::createFromLiteral("a");
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(aUpper.get()));
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*aUpper.get()));
+
+ RefPtr<StringImpl> abcLower = StringImpl::createFromLiteral("cba");
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(abcLower.get()));
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*abcLower.get()));
+ RefPtr<StringImpl> abcUpper = StringImpl::createFromLiteral("CBA");
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(abcUpper.get()));
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*abcUpper.get()));
+
+ RefPtr<StringImpl> abcAccentLower = stringFromUTF8("Écba");
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(abcAccentLower.get()));
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*abcAccentLower.get()));
+ RefPtr<StringImpl> abcAccentUpper = stringFromUTF8("ÉCBA");
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(abcAccentUpper.get()));
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*abcAccentUpper.get()));
+
+ // Negative cases.
+ RefPtr<StringImpl> differentLastChar = stringFromUTF8("XÉCbB");
+ RefPtr<StringImpl> differentLastCharProperSuffix = stringFromUTF8("ÉCbb");
+ ASSERT_FALSE(reference->endsWithIgnoringASCIICase(differentLastChar.get()));
+ ASSERT_FALSE(reference->endsWithIgnoringASCIICase(*differentLastChar.get()));
+ ASSERT_FALSE(reference->endsWithIgnoringASCIICase(differentLastCharProperSuffix.get()));
+ ASSERT_FALSE(reference->endsWithIgnoringASCIICase(*differentLastCharProperSuffix.get()));
+
+ RefPtr<StringImpl> lowercaseAccent = stringFromUTF8("aBcéX");
+ RefPtr<StringImpl> loweraseAccentProperSuffix = stringFromUTF8("aBcéX");
+ ASSERT_FALSE(reference->endsWithIgnoringASCIICase(lowercaseAccent.get()));
+ ASSERT_FALSE(reference->endsWithIgnoringASCIICase(*lowercaseAccent.get()));
+ ASSERT_FALSE(reference->endsWithIgnoringASCIICase(loweraseAccentProperSuffix.get()));
+ ASSERT_FALSE(reference->endsWithIgnoringASCIICase(*loweraseAccentProperSuffix.get()));
+}
+
+TEST(WTF, StringImplEndsWithIgnoringASCIICaseWithNull)
+{
+ RefPtr<StringImpl> reference = StringImpl::createFromLiteral("aBcDeFG");
+ ASSERT_FALSE(reference->endsWithIgnoringASCIICase(nullptr));
+
+ RefPtr<StringImpl> empty = StringImpl::create(reinterpret_cast<const LChar*>(""));
+ ASSERT_FALSE(empty->endsWithIgnoringASCIICase(nullptr));
+}
+
+TEST(WTF, StringImplEndsWithIgnoringASCIICaseWithEmpty)
+{
+ RefPtr<StringImpl> reference = StringImpl::createFromLiteral("aBcDeFG");
+ RefPtr<StringImpl> empty = StringImpl::create(reinterpret_cast<const LChar*>(""));
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(empty.get()));
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*empty.get()));
+ ASSERT_TRUE(empty->endsWithIgnoringASCIICase(empty.get()));
+ ASSERT_TRUE(empty->endsWithIgnoringASCIICase(*empty.get()));
+ ASSERT_FALSE(empty->endsWithIgnoringASCIICase(reference.get()));
+ ASSERT_FALSE(empty->endsWithIgnoringASCIICase(*reference.get()));
+}
+
+TEST(WTF, StringImplCreateSymbolEmpty)
+{
+ RefPtr<StringImpl> reference = StringImpl::createSymbolEmpty();
+ ASSERT_TRUE(reference->isSymbol());
+ ASSERT_FALSE(reference->isAtomic());
+ ASSERT_EQ(0u, reference->length());
+ ASSERT_TRUE(equal(reference.get(), ""));
+}
+
+TEST(WTF, StringImplCreateSymbol)
+{
+ RefPtr<StringImpl> original = stringFromUTF8("original");
+ RefPtr<StringImpl> reference = StringImpl::createSymbol(original);
+ ASSERT_TRUE(reference->isSymbol());
+ ASSERT_FALSE(reference->isAtomic());
+ ASSERT_FALSE(original->isSymbol());
+ ASSERT_FALSE(original->isAtomic());
+ ASSERT_EQ(original->length(), reference->length());
+ ASSERT_TRUE(equal(reference.get(), "original"));
+}
+
+TEST(WTF, StringImplSymbolToAtomicString)
+{
+ RefPtr<StringImpl> original = stringFromUTF8("original");
+ RefPtr<StringImpl> reference = StringImpl::createSymbol(original);
+ ASSERT_TRUE(reference->isSymbol());
+ ASSERT_FALSE(reference->isAtomic());
+
+ RefPtr<StringImpl> atomic = AtomicStringImpl::add(reference.get());
+ ASSERT_TRUE(atomic->isAtomic());
+ ASSERT_FALSE(atomic->isSymbol());
+ ASSERT_TRUE(reference->isSymbol());
+ ASSERT_FALSE(reference->isAtomic());
+}
+
+TEST(WTF, StringImplSymbolEmptyToAtomicString)
+{
+ RefPtr<StringImpl> reference = StringImpl::createSymbolEmpty();
+ ASSERT_TRUE(reference->isSymbol());
+ ASSERT_FALSE(reference->isAtomic());
+
+ RefPtr<StringImpl> atomic = AtomicStringImpl::add(reference.get());
+ ASSERT_TRUE(atomic->isAtomic());
+ ASSERT_FALSE(atomic->isSymbol());
+ ASSERT_TRUE(reference->isSymbol());
+ ASSERT_FALSE(reference->isAtomic());
+}
+
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/StringOperators.cpp b/Tools/TestWebKitAPI/Tests/WTF/StringOperators.cpp
index 149b85b21..7a1d9297f 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/StringOperators.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/StringOperators.cpp
@@ -184,4 +184,20 @@ TEST(WTF, StringOperators)
#endif
}
+TEST(WTF, ConcatenateCharacterArrayAndEmptyString)
+{
+ String emptyString;
+ EXPECT_EQ(static_cast<unsigned>(0), emptyString.length());
+
+ UChar ucharArray[] = { 't', 'e', 's', 't', '\0' };
+ String concatenation16 = ucharArray + emptyString;
+ ASSERT_EQ(static_cast<unsigned>(4), concatenation16.length());
+ ASSERT_TRUE(concatenation16 == String(ucharArray));
+
+ LChar lcharArray[] = { 't', 'e', 's', 't', '\0' };
+ String concatenation8 = lcharArray + emptyString;
+ ASSERT_EQ(static_cast<unsigned>(4), concatenation8.length());
+ ASSERT_TRUE(concatenation8 == String(lcharArray));
+}
+
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/StringView.cpp b/Tools/TestWebKitAPI/Tests/WTF/StringView.cpp
new file mode 100644
index 000000000..408cc642e
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/StringView.cpp
@@ -0,0 +1,736 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <wtf/text/StringBuilder.h>
+#include <wtf/text/StringView.h>
+
+namespace TestWebKitAPI {
+
+TEST(WTF, StringViewEmptyVsNull)
+{
+ StringView nullView;
+ EXPECT_TRUE(nullView.isNull());
+ EXPECT_TRUE(nullView.isEmpty());
+
+ // Test in a boolean context to test operator bool().
+ if (nullView)
+ FAIL();
+ else
+ SUCCEED();
+
+ if (!nullView)
+ SUCCEED();
+ else
+ FAIL();
+
+ StringView emptyView = StringView::empty();
+ EXPECT_FALSE(emptyView.isNull());
+ EXPECT_TRUE(emptyView.isEmpty());
+
+ // Test in a boolean context to test operator bool().
+ if (emptyView)
+ SUCCEED();
+ else
+ FAIL();
+
+ if (!emptyView)
+ FAIL();
+ else
+ SUCCEED();
+
+ StringView viewWithCharacters(String("hello"));
+ EXPECT_FALSE(viewWithCharacters.isNull());
+ EXPECT_FALSE(viewWithCharacters.isEmpty());
+
+ // Test in a boolean context to test operator bool().
+ if (viewWithCharacters)
+ SUCCEED();
+ else
+ FAIL();
+
+ if (!viewWithCharacters)
+ FAIL();
+ else
+ SUCCEED();
+}
+
+bool compareLoopIterations(StringView::CodePoints codePoints, std::vector<UChar32> expected)
+{
+ std::vector<UChar32> actual;
+ for (auto codePoint : codePoints)
+ actual.push_back(codePoint);
+ return actual == expected;
+}
+
+static bool compareLoopIterations(StringView::CodeUnits codeUnits, std::vector<UChar> expected)
+{
+ std::vector<UChar> actual;
+ for (auto codeUnit : codeUnits)
+ actual.push_back(codeUnit);
+ return actual == expected;
+}
+
+static void build(StringBuilder& builder, std::vector<UChar> input)
+{
+ builder.clear();
+ for (auto codeUnit : input)
+ builder.append(codeUnit);
+}
+
+TEST(WTF, StringViewIterators)
+{
+ compareLoopIterations(StringView().codePoints(), { });
+ compareLoopIterations(StringView().codeUnits(), { });
+
+ compareLoopIterations(StringView::empty().codePoints(), { });
+ compareLoopIterations(StringView::empty().codeUnits(), { });
+
+ compareLoopIterations(StringView(String("hello")).codePoints(), {'h', 'e', 'l', 'l', 'o'});
+ compareLoopIterations(StringView(String("hello")).codeUnits(), {'h', 'e', 'l', 'l', 'o'});
+
+ StringBuilder b;
+ build(b, {0xD800, 0xDD55}); // Surrogates for unicode code point U+10155
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0x10155}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0xD800, 0xDD55}));
+
+ build(b, {0xD800}); // Leading surrogate only
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0xD800}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0xD800}));
+
+ build(b, {0xD800, 0xD801}); // Two leading surrogates
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0xD800, 0xD801}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0xD800, 0xD801}));
+
+ build(b, {0xDD55}); // Trailing surrogate only
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0xDD55}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0xDD55}));
+
+ build(b, {0xD800, 'h'}); // Leading surrogate followed by non-surrogate
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0xD800, 'h'}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0xD800, 'h'}));
+
+ build(b, {0x0306}); // "COMBINING BREVE"
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0x0306}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0x0306}));
+
+ build(b, {0x0306, 0xD800, 0xDD55, 'h', 'e', 'l', 'o'}); // Mix of single code unit and multi code unit code points
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0x0306, 0x10155, 'h', 'e', 'l', 'o'}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0x0306, 0xD800, 0xDD55, 'h', 'e', 'l', 'o'}));
+}
+
+TEST(WTF, StringViewEqualIgnoringASCIICaseBasic)
+{
+ RefPtr<StringImpl> a = StringImpl::createFromLiteral("aBcDeFG");
+ RefPtr<StringImpl> b = StringImpl::createFromLiteral("ABCDEFG");
+ RefPtr<StringImpl> c = StringImpl::createFromLiteral("abcdefg");
+ const char d[] = "aBcDeFG";
+ RefPtr<StringImpl> empty = StringImpl::create(reinterpret_cast<const LChar*>(""));
+ RefPtr<StringImpl> shorter = StringImpl::createFromLiteral("abcdef");
+ RefPtr<StringImpl> different = StringImpl::createFromLiteral("abcrefg");
+
+ StringView stringViewA(*a.get());
+ StringView stringViewB(*b.get());
+ StringView stringViewC(*c.get());
+ StringView emptyStringView(*empty.get());
+ StringView shorterStringView(*shorter.get());
+ StringView differentStringView(*different.get());
+
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewB));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, stringViewC));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, stringViewC));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, d));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, d));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewC, d));
+
+ // Identity.
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewA));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, stringViewB));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewC, stringViewC));
+
+ // Transitivity.
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewB));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, stringViewC));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewC));
+
+ // Negative cases.
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewA, emptyStringView));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewB, emptyStringView));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewC, emptyStringView));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewA, shorterStringView));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewB, shorterStringView));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewC, shorterStringView));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewA, differentStringView));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewB, differentStringView));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewC, differentStringView));
+ ASSERT_FALSE(equalIgnoringASCIICase(emptyStringView, d));
+ ASSERT_FALSE(equalIgnoringASCIICase(shorterStringView, d));
+ ASSERT_FALSE(equalIgnoringASCIICase(differentStringView, d));
+}
+
+TEST(WTF, StringViewEqualIgnoringASCIICaseWithEmpty)
+{
+ RefPtr<StringImpl> a = StringImpl::create(reinterpret_cast<const LChar*>(""));
+ RefPtr<StringImpl> b = StringImpl::create(reinterpret_cast<const LChar*>(""));
+ StringView stringViewA(*a.get());
+ StringView stringViewB(*b.get());
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewB));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, stringViewA));
+}
+
+TEST(WTF, StringViewEqualIgnoringASCIICaseWithLatin1Characters)
+{
+ RefPtr<StringImpl> a = StringImpl::create(reinterpret_cast<const LChar*>("aBcéeFG"));
+ RefPtr<StringImpl> b = StringImpl::create(reinterpret_cast<const LChar*>("ABCÉEFG"));
+ RefPtr<StringImpl> c = StringImpl::create(reinterpret_cast<const LChar*>("ABCéEFG"));
+ RefPtr<StringImpl> d = StringImpl::create(reinterpret_cast<const LChar*>("abcéefg"));
+ const char e[] = "aBcéeFG";
+ StringView stringViewA(*a.get());
+ StringView stringViewB(*b.get());
+ StringView stringViewC(*c.get());
+ StringView stringViewD(*d.get());
+
+ // Identity.
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewA));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, stringViewB));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewC, stringViewC));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewD, stringViewD));
+
+ // All combination.
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewA, stringViewB));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewC));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewD));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewB, stringViewC));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewB, stringViewD));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewC, stringViewD));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewA, e));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewB, e));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewC, e));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewD, e));
+}
+
+StringView stringViewFromLiteral(const char* characters)
+{
+ return StringView(reinterpret_cast<const LChar*>(characters), strlen(characters));
+}
+
+StringView stringViewFromUTF8(String &ref, const char* characters)
+{
+ ref = String::fromUTF8(characters);
+ return ref;
+}
+
+TEST(WTF, StringViewFindIgnoringASCIICaseBasic)
+{
+ String referenceAHolder;
+ StringView referenceA = stringViewFromUTF8(referenceAHolder, "aBcéeFG");
+ String referenceBHolder;
+ StringView referenceB = stringViewFromUTF8(referenceBHolder, "ABCÉEFG");
+
+ // Search the exact string.
+ EXPECT_EQ(static_cast<size_t>(0), referenceA.findIgnoringASCIICase(referenceA));
+ EXPECT_EQ(static_cast<size_t>(0), referenceB.findIgnoringASCIICase(referenceB));
+
+ // A and B are distinct by the non-ascii character é/É.
+ EXPECT_EQ(static_cast<size_t>(notFound), referenceA.findIgnoringASCIICase(referenceB));
+ EXPECT_EQ(static_cast<size_t>(notFound), referenceB.findIgnoringASCIICase(referenceA));
+
+ String tempStringHolder;
+ // Find the prefix.
+ EXPECT_EQ(static_cast<size_t>(0), referenceA.findIgnoringASCIICase(stringViewFromLiteral("a")));
+ EXPECT_EQ(static_cast<size_t>(0), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "abcé")));
+ EXPECT_EQ(static_cast<size_t>(0), referenceA.findIgnoringASCIICase(stringViewFromLiteral("A")));
+ EXPECT_EQ(static_cast<size_t>(0), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCé")));
+ EXPECT_EQ(static_cast<size_t>(0), referenceB.findIgnoringASCIICase(stringViewFromLiteral("a")));
+ EXPECT_EQ(static_cast<size_t>(0), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "abcÉ")));
+ EXPECT_EQ(static_cast<size_t>(0), referenceB.findIgnoringASCIICase(stringViewFromLiteral("A")));
+ EXPECT_EQ(static_cast<size_t>(0), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ")));
+
+ // Not a prefix.
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromLiteral("x")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "accé")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "abcÉ")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromLiteral("X")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABDé")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromLiteral("y")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "accÉ")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "abcé")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromLiteral("Y")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABdÉ")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCé")));
+
+ // Find the infix.
+ EXPECT_EQ(static_cast<size_t>(2), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "cée")));
+ EXPECT_EQ(static_cast<size_t>(3), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ée")));
+ EXPECT_EQ(static_cast<size_t>(2), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "cé")));
+ EXPECT_EQ(static_cast<size_t>(2), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "c")));
+ EXPECT_EQ(static_cast<size_t>(3), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "é")));
+ EXPECT_EQ(static_cast<size_t>(2), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Cée")));
+ EXPECT_EQ(static_cast<size_t>(3), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éE")));
+ EXPECT_EQ(static_cast<size_t>(2), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Cé")));
+ EXPECT_EQ(static_cast<size_t>(2), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "C")));
+
+ EXPECT_EQ(static_cast<size_t>(2), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "cÉe")));
+ EXPECT_EQ(static_cast<size_t>(3), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Ée")));
+ EXPECT_EQ(static_cast<size_t>(2), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "cÉ")));
+ EXPECT_EQ(static_cast<size_t>(2), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "c")));
+ EXPECT_EQ(static_cast<size_t>(3), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "É")));
+ EXPECT_EQ(static_cast<size_t>(2), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "CÉe")));
+ EXPECT_EQ(static_cast<size_t>(3), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ÉE")));
+ EXPECT_EQ(static_cast<size_t>(2), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "CÉ")));
+ EXPECT_EQ(static_cast<size_t>(2), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "C")));
+
+ // Not an infix.
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "céd")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Ée")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "bé")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "x")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "É")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "CÉe")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éd")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "CÉ")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Y")));
+
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "cée")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Éc")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "cé")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "W")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "é")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "bÉe")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éE")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "BÉ")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "z")));
+
+ // Find the suffix.
+ EXPECT_EQ(static_cast<size_t>(6), referenceA.findIgnoringASCIICase(stringViewFromLiteral("g")));
+ EXPECT_EQ(static_cast<size_t>(4), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "efg")));
+ EXPECT_EQ(static_cast<size_t>(3), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éefg")));
+ EXPECT_EQ(static_cast<size_t>(6), referenceA.findIgnoringASCIICase(stringViewFromLiteral("G")));
+ EXPECT_EQ(static_cast<size_t>(4), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "EFG")));
+ EXPECT_EQ(static_cast<size_t>(3), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éEFG")));
+
+ EXPECT_EQ(static_cast<size_t>(6), referenceB.findIgnoringASCIICase(stringViewFromLiteral("g")));
+ EXPECT_EQ(static_cast<size_t>(4), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "efg")));
+ EXPECT_EQ(static_cast<size_t>(3), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Éefg")));
+ EXPECT_EQ(static_cast<size_t>(6), referenceB.findIgnoringASCIICase(stringViewFromLiteral("G")));
+ EXPECT_EQ(static_cast<size_t>(4), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "EFG")));
+ EXPECT_EQ(static_cast<size_t>(3), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ÉEFG")));
+
+ // Not a suffix.
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromLiteral("X")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "edg")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Éefg")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromLiteral("w")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "dFG")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ÉEFG")));
+
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromLiteral("Z")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ffg")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éefg")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromLiteral("r")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "EgG")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éEFG")));
+}
+
+TEST(WTF, StringViewFindIgnoringASCIICaseWithValidOffset)
+{
+ String referenceHolder;
+ StringView reference = stringViewFromUTF8(referenceHolder, "ABCÉEFGaBcéeFG");
+ String tempStringHolder;
+
+ EXPECT_EQ(static_cast<size_t>(0), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABC"), 0));
+ EXPECT_EQ(static_cast<size_t>(7), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABC"), 1));
+ EXPECT_EQ(static_cast<size_t>(0), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ"), 0));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ"), 1));
+ EXPECT_EQ(static_cast<size_t>(7), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCé"), 0));
+ EXPECT_EQ(static_cast<size_t>(7), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCé"), 1));
+}
+
+TEST(WTF, StringViewFindIgnoringASCIICaseWithInvalidOffset)
+{
+ String referenceHolder;
+ StringView reference = stringViewFromUTF8(referenceHolder, "ABCÉEFGaBcéeFG");
+ String tempStringHolder;
+
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABC"), 15));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABC"), 16));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ"), 17));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ"), 42));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ"), std::numeric_limits<unsigned>::max()));
+}
+
+TEST(WTF, StringViewFindIgnoringASCIICaseOnEmpty)
+{
+ String referenceHolder;
+ StringView reference = stringViewFromUTF8(referenceHolder, "ABCÉEFG");
+ StringView empty = stringViewFromLiteral("");
+ EXPECT_EQ(static_cast<size_t>(0), reference.findIgnoringASCIICase(empty));
+ EXPECT_EQ(static_cast<size_t>(0), reference.findIgnoringASCIICase(empty, 0));
+ EXPECT_EQ(static_cast<size_t>(3), reference.findIgnoringASCIICase(empty, 3));
+ EXPECT_EQ(static_cast<size_t>(7), reference.findIgnoringASCIICase(empty, 7));
+ EXPECT_EQ(static_cast<size_t>(7), reference.findIgnoringASCIICase(empty, 8));
+ EXPECT_EQ(static_cast<size_t>(7), reference.findIgnoringASCIICase(empty, 42));
+ EXPECT_EQ(static_cast<size_t>(7), reference.findIgnoringASCIICase(empty, std::numeric_limits<unsigned>::max()));
+}
+
+TEST(WTF, StringViewFindIgnoringASCIICaseWithPatternLongerThanReference)
+{
+ String referenceHolder;
+ StringView reference = stringViewFromUTF8(referenceHolder, "ABCÉEFG");
+ String patternHolder;
+ StringView pattern = stringViewFromUTF8(patternHolder, "ABCÉEFGA");
+
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference.findIgnoringASCIICase(pattern));
+ EXPECT_EQ(static_cast<size_t>(0), pattern.findIgnoringASCIICase(reference));
+}
+
+TEST(WTF, StringViewStartsWithBasic)
+{
+ StringView reference = stringViewFromLiteral("abcdefg");
+ String referenceUTF8Ref;
+ StringView referenceUTF8 = stringViewFromUTF8(referenceUTF8Ref, "àîûèô");
+
+ StringView oneLetterPrefix = stringViewFromLiteral("a");
+ StringView shortPrefix = stringViewFromLiteral("abc");
+ StringView longPrefix = stringViewFromLiteral("abcdef");
+ StringView upperCasePrefix = stringViewFromLiteral("ABC");
+ StringView empty = stringViewFromLiteral("");
+ StringView notPrefix = stringViewFromLiteral("bc");
+
+ String oneLetterPrefixUTF8Ref;
+ StringView oneLetterPrefixUTF8 = stringViewFromUTF8(oneLetterPrefixUTF8Ref, "à");
+ String shortPrefixUTF8Ref;
+ StringView shortPrefixUTF8 = stringViewFromUTF8(shortPrefixUTF8Ref, "àî");
+ String longPrefixUTF8Ref;
+ StringView longPrefixUTF8 = stringViewFromUTF8(longPrefixUTF8Ref, "àîûè");
+ String upperCasePrefixUTF8Ref;
+ StringView upperCasePrefixUTF8 = stringViewFromUTF8(upperCasePrefixUTF8Ref, "ÀÎ");
+ String notPrefixUTF8Ref;
+ StringView notPrefixUTF8 = stringViewFromUTF8(notPrefixUTF8Ref, "îû");
+
+ EXPECT_TRUE(reference.startsWith(reference));
+ EXPECT_TRUE(reference.startsWith(oneLetterPrefix));
+ EXPECT_TRUE(reference.startsWith(shortPrefix));
+ EXPECT_TRUE(reference.startsWith(longPrefix));
+ EXPECT_TRUE(reference.startsWith(empty));
+
+ EXPECT_TRUE(referenceUTF8.startsWith(referenceUTF8));
+ EXPECT_TRUE(referenceUTF8.startsWith(oneLetterPrefixUTF8));
+ EXPECT_TRUE(referenceUTF8.startsWith(shortPrefixUTF8));
+ EXPECT_TRUE(referenceUTF8.startsWith(longPrefixUTF8));
+ EXPECT_TRUE(referenceUTF8.startsWith(empty));
+
+ EXPECT_FALSE(reference.startsWith(notPrefix));
+ EXPECT_FALSE(reference.startsWith(upperCasePrefix));
+ EXPECT_FALSE(reference.startsWith(notPrefixUTF8));
+ EXPECT_FALSE(reference.startsWith(upperCasePrefixUTF8));
+ EXPECT_FALSE(referenceUTF8.startsWith(notPrefix));
+ EXPECT_FALSE(referenceUTF8.startsWith(upperCasePrefix));
+ EXPECT_FALSE(referenceUTF8.startsWith(notPrefixUTF8));
+ EXPECT_FALSE(referenceUTF8.startsWith(upperCasePrefixUTF8));
+}
+
+TEST(WTF, StringViewStartsWithEmpty)
+{
+ StringView a = stringViewFromLiteral("");
+ String refB;
+ StringView b = stringViewFromUTF8(refB, "");
+
+ EXPECT_TRUE(a.startsWith(a));
+ EXPECT_TRUE(a.startsWith(b));
+ EXPECT_TRUE(b.startsWith(a));
+ EXPECT_TRUE(b.startsWith(b));
+}
+
+TEST(WTF, StringViewStartsWithIgnoringASCIICaseBasic)
+{
+ StringView reference = stringViewFromLiteral("abcdefg");
+
+ String referenceUTF8Ref;
+ StringView referenceUTF8 = stringViewFromUTF8(referenceUTF8Ref, "àîûèô");
+
+ StringView oneLetterPrefix = stringViewFromLiteral("a");
+ StringView shortPrefix = stringViewFromLiteral("abc");
+ StringView longPrefix = stringViewFromLiteral("abcdef");
+ StringView upperCasePrefix = stringViewFromLiteral("ABC");
+ StringView mixedCasePrefix = stringViewFromLiteral("aBcDe");
+ StringView empty = stringViewFromLiteral("");
+ StringView notPrefix = stringViewFromLiteral("bc");
+
+ String oneLetterPrefixUTF8Ref;
+ StringView oneLetterPrefixUTF8 = stringViewFromUTF8(oneLetterPrefixUTF8Ref, "à");
+ String shortPrefixUTF8Ref;
+ StringView shortPrefixUTF8 = stringViewFromUTF8(shortPrefixUTF8Ref, "àî");
+ String longPrefixUTF8Ref;
+ StringView longPrefixUTF8 = stringViewFromUTF8(longPrefixUTF8Ref, "àîûè");
+ String upperCasePrefixUTF8Ref;
+ StringView upperCasePrefixUTF8 = stringViewFromUTF8(upperCasePrefixUTF8Ref, "ÀÎ");
+ String notPrefixUTF8Ref;
+ StringView notPrefixUTF8 = stringViewFromUTF8(notPrefixUTF8Ref, "îû");
+
+ EXPECT_TRUE(reference.startsWithIgnoringASCIICase(reference));
+ EXPECT_TRUE(reference.startsWithIgnoringASCIICase(oneLetterPrefix));
+ EXPECT_TRUE(reference.startsWithIgnoringASCIICase(shortPrefix));
+ EXPECT_TRUE(reference.startsWithIgnoringASCIICase(longPrefix));
+ EXPECT_TRUE(reference.startsWithIgnoringASCIICase(empty));
+ EXPECT_TRUE(reference.startsWithIgnoringASCIICase(upperCasePrefix));
+ EXPECT_TRUE(reference.startsWithIgnoringASCIICase(mixedCasePrefix));
+
+ EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(referenceUTF8));
+ EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(oneLetterPrefixUTF8));
+ EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(shortPrefixUTF8));
+ EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(longPrefixUTF8));
+ EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(empty));
+
+ EXPECT_FALSE(reference.startsWithIgnoringASCIICase(notPrefix));
+ EXPECT_FALSE(reference.startsWithIgnoringASCIICase(notPrefixUTF8));
+ EXPECT_FALSE(reference.startsWithIgnoringASCIICase(upperCasePrefixUTF8));
+ EXPECT_FALSE(referenceUTF8.startsWithIgnoringASCIICase(notPrefix));
+ EXPECT_FALSE(referenceUTF8.startsWithIgnoringASCIICase(notPrefixUTF8));
+ EXPECT_FALSE(referenceUTF8.startsWithIgnoringASCIICase(upperCasePrefix));
+ EXPECT_FALSE(referenceUTF8.startsWithIgnoringASCIICase(upperCasePrefixUTF8));
+}
+
+
+TEST(WTF, StringViewStartsWithIgnoringASCIICaseEmpty)
+{
+ StringView a = stringViewFromLiteral("");
+ String refB;
+ StringView b = stringViewFromUTF8(refB, "");
+
+ EXPECT_TRUE(a.startsWithIgnoringASCIICase(a));
+ EXPECT_TRUE(a.startsWithIgnoringASCIICase(b));
+ EXPECT_TRUE(b.startsWithIgnoringASCIICase(a));
+ EXPECT_TRUE(b.startsWithIgnoringASCIICase(b));
+}
+
+TEST(WTF, StringViewStartsWithIgnoringASCIICaseWithLatin1Characters)
+{
+ StringView reference = stringViewFromLiteral("aBcéeFG");
+ String referenceUTF8Ref;
+ StringView referenceUTF8 = stringViewFromUTF8(referenceUTF8Ref, "aBcéeFG");
+
+ StringView a = stringViewFromLiteral("aBcéeF");
+ StringView b = stringViewFromLiteral("ABCéEF");
+ StringView c = stringViewFromLiteral("abcéef");
+ StringView d = stringViewFromLiteral("Abcéef");
+
+ String refE;
+ StringView e = stringViewFromUTF8(refE, "aBcéeF");
+ String refF;
+ StringView f = stringViewFromUTF8(refF, "ABCéEF");
+ String refG;
+ StringView g = stringViewFromUTF8(refG, "abcéef");
+ String refH;
+ StringView h = stringViewFromUTF8(refH, "Abcéef");
+
+ EXPECT_TRUE(reference.startsWithIgnoringASCIICase(a));
+ EXPECT_TRUE(reference.startsWithIgnoringASCIICase(b));
+ EXPECT_TRUE(reference.startsWithIgnoringASCIICase(c));
+ EXPECT_TRUE(reference.startsWithIgnoringASCIICase(d));
+
+ EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(e));
+ EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(f));
+ EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(g));
+ EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(h));
+
+ EXPECT_FALSE(reference.endsWithIgnoringASCIICase(referenceUTF8));
+ EXPECT_FALSE(referenceUTF8.endsWithIgnoringASCIICase(reference));
+}
+
+TEST(WTF, StringViewEndsWithBasic)
+{
+ StringView reference = stringViewFromLiteral("abcdefg");
+ String referenceUTF8Ref;
+ StringView referenceUTF8 = stringViewFromUTF8(referenceUTF8Ref, "àîûèô");
+
+ StringView oneLetterSuffix = stringViewFromLiteral("g");
+ StringView shortSuffix = stringViewFromLiteral("efg");
+ StringView longSuffix = stringViewFromLiteral("cdefg");
+ StringView upperCaseSuffix = stringViewFromLiteral("EFG");
+ StringView empty = stringViewFromLiteral("");
+ StringView notSuffix = stringViewFromLiteral("bc");
+
+ String oneLetterSuffixUTF8Ref;
+ StringView oneLetterSuffixUTF8 = stringViewFromUTF8(oneLetterSuffixUTF8Ref, "ô");
+ String shortSuffixUTF8Ref;
+ StringView shortSuffixUTF8 = stringViewFromUTF8(shortSuffixUTF8Ref, "èô");
+ String longSuffixUTF8Ref;
+ StringView longSuffixUTF8 = stringViewFromUTF8(longSuffixUTF8Ref, "îûèô");
+ String upperCaseSuffixUTF8Ref;
+ StringView upperCaseSuffixUTF8 = stringViewFromUTF8(upperCaseSuffixUTF8Ref, "ÈÔ");
+ String notSuffixUTF8Ref;
+ StringView notSuffixUTF8 = stringViewFromUTF8(notSuffixUTF8Ref, "îû");
+
+ EXPECT_TRUE(reference.endsWith(reference));
+ EXPECT_TRUE(reference.endsWith(oneLetterSuffix));
+ EXPECT_TRUE(reference.endsWith(shortSuffix));
+ EXPECT_TRUE(reference.endsWith(longSuffix));
+ EXPECT_TRUE(reference.endsWith(empty));
+
+ EXPECT_TRUE(referenceUTF8.endsWith(referenceUTF8));
+ EXPECT_TRUE(referenceUTF8.endsWith(oneLetterSuffixUTF8));
+ EXPECT_TRUE(referenceUTF8.endsWith(shortSuffixUTF8));
+ EXPECT_TRUE(referenceUTF8.endsWith(longSuffixUTF8));
+ EXPECT_TRUE(referenceUTF8.endsWith(empty));
+
+ EXPECT_FALSE(reference.endsWith(notSuffix));
+ EXPECT_FALSE(reference.endsWith(upperCaseSuffix));
+ EXPECT_FALSE(reference.endsWith(notSuffixUTF8));
+ EXPECT_FALSE(reference.endsWith(upperCaseSuffixUTF8));
+ EXPECT_FALSE(referenceUTF8.endsWith(notSuffix));
+ EXPECT_FALSE(referenceUTF8.endsWith(upperCaseSuffix));
+ EXPECT_FALSE(referenceUTF8.endsWith(notSuffixUTF8));
+ EXPECT_FALSE(referenceUTF8.endsWith(upperCaseSuffixUTF8));
+}
+
+TEST(WTF, StringViewEndsWithEmpty)
+{
+ StringView a = stringViewFromLiteral("");
+ String refB;
+ StringView b = stringViewFromUTF8(refB, "");
+
+ EXPECT_TRUE(a.endsWith(a));
+ EXPECT_TRUE(a.endsWith(b));
+ EXPECT_TRUE(b.endsWith(a));
+ EXPECT_TRUE(b.endsWith(b));
+}
+
+TEST(WTF, StringViewEndsWithIgnoringASCIICaseBasic)
+{
+ StringView reference = stringViewFromLiteral("abcdefg");
+ String referenceUTF8Ref;
+ StringView referenceUTF8 = stringViewFromUTF8(referenceUTF8Ref, "àîûèô");
+
+ StringView oneLetterSuffix = stringViewFromLiteral("g");
+ StringView shortSuffix = stringViewFromLiteral("efg");
+ StringView longSuffix = stringViewFromLiteral("bcdefg");
+ StringView upperCaseSuffix = stringViewFromLiteral("EFG");
+ StringView mixedCaseSuffix = stringViewFromLiteral("bCdeFg");
+ StringView empty = stringViewFromLiteral("");
+ StringView notSuffix = stringViewFromLiteral("bc");
+
+ String oneLetterSuffixUTF8Ref;
+ StringView oneLetterSuffixUTF8 = stringViewFromUTF8(oneLetterSuffixUTF8Ref, "ô");
+ String shortSuffixUTF8Ref;
+ StringView shortSuffixUTF8 = stringViewFromUTF8(shortSuffixUTF8Ref, "èô");
+ String longSuffixUTF8Ref;
+ StringView longSuffixUTF8 = stringViewFromUTF8(longSuffixUTF8Ref, "îûèô");
+ String upperCaseSuffixUTF8Ref;
+ StringView upperCaseSuffixUTF8 = stringViewFromUTF8(upperCaseSuffixUTF8Ref, "ÈÔ");
+ String notSuffixUTF8Ref;
+ StringView notSuffixUTF8 = stringViewFromUTF8(notSuffixUTF8Ref, "îû");
+
+ EXPECT_TRUE(reference.endsWithIgnoringASCIICase(reference));
+ EXPECT_TRUE(reference.endsWithIgnoringASCIICase(oneLetterSuffix));
+ EXPECT_TRUE(reference.endsWithIgnoringASCIICase(shortSuffix));
+ EXPECT_TRUE(reference.endsWithIgnoringASCIICase(longSuffix));
+ EXPECT_TRUE(reference.endsWithIgnoringASCIICase(empty));
+ EXPECT_TRUE(reference.endsWithIgnoringASCIICase(upperCaseSuffix));
+ EXPECT_TRUE(reference.endsWithIgnoringASCIICase(mixedCaseSuffix));
+
+ EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(referenceUTF8));
+ EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(oneLetterSuffixUTF8));
+ EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(shortSuffixUTF8));
+ EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(longSuffixUTF8));
+ EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(empty));
+
+ EXPECT_FALSE(reference.endsWithIgnoringASCIICase(notSuffix));
+ EXPECT_FALSE(reference.endsWithIgnoringASCIICase(notSuffixUTF8));
+ EXPECT_FALSE(reference.endsWithIgnoringASCIICase(upperCaseSuffixUTF8));
+ EXPECT_FALSE(referenceUTF8.endsWithIgnoringASCIICase(notSuffix));
+ EXPECT_FALSE(referenceUTF8.endsWithIgnoringASCIICase(notSuffixUTF8));
+ EXPECT_FALSE(referenceUTF8.endsWithIgnoringASCIICase(upperCaseSuffix));
+ EXPECT_FALSE(referenceUTF8.endsWithIgnoringASCIICase(upperCaseSuffixUTF8));
+}
+
+TEST(WTF, StringViewEndsWithIgnoringASCIICaseEmpty)
+{
+ StringView a = stringViewFromLiteral("");
+ String refB;
+ StringView b = stringViewFromUTF8(refB, "");
+
+ EXPECT_TRUE(a.endsWithIgnoringASCIICase(a));
+ EXPECT_TRUE(a.endsWithIgnoringASCIICase(b));
+ EXPECT_TRUE(b.endsWithIgnoringASCIICase(a));
+ EXPECT_TRUE(b.endsWithIgnoringASCIICase(b));
+}
+
+TEST(WTF, StringViewEndsWithIgnoringASCIICaseWithLatin1Characters)
+{
+ StringView reference = stringViewFromLiteral("aBcéeFG");
+ String referenceUTF8Ref;
+ StringView referenceUTF8 = stringViewFromUTF8(referenceUTF8Ref, "aBcéeFG");
+
+ StringView a = stringViewFromLiteral("BcéeFG");
+ StringView b = stringViewFromLiteral("BCéEFG");
+ StringView c = stringViewFromLiteral("bcéefG");
+ StringView d = stringViewFromLiteral("bcéefg");
+
+ String refE;
+ StringView e = stringViewFromUTF8(refE, "bcéefG");
+ String refF;
+ StringView f = stringViewFromUTF8(refF, "BCéEFG");
+ String refG;
+ StringView g = stringViewFromUTF8(refG, "bcéefG");
+ String refH;
+ StringView h = stringViewFromUTF8(refH, "bcéefg");
+
+ EXPECT_TRUE(reference.endsWithIgnoringASCIICase(a));
+ EXPECT_TRUE(reference.endsWithIgnoringASCIICase(b));
+ EXPECT_TRUE(reference.endsWithIgnoringASCIICase(c));
+ EXPECT_TRUE(reference.endsWithIgnoringASCIICase(d));
+
+ EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(e));
+ EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(f));
+ EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(g));
+ EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(h));
+
+ EXPECT_FALSE(reference.endsWithIgnoringASCIICase(referenceUTF8));
+ EXPECT_FALSE(referenceUTF8.endsWithIgnoringASCIICase(reference));
+}
+
+TEST(WTF, StringView8Bit)
+{
+ StringView nullView;
+ StringView emptyView = StringView::empty();
+ EXPECT_TRUE(StringView().is8Bit());
+ EXPECT_TRUE(StringView::empty().is8Bit());
+
+ LChar* lcharPtr = nullptr;
+ UChar* ucharPtr = nullptr;
+ EXPECT_TRUE(StringView(lcharPtr, 0).is8Bit());
+ EXPECT_FALSE(StringView(ucharPtr, 0).is8Bit());
+
+ EXPECT_TRUE(StringView(String(lcharPtr, 0)).is8Bit());
+ EXPECT_TRUE(StringView(String(ucharPtr, 0)).is8Bit());
+
+ EXPECT_TRUE(StringView(String().impl()).is8Bit());
+ EXPECT_TRUE(StringView(emptyString().impl()).is8Bit());
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/Vector.cpp b/Tools/TestWebKitAPI/Tests/WTF/Vector.cpp
index 2278784c4..6567ac559 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/Vector.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/Vector.cpp
@@ -27,6 +27,7 @@
#include "MoveOnly.h"
#include <wtf/Vector.h>
+#include <wtf/text/CString.h>
namespace TestWebKitAPI {
@@ -34,8 +35,8 @@ TEST(WTF_Vector, Basic)
{
Vector<int> intVector;
EXPECT_TRUE(intVector.isEmpty());
- EXPECT_EQ(0ul, intVector.size());
- EXPECT_EQ(0ul, intVector.capacity());
+ EXPECT_EQ(0U, intVector.size());
+ EXPECT_EQ(0U, intVector.capacity());
}
TEST(WTF_Vector, Iterator)
@@ -94,6 +95,103 @@ TEST(WTF_Vector, InitializerList)
EXPECT_EQ(4, vector[3]);
}
+TEST(WTF_Vector, InitializeFromOtherInitialCapacity)
+{
+ Vector<int, 3> vector = { 1, 3, 2, 4 };
+ Vector<int, 5> vectorCopy(vector);
+ EXPECT_EQ(4U, vector.size());
+ EXPECT_EQ(4U, vectorCopy.size());
+ EXPECT_EQ(5U, vectorCopy.capacity());
+
+ EXPECT_EQ(1, vectorCopy[0]);
+ EXPECT_EQ(3, vectorCopy[1]);
+ EXPECT_EQ(2, vectorCopy[2]);
+ EXPECT_EQ(4, vectorCopy[3]);
+}
+
+TEST(WTF_Vector, CopyFromOtherInitialCapacity)
+{
+ Vector<int, 3> vector = { 1, 3, 2, 4 };
+ Vector<int, 5> vectorCopy { 0 };
+ EXPECT_EQ(4U, vector.size());
+ EXPECT_EQ(1U, vectorCopy.size());
+
+ vectorCopy = vector;
+
+ EXPECT_EQ(4U, vector.size());
+ EXPECT_EQ(4U, vectorCopy.size());
+ EXPECT_EQ(5U, vectorCopy.capacity());
+
+ EXPECT_EQ(1, vectorCopy[0]);
+ EXPECT_EQ(3, vectorCopy[1]);
+ EXPECT_EQ(2, vectorCopy[2]);
+ EXPECT_EQ(4, vectorCopy[3]);
+}
+
+TEST(WTF_Vector, InitializeFromOtherOverflowBehavior)
+{
+ Vector<int, 7, WTF::CrashOnOverflow> vector = { 4, 3, 2, 1 };
+ Vector<int, 7, UnsafeVectorOverflow> vectorCopy(vector);
+ EXPECT_EQ(4U, vector.size());
+ EXPECT_EQ(4U, vectorCopy.size());
+
+ EXPECT_EQ(4, vectorCopy[0]);
+ EXPECT_EQ(3, vectorCopy[1]);
+ EXPECT_EQ(2, vectorCopy[2]);
+ EXPECT_EQ(1, vectorCopy[3]);
+}
+
+TEST(WTF_Vector, CopyFromOtherOverflowBehavior)
+{
+ Vector<int, 7, WTF::CrashOnOverflow> vector = { 4, 3, 2, 1 };
+ Vector<int, 7, UnsafeVectorOverflow> vectorCopy = { 0, 0, 0 };
+
+ EXPECT_EQ(4U, vector.size());
+ EXPECT_EQ(3U, vectorCopy.size());
+
+ vectorCopy = vector;
+
+ EXPECT_EQ(4U, vector.size());
+ EXPECT_EQ(4U, vectorCopy.size());
+
+ EXPECT_EQ(4, vectorCopy[0]);
+ EXPECT_EQ(3, vectorCopy[1]);
+ EXPECT_EQ(2, vectorCopy[2]);
+ EXPECT_EQ(1, vectorCopy[3]);
+}
+
+TEST(WTF_Vector, InitializeFromOtherMinCapacity)
+{
+ Vector<int, 7, WTF::CrashOnOverflow, 1> vector = { 3, 4, 2, 1 };
+ Vector<int, 7, WTF::CrashOnOverflow, 50> vectorCopy(vector);
+ EXPECT_EQ(4U, vector.size());
+ EXPECT_EQ(4U, vectorCopy.size());
+
+ EXPECT_EQ(3, vectorCopy[0]);
+ EXPECT_EQ(4, vectorCopy[1]);
+ EXPECT_EQ(2, vectorCopy[2]);
+ EXPECT_EQ(1, vectorCopy[3]);
+}
+
+TEST(WTF_Vector, CopyFromOtherMinCapacity)
+{
+ Vector<int, 7, WTF::CrashOnOverflow, 1> vector = { 3, 4, 2, 1 };
+ Vector<int, 7, WTF::CrashOnOverflow, 50> vectorCopy;
+
+ EXPECT_EQ(4U, vector.size());
+ EXPECT_EQ(0U, vectorCopy.size());
+
+ vectorCopy = vector;
+
+ EXPECT_EQ(4U, vector.size());
+ EXPECT_EQ(4U, vectorCopy.size());
+
+ EXPECT_EQ(3, vectorCopy[0]);
+ EXPECT_EQ(4, vectorCopy[1]);
+ EXPECT_EQ(2, vectorCopy[2]);
+ EXPECT_EQ(1, vectorCopy[3]);
+}
+
TEST(WTF_Vector, Reverse)
{
Vector<int> intVector;
@@ -149,12 +247,12 @@ TEST(WTF_Vector, MoveOnly_UncheckedAppend)
vector.reserveInitialCapacity(100);
for (size_t i = 0; i < 100; ++i) {
MoveOnly moveOnly(i);
- vector.uncheckedAppend(std::move(moveOnly));
- EXPECT_EQ(moveOnly.value(), 0U);
+ vector.uncheckedAppend(WTFMove(moveOnly));
+ EXPECT_EQ(0U, moveOnly.value());
}
for (size_t i = 0; i < 100; ++i)
- EXPECT_EQ(vector[i].value(), i);
+ EXPECT_EQ(i, vector[i].value());
}
TEST(WTF_Vector, MoveOnly_Append)
@@ -163,12 +261,12 @@ TEST(WTF_Vector, MoveOnly_Append)
for (size_t i = 0; i < 100; ++i) {
MoveOnly moveOnly(i);
- vector.append(std::move(moveOnly));
- EXPECT_EQ(moveOnly.value(), 0U);
+ vector.append(WTFMove(moveOnly));
+ EXPECT_EQ(0U, moveOnly.value());
}
for (size_t i = 0; i < 100; ++i)
- EXPECT_EQ(vector[i].value(), i);
+ EXPECT_EQ(i, vector[i].value());
for (size_t i = 0; i < 16; ++i) {
Vector<MoveOnly> vector;
@@ -177,13 +275,13 @@ TEST(WTF_Vector, MoveOnly_Append)
for (size_t j = 0; j < i; ++j)
vector.append(j);
- vector.append(std::move(vector[0]));
+ vector.append(WTFMove(vector[0]));
- EXPECT_EQ(vector[0].value(), 0U);
+ EXPECT_EQ(0U, vector[0].value());
for (size_t j = 0; j < i; ++j)
- EXPECT_EQ(vector[j + 1].value(), j);
- EXPECT_EQ(vector.last().value(), i);
+ EXPECT_EQ(j, vector[j + 1].value());
+ EXPECT_EQ(i, vector.last().value());
}
}
@@ -193,7 +291,7 @@ TEST(WTF_Vector, MoveOnly_Insert)
for (size_t i = 0; i < 100; ++i) {
MoveOnly moveOnly(i);
- vector.insert(0, std::move(moveOnly));
+ vector.insert(0, WTFMove(moveOnly));
EXPECT_EQ(0U, moveOnly.value());
}
@@ -203,11 +301,11 @@ TEST(WTF_Vector, MoveOnly_Insert)
for (size_t i = 0; i < 200; i += 2) {
MoveOnly moveOnly(1000 + i);
- vector.insert(i, std::move(moveOnly));
+ vector.insert(i, WTFMove(moveOnly));
EXPECT_EQ(0U, moveOnly.value());
}
- EXPECT_EQ(vector.size(), 200U);
+ EXPECT_EQ(200U, vector.size());
for (size_t i = 0; i < 200; ++i) {
if (i % 2)
EXPECT_EQ(99 - i / 2, vector[i].value());
@@ -216,4 +314,304 @@ TEST(WTF_Vector, MoveOnly_Insert)
}
}
+TEST(WTF_Vector, MoveOnly_TakeLast)
+{
+ Vector<MoveOnly> vector;
+
+ for (size_t i = 0; i < 100; ++i) {
+ MoveOnly moveOnly(i);
+ vector.append(WTFMove(moveOnly));
+ EXPECT_EQ(0U, moveOnly.value());
+ }
+
+ EXPECT_EQ(100U, vector.size());
+ for (size_t i = 0; i < 100; ++i)
+ EXPECT_EQ(99 - i, vector.takeLast().value());
+
+ EXPECT_EQ(0U, vector.size());
+}
+
+TEST(WTF_Vector, VectorOfVectorsOfVectorsInlineCapacitySwap)
+{
+ Vector<Vector<Vector<int, 1>, 1>, 1> a;
+ Vector<Vector<Vector<int, 1>, 1>, 1> b;
+ Vector<Vector<Vector<int, 1>, 1>, 1> c;
+
+ EXPECT_EQ(0U, a.size());
+ EXPECT_EQ(0U, b.size());
+ EXPECT_EQ(0U, c.size());
+
+ Vector<int, 1> x;
+ x.append(42);
+
+ EXPECT_EQ(1U, x.size());
+ EXPECT_EQ(42, x[0]);
+
+ Vector<Vector<int, 1>, 1> y;
+ y.append(x);
+
+ EXPECT_EQ(1U, x.size());
+ EXPECT_EQ(42, x[0]);
+ EXPECT_EQ(1U, y.size());
+ EXPECT_EQ(1U, y[0].size());
+ EXPECT_EQ(42, y[0][0]);
+
+ a.append(y);
+
+ EXPECT_EQ(1U, x.size());
+ EXPECT_EQ(42, x[0]);
+ EXPECT_EQ(1U, y.size());
+ EXPECT_EQ(1U, y[0].size());
+ EXPECT_EQ(42, y[0][0]);
+ EXPECT_EQ(1U, a.size());
+ EXPECT_EQ(1U, a[0].size());
+ EXPECT_EQ(1U, a[0][0].size());
+ EXPECT_EQ(42, a[0][0][0]);
+
+ a.swap(b);
+
+ EXPECT_EQ(0U, a.size());
+ EXPECT_EQ(1U, x.size());
+ EXPECT_EQ(42, x[0]);
+ EXPECT_EQ(1U, y.size());
+ EXPECT_EQ(1U, y[0].size());
+ EXPECT_EQ(42, y[0][0]);
+ EXPECT_EQ(1U, b.size());
+ EXPECT_EQ(1U, b[0].size());
+ EXPECT_EQ(1U, b[0][0].size());
+ EXPECT_EQ(42, b[0][0][0]);
+
+ b.swap(c);
+
+ EXPECT_EQ(0U, a.size());
+ EXPECT_EQ(0U, b.size());
+ EXPECT_EQ(1U, x.size());
+ EXPECT_EQ(42, x[0]);
+ EXPECT_EQ(1U, y.size());
+ EXPECT_EQ(1U, y[0].size());
+ EXPECT_EQ(42, y[0][0]);
+ EXPECT_EQ(1U, c.size());
+ EXPECT_EQ(1U, c[0].size());
+ EXPECT_EQ(1U, c[0][0].size());
+ EXPECT_EQ(42, c[0][0][0]);
+
+ y[0][0] = 24;
+
+ EXPECT_EQ(1U, x.size());
+ EXPECT_EQ(42, x[0]);
+ EXPECT_EQ(1U, y.size());
+ EXPECT_EQ(1U, y[0].size());
+ EXPECT_EQ(24, y[0][0]);
+
+ a.append(y);
+
+ EXPECT_EQ(1U, x.size());
+ EXPECT_EQ(42, x[0]);
+ EXPECT_EQ(1U, y.size());
+ EXPECT_EQ(1U, y[0].size());
+ EXPECT_EQ(24, y[0][0]);
+ EXPECT_EQ(1U, a.size());
+ EXPECT_EQ(1U, a[0].size());
+ EXPECT_EQ(1U, a[0][0].size());
+ EXPECT_EQ(24, a[0][0][0]);
+ EXPECT_EQ(1U, c.size());
+ EXPECT_EQ(1U, c[0].size());
+ EXPECT_EQ(1U, c[0][0].size());
+ EXPECT_EQ(42, c[0][0][0]);
+ EXPECT_EQ(0U, b.size());
+}
+
+TEST(WTF_Vector, RemoveFirst)
+{
+ Vector<int> v;
+ EXPECT_TRUE(v.isEmpty());
+ EXPECT_FALSE(v.removeFirst(1));
+ EXPECT_FALSE(v.removeFirst(-1));
+ EXPECT_TRUE(v.isEmpty());
+
+ v.fill(2, 10);
+ EXPECT_EQ(10U, v.size());
+ EXPECT_FALSE(v.removeFirst(1));
+ EXPECT_EQ(10U, v.size());
+ v.clear();
+
+ v.fill(1, 10);
+ EXPECT_EQ(10U, v.size());
+ EXPECT_TRUE(v.removeFirst(1));
+ EXPECT_TRUE(v == Vector<int>({1, 1, 1, 1, 1, 1, 1, 1, 1}));
+ EXPECT_EQ(9U, v.size());
+ EXPECT_FALSE(v.removeFirst(2));
+ EXPECT_EQ(9U, v.size());
+ EXPECT_TRUE(v == Vector<int>({1, 1, 1, 1, 1, 1, 1, 1, 1}));
+
+ unsigned removed = 0;
+ while (v.removeFirst(1))
+ ++removed;
+ EXPECT_EQ(9U, removed);
+ EXPECT_TRUE(v.isEmpty());
+
+ v.resize(1);
+ EXPECT_EQ(1U, v.size());
+ EXPECT_TRUE(v.removeFirst(1));
+ EXPECT_EQ(0U, v.size());
+ EXPECT_TRUE(v.isEmpty());
+}
+
+TEST(WTF_Vector, RemoveAll)
+{
+ // Using a memcpy-able type.
+ static_assert(VectorTraits<int>::canMoveWithMemcpy, "Should use a memcpy-able type");
+ Vector<int> v;
+ EXPECT_TRUE(v.isEmpty());
+ EXPECT_FALSE(v.removeAll(1));
+ EXPECT_FALSE(v.removeAll(-1));
+ EXPECT_TRUE(v.isEmpty());
+
+ v.fill(1, 10);
+ EXPECT_EQ(10U, v.size());
+ EXPECT_EQ(10U, v.removeAll(1));
+ EXPECT_TRUE(v.isEmpty());
+
+ v.fill(2, 10);
+ EXPECT_EQ(10U, v.size());
+ EXPECT_EQ(0U, v.removeAll(1));
+ EXPECT_EQ(10U, v.size());
+
+ v = {1, 2, 1, 2, 1, 2, 2, 1, 1, 1};
+ EXPECT_EQ(10U, v.size());
+ EXPECT_EQ(6U, v.removeAll(1));
+ EXPECT_EQ(4U, v.size());
+ EXPECT_TRUE(v == Vector<int>({2, 2, 2, 2}));
+ EXPECT_TRUE(v.find(1) == notFound);
+ EXPECT_EQ(4U, v.removeAll(2));
+ EXPECT_TRUE(v.isEmpty());
+
+ v = {3, 1, 2, 1, 2, 1, 2, 2, 1, 1, 1, 3};
+ EXPECT_EQ(12U, v.size());
+ EXPECT_EQ(6U, v.removeAll(1));
+ EXPECT_EQ(6U, v.size());
+ EXPECT_TRUE(v.find(1) == notFound);
+ EXPECT_TRUE(v == Vector<int>({3, 2, 2, 2, 2, 3}));
+
+ EXPECT_EQ(4U, v.removeAll(2));
+ EXPECT_EQ(2U, v.size());
+ EXPECT_TRUE(v.find(2) == notFound);
+ EXPECT_TRUE(v == Vector<int>({3, 3}));
+
+ EXPECT_EQ(2U, v.removeAll(3));
+ EXPECT_TRUE(v.isEmpty());
+
+ v = {1, 1, 1, 3, 2, 4, 2, 2, 2, 4, 4, 3};
+ EXPECT_EQ(12U, v.size());
+ EXPECT_EQ(3U, v.removeAll(1));
+ EXPECT_EQ(9U, v.size());
+ EXPECT_TRUE(v.find(1) == notFound);
+ EXPECT_TRUE(v == Vector<int>({3, 2, 4, 2, 2, 2, 4, 4, 3}));
+
+ // Using a non memcpy-able type.
+ static_assert(!VectorTraits<CString>::canMoveWithMemcpy, "Should use a non memcpy-able type");
+ Vector<CString> vExpected;
+ Vector<CString> v2;
+ EXPECT_TRUE(v2.isEmpty());
+ EXPECT_FALSE(v2.removeAll("1"));
+ EXPECT_TRUE(v2.isEmpty());
+
+ v2.fill("1", 10);
+ EXPECT_EQ(10U, v2.size());
+ EXPECT_EQ(10U, v2.removeAll("1"));
+ EXPECT_TRUE(v2.isEmpty());
+
+ v2.fill("2", 10);
+ EXPECT_EQ(10U, v2.size());
+ EXPECT_EQ(0U, v2.removeAll("1"));
+ EXPECT_EQ(10U, v2.size());
+
+ v2 = {"1", "2", "1", "2", "1", "2", "2", "1", "1", "1"};
+ EXPECT_EQ(10U, v2.size());
+ EXPECT_EQ(6U, v2.removeAll("1"));
+ EXPECT_EQ(4U, v2.size());
+ EXPECT_TRUE(v2.find("1") == notFound);
+ EXPECT_EQ(4U, v2.removeAll("2"));
+ EXPECT_TRUE(v2.isEmpty());
+
+ v2 = {"3", "1", "2", "1", "2", "1", "2", "2", "1", "1", "1", "3"};
+ EXPECT_EQ(12U, v2.size());
+ EXPECT_EQ(6U, v2.removeAll("1"));
+ EXPECT_EQ(6U, v2.size());
+ EXPECT_TRUE(v2.find("1") == notFound);
+ vExpected = {"3", "2", "2", "2", "2", "3"};
+ EXPECT_TRUE(v2 == vExpected);
+
+ EXPECT_EQ(4U, v2.removeAll("2"));
+ EXPECT_EQ(2U, v2.size());
+ EXPECT_TRUE(v2.find("2") == notFound);
+ vExpected = {"3", "3"};
+ EXPECT_TRUE(v2 == vExpected);
+
+ EXPECT_EQ(2U, v2.removeAll("3"));
+ EXPECT_TRUE(v2.isEmpty());
+
+ v2 = {"1", "1", "1", "3", "2", "4", "2", "2", "2", "4", "4", "3"};
+ EXPECT_EQ(12U, v2.size());
+ EXPECT_EQ(3U, v2.removeAll("1"));
+ EXPECT_EQ(9U, v2.size());
+ EXPECT_TRUE(v2.find("1") == notFound);
+ vExpected = {"3", "2", "4", "2", "2", "2", "4", "4", "3"};
+ EXPECT_TRUE(v2 == vExpected);
+}
+
+TEST(WTF_Vector, RemoveFirstMatching)
+{
+ Vector<int> v;
+ EXPECT_TRUE(v.isEmpty());
+ EXPECT_FALSE(v.removeFirstMatching([] (int value) { return value > 0; }));
+ EXPECT_FALSE(v.removeFirstMatching([] (int) { return true; }));
+ EXPECT_FALSE(v.removeFirstMatching([] (int) { return false; }));
+
+ v = {3, 1, 2, 1, 2, 1, 2, 2, 1, 1, 1, 3};
+ EXPECT_EQ(12U, v.size());
+ EXPECT_FALSE(v.removeFirstMatching([] (int) { return false; }));
+ EXPECT_EQ(12U, v.size());
+ EXPECT_FALSE(v.removeFirstMatching([] (int value) { return value < 0; }));
+ EXPECT_EQ(12U, v.size());
+ EXPECT_TRUE(v.removeFirstMatching([] (int value) { return value < 3; }));
+ EXPECT_EQ(11U, v.size());
+ EXPECT_TRUE(v == Vector<int>({3, 2, 1, 2, 1, 2, 2, 1, 1, 1, 3}));
+ EXPECT_TRUE(v.removeFirstMatching([] (int value) { return value > 2; }));
+ EXPECT_EQ(10U, v.size());
+ EXPECT_TRUE(v == Vector<int>({2, 1, 2, 1, 2, 2, 1, 1, 1, 3}));
+ EXPECT_TRUE(v.removeFirstMatching([] (int value) { return value > 2; }));
+ EXPECT_EQ(9U, v.size());
+ EXPECT_TRUE(v == Vector<int>({2, 1, 2, 1, 2, 2, 1, 1, 1}));
+}
+
+TEST(WTF_Vector, RemoveAllMatching)
+{
+ Vector<int> v;
+ EXPECT_TRUE(v.isEmpty());
+ EXPECT_FALSE(v.removeAllMatching([] (int value) { return value > 0; }));
+ EXPECT_FALSE(v.removeAllMatching([] (int) { return true; }));
+ EXPECT_FALSE(v.removeAllMatching([] (int) { return false; }));
+
+ v = {3, 1, 2, 1, 2, 1, 2, 2, 1, 1, 1, 3};
+ EXPECT_EQ(12U, v.size());
+ EXPECT_EQ(0U, v.removeAllMatching([] (int) { return false; }));
+ EXPECT_EQ(12U, v.size());
+ EXPECT_EQ(0U, v.removeAllMatching([] (int value) { return value < 0; }));
+ EXPECT_EQ(12U, v.size());
+ EXPECT_EQ(12U, v.removeAllMatching([] (int value) { return value > 0; }));
+ EXPECT_TRUE(v.isEmpty());
+
+ v = {3, 1, 2, 1, 2, 1, 3, 2, 2, 1, 1, 1, 3};
+ EXPECT_EQ(13U, v.size());
+ EXPECT_EQ(3U, v.removeAllMatching([] (int value) { return value > 2; }));
+ EXPECT_EQ(10U, v.size());
+ EXPECT_TRUE(v == Vector<int>({1, 2, 1, 2, 1, 2, 2, 1, 1, 1}));
+ EXPECT_EQ(6U, v.removeAllMatching([] (int value) { return value != 2; }));
+ EXPECT_EQ(4U, v.size());
+ EXPECT_TRUE(v == Vector<int>({2, 2, 2, 2}));
+ EXPECT_EQ(4U, v.removeAllMatching([] (int value) { return value == 2; }));
+ EXPECT_TRUE(v.isEmpty());
+}
+
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/WTFString.cpp b/Tools/TestWebKitAPI/Tests/WTF/WTFString.cpp
new file mode 100644
index 000000000..e809ddac4
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/WTFString.cpp
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <limits>
+#include <wtf/MathExtras.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/WTFString.h>
+
+namespace TestWebKitAPI {
+
+TEST(WTF, StringCreationFromLiteral)
+{
+ String stringFromLiteral(ASCIILiteral("Explicit construction syntax"));
+ ASSERT_EQ(strlen("Explicit construction syntax"), stringFromLiteral.length());
+ ASSERT_TRUE(stringFromLiteral == "Explicit construction syntax");
+ ASSERT_TRUE(stringFromLiteral.is8Bit());
+ ASSERT_TRUE(String("Explicit construction syntax") == stringFromLiteral);
+
+ String stringWithTemplate("Template Literal", String::ConstructFromLiteral);
+ ASSERT_EQ(strlen("Template Literal"), stringWithTemplate.length());
+ ASSERT_TRUE(stringWithTemplate == "Template Literal");
+ ASSERT_TRUE(stringWithTemplate.is8Bit());
+ ASSERT_TRUE(String("Template Literal") == stringWithTemplate);
+}
+
+TEST(WTF, StringASCII)
+{
+ CString output;
+
+ // Null String.
+ output = String().ascii();
+ ASSERT_STREQ("", output.data());
+
+ // Empty String.
+ output = emptyString().ascii();
+ ASSERT_STREQ("", output.data());
+
+ // Regular String.
+ output = String(ASCIILiteral("foobar")).ascii();
+ ASSERT_STREQ("foobar", output.data());
+}
+
+static void testNumberToStringECMAScript(double number, const char* reference)
+{
+ CString numberString = String::numberToStringECMAScript(number).latin1();
+ ASSERT_STREQ(reference, numberString.data());
+}
+
+TEST(WTF, StringNumberToStringECMAScriptBoundaries)
+{
+ typedef std::numeric_limits<double> Limits;
+
+ // Infinity.
+ testNumberToStringECMAScript(Limits::infinity(), "Infinity");
+ testNumberToStringECMAScript(-Limits::infinity(), "-Infinity");
+
+ // NaN.
+ testNumberToStringECMAScript(-Limits::quiet_NaN(), "NaN");
+
+ // Zeros.
+ testNumberToStringECMAScript(0, "0");
+ testNumberToStringECMAScript(-0, "0");
+
+ // Min-Max.
+ testNumberToStringECMAScript(Limits::min(), "2.2250738585072014e-308");
+ testNumberToStringECMAScript(Limits::max(), "1.7976931348623157e+308");
+}
+
+TEST(WTF, StringNumberToStringECMAScriptRegularNumbers)
+{
+ // Pi.
+ testNumberToStringECMAScript(piDouble, "3.141592653589793");
+ testNumberToStringECMAScript(piFloat, "3.1415927410125732");
+ testNumberToStringECMAScript(piOverTwoDouble, "1.5707963267948966");
+ testNumberToStringECMAScript(piOverTwoFloat, "1.5707963705062866");
+ testNumberToStringECMAScript(piOverFourDouble, "0.7853981633974483");
+ testNumberToStringECMAScript(piOverFourFloat, "0.7853981852531433");
+
+ // e.
+ const double e = 2.71828182845904523536028747135266249775724709369995;
+ testNumberToStringECMAScript(e, "2.718281828459045");
+
+ // c, speed of light in m/s.
+ const double c = 299792458;
+ testNumberToStringECMAScript(c, "299792458");
+
+ // Golen ratio.
+ const double phi = 1.6180339887498948482;
+ testNumberToStringECMAScript(phi, "1.618033988749895");
+}
+
+TEST(WTF, StringReplaceWithLiteral)
+{
+ // Cases for 8Bit source.
+ String testString = "1224";
+ ASSERT_TRUE(testString.is8Bit());
+ testString.replaceWithLiteral('2', "");
+ ASSERT_STREQ("14", testString.utf8().data());
+
+ testString = "1224";
+ ASSERT_TRUE(testString.is8Bit());
+ testString.replaceWithLiteral('2', "3");
+ ASSERT_STREQ("1334", testString.utf8().data());
+
+ testString = "1224";
+ ASSERT_TRUE(testString.is8Bit());
+ testString.replaceWithLiteral('2', "555");
+ ASSERT_STREQ("15555554", testString.utf8().data());
+
+ testString = "1224";
+ ASSERT_TRUE(testString.is8Bit());
+ testString.replaceWithLiteral('3', "NotFound");
+ ASSERT_STREQ("1224", testString.utf8().data());
+
+ // Cases for 16Bit source.
+ testString = String::fromUTF8("résumé");
+ ASSERT_FALSE(testString.is8Bit());
+ testString.replaceWithLiteral(UChar(0x00E9 /*U+00E9 is 'é'*/), "e");
+ ASSERT_STREQ("resume", testString.utf8().data());
+
+ testString = String::fromUTF8("résumé");
+ ASSERT_FALSE(testString.is8Bit());
+ testString.replaceWithLiteral(UChar(0x00E9 /*U+00E9 is 'é'*/), "");
+ ASSERT_STREQ("rsum", testString.utf8().data());
+
+ testString = String::fromUTF8("résumé");
+ ASSERT_FALSE(testString.is8Bit());
+ testString.replaceWithLiteral('3', "NotFound");
+ ASSERT_STREQ("résumé", testString.utf8().data());
+}
+
+TEST(WTF, StringIsolatedCopy)
+{
+ String original = "1234";
+ auto copy = WTFMove(original).isolatedCopy();
+ ASSERT_FALSE(original.impl() == copy.impl());
+}
+
+TEST(WTF, StringToInt)
+{
+ bool ok;
+
+ EXPECT_EQ(0, String().toInt());
+ EXPECT_EQ(0, String().toInt(&ok));
+ EXPECT_FALSE(ok);
+
+ EXPECT_EQ(0, emptyString().toInt());
+ EXPECT_EQ(0, emptyString().toInt(&ok));
+ EXPECT_FALSE(ok);
+
+ EXPECT_EQ(0, String("0").toInt());
+ EXPECT_EQ(0, String("0").toInt(&ok));
+ EXPECT_TRUE(ok);
+
+ EXPECT_EQ(1, String("1").toInt());
+ EXPECT_EQ(1, String("1").toInt(&ok));
+ EXPECT_TRUE(ok);
+
+ EXPECT_EQ(2147483647, String("2147483647").toInt());
+ EXPECT_EQ(2147483647, String("2147483647").toInt(&ok));
+ EXPECT_TRUE(ok);
+
+ EXPECT_EQ(0, String("2147483648").toInt());
+ EXPECT_EQ(0, String("2147483648").toInt(&ok));
+ EXPECT_FALSE(ok);
+
+ EXPECT_EQ(-2147483648, String("-2147483648").toInt());
+ EXPECT_EQ(-2147483648, String("-2147483648").toInt(&ok));
+ EXPECT_TRUE(ok);
+
+ EXPECT_EQ(0, String("-2147483649").toInt());
+ EXPECT_EQ(0, String("-2147483649").toInt(&ok));
+ EXPECT_FALSE(ok);
+
+ // fail if we see leading junk
+ EXPECT_EQ(0, String("x1").toInt());
+ EXPECT_EQ(0, String("x1").toInt(&ok));
+ EXPECT_FALSE(ok);
+
+ // succeed if we see leading spaces
+ EXPECT_EQ(1, String(" 1").toInt());
+ EXPECT_EQ(1, String(" 1").toInt(&ok));
+ EXPECT_TRUE(ok);
+
+ // silently ignore trailing junk
+ EXPECT_EQ(1, String("1x").toInt());
+ EXPECT_EQ(1, String("1x").toInt(&ok));
+ EXPECT_TRUE(ok);
+}
+
+TEST(WTF, StringToDouble)
+{
+ bool ok;
+
+ EXPECT_EQ(0.0, String().toDouble());
+ EXPECT_EQ(0.0, String().toDouble(&ok));
+ EXPECT_FALSE(ok);
+
+ EXPECT_EQ(0.0, emptyString().toDouble());
+ EXPECT_EQ(0.0, emptyString().toDouble(&ok));
+ EXPECT_FALSE(ok);
+
+ EXPECT_EQ(0.0, String("0").toDouble());
+ EXPECT_EQ(0.0, String("0").toDouble(&ok));
+ EXPECT_TRUE(ok);
+
+ EXPECT_EQ(1.0, String("1").toDouble());
+ EXPECT_EQ(1.0, String("1").toDouble(&ok));
+ EXPECT_TRUE(ok);
+
+ // fail if we see leading junk
+ EXPECT_EQ(0.0, String("x1").toDouble());
+ EXPECT_EQ(0.0, String("x1").toDouble(&ok));
+ EXPECT_FALSE(ok);
+
+ // succeed if we see leading spaces
+ EXPECT_EQ(1.0, String(" 1").toDouble());
+ EXPECT_EQ(1.0, String(" 1").toDouble(&ok));
+ EXPECT_TRUE(ok);
+
+ // ignore trailing junk, but return false for "ok"
+ // FIXME: This is an inconsistency with toInt, which always guarantees
+ // it will return 0 if it's also going to return false for ok.
+ EXPECT_EQ(1.0, String("1x").toDouble());
+ EXPECT_EQ(1.0, String("1x").toDouble(&ok));
+ EXPECT_FALSE(ok);
+
+ // parse only numbers, not special values such as "infinity"
+ EXPECT_EQ(0.0, String("infinity").toDouble());
+ EXPECT_EQ(0.0, String("infinity").toDouble(&ok));
+ EXPECT_FALSE(ok);
+
+ // parse only numbers, not special values such as "nan"
+ EXPECT_EQ(0.0, String("nan").toDouble());
+ EXPECT_EQ(0.0, String("nan").toDouble(&ok));
+ EXPECT_FALSE(ok);
+}
+
+TEST(WTF, StringhasInfixStartingAt)
+{
+ EXPECT_TRUE(String("Test").is8Bit());
+ EXPECT_TRUE(String("Te").is8Bit());
+ EXPECT_TRUE(String("st").is8Bit());
+ EXPECT_TRUE(String("Test").hasInfixStartingAt(String("Te"), 0));
+ EXPECT_FALSE(String("Test").hasInfixStartingAt(String("Te"), 2));
+ EXPECT_TRUE(String("Test").hasInfixStartingAt(String("st"), 2));
+ EXPECT_FALSE(String("Test").hasInfixStartingAt(String("ST"), 2));
+
+ EXPECT_FALSE(String::fromUTF8("中国").is8Bit());
+ EXPECT_FALSE(String::fromUTF8("中").is8Bit());
+ EXPECT_FALSE(String::fromUTF8("国").is8Bit());
+ EXPECT_TRUE(String::fromUTF8("中国").hasInfixStartingAt(String::fromUTF8("中"), 0));
+ EXPECT_FALSE(String::fromUTF8("中国").hasInfixStartingAt(String::fromUTF8("中"), 1));
+ EXPECT_TRUE(String::fromUTF8("中国").hasInfixStartingAt(String::fromUTF8("国"), 1));
+
+ EXPECT_FALSE(String::fromUTF8("中国").hasInfixStartingAt(String("Te"), 0));
+ EXPECT_FALSE(String("Test").hasInfixStartingAt(String::fromUTF8("中"), 2));
+}
+
+TEST(WTF, StringExistingHash)
+{
+ String string1("Template Literal");
+ ASSERT_FALSE(string1.isNull());
+ ASSERT_FALSE(string1.impl()->hasHash());
+ string1.impl()->hash();
+ ASSERT_EQ(string1.existingHash(), string1.impl()->existingHash());
+ String string2;
+ ASSERT_EQ(string2.existingHash(), 0u);
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/WeakPtr.cpp b/Tools/TestWebKitAPI/Tests/WTF/WeakPtr.cpp
new file mode 100644
index 000000000..5b900007a
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/WeakPtr.cpp
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "config.h"
+#include "test.h"
+
+#include <wtf/WeakPtr.h>
+
+namespace TestWebKitAPI {
+
+TEST(WTF_WeakPtr, Basic)
+{
+ int dummy = 5;
+ WeakPtrFactory<int>* factory = new WeakPtrFactory<int>(&dummy);
+ WeakPtr<int> weakPtr1 = factory->createWeakPtr();
+ WeakPtr<int> weakPtr2 = factory->createWeakPtr();
+ WeakPtr<int> weakPtr3 = factory->createWeakPtr();
+ EXPECT_EQ(weakPtr1.get(), &dummy);
+ EXPECT_EQ(weakPtr2.get(), &dummy);
+ EXPECT_EQ(weakPtr3.get(), &dummy);
+ EXPECT_TRUE(weakPtr1);
+ EXPECT_TRUE(weakPtr2);
+ EXPECT_TRUE(weakPtr3);
+ delete factory;
+ EXPECT_NULL(weakPtr1.get());
+ EXPECT_NULL(weakPtr2.get());
+ EXPECT_NULL(weakPtr3.get());
+ EXPECT_FALSE(weakPtr1);
+ EXPECT_FALSE(weakPtr2);
+ EXPECT_FALSE(weakPtr3);
+}
+
+TEST(WTF_WeakPtr, Assignment)
+{
+ int dummy = 5;
+ WeakPtr<int> weakPtr;
+ {
+ WeakPtrFactory<int> factory(&dummy);
+ EXPECT_NULL(weakPtr.get());
+ weakPtr = factory.createWeakPtr();
+ EXPECT_EQ(weakPtr.get(), &dummy);
+ }
+ EXPECT_NULL(weakPtr.get());
+}
+
+TEST(WTF_WeakPtr, MultipleFactories)
+{
+ int dummy1 = 5;
+ int dummy2 = 7;
+ WeakPtrFactory<int>* factory1 = new WeakPtrFactory<int>(&dummy1);
+ WeakPtrFactory<int>* factory2 = new WeakPtrFactory<int>(&dummy2);
+ WeakPtr<int> weakPtr1 = factory1->createWeakPtr();
+ WeakPtr<int> weakPtr2 = factory2->createWeakPtr();
+ EXPECT_EQ(weakPtr1.get(), &dummy1);
+ EXPECT_EQ(weakPtr2.get(), &dummy2);
+ delete factory1;
+ EXPECT_NULL(weakPtr1.get());
+ EXPECT_EQ(weakPtr2.get(), &dummy2);
+ delete factory2;
+ EXPECT_NULL(weakPtr2.get());
+}
+
+TEST(WTF_WeakPtr, RevokeAll)
+{
+ int dummy = 5;
+ WeakPtrFactory<int> factory(&dummy);
+ WeakPtr<int> weakPtr1 = factory.createWeakPtr();
+ WeakPtr<int> weakPtr2 = factory.createWeakPtr();
+ WeakPtr<int> weakPtr3 = factory.createWeakPtr();
+ EXPECT_EQ(weakPtr1.get(), &dummy);
+ EXPECT_EQ(weakPtr2.get(), &dummy);
+ EXPECT_EQ(weakPtr3.get(), &dummy);
+ factory.revokeAll();
+ EXPECT_NULL(weakPtr1.get());
+ EXPECT_NULL(weakPtr2.get());
+ EXPECT_NULL(weakPtr3.get());
+}
+
+TEST(WTF_WeakPtr, NullFactory)
+{
+ WeakPtrFactory<int> factory(nullptr);
+ WeakPtr<int> weakPtr = factory.createWeakPtr();
+ EXPECT_NULL(weakPtr.get());
+ factory.revokeAll();
+ EXPECT_NULL(weakPtr.get());
+}
+
+struct Foo {
+ void bar() { };
+};
+
+TEST(WTF_WeakPtr, Dereference)
+{
+ Foo f;
+ WeakPtrFactory<Foo> factory(&f);
+ WeakPtr<Foo> weakPtr = factory.createWeakPtr();
+ weakPtr->bar();
+}
+
+TEST(WTF_WeakPtr, Forget)
+{
+ int dummy = 5;
+ int dummy2 = 7;
+
+ WeakPtrFactory<int> outerFactory(&dummy2);
+ WeakPtr<int> weakPtr1, weakPtr2, weakPtr3, weakPtr4;
+ {
+ WeakPtrFactory<int> innerFactory(&dummy);
+ weakPtr1 = innerFactory.createWeakPtr();
+ weakPtr2 = innerFactory.createWeakPtr();
+ weakPtr3 = innerFactory.createWeakPtr();
+ EXPECT_EQ(weakPtr1.get(), &dummy);
+ EXPECT_EQ(weakPtr2.get(), &dummy);
+ EXPECT_EQ(weakPtr3.get(), &dummy);
+ weakPtr1.clear();
+ weakPtr3 = nullptr;
+ EXPECT_NULL(weakPtr1.get());
+ EXPECT_EQ(weakPtr2.get(), &dummy);
+ EXPECT_NULL(weakPtr3.get());
+ weakPtr1.clear();
+ weakPtr3.clear();
+ EXPECT_NULL(weakPtr1.get());
+ EXPECT_EQ(weakPtr2.get(), &dummy);
+ EXPECT_NULL(weakPtr3.get());
+ weakPtr3 = nullptr;
+ EXPECT_NULL(weakPtr1.get());
+ EXPECT_EQ(weakPtr2.get(), &dummy);
+ EXPECT_NULL(weakPtr3.get());
+
+ weakPtr4 = weakPtr2;
+ EXPECT_EQ(weakPtr2.get(), &dummy);
+ EXPECT_EQ(weakPtr4.get(), &dummy);
+
+ WeakPtr<int> weakPtr5 = weakPtr2;
+ EXPECT_EQ(weakPtr2.get(), &dummy);
+ EXPECT_EQ(weakPtr5.get(), &dummy);
+ weakPtr5.clear();
+ EXPECT_NULL(weakPtr5.get());
+ EXPECT_EQ(weakPtr2.get(), &dummy);
+
+ weakPtr4 = outerFactory.createWeakPtr();
+ EXPECT_EQ(weakPtr2.get(), &dummy);
+ EXPECT_EQ(weakPtr4.get(), &dummy2);
+ }
+
+ EXPECT_NULL(weakPtr1.get());
+ EXPECT_NULL(weakPtr2.get());
+ EXPECT_EQ(weakPtr4.get(), &dummy2);
+
+ WeakPtr<int> weakPtr5 = weakPtr4;
+ EXPECT_EQ(weakPtr4.get(), &dummy2);
+ EXPECT_EQ(weakPtr5.get(), &dummy2);
+ weakPtr5.clear();
+ EXPECT_NULL(weakPtr5.get());
+ WeakPtr<int> weakPtr6 = weakPtr5;
+ EXPECT_NULL(weakPtr6.get());
+ EXPECT_EQ(weakPtr5.get(), weakPtr6.get());
+
+ WeakPtr<int> weakPtr7 = outerFactory.createWeakPtr();
+ EXPECT_EQ(weakPtr7.get(), &dummy2);
+ weakPtr7 = nullptr;
+ EXPECT_NULL(weakPtr7.get());
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/WorkQueue.cpp b/Tools/TestWebKitAPI/Tests/WTF/WorkQueue.cpp
new file mode 100644
index 000000000..74f5dc294
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/WorkQueue.cpp
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "config.h"
+
+#include "Test.h"
+#include <wtf/Condition.h>
+#include <wtf/Lock.h>
+#include <wtf/Vector.h>
+#include <wtf/WorkQueue.h>
+#include <string>
+#include <thread>
+
+namespace TestWebKitAPI {
+
+static const char* simpleTestLabel = "simpleTest";
+static const char* longTestLabel = "longTest";
+static const char* thirdTestLabel = "thirdTest";
+static const char* dispatchAfterLabel = "dispatchAfter";
+
+TEST(WTF_WorkQueue, Simple)
+{
+ Lock m_lock;
+ Condition m_testCompleted;
+ Vector<std::string> m_functionCallOrder;
+
+ bool calledSimpleTest = false;
+ bool calledLongTest = false;
+ bool calledThirdTest = false;
+
+ static const char* simpleTestLabel = "simpleTest";
+ static const char* longTestLabel = "longTest";
+ static const char* thirdTestLabel = "thirdTest";
+
+ auto queue = WorkQueue::create("com.apple.WebKit.Test.simple");
+ int initialRefCount = queue->refCount();
+ EXPECT_EQ(1, initialRefCount);
+
+ LockHolder locker(m_lock);
+ queue->dispatch([&](void) {
+ m_functionCallOrder.append(simpleTestLabel);
+ calledSimpleTest = true;
+ });
+
+ queue->dispatch([&](void) {
+ m_functionCallOrder.append(longTestLabel);
+ std::this_thread::sleep_for(std::chrono::nanoseconds(100));
+ calledLongTest = true;
+ });
+
+ queue->dispatch([&](void) {
+ LockHolder locker(m_lock);
+ m_functionCallOrder.append(thirdTestLabel);
+ calledThirdTest = true;
+
+ EXPECT_TRUE(calledSimpleTest);
+ EXPECT_TRUE(calledLongTest);
+ EXPECT_TRUE(calledThirdTest);
+
+ m_testCompleted.notifyOne();
+ });
+
+ EXPECT_GT(queue->refCount(), 1);
+
+ m_testCompleted.wait(m_lock);
+
+ EXPECT_TRUE(calledSimpleTest);
+ EXPECT_TRUE(calledLongTest);
+ EXPECT_TRUE(calledThirdTest);
+
+ EXPECT_EQ(static_cast<size_t>(3), m_functionCallOrder.size());
+ EXPECT_STREQ(simpleTestLabel, m_functionCallOrder[0].c_str());
+ EXPECT_STREQ(longTestLabel, m_functionCallOrder[1].c_str());
+ EXPECT_STREQ(thirdTestLabel, m_functionCallOrder[2].c_str());
+}
+
+TEST(WTF_WorkQueue, TwoQueues)
+{
+ Lock m_lock;
+ Condition m_testQueue1Completed, m_testQueue2Completed;
+ Vector<std::string> m_functionCallOrder;
+
+ bool calledSimpleTest = false;
+ bool calledLongTest = false;
+ bool calledThirdTest = false;
+
+ auto queue1 = WorkQueue::create("com.apple.WebKit.Test.twoQueues1");
+ auto queue2 = WorkQueue::create("com.apple.WebKit.Test.twoQueues2");
+
+ EXPECT_EQ(1, queue1->refCount());
+ EXPECT_EQ(1, queue2->refCount());
+
+ LockHolder locker(m_lock);
+
+ queue1->dispatch([&](void) {
+ m_functionCallOrder.append(simpleTestLabel);
+ calledSimpleTest = true;
+ });
+
+ queue2->dispatch([&](void) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
+
+ LockHolder locker(m_lock);
+
+ // Will fail if queue2 took the mutex before queue1.
+ EXPECT_TRUE(calledThirdTest);
+
+ m_functionCallOrder.append(longTestLabel);
+ calledLongTest = true;
+ m_testQueue2Completed.notifyOne();
+ });
+
+ queue1->dispatch([&](void) {
+ LockHolder locker(m_lock);
+ m_functionCallOrder.append(thirdTestLabel);
+ calledThirdTest = true;
+
+ m_testQueue1Completed.notifyOne();
+ });
+
+ m_testQueue1Completed.wait(m_lock);
+
+ EXPECT_TRUE(calledSimpleTest);
+ EXPECT_FALSE(calledLongTest);
+ EXPECT_TRUE(calledThirdTest);
+
+ m_testQueue2Completed.wait(m_lock);
+
+ EXPECT_TRUE(calledSimpleTest);
+ EXPECT_TRUE(calledLongTest);
+ EXPECT_TRUE(calledThirdTest);
+
+ EXPECT_EQ(static_cast<size_t>(3), m_functionCallOrder.size());
+ EXPECT_STREQ(simpleTestLabel, m_functionCallOrder[0].c_str());
+ EXPECT_STREQ(thirdTestLabel, m_functionCallOrder[1].c_str());
+ EXPECT_STREQ(longTestLabel, m_functionCallOrder[2].c_str());
+}
+
+TEST(WTF_WorkQueue, DispatchAfter)
+{
+ Lock m_lock;
+ Condition m_testCompleted, m_dispatchAfterTestCompleted;
+ Vector<std::string> m_functionCallOrder;
+
+ bool calledSimpleTest = false;
+ bool calledDispatchAfterTest = false;
+
+ auto queue = WorkQueue::create("com.apple.WebKit.Test.dispatchAfter");
+
+ LockHolder locker(m_lock);
+
+ queue->dispatch([&](void) {
+ LockHolder locker(m_lock);
+ m_functionCallOrder.append(simpleTestLabel);
+ calledSimpleTest = true;
+ m_testCompleted.notifyOne();
+ });
+
+ queue->dispatchAfter(std::chrono::milliseconds(500), [&](void) {
+ LockHolder locker(m_lock);
+ m_functionCallOrder.append(dispatchAfterLabel);
+ calledDispatchAfterTest = true;
+ m_dispatchAfterTestCompleted.notifyOne();
+ });
+
+ m_testCompleted.wait(m_lock);
+
+ EXPECT_TRUE(calledSimpleTest);
+ EXPECT_FALSE(calledDispatchAfterTest);
+
+ m_dispatchAfterTestCompleted.wait(m_lock);
+
+ EXPECT_TRUE(calledSimpleTest);
+ EXPECT_TRUE(calledDispatchAfterTest);
+
+ EXPECT_EQ(static_cast<size_t>(2), m_functionCallOrder.size());
+ EXPECT_STREQ(simpleTestLabel, m_functionCallOrder[0].c_str());
+ EXPECT_STREQ(dispatchAfterLabel, m_functionCallOrder[1].c_str());
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/darwin/OSObjectPtr.cpp b/Tools/TestWebKitAPI/Tests/WTF/darwin/OSObjectPtr.cpp
new file mode 100644
index 000000000..5389dcbc8
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/darwin/OSObjectPtr.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <wtf/OSObjectPtr.h>
+
+#include <dispatch/dispatch.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+namespace TestWebKitAPI {
+
+TEST(OSObjectPtr, AdoptOSObject)
+{
+ OSObjectPtr<dispatch_queue_t> foo = adoptOSObject(dispatch_queue_create(0, DISPATCH_QUEUE_SERIAL));
+
+ EXPECT_EQ(1, CFGetRetainCount(foo.get()));
+}
+
+TEST(OSObjectPtr, RetainRelease)
+{
+ dispatch_queue_t foo = dispatch_queue_create(0, DISPATCH_QUEUE_SERIAL);
+ EXPECT_EQ(1, CFGetRetainCount(foo));
+
+ WTF::retainOSObject(foo);
+ EXPECT_EQ(2, CFGetRetainCount(foo));
+
+ WTF::releaseOSObject(foo);
+ EXPECT_EQ(1, CFGetRetainCount(foo));
+}
+
+TEST(OSObjectPtr, LeakRef)
+{
+ OSObjectPtr<dispatch_queue_t> foo = adoptOSObject(dispatch_queue_create(0, DISPATCH_QUEUE_SERIAL));
+ EXPECT_EQ(1, CFGetRetainCount(foo.get()));
+
+ dispatch_queue_t queue = foo.leakRef();
+ EXPECT_EQ(nullptr, foo.get());
+ EXPECT_EQ(1, CFGetRetainCount(queue));
+
+ WTF::releaseOSObject(queue);
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/gobject/GUniquePtr.cpp b/Tools/TestWebKitAPI/Tests/WTF/glib/GUniquePtr.cpp
index 8942f8657..11f02c7b0 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/gobject/GUniquePtr.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/glib/GUniquePtr.cpp
@@ -80,7 +80,7 @@ static void (* _g_key_file_free)(GKeyFile*) = g_key_file_free;
log() << "g_key_file_free(" << ptr << ");"; \
_g_key_file_free(x);
-#include <wtf/gobject/GUniquePtr.h>
+#include <wtf/glib/GUniquePtr.h>
namespace TestWebKitAPI {
diff --git a/Tools/TestWebKitAPI/Tests/WTF/glib/WorkQueueGLib.cpp b/Tools/TestWebKitAPI/Tests/WTF/glib/WorkQueueGLib.cpp
new file mode 100644
index 000000000..9923d6580
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/glib/WorkQueueGLib.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 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 "Test.h"
+#include <gio/gio.h>
+#include <thread>
+#include <wtf/Condition.h>
+#include <wtf/Lock.h>
+#include <wtf/WorkQueue.h>
+#include <wtf/glib/GRefPtr.h>
+#include <wtf/glib/GUniquePtr.h>
+
+namespace TestWebKitAPI {
+
+TEST(WTF_WorkQueue, AsyncIO)
+{
+ struct TestingContext {
+ Lock m_lock;
+ Condition m_testCompleted;
+ GMainContext* m_mainContext;
+ } context;
+
+ auto queue = WorkQueue::create("com.apple.WebKit.Test.AsyncIO");
+ context.m_mainContext = g_main_context_default();
+ EXPECT_FALSE(g_main_context_get_thread_default());
+
+ GUniquePtr<char> currentDirectory(g_get_current_dir());
+ GRefPtr<GFile> file = adoptGRef(g_file_new_for_path(currentDirectory.get()));
+
+ LockHolder locker(context.m_lock);
+ queue->dispatch([&](void) {
+ EXPECT_TRUE(g_main_context_get_thread_default());
+ EXPECT_TRUE(g_main_context_get_thread_default() != context.m_mainContext);
+ context.m_mainContext = g_main_context_get_thread_default();
+ g_file_query_info_async(file.get(), G_FILE_ATTRIBUTE_STANDARD_SIZE, G_FILE_QUERY_INFO_NONE, G_PRIORITY_DEFAULT, nullptr,
+ [](GObject*, GAsyncResult*, gpointer userData) {
+ TestingContext* context = static_cast<TestingContext*>(userData);
+ LockHolder locker(context->m_lock);
+ EXPECT_EQ(g_main_context_get_thread_default(), context->m_mainContext);
+ context->m_testCompleted.notifyOne();
+ }, &context);
+ });
+
+ context.m_testCompleted.wait(context.m_lock);
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/CSSParser.cpp b/Tools/TestWebKitAPI/Tests/WebCore/CSSParser.cpp
new file mode 100644
index 000000000..25c450933
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/CSSParser.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2014 Igalia, S.L. 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 <WebCore/CSSParser.h>
+#include <WebCore/CSSValueList.h>
+#include <WebCore/StyleProperties.h>
+
+namespace TestWebKitAPI {
+
+using namespace WebCore;
+
+#if ENABLE(CSS_GRID_LAYOUT)
+static unsigned computeNumberOfTracks(CSSValueList& valueList)
+{
+ unsigned numberOfTracks = 0;
+ for (const auto& value : valueList) {
+ if (value->isGridLineNamesValue())
+ continue;
+ ++numberOfTracks;
+ }
+ return numberOfTracks;
+}
+#endif
+
+TEST(CSSPropertyParserTest, GridTrackLimits)
+{
+#if ENABLE(CSS_GRID_LAYOUT)
+ struct {
+ const CSSPropertyID propertyID;
+ const char* input;
+ const size_t output;
+ } testCases[] = {
+ {CSSPropertyWebkitGridTemplateColumns, "-webkit-grid-template-columns: repeat(999999, 20px);", 999999},
+ {CSSPropertyWebkitGridTemplateRows, "-webkit-grid-template-rows: repeat(999999, 20px);", 999999},
+ {CSSPropertyWebkitGridTemplateColumns, "-webkit-grid-template-columns: repeat(1000000, 10%);", 1000000},
+ {CSSPropertyWebkitGridTemplateRows, "-webkit-grid-template-rows: repeat(1000000, 10%);", 1000000},
+ {CSSPropertyWebkitGridTemplateColumns, "-webkit-grid-template-columns: repeat(1000000, [first] -webkit-min-content [last]);", 1000000},
+ {CSSPropertyWebkitGridTemplateRows, "-webkit-grid-template-rows: repeat(1000000, [first] -webkit-min-content [last]);", 1000000},
+ {CSSPropertyWebkitGridTemplateColumns, "-webkit-grid-template-columns: repeat(1000001, auto);", 1000000},
+ {CSSPropertyWebkitGridTemplateRows, "-webkit-grid-template-rows: repeat(1000001, auto);", 1000000},
+ {CSSPropertyWebkitGridTemplateColumns, "-webkit-grid-template-columns: repeat(400000, 2em minmax(10px, -webkit-max-content) 0.5fr);", 999999},
+ {CSSPropertyWebkitGridTemplateRows, "-webkit-grid-template-rows: repeat(400000, 2em minmax(10px, -webkit-max-content) 0.5fr);", 999999},
+ {CSSPropertyWebkitGridTemplateColumns, "-webkit-grid-template-columns: repeat(600000, [first] 3vh 10% 2fr [nav] 10px auto 1fr 6em [last]);", 999999},
+ {CSSPropertyWebkitGridTemplateRows, "-webkit-grid-template-rows: repeat(600000, [first] 3vh 10% 2fr [nav] 10px auto 1fr 6em [last]);", 999999},
+ {CSSPropertyWebkitGridTemplateColumns, "-webkit-grid-template-columns: repeat(100000000000000000000, 10% 1fr);", 1000000},
+ {CSSPropertyWebkitGridTemplateRows, "-webkit-grid-template-rows: repeat(100000000000000000000, 10% 1fr);", 1000000},
+ {CSSPropertyWebkitGridTemplateColumns, "-webkit-grid-template-columns: repeat(100000000000000000000, 10% 5em 1fr auto auto 15px -webkit-min-content);", 999999},
+ {CSSPropertyWebkitGridTemplateRows, "-webkit-grid-template-rows: repeat(100000000000000000000, 10% 5em 1fr auto auto 15px -webkit-min-content);", 999999},
+ };
+
+ CSSParser parser(strictCSSParserContext());
+ RefPtr<MutableStyleProperties> properties = MutableStyleProperties::create();
+
+ for (auto& testCase : testCases) {
+ ASSERT_TRUE(parser.parseDeclaration(properties.get(), testCase.input, nullptr, nullptr));
+ RefPtr<CSSValue> value = properties->getPropertyCSSValue(testCase.propertyID);
+
+ ASSERT_TRUE(value->isValueList());
+ EXPECT_EQ(computeNumberOfTracks(*downcast<CSSValueList>(value.get())), testCase.output);
+ }
+#endif // ENABLE(CSS_GRID_LAYOUT)
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/CalculationValue.cpp b/Tools/TestWebKitAPI/Tests/WebCore/CalculationValue.cpp
new file mode 100644
index 000000000..286f30fd0
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/CalculationValue.cpp
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <WebCore/CalculationValue.h>
+
+namespace TestWebKitAPI {
+
+static unsigned deletionCount;
+
+class CalculationDeletionTestNode : public WebCore::CalcExpressionNode {
+public:
+ virtual ~CalculationDeletionTestNode()
+ {
+ ++deletionCount;
+ }
+
+ virtual float evaluate(float) const override { return 0; }
+ bool operator==(const CalcExpressionNode&) const override { ASSERT_NOT_REACHED(); return false; }
+};
+
+static Ref<WebCore::CalculationValue> createTestValue()
+{
+ auto node = std::make_unique<CalculationDeletionTestNode>();
+ return WebCore::CalculationValue::create(WTFMove(node), WebCore::CalculationRangeAll);
+}
+
+TEST(CalculationValue, LengthConstruction)
+{
+ RefPtr<WebCore::CalculationValue> value = createTestValue();
+
+ EXPECT_EQ(1U, value->refCount());
+
+ {
+ WebCore::Length length(*value);
+ EXPECT_EQ(2U, value->refCount());
+ }
+
+ EXPECT_EQ(1U, value->refCount());
+
+ {
+ WebCore::Length lengthA(*value);
+ EXPECT_EQ(2U, value->refCount());
+ WebCore::Length lengthB(lengthA);
+ EXPECT_EQ(2U, value->refCount());
+ }
+
+ EXPECT_EQ(1U, value->refCount());
+
+ {
+ WebCore::Length lengthC(*value);
+ EXPECT_EQ(2U, value->refCount());
+ WebCore::Length lengthD(WTFMove(lengthC));
+ EXPECT_EQ(2U, value->refCount());
+ }
+
+ EXPECT_EQ(1U, value->refCount());
+
+ EXPECT_EQ(0U, deletionCount);
+ value = nullptr;
+ EXPECT_EQ(1U, deletionCount);
+ deletionCount = 0;
+}
+
+TEST(CalculationValue, LengthConstructionReleasedValue)
+{
+ RefPtr<WebCore::CalculationValue> value = createTestValue();
+
+ EXPECT_EQ(1U, value->refCount());
+
+ {
+ auto* rawValue = value.get();
+ WebCore::Length length(value.releaseNonNull());
+ EXPECT_EQ(1U, rawValue->refCount());
+
+ EXPECT_EQ(0U, deletionCount);
+ }
+
+ EXPECT_EQ(1U, deletionCount);
+ deletionCount = 0;
+
+ value = createTestValue();
+
+ {
+ auto* rawValue = value.get();
+ WebCore::Length lengthA(value.releaseNonNull());
+ EXPECT_EQ(1U, rawValue->refCount());
+ WebCore::Length lengthB(lengthA);
+ EXPECT_EQ(1U, rawValue->refCount());
+
+ EXPECT_EQ(0U, deletionCount);
+ }
+
+ EXPECT_EQ(1U, deletionCount);
+ deletionCount = 0;
+
+ value = createTestValue();
+
+ {
+ auto* rawValue = value.get();
+ WebCore::Length lengthC(value.releaseNonNull());
+ EXPECT_EQ(1U, rawValue->refCount());
+ WebCore::Length lengthD(WTFMove(lengthC));
+ EXPECT_EQ(1U, rawValue->refCount());
+
+ EXPECT_EQ(0U, deletionCount);
+ }
+
+ EXPECT_EQ(1U, deletionCount);
+ deletionCount = 0;
+}
+
+TEST(CalculationValue, LengthAssignment)
+{
+ RefPtr<WebCore::CalculationValue> value = createTestValue();
+
+ EXPECT_EQ(1U, value->refCount());
+
+ {
+ WebCore::Length lengthA(*value);
+ EXPECT_EQ(2U, value->refCount());
+ WebCore::Length lengthB;
+ lengthB = lengthA;
+ EXPECT_EQ(2U, value->refCount());
+ }
+
+ EXPECT_EQ(1U, value->refCount());
+
+ {
+ WebCore::Length lengthC(*value);
+ EXPECT_EQ(2U, value->refCount());
+ WebCore::Length lengthD;
+ lengthD = WTFMove(lengthC);
+ EXPECT_EQ(2U, value->refCount());
+ }
+
+ EXPECT_EQ(1U, value->refCount());
+
+ EXPECT_EQ(0U, deletionCount);
+ value = nullptr;
+ EXPECT_EQ(1U, deletionCount);
+ deletionCount = 0;
+
+ value = createTestValue();
+ RefPtr<WebCore::CalculationValue> value2 = createTestValue();
+
+ EXPECT_EQ(1U, value->refCount());
+ EXPECT_EQ(1U, value2->refCount());
+
+ {
+ WebCore::Length lengthE(*value);
+ EXPECT_EQ(2U, value->refCount());
+ WebCore::Length lengthF(*value2);
+ EXPECT_EQ(2U, value2->refCount());
+ lengthE = lengthF;
+ EXPECT_EQ(1U, value->refCount());
+ EXPECT_EQ(2U, value2->refCount());
+ }
+
+ EXPECT_EQ(1U, value->refCount());
+ EXPECT_EQ(1U, value2->refCount());
+
+ {
+ WebCore::Length lengthG(*value);
+ EXPECT_EQ(2U, value->refCount());
+ WebCore::Length lengthH(*value2);
+ EXPECT_EQ(2U, value2->refCount());
+ lengthG = WTFMove(lengthH);
+ EXPECT_EQ(1U, value->refCount());
+ EXPECT_EQ(2U, value2->refCount());
+ }
+
+ EXPECT_EQ(0U, deletionCount);
+ value = nullptr;
+ EXPECT_EQ(1U, deletionCount);
+ value2 = nullptr;
+ EXPECT_EQ(2U, deletionCount);
+ deletionCount = 0;
+}
+
+TEST(CalculationValue, LengthAssignmentReleasedValue)
+{
+ RefPtr<WebCore::CalculationValue> value = createTestValue();
+
+ {
+ auto* rawValue = value.get();
+ WebCore::Length lengthA(value.releaseNonNull());
+ EXPECT_EQ(1U, rawValue->refCount());
+ WebCore::Length lengthB;
+ lengthB = lengthA;
+ EXPECT_EQ(1U, rawValue->refCount());
+
+ EXPECT_EQ(0U, deletionCount);
+ }
+
+ EXPECT_EQ(1U, deletionCount);
+ deletionCount = 0;
+
+ value = createTestValue();
+
+ {
+ auto* rawValue = value.get();
+ WebCore::Length lengthC(value.releaseNonNull());
+ EXPECT_EQ(1U, rawValue->refCount());
+ WebCore::Length lengthD;
+ lengthD = WTFMove(lengthC);
+ EXPECT_EQ(1U, rawValue->refCount());
+
+ EXPECT_EQ(0U, deletionCount);
+ }
+
+ EXPECT_EQ(1U, deletionCount);
+ deletionCount = 0;
+
+ value = createTestValue();
+ RefPtr<WebCore::CalculationValue> value2 = createTestValue();
+
+ EXPECT_EQ(1U, value->refCount());
+ EXPECT_EQ(1U, value2->refCount());
+
+ {
+ auto* rawValue = value.get();
+ WebCore::Length lengthE(value.releaseNonNull());
+ EXPECT_EQ(1U, rawValue->refCount());
+ auto* rawValue2 = value2.get();
+ WebCore::Length lengthF(value2.releaseNonNull());
+ EXPECT_EQ(1U, rawValue2->refCount());
+
+ lengthE = lengthF;
+ EXPECT_EQ(1U, deletionCount);
+ EXPECT_EQ(1U, rawValue2->refCount());
+ }
+
+ EXPECT_EQ(2U, deletionCount);
+ deletionCount = 0;
+
+ value = createTestValue();
+ value2 = createTestValue();
+
+ EXPECT_EQ(1U, value->refCount());
+ EXPECT_EQ(1U, value2->refCount());
+
+ {
+ auto* rawValue = value.get();
+ WebCore::Length lengthG(value.releaseNonNull());
+ EXPECT_EQ(1U, rawValue->refCount());
+ auto* rawValue2 = value2.get();
+ WebCore::Length lengthH(value2.releaseNonNull());
+ EXPECT_EQ(1U, rawValue2->refCount());
+
+ lengthG = WTFMove(lengthH);
+ EXPECT_EQ(1U, deletionCount);
+ EXPECT_EQ(1U, rawValue2->refCount());
+ }
+
+ EXPECT_EQ(2U, deletionCount);
+ deletionCount = 0;
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp b/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp
new file mode 100644
index 000000000..d3c10afc7
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp
@@ -0,0 +1,2795 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "config.h"
+
+#include "PlatformUtilities.h"
+#include <JavaScriptCore/InitializeThreading.h>
+#include <WebCore/CombinedURLFilters.h>
+#include <WebCore/ContentExtensionCompiler.h>
+#include <WebCore/ContentExtensionError.h>
+#include <WebCore/ContentExtensionsBackend.h>
+#include <WebCore/DFA.h>
+#include <WebCore/DFABytecodeCompiler.h>
+#include <WebCore/DFABytecodeInterpreter.h>
+#include <WebCore/NFA.h>
+#include <WebCore/NFAToDFA.h>
+#include <WebCore/ResourceLoadInfo.h>
+#include <WebCore/URL.h>
+#include <WebCore/URLFilterParser.h>
+#include <wtf/MainThread.h>
+#include <wtf/RunLoop.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+namespace ContentExtensions {
+inline std::ostream& operator<<(std::ostream& os, const ActionType& action)
+{
+ switch (action) {
+ case ActionType::BlockLoad:
+ return os << "ActionType::BlockLoad";
+ case ActionType::BlockCookies:
+ return os << "ActionType::BlockCookies";
+ case ActionType::CSSDisplayNoneSelector:
+ return os << "ActionType::CSSDisplayNone";
+ case ActionType::CSSDisplayNoneStyleSheet:
+ return os << "ActionType::CSSDisplayNoneStyleSheet";
+ case ActionType::IgnorePreviousRules:
+ return os << "ActionType::IgnorePreviousRules";
+ case ActionType::MakeHTTPS:
+ return os << "ActionType::MakeHTTPS";
+ case ActionType::InvalidAction:
+ return os << "ActionType::InvalidAction";
+ }
+}
+}
+}
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+class ContentExtensionTest : public testing::Test {
+public:
+ virtual void SetUp()
+ {
+ WTF::initializeMainThread();
+ JSC::initializeThreading();
+ RunLoop::initializeMainRunLoop();
+ }
+};
+
+struct CompiledContentExtensionData {
+ Vector<ContentExtensions::SerializedActionByte> actions;
+ Vector<ContentExtensions::DFABytecode> filtersWithoutDomains;
+ Vector<ContentExtensions::DFABytecode> filtersWithDomains;
+ Vector<ContentExtensions::DFABytecode> domainFilters;
+};
+
+class InMemoryContentExtensionCompilationClient final : public ContentExtensions::ContentExtensionCompilationClient {
+public:
+ InMemoryContentExtensionCompilationClient(CompiledContentExtensionData& data)
+ : m_data(data)
+ {
+ EXPECT_EQ(data.actions.size(), 0ull);
+ EXPECT_EQ(data.filtersWithoutDomains.size(), 0ull);
+ EXPECT_EQ(data.filtersWithDomains.size(), 0ull);
+ EXPECT_EQ(data.domainFilters.size(), 0ull);
+ }
+
+ virtual void writeActions(Vector<ContentExtensions::SerializedActionByte>&& actions) override
+ {
+ EXPECT_FALSE(finalized);
+ EXPECT_EQ(m_data.actions.size(), 0ull);
+ EXPECT_EQ(m_data.filtersWithoutDomains.size(), 0ull);
+ EXPECT_EQ(m_data.filtersWithDomains.size(), 0ull);
+ EXPECT_EQ(m_data.domainFilters.size(), 0ull);
+ m_data.actions.appendVector(actions);
+ }
+
+ virtual void writeFiltersWithoutDomainsBytecode(Vector<ContentExtensions::DFABytecode>&& bytecode) override
+ {
+ EXPECT_FALSE(finalized);
+ EXPECT_EQ(m_data.filtersWithDomains.size(), 0ull);
+ EXPECT_EQ(m_data.domainFilters.size(), 0ull);
+ m_data.filtersWithoutDomains.appendVector(bytecode);
+ }
+
+ virtual void writeFiltersWithDomainsBytecode(Vector<ContentExtensions::DFABytecode>&& bytecode) override
+ {
+ EXPECT_FALSE(finalized);
+ EXPECT_EQ(m_data.domainFilters.size(), 0ull);
+ m_data.filtersWithDomains.appendVector(bytecode);
+ }
+
+ virtual void writeDomainFiltersBytecode(Vector<ContentExtensions::DFABytecode>&& bytecode) override
+ {
+ EXPECT_FALSE(finalized);
+ m_data.domainFilters.appendVector(bytecode);
+ }
+
+ virtual void finalize() override
+ {
+ finalized = true;
+ }
+
+private:
+ CompiledContentExtensionData& m_data;
+ bool finalized { false };
+};
+
+class InMemoryCompiledContentExtension : public ContentExtensions::CompiledContentExtension {
+public:
+ static RefPtr<InMemoryCompiledContentExtension> createFromFilter(String&& filter)
+ {
+ CompiledContentExtensionData extensionData;
+ InMemoryContentExtensionCompilationClient client(extensionData);
+ auto compilerError = ContentExtensions::compileRuleList(client, WTFMove(filter));
+ if (compilerError) {
+ // Compiling should always succeed here. We have other tests for compile failures.
+ EXPECT_TRUE(false);
+ return nullptr;
+ }
+
+ return InMemoryCompiledContentExtension::create(WTFMove(extensionData));
+ }
+
+ static RefPtr<InMemoryCompiledContentExtension> create(CompiledContentExtensionData&& data)
+ {
+ return adoptRef(new InMemoryCompiledContentExtension(WTFMove(data)));
+ }
+
+ virtual ~InMemoryCompiledContentExtension()
+ {
+ }
+
+ virtual const ContentExtensions::SerializedActionByte* actions() const override { return m_data.actions.data(); }
+ virtual unsigned actionsLength() const override { return m_data.actions.size(); }
+ virtual const ContentExtensions::DFABytecode* filtersWithoutDomainsBytecode() const override { return m_data.filtersWithoutDomains.data(); }
+ virtual unsigned filtersWithoutDomainsBytecodeLength() const override { return m_data.filtersWithoutDomains.size(); }
+ virtual const ContentExtensions::DFABytecode* filtersWithDomainsBytecode() const override { return m_data.filtersWithDomains.data(); }
+ virtual unsigned filtersWithDomainsBytecodeLength() const override { return m_data.filtersWithDomains.size(); }
+ virtual const ContentExtensions::DFABytecode* domainFiltersBytecode() const override { return m_data.domainFilters.data(); }
+ virtual unsigned domainFiltersBytecodeLength() const override { return m_data.domainFilters.size(); }
+
+private:
+ InMemoryCompiledContentExtension(CompiledContentExtensionData&& data)
+ : m_data(WTFMove(data))
+ {
+ }
+
+ CompiledContentExtensionData m_data;
+};
+
+void static testRequest(ContentExtensions::ContentExtensionsBackend contentExtensionsBackend, const ResourceLoadInfo& resourceLoadInfo, Vector<ContentExtensions::ActionType> expectedActions, bool ignorePreviousRules = false)
+{
+ auto actions = contentExtensionsBackend.actionsForResourceLoad(resourceLoadInfo);
+ unsigned expectedSize = actions.size();
+ if (!ignorePreviousRules)
+ expectedSize--; // The last action is applying the compiled stylesheet.
+
+ EXPECT_EQ(expectedActions.size(), expectedSize);
+ if (expectedActions.size() != expectedSize)
+ return;
+
+ for (unsigned i = 0; i < expectedActions.size(); ++i)
+ EXPECT_EQ(expectedActions[i], actions[i].type());
+ if (!ignorePreviousRules)
+ EXPECT_EQ(actions[actions.size() - 1].type(), ContentExtensions::ActionType::CSSDisplayNoneStyleSheet);
+}
+
+static ResourceLoadInfo mainDocumentRequest(const char* url, ResourceType resourceType = ResourceType::Document)
+{
+ return { URL(URL(), url), URL(URL(), url), resourceType };
+}
+
+static ResourceLoadInfo subResourceRequest(const char* url, const char* mainDocumentURL, ResourceType resourceType = ResourceType::Document)
+{
+ return { URL(URL(), url), URL(URL(), mainDocumentURL), resourceType };
+}
+
+ContentExtensions::ContentExtensionsBackend makeBackend(const char* json)
+{
+ auto extension = InMemoryCompiledContentExtension::createFromFilter(json);
+ ContentExtensions::ContentExtensionsBackend backend;
+ backend.addContentExtension("testFilter", extension);
+ return backend;
+}
+
+static Vector<ContentExtensions::NFA> createNFAs(ContentExtensions::CombinedURLFilters& combinedURLFilters)
+{
+ Vector<ContentExtensions::NFA> nfas;
+
+ combinedURLFilters.processNFAs(std::numeric_limits<size_t>::max(), [&](ContentExtensions::NFA&& nfa) {
+ nfas.append(WTFMove(nfa));
+ });
+
+ return nfas;
+}
+
+TEST_F(ContentExtensionTest, Basic)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+}
+
+TEST_F(ContentExtensionTest, SingleCharacter)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^z\"}}]");
+ testRequest(matchBackend, mainDocumentRequest("http://webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("zttp://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"y\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("http://webkit.org/"), { });
+ testRequest(searchBackend, mainDocumentRequest("http://webkit.org/ywebkit"), { ContentExtensions::ActionType::BlockLoad });
+}
+
+TEST_F(ContentExtensionTest, SingleCharacterDisjunction)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^z\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^c\"}}]");
+ testRequest(matchBackend, mainDocumentRequest("http://webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("bttp://webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("cttp://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("dttp://webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("zttp://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"x\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"y\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("http://webkit.org/"), { });
+ testRequest(searchBackend, mainDocumentRequest("http://webkit.org/dwebkit"), { });
+ testRequest(searchBackend, mainDocumentRequest("http://webkit.org/xwebkit"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("http://webkit.org/ywebkit"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("http://webkit.org/zwebkit"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeBasic)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"w[0-9]c\", \"url-filter-is-case-sensitive\":true}},"
+ "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"[A-H][a-z]cko\", \"url-filter-is-case-sensitive\":true}}]");
+
+ testRequest(backend, mainDocumentRequest("http://w3c.org"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("w2c://whatwg.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/w0c"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/wac"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/wAc"), { });
+
+ // Note: URL parsing and canonicalization lowercase the scheme and hostname.
+ testRequest(backend, mainDocumentRequest("Aacko://webkit.org"), { });
+ testRequest(backend, mainDocumentRequest("aacko://webkit.org"), { });
+ testRequest(backend, mainDocumentRequest("http://gCcko.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://gccko.org/"), { });
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/Gecko"), { ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/gecko"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/GEcko"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeExclusionGeneratingUniversalTransition)
+{
+ // Transition of the type ([^X]X) effictively transition on every input.
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[^a]+afoobar\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://w3c.org"), { });
+
+ testRequest(backend, mainDocumentRequest("http://w3c.org/foobafoobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://w3c.org/foobarfoobar"), { });
+ testRequest(backend, mainDocumentRequest("http://w3c.org/FOOBAFOOBAR"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://w3c.org/FOOBARFOOBAR"), { });
+
+ // The character before the "a" prefix cannot be another "a".
+ testRequest(backend, mainDocumentRequest("http://w3c.org/aafoobar"), { });
+ testRequest(backend, mainDocumentRequest("http://w3c.org/Aafoobar"), { });
+ testRequest(backend, mainDocumentRequest("http://w3c.org/aAfoobar"), { });
+ testRequest(backend, mainDocumentRequest("http://w3c.org/AAfoobar"), { });
+}
+
+TEST_F(ContentExtensionTest, PatternStartingWithGroup)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(http://whatwg\\\\.org/)?webkit\134\134.org\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://whatwg.org/webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://whatwg.org/webkit.org"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://whatwg.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://whatwg.org"), { });
+}
+
+TEST_F(ContentExtensionTest, PatternNestedGroups)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://webkit\\\\.org/(foo(bar)*)+\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foo"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobarbar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foofoobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobarfoobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foob"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foor"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/bar"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/fobar"), { });
+}
+
+TEST_F(ContentExtensionTest, EmptyGroups)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://webkit\\\\.org/foo()bar\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://webkit\\\\.org/((me)()(too))\"}}]");
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foo"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/bar"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/me"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/too"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/metoo"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foome"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foomebar"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/mefoo"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/mefootoo"), { });
+}
+
+TEST_F(ContentExtensionTest, QuantifiedEmptyGroups)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://webkit\\\\.org/foo()+bar\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://webkit\\\\.org/(()*()?(target)()+)\"}}]");
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foo"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/bar"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/me"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/too"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/target"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foome"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foomebar"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/mefoo"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/mefootoo"), { });
+}
+
+TEST_F(ContentExtensionTest, MatchPastEndOfString)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".+\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foo"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobarbar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foofoobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobarfoobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foob"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foor"), { ContentExtensions::ActionType::BlockLoad });
+}
+
+TEST_F(ContentExtensionTest, StartOfLineAssertion)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^foobar\"}}]");
+
+ testRequest(backend, mainDocumentRequest("foobar://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("foobars:///foobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("foobarfoobar:///foobarfoobarfoobar"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobarfoo"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobarf"), { });
+ testRequest(backend, mainDocumentRequest("http://foobar.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://foobar.org/"), { });
+}
+
+TEST_F(ContentExtensionTest, EndOfLineAssertion)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"foobar$\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("file:///foobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("file:///foobarfoobarfoobar"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobarfoo"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobarf"), { });
+}
+
+TEST_F(ContentExtensionTest, EndOfLineAssertionWithInvertedCharacterSet)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[^y]$\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/a"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/Ya"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/yFoobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/y"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/Y"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobary"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobarY"), { });
+}
+
+TEST_F(ContentExtensionTest, DotDoesNotIncludeEndOfLine)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"https://webkit\\\\.org/.\"}}]");
+
+ testRequest(backend, mainDocumentRequest("https://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/A"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/z"), { ContentExtensions::ActionType::BlockLoad });
+}
+
+TEST_F(ContentExtensionTest, PrefixInfixSuffixExactMatch)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"infix\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^prefix\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"suffix$\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://exact\\\\.org/$\"}}]");
+
+ testRequest(backend, mainDocumentRequest("infix://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://infix.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/infix"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("prefix://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://prefix.org/"), { });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/prefix"), { });
+
+ testRequest(backend, mainDocumentRequest("https://webkit.org/suffix"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://suffix.org/"), { });
+ testRequest(backend, mainDocumentRequest("suffix://webkit.org/"), { });
+
+ testRequest(backend, mainDocumentRequest("http://exact.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://exact.org/oops"), { });
+}
+
+TEST_F(ContentExtensionTest, DuplicatedMatchAllTermsInVariousFormat)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*.*(.)*(.*)(.+)*(.?)*infix\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"pre(.?)+(.+)?post\"}}]");
+
+ testRequest(backend, mainDocumentRequest("infix://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://infix.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/infix"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("pre://webkit.org/post"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://prepost.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://pre.org/posttail"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://pre.pre/posttail"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://pre.org/posttailpost"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("https://post.org/pre"), { });
+ testRequest(backend, mainDocumentRequest("https://pre.org/pre"), { });
+ testRequest(backend, mainDocumentRequest("https://post.org/post"), { });
+}
+
+TEST_F(ContentExtensionTest, UndistinguishableActionInsidePrefixTree)
+{
+ // In this case, the two actions are undistinguishable. The actions of "prefix" appear inside the prefixtree
+ // ending at "suffix".
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"prefix\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"prefixsuffix\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://prefix.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/prefix"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/aaaprefixaaa"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://prefixsuffix.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/prefixsuffix"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/bbbprefixsuffixbbb"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("http://suffix.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/suffix"), { });
+}
+
+TEST_F(ContentExtensionTest, DistinguishableActionInsidePrefixTree)
+{
+ // In this case, the two actions are distinguishable.
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"prefix\"}},"
+ "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"prefixsuffix\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://prefix.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/prefix"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/aaaprefixaaa"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://prefixsuffix.org/"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/prefixsuffix"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/bbbprefixsuffixbbb"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("http://suffix.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/suffix"), { });
+}
+
+TEST_F(ContentExtensionTest, DistinguishablePrefixAreNotMerged)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"foo\\\\.org\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"bar\\\\.org\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://foo.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://bar.org/"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("http://foor.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://fooar.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://fooba.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://foob.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://foor.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://foar.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://foba.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://fob.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://barf.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://barfo.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://baroo.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://baro.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://baf.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://bafo.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://baoo.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://bao.org/"), { });
+
+ testRequest(backend, mainDocumentRequest("http://foo.orgbar.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://oo.orgbar.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://o.orgbar.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://.orgbar.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://rgbar.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://gbar.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://foo.orgar.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://foo.orgr.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://foo.org.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://foo.orgorg/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://foo.orgrg/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://foo.orgg/"), { ContentExtensions::ActionType::BlockLoad });
+}
+
+static void compareContents(const ContentExtensions::DFABytecodeInterpreter::Actions& a, const Vector<uint64_t>& b)
+{
+ EXPECT_EQ(a.size(), b.size());
+ for (unsigned i = 0; i < b.size(); ++i)
+ EXPECT_TRUE(a.contains(b[i]));
+}
+
+TEST_F(ContentExtensionTest, SearchSuffixesWithIdenticalActionAreMerged)
+{
+ ContentExtensions::CombinedURLFilters combinedURLFilters;
+ ContentExtensions::URLFilterParser parser(combinedURLFilters);
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("foo\\.org", false, 0));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("ba\\.org", false, 0));
+
+ Vector<ContentExtensions::NFA> nfas = createNFAs(combinedURLFilters);
+ EXPECT_EQ(1ul, nfas.size());
+ EXPECT_EQ(12ul, nfas.first().nodes.size());
+
+ ContentExtensions::DFA dfa = ContentExtensions::NFAToDFA::convert(nfas.first());
+ Vector<ContentExtensions::DFABytecode> bytecode;
+ ContentExtensions::DFABytecodeCompiler compiler(dfa, bytecode);
+ compiler.compile();
+ ContentExtensions::DFABytecodeInterpreter interpreter(bytecode.data(), bytecode.size());
+ compareContents(interpreter.interpret("foo.org", 0), { 0 });
+ compareContents(interpreter.interpret("ba.org", 0), { 0 });
+ compareContents(interpreter.interpret("bar.org", 0), { });
+
+ compareContents(interpreter.interpret("paddingfoo.org", 0), { 0 });
+ compareContents(interpreter.interpret("paddingba.org", 0), { 0 });
+ compareContents(interpreter.interpret("paddingbar.org", 0), { });
+}
+
+TEST_F(ContentExtensionTest, SearchSuffixesWithDistinguishableActionAreNotMerged)
+{
+ ContentExtensions::CombinedURLFilters combinedURLFilters;
+ ContentExtensions::URLFilterParser parser(combinedURLFilters);
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("foo\\.org", false, 0));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("ba\\.org", false, 1));
+
+ Vector<ContentExtensions::NFA> nfas = createNFAs(combinedURLFilters);
+
+ EXPECT_EQ(1ul, nfas.size());
+ EXPECT_EQ(17ul, nfas.first().nodes.size());
+
+ ContentExtensions::DFA dfa = ContentExtensions::NFAToDFA::convert(nfas.first());
+ Vector<ContentExtensions::DFABytecode> bytecode;
+ ContentExtensions::DFABytecodeCompiler compiler(dfa, bytecode);
+ compiler.compile();
+ ContentExtensions::DFABytecodeInterpreter interpreter(bytecode.data(), bytecode.size());
+ compareContents(interpreter.interpret("foo.org", 0), { 0 });
+ compareContents(interpreter.interpret("ba.org", 0), { 1 });
+ compareContents(interpreter.interpret("bar.org", 0), { });
+
+ compareContents(interpreter.interpret("paddingfoo.org", 0), { 0 });
+ compareContents(interpreter.interpret("paddingba.org", 0), { 1 });
+ compareContents(interpreter.interpret("paddingba.orgfoo.org", 0), { 1, 0 });
+ compareContents(interpreter.interpret("paddingbar.org", 0), { });
+}
+
+TEST_F(ContentExtensionTest, DomainTriggers)
+{
+ auto ifDomainBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"if-domain\":[\"webkit.org\"]}}]");
+ testRequest(ifDomainBackend, mainDocumentRequest("http://webkit.org/test.htm"), { });
+ testRequest(ifDomainBackend, mainDocumentRequest("http://bugs.webkit.org/test.htm"), { });
+ testRequest(ifDomainBackend, mainDocumentRequest("http://webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(ifDomainBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { });
+ testRequest(ifDomainBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { });
+ testRequest(ifDomainBackend, mainDocumentRequest("http://not_webkit.org/test.htm"), { });
+ testRequest(ifDomainBackend, mainDocumentRequest("http://webkit.organization/test.htm"), { });
+ testRequest(ifDomainBackend, mainDocumentRequest("http://not_webkit.org/test.html"), { });
+ testRequest(ifDomainBackend, mainDocumentRequest("http://webkit.organization/test.html"), { });
+
+ auto unlessDomainBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"unless-domain\":[\"webkit.org\"]}}]");
+ testRequest(unlessDomainBackend, mainDocumentRequest("http://webkit.org/test.htm"), { });
+ testRequest(unlessDomainBackend, mainDocumentRequest("http://bugs.webkit.org/test.htm"), { });
+ testRequest(unlessDomainBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
+ testRequest(unlessDomainBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(unlessDomainBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(unlessDomainBackend, mainDocumentRequest("http://not_webkit.org/test.htm"), { });
+ testRequest(unlessDomainBackend, mainDocumentRequest("http://webkit.organization/test.htm"), { });
+ testRequest(unlessDomainBackend, mainDocumentRequest("http://not_webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(unlessDomainBackend, mainDocumentRequest("http://webkit.organization/test.html"), { ContentExtensions::ActionType::BlockLoad });
+
+ auto ifDomainStarBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"if-domain\":[\"*webkit.org\"]}}]");
+ testRequest(ifDomainStarBackend, mainDocumentRequest("http://webkit.org/test.htm"), { });
+ testRequest(ifDomainStarBackend, mainDocumentRequest("http://bugs.webkit.org/test.htm"), { });
+ testRequest(ifDomainStarBackend, mainDocumentRequest("http://webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(ifDomainStarBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(ifDomainStarBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(ifDomainStarBackend, mainDocumentRequest("http://not_webkit.org/test.htm"), { });
+ testRequest(ifDomainStarBackend, mainDocumentRequest("http://webkit.organization/test.htm"), { });
+ testRequest(ifDomainStarBackend, mainDocumentRequest("http://not_webkit.org/test.html"), { });
+ testRequest(ifDomainStarBackend, mainDocumentRequest("http://webkit.organization/test.html"), { });
+
+ auto unlessDomainStarBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"unless-domain\":[\"*webkit.org\"]}}]");
+ testRequest(unlessDomainStarBackend, mainDocumentRequest("http://webkit.org/test.htm"), { });
+ testRequest(unlessDomainStarBackend, mainDocumentRequest("http://bugs.webkit.org/test.htm"), { });
+ testRequest(unlessDomainStarBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
+ testRequest(unlessDomainStarBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { });
+ testRequest(unlessDomainStarBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { });
+ testRequest(unlessDomainStarBackend, mainDocumentRequest("http://not_webkit.org/test.htm"), { });
+ testRequest(unlessDomainStarBackend, mainDocumentRequest("http://webkit.organization/test.htm"), { });
+ testRequest(unlessDomainStarBackend, mainDocumentRequest("http://not_webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(unlessDomainStarBackend, mainDocumentRequest("http://webkit.organization/test.html"), { ContentExtensions::ActionType::BlockLoad });
+
+ auto ifSubDomainBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"if-domain\":[\"sub1.webkit.org\"]}}]");
+ testRequest(ifSubDomainBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
+ testRequest(ifSubDomainBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { });
+ testRequest(ifSubDomainBackend, mainDocumentRequest("http://sub1.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(ifSubDomainBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { });
+
+ auto ifSubDomainStarBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"if-domain\":[\"*sub1.webkit.org\"]}}]");
+ testRequest(ifSubDomainStarBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
+ testRequest(ifSubDomainStarBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { });
+ testRequest(ifSubDomainStarBackend, mainDocumentRequest("http://sub1.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(ifSubDomainStarBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+
+ auto unlessSubDomainBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"unless-domain\":[\"sub1.webkit.org\"]}}]");
+ testRequest(unlessSubDomainBackend, mainDocumentRequest("http://webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(unlessSubDomainBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(unlessSubDomainBackend, mainDocumentRequest("http://sub1.webkit.org/test.html"), { });
+ testRequest(unlessSubDomainBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+
+ auto unlessSubDomainStarBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"unless-domain\":[\"*sub1.webkit.org\"]}}]");
+ testRequest(unlessSubDomainStarBackend, mainDocumentRequest("http://webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(unlessSubDomainStarBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(unlessSubDomainStarBackend, mainDocumentRequest("http://sub1.webkit.org/test.html"), { });
+ testRequest(unlessSubDomainStarBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { });
+
+ auto combinedBackend1 = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test_block_load\", \"if-domain\":[\"webkit.org\"]}},"
+ "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"test_block_cookies\", \"unless-domain\":[\"webkit.org\"]}}]");
+ testRequest(combinedBackend1, mainDocumentRequest("http://webkit.org"), { });
+ testRequest(combinedBackend1, mainDocumentRequest("http://not_webkit.org"), { });
+ testRequest(combinedBackend1, mainDocumentRequest("http://webkit.org/test_block_load.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/test_block_load.html", "http://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/shouldnt_match.html", "http://webkit.org/"), { });
+ testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/test_block_load.html", "http://not_webkit.org/"), { });
+ testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/shouldnt_match.html", "http://not_webkit.org/"), { });
+ testRequest(combinedBackend1, mainDocumentRequest("http://webkit.org/test_block_cookies.html"), { });
+ testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/test_block_cookies.html", "http://webkit.org/"), { });
+ testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/shouldnt_match.html", "http://webkit.org/"), { });
+ testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/test_block_cookies.html", "http://not_webkit.org/path/to/main/document.html"), { ContentExtensions::ActionType::BlockCookies });
+ testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/shouldnt_match.html", "http://not_webkit.org/"), { });
+
+ auto combinedBackend2 = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test_block_load\\\\.html\", \"if-domain\":[\"webkit.org\"]}},"
+ "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"test_block_cookies\\\\.html\", \"unless-domain\":[\"w3c.org\"]}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"test_css\\\\.html\"}}]");
+ testRequest(combinedBackend2, mainDocumentRequest("http://webkit.org/test_css.html"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(combinedBackend2, mainDocumentRequest("http://webkit.org/test_css.htm"), { });
+ testRequest(combinedBackend2, mainDocumentRequest("http://webkit.org/test_block_load.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(combinedBackend2, mainDocumentRequest("http://not_webkit.org/test_block_load.html"), { });
+ testRequest(combinedBackend2, mainDocumentRequest("http://not_webkit.org/test_css.html"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(combinedBackend2, mainDocumentRequest("http://webkit.org/TEST_CSS.hTmL/test_block_load.html"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad});
+ testRequest(combinedBackend2, mainDocumentRequest("http://w3c.org/test_css.html"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(combinedBackend2, mainDocumentRequest("http://w3c.org/test_block_load.html"), { });
+ testRequest(combinedBackend2, mainDocumentRequest("http://w3c.org/test_block_cookies.html"), { });
+ testRequest(combinedBackend2, mainDocumentRequest("http://w3c.org/test_css.html/test_block_cookies.html"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(combinedBackend2, mainDocumentRequest("http://not_w3c.org/test_block_cookies.html"), { ContentExtensions::ActionType::BlockCookies });
+ testRequest(combinedBackend2, mainDocumentRequest("http://not_w3c.org/test_css.html/test_block_cookies.html"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockCookies });
+
+ auto ifDomainWithFlagsBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\", \"if-domain\":[\"webkit.org\"],\"resource-type\":[\"image\"]}}]");
+ testRequest(ifDomainWithFlagsBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
+ testRequest(ifDomainWithFlagsBackend, mainDocumentRequest("http://webkit.org/test.png", ResourceType::Image), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(ifDomainWithFlagsBackend, mainDocumentRequest("http://not_webkit.org/test.html"), { });
+ testRequest(ifDomainWithFlagsBackend, mainDocumentRequest("http://not_webkit.org/test.png", ResourceType::Image), { });
+
+ auto unlessDomainWithFlagsBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\", \"unless-domain\":[\"webkit.org\"],\"resource-type\":[\"image\"]}}]");
+ testRequest(unlessDomainWithFlagsBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
+ testRequest(unlessDomainWithFlagsBackend, mainDocumentRequest("http://webkit.org/test.png", ResourceType::Image), { });
+ testRequest(unlessDomainWithFlagsBackend, mainDocumentRequest("http://not_webkit.org/test.html"), { });
+ testRequest(unlessDomainWithFlagsBackend, mainDocumentRequest("http://not_webkit.org/test.png", ResourceType::Image), { ContentExtensions::ActionType::BlockLoad });
+
+ // Domains should not be interepted as regular expressions.
+ auto domainRegexBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"if-domain\":[\"we?bkit.org\"]}}]");
+ testRequest(domainRegexBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
+ testRequest(domainRegexBackend, mainDocumentRequest("http://wbkit.org/test.html"), { });
+
+ auto multipleIfDomainsBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"if-domain\":[\"webkit.org\", \"w3c.org\"]}}]");
+ testRequest(multipleIfDomainsBackend, mainDocumentRequest("http://webkit.org/test.htm"), { });
+ testRequest(multipleIfDomainsBackend, mainDocumentRequest("http://webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(multipleIfDomainsBackend, mainDocumentRequest("http://w3c.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(multipleIfDomainsBackend, mainDocumentRequest("http://whatwg.org/test.html"), { });
+
+ auto multipleUnlessDomainsBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"unless-domain\":[\"webkit.org\", \"w3c.org\"]}}]");
+ testRequest(multipleUnlessDomainsBackend, mainDocumentRequest("http://webkit.org/test.htm"), { });
+ testRequest(multipleUnlessDomainsBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
+ testRequest(multipleUnlessDomainsBackend, mainDocumentRequest("http://w3c.org/test.html"), { });
+ testRequest(multipleUnlessDomainsBackend, mainDocumentRequest("http://whatwg.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+
+ // FIXME: Add and test domain-specific popup-only blocking (with layout tests).
+}
+
+TEST_F(ContentExtensionTest, DomainTriggersAlongMergedActions)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"test\\\\.html\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"if-domain\":[\"webkit.org\"]}},"
+ "{\"action\":{\"type\":\"css-display-none\", \"selector\": \"*\"},\"trigger\":{\"url-filter\":\"trigger-on-scripts\\\\.html\",\"resource-type\":[\"script\"]}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"ignore-previous\",\"resource-type\":[\"image\"]}},"
+ "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"except-this\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/test.htm"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad, ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/test.html"), { ContentExtensions::ActionType::BlockCookies });
+
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/trigger-on-scripts.html"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/trigger-on-scripts.html"), { });
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/trigger-on-scripts.html", ResourceType::Script), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/trigger-on-scripts.html", ResourceType::Script), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/trigger-on-scripts.html.test.html", ResourceType::Script), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/trigger-on-scripts.html.test.html", ResourceType::Script), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad, ContentExtensions::ActionType::BlockCookies });
+
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/ignore-previous-trigger-on-scripts.html"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/ignore-previous-trigger-on-scripts.html"), { });
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/ignore-previous-trigger-on-scripts.html", ResourceType::Script), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/ignore-previous-trigger-on-scripts.html", ResourceType::Script), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/ignore-previous-trigger-on-scripts.html.test.html", ResourceType::Script), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/ignore-previous-trigger-on-scripts.html.test.html", ResourceType::Script), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad, ContentExtensions::ActionType::BlockCookies });
+
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/ignore-previous-trigger-on-scripts.html", ResourceType::Image), { }, true);
+ testRequest(backend, mainDocumentRequest("http://webkit.org/ignore-previous-trigger-on-scripts.html", ResourceType::Image), { }, true);
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/ignore-previous-trigger-on-scripts.html.test.html", ResourceType::Image), { }, true);
+ testRequest(backend, mainDocumentRequest("http://webkit.org/ignore-previous-trigger-on-scripts.html.test.html", ResourceType::Image), { }, true);
+
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/except-this-ignore-previous-trigger-on-scripts.html"), { ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/except-this-ignore-previous-trigger-on-scripts.html"), { ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/except-this-ignore-previous-trigger-on-scripts.html.test.html"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/except-this-ignore-previous-trigger-on-scripts.html.test.html"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::BlockLoad, ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/except-this-ignore-previous-trigger-on-scripts.html", ResourceType::Image), { ContentExtensions::ActionType::BlockCookies }, true);
+ testRequest(backend, mainDocumentRequest("http://webkit.org/except-this-ignore-previous-trigger-on-scripts.html", ResourceType::Image), { ContentExtensions::ActionType::BlockCookies }, true);
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/except-this-ignore-previous-trigger-on-scripts.html.test.html", ResourceType::Image), { ContentExtensions::ActionType::BlockCookies }, true);
+ testRequest(backend, mainDocumentRequest("http://webkit.org/except-this-ignore-previous-trigger-on-scripts.html.test.html", ResourceType::Image), { ContentExtensions::ActionType::BlockCookies }, true);
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/except-this-ignore-previous-trigger-on-scripts.html", ResourceType::Script), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/except-this-ignore-previous-trigger-on-scripts.html", ResourceType::Script), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/except-this-ignore-previous-trigger-on-scripts.html.test.html", ResourceType::Script), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/except-this-ignore-previous-trigger-on-scripts.html.test.html", ResourceType::Script), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad, ContentExtensions::ActionType::BlockCookies });
+
+}
+
+TEST_F(ContentExtensionTest, MultipleExtensions)
+{
+ auto extension1 = InMemoryCompiledContentExtension::createFromFilter("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"block_load\"}}]");
+ auto extension2 = InMemoryCompiledContentExtension::createFromFilter("[{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"block_cookies\"}}]");
+ ContentExtensions::ContentExtensionsBackend backend;
+ backend.addContentExtension("testFilter1", extension1);
+ backend.addContentExtension("testFilter2", extension2);
+
+ // These each have two display:none stylesheets. The second one is implied by using the default parameter ignorePreviousRules = false.
+ testRequest(backend, mainDocumentRequest("http://webkit.org"), { ContentExtensions::ActionType::CSSDisplayNoneStyleSheet });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/block_load.html"), { ContentExtensions::ActionType::CSSDisplayNoneStyleSheet, ContentExtensions::ActionType::BlockLoad});
+ testRequest(backend, mainDocumentRequest("http://webkit.org/block_cookies.html"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::CSSDisplayNoneStyleSheet});
+ testRequest(backend, mainDocumentRequest("http://webkit.org/block_load/block_cookies.html"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::CSSDisplayNoneStyleSheet, ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/block_cookies/block_load.html"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::CSSDisplayNoneStyleSheet, ContentExtensions::ActionType::BlockLoad });
+
+ auto ignoreExtension1 = InMemoryCompiledContentExtension::createFromFilter("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"block_load\"}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"ignore1\"}}]");
+ auto ignoreExtension2 = InMemoryCompiledContentExtension::createFromFilter("[{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"block_cookies\"}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"ignore2\"}}]");
+ ContentExtensions::ContentExtensionsBackend backendWithIgnore;
+ backendWithIgnore.addContentExtension("testFilter1", ignoreExtension1);
+ backendWithIgnore.addContentExtension("testFilter2", ignoreExtension2);
+
+ testRequest(backendWithIgnore, mainDocumentRequest("http://webkit.org"), { ContentExtensions::ActionType::CSSDisplayNoneStyleSheet, ContentExtensions::ActionType::CSSDisplayNoneStyleSheet }, true);
+ testRequest(backendWithIgnore, mainDocumentRequest("http://webkit.org/block_load/ignore1.html"), { ContentExtensions::ActionType::CSSDisplayNoneStyleSheet }, true);
+ testRequest(backendWithIgnore, mainDocumentRequest("http://webkit.org/block_cookies/ignore1.html"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::CSSDisplayNoneStyleSheet}, true);
+ testRequest(backendWithIgnore, mainDocumentRequest("http://webkit.org/block_load/ignore2.html"), { ContentExtensions::ActionType::BlockLoad, ContentExtensions::ActionType::CSSDisplayNoneStyleSheet }, true);
+ testRequest(backendWithIgnore, mainDocumentRequest("http://webkit.org/block_cookies/ignore2.html"), { ContentExtensions::ActionType::CSSDisplayNoneStyleSheet}, true);
+ testRequest(backendWithIgnore, mainDocumentRequest("http://webkit.org/block_load/block_cookies/ignore1/ignore2.html"), { }, true);
+}
+
+TEST_F(ContentExtensionTest, TermsKnownToMatchAnything)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre1.*post1$\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre2(.*)post2$\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre3(.*)?post3$\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre4(.*)+post4$\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre5(.*)*post5$\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre6(.)*post6$\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre7(.+)*post7$\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre8(.?)*post8$\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre9(.+)?post9$\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre0(.?)+post0$\"}}]");
+
+ testRequest(backend, mainDocumentRequest("pre1://webkit.org/post1"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("pre2://webkit.org/post2"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("pre3://webkit.org/post3"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("pre4://webkit.org/post4"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("pre5://webkit.org/post5"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("pre6://webkit.org/post6"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("pre7://webkit.org/post7"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("pre8://webkit.org/post8"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("pre9://webkit.org/post9"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("pre0://webkit.org/post0"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("pre1://webkit.org/post2"), { });
+ testRequest(backend, mainDocumentRequest("pre2://webkit.org/post3"), { });
+ testRequest(backend, mainDocumentRequest("pre3://webkit.org/post4"), { });
+ testRequest(backend, mainDocumentRequest("pre4://webkit.org/post5"), { });
+ testRequest(backend, mainDocumentRequest("pre5://webkit.org/post6"), { });
+ testRequest(backend, mainDocumentRequest("pre6://webkit.org/post7"), { });
+ testRequest(backend, mainDocumentRequest("pre7://webkit.org/post8"), { });
+ testRequest(backend, mainDocumentRequest("pre8://webkit.org/post9"), { });
+ testRequest(backend, mainDocumentRequest("pre9://webkit.org/post0"), { });
+ testRequest(backend, mainDocumentRequest("pre0://webkit.org/post1"), { });
+
+ testRequest(backend, mainDocumentRequest("pre0://webkit.org/post1"), { });
+ testRequest(backend, mainDocumentRequest("pre1://webkit.org/post2"), { });
+ testRequest(backend, mainDocumentRequest("pre2://webkit.org/post3"), { });
+ testRequest(backend, mainDocumentRequest("pre3://webkit.org/post4"), { });
+ testRequest(backend, mainDocumentRequest("pre4://webkit.org/post5"), { });
+ testRequest(backend, mainDocumentRequest("pre5://webkit.org/post6"), { });
+ testRequest(backend, mainDocumentRequest("pre6://webkit.org/post7"), { });
+ testRequest(backend, mainDocumentRequest("pre7://webkit.org/post8"), { });
+ testRequest(backend, mainDocumentRequest("pre8://webkit.org/post9"), { });
+ testRequest(backend, mainDocumentRequest("pre9://webkit.org/post0"), { });
+}
+
+TEST_F(ContentExtensionTest, TrailingDotStar)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"foo.*$\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"bar(.*)$\"}}]");
+
+ testRequest(backend, mainDocumentRequest("https://webkit.org/"), { });
+
+ testRequest(backend, mainDocumentRequest("foo://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://foo.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.foo/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/foo"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("bar://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://bar.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.bar/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/bar"), { ContentExtensions::ActionType::BlockLoad });
+}
+
+TEST_F(ContentExtensionTest, TrailingTermsCarryingNoData)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"foob?a?r?\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"bazo(ok)?a?$\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"cats*$\"}}]");
+
+ testRequest(backend, mainDocumentRequest("https://webkit.org/"), { });
+
+ // Anything is fine after foo.
+ testRequest(backend, mainDocumentRequest("https://webkit.org/foo"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/foob"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/fooc"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/fooba"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/foobar-stuff"), { ContentExtensions::ActionType::BlockLoad });
+
+ // Bazooka has to be at the tail without any character not defined by the filter.
+ testRequest(backend, mainDocumentRequest("https://webkit.org/baz"), { });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/bazo"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/bazoa"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/bazob"), { });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/bazoo"), { });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/bazook"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/bazookb"), { });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/bazooka"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/bazookaa"), { });
+
+ // The pattern must finish with cat, with any number of 's' following it, but no other character.
+ testRequest(backend, mainDocumentRequest("https://cat.org/"), { });
+ testRequest(backend, mainDocumentRequest("https://cats.org/"), { });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/cat"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/cats"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/catss"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/catsss"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/catso"), { });
+}
+
+TEST_F(ContentExtensionTest, UselessTermsMatchingEverythingAreEliminated)
+{
+ ContentExtensions::CombinedURLFilters combinedURLFilters;
+ ContentExtensions::URLFilterParser parser(combinedURLFilters);
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern(".*web", false, 0));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(.*)web", false, 0));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(.)*web", false, 0));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(.+)*web", false, 0));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(.?)*web", false, 0));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(.+)?web", false, 0));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(.?)+web", false, 0));
+
+ Vector<ContentExtensions::NFA> nfas = createNFAs(combinedURLFilters);
+ EXPECT_EQ(1ul, nfas.size());
+ EXPECT_EQ(7ul, nfas.first().nodes.size());
+
+ ContentExtensions::DFA dfa = ContentExtensions::NFAToDFA::convert(nfas.first());
+ Vector<ContentExtensions::DFABytecode> bytecode;
+ ContentExtensions::DFABytecodeCompiler compiler(dfa, bytecode);
+ compiler.compile();
+ ContentExtensions::DFABytecodeInterpreter interpreter(bytecode.data(), bytecode.size());
+ compareContents(interpreter.interpret("eb", 0), { });
+ compareContents(interpreter.interpret("we", 0), { });
+ compareContents(interpreter.interpret("weeb", 0), { });
+ compareContents(interpreter.interpret("web", 0), { 0 });
+ compareContents(interpreter.interpret("wweb", 0), { 0 });
+ compareContents(interpreter.interpret("wwebb", 0), { 0 });
+ compareContents(interpreter.interpret("http://theweb.com/", 0), { 0 });
+}
+
+TEST_F(ContentExtensionTest, LoadType)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":[\"third-party\"]}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"whatwg.org\",\"load-type\":[\"first-party\"]}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"alwaysblock.pdf\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org"), { });
+ testRequest(backend, {URL(URL(), "http://webkit.org"), URL(URL(), "http://not_webkit.org"), ResourceType::Document}, { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("http://whatwg.org"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, {URL(URL(), "http://whatwg.org"), URL(URL(), "http://not_whatwg.org"), ResourceType::Document}, { });
+
+ testRequest(backend, mainDocumentRequest("http://foobar.org/alwaysblock.pdf"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, {URL(URL(), "http://foobar.org/alwaysblock.pdf"), URL(URL(), "http://not_foobar.org/alwaysblock.pdf"), ResourceType::Document}, { ContentExtensions::ActionType::BlockLoad });
+}
+
+TEST_F(ContentExtensionTest, ResourceType)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"block_all_types.org\",\"resource-type\":[\"document\",\"image\",\"style-sheet\",\"script\",\"font\",\"raw\",\"svg-document\",\"media\",\"popup\"]}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"block_only_images\",\"resource-type\":[\"image\"]}}]");
+
+ testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Document), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Image), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::StyleSheet), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Script), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Font), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Raw), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::SVGDocument), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Media), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Popup), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://block_only_images.org", ResourceType::Image), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://block_only_images.org", ResourceType::Document), { });
+}
+
+TEST_F(ContentExtensionTest, ResourceAndLoadType)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"BlockOnlyIfThirdPartyAndScript\",\"resource-type\":[\"script\"],\"load-type\":[\"third-party\"]}}]");
+
+ testRequest(backend, subResourceRequest("http://webkit.org/BlockOnlyIfThirdPartyAndScript.js", "http://webkit.org", ResourceType::Script), { });
+ testRequest(backend, subResourceRequest("http://webkit.org/BlockOnlyIfThirdPartyAndScript.png", "http://not_webkit.org", ResourceType::Image), { });
+ testRequest(backend, subResourceRequest("http://webkit.org/BlockOnlyIfThirdPartyAndScript.js", "http://not_webkit.org", ResourceType::Script), { ContentExtensions::ActionType::BlockLoad });
+}
+
+TEST_F(ContentExtensionTest, ResourceOrLoadTypeMatchingEverything)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*\",\"resource-type\":[\"image\"]}},"
+ "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\".*\",\"load-type\":[\"third-party\"]}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\".*\",\"load-type\":[\"first-party\"]}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org"), { }, true);
+ testRequest(backend, {URL(URL(), "http://webkit.org"), URL(URL(), "http://not_webkit.org"), ResourceType::Document}, { ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, {URL(URL(), "http://webkit.org"), URL(URL(), "http://not_webkit.org"), ResourceType::Image}, { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::BlockLoad });
+}
+
+TEST_F(ContentExtensionTest, WideNFA)
+{
+ // Make an NFA with about 1400 nodes that won't be combined.
+ StringBuilder ruleList;
+ ruleList.append('[');
+ for (char c1 = 'A'; c1 <= 'Z'; ++c1) {
+ for (char c2 = 'A'; c2 <= 'C'; ++c2) {
+ for (char c3 = 'A'; c3 <= 'C'; ++c3) {
+ if (c1 != 'A' || c2 != 'A' || c3 != 'A')
+ ruleList.append(',');
+ ruleList.append("{\"action\":{\"type\":\"");
+
+ // Make every other rule ignore-previous-rules to not combine actions.
+ if (!((c1 + c2 + c3) % 2))
+ ruleList.append("ignore-previous-rules");
+ else {
+ ruleList.append("css-display-none");
+ ruleList.append("\",\"selector\":\"");
+ ruleList.append(c1);
+ ruleList.append(c2);
+ ruleList.append(c3);
+ }
+ ruleList.append("\"},\"trigger\":{\"url-filter\":\".*");
+ ruleList.append(c1);
+ ruleList.append(c2);
+ ruleList.append(c3);
+ ruleList.append("\", \"url-filter-is-case-sensitive\":true}}");
+ }
+ }
+ }
+ ruleList.append(']');
+
+ auto backend = makeBackend(ruleList.toString().utf8().data());
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/AAA"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/YAA"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/ZAA"), { }, true);
+ testRequest(backend, mainDocumentRequest("http://webkit.org/LAA/AAA"), { }, true);
+ testRequest(backend, mainDocumentRequest("http://webkit.org/LAA/MAA"), { ContentExtensions::ActionType::CSSDisplayNoneSelector }, true);
+ testRequest(backend, mainDocumentRequest("http://webkit.org/"), { });
+}
+
+#ifdef NDEBUG
+static uint64_t expectedIndex(char c, unsigned position)
+{
+ uint64_t index = c - 'A';
+ for (unsigned i = 1; i < position; ++i)
+ index *= (i == 1) ? ('C' - 'A' + 1) : ('Z' - 'A' + 1);
+ return index;
+}
+#endif
+
+TEST_F(ContentExtensionTest, LargeJumps)
+{
+// A large test like this is necessary to test 24 and 32 bit jumps, but it's so large it times out in debug builds.
+#ifdef NDEBUG
+ ContentExtensions::CombinedURLFilters combinedURLFilters;
+ ContentExtensions::URLFilterParser parser(combinedURLFilters);
+
+ uint64_t patternId = 0;
+ for (char c1 = 'A'; c1 <= 'Z'; ++c1) {
+ for (char c2 = 'A'; c2 <= 'Z'; ++c2) {
+ for (char c3 = 'A'; c3 <= 'Z'; ++c3) {
+ for (char c4 = 'A'; c4 <= 'C'; ++c4) {
+ StringBuilder pattern;
+ pattern.append(c1);
+ pattern.append(c2);
+ pattern.append(c3);
+ pattern.append(c4);
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern(pattern.toString(), true, patternId++));
+ }
+ }
+ }
+ }
+
+ Vector<ContentExtensions::NFA> nfas;
+ combinedURLFilters.processNFAs(std::numeric_limits<size_t>::max(), [&](ContentExtensions::NFA&& nfa) {
+ nfas.append(WTFMove(nfa));
+ });
+ EXPECT_EQ(nfas.size(), 1ull);
+
+ Vector<ContentExtensions::DFA> dfas;
+ for (auto& nfa : nfas)
+ dfas.append(ContentExtensions::NFAToDFA::convert(nfa));
+ EXPECT_EQ(dfas.size(), 1ull);
+
+ Vector<ContentExtensions::DFABytecode> combinedBytecode;
+ for (const auto& dfa : dfas) {
+ Vector<ContentExtensions::DFABytecode> bytecode;
+ ContentExtensions::DFABytecodeCompiler compiler(dfa, bytecode);
+ compiler.compile();
+ combinedBytecode.appendVector(bytecode);
+ }
+
+ ContentExtensions::DFABytecodeInterpreter interpreter(&combinedBytecode[0], combinedBytecode.size());
+
+ patternId = 0;
+ for (char c1 = 'A'; c1 <= 'Z'; ++c1) {
+ for (char c2 = 'A'; c2 <= 'Z'; ++c2) {
+ for (char c3 = 'A'; c3 <= 'Z'; ++c3) {
+ for (char c4 = 'A'; c4 <= 'C'; ++c4) {
+ StringBuilder pattern;
+ pattern.append(c1);
+ pattern.append(c2);
+ pattern.append(c3);
+ // Test different jumping patterns distributed throughout the DFA:
+ switch ((c1 + c2 + c3 + c4) % 4) {
+ case 0:
+ // This should not match.
+ pattern.append('x');
+ pattern.append(c4);
+ break;
+ case 1:
+ // This should jump back to the root, then match.
+ pattern.append('x');
+ pattern.append(c1);
+ pattern.append(c2);
+ pattern.append(c3);
+ pattern.append(c4);
+ break;
+ case 2:
+ // This should match at the end of the string.
+ pattern.append(c4);
+ break;
+ case 3:
+ // This should match then jump back to the root.
+ pattern.append(c4);
+ pattern.append('x');
+ break;
+ }
+ auto matches = interpreter.interpret(pattern.toString().utf8(), 0);
+ switch ((c1 + c2 + c3 + c4) % 4) {
+ case 0:
+ compareContents(matches, { });
+ break;
+ case 1:
+ case 2:
+ case 3:
+ compareContents(matches, {patternId});
+ break;
+ }
+ patternId++;
+ }
+ }
+ }
+ }
+
+ compareContents(interpreter.interpret("CAAAAx", 0), {expectedIndex('C', 4), expectedIndex('A', 1)});
+ compareContents(interpreter.interpret("KAAAAx", 0), {expectedIndex('K', 4), expectedIndex('A', 1)});
+ compareContents(interpreter.interpret("AKAAAx", 0), {expectedIndex('K', 3), expectedIndex('K', 4)});
+ compareContents(interpreter.interpret("AKxAAAAx", 0), {expectedIndex('A', 1)});
+ compareContents(interpreter.interpret("AKAxAAAAx", 0), {expectedIndex('A', 1)});
+ compareContents(interpreter.interpret("AKAxZKAxZKZxAAAAx", 0), {expectedIndex('A', 1)});
+ compareContents(interpreter.interpret("ZAAAA", 0), {expectedIndex('Z', 4), expectedIndex('A', 1)});
+ compareContents(interpreter.interpret("ZZxZAAAB", 0), {expectedIndex('Z', 4), expectedIndex('B', 1)});
+#endif
+}
+
+TEST_F(ContentExtensionTest, DeepNFA)
+{
+ const unsigned size = 100000;
+
+ ContentExtensions::CombinedURLFilters combinedURLFilters;
+ ContentExtensions::URLFilterParser parser(combinedURLFilters);
+
+ // FIXME: DFAToNFA::convert takes way too long on these deep NFAs. We should optimize for that case.
+
+ StringBuilder lotsOfAs;
+ for (unsigned i = 0; i < size; ++i)
+ lotsOfAs.append('A');
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern(lotsOfAs.toString().utf8().data(), false, 0));
+
+ // FIXME: Yarr ought to be able to handle 2MB regular expressions.
+ StringBuilder tooManyAs;
+ for (unsigned i = 0; i < size * 20; ++i)
+ tooManyAs.append('A');
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::YarrError, parser.addPattern(tooManyAs.toString().utf8().data(), false, 0));
+
+ StringBuilder nestedGroups;
+ for (unsigned i = 0; i < size; ++i)
+ nestedGroups.append('(');
+ for (unsigned i = 0; i < size; ++i)
+ nestedGroups.append("B)");
+ // FIXME: Add nestedGroups. Right now it also takes too long. It should be optimized.
+
+ // This should not crash and not timeout.
+ EXPECT_EQ(1ul, createNFAs(combinedURLFilters).size());
+}
+
+void checkCompilerError(const char* json, std::error_code expectedError)
+{
+ CompiledContentExtensionData extensionData;
+ InMemoryContentExtensionCompilationClient client(extensionData);
+ std::error_code compilerError = ContentExtensions::compileRuleList(client, json);
+ EXPECT_EQ(compilerError.value(), expectedError.value());
+ if (compilerError.value())
+ EXPECT_STREQ(compilerError.category().name(), expectedError.category().name());
+}
+
+TEST_F(ContentExtensionTest, MatchesEverything)
+{
+ // Only css-display-none rules with triggers that match everything, no domain rules, and no flags
+ // should go in the global display:none stylesheet. css-display-none rules with domain rules or flags
+ // are applied separately on pages where they apply.
+ auto backend1 = makeBackend("[{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\"}}]");
+ EXPECT_TRUE(nullptr != backend1.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
+ testRequest(backend1, mainDocumentRequest("http://webkit.org"), { }); // Selector is in global stylesheet.
+
+ auto backend2 = makeBackend("[{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\",\"if-domain\":[\"webkit.org\"]}}]");
+ EXPECT_EQ(nullptr, backend2.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
+ testRequest(backend2, mainDocumentRequest("http://webkit.org"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(backend2, mainDocumentRequest("http://w3c.org"), { });
+
+ auto backend3 = makeBackend("[{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\",\"unless-domain\":[\"webkit.org\"]}}]");
+ EXPECT_EQ(nullptr, backend3.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
+ testRequest(backend3, mainDocumentRequest("http://webkit.org"), { });
+ testRequest(backend3, mainDocumentRequest("http://w3c.org"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+
+ auto backend4 = makeBackend("[{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\",\"load-type\":[\"third-party\"]}}]");
+ EXPECT_EQ(nullptr, backend4.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
+ testRequest(backend4, mainDocumentRequest("http://webkit.org"), { });
+ testRequest(backend4, subResourceRequest("http://not_webkit.org", "http://webkit.org"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+
+ // css-display-none rules after ignore-previous-rules should not be put in the default stylesheet.
+ auto backend5 = makeBackend("[{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\".*\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\"}}]");
+ EXPECT_EQ(nullptr, backend5.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
+ testRequest(backend5, mainDocumentRequest("http://webkit.org"), { ContentExtensions::ActionType::CSSDisplayNoneSelector }, true);
+
+ auto backend6 = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*\",\"if-domain\":[\"webkit.org\",\"*w3c.org\"],\"resource-type\":[\"document\",\"script\"]}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"ignore\",\"if-domain\":[\"*webkit.org\",\"w3c.org\"]}},"
+ "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\".*\",\"unless-domain\":[\"webkit.org\",\"whatwg.org\"],\"resource-type\":[\"script\",\"image\"],\"load-type\":[\"third-party\"]}}]");
+ EXPECT_EQ(nullptr, backend6.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
+ testRequest(backend6, mainDocumentRequest("http://webkit.org"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend6, mainDocumentRequest("http://w3c.org"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend6, mainDocumentRequest("http://whatwg.org"), { });
+ testRequest(backend6, mainDocumentRequest("http://sub.webkit.org"), { });
+ testRequest(backend6, mainDocumentRequest("http://sub.w3c.org"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend6, mainDocumentRequest("http://sub.whatwg.org"), { });
+ testRequest(backend6, mainDocumentRequest("http://webkit.org/ignore"), { }, true);
+ testRequest(backend6, mainDocumentRequest("http://w3c.org/ignore"), { }, true);
+ testRequest(backend6, mainDocumentRequest("http://whatwg.org/ignore"), { });
+ testRequest(backend6, mainDocumentRequest("http://sub.webkit.org/ignore"), { }, true);
+ testRequest(backend6, mainDocumentRequest("http://sub.w3c.org/ignore"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend6, mainDocumentRequest("http://sub.whatwg.org/ignore"), { });
+ testRequest(backend6, subResourceRequest("http://example.com/image.png", "http://webkit.org/", ResourceType::Image), { });
+ testRequest(backend6, subResourceRequest("http://example.com/image.png", "http://w3c.org/", ResourceType::Image), { ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend6, subResourceRequest("http://example.com/doc.html", "http://webkit.org/", ResourceType::Document), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend6, subResourceRequest("http://example.com/script.js", "http://webkit.org/", ResourceType::Script), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend6, subResourceRequest("http://example.com/script.js", "http://w3c.org/", ResourceType::Script), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend6, subResourceRequest("http://example.com/script.js", "http://example.com/", ResourceType::Script), { });
+ testRequest(backend6, subResourceRequest("http://example.com/ignore/image.png", "http://webkit.org/", ResourceType::Image), { }, true);
+ testRequest(backend6, subResourceRequest("http://example.com/ignore/image.png", "http://example.com/", ResourceType::Image), { });
+ testRequest(backend6, subResourceRequest("http://example.com/ignore/image.png", "http://example.org/", ResourceType::Image), { ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend6, subResourceRequest("http://example.com/doc.html", "http://example.org/", ResourceType::Document), { });
+ testRequest(backend6, subResourceRequest("http://example.com/", "http://example.com/", ResourceType::Font), { });
+ testRequest(backend6, subResourceRequest("http://example.com/ignore", "http://webkit.org/", ResourceType::Image), { }, true);
+ testRequest(backend6, subResourceRequest("http://example.com/ignore", "http://webkit.org/", ResourceType::Font), { }, true);
+ testRequest(backend6, subResourceRequest("http://example.com/", "http://example.com/", ResourceType::Script), { });
+ testRequest(backend6, subResourceRequest("http://example.com/ignore", "http://example.com/", ResourceType::Script), { });
+}
+
+TEST_F(ContentExtensionTest, InvalidJSON)
+{
+ checkCompilerError("[", ContentExtensions::ContentExtensionError::JSONInvalid);
+ checkCompilerError("123", ContentExtensions::ContentExtensionError::JSONTopLevelStructureNotAnObject);
+ checkCompilerError("{}", ContentExtensions::ContentExtensionError::JSONTopLevelStructureNotAnArray);
+ // FIXME: Add unit test for JSONInvalidRule if that is possible to hit.
+ checkCompilerError("[]", ContentExtensions::ContentExtensionError::JSONContainsNoRules);
+
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":5}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidTrigger);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"\"}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidURLFilterInTrigger);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":{}}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidURLFilterInTrigger);
+
+ // FIXME: Add unit test for JSONInvalidObjectInTriggerFlagsArray if that is possible to hit.
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":{}}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":[\"invalid\"]}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidStringInTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":[5]}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidStringInTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":5}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":\"first-party\"}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":null}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":false}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":{}}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":[\"invalid\"]}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidStringInTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":[5]}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidStringInTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":5}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":\"document\"}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":null}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":false}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
+
+ StringBuilder rules;
+ rules.append("[");
+ for (unsigned i = 0; i < 49999; ++i)
+ rules.append("{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"a\"}},");
+ String rules50000 = rules.toString();
+ String rules50001 = rules.toString();
+ rules50000.append("{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"a\"}}]");
+ rules50001.append("{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"a\"}},{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"a\"}}]");
+ checkCompilerError(rules50000.utf8().data(), { });
+ checkCompilerError(rules50001.utf8().data(), ContentExtensions::ContentExtensionError::JSONTooManyRules);
+
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":{}}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":[5]}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":[\"a\"]}}]", { });
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":\"a\"}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":false}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":null}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":{}}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[5]}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[\"\"]}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":\"a\"}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":null}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":false}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[\"A\"]}}]", ContentExtensions::ContentExtensionError::JSONDomainNotLowerCaseASCII);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[\"\\u00DC\"]}}]", ContentExtensions::ContentExtensionError::JSONDomainNotLowerCaseASCII);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[\"0\"]}}]", { });
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[\"a\"]}}]", { });
+
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":[],\"unless-domain\":[\"a\"]}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[]}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":5}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":5}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":5,\"unless-domain\":5}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":[]}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":[\"a\"],\"unless-domain\":[]}}]", ContentExtensions::ContentExtensionError::JSONUnlessAndIfDomain);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":[\"a\"],\"unless-domain\":[\"a\"]}}]", ContentExtensions::ContentExtensionError::JSONUnlessAndIfDomain);
+
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\", \"unexpected-identifier-should-be-ignored\":5}}]", { });
+
+ checkCompilerError("[{\"action\":5,\"trigger\":{\"url-filter\":\"webkit.org\"}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidAction);
+ checkCompilerError("[{\"action\":{\"type\":\"invalid\"},\"trigger\":{\"url-filter\":\"webkit.org\"}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidActionType);
+ checkCompilerError("[{\"action\":{\"type\":\"css-display-none\"},\"trigger\":{\"url-filter\":\"webkit.org\"}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidCSSDisplayNoneActionType);
+
+ checkCompilerError("[{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"webkit.org\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\"}}]", { });
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*\",\"if-domain\":[\"a\"]}}]", { });
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*\",\"unless-domain\":[\"a\"]}}]", { });
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[\"}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidRegex);
+}
+
+TEST_F(ContentExtensionTest, StrictPrefixSeparatedMachines1)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^.*foo\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"bar$\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[ab]+bang\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foo"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("foo://webkit.org/bar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/bar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bar://webkit.org/bar"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("abang://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bbang://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("cbang://webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/bang"), { });
+ testRequest(backend, mainDocumentRequest("bang://webkit.org/"), { });
+}
+
+TEST_F(ContentExtensionTest, StrictPrefixSeparatedMachines1Partitioning)
+{
+ ContentExtensions::CombinedURLFilters combinedURLFilters;
+ ContentExtensions::URLFilterParser parser(combinedURLFilters);
+
+ // Those two share a prefix.
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("^.*foo", false, 0));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("bar$", false, 1));
+
+ // Not this one.
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("^[ab]+bang", false, 0));
+
+ EXPECT_EQ(2ul, createNFAs(combinedURLFilters).size());
+}
+
+TEST_F(ContentExtensionTest, StrictPrefixSeparatedMachines2)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^foo\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^.*[a-c]+bar\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^webkit:\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[a-c]+b+oom\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("foo://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("webkit://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("http://bar.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://abar.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://bbar.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://cbar.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://abcbar.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://dbar.org/"), { });
+}
+
+TEST_F(ContentExtensionTest, StrictPrefixSeparatedMachines2Partitioning)
+{
+ ContentExtensions::CombinedURLFilters combinedURLFilters;
+ ContentExtensions::URLFilterParser parser(combinedURLFilters);
+
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("^foo", false, 0));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("^.*[a-c]+bar", false, 1));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("^webkit:", false, 2));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("[a-c]+b+oom", false, 3));
+
+ // "^foo" and "^webkit:" can be grouped, the other two have a variable prefix.
+ EXPECT_EQ(3ul, createNFAs(combinedURLFilters).size());
+}
+
+TEST_F(ContentExtensionTest, StrictPrefixSeparatedMachines3)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"A*D\"}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"A*BA+\"}},"
+ "{\"action\":{\"type\":\"make-https\"},\"trigger\":{\"url-filter\":\"A*BC\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/D"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/AAD"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/AB"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/ABA"), { }, true);
+ testRequest(backend, mainDocumentRequest("http://webkit.org/ABAD"), { }, true);
+ testRequest(backend, mainDocumentRequest("http://webkit.org/BC"), { ContentExtensions::ActionType::MakeHTTPS });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/ABC"), { ContentExtensions::ActionType::MakeHTTPS });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/ABABC"), { ContentExtensions::ActionType::MakeHTTPS }, true);
+ testRequest(backend, mainDocumentRequest("http://webkit.org/ABABCAD"), { ContentExtensions::ActionType::MakeHTTPS }, true);
+ testRequest(backend, mainDocumentRequest("http://webkit.org/ABCAD"), { ContentExtensions::ActionType::MakeHTTPS, ContentExtensions::ActionType::BlockLoad });
+}
+
+TEST_F(ContentExtensionTest, StrictPrefixSeparatedMachines3Partitioning)
+{
+ ContentExtensions::CombinedURLFilters combinedURLFilters;
+ ContentExtensions::URLFilterParser parser(combinedURLFilters);
+
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("A*D", false, 0));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("A*BA+", false, 1));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("A*BC", false, 2));
+
+ // "A*A" and "A*BC" can be grouped, "A*BA+" should not.
+ EXPECT_EQ(2ul, createNFAs(combinedURLFilters).size());
+}
+
+TEST_F(ContentExtensionTest, SplittingLargeNFAs)
+{
+ const size_t expectedNFACounts[16] = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1};
+
+ for (size_t i = 0; i < 16; i++) {
+ ContentExtensions::CombinedURLFilters combinedURLFilters;
+ ContentExtensions::URLFilterParser parser(combinedURLFilters);
+
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("A+BBB", false, 1));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("A+CCC", false, 2));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("A+DDD", false, 2));
+
+ Vector<ContentExtensions::NFA> nfas;
+ combinedURLFilters.processNFAs(i, [&](ContentExtensions::NFA&& nfa) {
+ nfas.append(WTFMove(nfa));
+ });
+ EXPECT_EQ(nfas.size(), expectedNFACounts[i]);
+
+ Vector<ContentExtensions::DFA> dfas;
+ for (auto& nfa : nfas)
+ dfas.append(ContentExtensions::NFAToDFA::convert(nfa));
+
+ Vector<ContentExtensions::DFABytecode> combinedBytecode;
+ for (const auto& dfa : dfas) {
+ Vector<ContentExtensions::DFABytecode> bytecode;
+ ContentExtensions::DFABytecodeCompiler compiler(dfa, bytecode);
+ compiler.compile();
+ combinedBytecode.appendVector(bytecode);
+ }
+
+ ContentExtensions::DFABytecodeInterpreter interpreter(&combinedBytecode[0], combinedBytecode.size());
+
+ EXPECT_EQ(interpreter.interpret("ABBBX", 0).size(), 1ull);
+ EXPECT_EQ(interpreter.interpret("ACCCX", 0).size(), 1ull);
+ EXPECT_EQ(interpreter.interpret("ADDDX", 0).size(), 1ull);
+ EXPECT_EQ(interpreter.interpret("XBBBX", 0).size(), 0ull);
+ EXPECT_EQ(interpreter.interpret("ABBX", 0).size(), 0ull);
+ EXPECT_EQ(interpreter.interpret("ACCX", 0).size(), 0ull);
+ EXPECT_EQ(interpreter.interpret("ADDX", 0).size(), 0ull);
+ }
+}
+
+TEST_F(ContentExtensionTest, QuantifierInGroup)
+{
+ ContentExtensions::CombinedURLFilters combinedURLFilters;
+ ContentExtensions::URLFilterParser parser(combinedURLFilters);
+
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(((A+)B)C)", false, 0));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(((A)B+)C)", false, 1));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(((A)B+)C)D", false, 2));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(((A)B)C+)", false, 3));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(((A)B)C)", false, 4));
+
+ // (((A)B+)C) and (((A)B+)C)D should be in the same NFA.
+ EXPECT_EQ(4ul, createNFAs(combinedURLFilters).size());
+}
+
+static void testPatternStatus(String pattern, ContentExtensions::URLFilterParser::ParseStatus status)
+{
+ ContentExtensions::CombinedURLFilters combinedURLFilters;
+ ContentExtensions::URLFilterParser parser(combinedURLFilters);
+ EXPECT_EQ(status, parser.addPattern(pattern, false, 0));
+}
+
+TEST_F(ContentExtensionTest, ParsingFailures)
+{
+ testPatternStatus("a*b?.*.?[a-z]?[a-z]*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("a*b?.*.?[a-z]?[a-z]+", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus("a*b?.*.?[a-z]?[a-z]", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus(".*?a", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus(".*a", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+
+ testPatternStatus("(?!)", ContentExtensions::URLFilterParser::ParseStatus::Group);
+ testPatternStatus("(?=)", ContentExtensions::URLFilterParser::ParseStatus::Group);
+ testPatternStatus("(?!a)", ContentExtensions::URLFilterParser::ParseStatus::Group);
+ testPatternStatus("(?=a)", ContentExtensions::URLFilterParser::ParseStatus::Group);
+ testPatternStatus("(regex)", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus("(regex", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
+ testPatternStatus("((regex)", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
+ testPatternStatus("(?:regex)", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus("(?:regex", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
+ testPatternStatus("[^.]+", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+
+ testPatternStatus("a++", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
+ testPatternStatus("[a]++", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
+ testPatternStatus("+", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
+
+ testPatternStatus("[", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
+ testPatternStatus("[a}", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
+
+ // FIXME: Look into why these do not cause YARR parsing errors. They probably should.
+ testPatternStatus("a]", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus("{", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus("{[a]", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus("{0", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus("{0,", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus("{0,1", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus("a{0,1", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus("a{a,b}", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+
+ const char nonASCII[2] = {-1, '\0'};
+ testPatternStatus(nonASCII, ContentExtensions::URLFilterParser::ParseStatus::NonASCII);
+ testPatternStatus("\\xff", ContentExtensions::URLFilterParser::ParseStatus::NonASCII);
+
+ testPatternStatus("\\x\\r\\n", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus("\\b", ContentExtensions::URLFilterParser::ParseStatus::WordBoundary);
+ testPatternStatus("[\\d]", ContentExtensions::URLFilterParser::ParseStatus::AtomCharacter);
+ testPatternStatus("\\d\\D\\w\\s\\v\\h\\i\\c", ContentExtensions::URLFilterParser::ParseStatus::UnsupportedCharacterClass);
+
+ testPatternStatus("this|that", ContentExtensions::URLFilterParser::ParseStatus::Disjunction);
+ testPatternStatus("a{0,1}b", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus("a{0,2}b", ContentExtensions::URLFilterParser::ParseStatus::InvalidQuantifier);
+ testPatternStatus("", ContentExtensions::URLFilterParser::ParseStatus::EmptyPattern);
+ testPatternStatus("$$", ContentExtensions::URLFilterParser::ParseStatus::MisplacedEndOfLine);
+ testPatternStatus("a^", ContentExtensions::URLFilterParser::ParseStatus::MisplacedStartOfLine);
+ testPatternStatus("(^)", ContentExtensions::URLFilterParser::ParseStatus::MisplacedStartOfLine);
+
+ testPatternStatus("(a)\\1", ContentExtensions::URLFilterParser::ParseStatus::Ok); // This should be BackReference, right?
+}
+
+TEST_F(ContentExtensionTest, PatternMatchingTheEmptyString)
+{
+ // Simple atoms.
+ testPatternStatus(".*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("a*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus(".?", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("a?", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+
+ // Character sets.
+ testPatternStatus("[a-z]*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("[a-z]?", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+
+ // Groups.
+ testPatternStatus("(foobar)*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("(foobar)?", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("(.*)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("(a*)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("(.?)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("(a?)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("([a-z]*)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("([a-z]?)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+
+ testPatternStatus("(.)*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("(.+)*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("(.?)*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("(.*)*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("(.+)?", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("(.?)+", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+
+ // Nested groups.
+ testPatternStatus("((foo)?((.)*)(bar)*)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+}
+
+TEST_F(ContentExtensionTest, MinimizingWithMoreFinalStatesThanNonFinalStates)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^h[a-z://]+\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://foo.com/\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://bar.com/\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://foo.com/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://bar.com/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("attp://foo.com/"), { });
+ testRequest(backend, mainDocumentRequest("attp://bar.com/"), { });
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bttp://webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("bttps://webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/b"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/b"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("cttp://webkit.org/B"), { });
+ testRequest(backend, mainDocumentRequest("cttps://webkit.org/B"), { });
+}
+
+TEST_F(ContentExtensionTest, StatesWithDifferentActionsAreNotUnified1)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://www.webkit.org/\"}},"
+ "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"^https://www.webkit.org/\"}},"
+ "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"^attps://www.webkit.org/\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://www.webkit.org/"), { ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("attps://www.webkit.org/"), { ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("http://www.webkit.org/a"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://www.webkit.org/B"), { ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("attps://www.webkit.org/c"), { ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("http://www.whatwg.org/"), { });
+ testRequest(backend, mainDocumentRequest("https://www.whatwg.org/"), { });
+ testRequest(backend, mainDocumentRequest("attps://www.whatwg.org/"), { });
+}
+
+TEST_F(ContentExtensionTest, StatesWithDifferentActionsAreNotUnified2)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://www.webkit.org/\"}},"
+ "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"^https://www.webkit.org/\"}},"
+ "{\"action\":{\"type\":\"css-display-none\", \"selector\":\"#foo\"},\"trigger\":{\"url-filter\":\"^https://www.webkit.org/\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("https://www.whatwg.org/"), { });
+ testRequest(backend, mainDocumentRequest("attps://www.whatwg.org/"), { });
+}
+
+// The order in which transitions from the root will be processed is unpredictable.
+// To exercises the various options, this test exists in various version exchanging the transition to the final state.
+TEST_F(ContentExtensionTest, FallbackTransitionsWithDifferentiatorDoNotMerge1)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.a\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^b.a\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bac\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bbc\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^BCC\"}}]");
+
+ testRequest(backend, mainDocumentRequest("aza://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bac://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bbc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bcc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("aac://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("abc://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("acc://www.webkit.org/"), { });
+
+ testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
+}
+TEST_F(ContentExtensionTest, FallbackTransitionsWithDifferentiatorDoNotMerge2)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bac\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bbc\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^BCC\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.a\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^b.a\"}}]");
+
+ testRequest(backend, mainDocumentRequest("aza://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bac://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bbc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bcc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("aac://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("abc://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("acc://www.webkit.org/"), { });
+
+ testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
+}
+TEST_F(ContentExtensionTest, FallbackTransitionsWithDifferentiatorDoNotMerge3)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.c\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^b.c\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^baa\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bba\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^BCA\"}}]");
+
+ testRequest(backend, mainDocumentRequest("azc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("baa://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bba://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bca://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("aaa://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("aba://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("aca://www.webkit.org/"), { });
+
+ testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
+}
+TEST_F(ContentExtensionTest, FallbackTransitionsWithDifferentiatorDoNotMerge4)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^baa\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bba\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^BCA\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.c\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^b.c\"}}]");
+
+ testRequest(backend, mainDocumentRequest("azc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("baa://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bba://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bca://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("aaa://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("aba://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("aca://www.webkit.org/"), { });
+
+ testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
+}
+
+TEST_F(ContentExtensionTest, FallbackTransitionsToOtherNodeInSameGroupDoesNotDifferentiateGroup)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^aac\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.c\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^b.c\"}}]");
+
+ testRequest(backend, mainDocumentRequest("aac://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("abc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bac://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("abc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("aaa://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("aca://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("baa://www.webkit.org/"), { });
+}
+
+TEST_F(ContentExtensionTest, SimpleFallBackTransitionDifferentiator1)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.bc.de\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.bd.ef\"}}]");
+
+ testRequest(backend, mainDocumentRequest("abbccde://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("aabcdde://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("aabddef://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("aabddef://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("abcde://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("abdef://www.webkit.org/"), { });
+}
+
+TEST_F(ContentExtensionTest, SimpleFallBackTransitionDifferentiator2)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^cb.\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^db.b\"}}]");
+
+ testRequest(backend, mainDocumentRequest("cba://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("cbb://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("dbab://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("dbxb://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("cca://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("dddd://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("bbbb://www.webkit.org/"), { });
+}
+
+// *** We have the following ranges intersections: ***
+// Full overlap.
+// 1)
+// A: |-----|
+// B: |---|
+// 2)
+// A: |-----|
+// B: |
+// 3)
+// A: |---|
+// B: |-----|
+// 4)
+// A: |
+// B: |-----|
+// One edge in common
+// 5)
+// A: |-|
+// B: |-|
+// 6)
+// A: |
+// B: |-|
+// 7)
+// A: |-|
+// B: |
+// 8)
+// A: |-|
+// B: |-|
+// 9)
+// A: |
+// B: |-|
+// 10)
+// A: |-|
+// B: |
+// B overlap on the left side of A.
+// 11)
+// A: |---|
+// B: |---|
+// 12)
+// A: |---|
+// B: |-----|
+// A overlap on the left side of B
+// 13)
+// A: |---|
+// B: |---|
+// 14)
+// A: |-----|
+// B: |---|
+// Equal ranges
+// 15)
+// A: |---|
+// B: |---|
+// 16)
+// A: |
+// B: |
+
+TEST_F(ContentExtensionTest, RangeOverlapCase1)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[a-m]\"}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"^[c-e]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { }, true);
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { }, true);
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { }, true);
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[a-m]\"}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"[c-e]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { }, true);
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { }, true);
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { }, true);
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase2)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[a-m]\"}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"^b\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { }, true);
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[a-m]\"}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"l\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.k.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.l.xxx/"), { }, true);
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase3)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[b-d]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[a-m]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[b-d]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[a-m]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase4)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^l\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[a-m]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("k://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("l://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"l\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[a-m]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.k.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.l.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase5)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[a-e]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[e-h]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[a-e]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[e-h]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase6)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^e\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[e-h]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"e\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[e-h]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase7)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[a-e]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^e\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[a-e]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"e\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase8)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[e-h]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[a-e]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[e-h]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[a-e]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase9)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^e\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[a-e]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"e\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[a-e]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase10)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[e-h]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^e\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[e-h]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"e\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase11)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[e-g]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[d-f]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("g://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[e-g]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[d-f]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.g.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
+}
+
+
+TEST_F(ContentExtensionTest, RangeOverlapCase12)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[e-g]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[d-g]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("g://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[e-g]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[d-g]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.g.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase13)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[b-d]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[c-e]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[b-d]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[c-e]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase14)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[b-e]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[c-e]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[b-e]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[c-e]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase15)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[c-f]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[c-f]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("g://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[c-f]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[c-f]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.g.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase16)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^c\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^c\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"c\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"c\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, QuantifiedOneOrMoreRangesCase11And13)
+{
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[c-e]+[g-i]+YYY\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[b-d]+[h-j]+YYY\"}}]");
+
+ // The interesting ranges only match between 'b' and 'k', plus a gap in 'f'.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.aayyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.abyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.acyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.adyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.aeyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.afyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.agyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ahyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.aiyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ajyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.akyyy.xxx/"), { });
+
+ // 'b' is the first character of the second rule.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.byyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bayyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bbyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bcyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bdyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.beyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bfyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bgyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.biyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bkyyy.xxx/"), { });
+
+ // 'c' is the first character of the first rule, and it overlaps the first character of the second rule.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cayyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cbyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ccyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cdyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ceyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cfyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.chyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ciyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ckyyy.xxx/"), { });
+
+ // 'd' is in the first range of both rule. This series cover overlaps between the two rules.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.degyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dehyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dfgyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dfhyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.djyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+}
+
+TEST_F(ContentExtensionTest, QuantifiedOneOrMoreRangesCase11And13InGroups)
+{
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"([c-e])+([g-i]+YYY)\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[b-d]+[h-j]+YYY\"}}]");
+
+ // The interesting ranges only match between 'b' and 'k', plus a gap in 'f'.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.aayyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.abyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.acyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.adyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.aeyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.afyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.agyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ahyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.aiyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ajyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.akyyy.xxx/"), { });
+
+ // 'b' is the first character of the second rule.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.byyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bayyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bbyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bcyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bdyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.beyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bfyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bgyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.biyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bkyyy.xxx/"), { });
+
+ // 'c' is the first character of the first rule, and it overlaps the first character of the second rule.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cayyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cbyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ccyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cdyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ceyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cfyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.chyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ciyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ckyyy.xxx/"), { });
+
+ // 'd' is in the first range of both rule. This series cover overlaps between the two rules.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.degyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dehyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dfgyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dfhyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.djyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase1)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[a-m]\"}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"^(bar)*[c-e]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { }, true);
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { }, true);
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { }, true);
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[a-m]\"}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"(bar)*[c-e]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { }, true);
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { }, true);
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { }, true);
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
+}
+
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase2)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[a-m]\"}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"^(bar)*b\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { }, true);
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[a-m]\"}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"(bar)*l\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.k.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.l.xxx/"), { }, true);
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase3)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[b-d]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[a-m]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[b-d]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[a-m]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase4)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*l\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[a-m]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("k://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("l://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*l\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[a-m]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.k.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.l.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase5)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[a-e]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[e-h]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[a-e]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[e-h]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase6)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*e\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[e-h]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*e\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[e-h]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase7)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[a-e]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*e\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[a-e]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*e\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase8)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[e-h]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[a-e]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[e-h]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[a-e]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase9)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*e\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[a-e]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*e\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[a-e]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase10)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[e-h]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*e\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[e-h]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*e\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase11)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[e-g]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[d-f]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("g://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[e-g]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[d-f]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.g.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
+}
+
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase12)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[e-g]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[d-g]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("g://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[e-g]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[d-g]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.g.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase13)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[b-d]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[c-e]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[b-d]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[c-e]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase14)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[b-e]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[c-e]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[b-e]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[c-e]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase15)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[c-f]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[c-f]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("g://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[c-f]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[c-f]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.g.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase16)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*c\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*c\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*c\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*c\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedQuantifiedOneOrMoreRangesCase11And13)
+{
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[c-e]+[g-i]+YYY\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[b-d]+[h-j]+YYY\"}}]");
+
+ // The interesting ranges only match between 'b' and 'k', plus a gap in 'f'.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.aayyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.abyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.acyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.adyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.aeyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.afyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.agyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ahyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.aiyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ajyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.akyyy.xxx/"), { });
+
+ // 'b' is the first character of the second rule.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.byyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bayyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bbyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bcyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bdyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.beyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bfyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bgyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.biyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bkyyy.xxx/"), { });
+
+ // 'c' is the first character of the first rule, and it overlaps the first character of the second rule.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cayyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cbyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ccyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cdyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ceyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cfyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.chyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ciyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ckyyy.xxx/"), { });
+
+ // 'd' is in the first range of both rule. This series cover overlaps between the two rules.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.degyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dehyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dfgyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dfhyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.djyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+}
+
+TEST_F(ContentExtensionTest, CombinedQuantifiedOneOrMoreRangesCase11And13InGroups)
+{
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*([c-e])+([g-i]+YYY)\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[b-d]+[h-j]+YYY\"}}]");
+
+ // The interesting ranges only match between 'b' and 'k', plus a gap in 'f'.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.aayyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.abyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.acyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.adyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.aeyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.afyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.agyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ahyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.aiyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ajyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.akyyy.xxx/"), { });
+
+ // 'b' is the first character of the second rule.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.byyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bayyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bbyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bcyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bdyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.beyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bfyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bgyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.biyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bkyyy.xxx/"), { });
+
+ // 'c' is the first character of the first rule, and it overlaps the first character of the second rule.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cayyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cbyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ccyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cdyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ceyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cfyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.chyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ciyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ckyyy.xxx/"), { });
+
+ // 'd' is in the first range of both rule. This series cover overlaps between the two rules.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.degyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dehyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dfgyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dfhyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.djyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/DFACombiner.cpp b/Tools/TestWebKitAPI/Tests/WebCore/DFACombiner.cpp
new file mode 100644
index 000000000..d53ebb75a
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/DFACombiner.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "config.h"
+
+#include "DFAHelpers.h"
+#include <WebCore/DFACombiner.h>
+#include <wtf/MainThread.h>
+
+using namespace WebCore;
+using namespace ContentExtensions;
+
+namespace TestWebKitAPI {
+
+class DFACombinerTest : public testing::Test {
+public:
+ virtual void SetUp()
+ {
+ WTF::initializeMainThread();
+ }
+};
+
+Vector<DFA> combine(Vector<DFA> dfas, unsigned minimumSize)
+{
+ DFACombiner combiner;
+ for (DFA& dfa : dfas)
+ combiner.addDFA(WTFMove(dfa));
+
+ Vector<DFA> output;
+ combiner.combineDFAs(minimumSize, [&output](DFA&& dfa) {
+ output.append(dfa);
+ });
+ return output;
+}
+
+TEST_F(DFACombinerTest, Basic)
+{
+ Vector<DFA> dfas = { buildDFAFromPatterns({ "foo"}), buildDFAFromPatterns({ "bar"}) };
+ Vector<DFA> combinedDFAs = combine(dfas, 10000);
+ EXPECT_EQ(static_cast<size_t>(1), combinedDFAs.size());
+
+ DFA reference = buildDFAFromPatterns({ "foo", "bar"});
+ reference.minimize();
+ EXPECT_EQ(countLiveNodes(reference), countLiveNodes(combinedDFAs.first()));
+}
+
+
+TEST_F(DFACombinerTest, IdenticalDFAs)
+{
+ Vector<DFA> dfas = { buildDFAFromPatterns({ "foo"}), buildDFAFromPatterns({ "foo"}) };
+ Vector<DFA> combinedDFAs = combine(dfas, 10000);
+ EXPECT_EQ(static_cast<size_t>(1), combinedDFAs.size());
+
+ // The result should have the exact same size as the minimized input.
+ DFA reference = buildDFAFromPatterns({ "foo"});
+ reference.minimize();
+ EXPECT_EQ(countLiveNodes(reference), countLiveNodes(combinedDFAs.first()));
+}
+
+TEST_F(DFACombinerTest, NoInput)
+{
+ DFACombiner combiner;
+ unsigned counter = 0;
+ combiner.combineDFAs(100000, [&counter](DFA&& dfa) {
+ ++counter;
+ });
+ EXPECT_EQ(static_cast<unsigned>(0), counter);
+}
+
+TEST_F(DFACombinerTest, SingleInput)
+{
+ Vector<DFA> dfas = { buildDFAFromPatterns({ "WebKit"}) };
+ Vector<DFA> combinedDFAs = combine(dfas, 10000);
+ EXPECT_EQ(static_cast<size_t>(1), combinedDFAs.size());
+
+ DFA reference = buildDFAFromPatterns({ "WebKit"});
+ reference.minimize();
+ EXPECT_EQ(countLiveNodes(reference), countLiveNodes(combinedDFAs.first()));
+}
+
+TEST_F(DFACombinerTest, InputTooLargeForMinimumSize)
+{
+ Vector<DFA> dfas = { buildDFAFromPatterns({ "foo"}), buildDFAFromPatterns({ "bar"}) };
+ Vector<DFA> combinedDFAs = combine(dfas, 2);
+ EXPECT_EQ(static_cast<size_t>(2), combinedDFAs.size());
+ EXPECT_EQ(static_cast<size_t>(4), countLiveNodes(combinedDFAs[0]));
+ EXPECT_EQ(static_cast<size_t>(4), countLiveNodes(combinedDFAs[1]));
+}
+
+TEST_F(DFACombinerTest, CombinedInputReachesMinimumSize)
+{
+ Vector<DFA> dfas = { buildDFAFromPatterns({ "foo"}), buildDFAFromPatterns({ "bar"}), buildDFAFromPatterns({ "WebKit"}) };
+ Vector<DFA> combinedDFAs = combine(dfas, 5);
+ EXPECT_EQ(static_cast<size_t>(2), combinedDFAs.size());
+ EXPECT_EQ(static_cast<size_t>(7), countLiveNodes(combinedDFAs[0]));
+ EXPECT_EQ(static_cast<size_t>(6), countLiveNodes(combinedDFAs[1]));
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/DFAHelpers.h b/Tools/TestWebKitAPI/Tests/WebCore/DFAHelpers.h
new file mode 100644
index 000000000..8c6402760
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/DFAHelpers.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include <WebCore/CombinedURLFilters.h>
+#include <WebCore/NFA.h>
+#include <WebCore/NFAToDFA.h>
+#include <WebCore/URLFilterParser.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+static unsigned countLiveNodes(const ContentExtensions::DFA& dfa)
+{
+ unsigned counter = 0;
+ for (const auto& node : dfa.nodes) {
+ if (!node.isKilled())
+ ++counter;
+ }
+ return counter;
+}
+
+static Vector<ContentExtensions::NFA> createNFAs(ContentExtensions::CombinedURLFilters& combinedURLFilters)
+{
+ Vector<ContentExtensions::NFA> nfas;
+
+ combinedURLFilters.processNFAs(std::numeric_limits<size_t>::max(), [&](ContentExtensions::NFA&& nfa) {
+ nfas.append(WTFMove(nfa));
+ });
+
+ return nfas;
+}
+
+static ContentExtensions::DFA buildDFAFromPatterns(Vector<const char*> patterns)
+{
+ ContentExtensions::CombinedURLFilters combinedURLFilters;
+ ContentExtensions::URLFilterParser parser(combinedURLFilters);
+
+ for (const char* pattern : patterns)
+ parser.addPattern(pattern, false, 0);
+ Vector<ContentExtensions::NFA> nfas = createNFAs(combinedURLFilters);
+ return ContentExtensions::NFAToDFA::convert(nfas[0]);
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/DFAMinimizer.cpp b/Tools/TestWebKitAPI/Tests/WebCore/DFAMinimizer.cpp
new file mode 100644
index 000000000..bb3ac2e2a
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/DFAMinimizer.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "config.h"
+
+#include "DFAHelpers.h"
+#include <wtf/MainThread.h>
+
+namespace TestWebKitAPI {
+
+class DFAMinimizerTest : public testing::Test {
+public:
+ virtual void SetUp()
+ {
+ WTF::initializeMainThread();
+ }
+};
+
+TEST_F(DFAMinimizerTest, BasicSearch)
+{
+ ContentExtensions::DFA dfa = buildDFAFromPatterns({ ".*foo", ".*bar", ".*bang"});
+ EXPECT_EQ(static_cast<size_t>(8), countLiveNodes(dfa));
+ dfa.minimize();
+ EXPECT_EQ(static_cast<size_t>(7), countLiveNodes(dfa));
+}
+
+TEST_F(DFAMinimizerTest, MergeSuffixes)
+{
+ ContentExtensions::DFA dfa = buildDFAFromPatterns({ ".*aaa", ".*aab", ".*aba", ".*abb", ".*baa", ".*bab", ".*bba", ".*bbb"});
+ EXPECT_EQ(static_cast<size_t>(12), countLiveNodes(dfa));
+ dfa.minimize();
+ EXPECT_EQ(static_cast<size_t>(4), countLiveNodes(dfa));
+}
+
+TEST_F(DFAMinimizerTest, MergeInfixes)
+{
+ ContentExtensions::DFA dfa = buildDFAFromPatterns({ ".*aaakit", ".*aabkit", ".*abakit", ".*abbkit", ".*baakit", ".*babkit", ".*bbakit", ".*bbbkit"});
+ EXPECT_EQ(static_cast<size_t>(15), countLiveNodes(dfa));
+ dfa.minimize();
+ EXPECT_EQ(static_cast<size_t>(7), countLiveNodes(dfa));
+}
+
+TEST_F(DFAMinimizerTest, FallbackTransitionsWithDifferentiatorDoNotMerge1)
+{
+ ContentExtensions::DFA dfa = buildDFAFromPatterns({ "^a.a", "^b.a", "^bac", "^bbc", "^BCC"});
+ EXPECT_EQ(static_cast<size_t>(6), countLiveNodes(dfa));
+ dfa.minimize();
+ EXPECT_EQ(static_cast<size_t>(6), countLiveNodes(dfa));
+}
+
+TEST_F(DFAMinimizerTest, FallbackTransitionsWithDifferentiatorDoNotMerge2)
+{
+ ContentExtensions::DFA dfa = buildDFAFromPatterns({ "^bbc", "^BCC", "^a.a", "^b.a"});
+ EXPECT_EQ(static_cast<size_t>(6), countLiveNodes(dfa));
+ dfa.minimize();
+ EXPECT_EQ(static_cast<size_t>(6), countLiveNodes(dfa));
+}
+
+TEST_F(DFAMinimizerTest, FallbackTransitionsWithDifferentiatorDoNotMerge3)
+{
+ ContentExtensions::DFA dfa = buildDFAFromPatterns({ "^a.c", "^b.c", "^baa", "^bba", "^BCA"});
+ EXPECT_EQ(static_cast<size_t>(6), countLiveNodes(dfa));
+ dfa.minimize();
+ EXPECT_EQ(static_cast<size_t>(6), countLiveNodes(dfa));
+}
+
+TEST_F(DFAMinimizerTest, FallbackTransitionsWithDifferentiatorDoNotMerge4)
+{
+ ContentExtensions::DFA dfa = buildDFAFromPatterns({ "^baa", "^bba", "^BCA", "^a.c", "^b.c"});
+ EXPECT_EQ(static_cast<size_t>(6), countLiveNodes(dfa));
+ dfa.minimize();
+ EXPECT_EQ(static_cast<size_t>(6), countLiveNodes(dfa));
+}
+
+TEST_F(DFAMinimizerTest, FallbackTransitionsToOtherNodeInSameGroupDoesNotDifferentiateGroup)
+{
+ ContentExtensions::DFA dfa = buildDFAFromPatterns({ "^aac", "^a.c", "^b.c"});
+ EXPECT_EQ(static_cast<size_t>(5), countLiveNodes(dfa));
+ dfa.minimize();
+ EXPECT_EQ(static_cast<size_t>(4), countLiveNodes(dfa));
+}
+
+TEST_F(DFAMinimizerTest, SimpleFallBackTransitionDifferentiator1)
+{
+ ContentExtensions::DFA dfa = buildDFAFromPatterns({ "^a.bc.de", "^a.bd.ef"});
+ EXPECT_EQ(static_cast<size_t>(11), countLiveNodes(dfa));
+ dfa.minimize();
+ EXPECT_EQ(static_cast<size_t>(11), countLiveNodes(dfa));
+}
+
+TEST_F(DFAMinimizerTest, SimpleFallBackTransitionDifferentiator2)
+{
+ ContentExtensions::DFA dfa = buildDFAFromPatterns({ "^cb.", "^db.b"});
+ EXPECT_EQ(static_cast<size_t>(7), countLiveNodes(dfa));
+ dfa.minimize();
+ EXPECT_EQ(static_cast<size_t>(7), countLiveNodes(dfa));
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/FileSystem.cpp b/Tools/TestWebKitAPI/Tests/WebCore/FileSystem.cpp
new file mode 100644
index 000000000..fb23a4b7c
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/FileSystem.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2015 Canon 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 "Test.h"
+#include <WebCore/FileSystem.h>
+#include <wtf/MainThread.h>
+#include <wtf/StringExtras.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+const char* FileSystemTestData = "This is a test";
+
+// FIXME: Refactor FileSystemTest and SharedBufferTest as a single class.
+class FileSystemTest : public testing::Test {
+public:
+ virtual void SetUp() override
+ {
+ WTF::initializeMainThread();
+
+ // create temp file
+ PlatformFileHandle handle;
+ m_tempFilePath = openTemporaryFile("tempTestFile", handle);
+ writeToFile(handle, FileSystemTestData, strlen(FileSystemTestData));
+ closeFile(handle);
+
+ m_tempEmptyFilePath = openTemporaryFile("tempEmptyTestFile", handle);
+ closeFile(handle);
+ }
+
+ virtual void TearDown() override
+ {
+ deleteFile(m_tempFilePath);
+ deleteFile(m_tempEmptyFilePath);
+ }
+
+ const String& tempFilePath() { return m_tempFilePath; }
+ const String& tempEmptyFilePath() { return m_tempEmptyFilePath; }
+
+private:
+ String m_tempFilePath;
+ String m_tempEmptyFilePath;
+};
+
+TEST_F(FileSystemTest, MappingMissingFile)
+{
+ bool success;
+ MappedFileData mappedFileData(String("not_existing_file"), success);
+ EXPECT_FALSE(success);
+ EXPECT_TRUE(!mappedFileData);
+}
+
+TEST_F(FileSystemTest, MappingExistingFile)
+{
+ bool success;
+ MappedFileData mappedFileData(tempFilePath(), success);
+ EXPECT_TRUE(success);
+ EXPECT_TRUE(!!mappedFileData);
+ EXPECT_TRUE(mappedFileData.size() == strlen(FileSystemTestData));
+ EXPECT_TRUE(strnstr(FileSystemTestData, static_cast<const char*>(mappedFileData.data()), mappedFileData.size()));
+}
+
+TEST_F(FileSystemTest, MappingExistingEmptyFile)
+{
+ bool success;
+ MappedFileData mappedFileData(tempEmptyFilePath(), success);
+ EXPECT_TRUE(success);
+ EXPECT_TRUE(!mappedFileData);
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/LayoutUnit.cpp b/Tools/TestWebKitAPI/Tests/WebCore/LayoutUnit.cpp
index ceafb039c..f904c96a1 100644
--- a/Tools/TestWebKitAPI/Tests/WebCore/LayoutUnit.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebCore/LayoutUnit.cpp
@@ -28,8 +28,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#define ENABLE_SUBPIXEL_LAYOUT 1
-#define ENABLE_SATURATED_LAYOUT_ARITHMETIC 1
#include "config.h"
#include <WebCore/LayoutUnit.h>
@@ -77,6 +75,10 @@ TEST(WebCoreLayoutUnit, LayoutUnitFloat)
ASSERT_NEAR(LayoutUnit(345634.12335f).toFloat(), 345634.12335f, tolerance);
ASSERT_NEAR(LayoutUnit(-345634.12335f).toFloat(), -345634.12335f, tolerance);
ASSERT_NEAR(LayoutUnit(-345634).toFloat(), -345634.0f, tolerance);
+ ASSERT_NEAR(LayoutUnit(33554432.f).toFloat(), 33554432.f, tolerance);
+ ASSERT_NEAR(LayoutUnit(-33554432.f).toFloat(), -33554432.f, tolerance);
+ ASSERT_NEAR(LayoutUnit(33554432.f).toDouble(), 33554432.f, tolerance);
+ ASSERT_NEAR(LayoutUnit(-33554432.f).toDouble(), -33554432.f, tolerance);
}
TEST(WebCoreLayoutUnit, LayoutUnitRounding)
@@ -104,28 +106,6 @@ TEST(WebCoreLayoutUnit, LayoutUnitRounding)
ASSERT_EQ(LayoutUnit::fromFloatRound(1.51f).round(), 2);
}
-TEST(WebCoreLayoutUnit, LayoutUnitSnapSizeToPixel)
-{
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(1), LayoutUnit(0)), 1);
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(1), LayoutUnit(0.5)), 1);
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(1.5), LayoutUnit(0)), 2);
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(1.5), LayoutUnit(0.49)), 2);
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(1.5), LayoutUnit(0.5)), 1);
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(1.5), LayoutUnit(0.75)), 1);
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(1.5), LayoutUnit(0.99)), 1);
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(1.5), LayoutUnit(1)), 2);
-
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(0.5), LayoutUnit(1.5)), 0);
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(0.99), LayoutUnit(1.5)), 0);
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(1.0), LayoutUnit(1.5)), 1);
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(1.49), LayoutUnit(1.5)), 1);
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(1.5), LayoutUnit(1.5)), 1);
-
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(100.5), LayoutUnit(100)), 101);
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(intMaxForLayoutUnit), LayoutUnit(0.3)), intMaxForLayoutUnit);
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(intMinForLayoutUnit), LayoutUnit(-0.3)), intMinForLayoutUnit);
-}
-
TEST(WebCoreLayoutUnit, LayoutUnitMultiplication)
{
ASSERT_EQ((LayoutUnit(1) * LayoutUnit(1)).toInt(), 1);
@@ -250,5 +230,19 @@ TEST(WebCoreLayoutUnit, LayoutUnitFloor)
ASSERT_EQ((LayoutUnit(intMinForLayoutUnit) + LayoutUnit(1)).floor(), intMinForLayoutUnit + 1);
}
+TEST(WebCoreLayoutUnit, LayoutUnitPixelSnapping)
+{
+ for (int i = -100000; i <= 100000; ++i) {
+ ASSERT_EQ(roundToDevicePixel(LayoutUnit(i), 1), i);
+ ASSERT_EQ(roundToDevicePixel(LayoutUnit(i), 2), i);
+ ASSERT_EQ(roundToDevicePixel(LayoutUnit(i), 3), i);
+ }
+
+ for (float i = -10000; i < 0; i = i + 0.5)
+ ASSERT_FLOAT_EQ(roundToDevicePixel(LayoutUnit(i), 2), i);
+
+ for (float i = -10000.25; i < 0; i = i + 0.5)
+ ASSERT_FLOAT_EQ(roundToDevicePixel(LayoutUnit(i), 2), i + 0.25);
+}
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/ParsedContentRange.cpp b/Tools/TestWebKitAPI/Tests/WebCore/ParsedContentRange.cpp
new file mode 100644
index 000000000..986388302
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/ParsedContentRange.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <WebCore/ParsedContentRange.h>
+#include <wtf/text/WTFString.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+TEST(WebCore, ParsedContentRangeFromString)
+{
+ // Basic parsing
+ ASSERT_TRUE(ParsedContentRange("bytes 0-1/2").isValid());
+ ASSERT_TRUE(ParsedContentRange("bytes 0-1/*").isValid());
+ ASSERT_EQ(0, ParsedContentRange("bytes 0-1/2").firstBytePosition());
+ ASSERT_EQ(1, ParsedContentRange("bytes 0-1/2").lastBytePosition());
+ ASSERT_EQ(2, ParsedContentRange("bytes 0-1/2").instanceLength());
+ ASSERT_EQ(ParsedContentRange::UnknownLength, ParsedContentRange("bytes 0-1/*").instanceLength());
+
+ // Whitespace errors
+ ASSERT_FALSE(ParsedContentRange("bytes 0-1/*").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0 -1/*").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0- 1/*").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-1 /*").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-1/ *").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-1/* ").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-1/ 2").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-1/2 ").isValid());
+
+ // Non-digit errors
+ ASSERT_FALSE(ParsedContentRange("bytes abcd-1/2").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-abcd/2").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-1/abcd").isValid());
+
+ // Range requirement errors
+ ASSERT_FALSE(ParsedContentRange("bytes 1-0/2").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-2/1").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 2/0-1").isValid());
+ ASSERT_FALSE(ParsedContentRange("abcd 0/1-2").isValid());
+
+ // Negative value errors
+ ASSERT_FALSE(ParsedContentRange("bytes -0-1/*").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes -1/*").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0--0/2").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-1/-2").isValid());
+
+ // Edge cases
+ ASSERT_TRUE(ParsedContentRange("bytes 9223372036854775805-9223372036854775806/9223372036854775807").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 9223372036854775808-9223372036854775809/9223372036854775810").isValid());
+}
+
+TEST(WebCore, ParsedContentRangeFromValues)
+{
+ ASSERT_TRUE(ParsedContentRange(0, 1, 2).isValid());
+ ASSERT_TRUE(ParsedContentRange(0, 1, ParsedContentRange::UnknownLength).isValid());
+ ASSERT_FALSE(ParsedContentRange().isValid());
+ ASSERT_FALSE(ParsedContentRange(1, 0, 2).isValid());
+ ASSERT_FALSE(ParsedContentRange(0, 2, 1).isValid());
+ ASSERT_FALSE(ParsedContentRange(0, 0, 0).isValid());
+ ASSERT_FALSE(ParsedContentRange(-1, 1, 2).isValid());
+ ASSERT_FALSE(ParsedContentRange(0, -1, 2).isValid());
+ ASSERT_FALSE(ParsedContentRange(0, 1, -2).isValid());
+ ASSERT_FALSE(ParsedContentRange(-2, -1, 2).isValid());
+}
+
+TEST(WebCore, ParsedContentRangeToString)
+{
+ ASSERT_STREQ("bytes 0-1/2", ParsedContentRange(0, 1, 2).headerValue().utf8().data());
+ ASSERT_STREQ("bytes 0-1/*", ParsedContentRange(0, 1, ParsedContentRange::UnknownLength).headerValue().utf8().data());
+ ASSERT_STREQ("", ParsedContentRange().headerValue().utf8().data());
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/PublicSuffix.cpp b/Tools/TestWebKitAPI/Tests/WebCore/PublicSuffix.cpp
new file mode 100644
index 000000000..f87ba63eb
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/PublicSuffix.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(PUBLIC_SUFFIX_LIST)
+
+#include "WTFStringUtilities.h"
+#include <WebCore/PublicSuffix.h>
+#include <wtf/MainThread.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+class PublicSuffix: public testing::Test {
+public:
+ virtual void SetUp()
+ {
+ WTF::initializeMainThread();
+ }
+};
+
+TEST_F(PublicSuffix, IsPublicSuffix)
+{
+ EXPECT_TRUE(isPublicSuffix("com"));
+ EXPECT_FALSE(isPublicSuffix("test.com"));
+ EXPECT_FALSE(isPublicSuffix("com.com"));
+ EXPECT_TRUE(isPublicSuffix("net"));
+ EXPECT_TRUE(isPublicSuffix("org"));
+ EXPECT_TRUE(isPublicSuffix("co.uk"));
+ EXPECT_FALSE(isPublicSuffix("bl.uk"));
+ EXPECT_FALSE(isPublicSuffix("test.co.uk"));
+ EXPECT_TRUE(isPublicSuffix("xn--zf0ao64a.tw"));
+}
+
+TEST_F(PublicSuffix, TopPrivatelyControlledDomain)
+{
+ EXPECT_EQ(String("test.com"), topPrivatelyControlledDomain("test.com"));
+ EXPECT_EQ(String("test.com"), topPrivatelyControlledDomain("com.test.com"));
+ EXPECT_EQ(String("test.com"), topPrivatelyControlledDomain("subdomain.test.com"));
+ EXPECT_EQ(String("com.com"), topPrivatelyControlledDomain("www.com.com"));
+ EXPECT_EQ(String("test.co.uk"), topPrivatelyControlledDomain("test.co.uk"));
+ EXPECT_EQ(String("test.co.uk"), topPrivatelyControlledDomain("subdomain.test.co.uk"));
+ EXPECT_EQ(String("bl.uk"), topPrivatelyControlledDomain("bl.uk"));
+ EXPECT_EQ(String("bl.uk"), topPrivatelyControlledDomain("subdomain.bl.uk"));
+ EXPECT_EQ(String("test.xn--zf0ao64a.tw"), topPrivatelyControlledDomain("test.xn--zf0ao64a.tw"));
+ EXPECT_EQ(String("test.xn--zf0ao64a.tw"), topPrivatelyControlledDomain("www.test.xn--zf0ao64a.tw"));
+ EXPECT_EQ(String("127.0.0.1"), topPrivatelyControlledDomain("127.0.0.1"));
+ EXPECT_EQ(String(), topPrivatelyControlledDomain("1"));
+ EXPECT_EQ(String(), topPrivatelyControlledDomain("com"));
+}
+
+}
+
+#endif // ENABLE(PUBLIC_SUFFIX_LIST)
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/SharedBuffer.cpp b/Tools/TestWebKitAPI/Tests/WebCore/SharedBuffer.cpp
new file mode 100644
index 000000000..295281ef9
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/SharedBuffer.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2015 Canon 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 "Test.h"
+#include <WebCore/SharedBuffer.h>
+#include <wtf/MainThread.h>
+#include <wtf/StringExtras.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+const char* SharedBufferTestData = "This is a test";
+
+class SharedBufferTest : public testing::Test {
+public:
+ virtual void SetUp() override
+ {
+ WTF::initializeMainThread();
+
+ // create temp file
+ PlatformFileHandle handle;
+ m_tempFilePath = openTemporaryFile("tempTestFile", handle);
+ writeToFile(handle, SharedBufferTestData, strlen(SharedBufferTestData));
+ closeFile(handle);
+
+ m_tempEmptyFilePath = openTemporaryFile("tempEmptyTestFile", handle);
+ closeFile(handle);
+ }
+
+ virtual void TearDown() override
+ {
+ deleteFile(m_tempFilePath);
+ deleteFile(m_tempEmptyFilePath);
+ }
+
+ const String& tempFilePath() { return m_tempFilePath; }
+ const String& tempEmptyFilePath() { return m_tempEmptyFilePath; }
+
+private:
+ String m_tempFilePath;
+ String m_tempEmptyFilePath;
+};
+
+TEST_F(SharedBufferTest, createWithContentsOfMissingFile)
+{
+ RefPtr<SharedBuffer> buffer = SharedBuffer::createWithContentsOfFile(String("not_existing_file"));
+ ASSERT_NULL(buffer);
+}
+
+TEST_F(SharedBufferTest, createWithContentsOfExistingFile)
+{
+ RefPtr<SharedBuffer> buffer = SharedBuffer::createWithContentsOfFile(tempFilePath());
+ ASSERT_NOT_NULL(buffer);
+ EXPECT_TRUE(buffer->size() == strlen(SharedBufferTestData));
+ EXPECT_TRUE(String(SharedBufferTestData) == String(buffer->data(), buffer->size()));
+}
+
+TEST_F(SharedBufferTest, createWithContentsOfExistingEmptyFile)
+{
+ RefPtr<SharedBuffer> buffer = SharedBuffer::createWithContentsOfFile(tempEmptyFilePath());
+ ASSERT_NOT_NULL(buffer);
+ EXPECT_TRUE(buffer->isEmpty());
+}
+
+TEST_F(SharedBufferTest, copyBufferCreatedWithContentsOfExistingFile)
+{
+ RefPtr<SharedBuffer> buffer = SharedBuffer::createWithContentsOfFile(tempFilePath());
+ ASSERT_NOT_NULL(buffer);
+ RefPtr<SharedBuffer> copy = buffer->copy();
+ EXPECT_GT(buffer->size(), 0U);
+ EXPECT_TRUE(buffer->size() == copy->size());
+ EXPECT_TRUE(!memcmp(buffer->data(), copy->data(), buffer->size()));
+}
+
+TEST_F(SharedBufferTest, clearBufferCreatedWithContentsOfExistingFile)
+{
+ RefPtr<SharedBuffer> buffer = SharedBuffer::createWithContentsOfFile(tempFilePath());
+ ASSERT_NOT_NULL(buffer);
+ buffer->clear();
+ EXPECT_TRUE(!buffer->size());
+ EXPECT_TRUE(!buffer->data());
+}
+
+TEST_F(SharedBufferTest, appendBufferCreatedWithContentsOfExistingFile)
+{
+ RefPtr<SharedBuffer> buffer = SharedBuffer::createWithContentsOfFile(tempFilePath());
+ ASSERT_NOT_NULL(buffer);
+ buffer->append("a", 1);
+ EXPECT_TRUE(buffer->size() == (strlen(SharedBufferTestData) + 1));
+ EXPECT_TRUE(!memcmp(buffer->data(), SharedBufferTestData, strlen(SharedBufferTestData)));
+ EXPECT_EQ('a', buffer->data()[strlen(SharedBufferTestData)]);
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/TimeRanges.cpp b/Tools/TestWebKitAPI/Tests/WebCore/TimeRanges.cpp
new file mode 100644
index 000000000..1612bf8f0
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/TimeRanges.cpp
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2013, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include <WebCore/TimeRanges.h>
+
+#include <WebCore/ExceptionCodePlaceholder.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+static std::string ToString(const TimeRanges& ranges)
+{
+ std::stringstream ss;
+ ss << "{";
+ for (unsigned i = 0; i < ranges.length(); ++i)
+ ss << " [" << ranges.start(i, IGNORE_EXCEPTION) << "," << ranges.end(i, IGNORE_EXCEPTION) << ")";
+ ss << " }";
+
+ return ss.str();
+}
+
+#define ASSERT_RANGE(expected, range) EXPECT_EQ(expected, ToString(*range))
+
+TEST(TimeRanges, Empty)
+{
+ ASSERT_RANGE("{ }", TimeRanges::create().ptr());
+}
+
+TEST(TimeRanges, SingleRange)
+{
+ ASSERT_RANGE("{ [1,2) }", TimeRanges::create(1, 2).ptr());
+}
+
+TEST(TimeRanges, AddOrder)
+{
+ RefPtr<TimeRanges> rangeA = TimeRanges::create();
+ RefPtr<TimeRanges> rangeB = TimeRanges::create();
+
+ rangeA->add(0, 2);
+ rangeA->add(3, 4);
+ rangeA->add(5, 100);
+
+ std::string expected = "{ [0,2) [3,4) [5,100) }";
+ ASSERT_RANGE(expected, rangeA);
+
+ // Add the values in rangeA to rangeB in reverse order.
+ for (int i = rangeA->length() - 1; i >= 0; --i)
+ rangeB->add(rangeA->start(i, IGNORE_EXCEPTION), rangeA->end(i, IGNORE_EXCEPTION));
+
+ ASSERT_RANGE(expected, rangeB);
+}
+
+TEST(TimeRanges, OverlappingAdds)
+{
+ RefPtr<TimeRanges> ranges = TimeRanges::create();
+
+ ranges->add(0, 2);
+ ranges->add(10, 11);
+ ASSERT_RANGE("{ [0,2) [10,11) }", ranges);
+
+ ranges->add(0, 2);
+ ASSERT_RANGE("{ [0,2) [10,11) }", ranges);
+
+ ranges->add(2, 3);
+ ASSERT_RANGE("{ [0,3) [10,11) }", ranges);
+
+ ranges->add(2, 6);
+ ASSERT_RANGE("{ [0,6) [10,11) }", ranges);
+
+ ranges->add(9, 10);
+ ASSERT_RANGE("{ [0,6) [9,11) }", ranges);
+
+ ranges->add(8, 10);
+ ASSERT_RANGE("{ [0,6) [8,11) }", ranges);
+
+ ranges->add(-1, 7);
+ ASSERT_RANGE("{ [-1,7) [8,11) }", ranges);
+
+ ranges->add(6, 9);
+ ASSERT_RANGE("{ [-1,11) }", ranges);
+}
+
+TEST(TimeRanges, IntersectWith_Self)
+{
+ RefPtr<TimeRanges> ranges = TimeRanges::create(0, 2);
+
+ ASSERT_RANGE("{ [0,2) }", ranges);
+
+ ranges->intersectWith(*ranges.get());
+
+ ASSERT_RANGE("{ [0,2) }", ranges);
+}
+
+TEST(TimeRanges, IntersectWith_IdenticalRange)
+{
+ RefPtr<TimeRanges> rangesA = TimeRanges::create(0, 2);
+ RefPtr<TimeRanges> rangesB = rangesA->copy();
+
+ ASSERT_RANGE("{ [0,2) }", rangesA);
+ ASSERT_RANGE("{ [0,2) }", rangesB);
+
+ rangesA->intersectWith(*rangesB.get());
+
+ ASSERT_RANGE("{ [0,2) }", rangesA);
+ ASSERT_RANGE("{ [0,2) }", rangesB);
+}
+
+TEST(TimeRanges, IntersectWith_Empty)
+{
+ RefPtr<TimeRanges> rangesA = TimeRanges::create(0, 2);
+ RefPtr<TimeRanges> rangesB = TimeRanges::create();
+
+ ASSERT_RANGE("{ [0,2) }", rangesA);
+ ASSERT_RANGE("{ }", rangesB);
+
+ rangesA->intersectWith(*rangesB.get());
+
+ ASSERT_RANGE("{ }", rangesA);
+ ASSERT_RANGE("{ }", rangesB);
+}
+
+TEST(TimeRanges, IntersectWith_DisjointRanges1)
+{
+
+ RefPtr<TimeRanges> rangesA = TimeRanges::create();
+ RefPtr<TimeRanges> rangesB = TimeRanges::create();
+
+ rangesA->add(0, 1);
+ rangesA->add(4, 5);
+
+ rangesB->add(2, 3);
+ rangesB->add(6, 7);
+
+ ASSERT_RANGE("{ [0,1) [4,5) }", rangesA);
+ ASSERT_RANGE("{ [2,3) [6,7) }", rangesB);
+
+ rangesA->intersectWith(*rangesB.get());
+
+ ASSERT_RANGE("{ }", rangesA);
+ ASSERT_RANGE("{ [2,3) [6,7) }", rangesB);
+}
+
+TEST(TimeRanges, IntersectWith_DisjointRanges2)
+{
+ RefPtr<TimeRanges> rangesA = TimeRanges::create();
+ RefPtr<TimeRanges> rangesB = TimeRanges::create();
+
+ rangesA->add(0, 1);
+ rangesA->add(4, 5);
+
+ rangesB->add(1, 4);
+ rangesB->add(5, 7);
+
+ ASSERT_RANGE("{ [0,1) [4,5) }", rangesA);
+ ASSERT_RANGE("{ [1,4) [5,7) }", rangesB);
+
+ rangesA->intersectWith(*rangesB.get());
+
+ ASSERT_RANGE("{ }", rangesA);
+ ASSERT_RANGE("{ [1,4) [5,7) }", rangesB);
+}
+
+TEST(TimeRanges, IntersectWith_CompleteOverlap1)
+{
+ RefPtr<TimeRanges> rangesA = TimeRanges::create();
+ RefPtr<TimeRanges> rangesB = TimeRanges::create();
+
+ rangesA->add(1, 3);
+ rangesA->add(4, 5);
+ rangesA->add(6, 9);
+
+ rangesB->add(0, 10);
+
+ ASSERT_RANGE("{ [1,3) [4,5) [6,9) }", rangesA);
+ ASSERT_RANGE("{ [0,10) }", rangesB);
+
+ rangesA->intersectWith(*rangesB.get());
+
+ ASSERT_RANGE("{ [1,3) [4,5) [6,9) }", rangesA);
+ ASSERT_RANGE("{ [0,10) }", rangesB);
+}
+
+TEST(TimeRanges, IntersectWith_CompleteOverlap2)
+{
+ RefPtr<TimeRanges> rangesA = TimeRanges::create();
+ RefPtr<TimeRanges> rangesB = TimeRanges::create();
+
+ rangesA->add(1, 3);
+ rangesA->add(4, 5);
+ rangesA->add(6, 9);
+
+ rangesB->add(1, 9);
+
+ ASSERT_RANGE("{ [1,3) [4,5) [6,9) }", rangesA);
+ ASSERT_RANGE("{ [1,9) }", rangesB);
+
+ rangesA->intersectWith(*rangesB.get());
+
+ ASSERT_RANGE("{ [1,3) [4,5) [6,9) }", rangesA);
+ ASSERT_RANGE("{ [1,9) }", rangesB);
+}
+
+TEST(TimeRanges, IntersectWith_Gaps1)
+{
+ RefPtr<TimeRanges> rangesA = TimeRanges::create();
+ RefPtr<TimeRanges> rangesB = TimeRanges::create();
+
+ rangesA->add(0, 2);
+ rangesA->add(4, 6);
+
+ rangesB->add(1, 5);
+
+ ASSERT_RANGE("{ [0,2) [4,6) }", rangesA);
+ ASSERT_RANGE("{ [1,5) }", rangesB);
+
+ rangesA->intersectWith(*rangesB.get());
+
+ ASSERT_RANGE("{ [1,2) [4,5) }", rangesA);
+ ASSERT_RANGE("{ [1,5) }", rangesB);
+}
+
+TEST(TimeRanges, IntersectWith_Gaps2)
+{
+ RefPtr<TimeRanges> rangesA = TimeRanges::create();
+ RefPtr<TimeRanges> rangesB = TimeRanges::create();
+
+ rangesA->add(0, 2);
+ rangesA->add(4, 6);
+ rangesA->add(8, 10);
+
+ rangesB->add(1, 9);
+
+ ASSERT_RANGE("{ [0,2) [4,6) [8,10) }", rangesA);
+ ASSERT_RANGE("{ [1,9) }", rangesB);
+
+ rangesA->intersectWith(*rangesB.get());
+
+ ASSERT_RANGE("{ [1,2) [4,6) [8,9) }", rangesA);
+ ASSERT_RANGE("{ [1,9) }", rangesB);
+}
+
+TEST(TimeRanges, IntersectWith_Gaps3)
+{
+ RefPtr<TimeRanges> rangesA = TimeRanges::create();
+ RefPtr<TimeRanges> rangesB = TimeRanges::create();
+
+ rangesA->add(0, 2);
+ rangesA->add(4, 7);
+ rangesA->add(8, 10);
+
+ rangesB->add(1, 5);
+ rangesB->add(6, 9);
+
+ ASSERT_RANGE("{ [0,2) [4,7) [8,10) }", rangesA);
+ ASSERT_RANGE("{ [1,5) [6,9) }", rangesB);
+
+ rangesA->intersectWith(*rangesB.get());
+
+ ASSERT_RANGE("{ [1,2) [4,5) [6,7) [8,9) }", rangesA);
+ ASSERT_RANGE("{ [1,5) [6,9) }", rangesB);
+}
+
+}
+
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/gtk/UserAgentQuirks.cpp b/Tools/TestWebKitAPI/Tests/WebCore/gtk/UserAgentQuirks.cpp
index 40305e801..4033b37e2 100644
--- a/Tools/TestWebKitAPI/Tests/WebCore/gtk/UserAgentQuirks.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebCore/gtk/UserAgentQuirks.cpp
@@ -43,21 +43,6 @@ TEST(WebCore, UserAgentQuirksTest)
EXPECT_TRUE(uaString.contains("Macintosh"));
EXPECT_TRUE(uaString.contains("Mac OS X"));
EXPECT_FALSE(uaString.contains("Linux"));
-
- // For Google domains we always return the standard UA.
- uaString = standardUserAgent();
- EXPECT_FALSE(uaString.isNull());
- EXPECT_TRUE(uaString == standardUserAgentForURL(URL(ParsedURLString, "http://www.google.com/")));
- EXPECT_TRUE(uaString == standardUserAgentForURL(URL(ParsedURLString, "http://calendar.google.com/")));
- EXPECT_TRUE(uaString == standardUserAgentForURL(URL(ParsedURLString, "http://gmail.com/")));
- EXPECT_TRUE(uaString == standardUserAgentForURL(URL(ParsedURLString, "http://www.google.com.br/")));
- EXPECT_TRUE(uaString == standardUserAgentForURL(URL(ParsedURLString, "http://www.youtube.com/")));
- EXPECT_TRUE(uaString != standardUserAgentForURL(URL(ParsedURLString, "http://www.google.uk.not.com.br/")));
-
- // For Google Maps we remove the Version/8.0 string.
- uaString = standardUserAgentForURL(URL(ParsedURLString, "http://maps.google.com/"));
- EXPECT_TRUE(uaString == standardUserAgentForURL(URL(ParsedURLString, "http://www.google.com/maps/")));
- EXPECT_FALSE(uaString.contains("Version/8.0 Safari/"));
}
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/18-characters.html b/Tools/TestWebKitAPI/Tests/WebKit2/18-characters.html
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/18-characters.html
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/AboutBlankLoad.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/AboutBlankLoad.cpp
index 0a2f00ca5..5503edd9e 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/AboutBlankLoad.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/AboutBlankLoad.cpp
@@ -24,6 +24,9 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
@@ -57,3 +60,5 @@ TEST(WebKit2, AboutBlankLoad)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/Ahem.ttf b/Tools/TestWebKitAPI/Tests/WebKit2/Ahem.ttf
new file mode 100644
index 000000000..ac81cb031
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/Ahem.ttf
Binary files differ
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/CanHandleRequest.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/CanHandleRequest.cpp
index 4c0c77963..a1d09f2cd 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/CanHandleRequest.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/CanHandleRequest.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKContextPrivate.h>
+#include <WebKit/WKContextPrivate.h>
namespace TestWebKitAPI {
@@ -71,3 +74,5 @@ TEST(WebKit2, CanHandleRequest)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/CanHandleRequest_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/CanHandleRequest_Bundle.cpp
index 5f66b537a..590615e8c 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/CanHandleRequest_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/CanHandleRequest_Bundle.cpp
@@ -24,10 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKBundlePage.h>
+#include <WebKit/WKBundlePage.h>
namespace TestWebKitAPI {
@@ -65,3 +68,5 @@ void CanHandleRequestTest::didReceiveMessage(WKBundleRef bundle, WKStringRef mes
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/CloseFromWithinCreatePage.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/CloseFromWithinCreatePage.cpp
new file mode 100644
index 000000000..b5e4a901b
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/CloseFromWithinCreatePage.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+
+namespace TestWebKitAPI {
+
+static bool testDone;
+static std::unique_ptr<PlatformWebView> openedWebView;
+
+static void runJavaScriptAlert(WKPageRef page, WKStringRef alertText, WKFrameRef frame, WKSecurityOriginRef, const void* clientInfo)
+{
+ // FIXME: Check that the alert text matches the storage.
+ testDone = true;
+}
+
+static WKPageRef createNewPage(WKPageRef page, WKURLRequestRef urlRequest, WKDictionaryRef features, WKEventModifiers modifiers, WKEventMouseButton mouseButton, const void *clientInfo)
+{
+ EXPECT_TRUE(openedWebView == nullptr);
+
+ openedWebView = std::make_unique<PlatformWebView>(page);
+
+ WKPageUIClientV5 uiClient;
+ memset(&uiClient, 0, sizeof(uiClient));
+
+ uiClient.base.version = 5;
+ uiClient.runJavaScriptAlert = runJavaScriptAlert;
+ WKPageSetPageUIClient(openedWebView->page(), &uiClient.base);
+
+ WKPageClose(page);
+
+ WKRetain(openedWebView->page());
+ return openedWebView->page();
+}
+
+TEST(WebKit2, CloseFromWithinCreatePage)
+{
+ WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+
+ PlatformWebView webView(context.get());
+
+ WKPageUIClientV5 uiClient;
+ memset(&uiClient, 0, sizeof(uiClient));
+
+ uiClient.base.version = 5;
+ uiClient.createNewPage = createNewPage;
+ uiClient.runJavaScriptAlert = runJavaScriptAlert;
+ WKPageSetPageUIClient(webView.page(), &uiClient.base);
+
+ WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("close-from-within-create-page", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+
+ Util::run(&testDone);
+
+ openedWebView = nullptr;
+}
+
+}
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/CloseThenTerminate.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/CloseThenTerminate.cpp
index ff70511f4..71239e4f0 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/CloseThenTerminate.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/CloseThenTerminate.cpp
@@ -24,6 +24,9 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
@@ -62,3 +65,5 @@ TEST(WebKit2, CloseThenTerminate)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/CookieManager.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/CookieManager.cpp
index 2f17b8162..d231e0e75 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/CookieManager.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/CookieManager.cpp
@@ -24,10 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKCookieManager.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKCookieManager.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -86,3 +89,5 @@ TEST(WebKit2, CookieManager)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewIsActiveSetIsActive.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewIsActiveSetIsActive.cpp
new file mode 100644
index 000000000..ef9625b99
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewIsActiveSetIsActive.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2013 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 THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "PlatformUtilities.h"
+#include "Test.h"
+
+#include <WebKit/WKContext.h>
+#include <WebKit/WKPage.h>
+#include <WebKit/WKRetainPtr.h>
+#include <WebKit/WKView.h>
+
+namespace TestWebKitAPI {
+
+static bool didWebProcessCrash = false;
+static bool didWebProcessRelaunch = false;
+static bool didFinishLoad = false;
+
+static void didFinishLoadForFrame(WKPageRef, WKFrameRef, WKTypeRef, const void*)
+{
+ didFinishLoad = true;
+}
+
+static void webProcessCrashed(WKViewRef view, WKURLRef, const void*)
+{
+ // WebProcess crashed, so at this point the view should not be active.
+ ASSERT_FALSE(WKViewIsActive(view));
+ didWebProcessCrash = true;
+}
+
+static void webProcessRelaunched(WKViewRef view, const void*)
+{
+ // WebProcess just relaunched, so at this point the view should not be active.
+ ASSERT_FALSE(WKViewIsActive(view));
+
+ didWebProcessRelaunch = true;
+}
+
+TEST(WebKit2, WKViewIsActiveSetIsActive)
+{
+ WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreate());
+ WKRetainPtr<WKViewRef> view = adoptWK(WKViewCreate(context.get(), 0));
+
+ WKViewInitialize(view.get());
+
+ // At this point we should have an active view.
+ ASSERT_TRUE(WKViewIsActive(view.get()));
+
+ // Now we are going to play with its active state a few times.
+ WKViewSetIsActive(view.get(), true);
+ ASSERT_TRUE(WKViewIsActive(view.get()));
+
+ WKViewSetIsActive(view.get(), false);
+ ASSERT_FALSE(WKViewIsActive(view.get()));
+
+ WKViewSetIsActive(view.get(), false);
+ ASSERT_FALSE(WKViewIsActive(view.get()));
+
+ WKViewSetIsActive(view.get(), true);
+ ASSERT_TRUE(WKViewIsActive(view.get()));
+}
+
+TEST(WebKit2, WKViewIsActive)
+{
+ WKRetainPtr<WKContextRef> context = adoptWK(Util::createContextForInjectedBundleTest("WKViewIsActiveSetIsActiveTest"));
+ WKRetainPtr<WKViewRef> view = adoptWK(WKViewCreate(context.get(), 0));
+
+ WKViewClientV0 viewClient;
+ memset(&viewClient, 0, sizeof(WKViewClientV0));
+ viewClient.base.version = 0;
+ viewClient.webProcessCrashed = webProcessCrashed;
+ viewClient.webProcessDidRelaunch = webProcessRelaunched;
+ WKViewSetViewClient(view.get(), &viewClient.base);
+
+ WKViewInitialize(view.get());
+
+ // At this point we should have an active view.
+ ASSERT_TRUE(WKViewIsActive(view.get()));
+
+ WKPageLoaderClientV3 pageLoaderClient;
+ memset(&pageLoaderClient, 0, sizeof(WKPageLoaderClient));
+ pageLoaderClient.base.version = 3;
+ pageLoaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+ WKPageSetPageLoaderClient(WKViewGetPage(view.get()), &pageLoaderClient.base);
+
+ const WKSize size = WKSizeMake(100, 100);
+ WKViewSetSize(view.get(), size);
+
+ didFinishLoad = false;
+ didWebProcessCrash = false;
+ didWebProcessRelaunch = false;
+
+ WKRetainPtr<WKURLRef> simpleUrl = adoptWK(Util::createURLForResource("../WebKit/simple", "html"));
+ WKPageLoadURL(WKViewGetPage(view.get()), simpleUrl.get());
+ Util::run(&didFinishLoad);
+ didFinishLoad = false;
+
+ WKContextPostMessageToInjectedBundle(context.get(), Util::toWK("Crash").get(), 0);
+ Util::run(&didWebProcessCrash);
+ ASSERT_TRUE(didWebProcessCrash);
+
+ WKPageLoadURL(WKViewGetPage(view.get()), simpleUrl.get());
+ Util::run(&didFinishLoad);
+
+ ASSERT_TRUE(didWebProcessRelaunch);
+ ASSERT_TRUE(didFinishLoad);
+}
+
+} // TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewIsActiveSetIsActive_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewIsActiveSetIsActive_Bundle.cpp
new file mode 100644
index 000000000..a3cb1b6de
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewIsActiveSetIsActive_Bundle.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2013 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 THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "InjectedBundleTest.h"
+#include <WebKit/WKRetainPtr.h>
+
+#include <cstdlib>
+
+namespace TestWebKitAPI {
+
+class WKViewIsActiveSetIsActiveTest : public InjectedBundleTest {
+public:
+ WKViewIsActiveSetIsActiveTest(const std::string& identifier)
+ : InjectedBundleTest(identifier)
+ {
+ }
+
+ virtual void didReceiveMessage(WKBundleRef bundle, WKStringRef messageName, WKTypeRef messageBody)
+ {
+ if (!WKStringIsEqualToUTF8CString(messageName, "Crash"))
+ return;
+ abort();
+ }
+};
+
+static InjectedBundleTest::Register<WKViewIsActiveSetIsActiveTest> registrar("WKViewIsActiveSetIsActiveTest");
+
+} // namespace TestWebKitAPI
+
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewRestoreZoomAndScrollBackForward.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewRestoreZoomAndScrollBackForward.cpp
new file mode 100644
index 000000000..5c556ecee
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewRestoreZoomAndScrollBackForward.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2012-2013 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2011 Samsung Electronics. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "ewk_view_private.h"
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include <WebKit/WKContext.h>
+#include <WebKit/WKRetainPtr.h>
+#include "Test.h"
+
+namespace TestWebKitAPI {
+
+static bool finishedLoad = false;
+static bool scroll = false;
+
+static void didFinishLoadForFrame(WKPageRef, WKFrameRef, WKTypeRef, const void*)
+{
+ finishedLoad = true;
+}
+
+static void didChangeContentsPosition(WKViewRef, WKPoint p, const void*)
+{
+ scroll = true;
+}
+
+TEST(WebKit2, WKViewRestoreZoomAndScrollBackForward)
+{
+ WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+ PlatformWebView webView(context.get());
+ WKRetainPtr<WKViewRef> view = EWKViewGetWKView(webView.platformView());
+
+ WKPageSetUseFixedLayout(webView.page(), true);
+
+ WKPageLoaderClientV0 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+ loaderClient.base.version = 0;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+ WKPageSetPageLoaderClient(webView.page(), &loaderClient.base);
+
+ WKViewClientV0 viewClient;
+ memset(&viewClient, 0, sizeof(viewClient));
+ viewClient.base.version = 0;
+ viewClient.didChangeContentsPosition = didChangeContentsPosition;
+ WKViewSetViewClient(view.get(), &viewClient.base);
+
+ // Load first page.
+ WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("CoordinatedGraphics/backforward1", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+ Util::run(&finishedLoad);
+
+ // Change scale and position on first page.
+ float firstPageScale = 2.0;
+ WKPoint firstPageScrollPosition = WKPointMake(10, 350); // Scroll position of first page.
+ WKViewSetContentPosition(view.get(), firstPageScrollPosition);
+ WKViewSetContentScaleFactor(view.get(), firstPageScale);
+ float currentPageScale = WKViewGetContentScaleFactor(view.get());
+ WKPoint currentPagePosition = WKViewGetContentPosition(view.get());
+ Util::run(&scroll);
+ EXPECT_EQ(firstPageScale, currentPageScale);
+ EXPECT_EQ(firstPageScrollPosition.x, currentPagePosition.x);
+ EXPECT_EQ(firstPageScrollPosition.y, currentPagePosition.y);
+
+ // Load second page.
+ finishedLoad = false;
+ url = adoptWK(Util::createURLForResource("CoordinatedGraphics/backforward2", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+ Util::run(&finishedLoad);
+
+ // Check if second page scale and position is correct.
+ currentPageScale = WKViewGetContentScaleFactor(view.get());
+ currentPagePosition = WKViewGetContentPosition(view.get());
+ EXPECT_EQ(1, currentPageScale);
+ EXPECT_EQ(0, currentPagePosition.x);
+ EXPECT_EQ(0, currentPagePosition.y);
+
+ // Go back first page.
+ scroll = false;
+ finishedLoad = false;
+ WKPageGoBack(webView.page());
+ Util::run(&finishedLoad);
+ Util::run(&scroll);
+
+ // Check if scroll position and scale of first page are restored correctly.
+ currentPageScale = WKViewGetContentScaleFactor(view.get());
+ currentPagePosition = WKViewGetContentPosition(view.get());
+ EXPECT_EQ(firstPageScale, currentPageScale);
+ EXPECT_EQ(firstPageScrollPosition.x, currentPagePosition.x);
+ EXPECT_EQ(firstPageScrollPosition.y, currentPagePosition.y);
+
+ // Go to second page again.
+ WKPageGoForward(webView.page());
+ scroll = false;
+ finishedLoad = false;
+ Util::run(&finishedLoad);
+
+ // Check if the scroll position and scale of second page are restored correctly.
+ currentPageScale = WKViewGetContentScaleFactor(view.get());
+ currentPagePosition = WKViewGetContentPosition(view.get());
+ EXPECT_EQ(1, currentPageScale);
+ EXPECT_EQ(0, currentPagePosition.x);
+ EXPECT_EQ(0, currentPagePosition.y);
+}
+
+} // TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewUserViewportToContents.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewUserViewportToContents.cpp
new file mode 100644
index 000000000..2445fd71f
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewUserViewportToContents.cpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2013 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 THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "WebKit/WKView.h"
+#include "WebKit/WKRetainPtr.h"
+
+namespace TestWebKitAPI {
+
+TEST(WebKit2, DISABLED_WKViewUserViewportToContents)
+{
+ // This test creates a WKView and uses the WKViewUserViewportToContents
+ // function to convert viewport coordinates to contents (page) coordinates.
+ // It scrolls and scales around the contents and check if the coordinates
+ // conversion math is right.
+
+ WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+ WKRetainPtr<WKPageConfigurationRef> configuration(AdoptWK, WKPageConfigurationCreate());
+ WKPageConfigurationSetContext(configuration.get(), context.get());
+
+ WKRetainPtr<WKViewRef> webView(AdoptWK, WKViewCreate(context.get(), configuration.get()));
+
+ WKViewSetIsActive(webView.get(), true);
+ WKPageSetUseFixedLayout(WKViewGetPage(webView.get()), false);
+
+ WKPoint out;
+
+ // At scale 1.0 the viewport and contents coordinates should match.
+
+ WKViewSetContentScaleFactor(webView.get(), 1.0);
+ WKViewSetContentPosition(webView.get(), WKPointMake(0, 0));
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0));
+ EXPECT_EQ(out.x, 0);
+ EXPECT_EQ(out.y, 0);
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10));
+ EXPECT_EQ(out.x, 10);
+ EXPECT_EQ(out.y, 10);
+
+ WKViewSetContentPosition(webView.get(), WKPointMake(20, 20));
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0));
+ EXPECT_EQ(out.x, 20);
+ EXPECT_EQ(out.y, 20);
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10));
+ EXPECT_EQ(out.x, 30);
+ EXPECT_EQ(out.y, 30);
+
+ // At scale 2.0 the viewport distance values will be half
+ // the ones seem in the contents.
+
+ WKViewSetContentScaleFactor(webView.get(), 2.0);
+ WKViewSetContentPosition(webView.get(), WKPointMake(0, 0));
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0));
+ EXPECT_EQ(out.x, 0);
+ EXPECT_EQ(out.y, 0);
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10));
+ EXPECT_EQ(out.x, 5);
+ EXPECT_EQ(out.y, 5);
+
+ WKViewSetContentPosition(webView.get(), WKPointMake(20, 20));
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0));
+ EXPECT_EQ(out.x, 20);
+ EXPECT_EQ(out.y, 20);
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10));
+ EXPECT_EQ(out.x, 25);
+ EXPECT_EQ(out.y, 25);
+
+ // At scale 0.5 the viewport distance values will be twice
+ // the ones seem in the contents.
+
+ WKViewSetContentScaleFactor(webView.get(), 0.5);
+ WKViewSetContentPosition(webView.get(), WKPointMake(0, 0));
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0));
+ EXPECT_EQ(out.x, 0);
+ EXPECT_EQ(out.y, 0);
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10));
+ EXPECT_EQ(out.x, 20);
+ EXPECT_EQ(out.y, 20);
+
+ WKViewSetContentPosition(webView.get(), WKPointMake(20, 20));
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0));
+ EXPECT_EQ(out.x, 20);
+ EXPECT_EQ(out.y, 20);
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10));
+ EXPECT_EQ(out.x, 40);
+ EXPECT_EQ(out.y, 40);
+
+ // Let's add translation to the viewport.
+
+ const int delta = 10;
+ WKViewSetUserViewportTranslation(webView.get(), delta, delta);
+
+ WKViewSetContentPosition(webView.get(), WKPointMake(0, 0));
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0));
+ EXPECT_EQ(out.x, 0 - delta / 0.5);
+ EXPECT_EQ(out.y, 0 - delta / 0.5);
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10));
+ EXPECT_EQ(out.x, 20 - delta / 0.5);
+ EXPECT_EQ(out.y, 20 - delta / 0.5);
+
+ WKViewSetContentPosition(webView.get(), WKPointMake(20, 20));
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0));
+ EXPECT_EQ(out.x, 20 - delta / 0.5);
+ EXPECT_EQ(out.y, 20 - delta / 0.5);
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10));
+ EXPECT_EQ(out.x, 40 - delta / 0.5);
+ EXPECT_EQ(out.y, 40 - delta / 0.5);
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/backforward1.html b/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/backforward1.html
new file mode 100644
index 000000000..98c1c107c
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/backforward1.html
@@ -0,0 +1,5 @@
+<html>
+<body style="width:100%; height:100%">
+ <div style="position: absolute; top: 0; left: 0; width: 900px; height: 1200px;"></div>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/backforward2.html b/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/backforward2.html
new file mode 100644
index 000000000..3806b9d32
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/backforward2.html
@@ -0,0 +1 @@
+<body style="width:100%; height:100%"/>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic.cpp
index 06abe884b..c336652ac 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic.cpp
@@ -24,10 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
#include <wtf/Vector.h>
namespace TestWebKitAPI {
@@ -133,3 +136,5 @@ TEST(WebKit2, DISABLED_DOMWindowExtensionBasic)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic_Bundle.cpp
index 5c946625a..9bdc683ba 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic_Bundle.cpp
@@ -24,14 +24,17 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
-#include <WebKit2/WKBundleDOMWindowExtension.h>
-#include <WebKit2/WKBundleFrame.h>
-#include <WebKit2/WKBundlePage.h>
-#include <WebKit2/WKBundlePageGroup.h>
-#include <WebKit2/WKBundlePrivate.h>
-#include <WebKit2/WKBundleScriptWorld.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKBundleDOMWindowExtension.h>
+#include <WebKit/WKBundleFrame.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundlePageGroup.h>
+#include <WebKit/WKBundlePrivate.h>
+#include <WebKit/WKBundleScriptWorld.h>
+#include <WebKit/WKRetainPtr.h>
#include <wtf/HashMap.h>
#include <assert.h>
@@ -257,3 +260,5 @@ static void willDestroyGlobalObjectForDOMWindowExtensionCallback(WKBundlePageRef
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache.cpp
index c5f6104f6..56a069fb9 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache.cpp
@@ -24,6 +24,9 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
@@ -132,3 +135,5 @@ TEST(WebKit2, DISABLED_DOMWindowExtensionNoCache)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache_Bundle.cpp
index 680c17288..e48dadd1e 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache_Bundle.cpp
@@ -24,14 +24,17 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
-#include <WebKit2/WKBundleDOMWindowExtension.h>
-#include <WebKit2/WKBundleFrame.h>
-#include <WebKit2/WKBundlePage.h>
-#include <WebKit2/WKBundlePageGroup.h>
-#include <WebKit2/WKBundlePrivate.h>
-#include <WebKit2/WKBundleScriptWorld.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKBundleDOMWindowExtension.h>
+#include <WebKit/WKBundleFrame.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundlePageGroup.h>
+#include <WebKit/WKBundlePrivate.h>
+#include <WebKit/WKBundleScriptWorld.h>
+#include <WebKit/WKRetainPtr.h>
#include <wtf/HashMap.h>
#include <assert.h>
@@ -276,3 +279,5 @@ static void willDestroyGlobalObjectForDOMWindowExtensionCallback(WKBundlePageRef
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/DidAssociateFormControls.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/DidAssociateFormControls.cpp
index a78b8867f..a930f5346 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/DidAssociateFormControls.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/DidAssociateFormControls.cpp
@@ -24,6 +24,9 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
@@ -83,3 +86,5 @@ TEST(WebKit2, DidAssociateFormControls)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/DidAssociateFormControls_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/DidAssociateFormControls_Bundle.cpp
index fd373d282..5dcd91da8 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/DidAssociateFormControls_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/DidAssociateFormControls_Bundle.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKBundle.h>
-#include <WebKit2/WKBundlePage.h>
+#include <WebKit/WKBundle.h>
+#include <WebKit/WKBundlePage.h>
namespace TestWebKitAPI {
@@ -54,7 +57,7 @@ static void didAssociateFormControls(WKBundlePageRef page, WKArrayRef elementHan
WKRetainPtr<WKUInt64Ref> numberOfElements = adoptWK(WKUInt64Create(WKArrayGetSize(elementHandles)));
WKDictionarySetItem(messageBody.get(), Util::toWK("NumberOfControls").get(), numberOfElements.get());
- WKBundlePostMessage(InjectedBundleController::shared().bundle(), Util::toWK("DidReceiveDidAssociateFormControls").get(), messageBody.get());
+ WKBundlePostMessage(InjectedBundleController::singleton().bundle(), Util::toWK("DidReceiveDidAssociateFormControls").get(), messageBody.get());
}
DidAssociateFormControlsTest::DidAssociateFormControlsTest(const std::string& identifier)
@@ -76,3 +79,5 @@ void DidAssociateFormControlsTest::didCreatePage(WKBundleRef bundle, WKBundlePag
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/DidNotHandleKeyDown.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/DidNotHandleKeyDown.cpp
index e0c5cb0d8..b5f4fb863 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/DidNotHandleKeyDown.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/DidNotHandleKeyDown.cpp
@@ -24,10 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "JavaScriptTest.h"
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -76,3 +79,5 @@ TEST(WebKit2, DidNotHandleKeyDown)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/DocumentStartUserScriptAlertCrash.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/DocumentStartUserScriptAlertCrash.cpp
index efdcd56a7..21bca74dd 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/DocumentStartUserScriptAlertCrash.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/DocumentStartUserScriptAlertCrash.cpp
@@ -24,10 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -65,3 +68,5 @@ TEST(WebKit2, DocumentStartUserScriptAlertCrashTest)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/DocumentStartUserScriptAlertCrash_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/DocumentStartUserScriptAlertCrash_Bundle.cpp
index 30805f759..18b9f1b48 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/DocumentStartUserScriptAlertCrash_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/DocumentStartUserScriptAlertCrash_Bundle.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
-#include <WebKit2/WKBundlePageGroup.h>
-#include <WebKit2/WKBundlePrivate.h>
-#include <WebKit2/WKBundleScriptWorld.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKBundlePageGroup.h>
+#include <WebKit/WKBundlePrivate.h>
+#include <WebKit/WKBundleScriptWorld.h>
+#include <WebKit/WKRetainPtr.h>
#include <assert.h>
namespace TestWebKitAPI {
@@ -53,3 +56,5 @@ public:
static InjectedBundleTest::Register<DocumentStartUserScriptAlertCrashTest> registrar("DocumentStartUserScriptAlertCrashTest");
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/DownloadDecideDestinationCrash.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/DownloadDecideDestinationCrash.cpp
index aaead72dd..eac36d87a 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/DownloadDecideDestinationCrash.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/DownloadDecideDestinationCrash.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKDownload.h>
+#include <WebKit/WKDownload.h>
namespace TestWebKitAPI {
@@ -41,7 +44,7 @@ static WKStringRef decideDestinationWithSuggestedFilename(WKContextRef, WKDownlo
{
didDecideDestination = true;
WKDownloadCancel(download);
- return Util::toWK("does not matter").leakRef();
+ return Util::toWK("/tmp/WebKitAPITest/DownloadDecideDestinationCrash").leakRef();
}
static void setContextDownloadClient(WKContextRef context)
@@ -83,3 +86,5 @@ TEST(WebKit2, DownloadDecideDestinationCrash)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/EphemeralSessionPushStateNoHistoryCallback.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/EphemeralSessionPushStateNoHistoryCallback.cpp
new file mode 100644
index 000000000..07a81f646
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/EphemeralSessionPushStateNoHistoryCallback.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+#include <WebKit/WKRetainPtr.h>
+
+namespace TestWebKitAPI {
+
+static bool testDone;
+
+static void didNavigateWithNavigationData(WKContextRef context, WKPageRef page, WKNavigationDataRef navigationData, WKFrameRef frame, const void* clientInfo)
+{
+ // This should never be called when navigating in Private Browsing.
+ FAIL();
+}
+
+static void didSameDocumentNavigationForFrame(WKPageRef page, WKFrameRef frame, WKSameDocumentNavigationType type, WKTypeRef userData, const void *clientInfo)
+{
+ testDone = true;
+}
+
+TEST(WebKit2, EphemeralSessionPushStateNoHistoryCallback)
+{
+ WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+
+ WKContextHistoryClientV0 historyClient;
+ memset(&historyClient, 0, sizeof(historyClient));
+
+ historyClient.base.version = 0;
+ historyClient.didNavigateWithNavigationData = didNavigateWithNavigationData;
+
+ WKContextSetHistoryClient(context.get(), &historyClient.base);
+
+ PlatformWebView webView(context.get());
+
+ WKPageLoaderClientV0 pageLoaderClient;
+ memset(&pageLoaderClient, 0, sizeof(pageLoaderClient));
+
+ pageLoaderClient.base.version = 0;
+ pageLoaderClient.didSameDocumentNavigationForFrame = didSameDocumentNavigationForFrame;
+
+ WKPageSetPageLoaderClient(webView.page(), &pageLoaderClient.base);
+
+ WKSessionRef session = WKSessionCreate(true);
+ WKPageSetSession(webView.page(), session);
+
+ WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("push-state", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+
+ Util::run(&testDone);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/EvaluateJavaScript.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/EvaluateJavaScript.cpp
index 90ad04fd1..a6b5a4dd5 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/EvaluateJavaScript.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/EvaluateJavaScript.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKRetainPtr.h>
-#include <WebKit2/WKSerializedScriptValue.h>
+#include <WebKit/WKRetainPtr.h>
+#include <WebKit/WKSerializedScriptValue.h>
namespace TestWebKitAPI {
@@ -58,3 +61,5 @@ TEST(WebKit2, EvaluateJavaScriptThatThrowsAnException)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/FailedLoad.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/FailedLoad.cpp
index ac8d6a39d..c12b5366b 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/FailedLoad.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/FailedLoad.cpp
@@ -24,10 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -65,3 +68,5 @@ TEST(WebKit2, FailedLoad)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/Find.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/Find.cpp
index 41b52eacd..2e2189906 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/Find.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/Find.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -79,3 +82,5 @@ TEST(WebKit2, Find)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ForceRepaint.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ForceRepaint.cpp
index 86c6754a2..6cd63fab4 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/ForceRepaint.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ForceRepaint.cpp
@@ -24,10 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -67,3 +70,5 @@ TEST(WebKit2, ForceRepaint)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypeHTML.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypeHTML.cpp
index 093a5747b..2c9c11332 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypeHTML.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypeHTML.cpp
@@ -24,10 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -75,3 +78,5 @@ TEST(WebKit2, FrameMIMETypeHTML)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypePNG.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypePNG.cpp
index edaa7cada..eb3bf38a3 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypePNG.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypePNG.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -74,3 +77,5 @@ TEST(WebKit2, FrameMIMETypePNG)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/Geolocation.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/Geolocation.cpp
index bf7a93726..90fd37937 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/Geolocation.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/Geolocation.cpp
@@ -24,10 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKContextPrivate.h>
+#include <WebKit/WKRetainPtr.h>
#include <string.h>
#include <vector>
@@ -103,7 +107,7 @@ void decidePolicyForGeolocationPermissionRequestCallBack(WKPageRef page, WKFrame
void setupGeolocationProvider(WKContextRef context, void *clientInfo)
{
WKGeolocationProviderV1 providerCallback;
- memset(&providerCallback, 0, sizeof(WKGeolocationProvider));
+ memset(&providerCallback, 0, sizeof(WKGeolocationProviderV1));
providerCallback.base.version = 1;
providerCallback.base.clientInfo = clientInfo;
@@ -209,14 +213,9 @@ TEST(WebKit2, GeolocationBasicWithHighAccuracy)
// Geolocation start without High Accuracy, then requires High Accuracy.
struct GeolocationTransitionToHighAccuracyStateTracker : GeolocationStateTracker {
- bool finishedFirstStep;
- bool finished;
-
- GeolocationTransitionToHighAccuracyStateTracker()
- : finishedFirstStep(false)
- , finished(false)
- {
- }
+ bool finishedFirstStep { false };
+ bool enabledHighAccuracy { false };
+ bool finished { false };
virtual void eventsChanged()
{
@@ -230,11 +229,19 @@ struct GeolocationTransitionToHighAccuracyStateTracker : GeolocationStateTracker
break;
case 3:
EXPECT_EQ(GeolocationEvent::EnableHighAccuracy, events[2]);
+ enabledHighAccuracy = true;
+ break;
+ case 4:
+ EXPECT_EQ(GeolocationEvent::DisableHighAccuracy, events[3]);
+ break;
+ case 5:
+ EXPECT_EQ(GeolocationEvent::StopUpdating, events[4]);
finished = true;
break;
default:
EXPECT_TRUE(false);
finishedFirstStep = true;
+ enabledHighAccuracy = true;
finished = true;
}
}
@@ -243,6 +250,7 @@ struct GeolocationTransitionToHighAccuracyStateTracker : GeolocationStateTracker
TEST(WebKit2, GeolocationTransitionToHighAccuracy)
{
WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+ WKContextSetMaximumNumberOfProcesses(context.get(), 1);
GeolocationTransitionToHighAccuracyStateTracker stateTracker;
setupGeolocationProvider(context.get(), &stateTracker);
@@ -257,19 +265,20 @@ TEST(WebKit2, GeolocationTransitionToHighAccuracy)
setupView(highAccuracyWebView);
WKRetainPtr<WKURLRef> highAccuracyURL(AdoptWK, Util::createURLForResource("geolocationWatchPositionWithHighAccuracy", "html"));
WKPageLoadURL(highAccuracyWebView.page(), highAccuracyURL.get());
+ Util::run(&stateTracker.enabledHighAccuracy);
+
+ WKRetainPtr<WKURLRef> resetUrl = adoptWK(WKURLCreateWithUTF8CString("about:blank"));
+ WKPageLoadURL(highAccuracyWebView.page(), resetUrl.get());
+ Util::run(&stateTracker.enabledHighAccuracy);
+ WKPageLoadURL(lowAccuracyWebView.page(), resetUrl.get());
Util::run(&stateTracker.finished);
}
// Geolocation start with High Accuracy, then should fall back to low accuracy.
struct GeolocationTransitionToLowAccuracyStateTracker : GeolocationStateTracker {
- bool finishedFirstStep;
- bool finished;
-
- GeolocationTransitionToLowAccuracyStateTracker()
- : finishedFirstStep(false)
- , finished(false)
- {
- }
+ bool finishedFirstStep { false };
+ bool disabledHighAccuracy { false };
+ bool finished { false };
virtual void eventsChanged()
{
@@ -283,11 +292,16 @@ struct GeolocationTransitionToLowAccuracyStateTracker : GeolocationStateTracker
break;
case 3:
EXPECT_EQ(GeolocationEvent::DisableHighAccuracy, events[2]);
+ disabledHighAccuracy = true;
+ break;
+ case 4:
+ EXPECT_EQ(GeolocationEvent::StopUpdating, events[3]);
finished = true;
break;
default:
EXPECT_TRUE(false);
finishedFirstStep = true;
+ disabledHighAccuracy = true;
finished = true;
}
}
@@ -301,6 +315,7 @@ static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef us
TEST(WebKit2, GeolocationTransitionToLowAccuracy)
{
WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+ WKContextSetMaximumNumberOfProcesses(context.get(), 1);
GeolocationTransitionToLowAccuracyStateTracker stateTracker;
setupGeolocationProvider(context.get(), &stateTracker);
@@ -331,7 +346,11 @@ TEST(WebKit2, GeolocationTransitionToLowAccuracy)
WKRetainPtr<WKURLRef> resetUrl = adoptWK(WKURLCreateWithUTF8CString("about:blank"));
WKPageLoadURL(highAccuracyWebView.page(), resetUrl.get());
+ Util::run(&stateTracker.disabledHighAccuracy);
+ WKPageLoadURL(lowAccuracyWebView.page(), resetUrl.get());
Util::run(&stateTracker.finished);
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback.cpp
index fe898ffa8..e3280a3b7 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -65,3 +68,5 @@ TEST(WebKit2, GetInjectedBundleInitializationUserDataCallback)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback_Bundle.cpp
index 97500b59b..bf8da42e3 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback_Bundle.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -46,3 +49,5 @@ public:
static InjectedBundleTest::Register<GetInjectedBundleInitializationUserDataCallbackTest> registrar("GetInjectedBundleInitializationUserDataCallbackTest");
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/HitTestResultNodeHandle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/HitTestResultNodeHandle.cpp
index 2f7c7deed..1f4a3726c 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/HitTestResultNodeHandle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/HitTestResultNodeHandle.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -86,3 +89,5 @@ TEST(WebKit2, HitTestResultNodeHandle)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/HitTestResultNodeHandle_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/HitTestResultNodeHandle_Bundle.cpp
index c6aaa1fec..d68ff2193 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/HitTestResultNodeHandle_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/HitTestResultNodeHandle_Bundle.cpp
@@ -24,12 +24,15 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "InjectedBundleController.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKBundlePage.h>
-#include <WebKit2/WKBundleHitTestResult.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundleHitTestResult.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -46,7 +49,7 @@ public:
if (!nodeHandle)
return;
- WKBundlePostMessage(InjectedBundleController::shared().bundle(), Util::toWK("HitTestResultNodeHandleTestDoneMessageName").get(), Util::toWK("HitTestResultNodeHandleTestDoneMessageBody").get());
+ WKBundlePostMessage(InjectedBundleController::singleton().bundle(), Util::toWK("HitTestResultNodeHandleTestDoneMessageName").get(), Util::toWK("HitTestResultNodeHandleTestDoneMessageBody").get());
}
virtual void didCreatePage(WKBundleRef bundle, WKBundlePageRef page)
@@ -64,3 +67,5 @@ public:
static InjectedBundleTest::Register<HitTestResultNodeHandleTest> registrar("HitTestResultNodeHandleTest");
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic.cpp
index 1b3b3b7b6..a1d4046ed 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -77,3 +80,5 @@ TEST(WebKit2, InjectedBundleBasic)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic_Bundle.cpp
index 6a597be41..4d8689b93 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic_Bundle.cpp
@@ -24,8 +24,11 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -47,3 +50,5 @@ public:
static InjectedBundleTest::Register<InjectedBundleBasicTest> registrar("InjectedBundleBasicTest");
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleFrameHitTest.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleFrameHitTest.cpp
index acc76c01e..e178dc3cb 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleFrameHitTest.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleFrameHitTest.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -66,3 +69,5 @@ TEST(WebKit2, InjectedBundleFrameHitTest)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleFrameHitTest_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleFrameHitTest_Bundle.cpp
index 6ae018765..14806685e 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleFrameHitTest_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleFrameHitTest_Bundle.cpp
@@ -24,13 +24,16 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKBundle.h>
-#include <WebKit2/WKBundleFramePrivate.h>
-#include <WebKit2/WKBundleHitTestResult.h>
-#include <WebKit2/WKBundlePage.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKBundle.h>
+#include <WebKit/WKBundleFramePrivate.h>
+#include <WebKit/WKBundleHitTestResult.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -76,3 +79,5 @@ void InjectedBundleFrameHitTestTest::frameLoadFinished(WKBundleFrameRef frame)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins.cpp
index 407ecceb5..678aaa85b 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -67,3 +70,5 @@ TEST(WebKit2, InjectedBundleInitializationUserDataCallbackWins)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins_Bundle.cpp
index 36708a4d7..cac7738dd 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins_Bundle.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -46,3 +49,5 @@ public:
static InjectedBundleTest::Register<InjectedBundleInitializationUserDataCallbackWinsTest> registrar("InjectedBundleInitializationUserDataCallbackWinsTest");
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleMakeAllShadowRootOpen_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleMakeAllShadowRootOpen_Bundle.cpp
new file mode 100644
index 000000000..4a923dba9
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleMakeAllShadowRootOpen_Bundle.cpp
@@ -0,0 +1,65 @@
+/*
+ * 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
+ * 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"
+
+#if WK_HAVE_C_SPI
+
+#include "InjectedBundleTest.h"
+#include <WebKit/WKBundlePageGroup.h>
+#include <WebKit/WKBundlePrivate.h>
+#include <WebKit/WKBundleScriptWorld.h>
+#include <WebKit/WKRetainPtr.h>
+#include <assert.h>
+
+namespace TestWebKitAPI {
+
+class InjectedBundleMakeAllShadowRootOpenTest : public InjectedBundleTest {
+public:
+ InjectedBundleMakeAllShadowRootOpenTest(const std::string& identifier)
+ : InjectedBundleTest(identifier)
+ { }
+
+ virtual void initialize(WKBundleRef bundle, WKTypeRef userData)
+ {
+ assert(WKGetTypeID(userData) == WKBundlePageGroupGetTypeID());
+ WKBundlePageGroupRef pageGroup = static_cast<WKBundlePageGroupRef>(userData);
+
+ auto world = WKBundleScriptWorldCreateWorld();
+ WKBundleScriptWorldMakeAllShadowRootsOpen(world);
+
+ WKRetainPtr<WKStringRef> source(AdoptWK, WKStringCreateWithUTF8CString(
+ "var element = document.createElement('div');"
+ "element.attachShadow({mode: 'closed'});"
+ "alert(element.shadowRoot ? 'PASS' : 'FAIL');"));
+ WKBundleAddUserScript(bundle, pageGroup, world, source.get(), 0, 0, 0, kWKInjectAtDocumentStart, kWKInjectInAllFrames);
+ }
+};
+
+static InjectedBundleTest::Register<InjectedBundleMakeAllShadowRootOpenTest> registrar("InjectedBundleMakeAllShadowRootOpenTest");
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleMakeAllShadowRootsOpen.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleMakeAllShadowRootsOpen.cpp
new file mode 100644
index 000000000..982e6964e
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleMakeAllShadowRootsOpen.cpp
@@ -0,0 +1,72 @@
+/*
+ * 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
+ * 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"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+#include <WebKit/WKRetainPtr.h>
+
+namespace TestWebKitAPI {
+
+static bool done;
+
+static void runJavaScriptAlert(WKPageRef page, WKStringRef alertText, WKFrameRef frame, const void* clientInfo)
+{
+ ASSERT_NOT_NULL(frame);
+
+ EXPECT_EQ(page, WKFrameGetPage(frame));
+ EXPECT_WK_STREQ("PASS", alertText);
+
+ done = true;
+}
+
+TEST(WebKit2, InjectedBundleMakeAllShadowRootOpenTest)
+{
+ WKRetainPtr<WKPageGroupRef> pageGroup(AdoptWK, WKPageGroupCreateWithIdentifier(WKStringCreateWithUTF8CString("InjectedBundleMakeAllShadowRootOpenTestPageGroup")));
+
+ WKRetainPtr<WKContextRef> context(AdoptWK, Util::createContextForInjectedBundleTest("InjectedBundleMakeAllShadowRootOpenTest", pageGroup.get()));
+ PlatformWebView webView(context.get(), pageGroup.get());
+
+ WKPageUIClientV0 uiClient;
+ memset(&uiClient, 0, sizeof(uiClient));
+
+ uiClient.base.version = 0;
+ uiClient.runJavaScriptAlert = runJavaScriptAlert;
+
+ WKPageSetPageUIClient(webView.page(), &uiClient.base);
+
+ WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("simple", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+
+ Util::run(&done);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/LayoutMilestonesWithAllContentInFrame.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/LayoutMilestonesWithAllContentInFrame.cpp
index ef53f5e91..aa294643c 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/LayoutMilestonesWithAllContentInFrame.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/LayoutMilestonesWithAllContentInFrame.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKContextPrivate.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKContextPrivate.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -64,3 +67,5 @@ TEST(WebKit2, LayoutMilestonesWithAllContentInFrame)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/LoadAlternateHTMLStringWithNonDirectoryURL.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/LoadAlternateHTMLStringWithNonDirectoryURL.cpp
index def60bcb9..acc23348b 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/LoadAlternateHTMLStringWithNonDirectoryURL.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/LoadAlternateHTMLStringWithNonDirectoryURL.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2015 Igalia S.L.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -24,13 +25,16 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "JavaScriptTest.h"
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKContext.h>
-#include <WebKit2/WKPage.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKContext.h>
+#include <WebKit/WKPage.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -41,7 +45,7 @@ static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef us
didFinishLoad = true;
}
-TEST(WebKit2, LoadAlternateHTMLStringWithNonDirectoryURL)
+static void loadAlternateHTMLString(WKURLRef baseURL, WKURLRef unreachableURL)
{
WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
PlatformWebView webView(context.get());
@@ -53,14 +57,29 @@ TEST(WebKit2, LoadAlternateHTMLStringWithNonDirectoryURL)
loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
WKPageSetPageLoaderClient(webView.page(), &loaderClient.base);
- WKRetainPtr<WKURLRef> fileURL(AdoptWK, Util::createURLForResource("simple", "html"));
WKRetainPtr<WKStringRef> alternateHTMLString(AdoptWK, WKStringCreateWithUTF8CString("<html><body><img src='icon.png'></body></html>"));
-
- // Call WKPageLoadAlternateHTMLString() with fileURL which does not point to a directory
- WKPageLoadAlternateHTMLString(webView.page(), alternateHTMLString.get(), fileURL.get(), fileURL.get());
-
+ WKPageLoadAlternateHTMLString(webView.page(), alternateHTMLString.get(), baseURL, unreachableURL);
+
// If we can finish loading the html without resulting in an invalid message being sent from the WebProcess, this test passes.
Util::run(&didFinishLoad);
}
+TEST(WebKit2, LoadAlternateHTMLStringWithNonDirectoryURL)
+{
+ // Call WKPageLoadAlternateHTMLString() with fileURL which does not point to a directory.
+ WKRetainPtr<WKURLRef> fileURL(AdoptWK, Util::createURLForResource("simple", "html"));
+ loadAlternateHTMLString(fileURL.get(), fileURL.get());
+}
+
+TEST(WebKit2, LoadAlternateHTMLStringWithEmptyBaseURL)
+{
+ // Call WKPageLoadAlternateHTMLString() with empty baseURL to make sure this test works
+ // when baseURL does not grant read access to the unreachableURL. We use a separate test
+ // to ensure the previous test does not pollute the result.
+ WKRetainPtr<WKURLRef> unreachableURL(AdoptWK, Util::URLForNonExistentResource());
+ loadAlternateHTMLString(nullptr, unreachableURL.get());
+}
+
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/LoadCanceledNoServerRedirectCallback.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/LoadCanceledNoServerRedirectCallback.cpp
index abf447155..ac45fba26 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/LoadCanceledNoServerRedirectCallback.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/LoadCanceledNoServerRedirectCallback.cpp
@@ -24,13 +24,16 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "JavaScriptTest.h"
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKContext.h>
-#include <WebKit2/WKFrame.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKContext.h>
+#include <WebKit/WKFrame.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -93,3 +96,5 @@ TEST(WebKit2, LoadCanceledNoServerRedirectCallback)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/LoadCanceledNoServerRedirectCallback_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/LoadCanceledNoServerRedirectCallback_Bundle.cpp
index 13aa1106e..6ea0dc77d 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/LoadCanceledNoServerRedirectCallback_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/LoadCanceledNoServerRedirectCallback_Bundle.cpp
@@ -24,13 +24,16 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
#include "Test.h"
-#include <WebKit2/WKBundlePage.h>
-#include <WebKit2/WKBundleFrame.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundleFrame.h>
+#include <WebKit/WKRetainPtr.h>
#include <wtf/Assertions.h>
@@ -70,3 +73,5 @@ public:
static InjectedBundleTest::Register<LoadCanceledNoServerRedirectCallbackTest> registrar("LoadCanceledNoServerRedirectCallbackTest");
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/LoadPageOnCrash.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/LoadPageOnCrash.cpp
index 3228d084a..63ad664e2 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/LoadPageOnCrash.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/LoadPageOnCrash.cpp
@@ -24,10 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -103,3 +106,5 @@ TEST(WebKit2, LoadPageAfterCrash)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/MenuTypesForMouseEvents.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/MenuTypesForMouseEvents.cpp
new file mode 100644
index 000000000..f77a11ad8
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/MenuTypesForMouseEvents.cpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "JavaScriptTest.h"
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+
+namespace TestWebKitAPI {
+
+static bool didFinishLoad;
+
+static void didFinishLoadForFrame(WKPageRef, WKFrameRef, WKTypeRef, const void*)
+{
+ didFinishLoad = true;
+}
+
+static void setPageLoaderClient(WKPageRef page)
+{
+ WKPageLoaderClientV0 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+
+ loaderClient.base.version = 0;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+
+ WKPageSetPageLoaderClient(page, &loaderClient.base);
+}
+
+static void buildAndPerformTest(WKEventMouseButton button, WKEventModifiers modifiers, const char* expectedButton, const char* expectedMenuType)
+{
+ WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+ PlatformWebView webView(context.get());
+ setPageLoaderClient(webView.page());
+
+ WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("mouse-button-listener", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+ Util::run(&didFinishLoad);
+
+ didFinishLoad = false;
+
+ webView.simulateButtonClick(button, 10, 10, modifiers);
+
+ EXPECT_JS_EQ(webView.page(), "pressedMouseButton()", expectedButton);
+ EXPECT_JS_EQ(webView.page(), "displayedMenu()", expectedMenuType);
+}
+
+TEST(WebKit2, MenuAndButtonForNormalLeftClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonLeftButton, 0, "0", "none");
+}
+
+TEST(WebKit2, MenuAndButtonForNormalRightClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonRightButton, 0, "2", "context");
+}
+
+TEST(WebKit2, MenuAndButtonForNormalMiddleClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonMiddleButton, 0, "1", "none");
+}
+
+TEST(WebKit2, MenuAndButtonForControlLeftClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonLeftButton, kWKEventModifiersControlKey, "0", "context");
+}
+
+TEST(WebKit2, MenuAndButtonForControlRightClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonRightButton, kWKEventModifiersControlKey, "2", "context");
+}
+
+TEST(WebKit2, MenuAndButtonForControlMiddleClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonMiddleButton, kWKEventModifiersControlKey, "1", "none");
+}
+
+TEST(WebKit2, MenuAndButtonForShiftLeftClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonLeftButton, kWKEventModifiersShiftKey, "0", "none");
+}
+
+TEST(WebKit2, MenuAndButtonForShiftRightClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonRightButton, kWKEventModifiersShiftKey, "2", "context");
+}
+
+TEST(WebKit2, MenuAndButtonForShiftMiddleClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonMiddleButton, kWKEventModifiersShiftKey, "1", "none");
+}
+
+TEST(WebKit2, MenuAndButtonForCommandLeftClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonLeftButton, kWKEventModifiersMetaKey, "0", "none");
+}
+
+TEST(WebKit2, MenuAndButtonForCommandRightClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonRightButton, kWKEventModifiersMetaKey, "2", "context");
+}
+
+TEST(WebKit2, MenuAndButtonForCommandMiddleClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonMiddleButton, kWKEventModifiersMetaKey, "1", "none");
+}
+
+TEST(WebKit2, MenuAndButtonForAltLeftClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonLeftButton, kWKEventModifiersAltKey, "0", "none");
+}
+
+TEST(WebKit2, MenuAndButtonForAltRightClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonRightButton, kWKEventModifiersAltKey, "2", "context");
+}
+
+TEST(WebKit2, MenuAndButtonForAltMiddleClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonMiddleButton, kWKEventModifiersAltKey, "1", "none");
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ModalAlertsSPI.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ModalAlertsSPI.cpp
new file mode 100644
index 000000000..0278f005b
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ModalAlertsSPI.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+#include <WebKit/WKFrame.h>
+#include <WebKit/WKRetainPtr.h>
+#include <WebKit/WKSecurityOriginRef.h>
+
+namespace TestWebKitAPI {
+
+static bool done;
+static unsigned dialogsSeen;
+static const unsigned dialogsExpected = 3;
+
+static void analyzeDialogArguments(WKPageRef page, WKFrameRef frame, WKSecurityOriginRef securityOrigin)
+{
+ EXPECT_EQ(page, WKFrameGetPage(frame));
+
+ WKRetainPtr<WKURLRef> url = adoptWK(WKFrameCopyURL(frame));
+ WKRetainPtr<WKStringRef> urlString = adoptWK(WKURLCopyString(url.get()));
+ EXPECT_WK_STREQ("about:blank", urlString.get());
+
+ WKRetainPtr<WKStringRef> protocol = adoptWK(WKSecurityOriginCopyProtocol(securityOrigin));
+ EXPECT_WK_STREQ("file", protocol.get());
+
+ WKRetainPtr<WKStringRef> host = adoptWK(WKSecurityOriginCopyHost(securityOrigin));
+ EXPECT_WK_STREQ("", host.get());
+
+ EXPECT_EQ(WKSecurityOriginGetPort(securityOrigin), 0);
+
+ if (++dialogsSeen == dialogsExpected)
+ done = true;
+}
+
+static void runJavaScriptAlert(WKPageRef page, WKStringRef, WKFrameRef frame, WKSecurityOriginRef securityOrigin, const void*)
+{
+ analyzeDialogArguments(page, frame, securityOrigin);
+}
+
+static bool runJavaScriptConfirm(WKPageRef page, WKStringRef, WKFrameRef frame, WKSecurityOriginRef securityOrigin, const void*)
+{
+ analyzeDialogArguments(page, frame, securityOrigin);
+ return false;
+}
+
+static WKStringRef runJavaScriptPrompt(WKPageRef page, WKStringRef, WKStringRef, WKFrameRef frame, WKSecurityOriginRef securityOrigin, const void*)
+{
+ analyzeDialogArguments(page, frame, securityOrigin);
+ return nullptr;
+}
+
+static std::unique_ptr<PlatformWebView> openedWebView;
+
+static WKPageRef createNewPage(WKPageRef page, WKURLRequestRef urlRequest, WKDictionaryRef features, WKEventModifiers modifiers, WKEventMouseButton mouseButton, const void *clientInfo)
+{
+ EXPECT_TRUE(openedWebView == nullptr);
+
+ openedWebView = std::make_unique<PlatformWebView>(page);
+
+ WKPageUIClientV5 uiClient;
+ memset(&uiClient, 0, sizeof(uiClient));
+
+ uiClient.base.version = 5;
+ uiClient.runJavaScriptAlert = runJavaScriptAlert;
+ uiClient.runJavaScriptConfirm = runJavaScriptConfirm;
+ uiClient.runJavaScriptPrompt = runJavaScriptPrompt;
+
+ WKPageSetPageUIClient(openedWebView->page(), &uiClient.base);
+
+ WKRetain(openedWebView->page());
+ return openedWebView->page();
+}
+
+TEST(WebKit2, ModalAlertsSPI)
+{
+ WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreate());
+ PlatformWebView webView(context.get());
+
+ WKPageUIClientV5 uiClient;
+ memset(&uiClient, 0, sizeof(uiClient));
+
+ uiClient.base.version = 5;
+ uiClient.createNewPage = createNewPage;
+
+ WKPageSetPageUIClient(webView.page(), &uiClient.base);
+
+ WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("modal-alerts-in-new-about-blank-window", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+
+ Util::run(&done);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/MouseMoveAfterCrash.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/MouseMoveAfterCrash.cpp
index b75be6a1a..9d7f3997d 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/MouseMoveAfterCrash.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/MouseMoveAfterCrash.cpp
@@ -24,6 +24,9 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "JavaScriptTest.h"
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
@@ -48,11 +51,7 @@ static void setPageLoaderClient(WKPageRef page)
WKPageSetPageLoaderClient(page, &loaderClient.base);
}
-#if PLATFORM(WIN)
-TEST(WebKit2, DISABLED_MouseMoveAfterCrash)
-#else
TEST(WebKit2, MouseMoveAfterCrash)
-#endif
{
WKRetainPtr<WKContextRef> context = adoptWK(Util::createContextForInjectedBundleTest("MouseMoveAfterCrashTest"));
@@ -90,3 +89,5 @@ TEST(WebKit2, MouseMoveAfterCrash)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/MouseMoveAfterCrash_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/MouseMoveAfterCrash_Bundle.cpp
index a07562093..8d92f4209 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/MouseMoveAfterCrash_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/MouseMoveAfterCrash_Bundle.cpp
@@ -24,6 +24,9 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
@@ -54,3 +57,5 @@ void MouseMoveAfterCrashTest::didReceiveMessage(WKBundleRef bundle, WKStringRef
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout.cpp
index 640a825f8..778d285ba 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKContextPrivate.h>
+#include <WebKit/WKContextPrivate.h>
namespace TestWebKitAPI {
@@ -86,3 +89,5 @@ TEST(WebKit2, DISABLED_NewFirstVisuallyNonEmptyLayout)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails.cpp
index 1568b7663..5cff318fa 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKContextPrivate.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKContextPrivate.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -86,3 +89,5 @@ TEST(WebKit2, NewFirstVisuallyNonEmptyLayoutFails)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails_Bundle.cpp
index b909ec941..2700d66c8 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails_Bundle.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKBundlePage.h>
-#include <WebKit2/WKBundlePagePrivate.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundlePagePrivate.h>
namespace TestWebKitAPI {
@@ -49,3 +52,5 @@ public:
static InjectedBundleTest::Register<NewFirstVisuallyNonEmptyLayoutFailsTest> registrar("NewFirstVisuallyNonEmptyLayoutFailsTest");
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages.cpp
index 11fc17ebd..7bd1fd7b3 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKContextPrivate.h>
+#include <WebKit/WKContextPrivate.h>
namespace TestWebKitAPI {
@@ -86,3 +89,5 @@ TEST(WebKit2, DISABLED_NewFirstVisuallyNonEmptyLayoutForImages)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages_Bundle.cpp
index bdaade77b..d8644bb69 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages_Bundle.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKBundlePage.h>
-#include <WebKit2/WKBundlePagePrivate.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundlePagePrivate.h>
namespace TestWebKitAPI {
@@ -49,3 +52,5 @@ public:
static InjectedBundleTest::Register<NewFirstVisuallyNonEmptyLayoutForImagesTest> registrar("NewFirstVisuallyNonEmptyLayoutForImagesTest");
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames.cpp
index 04d6ee448..c7b24680e 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKContextPrivate.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKContextPrivate.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -64,7 +67,7 @@ static void setPageLoaderClient(WKPageRef page)
WKPageLoaderClientV3 loaderClient;
memset(&loaderClient, 0, sizeof(loaderClient));
- loaderClient.base.version = kWKPageLoaderClientCurrentVersion;
+ loaderClient.base.version = 3;
loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
loaderClient.didLayout = didLayout;
@@ -90,3 +93,5 @@ TEST(WebKit2, NewFirstVisuallyNonEmptyLayoutFrames)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp
index 33e16bd3e..f66fc957d 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKBundlePage.h>
-#include <WebKit2/WKBundlePagePrivate.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundlePagePrivate.h>
namespace TestWebKitAPI {
@@ -49,3 +52,5 @@ public:
static InjectedBundleTest::Register<NewFirstVisuallyNonEmptyLayoutFramesTest> registrar("NewFirstVisuallyNonEmptyLayoutFramesTest");
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout_Bundle.cpp
index c408c3b2c..8f1901d10 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout_Bundle.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKBundlePage.h>
-#include <WebKit2/WKBundlePagePrivate.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundlePagePrivate.h>
namespace TestWebKitAPI {
@@ -49,3 +52,5 @@ public:
static InjectedBundleTest::Register<NewFirstVisuallyNonEmptyLayoutTest> registrar("NewFirstVisuallyNonEmptyLayoutTest");
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/PageLoadBasic.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/PageLoadBasic.cpp
index 26a6fddfd..ad62a5b29 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/PageLoadBasic.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/PageLoadBasic.cpp
@@ -24,10 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -108,6 +111,7 @@ static void decidePolicyForResponse(WKPageRef page, WKFrameRef frame, WKURLRespo
WKFramePolicyListenerUse(listener);
}
+// FIXME: http://webkit.org/b/127934 REGRESSION (r163037): WebKit2.PageLoadBasic API test failing on Mountain Lion
TEST(WebKit2, PageLoadBasic)
{
State state;
@@ -151,4 +155,26 @@ TEST(WebKit2, PageLoadBasic)
Util::run(&test1Done);
}
+TEST(WebKit2, PageReload)
+{
+ WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+ PlatformWebView webView(context.get());
+
+ // Reload test before url loading.
+ WKPageReload(webView.page());
+ WKPageReload(webView.page());
+
+ WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("simple", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+
+ // Reload test after url loading.
+ WKPageReload(webView.page());
+
+ WKRetainPtr<WKURLRef> activeUrl = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeUrl.get());
+ EXPECT_TRUE(WKURLIsEqual(activeUrl.get(), url.get()));
+}
+
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/PageLoadDidChangeLocationWithinPageForFrame.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/PageLoadDidChangeLocationWithinPageForFrame.cpp
index 8ef9bb66d..46838db93 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/PageLoadDidChangeLocationWithinPageForFrame.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/PageLoadDidChangeLocationWithinPageForFrame.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -84,3 +87,5 @@ TEST(WebKit2, PageLoadDidChangeLocationWithinPageForFrame)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ParentFrame.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ParentFrame.cpp
index ec97ac0b0..7953608c8 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/ParentFrame.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ParentFrame.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKContextPrivate.h>
+#include <WebKit/WKContextPrivate.h>
namespace TestWebKitAPI {
@@ -68,3 +71,5 @@ TEST(WebKit2, ParentFrame)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ParentFrame_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ParentFrame_Bundle.cpp
index b23336293..e1da9ee02 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/ParentFrame_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ParentFrame_Bundle.cpp
@@ -24,12 +24,15 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKBundlePage.h>
-#include <WebKit2/WKBundleFrame.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundleFrame.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -77,3 +80,5 @@ void ParentFrameTest::didCreatePage(WKBundleRef bundle, WKBundlePageRef page)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/PasteboardNotifications_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/PasteboardNotifications_Bundle.cpp
new file mode 100644
index 000000000..8c1404e7a
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/PasteboardNotifications_Bundle.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "InjectedBundleTest.h"
+
+#include "PlatformUtilities.h"
+#include <WebKit/WKArray.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundleBackForwardListItem.h>
+#include <WebKit/WKWebArchive.h>
+
+namespace TestWebKitAPI {
+
+class PasteboardNotificationsTest : public InjectedBundleTest {
+public:
+ PasteboardNotificationsTest(const std::string& identifier);
+
+ virtual void didCreatePage(WKBundleRef, WKBundlePageRef);
+};
+
+static InjectedBundleTest::Register<PasteboardNotificationsTest> registrar("PasteboardNotificationsTest");
+
+static void willWriteToPasteboard(WKBundlePageRef page, WKBundleRangeHandleRef range, const void*)
+{
+ if (!range)
+ WKBundlePostMessage(InjectedBundleController::singleton().bundle(), Util::toWK("PasteboardNotificationTestDoneMessageName").get(), Util::toWK("willWritetoPasteboardFail").get());
+}
+
+static void getPasteboardDataForRange(WKBundlePageRef, WKBundleRangeHandleRef range, WKArrayRef* pasteboardTypes, WKArrayRef* pasteboardData, const void*)
+{
+ WKTypeRef typeName = WKStringCreateWithUTF8CString("AnotherArchivePasteboardType");
+ *pasteboardTypes = WKArrayCreateAdoptingValues(&typeName, 1);
+ WKTypeRef typeData = WKWebArchiveCopyData(WKWebArchiveCreateFromRange(range));
+ *pasteboardData = WKArrayCreateAdoptingValues(&typeData, 1);
+}
+
+static void didWriteToPasteboard(WKBundlePageRef, const void*)
+{
+ WKBundlePostMessage(InjectedBundleController::singleton().bundle(), Util::toWK("PasteboardNotificationTestDoneMessageName").get(), Util::toWK("didWriteToPasteboard").get());
+}
+
+PasteboardNotificationsTest::PasteboardNotificationsTest(const std::string& identifier)
+ : InjectedBundleTest(identifier)
+{
+}
+
+void PasteboardNotificationsTest::didCreatePage(WKBundleRef bundle, WKBundlePageRef page)
+{
+ WKBundlePageEditorClientV1 pageEditorClient;
+ memset(&pageEditorClient, 0, sizeof(pageEditorClient));
+
+ pageEditorClient.base.version = 1;
+ pageEditorClient.base.clientInfo = this;
+ pageEditorClient.willWriteToPasteboard = willWriteToPasteboard;
+ pageEditorClient.getPasteboardDataForRange = getPasteboardDataForRange;
+ pageEditorClient.didWriteToPasteboard = didWriteToPasteboard;
+
+ WKBundlePageSetEditorClient(page, &pageEditorClient.base);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/PendingAPIRequestURL.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/PendingAPIRequestURL.cpp
new file mode 100644
index 000000000..d02a5acf3
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/PendingAPIRequestURL.cpp
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 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 "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+#include <WebKit/WKRetainPtr.h>
+
+namespace TestWebKitAPI {
+
+static bool done;
+
+TEST(WebKit2, PendingAPIRequestURL)
+{
+ WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+ PlatformWebView webView(context.get());
+
+ WKPageLoaderClientV0 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+ loaderClient.base.version = 0;
+ loaderClient.didFinishLoadForFrame = [](WKPageRef, WKFrameRef, WKTypeRef, const void*) { done = true; };
+ WKPageSetPageLoaderClient(webView.page(), &loaderClient.base);
+
+ WKRetainPtr<WKURLRef> activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ EXPECT_NULL(activeURL.get());
+
+ WKRetainPtr<WKURLRef> url = adoptWK(Util::createURLForResource("simple", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), url.get()));
+ Util::run(&done);
+ done = false;
+
+ WKPageReload(webView.page());
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), url.get()));
+ Util::run(&done);
+ done = false;
+
+ WKRetainPtr<WKStringRef> htmlString = Util::toWK("<body>Hello, World</body>");
+ WKRetainPtr<WKURLRef> blankURL = adoptWK(WKURLCreateWithUTF8CString("about:blank"));
+ WKPageLoadHTMLString(webView.page(), htmlString.get(), nullptr);
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), blankURL.get()));
+ Util::run(&done);
+ done = false;
+
+ WKPageReload(webView.page());
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), blankURL.get()));
+ Util::run(&done);
+ done = false;
+
+ url = adoptWK(Util::createURLForResource("simple2", "html"));
+ WKPageLoadHTMLString(webView.page(), htmlString.get(), url.get());
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), url.get()));
+ Util::run(&done);
+ done = false;
+
+ WKPageReload(webView.page());
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), url.get()));
+ Util::run(&done);
+ done = false;
+
+ WKRetainPtr<WKDataRef> data = adoptWK(WKDataCreate(nullptr, 0));
+ WKPageLoadData(webView.page(), data.get(), nullptr, nullptr, nullptr);
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), blankURL.get()));
+ Util::run(&done);
+ done = false;
+
+ WKPageReload(webView.page());
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), blankURL.get()));
+ Util::run(&done);
+ done = false;
+
+ WKPageLoadData(webView.page(), data.get(), nullptr, nullptr, url.get());
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), url.get()));
+ Util::run(&done);
+ done = false;
+
+ WKPageReload(webView.page());
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), url.get()));
+ Util::run(&done);
+ done = false;
+
+ WKPageLoadAlternateHTMLString(webView.page(), htmlString.get(), nullptr, url.get());
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), url.get()));
+ Util::run(&done);
+ done = false;
+
+ WKPageReload(webView.page());
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), url.get()));
+ Util::run(&done);
+ done = false;
+
+ WKRetainPtr<WKStringRef> plainTextString = Util::toWK("Hello, World");
+ WKPageLoadPlainTextString(webView.page(), plainTextString.get());
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), blankURL.get()));
+ Util::run(&done);
+ done = false;
+
+ WKPageReload(webView.page());
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), blankURL.get()));
+ Util::run(&done);
+ done = false;
+
+ url = adoptWK(WKURLCreateWithUTF8CString("file:///tmp/index.html"));
+ WKPageLoadFile(webView.page(), url.get(), nullptr);
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), url.get()));
+ WKPageStopLoading(webView.page());
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/PreventEmptyUserAgent.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/PreventEmptyUserAgent.cpp
index c5acb6172..7712b142c 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/PreventEmptyUserAgent.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/PreventEmptyUserAgent.cpp
@@ -24,12 +24,15 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
#include <JavaScriptCore/JSContextRef.h>
-#include <WebKit2/WKRetainPtr.h>
-#include <WebKit2/WKSerializedScriptValue.h>
+#include <WebKit/WKRetainPtr.h>
+#include <WebKit/WKSerializedScriptValue.h>
namespace TestWebKitAPI {
@@ -68,3 +71,5 @@ TEST(WebKit2, PreventEmptyUserAgent)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/PrivateBrowsingPushStateNoHistoryCallback.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/PrivateBrowsingPushStateNoHistoryCallback.cpp
index 3d0db3d2f..532c92373 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/PrivateBrowsingPushStateNoHistoryCallback.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/PrivateBrowsingPushStateNoHistoryCallback.cpp
@@ -24,24 +24,33 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
-static bool testDone;
+static bool didNavigate;
+static bool didSameDocumentNavigation;
-static void didNavigateWithNavigationData(WKContextRef context, WKPageRef page, WKNavigationDataRef navigationData, WKFrameRef frame, const void* clientInfo)
+static void didNavigateWithoutNavigationData(WKContextRef context, WKPageRef page, WKNavigationDataRef navigationData, WKFrameRef frame, const void* clientInfo)
{
// This should never be called when navigating in Private Browsing.
FAIL();
}
+static void didNavigateWithNavigationData(WKContextRef context, WKPageRef page, WKNavigationDataRef navigationData, WKFrameRef frame, const void* clientInfo)
+{
+ didNavigate = true;
+}
+
static void didSameDocumentNavigationForFrame(WKPageRef page, WKFrameRef frame, WKSameDocumentNavigationType type, WKTypeRef userData, const void *clientInfo)
{
- testDone = true;
+ didSameDocumentNavigation = true;
}
TEST(WebKit2, PrivateBrowsingPushStateNoHistoryCallback)
@@ -52,7 +61,7 @@ TEST(WebKit2, PrivateBrowsingPushStateNoHistoryCallback)
memset(&historyClient, 0, sizeof(historyClient));
historyClient.base.version = 0;
- historyClient.didNavigateWithNavigationData = didNavigateWithNavigationData;
+ historyClient.didNavigateWithNavigationData = didNavigateWithoutNavigationData;
WKContextSetHistoryClient(context.get(), &historyClient.base);
@@ -75,7 +84,18 @@ TEST(WebKit2, PrivateBrowsingPushStateNoHistoryCallback)
WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("push-state", "html"));
WKPageLoadURL(webView.page(), url.get());
- Util::run(&testDone);
+ Util::run(&didSameDocumentNavigation);
+
+ WKPreferencesSetPrivateBrowsingEnabled(preferences.get(), false);
+
+ historyClient.didNavigateWithNavigationData = didNavigateWithNavigationData;
+ WKContextSetHistoryClient(context.get(), &historyClient.base);
+
+ WKPageLoadURL(webView.page(), url.get());
+
+ Util::run(&didNavigate);
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ReloadPageAfterCrash.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ReloadPageAfterCrash.cpp
index fb265abc1..190c85341 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/ReloadPageAfterCrash.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ReloadPageAfterCrash.cpp
@@ -24,10 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -86,3 +89,5 @@ TEST(WebKit2, ReloadPageAfterCrash)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ResizeReversePaginatedWebView.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ResizeReversePaginatedWebView.cpp
index af1f1e705..f2e1ae17f 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/ResizeReversePaginatedWebView.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ResizeReversePaginatedWebView.cpp
@@ -24,14 +24,17 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "JavaScriptTest.h"
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
#include <JavaScriptCore/JSContextRef.h>
-#include <WebKit2/WKContextPrivate.h>
-#include <WebKit2/WKPagePrivate.h>
-#include <WebKit2/WKSerializedScriptValue.h>
+#include <WebKit/WKContextPrivate.h>
+#include <WebKit/WKPagePrivate.h>
+#include <WebKit/WKSerializedScriptValue.h>
namespace TestWebKitAPI {
@@ -88,3 +91,5 @@ TEST(WebKit2, ResizeReversePaginatedWebView)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ResizeWindowAfterCrash.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ResizeWindowAfterCrash.cpp
index 4cd9eddb4..2dfc8b4c2 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/ResizeWindowAfterCrash.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ResizeWindowAfterCrash.cpp
@@ -24,10 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -97,3 +100,5 @@ TEST(WebKit2, ResizeWindowAfterCrash)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ResponsivenessTimerDoesntFireEarly.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ResponsivenessTimerDoesntFireEarly.cpp
index 9de11a286..a034637e3 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/ResponsivenessTimerDoesntFireEarly.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ResponsivenessTimerDoesntFireEarly.cpp
@@ -24,6 +24,9 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
@@ -96,3 +99,5 @@ TEST(WebKit2, ResponsivenessTimerDoesntFireEarly)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ResponsivenessTimerDoesntFireEarly_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ResponsivenessTimerDoesntFireEarly_Bundle.cpp
index 50d664f38..ddd2ca158 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/ResponsivenessTimerDoesntFireEarly_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ResponsivenessTimerDoesntFireEarly_Bundle.cpp
@@ -24,6 +24,9 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
@@ -57,3 +60,5 @@ void ResponsivenessTimerDoesntFireEarlyTest::didReceiveMessage(WKBundleRef bundl
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/RestoreSessionStateContainingFormData.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/RestoreSessionStateContainingFormData.cpp
index 079c51856..b16537e70 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/RestoreSessionStateContainingFormData.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/RestoreSessionStateContainingFormData.cpp
@@ -24,10 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "JavaScriptTest.h"
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
+#include <WebKit/WKSessionStateRef.h>
namespace TestWebKitAPI {
@@ -49,7 +53,7 @@ static void setPageLoaderClient(WKPageRef page)
WKPageSetPageLoaderClient(page, &loaderClient.base);
}
-static WKRetainPtr<WKDataRef> createSessionStateContainingFormData(WKContextRef context)
+static WKRetainPtr<WKDataRef> createSessionStateDataContainingFormData(WKContextRef context)
{
PlatformWebView webView(context);
setPageLoaderClient(webView.page());
@@ -62,7 +66,8 @@ static WKRetainPtr<WKDataRef> createSessionStateContainingFormData(WKContextRef
Util::run(&didFinishLoad);
didFinishLoad = false;
- return adoptWK(WKPageCopySessionState(webView.page(), 0, 0));
+ auto sessionState = adoptWK(static_cast<WKSessionStateRef>(WKPageCopySessionState(webView.page(), reinterpret_cast<void*>(1), nullptr)));
+ return adoptWK(WKSessionStateCopyData(sessionState.get()));
}
TEST(WebKit2, RestoreSessionStateContainingFormData)
@@ -75,13 +80,17 @@ TEST(WebKit2, RestoreSessionStateContainingFormData)
PlatformWebView webView(context.get());
setPageLoaderClient(webView.page());
- WKRetainPtr<WKDataRef> data = createSessionStateContainingFormData(context.get());
+ WKRetainPtr<WKDataRef> data = createSessionStateDataContainingFormData(context.get());
EXPECT_NOT_NULL(data);
- WKPageRestoreFromSessionState(webView.page(), data.get());
+ auto sessionState = adoptWK(WKSessionStateCreateFromData(data.get()));
+ WKPageRestoreFromSessionState(webView.page(), sessionState.get());
+
Util::run(&didFinishLoad);
EXPECT_TRUE(WKPageCanGoBack(webView.page()));
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ScrollPinningBehaviors.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ScrollPinningBehaviors.cpp
index 5b628a932..015571f5f 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/ScrollPinningBehaviors.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ScrollPinningBehaviors.cpp
@@ -24,15 +24,18 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "JavaScriptTest.h"
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
#include <JavaScriptCore/JSContextRef.h>
-#include <WebKit2/WKContextPrivate.h>
-#include <WebKit2/WKPagePrivate.h>
-#include <WebKit2/WKPreferencesPrivate.h>
-#include <WebKit2/WKSerializedScriptValue.h>
+#include <WebKit/WKContextPrivate.h>
+#include <WebKit/WKPagePrivate.h>
+#include <WebKit/WKPreferencesRefPrivate.h>
+#include <WebKit/WKSerializedScriptValue.h>
namespace TestWebKitAPI {
@@ -95,3 +98,5 @@ TEST(WebKit2, ScrollPinningBehaviors)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/SeccompFilters.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/SeccompFilters.cpp
new file mode 100644
index 000000000..9ca6080d3
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/SeccompFilters.cpp
@@ -0,0 +1,441 @@
+/*
+ * Copyright (C) 2013 Intel Corporation. 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 <WebKit/SeccompBroker.h>
+#include <WebKit/SeccompFilters.h>
+#include <WebKit/SyscallPolicy.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/WTFString.h>
+
+using namespace WebKit;
+
+namespace TestWebKitAPI {
+
+DEPRECATED_DEFINE_STATIC_LOCAL(String, rootDir, (ASCIILiteral("/")));
+DEPRECATED_DEFINE_STATIC_LOCAL(String, homeDir, (String(getenv("HOME"))));
+DEPRECATED_DEFINE_STATIC_LOCAL(String, usrDir, (ASCIILiteral("/usr")));
+DEPRECATED_DEFINE_STATIC_LOCAL(String, usrSbinDir, (ASCIILiteral("/usr/sbin")));
+DEPRECATED_DEFINE_STATIC_LOCAL(String, testDirRead, (ASCIILiteral("/tmp/WebKitSeccompFilters/testRead")));
+DEPRECATED_DEFINE_STATIC_LOCAL(String, testDirWrite, (ASCIILiteral("/tmp/WebKitSeccompFilters/testWrite")));
+DEPRECATED_DEFINE_STATIC_LOCAL(String, testDirReadAndWrite, (ASCIILiteral("/tmp/WebKitSeccompFilters/testReadAndWrite")));
+DEPRECATED_DEFINE_STATIC_LOCAL(String, testDirNotAllowed, (ASCIILiteral("/tmp/WebKitSeccompFilters/testNotAllowed")));
+DEPRECATED_DEFINE_STATIC_LOCAL(String, testFileNotAllowed, (testDirReadAndWrite + "/testFilePolicy"));
+DEPRECATED_DEFINE_STATIC_LOCAL(String, testFileReadAndWrite, (testDirNotAllowed + "/testFilePolicy"));
+
+static const mode_t defaultMode = S_IRUSR | S_IWUSR | S_IXUSR;
+
+class SeccompEnvironment : public testing::Environment {
+public:
+ virtual void SetUp()
+ {
+ ASSERT_TRUE(!homeDir.isEmpty());
+
+ mkdir("/tmp/WebKitSeccompFilters", defaultMode);
+ mkdir(testDirRead.utf8().data(), defaultMode);
+ mkdir(testDirWrite.utf8().data(), defaultMode);
+ mkdir(testDirReadAndWrite.utf8().data(), defaultMode);
+ mkdir(testDirNotAllowed.utf8().data(), defaultMode);
+
+ // Create a file for the Read only and NotAllowed directory before
+ // loading the filters.
+ String file = testDirRead + "/testFile";
+ int fd = open(file.utf8().data(), O_RDWR | O_CREAT, defaultMode);
+ ASSERT_NE(close(fd), -1);
+ file = testDirNotAllowed + "/testFile";
+ fd = open(file.utf8().data(), O_RDWR | O_CREAT, defaultMode);
+ ASSERT_NE(close(fd), -1);
+
+ // Create files for the file policy tests. File policies precedes the
+ // directory policy. In this case, we create a file with read and write
+ // policies inside a directory that is not allowed, and vice versa.
+ fd = open(testFileNotAllowed.utf8().data(), O_RDWR | O_CREAT, defaultMode);
+ ASSERT_NE(close(fd), -1);
+ fd = open(testFileReadAndWrite.utf8().data(), O_RDWR | O_CREAT, defaultMode);
+ ASSERT_NE(close(fd), -1);
+
+ SyscallPolicy policy;
+ policy.addDirectoryPermission(rootDir, SyscallPolicy::NotAllowed);
+ policy.addDirectoryPermission(usrDir, SyscallPolicy::Read);
+ policy.addDirectoryPermission(usrSbinDir, SyscallPolicy::NotAllowed);
+ policy.addDirectoryPermission(testDirRead, SyscallPolicy::Read);
+ policy.addDirectoryPermission(testDirWrite, SyscallPolicy::Write);
+ policy.addDirectoryPermission(testDirReadAndWrite, SyscallPolicy::ReadAndWrite);
+ policy.addDirectoryPermission(testDirNotAllowed, SyscallPolicy::NotAllowed);
+ policy.addFilePermission(testFileNotAllowed, SyscallPolicy::NotAllowed);
+ policy.addFilePermission(testFileReadAndWrite, SyscallPolicy::ReadAndWrite);
+
+ SeccompFilters seccompFilters(SeccompFilters::Allow);
+ seccompFilters.addRule("open", SeccompFilters::Trap);
+ seccompFilters.addRule("openat", SeccompFilters::Trap);
+ seccompFilters.addRule("creat", SeccompFilters::Trap);
+
+ SeccompBroker::launchProcess(&seccompFilters, policy);
+ seccompFilters.initialize();
+ }
+
+ virtual void TearDown()
+ {
+ // This will have to move to a separated process created before loading
+ // the filters when we put the rmdir/unlink policies in place.
+ unlink("/tmp/WebKitSeccompFilters/testNotAllowed/testFile");
+ unlink("/tmp/WebKitSeccompFilters/testNotAllowed/testFilePolicy");
+ unlink("/tmp/WebKitSeccompFilters/testReadAndWrite/testFile");
+ unlink("/tmp/WebKitSeccompFilters/testReadAndWrite/testFile2");
+ unlink("/tmp/WebKitSeccompFilters/testReadAndWrite/testFile3");
+ unlink("/tmp/WebKitSeccompFilters/testReadAndWrite/testFilePolicy");
+ unlink("/tmp/WebKitSeccompFilters/testWrite/testFile");
+ unlink("/tmp/WebKitSeccompFilters/testWrite/testFile2");
+ unlink("/tmp/WebKitSeccompFilters/testRead/testFile");
+ rmdir("/tmp/WebKitSeccompFilters/testNotAllowed");
+ rmdir("/tmp/WebKitSeccompFilters/testReadAndWrite");
+ rmdir("/tmp/WebKitSeccompFilters/testWrite");
+ rmdir("/tmp/WebKitSeccompFilters/testRead");
+ rmdir("/tmp/WebKitSeccompFilters");
+ }
+};
+
+::testing::Environment* const env = ::testing::AddGlobalTestEnvironment(new SeccompEnvironment);
+
+static void dummyHandler(int, siginfo_t*, void*)
+{
+}
+
+TEST(WebKit2, sigaction)
+{
+ // Setting a handler should be enough to break any subsequent test if
+ // not silently ignored by the sandbox.
+ struct sigaction action;
+ memset(&action, 0, sizeof(action));
+ action.sa_sigaction = &dummyHandler;
+ action.sa_flags = SA_SIGINFO;
+
+ ASSERT_NE(sigaction(SIGSYS, &action, 0), -1);
+}
+
+TEST(WebKit2, sigprocmask)
+{
+ // We test here the mechanism installed to prevent SIGSYS to be blocked. Any
+ // attemp to add SIGSYS to the set of blocked signals will be silently
+ // ignored (but other signals will be blocked just fine).
+ sigset_t set, oldSet;
+ sigemptyset(&set);
+ sigaddset(&set, SIGSYS);
+ sigaddset(&set, SIGUSR1);
+
+ ASSERT_NE(sigprocmask(SIG_BLOCK, &set, 0), -1);
+ ASSERT_NE(sigprocmask(SIG_BLOCK, 0, &oldSet), -1);
+ ASSERT_FALSE(sigismember(&oldSet, SIGSYS)) << "SIGSYS should not be blocked.";
+ ASSERT_TRUE(sigismember(&oldSet, SIGUSR1)) << "Other signals should be blocked normally.";
+
+ sigemptyset(&set);
+ sigaddset(&set, SIGSYS);
+ sigaddset(&set, SIGUSR2);
+
+ ASSERT_NE(sigprocmask(SIG_SETMASK, &set, &oldSet), -1);
+ ASSERT_NE(sigprocmask(SIG_SETMASK, 0, &set), -1);
+ ASSERT_FALSE(sigismember(&set, SIGSYS)) << "SIGSYS should not be blocked.";
+ ASSERT_TRUE(sigismember(&set, SIGUSR2)) << "Other signals should be blocked normally.";
+ ASSERT_FALSE(sigismember(&oldSet, SIGUSR2));
+
+ ASSERT_NE(sigprocmask(SIG_SETMASK, &oldSet, 0), -1) << "Should restore the old signal set just fine.";
+ ASSERT_NE(sigprocmask(SIG_SETMASK, 0, &set), -1);
+ ASSERT_FALSE(sigismember(&set, SIGUSR2)) << "The restored set doesn't have SIGUSR2.";
+}
+
+TEST(WebKit2, open)
+{
+ // Read only directory.
+ String file = testDirRead + "/testFile";
+ int fd = open(file.utf8().data(), O_RDWR);
+ EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+ fd = open(file.utf8().data(), O_WRONLY);
+ EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+ fd = open(file.utf8().data(), O_RDONLY | O_CREAT, defaultMode);
+ EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+ fd = open(file.utf8().data(), O_RDONLY);
+ EXPECT_NE(fd, -1);
+ close(fd);
+
+ file = testDirRead + "/ThisFileDoesNotExist";
+ fd = open(file.utf8().data(), O_RDONLY);
+ EXPECT_TRUE(fd == -1 && errno == ENOENT) << "Should return ENOENT when trying " \
+ "to open a file that does not exit and the permissions are OK.";
+
+ fd = open(file.utf8().data(), O_WRONLY);
+ EXPECT_TRUE(fd == -1 && errno == EACCES) << "Should return EACCES when trying " \
+ "to open a file that does not exit and the permissions are not OK.";
+
+ // Write only directory.
+ file = testDirWrite + "/testFile";
+ fd = open(file.utf8().data(), O_WRONLY | O_CREAT, defaultMode);
+ ASSERT_NE(fd, -1);
+ close(fd);
+
+ fd = open(file.utf8().data(), O_RDWR);
+ EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+ fd = open(file.utf8().data(), O_RDONLY);
+ EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+ fd = open(file.utf8().data(), O_WRONLY);
+ EXPECT_NE(fd, -1);
+ close(fd);
+
+ // Read an write directory.
+ file = testDirReadAndWrite + "/testFile";
+ fd = open(file.utf8().data(), O_WRONLY | O_CREAT, defaultMode);
+ ASSERT_NE(fd, -1);
+ close(fd);
+
+ fd = open(file.utf8().data(), O_RDWR);
+ EXPECT_NE(fd, -1);
+ close(fd);
+
+ fd = open(file.utf8().data(), O_RDONLY);
+ EXPECT_NE(fd, -1);
+ close(fd);
+
+ fd = open(file.utf8().data(), O_WRONLY);
+ EXPECT_NE(fd, -1);
+ close(fd);
+
+ // NotAllowed directory.
+ file = testDirNotAllowed + "/testFile";
+ fd = open(file.utf8().data(), O_WRONLY | O_CREAT, defaultMode);
+ EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+ fd = open(file.utf8().data(), O_RDWR);
+ EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+ fd = open(file.utf8().data(), O_RDONLY);
+ EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+ fd = open(file.utf8().data(), O_WRONLY);
+ EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+
+ // The /usr directory here has read permissions, so it's subdirectories
+ // should resolve to the /usr permissions unless explicitly specified.
+ file = usrDir + "/bin/basename";
+ fd = open(file.utf8().data(), O_RDONLY);
+ EXPECT_NE(fd, -1) << "Subdirectories should with no policy should " \
+ "inherit the parent's policies.";
+ close(fd);
+
+ file = usrSbinDir + "/adduser";
+ fd = open(file.utf8().data(), O_RDONLY);
+ EXPECT_TRUE(fd == -1 && errno == EACCES) << "This directory should have " \
+ "its own policy instead of the parent's.";
+
+ // Access to the rest of the files system is blocked and should
+ // never return anything else other than EACCES regardless if the
+ // file exists or not. The reason is because it will fallback to the
+ // policy of the Root directory, marked as NotAllowed.
+ file = homeDir + "/testFile";
+ fd = open(file.utf8().data(), O_RDWR | O_CREAT, defaultMode);
+ EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+ fd = open("/etc/passwd", O_RDONLY);
+ EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+ file = testDirReadAndWrite + "/../../../etc/passwd";
+ fd = open(file.utf8().data(), O_RDONLY);
+ EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+ file = testDirReadAndWrite + "/../../.." + testDirReadAndWrite + "/../../../etc/passwd";
+ fd = open(file.utf8().data(), O_RDONLY);
+ EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+ // Here we test file policies. The have precedence over directory policies.
+ // The file bellow lives inside a directory with ReadAndWrite policy.
+ fd = open(testFileNotAllowed.utf8().data(), O_RDONLY);
+ EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+ fd = open(testFileNotAllowed.utf8().data(), O_WRONLY);
+ EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+ fd = open(testFileNotAllowed.utf8().data(), O_RDWR);
+ EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+ file = testDirReadAndWrite + "/../../.." + testDirReadAndWrite + "/testFilePolicy";
+ fd = open(file.utf8().data(), O_RDONLY);
+ EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+ // The next file is located inside a directory marked as NotAllowed, but
+ // it has its own file policy that precedes the directory policy.
+ fd = open(testFileReadAndWrite.utf8().data(), O_RDONLY);
+ EXPECT_NE(fd, -1);
+ close(fd);
+
+ fd = open(testFileReadAndWrite.utf8().data(), O_WRONLY);
+ EXPECT_NE(fd, -1);
+ close(fd);
+
+ fd = open(testFileReadAndWrite.utf8().data(), O_RDWR);
+ EXPECT_NE(fd, -1);
+ close(fd);
+
+ file = testDirReadAndWrite + "/../../.." + testDirNotAllowed + "/testFilePolicy";
+ fd = open(file.utf8().data(), O_RDONLY);
+ EXPECT_NE(fd, -1);
+ close(fd);
+}
+
+TEST(WebKit2, creat)
+{
+ // Read only directory.
+ String file = testDirRead + "/testFile2";
+ int fd = creat(file.utf8().data(), defaultMode);
+ EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+ // Write only directory.
+ file = testDirWrite + "/testFile2";
+ fd = creat(file.utf8().data(), defaultMode);
+ EXPECT_NE(fd, -1);
+ close(fd);
+
+ // Read an write directory.
+ file = testDirReadAndWrite + "/testFile2";
+ fd = creat(file.utf8().data(), defaultMode);
+ EXPECT_NE(fd, -1);
+ close(fd);
+
+ // NotAllowed directory.
+ file = testDirNotAllowed + "/testFile2";
+ fd = creat(file.utf8().data(), defaultMode);
+ EXPECT_TRUE(fd == -1 && errno == EACCES);
+}
+
+TEST(WebKit2, openat)
+{
+ int dirFd = open(testDirReadAndWrite.utf8().data(), O_RDONLY);
+ ASSERT_NE(dirFd, -1);
+
+ int fd = openat(dirFd, "testFile3", O_RDWR | O_CREAT, defaultMode);
+ EXPECT_NE(fd, -1);
+ close(fd);
+
+ fd = openat(dirFd, "testFile3", O_RDWR);
+ EXPECT_NE(fd, -1);
+ close(fd);
+
+ fd = openat(dirFd, "testFile3", O_RDONLY);
+ EXPECT_NE(fd, -1);
+ close(fd);
+
+ fd = openat(dirFd, "testFile3", O_WRONLY);
+ EXPECT_NE(fd, -1);
+
+ fd = openat(fd, "testFile3", O_WRONLY);
+ EXPECT_TRUE(fd == -1 && errno == ENOTDIR) << "Should return ENOTDIR when the fd is a file.";
+ close(fd);
+
+ String file = "../../.." + testDirReadAndWrite + "/testFile3";
+ fd = openat(dirFd, file.utf8().data(), O_WRONLY);
+ EXPECT_NE(fd, -1);
+ close(fd);
+
+ file = "../../.." + testDirRead + "/testFile3";
+ fd = openat(dirFd, file.utf8().data(), O_WRONLY);
+ EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+ file = testDirReadAndWrite + "/testFile3";
+ fd = openat(-1, file.utf8().data(), O_WRONLY);
+ EXPECT_NE(fd, -1) << "Directory fd should be ignored when the path is absolute.";
+ close(fd);
+
+ fd = openat(-1, "testFile3", O_WRONLY);
+ EXPECT_TRUE(fd == -1 && errno == EBADF) << "Should return EBADF when the fd is invalid.";
+ close(dirFd);
+
+ dirFd = open(testDirNotAllowed.utf8().data(), O_RDONLY);
+ EXPECT_TRUE(dirFd == -1 && errno == EACCES);
+
+ dirFd = open(testDirRead.utf8().data(), O_RDONLY);
+ ASSERT_NE(dirFd, -1);
+
+ fd = openat(dirFd, "testFile2", O_RDONLY | O_CREAT, defaultMode);
+ EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+ fd = openat(dirFd, "testFile", O_WRONLY);
+ EXPECT_TRUE(fd == -1 && errno == EACCES);
+ close(dirFd);
+}
+
+static void* stressTest(void*)
+{
+ for (int i = 0; i < 500; ++i) {
+ int fd = open("/tmp/WebKitSeccompFilters/testRead/testFile", O_RDWR);
+ EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+ fd = open("/tmp/WebKitSeccompFilters/testRead/testFile", O_RDONLY);
+ EXPECT_NE(fd, -1);
+ close(fd);
+
+ fd = open("/tmp/WebKitSeccompFilters/testNotAllowed/testFile", O_RDONLY);
+ EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+ fd = creat("/tmp/WebKitSeccompFilters/testNotAllowed/SholdNotBeAllowed", defaultMode);
+ EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+ int dirFd = open("/tmp/WebKitSeccompFilters/testRead", O_RDONLY);
+ EXPECT_NE(dirFd, -1);
+
+ fd = openat(dirFd, "testFile", O_RDONLY);
+ EXPECT_NE(fd, -1);
+ close(fd);
+ close(dirFd);
+ }
+
+ return 0;
+}
+
+TEST(WebKit2, threading)
+{
+ // Tests if concurrent syscall execution works fine. It can be
+ // also used for performance testing and leak detection. The test
+ // is disabled on Debug mode because it can be way too verbose.
+ pthread_t threads[5];
+
+ for (int i = 0; i < sizeof(threads) / sizeof(pthread_t); ++i)
+ pthread_create(&threads[i], 0, stressTest, 0);
+
+ for (int i = 0; i < sizeof(threads) / sizeof(pthread_t); ++i)
+ pthread_join(threads[i], 0);
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ShouldGoToBackForwardListItem.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ShouldGoToBackForwardListItem.cpp
index 5754155ed..f41e44a5e 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/ShouldGoToBackForwardListItem.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ShouldGoToBackForwardListItem.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKString.h>
+#include <WebKit/WKString.h>
namespace TestWebKitAPI {
@@ -90,3 +93,5 @@ TEST(WebKit2, ShouldGoToBackForwardListItem)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ShouldGoToBackForwardListItem_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ShouldGoToBackForwardListItem_Bundle.cpp
index dd81bf3bf..5eba75a9e 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/ShouldGoToBackForwardListItem_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ShouldGoToBackForwardListItem_Bundle.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKBundlePage.h>
-#include <WebKit2/WKBundleBackForwardListItem.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundleBackForwardListItem.h>
namespace TestWebKitAPI {
@@ -68,3 +71,5 @@ void ShouldGoToBackForwardListItemTest::didCreatePage(WKBundleRef bundle, WKBund
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ShouldKeepCurrentBackForwardListItemInList.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ShouldKeepCurrentBackForwardListItemInList.cpp
new file mode 100644
index 000000000..f8098e6f1
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ShouldKeepCurrentBackForwardListItemInList.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+
+// This test navigates from simple.html, to simple2.html, to simple3.html
+// When navigating from simple2 to simple3, it disallows the simple2 back/forward list item from staying in the list
+// It then navigates back from simple3, expecting to land at simple.
+
+namespace TestWebKitAPI {
+
+static bool finished = false;
+static bool successfulSoFar = true;
+static int navigationNumber = 0;
+
+static bool itemURLLastComponentIsString(WKBackForwardListItemRef item, const char* string)
+{
+ WKRetainPtr<WKURLRef> url = adoptWK(WKBackForwardListItemCopyURL(item));
+ WKRetainPtr<WKStringRef> path = adoptWK(WKURLCopyLastPathComponent(url.get()));
+
+ return WKStringIsEqualToUTF8CString(path.get(), string);
+}
+
+static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef, const void*)
+{
+ // Only mark finished when the main frame loads
+ if (!WKFrameIsMainFrame(frame))
+ return;
+
+ finished = true;
+ navigationNumber++;
+
+ WKBackForwardListRef list = WKPageGetBackForwardList(page);
+ WKBackForwardListItemRef currentItem = WKBackForwardListGetCurrentItem(list);
+ WKBackForwardListItemRef backItem = WKBackForwardListGetBackItem(list);
+ WKBackForwardListItemRef forwardItem = WKBackForwardListGetForwardItem(list);
+ unsigned forwardCount = WKBackForwardListGetForwardListCount(list);
+
+ // This test should never have a forward list.
+ if (forwardCount)
+ successfulSoFar = false;
+
+ if (navigationNumber == 1) {
+ // We've only performed 1 navigation, we should only have a current item.
+ if (!currentItem || !itemURLLastComponentIsString(currentItem, "simple.html"))
+ successfulSoFar = false;
+ if (backItem || forwardItem)
+ successfulSoFar = false;
+ } else if (navigationNumber == 2) {
+ // On the second navigation, simple2 should be current and simple should be the back item.
+ if (!currentItem || !itemURLLastComponentIsString(currentItem, "simple2.html"))
+ successfulSoFar = false;
+ if (!backItem || !itemURLLastComponentIsString(backItem, "simple.html"))
+ successfulSoFar = false;
+ if (forwardItem)
+ successfulSoFar = false;
+ } else if (navigationNumber == 3) {
+ // On the third navigation the item for simple2 should have been removed.
+ // So simple3 should be current and simple should still be the back item.
+ if (!currentItem || !itemURLLastComponentIsString(currentItem, "simple3.html"))
+ successfulSoFar = false;
+ if (!backItem || !itemURLLastComponentIsString(backItem, "simple.html"))
+ successfulSoFar = false;
+ if (forwardItem)
+ successfulSoFar = false;
+ } else if (navigationNumber == 4) {
+ // After the fourth navigation (which was a "back" navigation), the item for simple3 should have been removed.
+ // So simple should be current and there should be no other items.
+ if (!currentItem || !itemURLLastComponentIsString(currentItem, "simple.html"))
+ successfulSoFar = false;
+ if (backItem || forwardItem)
+ successfulSoFar = false;
+ }
+}
+
+static void willGoToBackForwardListItem(WKPageRef, WKBackForwardListItemRef item, WKTypeRef userData, const void*)
+{
+ if (!itemURLLastComponentIsString(item, "simple.html"))
+ successfulSoFar = false;
+}
+
+static bool shouldKeepCurrentBackForwardListItemInList(WKPageRef page, WKBackForwardListItemRef item, const void*)
+{
+ // We make sure the item for "simple2.html" is removed when we navigate to "simple3.html"
+ // We also want to make sure the item for "simple3.html" is removed when we go back to "simple.html"
+ // So we only want to keep "simple.html"
+ return itemURLLastComponentIsString(item, "simple.html");
+}
+
+static void setPageLoaderClient(WKPageRef page)
+{
+ WKPageLoaderClientV5 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+
+ loaderClient.base.version = 5;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+ loaderClient.shouldKeepCurrentBackForwardListItemInList = shouldKeepCurrentBackForwardListItemInList;
+ loaderClient.willGoToBackForwardListItem = willGoToBackForwardListItem;
+
+ WKPageSetPageLoaderClient(page, &loaderClient.base);
+}
+
+TEST(WebKit2, ShouldKeepCurrentBackForwardListItemInList)
+{
+ WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+
+ PlatformWebView webView(context.get());
+ setPageLoaderClient(webView.page());
+
+ WKPageLoadURL(webView.page(), adoptWK(Util::createURLForResource("simple", "html")).get());
+ Util::run(&finished);
+ EXPECT_EQ(successfulSoFar, true);
+
+ finished = false;
+ WKPageLoadURL(webView.page(), adoptWK(Util::createURLForResource("simple2", "html")).get());
+ Util::run(&finished);
+ EXPECT_EQ(successfulSoFar, true);
+
+ finished = false;
+ WKPageLoadURL(webView.page(), adoptWK(Util::createURLForResource("simple3", "html")).get());
+ Util::run(&finished);
+ EXPECT_EQ(successfulSoFar, true);
+
+ finished = false;
+ WKPageGoBack(webView.page());
+ Util::run(&finished);
+
+ EXPECT_EQ(successfulSoFar, true);
+ EXPECT_EQ(navigationNumber, 4);
+}
+
+} // namespace TestWebKitAPI
+
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/SpacebarScrolling.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/SpacebarScrolling.cpp
index 577e0d77c..226f52cc2 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/SpacebarScrolling.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/SpacebarScrolling.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "JavaScriptTest.h"
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKRetainPtr.h>
-#include <WebKit2/WKPreferencesPrivate.h>
+#include <WebKit/WKRetainPtr.h>
+#include <WebKit/WKPreferencesPrivate.h>
namespace TestWebKitAPI {
@@ -86,13 +89,11 @@ TEST(WebKit2, SpacebarScrolling)
EXPECT_JS_FALSE(webView.page(), "isDocumentScrolled()");
EXPECT_JS_TRUE(webView.page(), "textFieldContainsSpace()");
- // On Mac, a key down event represents both a raw key down and a key press. On Windows, a key
- // down event only represents a raw key down. We expect the key press to be handled (because it
- // inserts text into the text field). But the raw key down should not be handled.
-#if PLATFORM(MAC)
+ // On Mac, a key down event represents both a raw key down and a key press.
+ // We expect the key press to be handled (because it inserts text into the text field),
+ // but the raw key down should not be handled.
+#if PLATFORM(COCOA)
EXPECT_FALSE(didNotHandleKeyDownEvent);
-#elif PLATFORM(WIN)
- EXPECT_TRUE(didNotHandleKeyDownEvent);
#endif
EXPECT_JS_EQ(webView.page(), "blurTextField()", "undefined");
@@ -100,18 +101,14 @@ TEST(WebKit2, SpacebarScrolling)
didNotHandleKeyDownEvent = false;
webView.simulateSpacebarKeyPress();
- // This EXPECT_JS_TRUE test fails on Windows port
- // https://bugs.webkit.org/show_bug.cgi?id=84961
-#if !PLATFORM(WIN)
EXPECT_JS_TRUE(webView.page(), "isDocumentScrolled()");
-#endif
EXPECT_JS_TRUE(webView.page(), "textFieldContainsSpace()");
-#if PLATFORM(MAC)
+#if PLATFORM(COCOA)
EXPECT_FALSE(didNotHandleKeyDownEvent);
-#elif PLATFORM(WIN)
- EXPECT_TRUE(didNotHandleKeyDownEvent);
#endif
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/StopLoadingDuringDidFailProvisionalLoad.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/StopLoadingDuringDidFailProvisionalLoad.cpp
new file mode 100644
index 000000000..386dfd303
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/StopLoadingDuringDidFailProvisionalLoad.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+#include <WebKit/WKRetainPtr.h>
+
+namespace TestWebKitAPI {
+
+static bool done;
+static bool receivedMessageFromBundle;
+
+static void didReceiveMessageFromInjectedBundle(WKContextRef context, WKStringRef messageName, WKTypeRef messageBody, const void* clientInfo)
+{
+ if (WKStringIsEqualToUTF8CString(messageName, "StopLoadingDuringDidFailProvisionalLoadTestDone"))
+ receivedMessageFromBundle = true;
+}
+
+static void setInjectedBundleClient(WKContextRef context)
+{
+ WKContextInjectedBundleClientV0 injectedBundleClient;
+ memset(&injectedBundleClient, 0, sizeof(injectedBundleClient));
+
+ injectedBundleClient.didReceiveMessageFromInjectedBundle = didReceiveMessageFromInjectedBundle;
+
+ WKContextSetInjectedBundleClient(context, &injectedBundleClient.base);
+}
+
+static void didFailProvisionalLoadWithErrorForFrame(WKPageRef, WKFrameRef, WKErrorRef, WKTypeRef, const void*)
+{
+ // The injected bundle is notified of the failed load first. If we also receive this callback, the test didn't crash.
+ EXPECT_TRUE(receivedMessageFromBundle);
+ done = true;
+}
+
+TEST(WebKit2, StopLoadingDuringDidFailProvisionalLoadTest)
+{
+ WKRetainPtr<WKContextRef> context(AdoptWK, Util::createContextForInjectedBundleTest("StopLoadingDuringDidFailProvisionalLoadTest"));
+ setInjectedBundleClient(context.get());
+
+ PlatformWebView webView(context.get());
+
+ WKPageLoaderClientV0 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+ loaderClient.didFailProvisionalLoadWithErrorForFrame = didFailProvisionalLoadWithErrorForFrame;
+ WKPageSetPageLoaderClient(webView.page(), &loaderClient.base);
+
+ WKRetainPtr<WKURLRef> url(AdoptWK, Util::URLForNonExistentResource());
+ WKPageLoadURL(webView.page(), url.get());
+
+ Util::run(&done);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/StopLoadingDuringDidFailProvisionalLoad_bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/StopLoadingDuringDidFailProvisionalLoad_bundle.cpp
new file mode 100644
index 000000000..56105522b
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/StopLoadingDuringDidFailProvisionalLoad_bundle.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "InjectedBundleTest.h"
+#include "PlatformUtilities.h"
+#include <WebKit/WKBundle.h>
+#include <WebKit/WKBundleFramePrivate.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundlePagePrivate.h>
+
+namespace TestWebKitAPI {
+
+class StopLoadingDuringDidFailProvisionalLoadTest : public InjectedBundleTest {
+public:
+ StopLoadingDuringDidFailProvisionalLoadTest(const std::string& identifier)
+ : InjectedBundleTest(identifier)
+ {
+ }
+
+ virtual void didCreatePage(WKBundleRef, WKBundlePageRef) override;
+ void didFailProvisionalLoad(WKBundlePageRef, WKBundleFrameRef);
+
+ WKBundleRef m_bundle;
+};
+
+static InjectedBundleTest::Register<StopLoadingDuringDidFailProvisionalLoadTest> registrar("StopLoadingDuringDidFailProvisionalLoadTest");
+
+static void didFailProvisionalLoadWithErrorForFrameCallback(WKBundlePageRef page, WKBundleFrameRef frame, WKErrorRef, WKTypeRef*, const void *clientInfo)
+{
+ ((StopLoadingDuringDidFailProvisionalLoadTest*)clientInfo)->didFailProvisionalLoad(page, frame);
+}
+
+void StopLoadingDuringDidFailProvisionalLoadTest::didCreatePage(WKBundleRef bundle, WKBundlePageRef page)
+{
+ m_bundle = bundle;
+
+ WKBundlePageLoaderClientV2 pageLoaderClient;
+ memset(&pageLoaderClient, 0, sizeof(pageLoaderClient));
+
+ pageLoaderClient.base.version = 2;
+ pageLoaderClient.base.clientInfo = this;
+ pageLoaderClient.didFailProvisionalLoadWithErrorForFrame = didFailProvisionalLoadWithErrorForFrameCallback;
+
+ WKBundlePageSetPageLoaderClient(page, &pageLoaderClient.base);
+}
+
+void StopLoadingDuringDidFailProvisionalLoadTest::didFailProvisionalLoad(WKBundlePageRef page, WKBundleFrameRef)
+{
+ WKBundlePageStopLoading(page);
+ WKBundlePostMessage(m_bundle, Util::toWK("StopLoadingDuringDidFailProvisionalLoadTestDone").get(), nullptr);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/TerminateTwice.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/TerminateTwice.cpp
index 879312520..2e1950860 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/TerminateTwice.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/TerminateTwice.cpp
@@ -24,11 +24,17 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
namespace TestWebKitAPI {
+// Disabled in debug mode while investigating <https://bugs.webkit.org/show_bug.cgi?id=136012>.
+#ifdef NDEBUG
+
static bool loaded;
static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo)
@@ -62,5 +68,8 @@ TEST(WebKit2, TerminateTwice)
WKPageTerminate(webView.page());
}
+#endif
+
} // namespace TestWebKitAPI
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/TextFieldDidBeginAndEndEditing.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/TextFieldDidBeginAndEndEditing.cpp
new file mode 100644
index 000000000..cfe0be254
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/TextFieldDidBeginAndEndEditing.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI && !PLATFORM(MAC)
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+#include <wtf/StdLibExtras.h>
+
+namespace TestWebKitAPI {
+
+struct WebKit2TextFieldBeginAndEditEditingTest : public ::testing::Test {
+ std::unique_ptr<PlatformWebView> webView;
+
+ WKRetainPtr<WKStringRef> messageName;
+
+ bool didFinishLoad { false };
+ bool didReceiveMessage { false };
+
+ static void didReceiveMessageFromInjectedBundle(WKContextRef, WKStringRef messageName, WKTypeRef, const void* clientInfo)
+ {
+ WebKit2TextFieldBeginAndEditEditingTest& client = *static_cast<WebKit2TextFieldBeginAndEditEditingTest*>(const_cast<void*>(clientInfo));
+ client.messageName = messageName;
+ client.didReceiveMessage = true;
+ }
+
+ static void didFinishLoadForFrame(WKPageRef, WKFrameRef, WKTypeRef, const void* clientInfo)
+ {
+ WebKit2TextFieldBeginAndEditEditingTest& client = *static_cast<WebKit2TextFieldBeginAndEditEditingTest*>(const_cast<void*>(clientInfo));
+ client.didFinishLoad = true;
+ }
+
+ static void setInjectedBundleClient(WKContextRef context, const void* clientInfo)
+ {
+ WKContextInjectedBundleClientV1 injectedBundleClient;
+ memset(&injectedBundleClient, 0, sizeof(injectedBundleClient));
+
+ injectedBundleClient.base.version = 1;
+ injectedBundleClient.base.clientInfo = clientInfo;
+ injectedBundleClient.didReceiveMessageFromInjectedBundle = didReceiveMessageFromInjectedBundle;
+
+ WKContextSetInjectedBundleClient(context, &injectedBundleClient.base);
+ }
+
+ static void setPageLoaderClient(WKPageRef page, const void* clientInfo)
+ {
+ WKPageLoaderClientV6 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+
+ loaderClient.base.version = 6;
+ loaderClient.base.clientInfo = clientInfo;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+
+ WKPageSetPageLoaderClient(page, &loaderClient.base);
+ }
+
+ static void nullJavaScriptCallback(WKSerializedScriptValueRef, WKErrorRef, void*)
+ {
+ }
+
+ void executeJavaScriptAndCheckDidReceiveMessage(const char* javaScriptCode, const char* expectedMessageName)
+ {
+ didReceiveMessage = false;
+ WKPageRunJavaScriptInMainFrame(webView->page(), Util::toWK(javaScriptCode).get(), 0, nullJavaScriptCallback);
+ Util::run(&didReceiveMessage);
+ EXPECT_WK_STREQ(expectedMessageName, messageName);
+ }
+
+ // From ::testing::Test
+ void SetUp() override
+ {
+ WKRetainPtr<WKContextRef> context = adoptWK(Util::createContextForInjectedBundleTest("TextFieldDidBeginAndEndEditingEventsTest"));
+ setInjectedBundleClient(context.get(), this);
+
+ webView = std::make_unique<PlatformWebView>(context.get());
+ setPageLoaderClient(webView->page(), this);
+
+ didFinishLoad = false;
+ didReceiveMessage = false;
+
+ WKPageLoadURL(webView->page(), adoptWK(Util::createURLForResource("input-focus-blur", "html")).get());
+ Util::run(&didFinishLoad);
+ }
+};
+
+TEST_F(WebKit2TextFieldBeginAndEditEditingTest, TextFieldDidBeginAndEndEditingEvents)
+{
+ executeJavaScriptAndCheckDidReceiveMessage("focusTextField('input')", "DidReceiveTextFieldDidBeginEditing");
+ executeJavaScriptAndCheckDidReceiveMessage("blurTextField('input')", "DidReceiveTextFieldDidEndEditing");
+}
+
+TEST_F(WebKit2TextFieldBeginAndEditEditingTest, TextFieldDidBeginAndEndEditingEventsInReadOnlyField)
+{
+ executeJavaScriptAndCheckDidReceiveMessage("focusTextField('readonly')", "DidReceiveTextFieldDidBeginEditing");
+ executeJavaScriptAndCheckDidReceiveMessage("blurTextField('readonly')", "DidReceiveTextFieldDidEndEditing");
+}
+
+TEST_F(WebKit2TextFieldBeginAndEditEditingTest, TextFieldDidBeginShouldNotBeDispatchedForAlreadyFocusedField)
+{
+ executeJavaScriptAndCheckDidReceiveMessage("focusTextField('input'); focusTextField('input')", "DidReceiveTextFieldDidBeginEditing");
+ executeJavaScriptAndCheckDidReceiveMessage("blurTextField('input')", "DidReceiveTextFieldDidEndEditing");
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/TextFieldDidBeginAndEndEditing_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/TextFieldDidBeginAndEndEditing_Bundle.cpp
new file mode 100644
index 000000000..19898f703
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/TextFieldDidBeginAndEndEditing_Bundle.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI && !PLATFORM(MAC)
+
+#include "InjectedBundleTest.h"
+
+#include "PlatformUtilities.h"
+#include <WebKit/WKBundlePage.h>
+
+namespace TestWebKitAPI {
+
+class TextFieldDidBeginAndEndEditingEventsTest : public InjectedBundleTest {
+public:
+ TextFieldDidBeginAndEndEditingEventsTest(const std::string& identifier);
+
+ virtual void didCreatePage(WKBundleRef, WKBundlePageRef);
+};
+
+static InjectedBundleTest::Register<TextFieldDidBeginAndEndEditingEventsTest> registrar("TextFieldDidBeginAndEndEditingEventsTest");
+
+static void textFieldDidBeginEditing(WKBundlePageRef, WKBundleNodeHandleRef inputElement, WKBundleFrameRef, const void*)
+{
+ WKBundlePostMessage(InjectedBundleController::singleton().bundle(), Util::toWK("DidReceiveTextFieldDidBeginEditing").get(), nullptr);
+}
+
+static void textFieldDidEndEditing(WKBundlePageRef, WKBundleNodeHandleRef inputElement, WKBundleFrameRef, const void*)
+{
+ WKBundlePostMessage(InjectedBundleController::singleton().bundle(), Util::toWK("DidReceiveTextFieldDidEndEditing").get(), nullptr);
+}
+
+TextFieldDidBeginAndEndEditingEventsTest::TextFieldDidBeginAndEndEditingEventsTest(const std::string& identifier)
+ : InjectedBundleTest(identifier)
+{
+}
+
+void TextFieldDidBeginAndEndEditingEventsTest::didCreatePage(WKBundleRef bundle, WKBundlePageRef page)
+{
+ WKBundlePageFormClientV2 formClient;
+ memset(&formClient, 0, sizeof(formClient));
+
+ formClient.base.version = 2;
+ formClient.base.clientInfo = this;
+ formClient.textFieldDidBeginEditing = textFieldDidBeginEditing;
+ formClient.textFieldDidEndEditing = textFieldDidEndEditing;
+
+ WKBundlePageSetFormClient(page, &formClient.base);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/UserMedia.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/UserMedia.cpp
new file mode 100644
index 000000000..24dd943de
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/UserMedia.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2014 Igalia S.L
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#if ENABLE(MEDIA_STREAM)
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+#include <WebKit/WKRetainPtr.h>
+#include <string.h>
+#include <vector>
+
+namespace TestWebKitAPI {
+
+static bool done;
+
+void decidePolicyForUserMediaPermissionRequestCallBack(WKPageRef, WKFrameRef, WKSecurityOriginRef, WKUserMediaPermissionRequestRef permissionRequest, const void* /* clientInfo */)
+{
+ WKRetainPtr<WKArrayRef> audioDeviceUIDs = WKUserMediaPermissionRequestAudioDeviceUIDs(permissionRequest);
+ WKRetainPtr<WKArrayRef> videoDeviceUIDs = WKUserMediaPermissionRequestVideoDeviceUIDs(permissionRequest);
+
+ if (WKArrayGetSize(videoDeviceUIDs.get()) || WKArrayGetSize(audioDeviceUIDs.get())) {
+ WKRetainPtr<WKStringRef> videoDeviceUID;
+ if (WKArrayGetSize(videoDeviceUIDs.get()))
+ videoDeviceUID = reinterpret_cast<WKStringRef>(WKArrayGetItemAtIndex(videoDeviceUIDs.get(), 0));
+ else
+ videoDeviceUID = WKStringCreateWithUTF8CString("");
+
+ WKRetainPtr<WKStringRef> audioDeviceUID;
+ if (WKArrayGetSize(audioDeviceUIDs.get()))
+ audioDeviceUID = reinterpret_cast<WKStringRef>(WKArrayGetItemAtIndex(audioDeviceUIDs.get(), 0));
+ else
+ audioDeviceUID = WKStringCreateWithUTF8CString("");
+
+ WKUserMediaPermissionRequestAllow(permissionRequest, videoDeviceUID.get(), audioDeviceUID.get());
+ }
+
+ done = true;
+}
+
+TEST(WebKit2, UserMediaBasic)
+{
+ auto context = adoptWK(WKContextCreate());
+ PlatformWebView webView(context.get());
+ WKPageUIClientV5 uiClient;
+ memset(&uiClient, 0, sizeof(uiClient));
+
+
+ uiClient.base.version = 5;
+ uiClient.decidePolicyForUserMediaPermissionRequest = decidePolicyForUserMediaPermissionRequestCallBack;
+
+ WKPageSetPageUIClient(webView.page(), &uiClient.base);
+
+ done = false;
+ auto url = adoptWK(Util::createURLForResource("getUserMedia", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+
+ Util::run(&done);
+}
+
+} // namespace TestWebKitAPI
+
+#endif // ENABLE(MEDIA_STREAM)
+
+#endif // WK_HAVE_C_SPI
+
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/UserMessage.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/UserMessage.cpp
index 2585a06ff..064cbb838 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/UserMessage.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/UserMessage.cpp
@@ -24,12 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "Test.h"
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <wtf/OwnPtr.h>
-#include <wtf/PassOwnPtr.h>
namespace TestWebKitAPI {
@@ -42,7 +43,7 @@ public:
}
WKRetainPtr<WKContextRef> context;
- OwnPtr<PlatformWebView> webView;
+ std::unique_ptr<PlatformWebView> webView;
WKRetainPtr<WKTypeRef> recievedBody;
@@ -80,7 +81,7 @@ public:
WKPageLoaderClientV3 loaderClient;
memset(&loaderClient, 0, sizeof(loaderClient));
- loaderClient.base.version = kWKPageLoaderClientCurrentVersion;
+ loaderClient.base.version = 3;
loaderClient.base.clientInfo = clientInfo;
loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
@@ -92,7 +93,7 @@ public:
context = adoptWK(Util::createContextForInjectedBundleTest("UserMessageTest"));
setInjectedBundleClient(context.get(), this);
- webView = adoptPtr(new PlatformWebView(context.get()));
+ webView = std::make_unique<PlatformWebView>(context.get());
setPageLoaderClient(webView->page(), this);
didFinishLoad = false;
@@ -157,3 +158,5 @@ TEST_F(WebKit2UserMessageRoundTripTest, WKString)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/UserMessage_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/UserMessage_Bundle.cpp
index 29ede3d83..cec713655 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/UserMessage_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/UserMessage_Bundle.cpp
@@ -24,6 +24,9 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
@@ -50,3 +53,5 @@ private:
static InjectedBundleTest::Register<UserMessageTest> registrar("UserMessageTest");
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WKBundleFileHandle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WKBundleFileHandle.cpp
new file mode 100644
index 000000000..b9a84ff80
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WKBundleFileHandle.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+
+namespace TestWebKitAPI {
+
+static bool done;
+static bool loadDone;
+
+static void didReceiveMessageFromInjectedBundle(WKContextRef, WKStringRef messageName, WKTypeRef body, const void*)
+{
+ if (!WKStringIsEqualToUTF8CString(messageName, "SUCCESS"))
+ FAIL();
+ else
+ SUCCEED();
+
+ done = true;
+}
+
+static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void*)
+{
+ loadDone = true;
+}
+
+TEST(WebKit2, WKBundleFileHandle)
+{
+ WKRetainPtr<WKContextRef> context = adoptWK(Util::createContextForInjectedBundleTest("WKBundleFileHandleTest"));
+
+ WKContextInjectedBundleClientV0 injectedBundleClient;
+ memset(&injectedBundleClient, 0, sizeof(injectedBundleClient));
+ injectedBundleClient.base.version = 0;
+ injectedBundleClient.didReceiveMessageFromInjectedBundle = didReceiveMessageFromInjectedBundle;
+ WKContextSetInjectedBundleClient(context.get(), &injectedBundleClient.base);
+
+ PlatformWebView webView(context.get());
+
+ WKPageLoaderClientV0 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+ loaderClient.base.version = 0;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+ WKPageSetPageLoaderClient(webView.page(), &loaderClient.base);
+
+ WKPageLoadURL(webView.page(), adoptWK(Util::createURLForResource("bundle-file", "html")).get());
+ Util::run(&loadDone);
+
+ // Get path to a file.
+ auto urlToFile = adoptWK(Util::createURLForResource("simple", "html"));
+ auto pathToFile = adoptWK(WKURLCopyPath(urlToFile.get()));
+
+ WKContextPostMessageToInjectedBundle(context.get(), Util::toWK("TestFile").get(), pathToFile.get());
+
+ Util::run(&done);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WKBundleFileHandle_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WKBundleFileHandle_Bundle.cpp
new file mode 100644
index 000000000..27d359ba6
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WKBundleFileHandle_Bundle.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "InjectedBundleTest.h"
+
+#include "PlatformUtilities.h"
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundleFileHandleRef.h>
+#include <WebKit/WKBundleFrame.h>
+#include <WebKit/WKBundleScriptWorld.h>
+
+namespace TestWebKitAPI {
+
+static WKBundlePageRef loadedPage;
+
+class WKBundleFileHandleTest : public InjectedBundleTest {
+public:
+ WKBundleFileHandleTest(const std::string& identifier)
+ : InjectedBundleTest(identifier)
+ {
+ }
+
+private:
+ virtual void didReceiveMessage(WKBundleRef bundle, WKStringRef messageName, WKTypeRef messageBody) override
+ {
+ if (!WKStringIsEqualToUTF8CString(messageName, "TestFile")) {
+ WKBundlePostMessage(bundle, Util::toWK("FAIL").get(), Util::toWK("Recieved invalid message").get());
+ return;
+ }
+
+ if (!loadedPage) {
+ WKBundlePostMessage(bundle, Util::toWK("FAIL").get(), Util::toWK("No loaded page").get());
+ return;
+ }
+
+ if (WKGetTypeID(messageBody) != WKStringGetTypeID()) {
+ WKBundlePostMessage(bundle, Util::toWK("FAIL").get(), Util::toWK("Message body has invalid type").get());
+ return;
+ }
+
+ WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(loadedPage);
+ WKBundleScriptWorldRef world = WKBundleScriptWorldNormalWorld();
+
+ JSGlobalContextRef globalContext = WKBundleFrameGetJavaScriptContextForWorld(mainFrame, world);
+
+ auto fileHandle = adoptWK(WKBundleFileHandleCreateWithPath((WKStringRef)messageBody));
+ JSValueRef jsFileHandle = WKBundleFrameGetJavaScriptWrapperForFileForWorld(mainFrame, fileHandle.get(), world);
+
+ JSObjectRef globalObject = JSContextGetGlobalObject(globalContext);
+
+ JSStringRef jsString = JSStringCreateWithUTF8CString("testFile");
+ JSValueRef function = JSObjectGetProperty(globalContext, globalObject, jsString, nullptr);
+ JSStringRelease(jsString);
+
+ JSValueRef result = JSObjectCallAsFunction(globalContext, (JSObjectRef)function, globalObject, 1, &jsFileHandle, nullptr);
+
+ if (JSValueToBoolean(globalContext, result))
+ WKBundlePostMessage(bundle, Util::toWK("SUCCESS").get(), nullptr);
+ else
+ WKBundlePostMessage(bundle, Util::toWK("FAIL").get(), Util::toWK("Script failed").get());
+ }
+
+ virtual void didCreatePage(WKBundleRef bundle, WKBundlePageRef page) override
+ {
+ loadedPage = page;
+ }
+};
+
+static InjectedBundleTest::Register<WKBundleFileHandleTest> registrar("WKBundleFileHandleTest");
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WKImageCreateCGImageCrash.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WKImageCreateCGImageCrash.cpp
new file mode 100644
index 000000000..f0d19025f
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WKImageCreateCGImageCrash.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include <WebKit/WKImageCG.h>
+
+namespace TestWebKitAPI {
+
+TEST(WebKit2, WKImageCreateCGImageCrash)
+{
+ EXPECT_FALSE(WKImageCreateCGImage(nullptr));
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WKPageConfiguration.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WKPageConfiguration.cpp
new file mode 100644
index 000000000..d041eeaed
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WKPageConfiguration.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+
+#include <WebKit/WKWebsiteDataStoreRef.h>
+
+namespace TestWebKitAPI {
+
+TEST(WebKit2, WKPageConfigurationEmpty)
+{
+ WKRetainPtr<WKPageConfigurationRef> configuration = adoptWK(WKPageConfigurationCreate());
+
+ ASSERT_NULL(WKPageConfigurationGetContext(configuration.get()));
+ ASSERT_NULL(WKPageConfigurationGetUserContentController(configuration.get()));
+ ASSERT_NULL(WKPageConfigurationGetPageGroup(configuration.get()));
+ ASSERT_NULL(WKPageConfigurationGetPreferences(configuration.get()));
+ ASSERT_NULL(WKPageConfigurationGetRelatedPage(configuration.get()));
+}
+
+static bool didFinishLoad;
+
+static void didFinishLoadForFrame(WKPageRef, WKFrameRef, WKTypeRef, const void*)
+{
+ didFinishLoad = true;
+}
+
+static void setPageLoaderClient(WKPageRef page)
+{
+ WKPageLoaderClientV0 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+
+ loaderClient.base.version = 0;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+
+ WKPageSetPageLoaderClient(page, &loaderClient.base);
+}
+
+TEST(WebKit2, WKPageConfigurationBasic)
+{
+ WKRetainPtr<WKPageConfigurationRef> configuration = adoptWK(WKPageConfigurationCreate());
+ WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreate());
+ WKPageConfigurationSetContext(configuration.get(), context.get());
+
+ PlatformWebView webView(configuration.get());
+ setPageLoaderClient(webView.page());
+
+ WKRetainPtr<WKPageConfigurationRef> copiedConfiguration = adoptWK(WKPageCopyPageConfiguration(webView.page()));
+ ASSERT_EQ(context.get(), WKPageConfigurationGetContext(copiedConfiguration.get()));
+
+ WKRetainPtr<WKURLRef> url = adoptWK(Util::createURLForResource("simple", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+
+ didFinishLoad = false;
+ Util::run(&didFinishLoad);
+}
+
+TEST(WebKit2, WKPageConfigurationBasicWithDataStore)
+{
+ WKRetainPtr<WKPageConfigurationRef> configuration = adoptWK(WKPageConfigurationCreate());
+ WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreate());
+ WKPageConfigurationSetContext(configuration.get(), context.get());
+ WKRetainPtr<WKWebsiteDataStoreRef> websiteDataStore = WKWebsiteDataStoreGetDefaultDataStore();
+ WKPageConfigurationSetWebsiteDataStore(configuration.get(), websiteDataStore.get());
+
+ PlatformWebView webView(configuration.get());
+ setPageLoaderClient(webView.page());
+
+ WKRetainPtr<WKPageConfigurationRef> copiedConfiguration = adoptWK(WKPageCopyPageConfiguration(webView.page()));
+ ASSERT_EQ(context.get(), WKPageConfigurationGetContext(copiedConfiguration.get()));
+ ASSERT_EQ(WKWebsiteDataStoreGetDefaultDataStore(), WKPageConfigurationGetWebsiteDataStore(copiedConfiguration.get()));
+
+ WKRetainPtr<WKURLRef> url = adoptWK(Util::createURLForResource("simple", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+
+ didFinishLoad = false;
+ Util::run(&didFinishLoad);
+}
+
+TEST(WebKit2, WKPageConfigurationBasicWithNonPersistentDataStore)
+{
+ WKRetainPtr<WKPageConfigurationRef> configuration = adoptWK(WKPageConfigurationCreate());
+ WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreate());
+ WKPageConfigurationSetContext(configuration.get(), context.get());
+ WKRetainPtr<WKWebsiteDataStoreRef> websiteDataStore = adoptWK(WKWebsiteDataStoreCreateNonPersistentDataStore());
+ WKPageConfigurationSetWebsiteDataStore(configuration.get(), websiteDataStore.get());
+
+ PlatformWebView webView(configuration.get());
+ setPageLoaderClient(webView.page());
+
+ WKRetainPtr<WKPageConfigurationRef> copiedConfiguration = adoptWK(WKPageCopyPageConfiguration(webView.page()));
+ ASSERT_EQ(context.get(), WKPageConfigurationGetContext(copiedConfiguration.get()));
+ ASSERT_EQ(websiteDataStore.get(), WKPageConfigurationGetWebsiteDataStore(copiedConfiguration.get()));
+
+ WKRetainPtr<WKURLRef> url = adoptWK(Util::createURLForResource("simple", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+
+ didFinishLoad = false;
+ Util::run(&didFinishLoad);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WKPageCopySessionStateWithFiltering.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WKPageCopySessionStateWithFiltering.cpp
new file mode 100644
index 000000000..6ce49a13b
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WKPageCopySessionStateWithFiltering.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+
+namespace TestWebKitAPI {
+
+static bool didFinishLoad;
+static WKRetainPtr<WKSessionStateRef> sessionStateWithFirstItemRemoved;
+static WKRetainPtr<WKSessionStateRef> sessionStateWithAllItemsRemoved;
+
+static void didFinishLoadForFrame(WKPageRef, WKFrameRef, WKTypeRef, const void*)
+{
+ didFinishLoad = true;
+}
+
+static void setPageLoaderClient(WKPageRef page)
+{
+ WKPageLoaderClientV0 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+
+ loaderClient.base.version = 0;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+
+ WKPageSetPageLoaderClient(page, &loaderClient.base);
+}
+
+static bool filterFirstItemCallback(WKPageRef page, WKStringRef valueType, WKTypeRef value, void* context)
+{
+ if (!WKStringIsEqual(valueType, WKPageGetSessionBackForwardListItemValueType()))
+ return true;
+
+ ASSERT(WKGetTypeID(value) == WKBackForwardListItemGetTypeID());
+ WKBackForwardListItemRef backForwardListItem = static_cast<WKBackForwardListItemRef>(value);
+
+ WKRetainPtr<WKURLRef> url = adoptWK(WKBackForwardListItemCopyURL(backForwardListItem));
+ WKRetainPtr<WKStringRef> path = adoptWK(WKURLCopyLastPathComponent(url.get()));
+
+ return !WKStringIsEqualToUTF8CString(path.get(), "simple.html");
+}
+
+static bool filterAllItemsCallback(WKPageRef page, WKStringRef valueType, WKTypeRef value, void* context)
+{
+ return false;
+}
+
+static void createSessionStates(WKContextRef context)
+{
+ PlatformWebView webView(context);
+ setPageLoaderClient(webView.page());
+
+ WKPageLoadURL(webView.page(), adoptWK(Util::createURLForResource("simple", "html")).get());
+ Util::run(&didFinishLoad);
+ didFinishLoad = false;
+
+ WKPageLoadURL(webView.page(), adoptWK(Util::createURLForResource("simple2", "html")).get());
+ Util::run(&didFinishLoad);
+ didFinishLoad = false;
+
+ WKPageLoadURL(webView.page(), adoptWK(Util::createURLForResource("simple3", "html")).get());
+ Util::run(&didFinishLoad);
+ didFinishLoad = false;
+
+ WKPageGoBack(webView.page());
+ Util::run(&didFinishLoad);
+ didFinishLoad = false;
+
+ WKPageGoBack(webView.page());
+ Util::run(&didFinishLoad);
+ didFinishLoad = false;
+
+ // Should be back on simple.html at this point.
+
+ sessionStateWithFirstItemRemoved = adoptWK(static_cast<WKSessionStateRef>(WKPageCopySessionState(webView.page(), reinterpret_cast<void*>(1), filterFirstItemCallback)));
+ sessionStateWithAllItemsRemoved = adoptWK(static_cast<WKSessionStateRef>(WKPageCopySessionState(webView.page(), reinterpret_cast<void*>(1), filterAllItemsCallback)));
+}
+
+TEST(WebKit2, WKPageCopySessionStateWithFiltering)
+{
+ WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+
+ createSessionStates(context.get());
+
+ EXPECT_NOT_NULL(sessionStateWithFirstItemRemoved);
+ PlatformWebView webView1(context.get());
+ setPageLoaderClient(webView1.page());
+ WKPageRestoreFromSessionState(webView1.page(), sessionStateWithFirstItemRemoved.get());
+ Util::run(&didFinishLoad);
+ didFinishLoad = false;
+
+ WKBackForwardListRef backForwardList1 = WKPageGetBackForwardList(webView1.page());
+ EXPECT_EQ(0u, WKBackForwardListGetBackListCount(backForwardList1));
+ EXPECT_EQ(1u, WKBackForwardListGetForwardListCount(backForwardList1));
+
+ EXPECT_NOT_NULL(sessionStateWithAllItemsRemoved);
+ PlatformWebView webView2(context.get());
+ setPageLoaderClient(webView2.page());
+ WKPageRestoreFromSessionState(webView2.page(), sessionStateWithAllItemsRemoved.get());
+ // Because the session state ends up being empty, nothing is actually loaded.
+
+ WKBackForwardListRef backForwardList2 = WKPageGetBackForwardList(webView2.page());
+ EXPECT_EQ(0u, WKBackForwardListGetBackListCount(backForwardList2));
+ EXPECT_EQ(0u, WKBackForwardListGetForwardListCount(backForwardList2));
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WKPageGetScaleFactorNotZero.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WKPageGetScaleFactorNotZero.cpp
index 8ecf1659f..929baaa71 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/WKPageGetScaleFactorNotZero.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WKPageGetScaleFactorNotZero.cpp
@@ -24,6 +24,9 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
@@ -48,7 +51,7 @@ static void setPageLoaderClient(WKPageRef page)
WKPageSetPageLoaderClient(page, &loaderClient.base);
}
-static WKRetainPtr<WKDataRef> createSessionState(WKContextRef context)
+static WKRetainPtr<WKSessionStateRef> createSessionState(WKContextRef context)
{
PlatformWebView webView(context);
setPageLoaderClient(webView.page());
@@ -57,7 +60,7 @@ static WKRetainPtr<WKDataRef> createSessionState(WKContextRef context)
Util::run(&didFinishLoad);
didFinishLoad = false;
- return adoptWK(WKPageCopySessionState(webView.page(), 0, 0));
+ return adoptWK(static_cast<WKSessionStateRef>(WKPageCopySessionState(webView.page(), reinterpret_cast<void*>(1), nullptr)));
}
TEST(WebKit2, WKPageGetScaleFactorNotZero)
@@ -67,13 +70,15 @@ TEST(WebKit2, WKPageGetScaleFactorNotZero)
PlatformWebView webView(context.get());
setPageLoaderClient(webView.page());
- WKRetainPtr<WKDataRef> data = createSessionState(context.get());
- EXPECT_NOT_NULL(data);
+ auto sessionState = createSessionState(context.get());
+ EXPECT_NOT_NULL(sessionState);
- WKPageRestoreFromSessionState(webView.page(), data.get());
+ WKPageRestoreFromSessionState(webView.page(), sessionState.get());
Util::run(&didFinishLoad);
EXPECT_TRUE(WKPageGetScaleFactor(webView.page()) == 1.0);
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WKPageIsPlayingAudio.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WKPageIsPlayingAudio.cpp
new file mode 100644
index 000000000..1e848133f
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WKPageIsPlayingAudio.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+#include <JavaScriptCore/JSRetainPtr.h>
+#include <JavaScriptCore/JavaScriptCore.h>
+#include <WebKit/WKSerializedScriptValue.h>
+#include <WebKit/WKPagePrivate.h>
+#include <WebKit/WKPreferencesRef.h>
+#include <WebKit/WKPreferencesRefPrivate.h>
+
+// This test loads file-with-video.html. It first checks to make sure WKPageIsPlayingAudio() returns
+// false for the page. Then it calls a JavaScript method to play the video, waits for
+// WKPageUIClient::isPlayingAudioDidChange() to get called, and checks that WKPageIsPlayingAudio() now
+// returns true for the page.
+
+namespace TestWebKitAPI {
+
+static bool isMSEEnabledChanged;
+static bool isMSEEnabled;
+static bool didFinishLoad;
+static bool isPlayingAudioChanged;
+
+static void nullJavaScriptCallback(WKSerializedScriptValueRef, WKErrorRef error, void*)
+{
+}
+
+static void isMSEEnabledCallback(WKSerializedScriptValueRef serializedResultValue, WKErrorRef error, void*)
+{
+ JSGlobalContextRef scriptContext = JSGlobalContextCreate(0);
+
+ JSValueRef resultValue = WKSerializedScriptValueDeserialize(serializedResultValue, scriptContext, 0);
+ EXPECT_TRUE(JSValueIsBoolean(scriptContext, resultValue));
+
+ isMSEEnabledChanged = true;
+ isMSEEnabled = JSValueToBoolean(scriptContext, resultValue);
+
+ JSGlobalContextRelease(scriptContext);
+}
+
+static void didFinishLoadForFrame(WKPageRef page, WKFrameRef, WKTypeRef, const void*)
+{
+ didFinishLoad = true;
+}
+
+static void isPlayingAudioDidChangeCallback(WKPageRef page, const void*)
+{
+ isPlayingAudioChanged = true;
+}
+
+static void setUpClients(WKPageRef page)
+{
+ WKPageLoaderClientV0 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+
+ loaderClient.base.version = 0;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+
+ WKPageSetPageLoaderClient(page, &loaderClient.base);
+
+ WKPageUIClientV5 uiClient;
+ memset(&uiClient, 0, sizeof(uiClient));
+
+ uiClient.base.version = 5;
+ uiClient.isPlayingAudioDidChange = isPlayingAudioDidChangeCallback;
+
+ WKPageSetPageUIClient(page, &uiClient.base);
+}
+
+TEST(WebKit2, WKPageIsPlayingAudio)
+{
+ WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreate());
+
+ PlatformWebView webView(context.get());
+ setUpClients(webView.page());
+
+ WKRetainPtr<WKURLRef> url = adoptWK(Util::createURLForResource("file-with-video", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+
+ Util::run(&didFinishLoad);
+
+ EXPECT_FALSE(WKPageIsPlayingAudio(webView.page()));
+ WKPageRunJavaScriptInMainFrame(webView.page(), Util::toWK("playVideo()").get(), 0, nullJavaScriptCallback);
+
+ Util::run(&isPlayingAudioChanged);
+ EXPECT_TRUE(WKPageIsPlayingAudio(webView.page()));
+}
+
+TEST(WebKit2, MSEIsPlayingAudio)
+{
+ WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreate());
+
+ WKRetainPtr<WKPageGroupRef> pageGroup(AdoptWK, WKPageGroupCreateWithIdentifier(Util::toWK("MSEIsPlayingAudioPageGroup").get()));
+ WKPreferencesRef preferences = WKPageGroupGetPreferences(pageGroup.get());
+ WKPreferencesSetMediaSourceEnabled(preferences, true);
+ WKPreferencesSetFileAccessFromFileURLsAllowed(preferences, true);
+
+ PlatformWebView webView(context.get(), pageGroup.get());
+ setUpClients(webView.page());
+
+ WKRetainPtr<WKURLRef> url = adoptWK(Util::createURLForResource("file-with-mse", "html"));
+ didFinishLoad = false;
+ WKPageLoadURL(webView.page(), url.get());
+
+ Util::run(&didFinishLoad);
+
+ // Bail out of the test early if the platform does not support MSE.
+ isMSEEnabledChanged = false;
+ WKPageRunJavaScriptInMainFrame(webView.page(), Util::toWK("window.MediaSource !== undefined").get(), 0, isMSEEnabledCallback);
+ Util::run(&isMSEEnabledChanged);
+ if (!isMSEEnabled)
+ return;
+
+ EXPECT_FALSE(WKPageIsPlayingAudio(webView.page()));
+ isPlayingAudioChanged = false;
+ WKPageRunJavaScriptInMainFrame(webView.page(), Util::toWK("playVideo()").get(), 0, nullJavaScriptCallback);
+
+ Util::run(&isPlayingAudioChanged);
+ EXPECT_TRUE(WKPageIsPlayingAudio(webView.page()));
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WKPreferences.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WKPreferences.cpp
index 976e7041b..7971b0b27 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/WKPreferences.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WKPreferences.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
-#include <WebKit2/WKPreferencesPrivate.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKPreferencesRefPrivate.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -41,15 +44,15 @@ TEST(WebKit2, WKPreferencesBasic)
TEST(WebKit2, WKPreferencesDefaults)
{
-#if PLATFORM(WIN)
- static const char* expectedStandardFontFamily = "Times New Roman";
+#if PLATFORM(GTK) || PLATFORM(EFL)
+ static const char* expectedStandardFontFamily = "Times";
static const char* expectedFixedFontFamily = "Courier New";
- static const char* expectedSerifFontFamily = "Times New Roman";
- static const char* expectedSansSerifFontFamily = "Arial";
+ static const char* expectedSerifFontFamily = "Times";
+ static const char* expectedSansSerifFontFamily = "Helvetica";
static const char* expectedCursiveFontFamily = "Comic Sans MS";
- static const char* expectedFantasyFontFamily = "Comic Sans MS";
- static const char* expectedPictographFontFamily = "Times New Roman";
-#elif PLATFORM(MAC)
+ static const char* expectedFantasyFontFamily = "Impact";
+ static const char* expectedPictographFontFamily = "Times";
+#elif WK_HAVE_C_SPI
static const char* expectedStandardFontFamily = "Times";
static const char* expectedFixedFontFamily = "Courier";
static const char* expectedSerifFontFamily = "Times";
@@ -57,14 +60,14 @@ TEST(WebKit2, WKPreferencesDefaults)
static const char* expectedCursiveFontFamily = "Apple Chancery";
static const char* expectedFantasyFontFamily = "Papyrus";
static const char* expectedPictographFontFamily = "Apple Color Emoji";
-#elif PLATFORM(GTK) || PLATFORM(EFL)
+#elif PLATFORM(IOS)
static const char* expectedStandardFontFamily = "Times";
- static const char* expectedFixedFontFamily = "Courier New";
+ static const char* expectedFixedFontFamily = "Courier";
static const char* expectedSerifFontFamily = "Times";
static const char* expectedSansSerifFontFamily = "Helvetica";
- static const char* expectedCursiveFontFamily = "Comic Sans MS";
- static const char* expectedFantasyFontFamily = "Impact";
- static const char* expectedPictographFontFamily = "Times";
+ static const char* expectedCursiveFontFamily = "Snell Roundhand";
+ static const char* expectedFantasyFontFamily = "Papyrus";
+ static const char* expectedPictographFontFamily = "AppleColorEmoji";
#endif
WKPreferencesRef preference = WKPreferencesCreate();
@@ -91,11 +94,7 @@ TEST(WebKit2, WKPreferencesDefaults)
EXPECT_FALSE(WKPreferencesGetDeveloperExtrasEnabled(preference));
EXPECT_TRUE(WKPreferencesGetTextAreasAreResizable(preference));
-#if PLATFORM(WIN)
- EXPECT_EQ(kWKFontSmoothingLevelWindows, WKPreferencesGetFontSmoothingLevel(preference));
-#else
EXPECT_EQ(kWKFontSmoothingLevelMedium, WKPreferencesGetFontSmoothingLevel(preference));
-#endif
EXPECT_TRUE(WKPreferencesGetAcceleratedCompositingEnabled(preference));
EXPECT_FALSE(WKPreferencesGetCompositingBordersVisible(preference));
@@ -122,3 +121,5 @@ TEST(WebKit2, WKPreferencesCopying)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/GtkLauncher/LauncherInspectorWindow.h b/Tools/TestWebKitAPI/Tests/WebKit2/WKRetainPtr.cpp
index f7091d238..860d7d48d 100644
--- a/Tools/GtkLauncher/LauncherInspectorWindow.h
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WKRetainPtr.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Igalia S.L.
+ * Copyright (C) 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,29 +23,36 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef LauncherInspectorWindow_h
-#define LauncherInspectorWindow_h
+#include "config.h"
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
+#if WK_HAVE_C_SPI
-G_BEGIN_DECLS
+#include "PlatformUtilities.h"
+#include <wtf/HashMap.h>
-#define LAUNCHER_TYPE_INSPECTOR_WINDOW (launcher_inspector_window_get_type())
-#define LAUNCHER_INSPECTOR_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), LAUNCHER_TYPE_INSPECTOR_WINDOW, LauncherInspectorWindow))
-#define LAUNCHER_IS_INSPECTOR_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), LAUNCHER_TYPE_INSPECTOR_WINDOW))
-#define LAUNCHER_INSPECTOR_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), LAUNCHER_TYPE_INSPECTOR_WINDOW, LauncherInspectorWindowClass))
-#define LAUNCHER_IS_INSPECTOR_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), LAUNCHER_TYPE_INSPECTOR_WINDOW))
-#define LAUNCHER_INSPECTOR_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), LAUNCHER_TYPE_INSPECTOR_WINDOW, LauncherInspectorWindowClass))
+namespace TestWebKitAPI {
-typedef struct _LauncherInspectorWindow LauncherInspectorWindow;
-typedef struct _LauncherInspectorWindowClass LauncherInspectorWindowClass;
+TEST(WebKit2, WKRetainPtr)
+{
+ WKRetainPtr<WKStringRef> string1 = adoptWK(WKStringCreateWithUTF8CString("a"));
+ WKRetainPtr<WKStringRef> string2 = adoptWK(WKStringCreateWithUTF8CString("a"));
+ WKRetainPtr<WKStringRef> string3 = adoptWK(WKStringCreateWithUTF8CString("a"));
+ WKRetainPtr<WKStringRef> string4 = adoptWK(WKStringCreateWithUTF8CString("a"));
-GType launcher_inspector_window_get_type(void);
+ HashMap<WKRetainPtr<WKStringRef>, int> map;
-GtkWidget *launcherInspectorWindowNew(WebKitWebInspector *, GtkWindow *parent);
-WebKitWebView *launcherInspectorWindowGetWebView(LauncherInspectorWindow *);
+ map.set(string2, 2);
+ map.set(string1, 1);
-G_END_DECLS
+ EXPECT_TRUE(map.contains(string1));
+ EXPECT_TRUE(map.contains(string2));
+ EXPECT_FALSE(map.contains(string3));
+ EXPECT_FALSE(map.contains(string4));
+
+ EXPECT_EQ(1, map.get(string1));
+ EXPECT_EQ(2, map.get(string2));
+}
+
+} // namespace TestWebKitAPI
#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WKString.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WKString.cpp
index b67235932..b4167be81 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/WKString.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WKString.cpp
@@ -25,6 +25,8 @@
#include "config.h"
+#if WK_HAVE_C_SPI
+
namespace TestWebKitAPI {
TEST(WebKit2, WKString)
@@ -69,3 +71,5 @@ TEST(WebKit2, WKString)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WKStringJSString.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WKStringJSString.cpp
index cdba57de4..8b6e08b9d 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/WKStringJSString.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WKStringJSString.cpp
@@ -24,7 +24,10 @@
*/
#include "config.h"
-#include <WebKit2/WKStringPrivate.h>
+
+#if WK_HAVE_C_SPI
+
+#include <WebKit/WKStringPrivate.h>
#include <JavaScriptCore/JSStringRef.h>
namespace TestWebKitAPI {
@@ -48,3 +51,5 @@ TEST(WebKit2, WKStringJSString)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WebArchive.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WebArchive.cpp
new file mode 100644
index 000000000..06d673e21
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WebArchive.cpp
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include <CoreFoundation/CoreFoundation.h>
+#include <WebKit/WKURLCF.h>
+#include <WebKit/WKContextPrivate.h>
+#include <wtf/RetainPtr.h>
+
+namespace TestWebKitAPI {
+
+static bool didFinishLoad;
+static bool didReceiveMessage;
+
+static void didReceiveMessageFromInjectedBundle(WKContextRef, WKStringRef messageName, WKTypeRef body, const void*)
+{
+ didReceiveMessage = true;
+
+ EXPECT_WK_STREQ("DidGetWebArchive", messageName);
+ EXPECT_TRUE(body);
+ EXPECT_EQ(WKDataGetTypeID(), WKGetTypeID(body));
+ WKDataRef receivedData = static_cast<WKDataRef>(body);
+
+ // Do basic sanity checks on the returned webarchive. We have more thorough checks in LayoutTests.
+ size_t size = WKDataGetSize(receivedData);
+ const unsigned char* bytes = WKDataGetBytes(receivedData);
+ RetainPtr<CFDataRef> data = adoptCF(CFDataCreate(0, bytes, size));
+ RetainPtr<CFPropertyListRef> propertyList = adoptCF(CFPropertyListCreateWithData(0, data.get(), kCFPropertyListImmutable, 0, 0));
+ EXPECT_TRUE(propertyList);
+
+ // It should be a dictionary.
+ EXPECT_EQ(CFDictionaryGetTypeID(), CFGetTypeID(propertyList.get()));
+ CFDictionaryRef dictionary = (CFDictionaryRef)propertyList.get();
+
+ // It should have a main resource.
+ CFTypeRef mainResource = CFDictionaryGetValue(dictionary, CFSTR("WebMainResource"));
+ EXPECT_TRUE(mainResource);
+ EXPECT_EQ(CFDictionaryGetTypeID(), CFGetTypeID(mainResource));
+ CFDictionaryRef mainResourceDictionary = (CFDictionaryRef)mainResource;
+
+ // Main resource should have a non-empty url and mime type.
+ CFTypeRef url = CFDictionaryGetValue(mainResourceDictionary, CFSTR("WebResourceURL"));
+ EXPECT_TRUE(url);
+ EXPECT_EQ(CFStringGetTypeID(), CFGetTypeID(url));
+ EXPECT_NE(CFStringGetLength((CFStringRef)url), 0);
+
+ CFTypeRef mimeType = CFDictionaryGetValue(mainResourceDictionary, CFSTR("WebResourceMIMEType"));
+ EXPECT_TRUE(mimeType);
+ EXPECT_EQ(CFStringGetTypeID(), CFGetTypeID(mimeType));
+ EXPECT_NE(CFStringGetLength((CFStringRef)mimeType), 0);
+
+ // Main resource dictionary should have a "WebResourceData" key.
+ CFTypeRef resourceData = CFDictionaryGetValue(mainResourceDictionary, CFSTR("WebResourceData"));
+ EXPECT_TRUE(resourceData);
+ EXPECT_EQ(CFDataGetTypeID(), CFGetTypeID(resourceData));
+
+ RetainPtr<CFStringRef> stringData = adoptCF(CFStringCreateFromExternalRepresentation(0, (CFDataRef)resourceData, kCFStringEncodingUTF8));
+ EXPECT_TRUE(stringData);
+
+ // It should contain the string "Simple HTML file." in it.
+ bool foundString = CFStringFind(stringData.get(), CFSTR("Simple HTML file."), 0).location != kCFNotFound;
+ EXPECT_TRUE(foundString);
+}
+
+static void setInjectedBundleClient(WKContextRef context)
+{
+ WKContextInjectedBundleClientV0 injectedBundleClient;
+ memset(&injectedBundleClient, 0, sizeof(injectedBundleClient));
+
+ injectedBundleClient.base.version = 0;
+ injectedBundleClient.didReceiveMessageFromInjectedBundle = didReceiveMessageFromInjectedBundle;
+
+ WKContextSetInjectedBundleClient(context, &injectedBundleClient.base);
+}
+
+static void didFinishLoadForFrame(WKPageRef page, WKFrameRef, WKTypeRef, const void*)
+{
+ didFinishLoad = true;
+}
+
+TEST(WebKit2, WebArchive)
+{
+ WKRetainPtr<WKContextRef> context = adoptWK(Util::createContextForInjectedBundleTest("WebArchiveTest"));
+ setInjectedBundleClient(context.get());
+
+ PlatformWebView webView(context.get());
+
+ WKPageLoaderClientV3 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+
+ loaderClient.base.version = 3;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+
+ WKPageSetPageLoaderClient(webView.page(), &loaderClient.base);
+
+ WKPageLoadURL(webView.page(), adoptWK(Util::createURLForResource("simple", "html")).get());
+
+ // Wait till the load finishes before getting the web archive.
+ Util::run(&didFinishLoad);
+ WKContextPostMessageToInjectedBundle(context.get(), Util::toWK("GetWebArchive").get(), webView.page());
+
+ // Wait till we have received the web archive from the injected bundle.
+ Util::run(&didReceiveMessage);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WebArchive_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WebArchive_Bundle.cpp
new file mode 100644
index 000000000..11109fee0
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WebArchive_Bundle.cpp
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "InjectedBundleTest.h"
+
+#include "PlatformUtilities.h"
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundleFrame.h>
+
+namespace TestWebKitAPI {
+
+class WebArchiveTest : public InjectedBundleTest {
+public:
+ WebArchiveTest(const std::string& identifier);
+
+private:
+ virtual void didReceiveMessage(WKBundleRef, WKStringRef messageName, WKTypeRef messageBody);
+};
+
+static InjectedBundleTest::Register<WebArchiveTest> registrar("WebArchiveTest");
+
+WebArchiveTest::WebArchiveTest(const std::string& identifier)
+ : InjectedBundleTest(identifier)
+{
+}
+
+void WebArchiveTest::didReceiveMessage(WKBundleRef bundle, WKStringRef messageName, WKTypeRef body)
+{
+ if (!WKStringIsEqualToUTF8CString(messageName, "GetWebArchive"))
+ return;
+
+ if (WKGetTypeID(body) != WKBundlePageGetTypeID())
+ return;
+
+ WKBundleFrameRef frame = WKBundlePageGetMainFrame(static_cast<WKBundlePageRef>(body));
+ if (!frame)
+ return;
+ WKBundlePostMessage(bundle, Util::toWK("DidGetWebArchive").get(), adoptWK(WKBundleFrameCopyWebArchive(frame)).get());
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WebCoreStatisticsWithNoWebProcess.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WebCoreStatisticsWithNoWebProcess.cpp
new file mode 100644
index 000000000..ff5eef04d
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WebCoreStatisticsWithNoWebProcess.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "Test.h"
+
+namespace TestWebKitAPI {
+
+static bool done;
+
+// Callback for WKContextGetStatistics.
+static void wkContextGetStatisticsCallback(WKDictionaryRef statistics, WKErrorRef error, void* functionContext)
+{
+ EXPECT_NOT_NULL(error);
+ done = true;
+}
+
+TEST(WebKit2, WebCoreStatisticsWithNoWebProcess)
+{
+ WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreate());
+
+ WKContextGetStatistics(context.get(), 0, wkContextGetStatisticsCallback);
+
+ Util::run(&done);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WillLoad.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WillLoad.cpp
index 0f0bf4caf..83d63ab18 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/WillLoad.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WillLoad.cpp
@@ -24,12 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "Test.h"
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <wtf/OwnPtr.h>
-#include <wtf/PassOwnPtr.h>
namespace TestWebKitAPI {
@@ -41,7 +42,7 @@ public:
}
WKRetainPtr<WKContextRef> context;
- OwnPtr<PlatformWebView> webView;
+ std::unique_ptr<PlatformWebView> webView;
WKRetainPtr<WKStringRef> messageName;
WKRetainPtr<WKTypeRef> messageBody;
@@ -71,7 +72,7 @@ public:
context = adoptWK(Util::createContextForInjectedBundleTest("WillLoadTest"));
setInjectedBundleClient(context.get(), this);
- webView = adoptPtr(new PlatformWebView(context.get()));
+ webView = std::make_unique<PlatformWebView>(context.get());
didReceiveMessage = false;
}
@@ -239,3 +240,5 @@ TEST_F(WebKit2WillLoadTest, WKPageLoadPlainTextString)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WillLoad_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WillLoad_Bundle.cpp
index 783aebe7a..091e5a942 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/WillLoad_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WillLoad_Bundle.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKBundlePage.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -47,7 +50,7 @@ private:
WKDictionarySetItem(messageBody.get(), Util::toWK("URLRequestReturn").get(), request);
WKDictionarySetItem(messageBody.get(), Util::toWK("UserDataReturn").get(), userData);
- WKBundlePostMessage(InjectedBundleController::shared().bundle(), Util::toWK("WillLoadURLRequestReturn").get(), messageBody.get());
+ WKBundlePostMessage(InjectedBundleController::singleton().bundle(), Util::toWK("WillLoadURLRequestReturn").get(), messageBody.get());
}
static void willLoadDataRequest(WKBundlePageRef page, WKURLRequestRef request, WKDataRef data, WKStringRef MIMEType, WKStringRef encodingName, WKURLRef unreachableURL, WKTypeRef userData, const void *clientInfo)
@@ -61,7 +64,7 @@ private:
WKDictionarySetItem(messageBody.get(), Util::toWK("UnreachableURLReturn").get(), unreachableURL);
WKDictionarySetItem(messageBody.get(), Util::toWK("UserDataReturn").get(), userData);
- WKBundlePostMessage(InjectedBundleController::shared().bundle(), Util::toWK("WillLoadDataRequestReturn").get(), messageBody.get());
+ WKBundlePostMessage(InjectedBundleController::singleton().bundle(), Util::toWK("WillLoadDataRequestReturn").get(), messageBody.get());
}
@@ -82,3 +85,5 @@ private:
static InjectedBundleTest::Register<WillLoadTest> registrar("WillLoadTest");
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WillSendSubmitEvent.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WillSendSubmitEvent.cpp
index ee5934688..951aaf005 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/WillSendSubmitEvent.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WillSendSubmitEvent.cpp
@@ -24,6 +24,9 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
@@ -77,3 +80,5 @@ TEST(WebKit2, WillSendSubmitEvent)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WillSendSubmitEvent_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WillSendSubmitEvent_Bundle.cpp
index e85ca256f..fa7d2a9a7 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/WillSendSubmitEvent_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WillSendSubmitEvent_Bundle.cpp
@@ -24,10 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKBundlePage.h>
+#include <WebKit/WKBundlePage.h>
namespace TestWebKitAPI {
@@ -42,7 +45,7 @@ static InjectedBundleTest::Register<WillSendSubmitEventTest> registrar("WillSend
static void willSendSubmitEvent(WKBundlePageRef, WKBundleNodeHandleRef, WKBundleFrameRef, WKBundleFrameRef, WKDictionaryRef values, const void*)
{
- WKBundlePostMessage(InjectedBundleController::shared().bundle(), Util::toWK("DidReceiveWillSendSubmitEvent").get(), values);
+ WKBundlePostMessage(InjectedBundleController::singleton().bundle(), Util::toWK("DidReceiveWillSendSubmitEvent").get(), values);
}
WillSendSubmitEventTest::WillSendSubmitEventTest(const std::string& identifier)
@@ -63,3 +66,5 @@ void WillSendSubmitEventTest::didCreatePage(WKBundleRef bundle, WKBundlePageRef
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/all-content-in-one-iframe.html b/Tools/TestWebKitAPI/Tests/WebKit2/all-content-in-one-iframe.html
new file mode 100644
index 000000000..6f45cbd6b
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/all-content-in-one-iframe.html
@@ -0,0 +1 @@
+<iframe src="lots-of-text.html"></iframe>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/associate-form-controls.html b/Tools/TestWebKitAPI/Tests/WebKit2/associate-form-controls.html
new file mode 100644
index 000000000..906246a54
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/associate-form-controls.html
@@ -0,0 +1,31 @@
+<html>
+<head>
+ <script>
+ function addForm()
+ {
+ var form = document.createElement("form");
+ form.id = "login_form";
+
+ var usernameField = document.createElement("input");
+ usernameField.id = "username";
+ usernameField.type = "text";
+ form.appendChild(usernameField);
+
+ document.body.appendChild(form);
+ }
+
+ function addPasswordFieldToForm()
+ {
+ var passwordField = document.createElement("input");
+ passwordField.id = "password";
+ passwordField.type = "password";
+
+ var form = document.getElementById("login_form");
+ form.appendChild(passwordField);
+ }
+ </script>
+</head>
+<body onload="addForm()">
+<button onclick="addPasswordFieldToForm()">Manual Testing: Add the password field</button>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/auto-submitting-form.html b/Tools/TestWebKitAPI/Tests/WebKit2/auto-submitting-form.html
new file mode 100644
index 000000000..9ed815e03
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/auto-submitting-form.html
@@ -0,0 +1,20 @@
+<html>
+ <head>
+ <script>
+ function submitFormIfNecessary()
+ {
+ if (window.location.search)
+ return;
+ document.forms[0].submit.click();
+ }
+ </script>
+ </head>
+ <body onload="submitFormIfNecessary()">
+ <form action="#" method="GET">
+ <input type="text" name="textField" value="text field">
+ <input type="password" name="passwordField" value="password field">
+ <input type="hidden" name="hiddenField" value="hidden field">
+ <input type="submit" name="submit">
+ </form>
+ </body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/bundle-file.html b/Tools/TestWebKitAPI/Tests/WebKit2/bundle-file.html
new file mode 100644
index 000000000..f426ebdb0
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/bundle-file.html
@@ -0,0 +1,16 @@
+<html>
+<head>
+ <script>
+ function testFile(file)
+ {
+ if (!(file instanceof File))
+ return false;
+
+ return true;
+ }
+ </script>
+</head>
+<body>
+ File test.
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/close-from-within-create-page.html b/Tools/TestWebKitAPI/Tests/WebKit2/close-from-within-create-page.html
new file mode 100644
index 000000000..51c7981c1
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/close-from-within-create-page.html
@@ -0,0 +1,16 @@
+<html>
+<script>
+function runTest()
+{
+ if (document.location.search === "?opened-window") {
+ alert(window.sessionStorage['storageKey'])
+ return;
+ }
+
+ window.sessionStorage['storageKey'] = 'value';
+ window.open("close-from-within-create-page.html?opened-window");
+}
+</script>
+<body onload="runTest()">
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/custom-protocol-sync-xhr.html b/Tools/TestWebKitAPI/Tests/WebKit2/custom-protocol-sync-xhr.html
new file mode 100644
index 000000000..6cf00b6ca
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/custom-protocol-sync-xhr.html
@@ -0,0 +1,6 @@
+<script>
+ var request = new XMLHttpRequest();
+ request.open('GET', 'http://test', false);
+ request.send(null);
+ window._testResult = request.responseText;
+</script> \ No newline at end of file
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/execCopy.html b/Tools/TestWebKitAPI/Tests/WebKit2/execCopy.html
new file mode 100644
index 000000000..cf4608ebd
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/execCopy.html
@@ -0,0 +1,15 @@
+<html>
+<head>
+<script type="text/javascript">
+ function doCopy() {
+ document.execCommand("selectAll", true);
+ document.execCommand("copy");
+ }
+</script>
+</head>
+<body onLoad="doCopy()">
+ <div>Hello world.</div>
+ <div><b>Hello</b><i> world</i></div>
+ <div style="border: solid red 1px">Hello world</div>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/file-with-anchor.html b/Tools/TestWebKitAPI/Tests/WebKit2/file-with-anchor.html
new file mode 100644
index 000000000..8ea866ba9
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/file-with-anchor.html
@@ -0,0 +1,19 @@
+<html>
+<head>
+ <script>
+ function clickLink()
+ {
+ var evt = document.createEvent("MouseEvent");
+ evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+ var link = document.querySelector('a');
+ link.dispatchEvent(evt);
+ }
+ </script>
+</head>
+<body>
+ <a href="#anchor">Link to anchor</a><br>
+ In between.<br>
+ <span id="anchor">Anchor</span><br>
+ After the anchor.<br>
+ </body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/file-with-mse.html b/Tools/TestWebKitAPI/Tests/WebKit2/file-with-mse.html
new file mode 100644
index 000000000..413eed6e8
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/file-with-mse.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script>
+ var source;
+ var request;
+
+ function playVideo()
+ {
+ request = new XMLHttpRequest();
+ request.responseType = 'arraybuffer';
+ request.open('GET', 'test-mse.mp4', true);
+ request.addEventListener('load', load);
+ request.send();
+ }
+
+ function load(event)
+ {
+ source = new MediaSource();
+ source.addEventListener('sourceopen', sourceopen);
+ var video = document.getElementById('test-video');
+ video.src = URL.createObjectURL(source);
+ }
+
+ function sourceopen(event)
+ {
+ var sourceBuffer = source.addSourceBuffer('video/mp4;codecs="avc1.4D4001,mp4a.40.2"');
+ sourceBuffer.appendBuffer(request.response);
+ sourceBuffer.addEventListener('updateend', updateend);
+ }
+
+ function updateend(event)
+ {
+ document.getElementById('test-video').play();
+ }
+ </script>
+</head>
+<body>
+ <p>
+ <video id="test-video" controls></video>
+ </p>
+ <p>
+ <button onclick="playVideo()">Play video</button>
+ </p>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/file-with-video.html b/Tools/TestWebKitAPI/Tests/WebKit2/file-with-video.html
new file mode 100644
index 000000000..aa2259a0f
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/file-with-video.html
@@ -0,0 +1,18 @@
+<html>
+<head>
+ <script>
+ function playVideo()
+ {
+ document.getElementById("test-video").play();
+ }
+ </script>
+</head>
+<body>
+ <p>
+ <video id="test-video" src="test.mp4" controls></video>
+ </p>
+ <p>
+ <button onclick="playVideo()">Play Video</button>
+ </p>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/find.html b/Tools/TestWebKitAPI/Tests/WebKit2/find.html
new file mode 100644
index 000000000..d9659119d
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/find.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+ Test search. Hello Hello Hello!
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/findRanges.html b/Tools/TestWebKitAPI/Tests/WebKit2/findRanges.html
new file mode 100644
index 000000000..e10bbeb47
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/findRanges.html
@@ -0,0 +1,11 @@
+<html>
+<body>Test search. Hello world, Hello crazy world, Hello!</body>
+<script>
+ var s = window.getSelection();
+ var r = document.createRange();
+
+ r.setStart(document.body.firstChild, 38);
+ r.setEnd(document.body.firstChild, 43);
+ s.addRange(r);
+</script>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/geolocationGetCurrentPosition.html b/Tools/TestWebKitAPI/Tests/WebKit2/geolocationGetCurrentPosition.html
new file mode 100644
index 000000000..099f51536
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/geolocationGetCurrentPosition.html
@@ -0,0 +1,3 @@
+<script>
+navigator.geolocation.getCurrentPosition(function() { });
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/geolocationGetCurrentPositionWithHighAccuracy.html b/Tools/TestWebKitAPI/Tests/WebKit2/geolocationGetCurrentPositionWithHighAccuracy.html
new file mode 100644
index 000000000..26a314858
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/geolocationGetCurrentPositionWithHighAccuracy.html
@@ -0,0 +1,3 @@
+<script>
+navigator.geolocation.getCurrentPosition(function() { }, function() {}, { enableHighAccuracy:true });
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/geolocationWatchPosition.html b/Tools/TestWebKitAPI/Tests/WebKit2/geolocationWatchPosition.html
new file mode 100644
index 000000000..24788b780
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/geolocationWatchPosition.html
@@ -0,0 +1,3 @@
+<script>
+navigator.geolocation.watchPosition(function() { });
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/geolocationWatchPositionWithHighAccuracy.html b/Tools/TestWebKitAPI/Tests/WebKit2/geolocationWatchPositionWithHighAccuracy.html
new file mode 100644
index 000000000..aba98fce7
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/geolocationWatchPositionWithHighAccuracy.html
@@ -0,0 +1,3 @@
+<script>
+navigator.geolocation.watchPosition(function() { }, function() {}, { enableHighAccuracy:true });
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/getUserMedia.html b/Tools/TestWebKitAPI/Tests/WebKit2/getUserMedia.html
new file mode 100644
index 000000000..e54f853bf
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/getUserMedia.html
@@ -0,0 +1,14 @@
+<script>
+function gotUserMedia(mediaStream)
+{
+ console.log("Got user media");
+}
+
+function userMediaError(error)
+{
+ console.log(error);
+}
+
+var options = { audio: false, video: true};
+navigator.webkitGetUserMedia(options, gotUserMedia, userMediaError);
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/gtk/InputMethodFilter.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/gtk/InputMethodFilter.cpp
index 4aab7c0a2..4a0e684d6 100644
--- a/Tools/TestWebKitAPI/Tests/gtk/InputMethodFilter.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/gtk/InputMethodFilter.cpp
@@ -25,44 +25,45 @@
#include "config.h"
-#include "GtkInputMethodFilter.h"
#include "WTFStringUtilities.h"
+#include <WebKit/InputMethodFilter.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
-#include <wtf/gobject/GUniquePtr.h>
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
+#include <wtf/glib/GUniquePtr.h>
#include <wtf/text/CString.h>
-using namespace WebCore;
+using namespace WebKit;
namespace TestWebKitAPI {
-class TestInputMethodFilter : public GtkInputMethodFilter {
+class TestInputMethodFilter : public InputMethodFilter {
public:
TestInputMethodFilter()
: m_testWindow(gtk_window_new(GTK_WINDOW_POPUP))
{
- gtk_widget_show(m_testWindow.get());
- setWidget(m_testWindow.get());
+ setTestingMode(true);
- // Focus in is necessary to activate the default input method in the multicontext.
- notifyFocusedIn();
+ gtk_widget_show(m_testWindow);
+ gtk_im_context_set_client_window(context(), gtk_widget_get_window(m_testWindow));
+
+ setEnabled(true);
}
- Vector<String>& events() { return m_events; }
+ ~TestInputMethodFilter()
+ {
+ gtk_widget_destroy(m_testWindow);
+ }
- void sendKeyEventToFilter(unsigned int gdkKeyValue, GdkEventType type, unsigned int modifiers = 0)
+ void sendKeyEventToFilter(unsigned gdkKeyValue, GdkEventType type, unsigned modifiers = 0)
{
GdkEvent* event = gdk_event_new(type);
event->key.keyval = gdkKeyValue;
event->key.state = modifiers;
- event->key.window = gtk_widget_get_window(m_testWindow.get());
+ event->key.window = gtk_widget_get_window(m_testWindow);
event->key.time = GDK_CURRENT_TIME;
g_object_ref(event->key.window);
-
-#ifndef GTK_API_VERSION_2
gdk_event_set_device(event, gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gdk_display_get_default())));
-#endif
GUniqueOutPtr<GdkKeymapKey> keys;
gint nKeys;
@@ -73,70 +74,17 @@ public:
gdk_event_free(event);
}
- void sendPressAndReleaseKeyEventPairToFilter(unsigned int gdkKeyValue, unsigned int modifiers = 0)
+ void sendPressAndReleaseKeyEventPairToFilter(unsigned gdkKeyValue, unsigned modifiers = 0)
{
sendKeyEventToFilter(gdkKeyValue, GDK_KEY_PRESS, modifiers);
sendKeyEventToFilter(gdkKeyValue, GDK_KEY_RELEASE, modifiers);
}
-protected:
- virtual bool sendSimpleKeyEvent(GdkEventKey* event, WTF::String eventString, EventFakedForComposition faked)
- {
- const char* eventType = event->type == GDK_KEY_RELEASE ? "release" : "press";
- const char* fakedString = faked == EventFaked ? " (faked)" : "";
- if (!eventString.isNull())
- m_events.append(String::format("sendSimpleKeyEvent type=%s keycode=%x text='%s'%s", eventType, event->keyval, eventString.utf8().data(), fakedString));
- else
- m_events.append(String::format("sendSimpleKeyEvent type=%s keycode=%x%s", eventType, event->keyval, fakedString));
-
- return true;
- }
-
- virtual bool sendKeyEventWithCompositionResults(GdkEventKey* event, ResultsToSend resultsToSend, EventFakedForComposition faked)
- {
- const char* eventType = event->type == GDK_KEY_RELEASE ? "release" : "press";
- const char* fakedString = faked == EventFaked ? " (faked)" : "";
- m_events.append(String::format("sendKeyEventWithCompositionResults type=%s keycode=%u%s", eventType, event->keyval, fakedString));
-
- if (resultsToSend & Composition && !m_confirmedComposition.isNull())
- confirmCompositionText(m_confirmedComposition);
- if (resultsToSend & Preedit && !m_preedit.isNull())
- setPreedit(m_preedit, m_cursorOffset);
-
- return true;
- }
-
- virtual bool canEdit()
- {
- return true;
- }
-
- virtual void confirmCompositionText(String text)
- {
- m_events.append(String::format("confirmComposition '%s'", text.utf8().data()));
- }
-
- virtual void confirmCurrentComposition()
- {
- m_events.append(String("confirmCurrentcomposition"));
- }
-
- virtual void cancelCurrentComposition()
- {
- m_events.append(String("cancelCurrentComposition"));
- }
-
- virtual void setPreedit(String preedit, int cursorOffset)
- {
- m_events.append(String::format("setPreedit text='%s' cursorOffset=%i", preedit.utf8().data(), cursorOffset));
- }
-
private:
- GRefPtr<GtkWidget> m_testWindow;
- Vector<String> m_events;
+ GtkWidget* m_testWindow;
};
-TEST(GTK, GtkInputMethodFilterSimple)
+TEST(WebKit2, InputMethodFilterSimple)
{
TestInputMethodFilter inputMethodFilter;
inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_g);
@@ -154,7 +102,7 @@ TEST(GTK, GtkInputMethodFilterSimple)
ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=6b"), events[5]);
}
-TEST(GTK, GtkInputMethodFilterUnicodeSequence)
+TEST(WebKit2, InputMethodFilterUnicodeSequence)
{
TestInputMethodFilter inputMethodFilter;
@@ -201,7 +149,7 @@ TEST(GTK, GtkInputMethodFilterUnicodeSequence)
ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=ffe3"), events[20]);
}
-TEST(GTK, GtkInputMethodFilterComposeKey)
+TEST(WebKit2, InputMethodFilterComposeKey)
{
TestInputMethodFilter inputMethodFilter;
@@ -225,7 +173,7 @@ static void temporaryGetPreeditStringOverride(GtkIMContext*, char** string, Pang
*cursorPosition = 3;
}
-TEST(GTK, GtkInputMethodFilterContextEventsWithoutKeyEvents)
+TEST(WebKit2, InputMethodFilterContextEventsWithoutKeyEvents)
{
TestInputMethodFilter inputMethodFilter;
@@ -267,7 +215,7 @@ static void verifyCanceledComposition(const Vector<String>& events)
ASSERT(gSawContextReset);
}
-TEST(GTK, GtkInputMethodFilterContextFocusOutDuringOngoingComposition)
+TEST(WebKit2, InputMethodFilterContextFocusOutDuringOngoingComposition)
{
TestInputMethodFilter inputMethodFilter;
@@ -287,7 +235,7 @@ TEST(GTK, GtkInputMethodFilterContextFocusOutDuringOngoingComposition)
contextClass->reset = previousCallback;
}
-TEST(GTK, GtkInputMethodFilterContextMouseClickDuringOngoingComposition)
+TEST(WebKit2, InputMethodFilterContextMouseClickDuringOngoingComposition)
{
TestInputMethodFilter inputMethodFilter;
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/icon.png b/Tools/TestWebKitAPI/Tests/WebKit2/icon.png
new file mode 100644
index 000000000..79e459894
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/icon.png
Binary files differ
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/input-focus-blur.html b/Tools/TestWebKitAPI/Tests/WebKit2/input-focus-blur.html
new file mode 100644
index 000000000..c06439e66
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/input-focus-blur.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<body>
+<input id="input" type="text">
+<input id="readonly" type="text" readonly>
+<script>
+function focusTextField(id)
+{
+ document.getElementById(id).focus();
+}
+
+function blurTextField(id)
+{
+ document.getElementById(id).blur();
+}
+</script>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/link-with-title.html b/Tools/TestWebKitAPI/Tests/WebKit2/link-with-title.html
new file mode 100644
index 000000000..971ed281b
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/link-with-title.html
@@ -0,0 +1,5 @@
+<html>
+ <body>
+ <a href="#" style="display: block; height: 100%;" title="HitTestLinkTitle"></a>
+ </body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-iframes.html b/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-iframes.html
new file mode 100644
index 000000000..5436310c8
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-iframes.html
@@ -0,0 +1,35 @@
+<html>
+<head>
+<script type="text/javascript">
+ var maxNumberOfFrames = 100;
+
+ function createIFrames() {
+ var str = "<div id=\"status\"></div>";
+ for (var i = 0; i < maxNumberOfFrames + 1; i++) {
+ str += "<iframe id=\"i" + i + "\" src=\"data:text/html,iframe_" + i + "\"></iframe>";
+ }
+ document.getElementsByTagName("body")[0].innerHTML = str;
+
+ var results = "";
+
+ var f = document.getElementById("i" + (maxNumberOfFrames - 1));
+ if (f && f.contentWindow) {
+ results += "Sucessfully created " + maxNumberOfFrames + " frames.<br>";
+ } else {
+ results += "Failed to create " + maxNumberOfFrames + " frames.<br>";
+ }
+
+ var g = document.getElementById("i" + maxNumberOfFrames);
+ if (g && g.contentWindow) {
+ results += "Failed to block creation of frame number " + (maxNumberOfFrames + 1) + ".";
+ } else {
+ results += "Successfully blocked creation of frame number " + (maxNumberOfFrames + 1) + ".";
+ }
+
+ document.getElementById("status").innerHTML = results;
+ }
+</script>
+</head>
+<body onLoad="createIFrames()">
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-images.html b/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-images.html
new file mode 100644
index 000000000..2233b8e0b
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-images.html
@@ -0,0 +1,17 @@
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-text-vertical-lr.html b/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-text-vertical-lr.html
new file mode 100644
index 000000000..9598a3efa
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-text-vertical-lr.html
@@ -0,0 +1,3 @@
+<body style="-webkit-writing-mode: vertical-lr;">
+You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!
+</body>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-text.html b/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-text.html
new file mode 100644
index 000000000..3cd1b4c52
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-text.html
@@ -0,0 +1,3 @@
+<body style="width:800px">
+You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!
+</body>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/modal-alerts-in-new-about-blank-window.html b/Tools/TestWebKitAPI/Tests/WebKit2/modal-alerts-in-new-about-blank-window.html
new file mode 100644
index 000000000..f76cb650b
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/modal-alerts-in-new-about-blank-window.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+
+var newWindow = window.open("about:blank");
+newWindow.alert("Testing alert");
+newWindow.confirm("Testing confirm");
+newWindow.prompt("Testing prompt", "Default text");
+
+</script>
+</head>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/mouse-button-listener.html b/Tools/TestWebKitAPI/Tests/WebKit2/mouse-button-listener.html
new file mode 100644
index 000000000..1fdbb1a95
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/mouse-button-listener.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<script>
+ var mouseButton = -1;
+ var menuType = "none";
+
+ function mouseDownHandler(event)
+ {
+ mouseButton = event.button;
+ event.preventDefault();
+ }
+
+ function pressedMouseButton()
+ {
+ return mouseButton;
+ }
+
+ function contextMenuHandler(event)
+ {
+ menuType = "context";
+ event.preventDefault();
+ }
+
+ function displayedMenu()
+ {
+ return menuType;
+ }
+
+ addEventListener("mousedown", mouseDownHandler);
+ addEventListener("contextmenu", contextMenuHandler);
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/mouse-move-listener.html b/Tools/TestWebKitAPI/Tests/WebKit2/mouse-move-listener.html
new file mode 100644
index 000000000..afca7ed86
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/mouse-move-listener.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<script>
+ var mouseMoved = false;
+
+ function mouseMoveHandler()
+ {
+ mouseMoved = true;
+ }
+
+ function didMoveMouse()
+ {
+ return mouseMoved;
+ }
+
+ addEventListener("mousemove", mouseMoveHandler);
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/open-and-close-window.html b/Tools/TestWebKitAPI/Tests/WebKit2/open-and-close-window.html
new file mode 100644
index 000000000..6ac778a9e
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/open-and-close-window.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+if (document.location.search === "?close-window")
+ window.close();
+else
+ window.open("open-and-close-window.html?close-window");
+</script>
+</head>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/push-state.html b/Tools/TestWebKitAPI/Tests/WebKit2/push-state.html
new file mode 100644
index 000000000..f3a04a6bb
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/push-state.html
@@ -0,0 +1,3 @@
+<script type="text/javascript">
+history.pushState('newState', 0, '?newState');
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/should-open-external-schemes.html b/Tools/TestWebKitAPI/Tests/WebKit2/should-open-external-schemes.html
new file mode 100644
index 000000000..299e4d66a
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/should-open-external-schemes.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+function navigateToTelURL()
+{
+ window.location.href = "tel:+1 (408) 996-1010";
+}
+
+function navigateToTelURLInZeroTimer()
+{
+ window.setTimeout(navigateToTelURL, 0);
+}
+
+function navigateToTelURLInNestedZeroTimer()
+{
+ window.setTimeout(navigateToTelURLInZeroTimer, 0);
+}
+</script>
+</head>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/simple-accelerated-compositing.html b/Tools/TestWebKitAPI/Tests/WebKit2/simple-accelerated-compositing.html
new file mode 100644
index 000000000..bea62721b
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/simple-accelerated-compositing.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+ <div style="-webkit-transform: translateZ(0);">Simple HTML file with accelerated compositing</div>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/simple-form.html b/Tools/TestWebKitAPI/Tests/WebKit2/simple-form.html
new file mode 100644
index 000000000..3bf185293
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/simple-form.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<script>
+function submitForm()
+{
+ document.forms[0].submit();
+}
+</script>
+<form method=post>
+<input name=foo value="Some unimportant data">
+<input type=submit>
+</form>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/simple-iframe.html b/Tools/TestWebKitAPI/Tests/WebKit2/simple-iframe.html
new file mode 100644
index 000000000..429521c7f
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/simple-iframe.html
@@ -0,0 +1,6 @@
+<html>
+<body>
+ Simple HTML file.
+ <iframe src="simple.html"></iframe>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/simple-tall.html b/Tools/TestWebKitAPI/Tests/WebKit2/simple-tall.html
new file mode 100644
index 000000000..a220e9b2d
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/simple-tall.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+<body>
+ Simple and tall HTML file.
+ <div style="height: 3000px;"></div>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/simple.html b/Tools/TestWebKitAPI/Tests/WebKit2/simple.html
new file mode 100644
index 000000000..12cf87364
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/simple.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+ Simple HTML file.
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/simple2.html b/Tools/TestWebKitAPI/Tests/WebKit2/simple2.html
new file mode 100644
index 000000000..1dcbfddd2
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/simple2.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+ Second simple HTML file.
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/simple3.html b/Tools/TestWebKitAPI/Tests/WebKit2/simple3.html
new file mode 100644
index 000000000..786516e89
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/simple3.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+ Third simple HTML file.
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/spacebar-scrolling.html b/Tools/TestWebKitAPI/Tests/WebKit2/spacebar-scrolling.html
new file mode 100644
index 000000000..8da08b3f9
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/spacebar-scrolling.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<script>
+ function textFieldContainsSpace()
+ {
+ return document.querySelector("input").value === " ";
+ }
+
+ function blurTextField()
+ {
+ document.querySelector("input").blur();
+ }
+
+ function isDocumentScrolled()
+ {
+ return scrollY !== 0;
+ }
+
+ function loaded()
+ {
+ document.querySelector("input").focus();
+ }
+
+ addEventListener("load", loaded);
+</script>
+<input>
+<div style="height: 3000px;"></div>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/test-mse.mp4 b/Tools/TestWebKitAPI/Tests/WebKit2/test-mse.mp4
new file mode 100644
index 000000000..901c907e0
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/test-mse.mp4
Binary files differ
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/test.mp4 b/Tools/TestWebKitAPI/Tests/WebKit2/test.mp4
new file mode 100644
index 000000000..d278c8ad8
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/test.mp4
Binary files differ
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/webfont.html b/Tools/TestWebKitAPI/Tests/WebKit2/webfont.html
new file mode 100644
index 000000000..008edd098
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/webfont.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+@font-face {
+ font-family: "WebFont";
+ src: url("Ahem.ttf") format("truetype");
+}
+</style>
+</head>
+<body>
+<div style="font: 100px 'WebFont';">Hello</div>
+This tests passes if there is no Web Process crash.
+</body>
+</html> \ No newline at end of file
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.h b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.h
new file mode 100644
index 000000000..9d5b5d433
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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.
+ */
+
+@protocol ContentFilteringProtocol <NSObject>
+- (void)checkIfPlatformFrameworksAreLoaded:(void (^)(BOOL parentalControlsLoaded, BOOL networkExtensionLoaded))completionHandler;
+@end
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.html
new file mode 100644
index 000000000..a48eabb65
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html>
+<body>
+PASS
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-1.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-1.html
new file mode 100644
index 000000000..e3e8552a5
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-1.html
@@ -0,0 +1,46 @@
+<script>
+
+var request = window.indexedDB.deleteDatabase("IndexedDBMultiProcess");
+request.onsuccess = function(e)
+{
+ continueTest();
+}
+request.onerror = function(e)
+{
+ // Unexpected error
+ window.webkit.messageHandlers.testHandler.postMessage('Error opening database');
+}
+
+function continueTest()
+{
+ var request = window.indexedDB.open("IndexedDBMultiProcess", 2);
+
+ request.onsuccess = function()
+ {
+ window.webkit.messageHandlers.testHandler.postMessage('Success');
+ }
+
+ request.onerror = function()
+ {
+ // Unexpected error
+ window.webkit.messageHandlers.testHandler.postMessage('Error');
+ }
+
+ request.onupgradeneeded = function(event)
+ {
+ window.webkit.messageHandlers.testHandler.postMessage('UpgradeNeeded');
+
+ var store = event.target.result.createObjectStore("TestObjectStore");
+
+ event.target.transaction.oncomplete = function() {
+ window.webkit.messageHandlers.testHandler.postMessage('Transaction complete');
+ }
+
+ event.target.transaction.onerror = function() {
+ window.webkit.messageHandlers.testHandler.postMessage('Transaction errored!');
+ }
+
+ store.put("bar", "foo");
+ }
+}
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-2.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-2.html
new file mode 100644
index 000000000..3e4e2d7da
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-2.html
@@ -0,0 +1,32 @@
+<script>
+
+var request = window.indexedDB.open("IndexedDBMultiProcess", 2);
+
+request.onsuccess = function(event)
+{
+ var req = event.target.result.transaction("TestObjectStore").objectStore("TestObjectStore").get("foo");
+
+ req.onsuccess = function(event)
+ {
+ window.webkit.messageHandlers.testHandler.postMessage('Value of foo: ' + req.result);
+ }
+
+ req.onerror = function(event)
+ {
+ // Unexpected error
+ window.webkit.messageHandlers.testHandler.postMessage('Unexpected error');
+ }
+}
+
+request.onerror = function()
+{
+ // Unexpected error
+ window.webkit.messageHandlers.testHandler.postMessage('Unexpected error');
+}
+
+request.onupgradeneeded = function(event)
+{
+ // Unexpected upgrade needed
+ window.webkit.messageHandlers.testHandler.postMessage('Unexpected UpgradeNeeded');
+}
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBPersistence-1.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBPersistence-1.html
new file mode 100644
index 000000000..62a1baf6f
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBPersistence-1.html
@@ -0,0 +1,35 @@
+<script>
+
+var request = window.indexedDB.deleteDatabase("IndexedDBPersistence");
+request.onsuccess = function(e)
+{
+ continueTest();
+}
+request.onerror = function(e)
+{
+ // Unexpected error
+ window.webkit.messageHandlers.testHandler.postMessage('Error');
+}
+
+function continueTest()
+{
+ var request = window.indexedDB.open("IndexedDBPersistence", 2);
+
+ request.onsuccess = function()
+ {
+ window.webkit.messageHandlers.testHandler.postMessage('Success');
+
+ }
+ request.onerror = function()
+ {
+ // Unexpected error
+ window.webkit.messageHandlers.testHandler.postMessage('Error');
+ }
+ request.onupgradeneeded = function(event)
+ {
+ window.webkit.messageHandlers.testHandler.postMessage('UpgradeNeeded');
+
+ event.target.result.createObjectStore("TestObjectStore");
+ }
+}
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBPersistence-2.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBPersistence-2.html
new file mode 100644
index 000000000..d8ab125f2
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBPersistence-2.html
@@ -0,0 +1,22 @@
+<script>
+
+var request = window.indexedDB.open("IndexedDBPersistence");
+
+request.onsuccess = function(event)
+{
+ window.webkit.messageHandlers.testHandler.postMessage(event.target.result.version + " " + event.target.result.objectStoreNames[0]);
+}
+
+request.onerror = function()
+{
+ // Unexpected error
+ window.webkit.messageHandlers.testHandler.postMessage('Unexpected Error');
+}
+
+request.onupgradeneeded = function()
+{
+ // Unexpected error
+ window.webkit.messageHandlers.testHandler.postMessage('Unexpected UpgradeNeeded');
+}
+
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/RemoteObjectRegistry.h b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/RemoteObjectRegistry.h
new file mode 100644
index 000000000..b72826817
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/RemoteObjectRegistry.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#import <WebKit/WKFoundation.h>
+
+#if WK_API_ENABLED
+
+#import <WebKit/_WKRemoteObjectInterface.h>
+
+@protocol RemoteObjectProtocol <NSObject>
+
+- (void)sayHello:(NSString *)hello;
+- (void)sayHello:(NSString *)hello completionHandler:(void (^)(NSString *))completionHandler;
+- (void)selectionAndClickInformationForClickAtPoint:(NSValue *)pointValue completionHandler:(void (^)(NSDictionary *))completionHandler;
+
+@end
+
+static inline _WKRemoteObjectInterface *remoteObjectInterface()
+{
+ _WKRemoteObjectInterface *interface = [_WKRemoteObjectInterface remoteObjectInterfaceWithProtocol:@protocol(RemoteObjectProtocol)];
+
+ [interface setClasses:[NSSet setWithObjects:[NSDictionary class], [NSURL class], nil] forSelector:@selector(selectionAndClickInformationForClickAtPoint:completionHandler:) argumentIndex:0 ofReply:YES];
+
+ return interface;
+}
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/AutocleanupsTest.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/AutocleanupsTest.cpp
new file mode 100644
index 000000000..a20cbfd73
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/AutocleanupsTest.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2013 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "WebProcessTest.h"
+#include <webkit2/webkit-web-extension.h>
+
+#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
+
+class AutocleanupsTest : public WebProcessTest {
+public:
+ static std::unique_ptr<WebProcessTest> create() { return std::unique_ptr<WebProcessTest>(new AutocleanupsTest()); }
+
+private:
+ bool testWebProcessAutocleanups(WebKitWebPage* webPage)
+ {
+ // Transfer none
+ g_autoptr(WebKitWebPage) page = WEBKIT_WEB_PAGE(g_object_ref(G_OBJECT(webPage)));
+ g_assert(WEBKIT_IS_WEB_PAGE(page));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(page));
+
+ // Transfer none
+ g_autoptr(WebKitDOMDocument) document = WEBKIT_DOM_DOCUMENT(g_object_ref(G_OBJECT(webkit_web_page_get_dom_document(page))));
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(document));
+
+ // Transfer full
+ g_autoptr(WebKitDOMDOMWindow) window = webkit_dom_document_get_default_view(document);
+ g_assert(WEBKIT_DOM_IS_DOM_WINDOW(window));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(window));
+
+ // Transfer full
+ g_autoptr(WebKitDOMRange) range = webkit_dom_document_create_range(document);
+ g_assert(WEBKIT_DOM_IS_RANGE(range));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(range));
+
+ return true;
+ }
+
+ bool runTest(const char* testName, WebKitWebPage* page) override
+ {
+ if (!strcmp(testName, "web-process-autocleanups"))
+ return testWebProcessAutocleanups(page);
+
+ g_assert_not_reached();
+ return false;
+ }
+};
+
+static void __attribute__((constructor)) registerTests()
+{
+ REGISTER_TEST(AutocleanupsTest, "Autocleanups/web-process-autocleanups");
+}
+
+#endif // G_DEFINE_AUTOPTR_CLEANUP_FUNC
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/CMakeLists.txt b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/CMakeLists.txt
new file mode 100644
index 000000000..b0b473962
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/CMakeLists.txt
@@ -0,0 +1,135 @@
+set(TEST_LIBRARY_DIR ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/WebKit2GtkAPITests)
+set(TEST_BINARY_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/TestWebKitAPI/WebKit2Gtk)
+set(TEST_RESOURCES_DIR ${TEST_BINARY_DIR}/resources)
+file(MAKE_DIRECTORY ${TEST_RESOURCES_DIR})
+
+add_definitions(
+ -DWEBKIT_TEST_PLUGIN_DIR="${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/plugins"
+ -DWEBKIT_EXEC_PATH="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}"
+ -DWEBKIT_SRC_DIR="${CMAKE_SOURCE_DIR}"
+ -DWEBKIT_TEST_WEB_EXTENSIONS_DIR="${TEST_LIBRARY_DIR}"
+ -DWEBKIT_INJECTED_BUNDLE_PATH="${CMAKE_LIBRARY_OUTPUT_DIRECTORY}"
+)
+
+include_directories(
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_SOURCE_DIR}/Source
+ ${CMAKE_SOURCE_DIR}/Source/WTF
+ ${DERIVED_SOURCES_DIR}
+ ${DERIVED_SOURCES_WEBKIT2GTK_DIR}
+ ${FORWARDING_HEADERS_DIR}
+ ${FORWARDING_HEADERS_WEBKIT2GTK_DIR}
+ ${FORWARDING_HEADERS_WEBKIT2GTK_EXTENSION_DIR}
+ ${TOOLS_DIR}/TestWebKitAPI/gtk/WebKit2Gtk
+)
+
+include_directories(SYSTEM
+ ${ATSPI_INCLUDE_DIRS}
+ ${GLIB_INCLUDE_DIRS}
+ ${GSTREAMER_INCLUDE_DIRS}
+ ${GTK3_INCLUDE_DIRS}
+ ${GTK_UNIX_PRINT_INCLUDE_DIRS}
+ ${LIBSOUP_INCLUDE_DIRS}
+)
+
+add_library(WebKit2APITestCore STATIC
+ ${TOOLS_DIR}/TestWebKitAPI/gtk/WebKit2Gtk/LoadTrackingTest.cpp
+ ${TOOLS_DIR}/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.cpp
+ ${TOOLS_DIR}/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestServer.cpp
+ ${TOOLS_DIR}/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.cpp
+ ${TOOLS_DIR}/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.cpp
+)
+target_link_libraries(WebKit2APITestCore WebKit2)
+
+add_custom_command(
+ OUTPUT ${TEST_RESOURCES_DIR}/webkit2gtk-tests-resources.gresource
+ DEPENDS resources/webkit2gtk-tests.gresource.xml
+ resources/link-title.js
+ COMMAND glib-compile-resources
+ --target=${TEST_RESOURCES_DIR}/webkit2gtk-tests-resources.gresource
+ --sourcedir=${CMAKE_SOURCE_DIR}
+ ${CMAKE_CURRENT_LIST_DIR}/resources/webkit2gtk-tests.gresource.xml
+)
+
+add_custom_target(test-gresource-bundle
+ DEPENDS ${TEST_RESOURCES_DIR}/webkit2gtk-tests-resources.gresource
+)
+
+macro(ADD_WK2_TEST_WEB_EXTENSION extension_name)
+ add_library(${extension_name} MODULE ${ARGN})
+ add_dependencies(${extension_name} WebKit2)
+ set_property(
+ TARGET ${extension_name}
+ APPEND
+ PROPERTY COMPILE_DEFINITIONS WEBKIT2_COMPILATION
+ )
+ set_target_properties(${extension_name} PROPERTIES
+ LIBRARY_OUTPUT_DIRECTORY ${TEST_LIBRARY_DIR}
+ )
+ target_link_libraries(${extension_name}
+ JavaScriptCore
+ WebKit2
+ ${GLIB_LIBRARIES}
+ )
+endmacro()
+
+macro(ADD_WK2_TEST test_name)
+ add_executable(${test_name} ${ARGN})
+ add_dependencies(${test_name}
+ test-gresource-bundle
+ WebExtensionTest
+ )
+ target_link_libraries(${test_name}
+ JavaScriptCore
+ WebKit2
+ WebKit2APITestCore
+ ${ATSPI_LIBRARIES}
+ ${GLIB_LIBRARIES}
+ ${GTK3_LIBRARIES}
+ ${GTK_UNIX_PRINT_LIBRARIES}
+ ${LIBSOUP_LIBRARIES}
+ )
+ set_target_properties(${test_name} PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY ${TEST_BINARY_DIR}
+ )
+endmacro()
+
+ADD_WK2_TEST_WEB_EXTENSION(WebExtensionTest WebExtensionTest.cpp)
+ADD_WK2_TEST_WEB_EXTENSION(WebProcessTest AutocleanupsTest.cpp DOMNodeTest.cpp DOMNodeFilterTest.cpp DOMXPathNSResolverTest.cpp FrameTest.cpp WebProcessTest.cpp EditorTest.cpp)
+
+ADD_WK2_TEST(InspectorTestServer InspectorTestServer.cpp)
+ADD_WK2_TEST(TestAuthentication TestAuthentication.cpp)
+ADD_WK2_TEST(TestAutocleanups TestAutocleanups.cpp)
+ADD_WK2_TEST(TestBackForwardList TestBackForwardList.cpp)
+ADD_WK2_TEST(TestContextMenu TestContextMenu.cpp)
+ADD_WK2_TEST(TestCookieManager TestCookieManager.cpp)
+ADD_WK2_TEST(TestDOMNode TestDOMNode.cpp)
+ADD_WK2_TEST(TestDOMNodeFilter TestDOMNodeFilter.cpp)
+ADD_WK2_TEST(TestDOMXPathNSResolver TestDOMXPathNSResolver.cpp)
+ADD_WK2_TEST(TestDownloads TestDownloads.cpp)
+ADD_WK2_TEST(TestWebKitFaviconDatabase TestWebKitFaviconDatabase.cpp)
+ADD_WK2_TEST(TestWebKitFindController TestWebKitFindController.cpp)
+ADD_WK2_TEST(TestFrame TestFrame.cpp)
+ADD_WK2_TEST(TestInspector TestInspector.cpp)
+ADD_WK2_TEST(TestInspectorServer TestInspectorServer.cpp)
+ADD_WK2_TEST(TestLoaderClient TestLoaderClient.cpp)
+ADD_WK2_TEST(TestMultiprocess TestMultiprocess.cpp)
+ADD_WK2_TEST(TestPrinting TestPrinting.cpp)
+ADD_WK2_TEST(TestResources TestResources.cpp)
+ADD_WK2_TEST(TestSSL TestSSL.cpp)
+ADD_WK2_TEST(TestUIClient TestUIClient.cpp)
+ADD_WK2_TEST(TestWebExtensions TestWebExtensions.cpp)
+ADD_WK2_TEST(TestWebKitPolicyClient TestWebKitPolicyClient.cpp)
+ADD_WK2_TEST(TestWebKitSettings TestWebKitSettings.cpp)
+ADD_WK2_TEST(TestWebKitVersion TestWebKitVersion.cpp)
+ADD_WK2_TEST(TestWebViewEditor TestWebViewEditor.cpp)
+ADD_WK2_TEST(TestWebKitWebContext TestWebKitWebContext.cpp)
+ADD_WK2_TEST(TestWebKitWebView TestWebKitWebView.cpp)
+ADD_WK2_TEST(TestWebKitUserContentManager TestWebKitUserContentManager.cpp)
+ADD_WK2_TEST(TestEditor TestEditor.cpp)
+ADD_WK2_TEST(TestConsoleMessage TestConsoleMessage.cpp)
+
+if (ATSPI_FOUND)
+ ADD_WK2_TEST(AccessibilityTestServer AccessibilityTestServer.cpp)
+ ADD_WK2_TEST(TestWebKitAccessibility TestWebKitAccessibility.cpp)
+endif ()
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMDOMWindowTest.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMDOMWindowTest.cpp
new file mode 100644
index 000000000..fc8cefb52
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMDOMWindowTest.cpp
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2013 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "WebProcessTest.h"
+#include <gio/gio.h>
+#include <webkit2/webkit-web-extension.h>
+#include <wtf/RunLoop.h>
+
+class WebKitDOMDOMWindowTest;
+static gboolean loadedCallback(WebKitDOMDOMWindow*, WebKitDOMEvent*, WebKitDOMDOMWindowTest*);
+static gboolean clickedCallback(WebKitDOMDOMWindow*, WebKitDOMEvent*, WebKitDOMDOMWindowTest*);
+
+class WebKitDOMDOMWindowTest : public WebProcessTest {
+public:
+ static std::unique_ptr<WebProcessTest> create() { return std::make_unique<WebKitDOMDOMWindowTest>(); }
+
+private:
+ guint64 webPageFromArgs(GVariant* args)
+ {
+ GVariantIter iter;
+ g_variant_iter_init(&iter, args);
+
+ const char* key;
+ GVariant* value;
+ while (g_variant_iter_loop(&iter, "{&sv}", &key, &value)) {
+ if (!strcmp(key, "pageID") && g_variant_classify(value) == G_VARIANT_CLASS_UINT64)
+ return g_variant_get_uint64(value);
+ }
+
+ g_assert_not_reached();
+ return 0;
+ }
+
+ bool testSignals(WebKitWebExtension* extension, GVariant* args)
+ {
+ notify("ready", "");
+
+ WebKitWebPage* page = webkit_web_extension_get_page(extension, webPageFromArgs(args));
+ g_assert(WEBKIT_IS_WEB_PAGE(page));
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+
+ WebKitDOMDOMWindow* domWindow = webkit_dom_document_get_default_view(document);
+ g_assert(domWindow);
+
+ // The "load" WebKitDOMDOMWindow signal is issued before this test is
+ // called. There's no way to capture it here. We simply assume that
+ // the document is loaded and notify the uiprocess accordingly
+ // notify("loaded", "");
+
+ webkit_dom_event_target_add_event_listener(
+ WEBKIT_DOM_EVENT_TARGET(domWindow),
+ "load",
+ G_CALLBACK(loadedCallback),
+ false,
+ this);
+
+ // loadedCallback() will stop this loop
+ RunLoop::run();
+
+ document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+
+ WebKitDOMElement* element = webkit_dom_document_get_element_by_id(document, "test");
+ g_assert(element);
+
+ webkit_dom_event_target_add_event_listener(
+ WEBKIT_DOM_EVENT_TARGET(element),
+ "click",
+ G_CALLBACK(clickedCallback),
+ false,
+ this);
+
+ // The "click" action will be issued in the uiprocess and that will
+ // trigger the dom event here.
+ // clickedCallback() will stop this loop
+ RunLoop::run();
+
+ return true;
+ }
+
+ bool testDispatchEvent(WebKitWebExtension* extension, GVariant* args)
+ {
+ notify("ready", "");
+
+ WebKitWebPage* page = webkit_web_extension_get_page(extension, webPageFromArgs(args));
+ g_assert(WEBKIT_IS_WEB_PAGE(page));
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+
+ WebKitDOMDOMWindow* domWindow = webkit_dom_document_get_default_view(document);
+ g_assert(domWindow);
+
+ // The "load" WebKitDOMDOMWindow signal is issued before this test is
+ // called. There's no way to capture it here. We simply assume that
+ // the document is loaded and notify the uiprocess accordingly
+ // notify("loaded", "");
+
+ webkit_dom_event_target_add_event_listener(
+ WEBKIT_DOM_EVENT_TARGET(domWindow),
+ "load",
+ G_CALLBACK(loadedCallback),
+ false,
+ this);
+
+ // loadedCallback() will stop this loop
+ RunLoop::run();
+
+ document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+
+ WebKitDOMElement* element = webkit_dom_document_get_element_by_id(document, "test");
+ g_assert(element);
+
+ WebKitDOMEvent* event = webkit_dom_document_create_event(document, "MouseEvent", 0);
+ g_assert(event);
+ g_assert(WEBKIT_DOM_IS_EVENT(event));
+ g_assert(WEBKIT_DOM_IS_MOUSE_EVENT(event));
+
+ glong clientX, clientY;
+ clientX = webkit_dom_element_get_client_left(element);
+ clientY = webkit_dom_element_get_client_top(element);
+
+ webkit_dom_event_target_add_event_listener(
+ WEBKIT_DOM_EVENT_TARGET(element),
+ "click",
+ G_CALLBACK(clickedCallback),
+ false,
+ this);
+
+ webkit_dom_mouse_event_init_mouse_event(WEBKIT_DOM_MOUSE_EVENT(event),
+ "click", TRUE, TRUE,
+ domWindow, 0, 0, 0, clientX, clientY,
+ FALSE, FALSE, FALSE, FALSE,
+ 1, WEBKIT_DOM_EVENT_TARGET(element));
+
+ webkit_dom_event_target_dispatch_event(WEBKIT_DOM_EVENT_TARGET(element), event, 0);
+
+ // clickedCallback() will stop this loop
+ RunLoop::run();
+
+ return true;
+ }
+
+ bool testGetComputedStyle(WebKitWebExtension* extension, GVariant* args)
+ {
+ WebKitWebPage* page = webkit_web_extension_get_page(extension, webPageFromArgs(args));
+ g_assert(WEBKIT_IS_WEB_PAGE(page));
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ WebKitDOMDOMWindow* domWindow = webkit_dom_document_get_default_view(document);
+ g_assert(domWindow);
+ WebKitDOMElement* element = webkit_dom_document_get_element_by_id(document, "test");
+ g_assert(element);
+ g_assert(WEBKIT_DOM_IS_ELEMENT(element));
+ WebKitDOMCSSStyleDeclaration* cssStyle = webkit_dom_dom_window_get_computed_style(domWindow, element, 0);
+ gchar* fontSize = webkit_dom_css_style_declaration_get_property_value(cssStyle, "font-size");
+ g_assert_cmpstr(fontSize, ==, "16px");
+
+ return true;
+ }
+
+ virtual bool runTest(const char* testName, WebKitWebExtension* extension, GVariant* args)
+ {
+ if (!strcmp(testName, "signals"))
+ return testSignals(extension, args);
+ if (!strcmp(testName, "dispatch-event"))
+ return testDispatchEvent(extension, args);
+ if (!strcmp(testName, "get-computed-style"))
+ return testGetComputedStyle(extension, args);
+
+ g_assert_not_reached();
+ return false;
+ }
+};
+
+static void __attribute__((constructor)) registerTests()
+{
+ REGISTER_TEST(WebKitDOMDOMWindowTest, "WebKitDOMDOMWindow/signals");
+ REGISTER_TEST(WebKitDOMDOMWindowTest, "WebKitDOMDOMWindow/dispatch-event");
+ REGISTER_TEST(WebKitDOMDOMWindowTest, "WebKitDOMDOMWindow/get-computed-style");
+}
+
+static gboolean loadedCallback(WebKitDOMDOMWindow* view, WebKitDOMEvent* event, WebKitDOMDOMWindowTest* test)
+{
+ test->notify("loaded", "");
+
+ // Stop the loop and let testSignals() or testDispatchEvent() continue its course
+ RunLoop::current().stop();
+
+ return FALSE;
+}
+
+static gboolean clickedCallback(WebKitDOMDOMWindow* view, WebKitDOMEvent* event, WebKitDOMDOMWindowTest* test)
+{
+ test->notify("clicked", "");
+ test->notify("finish", "");
+
+ // Stop the loop and let testSignals() or testDispatchEvent() continue its course
+ RunLoop::current().stop();
+
+ return FALSE;
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMNodeFilterTest.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMNodeFilterTest.cpp
new file mode 100644
index 000000000..0f18d1f31
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMNodeFilterTest.cpp
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2013 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "WebProcessTest.h"
+#include <gio/gio.h>
+#include <webkit2/webkit-web-extension.h>
+#include <wtf/glib/GUniquePtr.h>
+
+typedef struct _WebKitNodeFilter {
+ GObject parent;
+} WebKitNodeFilter;
+
+typedef struct _WebKitNodeFilterClass {
+ GObjectClass parentClass;
+} WebKitNodeFilterClass;
+
+static short webkitNodeFilterAcceptNode(WebKitDOMNodeFilter*, WebKitDOMNode* node)
+{
+ // Filter out input elements.
+ return WEBKIT_DOM_IS_HTML_INPUT_ELEMENT(node) ? WEBKIT_DOM_NODE_FILTER_REJECT : WEBKIT_DOM_NODE_FILTER_ACCEPT;
+}
+
+static void webkitNodeFilterDOMNodeFilterIfaceInit(WebKitDOMNodeFilterIface* iface)
+{
+ iface->accept_node = webkitNodeFilterAcceptNode;
+}
+
+G_DEFINE_TYPE_WITH_CODE(WebKitNodeFilter, webkit_node_filter, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE(WEBKIT_DOM_TYPE_NODE_FILTER, webkitNodeFilterDOMNodeFilterIfaceInit))
+
+static void webkit_node_filter_init(WebKitNodeFilter*)
+{
+}
+
+static void webkit_node_filter_class_init(WebKitNodeFilterClass*)
+{
+}
+
+static const char* expectedNodesAll[] = { "HTML", "HEAD", "TITLE", "#text", "BODY", "INPUT", "INPUT", "BR" };
+static const char* expectedNodesNoInput[] = { "HTML", "HEAD", "TITLE", "#text", "BODY", "BR" };
+static const char* expectedElementsNoInput[] = { "HTML", "HEAD", "TITLE", "BODY", "BR" };
+
+class WebKitDOMNodeFilterTest : public WebProcessTest {
+public:
+ static std::unique_ptr<WebProcessTest> create() { return std::unique_ptr<WebProcessTest>(new WebKitDOMNodeFilterTest()); }
+
+private:
+ bool testTreeWalker(WebKitWebPage* page)
+ {
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(document));
+
+ WebKitDOMElement* root = webkit_dom_document_get_element_by_id(document, "root");
+ g_assert(WEBKIT_DOM_IS_NODE(root));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(root));
+
+ // No filter.
+ GRefPtr<WebKitDOMTreeWalker> walker = adoptGRef(webkit_dom_document_create_tree_walker(document, WEBKIT_DOM_NODE(root), WEBKIT_DOM_NODE_FILTER_SHOW_ALL, nullptr, FALSE, nullptr));
+ g_assert(WEBKIT_DOM_IS_TREE_WALKER(walker.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(walker.get()));
+ g_assert(!webkit_dom_tree_walker_get_filter(walker.get()));
+
+ unsigned i = 0;
+ for (WebKitDOMNode* node = WEBKIT_DOM_NODE(root); node; node = webkit_dom_tree_walker_next_node(walker.get()), ++i) {
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
+ g_assert_cmpuint(i, <, G_N_ELEMENTS(expectedNodesAll));
+ GUniquePtr<char> nodeName(webkit_dom_node_get_node_name(node));
+ g_assert_cmpstr(nodeName.get(), ==, expectedNodesAll[i]);
+ }
+ g_assert_cmpuint(i, ==, G_N_ELEMENTS(expectedNodesAll));
+
+ // Input elements filter.
+ GRefPtr<WebKitDOMNodeFilter> filter = adoptGRef(static_cast<WebKitDOMNodeFilter*>(g_object_new(webkit_node_filter_get_type(), nullptr)));
+ walker = adoptGRef(webkit_dom_document_create_tree_walker(document, WEBKIT_DOM_NODE(root), WEBKIT_DOM_NODE_FILTER_SHOW_ALL, filter.get(), FALSE, nullptr));
+ g_assert(WEBKIT_DOM_IS_TREE_WALKER(walker.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(filter.get()));
+ g_assert(webkit_dom_tree_walker_get_filter(walker.get()) == filter.get());
+
+ i = 0;
+ for (WebKitDOMNode* node = WEBKIT_DOM_NODE(root); node; node = webkit_dom_tree_walker_next_node(walker.get()), ++i) {
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
+ g_assert_cmpuint(i, <, G_N_ELEMENTS(expectedNodesNoInput));
+ GUniquePtr<char> nodeName(webkit_dom_node_get_node_name(node));
+ g_assert_cmpstr(nodeName.get(), ==, expectedNodesNoInput[i]);
+ }
+ g_assert_cmpuint(i, ==, G_N_ELEMENTS(expectedNodesNoInput));
+
+ // Show only elements, reusing the input filter.
+ walker = adoptGRef(webkit_dom_document_create_tree_walker(document, WEBKIT_DOM_NODE(root), WEBKIT_DOM_NODE_FILTER_SHOW_ELEMENT, filter.get(), FALSE, nullptr));
+ g_assert(WEBKIT_DOM_IS_TREE_WALKER(walker.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(walker.get()));
+ g_assert(webkit_dom_tree_walker_get_filter(walker.get()) == filter.get());
+
+ i = 0;
+ for (WebKitDOMNode* node = WEBKIT_DOM_NODE(root); node; node = webkit_dom_tree_walker_next_node(walker.get()), ++i) {
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
+ g_assert_cmpuint(i, <, G_N_ELEMENTS(expectedElementsNoInput));
+ GUniquePtr<char> nodeName(webkit_dom_node_get_node_name(node));
+ g_assert_cmpstr(nodeName.get(), ==, expectedElementsNoInput[i]);
+ }
+ g_assert_cmpuint(i, ==, G_N_ELEMENTS(expectedElementsNoInput));
+
+ return true;
+ }
+
+ bool testNodeIterator(WebKitWebPage* page)
+ {
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(document));
+
+ WebKitDOMElement* root = webkit_dom_document_get_element_by_id(document, "root");
+ g_assert(WEBKIT_DOM_IS_NODE(root));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(root));
+
+ // No filter.
+ GRefPtr<WebKitDOMNodeIterator> iter = adoptGRef(webkit_dom_document_create_node_iterator(document, WEBKIT_DOM_NODE(root), WEBKIT_DOM_NODE_FILTER_SHOW_ALL, nullptr, FALSE, nullptr));
+ g_assert(WEBKIT_DOM_IS_NODE_ITERATOR(iter.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(iter.get()));
+ g_assert(!webkit_dom_node_iterator_get_filter(iter.get()));
+
+ unsigned i = 0;
+ while (WebKitDOMNode* node = webkit_dom_node_iterator_next_node(iter.get(), nullptr)) {
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
+ g_assert_cmpuint(i, <, G_N_ELEMENTS(expectedNodesAll));
+ GUniquePtr<char> nodeName(webkit_dom_node_get_node_name(node));
+ g_assert_cmpstr(nodeName.get(), ==, expectedNodesAll[i]);
+ i++;
+ }
+ g_assert_cmpuint(i, ==, G_N_ELEMENTS(expectedNodesAll));
+
+ // Input elements filter.
+ GRefPtr<WebKitDOMNodeFilter> filter = adoptGRef(static_cast<WebKitDOMNodeFilter*>(g_object_new(webkit_node_filter_get_type(), nullptr)));
+ iter = adoptGRef(webkit_dom_document_create_node_iterator(document, WEBKIT_DOM_NODE(root), WEBKIT_DOM_NODE_FILTER_SHOW_ALL, filter.get(), FALSE, nullptr));
+ g_assert(WEBKIT_DOM_IS_NODE_ITERATOR(iter.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(iter.get()));
+ g_assert(webkit_dom_node_iterator_get_filter(iter.get()) == filter.get());
+
+ i = 0;
+ while (WebKitDOMNode* node = webkit_dom_node_iterator_next_node(iter.get(), nullptr)) {
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
+ g_assert_cmpuint(i, <, G_N_ELEMENTS(expectedNodesNoInput));
+ GUniquePtr<char> nodeName(webkit_dom_node_get_node_name(node));
+ g_assert_cmpstr(nodeName.get(), ==, expectedNodesNoInput[i]);
+ i++;
+ }
+ g_assert_cmpuint(i, ==, G_N_ELEMENTS(expectedNodesNoInput));
+
+ // Show only elements, reusing the input filter.
+ iter = adoptGRef(webkit_dom_document_create_node_iterator(document, WEBKIT_DOM_NODE(root), WEBKIT_DOM_NODE_FILTER_SHOW_ELEMENT, filter.get(), FALSE, nullptr));
+ g_assert(WEBKIT_DOM_IS_NODE_ITERATOR(iter.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(iter.get()));
+ g_assert(webkit_dom_node_iterator_get_filter(iter.get()) == filter.get());
+
+ i = 0;
+ while (WebKitDOMNode* node = webkit_dom_node_iterator_next_node(iter.get(), nullptr)) {
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
+ g_assert_cmpuint(i, <, G_N_ELEMENTS(expectedElementsNoInput));
+ GUniquePtr<char> nodeName(webkit_dom_node_get_node_name(node));
+ g_assert_cmpstr(nodeName.get(), ==, expectedElementsNoInput[i]);
+ i++;
+ }
+ g_assert_cmpuint(i, ==, G_N_ELEMENTS(expectedElementsNoInput));
+
+ return true;
+ }
+
+ bool runTest(const char* testName, WebKitWebPage* page) override
+ {
+ if (!strcmp(testName, "tree-walker"))
+ return testTreeWalker(page);
+ if (!strcmp(testName, "node-iterator"))
+ return testNodeIterator(page);
+
+ g_assert_not_reached();
+ return false;
+ }
+};
+
+static void __attribute__((constructor)) registerTests()
+{
+ REGISTER_TEST(WebKitDOMNodeFilterTest, "WebKitDOMNodeFilter/tree-walker");
+ REGISTER_TEST(WebKitDOMNodeFilterTest, "WebKitDOMNodeFilter/node-iterator");
+}
+
+
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMNodeTest.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMNodeTest.cpp
index 5f62e5493..9d57b42d2 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMNodeTest.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMNodeTest.cpp
@@ -22,7 +22,7 @@
#include "WebProcessTest.h"
#include <gio/gio.h>
#include <webkit2/webkit-web-extension.h>
-#include <wtf/gobject/GUniquePtr.h>
+#include <wtf/glib/GUniquePtr.h>
class WebKitDOMNodeTest : public WebProcessTest {
public:
@@ -33,21 +33,26 @@ private:
{
WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(document));
WebKitDOMHTMLHeadElement* head = webkit_dom_document_get_head(document);
g_assert(WEBKIT_DOM_IS_HTML_HEAD_ELEMENT(head));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(head));
// Title, head's child.
g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(head)));
GRefPtr<WebKitDOMNodeList> list = adoptGRef(webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(head)));
g_assert(WEBKIT_DOM_IS_NODE_LIST(list.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(list.get()));
g_assert_cmpint(webkit_dom_node_list_get_length(list.get()), ==, 1);
WebKitDOMNode* node = webkit_dom_node_list_item(list.get(), 0);
g_assert(WEBKIT_DOM_IS_HTML_TITLE_ELEMENT(node));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
// Body, Head sibling.
node = webkit_dom_node_get_next_sibling(WEBKIT_DOM_NODE(head));
g_assert(WEBKIT_DOM_IS_HTML_BODY_ELEMENT(node));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
WebKitDOMHTMLBodyElement* body = WEBKIT_DOM_HTML_BODY_ELEMENT(node);
// There is no third sibling
@@ -56,10 +61,13 @@ private:
// Body's previous sibling is Head.
node = webkit_dom_node_get_previous_sibling(WEBKIT_DOM_NODE(body));
g_assert(WEBKIT_DOM_IS_HTML_HEAD_ELEMENT(node));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
// Body has 3 children.
g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(body)));
list = adoptGRef(webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(body)));
+ g_assert(WEBKIT_DOM_IS_NODE_LIST(list.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(list.get()));
unsigned long length = webkit_dom_node_list_get_length(list.get());
g_assert_cmpint(length, ==, 3);
@@ -67,6 +75,7 @@ private:
for (unsigned long i = 0; i < length; i++) {
node = webkit_dom_node_list_item(list.get(), i);
g_assert(WEBKIT_DOM_IS_HTML_PARAGRAPH_ELEMENT(node));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
}
// Go backwards
@@ -81,88 +90,135 @@ private:
{
WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(document));
WebKitDOMHTMLElement* body = webkit_dom_document_get_body(document);
g_assert(WEBKIT_DOM_IS_HTML_ELEMENT(body));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(body));
// Body shouldn't have any children at this point.
g_assert(!webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(body)));
+ // The value of a non-existent attribute should be null, not an empty string
+ g_assert(!webkit_dom_html_body_element_get_background(WEBKIT_DOM_HTML_BODY_ELEMENT(body)));
+
// Insert one P element.
WebKitDOMElement* p = webkit_dom_document_create_element(document, "P", 0);
g_assert(WEBKIT_DOM_IS_HTML_ELEMENT(p));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(p));
webkit_dom_node_append_child(WEBKIT_DOM_NODE(body), WEBKIT_DOM_NODE(p), 0);
// Now it should have one, the same that we inserted.
g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(body)));
GRefPtr<WebKitDOMNodeList> list = adoptGRef(webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(body)));
g_assert(WEBKIT_DOM_IS_NODE_LIST(list.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(list.get()));
g_assert_cmpint(webkit_dom_node_list_get_length(list.get()), ==, 1);
WebKitDOMNode* node = webkit_dom_node_list_item(list.get(), 0);
g_assert(WEBKIT_DOM_IS_HTML_ELEMENT(node));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
g_assert(webkit_dom_node_is_same_node(WEBKIT_DOM_NODE(p), node));
// Replace the P tag with a DIV tag.
WebKitDOMElement* div = webkit_dom_document_create_element(document, "DIV", 0);
g_assert(WEBKIT_DOM_IS_HTML_ELEMENT(div));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(div));
webkit_dom_node_replace_child(WEBKIT_DOM_NODE(body), WEBKIT_DOM_NODE(div), WEBKIT_DOM_NODE(p), 0);
g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(body)));
list = adoptGRef(webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(body)));
g_assert(WEBKIT_DOM_IS_NODE_LIST(list.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(list.get()));
g_assert_cmpint(webkit_dom_node_list_get_length(list.get()), ==, 1);
node = webkit_dom_node_list_item(list.get(), 0);
g_assert(WEBKIT_DOM_IS_HTML_ELEMENT(node));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
g_assert(webkit_dom_node_is_same_node(WEBKIT_DOM_NODE(div), node));
// Now remove the tag.
webkit_dom_node_remove_child(WEBKIT_DOM_NODE(body), node, 0);
list = adoptGRef(webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(body)));
g_assert(WEBKIT_DOM_IS_NODE_LIST(list.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(list.get()));
g_assert_cmpint(webkit_dom_node_list_get_length(list.get()), ==, 0);
// Test insert before. If refChild is null, insert newChild as last element of parent.
div = webkit_dom_document_create_element(document, "DIV", 0);
g_assert(WEBKIT_DOM_IS_HTML_ELEMENT(div));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(div));
webkit_dom_node_insert_before(WEBKIT_DOM_NODE(body), WEBKIT_DOM_NODE(div), 0, 0);
g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(body)));
list = adoptGRef(webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(body)));
g_assert(WEBKIT_DOM_IS_NODE_LIST(list.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(list.get()));
g_assert_cmpint(webkit_dom_node_list_get_length(list.get()), ==, 1);
node = webkit_dom_node_list_item(list.get(), 0);
g_assert(WEBKIT_DOM_IS_HTML_ELEMENT(node));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
g_assert(webkit_dom_node_is_same_node(WEBKIT_DOM_NODE(div), node));
// Now insert a 'p' before 'div'.
p = webkit_dom_document_create_element(document, "P", 0);
g_assert(WEBKIT_DOM_IS_HTML_ELEMENT(p));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(p));
webkit_dom_node_insert_before(WEBKIT_DOM_NODE(body), WEBKIT_DOM_NODE(p), WEBKIT_DOM_NODE(div), 0);
g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(body)));
list = adoptGRef(webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(body)));
g_assert(WEBKIT_DOM_IS_NODE_LIST(list.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(list.get()));
g_assert_cmpint(webkit_dom_node_list_get_length(list.get()), ==, 2);
node = webkit_dom_node_list_item(list.get(), 0);
g_assert(WEBKIT_DOM_IS_HTML_ELEMENT(node));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
g_assert(webkit_dom_node_is_same_node(WEBKIT_DOM_NODE(p), node));
node = webkit_dom_node_list_item(list.get(), 1);
g_assert(WEBKIT_DOM_IS_HTML_ELEMENT(node));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
g_assert(webkit_dom_node_is_same_node(WEBKIT_DOM_NODE(div), node));
return true;
}
- bool testTagNames(WebKitWebPage* page)
+ bool testTagNamesNodeList(WebKitWebPage* page)
+ {
+ static const char* expectedTagNames[] = { "HTML", "HEAD", "BODY", "VIDEO", "SOURCE", "VIDEO", "SOURCE", "INPUT" };
+
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(document));
+
+ GRefPtr<WebKitDOMNodeList> list = adoptGRef(webkit_dom_document_query_selector_all(document, "*", nullptr));
+ g_assert(WEBKIT_DOM_IS_NODE_LIST(list.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(list.get()));
+ gulong nodeCount = webkit_dom_node_list_get_length(list.get());
+ g_assert_cmpuint(nodeCount, ==, G_N_ELEMENTS(expectedTagNames));
+ for (unsigned i = 0; i < nodeCount; i++) {
+ WebKitDOMNode* node = webkit_dom_node_list_item(list.get(), i);
+ g_assert(WEBKIT_DOM_IS_NODE(node));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
+ GUniquePtr<char> tagName(webkit_dom_node_get_node_name(node));
+ g_assert_cmpstr(tagName.get(), ==, expectedTagNames[i]);
+ }
+
+ return true;
+ }
+
+ bool testTagNamesHTMLCollection(WebKitWebPage* page)
{
static const char* expectedTagNames[] = { "HTML", "HEAD", "BODY", "VIDEO", "SOURCE", "VIDEO", "SOURCE", "INPUT" };
WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(document));
- WebKitDOMNodeList* list = webkit_dom_document_get_elements_by_tag_name(document, "*");
- gulong nodeCount = webkit_dom_node_list_get_length(list);
+ GRefPtr<WebKitDOMHTMLCollection> collection = adoptGRef(webkit_dom_document_get_elements_by_tag_name_as_html_collection(document, "*"));
+ g_assert(WEBKIT_DOM_IS_HTML_COLLECTION(collection.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(collection.get()));
+ gulong nodeCount = webkit_dom_html_collection_get_length(collection.get());
g_assert_cmpuint(nodeCount, ==, G_N_ELEMENTS(expectedTagNames));
for (unsigned i = 0; i < nodeCount; i++) {
- WebKitDOMNode* node = webkit_dom_node_list_item(list, i);
+ WebKitDOMNode* node = webkit_dom_html_collection_item(collection.get(), i);
g_assert(WEBKIT_DOM_IS_NODE(node));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
GUniquePtr<char> tagName(webkit_dom_node_get_node_name(node));
g_assert_cmpstr(tagName.get(), ==, expectedTagNames[i]);
}
@@ -170,14 +226,62 @@ private:
return true;
}
+ bool testDOMCache(WebKitWebPage* page)
+ {
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(document));
+
+ // DOM objects already in the document should be automatically handled by the cache.
+ WebKitDOMElement* div = webkit_dom_document_get_element_by_id(document, "container");
+ g_assert(WEBKIT_DOM_IS_HTML_ELEMENT(div));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(div));
+
+ // Get the same elment twice should return the same pointer.
+ g_assert(div == webkit_dom_document_get_element_by_id(document, "container"));
+
+ // A new DOM object created that is derived from Node should be automatically handled by the cache.
+ WebKitDOMElement* p = webkit_dom_document_create_element(document, "P", nullptr);
+ g_assert(WEBKIT_DOM_IS_HTML_PARAGRAPH_ELEMENT(p));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(p));
+
+ // A new DOM object created that isn't derived from Node should be manually handled.
+ GRefPtr<WebKitDOMNodeIterator> iter = adoptGRef(webkit_dom_document_create_node_iterator(document, WEBKIT_DOM_NODE(div), WEBKIT_DOM_NODE_FILTER_SHOW_ALL, nullptr, FALSE, nullptr));
+ g_assert(WEBKIT_DOM_IS_NODE_ITERATOR(iter.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(iter.get()));
+
+ // We can also manually handle a DOM object handled by the cache.
+ GRefPtr<WebKitDOMElement> p2 = adoptGRef(webkit_dom_document_create_element(document, "P", nullptr));
+ g_assert(WEBKIT_DOM_IS_HTML_PARAGRAPH_ELEMENT(p2.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(p2.get()));
+
+ // Manually handling a DOM object owned by the cache shouldn't crash when the cache has more than one reference.
+ GRefPtr<WebKitDOMElement> p3 = adoptGRef(webkit_dom_document_create_element(document, "P", nullptr));
+ g_assert(WEBKIT_DOM_IS_HTML_PARAGRAPH_ELEMENT(p3.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(p3.get()));
+ webkit_dom_node_append_child(WEBKIT_DOM_NODE(div), WEBKIT_DOM_NODE(p3.get()), nullptr);
+
+ // DOM objects removed from the document are also correctly handled by the cache.
+ WebKitDOMElement* a = webkit_dom_document_create_element(document, "A", nullptr);
+ g_assert(WEBKIT_DOM_IS_ELEMENT(a));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(a));
+ webkit_dom_node_remove_child(WEBKIT_DOM_NODE(div), WEBKIT_DOM_NODE(a), nullptr);
+
+ return true;
+ }
+
bool runTest(const char* testName, WebKitWebPage* page) override
{
if (!strcmp(testName, "hierarchy-navigation"))
return testHierarchyNavigation(page);
if (!strcmp(testName, "insertion"))
return testInsertion(page);
- if (!strcmp(testName, "tag-names"))
- return testTagNames(page);
+ if (!strcmp(testName, "tag-names-node-list"))
+ return testTagNamesNodeList(page);
+ if (!strcmp(testName, "tag-names-html-collection"))
+ return testTagNamesHTMLCollection(page);
+ if (!strcmp(testName, "dom-cache"))
+ return testDOMCache(page);
g_assert_not_reached();
return false;
@@ -188,7 +292,9 @@ static void __attribute__((constructor)) registerTests()
{
REGISTER_TEST(WebKitDOMNodeTest, "WebKitDOMNode/hierarchy-navigation");
REGISTER_TEST(WebKitDOMNodeTest, "WebKitDOMNode/insertion");
- REGISTER_TEST(WebKitDOMNodeTest, "WebKitDOMNode/tag-names");
+ REGISTER_TEST(WebKitDOMNodeTest, "WebKitDOMNode/tag-names-node-list");
+ REGISTER_TEST(WebKitDOMNodeTest, "WebKitDOMNode/tag-names-html-collection");
+ REGISTER_TEST(WebKitDOMNodeTest, "WebKitDOMNode/dom-cache");
}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMXPathNSResolverTest.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMXPathNSResolverTest.cpp
new file mode 100644
index 000000000..110677e41
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMXPathNSResolverTest.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "WebProcessTest.h"
+#include <gio/gio.h>
+#include <webkit2/webkit-web-extension.h>
+#include <wtf/glib/GUniquePtr.h>
+
+typedef struct _WebKitXPathNSResolver {
+ GObject parent;
+} WebKitXPathNSResolver;
+
+typedef struct _WebKitXPathNSResolverClass {
+ GObjectClass parentClass;
+} WebKitXPathNSResolverClass;
+
+static char* webkitXPathNSResolverLookupNamespaceURI(WebKitDOMXPathNSResolver* resolver, const char* prefix)
+{
+ if (!g_strcmp0(prefix, "foo"))
+ return g_strdup("http://www.example.com");
+
+ return nullptr;
+}
+
+static void webkitXPathNSResolverDOMXPathNSResolverIfaceInit(WebKitDOMXPathNSResolverIface* iface)
+{
+ iface->lookup_namespace_uri = webkitXPathNSResolverLookupNamespaceURI;
+}
+
+G_DEFINE_TYPE_WITH_CODE(WebKitXPathNSResolver, webkit_xpath_ns_resolver, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE(WEBKIT_DOM_TYPE_XPATH_NS_RESOLVER, webkitXPathNSResolverDOMXPathNSResolverIfaceInit))
+
+static void webkit_xpath_ns_resolver_init(WebKitXPathNSResolver*)
+{
+}
+
+static void webkit_xpath_ns_resolver_class_init(WebKitXPathNSResolverClass*)
+{
+}
+
+class WebKitDOMXPathNSResolverTest : public WebProcessTest {
+public:
+ static std::unique_ptr<WebProcessTest> create() { return std::unique_ptr<WebProcessTest>(new WebKitDOMXPathNSResolverTest()); }
+
+private:
+ void evaluateFooChildTextAndCheckResult(WebKitDOMDocument* document, WebKitDOMXPathNSResolver* resolver)
+ {
+ WebKitDOMElement* documentElement = webkit_dom_document_get_document_element(document);
+ g_assert(WEBKIT_DOM_IS_ELEMENT(documentElement));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(documentElement));
+
+ GRefPtr<WebKitDOMXPathResult> result = adoptGRef(webkit_dom_document_evaluate(document, "foo:child/text()", WEBKIT_DOM_NODE(documentElement), resolver, WEBKIT_DOM_XPATH_RESULT_ORDERED_NODE_ITERATOR_TYPE, nullptr, nullptr));
+ g_assert(WEBKIT_DOM_IS_XPATH_RESULT(result.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(result.get()));
+
+ WebKitDOMNode* nodeResult = webkit_dom_xpath_result_iterate_next(result.get(), nullptr);
+ g_assert(WEBKIT_DOM_IS_NODE(nodeResult));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(nodeResult));
+
+ GUniquePtr<char> nodeValue(webkit_dom_node_get_node_value(nodeResult));
+ g_assert_cmpstr(nodeValue.get(), ==, "SUCCESS");
+ }
+
+ bool testXPathNSResolverNative(WebKitWebPage* page)
+ {
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(document));
+
+ GRefPtr<WebKitDOMXPathNSResolver> resolver = adoptGRef(webkit_dom_document_create_ns_resolver(document, WEBKIT_DOM_NODE(webkit_dom_document_get_document_element(document))));
+ g_assert(WEBKIT_DOM_IS_XPATH_NS_RESOLVER(resolver.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(resolver.get()));
+ evaluateFooChildTextAndCheckResult(document, resolver.get());
+
+ return true;
+ }
+
+ bool testXPathNSResolverCustom(WebKitWebPage* page)
+ {
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(document));
+
+ GRefPtr<WebKitDOMXPathNSResolver> resolver = adoptGRef(WEBKIT_DOM_XPATH_NS_RESOLVER(g_object_new(webkit_xpath_ns_resolver_get_type(), nullptr)));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(resolver.get()));
+ evaluateFooChildTextAndCheckResult(document, resolver.get());
+
+ return true;
+ }
+
+ bool runTest(const char* testName, WebKitWebPage* page) override
+ {
+ if (!strcmp(testName, "native"))
+ return testXPathNSResolverNative(page);
+ if (!strcmp(testName, "custom"))
+ return testXPathNSResolverCustom(page);
+
+ g_assert_not_reached();
+ return false;
+ }
+};
+
+static void __attribute__((constructor)) registerTests()
+{
+ REGISTER_TEST(WebKitDOMXPathNSResolverTest, "WebKitDOMXPathNSResolver/native");
+ REGISTER_TEST(WebKitDOMXPathNSResolverTest, "WebKitDOMXPathNSResolver/custom");
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/EditorTest.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/EditorTest.cpp
new file mode 100644
index 000000000..873344271
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/EditorTest.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2015 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "WebProcessTest.h"
+#include <webkit2/webkit-web-extension.h>
+
+#define WEBKIT_DOM_USE_UNSTABLE_API
+#include <webkitdom/WebKitDOMDOMSelection.h>
+#include <webkitdom/WebKitDOMDOMWindowUnstable.h>
+
+class WebKitWebEditorTest : public WebProcessTest {
+public:
+ static std::unique_ptr<WebProcessTest> create() { return std::unique_ptr<WebProcessTest>(new WebKitWebEditorTest()); }
+
+private:
+ static void selectionChangedCallback(bool* selectionChanged)
+ {
+ *selectionChanged = true;
+ }
+
+ void testSelectionSelectAll(WebKitWebPage* page)
+ {
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+
+ webkit_dom_document_exec_command(document, "SelectAll", false, "");
+ }
+
+ void testSelectionCollapse(WebKitWebPage* page)
+ {
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ GRefPtr<WebKitDOMDOMWindow> domWindow = adoptGRef(webkit_dom_document_get_default_view(document));
+ g_assert(WEBKIT_DOM_IS_DOM_WINDOW(domWindow.get()));
+ GRefPtr<WebKitDOMDOMSelection> domSelection = adoptGRef(webkit_dom_dom_window_get_selection(domWindow.get()));
+ g_assert(WEBKIT_DOM_IS_DOM_SELECTION(domSelection.get()));
+
+ webkit_dom_dom_selection_collapse_to_start(domSelection.get(), nullptr);
+ }
+
+ void testSelectionModifyMove(WebKitWebPage* page)
+ {
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ GRefPtr<WebKitDOMDOMWindow> domWindow = adoptGRef(webkit_dom_document_get_default_view(document));
+ g_assert(WEBKIT_DOM_IS_DOM_WINDOW(domWindow.get()));
+ GRefPtr<WebKitDOMDOMSelection> domSelection = adoptGRef(webkit_dom_dom_window_get_selection(domWindow.get()));
+ g_assert(WEBKIT_DOM_IS_DOM_SELECTION(domSelection.get()));
+
+ webkit_dom_dom_selection_modify(domSelection.get(), "move", "forward", "character");
+ }
+
+ void testSelectionModifyExtend(WebKitWebPage* page)
+ {
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ GRefPtr<WebKitDOMDOMWindow> domWindow = adoptGRef(webkit_dom_document_get_default_view(document));
+ g_assert(WEBKIT_DOM_IS_DOM_WINDOW(domWindow.get()));
+ GRefPtr<WebKitDOMDOMSelection> domSelection = adoptGRef(webkit_dom_dom_window_get_selection(domWindow.get()));
+ g_assert(WEBKIT_DOM_IS_DOM_SELECTION(domSelection.get()));
+
+ webkit_dom_dom_selection_modify(domSelection.get(), "extend", "forward", "word");
+ }
+
+ void testSelectionUnselect(WebKitWebPage* page)
+ {
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+
+ webkit_dom_document_exec_command(document, "Unselect", false, "");
+ }
+
+ bool runTest(const char* testName, WebKitWebPage* page) override
+ {
+ if (!strcmp(testName, "selection-changed")) {
+ bool selectionChanged = false;
+
+ WebKitWebEditor* editor = webkit_web_page_get_editor(page);
+ g_assert(WEBKIT_IS_WEB_EDITOR(editor));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(editor));
+ g_signal_connect_swapped(editor, "selection-changed", G_CALLBACK(selectionChangedCallback), &selectionChanged);
+
+ testSelectionSelectAll(page);
+ g_assert(selectionChanged);
+
+ selectionChanged = false;
+ testSelectionCollapse(page);
+ g_assert(selectionChanged);
+
+ selectionChanged = false;
+ testSelectionModifyMove(page);
+ g_assert(selectionChanged);
+
+ selectionChanged = false;
+ testSelectionModifyExtend(page);
+ g_assert(selectionChanged);
+
+ selectionChanged = false;
+ testSelectionUnselect(page);
+ g_assert(selectionChanged);
+
+ return true;
+ }
+
+ g_assert_not_reached();
+ return false;
+ }
+};
+
+static void __attribute__((constructor)) registerTests()
+{
+ REGISTER_TEST(WebKitWebEditorTest, "WebKitWebEditor/selection-changed");
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/FrameTest.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/FrameTest.cpp
index b9c86365b..a32d3e52f 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/FrameTest.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/FrameTest.cpp
@@ -32,6 +32,7 @@ private:
{
WebKitFrame* frame = webkit_web_page_get_main_frame(page);
g_assert(WEBKIT_IS_FRAME(frame));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(frame));
g_assert(webkit_frame_is_main_frame(frame));
return true;
@@ -41,6 +42,7 @@ private:
{
WebKitFrame* frame = webkit_web_page_get_main_frame(page);
g_assert(WEBKIT_IS_FRAME(frame));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(frame));
g_assert_cmpstr(webkit_web_page_get_uri(page), ==, webkit_frame_get_uri(frame));
return true;
@@ -50,6 +52,7 @@ private:
{
WebKitFrame* frame = webkit_web_page_get_main_frame(page);
g_assert(WEBKIT_IS_FRAME(frame));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(frame));
g_assert(webkit_frame_get_javascript_global_context(frame));
return true;
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestAuthentication.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestAuthentication.cpp
index ede422556..0d0e0765d 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestAuthentication.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestAuthentication.cpp
@@ -20,7 +20,7 @@
#include "config.h"
#include "LoadTrackingTest.h"
#include "WebKitTestServer.h"
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
static WebKitTestServer* kServer;
@@ -232,6 +232,22 @@ static void testWebViewAuthenticationSuccess(AuthenticationTest* test, gconstpoi
g_assert_cmpstr(webkit_web_view_get_title(test->m_webView), ==, authExpectedSuccessTitle);
}
+static void testWebViewAuthenticationEmptyRealm(AuthenticationTest* test, gconstpointer)
+{
+ test->loadURI(kServer->getURIForPath("/empty-realm.html").data());
+ WebKitAuthenticationRequest* request = test->waitForAuthenticationRequest();
+ WebKitCredential* credential = webkit_credential_new(authTestUsername, authTestPassword, WEBKIT_CREDENTIAL_PERSISTENCE_FOR_SESSION);
+ webkit_authentication_request_authenticate(request, credential);
+ webkit_credential_free(credential);
+ test->waitUntilLoadFinished();
+
+ g_assert_cmpint(test->m_loadEvents.size(), ==, 3);
+ g_assert_cmpint(test->m_loadEvents[0], ==, LoadTrackingTest::ProvisionalLoadStarted);
+ g_assert_cmpint(test->m_loadEvents[1], ==, LoadTrackingTest::LoadCommitted);
+ g_assert_cmpint(test->m_loadEvents[2], ==, LoadTrackingTest::LoadFinished);
+ g_assert_cmpstr(webkit_web_view_get_title(test->m_webView), ==, authExpectedSuccessTitle);
+}
+
static void serverCallback(SoupServer*, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, void*)
{
if (message->method != SOUP_METHOD_GET) {
@@ -239,7 +255,7 @@ static void serverCallback(SoupServer*, SoupMessage* message, const char* path,
return;
}
- if (!strcmp(path, "/auth-test.html")) {
+ if (!strcmp(path, "/auth-test.html") || !strcmp(path, "/empty-realm.html")) {
const char* authorization = soup_message_headers_get_one(message->request_headers, "Authorization");
// Require authentication.
if (!g_strcmp0(authorization, authExpectedAuthorization)) {
@@ -250,7 +266,10 @@ static void serverCallback(SoupServer*, SoupMessage* message, const char* path,
} else if (++AuthenticationTest::authenticationRetries < 3) {
// No or invalid authorization header provided by the client, request authentication twice then fail.
soup_message_set_status(message, SOUP_STATUS_UNAUTHORIZED);
- soup_message_headers_append(message->response_headers, "WWW-Authenticate", "Basic realm=\"my realm\"");
+ if (!strcmp(path, "/empty-realm.html"))
+ soup_message_headers_append(message->response_headers, "WWW-Authenticate", "Basic");
+ else
+ soup_message_headers_append(message->response_headers, "WWW-Authenticate", "Basic realm=\"my realm\"");
// Include a failure message in case the user attempts to proceed without authentication.
soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, authFailureHTMLString, strlen(authFailureHTMLString));
} else {
@@ -272,12 +291,11 @@ void beforeAll()
AuthenticationTest::add("WebKitWebView", "authentication-request", testWebViewAuthenticationRequest);
AuthenticationTest::add("WebKitWebView", "authentication-cancel", testWebViewAuthenticationCancel);
AuthenticationTest::add("WebKitWebView", "authentication-load-cancelled", testWebViewAuthenticationLoadCancelled);
+ AuthenticationTest::add("WebKitWebView", "authentication-success", testWebViewAuthenticationSuccess);
AuthenticationTest::add("WebKitWebView", "authentication-failure", testWebViewAuthenticationFailure);
AuthenticationTest::add("WebKitWebView", "authentication-no-credential", testWebViewAuthenticationNoCredential);
AuthenticationTest::add("WebKitWebView", "authentication-storage", testWebViewAuthenticationStorage);
- // Testing authentication success must be done last because libsoup will never fire
- // the authenticate signal again once authentication is successful.
- AuthenticationTest::add("WebKitWebView", "authentication-success", testWebViewAuthenticationSuccess);
+ AuthenticationTest::add("WebKitWebView", "authentication-empty-realm", testWebViewAuthenticationEmptyRealm);
}
void afterAll()
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestAutocleanups.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestAutocleanups.cpp
new file mode 100644
index 000000000..3265182de
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestAutocleanups.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2015 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "WebViewTest.h"
+#include <webkit2/webkit2.h>
+
+#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
+
+static void testUIProcessAutocleanups(WebViewTest* test, gconstpointer)
+{
+ // Sanity-check a couple UI process API autocleanups that are easy to test....
+ g_autoptr(WebKitWebContext) context = webkit_web_context_new();
+ g_assert(WEBKIT_IS_WEB_CONTEXT(context));
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(context));
+
+ g_autoptr(WebKitWebsiteDataManager) manager = webkit_website_data_manager_new(nullptr);
+ g_assert(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager));
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(context));
+
+ g_autoptr(WebKitUserScript) userScript = webkit_user_script_new("",
+ WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_START,
+ nullptr, nullptr);
+ g_assert(userScript);
+ // Not a GObject, so just checking that this doesn't crash....
+}
+
+static void testWebProcessAutocleanups(WebViewTest* test, gconstpointer)
+{
+ static const char* testHTML = "<html><body></body></html>";
+ test->loadHtml(testHTML, nullptr);
+ test->waitUntilLoadFinished();
+
+ g_assert(test->runWebProcessTest("Autocleanups", "web-process-autocleanups"));
+}
+
+void beforeAll()
+{
+ WebViewTest::add("Autocleanups", "ui-process-autocleanups", testUIProcessAutocleanups);
+ WebViewTest::add("Autocleanups", "web-process-autocleanups", testWebProcessAutocleanups);
+}
+
+void afterAll()
+{
+}
+
+#endif // G_DEFINE_AUTOPTR_CLEANUP_FUNC
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestBackForwardList.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestBackForwardList.cpp
index 65c3d2d7c..fd2fbf5f2 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestBackForwardList.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestBackForwardList.cpp
@@ -264,6 +264,140 @@ static void testBackForwardListLimitAndCache(BackForwardListTest* test, gconstpo
g_assert_cmpuint(webkit_back_forward_list_get_length(test->m_list), ==, kBackForwardListLimit);
}
+static void testWebKitWebViewSessionState(BackForwardListTest* test, gconstpointer)
+{
+ WebKitWebViewSessionState* state = webkit_web_view_get_session_state(test->m_webView);
+ g_assert(state);
+ GRefPtr<WebKitWebView> view = WEBKIT_WEB_VIEW(webkit_web_view_new());
+ WebKitBackForwardList* bfList = webkit_web_view_get_back_forward_list(view.get());
+ g_assert_cmpuint(webkit_back_forward_list_get_length(bfList), ==, 0);
+ webkit_web_view_restore_session_state(view.get(), state);
+ g_assert_cmpuint(webkit_back_forward_list_get_length(bfList), ==, 0);
+ GRefPtr<GBytes> data = adoptGRef(webkit_web_view_session_state_serialize(state));
+ g_assert(data);
+ state = webkit_web_view_session_state_new(data.get());
+ g_assert(state);
+ view = WEBKIT_WEB_VIEW(webkit_web_view_new());
+ bfList = webkit_web_view_get_back_forward_list(view.get());
+ g_assert_cmpuint(webkit_back_forward_list_get_length(bfList), ==, 0);
+ webkit_web_view_restore_session_state(view.get(), state);
+ g_assert_cmpuint(webkit_back_forward_list_get_length(bfList), ==, 0);
+ webkit_web_view_session_state_unref(state);
+
+ CString uriPage1 = kServer->getURIForPath("/Page1");
+ test->m_changedFlags = BackForwardListTest::CurrentItem | BackForwardListTest::AddedItem;
+ test->loadURI(uriPage1.data());
+ test->waitUntilLoadFinished();
+
+ CString uriPage2 = kServer->getURIForPath("/Page2");
+ test->m_changedFlags = BackForwardListTest::CurrentItem | BackForwardListTest::AddedItem;
+ test->loadURI(uriPage2.data());
+ test->waitUntilLoadFinished();
+
+ CString uriPage3 = kServer->getURIForPath("/Page3");
+ test->m_changedFlags = BackForwardListTest::CurrentItem | BackForwardListTest::AddedItem;
+ test->loadURI(uriPage3.data());
+ test->waitUntilLoadFinished();
+
+ test->m_changedFlags = BackForwardListTest::CurrentItem;
+ test->goBack();
+ test->waitUntilLoadFinished();
+
+ state = webkit_web_view_get_session_state(test->m_webView);
+ g_assert(state);
+
+ g_assert_cmpuint(webkit_back_forward_list_get_length(bfList), ==, 0);
+ webkit_web_view_restore_session_state(view.get(), state);
+ g_assert_cmpuint(webkit_back_forward_list_get_length(bfList), ==, 3);
+
+ BackForwardListTest::checkItem(webkit_back_forward_list_get_nth_item(bfList, -1), "Page1", uriPage1.data(), uriPage1.data());
+ BackForwardListTest::checkItem(webkit_back_forward_list_get_current_item(bfList), "Page2", uriPage2.data(), uriPage2.data());
+ BackForwardListTest::checkItem(webkit_back_forward_list_get_nth_item(bfList, 1), "Page3", uriPage3.data(), uriPage3.data());
+
+ data = adoptGRef(webkit_web_view_session_state_serialize(state));
+ g_assert(data);
+ webkit_web_view_session_state_unref(state);
+ state = webkit_web_view_session_state_new(data.get());
+ g_assert(state);
+
+ view = WEBKIT_WEB_VIEW(webkit_web_view_new());
+ bfList = webkit_web_view_get_back_forward_list(view.get());
+ g_assert_cmpuint(webkit_back_forward_list_get_length(bfList), ==, 0);
+ webkit_web_view_restore_session_state(view.get(), state);
+ g_assert_cmpuint(webkit_back_forward_list_get_length(bfList), ==, 3);
+ webkit_web_view_session_state_unref(state);
+
+ BackForwardListTest::checkItem(webkit_back_forward_list_get_nth_item(bfList, -1), "Page1", uriPage1.data(), uriPage1.data());
+ BackForwardListTest::checkItem(webkit_back_forward_list_get_current_item(bfList), "Page2", uriPage2.data(), uriPage2.data());
+ BackForwardListTest::checkItem(webkit_back_forward_list_get_nth_item(bfList, 1), "Page3", uriPage3.data(), uriPage3.data());
+
+ static const char* invalidSessionData = "invalid session data";
+ data = adoptGRef(g_bytes_new_static(invalidSessionData, strlen(invalidSessionData)));
+ g_assert(!webkit_web_view_session_state_new(data.get()));
+}
+
+static void testWebKitWebViewSessionStateWithFormData(BackForwardListTest* test, gconstpointer)
+{
+ GUniquePtr<char> htmlPath(g_build_filename(Test::getResourcesDir(Test::WebKit2Resources).data(), "simple-form.html", nullptr));
+ GUniquePtr<char> htmlURL(g_filename_to_uri(htmlPath.get(), nullptr, nullptr));
+ test->m_changedFlags = BackForwardListTest::CurrentItem | BackForwardListTest::AddedItem;
+ test->loadURI(htmlURL.get());
+ test->waitUntilLoadFinished();
+
+ webkit_web_view_run_javascript(test->m_webView, "submitForm();", nullptr, nullptr, nullptr);
+ test->waitUntilLoadFinished();
+
+ WebKitWebViewSessionState* state = webkit_web_view_get_session_state(test->m_webView);
+ g_assert(state);
+ GRefPtr<WebKitWebView> view = WEBKIT_WEB_VIEW(webkit_web_view_new());
+ WebKitBackForwardList* bfList = webkit_web_view_get_back_forward_list(view.get());
+ g_assert_cmpuint(webkit_back_forward_list_get_length(bfList), ==, 0);
+ webkit_web_view_restore_session_state(view.get(), state);
+ g_assert_cmpuint(webkit_back_forward_list_get_length(bfList), ==, 2);
+ GRefPtr<GBytes> data = adoptGRef(webkit_web_view_session_state_serialize(state));
+ g_assert(data);
+ state = webkit_web_view_session_state_new(data.get());
+ g_assert(state);
+ view = WEBKIT_WEB_VIEW(webkit_web_view_new());
+ bfList = webkit_web_view_get_back_forward_list(view.get());
+ g_assert_cmpuint(webkit_back_forward_list_get_length(bfList), ==, 0);
+ webkit_web_view_restore_session_state(view.get(), state);
+ g_assert_cmpuint(webkit_back_forward_list_get_length(bfList), ==, 2);
+ webkit_web_view_session_state_unref(state);
+}
+
+static void viewLoadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent, GMainLoop* mainLoop)
+{
+ if (loadEvent == WEBKIT_LOAD_FINISHED)
+ g_main_loop_quit(mainLoop);
+}
+
+static void testWebKitWebViewNavigationAfterSessionRestore(BackForwardListTest* test, gconstpointer)
+{
+ // This test checks that a normal load after a session restore with a BackForard list having
+ // forward items doesn't produce any runtime critical warning. See https://bugs.webkit.org/show_bug.cgi?id=153233.
+ GRefPtr<WebKitWebView> view = WEBKIT_WEB_VIEW(webkit_web_view_new());
+ g_signal_connect(view.get(), "load-changed", G_CALLBACK(viewLoadChanged), test->m_mainLoop);
+
+ webkit_web_view_load_uri(view.get(), kServer->getURIForPath("/Page1").data());
+ g_main_loop_run(test->m_mainLoop);
+ webkit_web_view_load_uri(view.get(), kServer->getURIForPath("/Page2").data());
+ g_main_loop_run(test->m_mainLoop);
+ webkit_web_view_load_uri(view.get(), kServer->getURIForPath("/Page3").data());
+ g_main_loop_run(test->m_mainLoop);
+ webkit_web_view_go_back(view.get());
+ g_main_loop_run(test->m_mainLoop);
+
+ WebKitWebViewSessionState* state = webkit_web_view_get_session_state(view.get());
+ webkit_web_view_restore_session_state(test->m_webView, state);
+ webkit_web_view_session_state_unref(state);
+
+ // A normal load after a session restore should remove the forward list, add the new item and update the current one.
+ test->m_changedFlags = BackForwardListTest::CurrentItem | BackForwardListTest::AddedItem | BackForwardListTest::RemovedItems;
+ test->loadURI(kServer->getURIForPath("/Page4").data());
+ test->waitUntilLoadFinished();
+}
+
void beforeAll()
{
kServer = new WebKitTestServer();
@@ -271,6 +405,9 @@ void beforeAll()
BackForwardListTest::add("BackForwardList", "navigation", testBackForwardListNavigation);
BackForwardListTest::add("BackForwardList", "list-limit-and-cache", testBackForwardListLimitAndCache);
+ BackForwardListTest::add("WebKitWebView", "session-state", testWebKitWebViewSessionState);
+ BackForwardListTest::add("WebKitWebView", "session-state-with-form-data", testWebKitWebViewSessionStateWithFormData);
+ BackForwardListTest::add("WebKitWebView", "navigation-after-session-restore", testWebKitWebViewNavigationAfterSessionRestore);
}
void afterAll()
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestConsoleMessage.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestConsoleMessage.cpp
new file mode 100644
index 000000000..10dd8ca44
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestConsoleMessage.cpp
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2015 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2,1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "WebViewTest.h"
+#include <gtk/gtk.h>
+#include <webkit2/webkit2.h>
+
+class ConsoleMessageTest : public WebViewTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(ConsoleMessageTest);
+
+ // This should be keep in sync with the public enums in WebKitConsoleMessage.h.
+ enum class MessageSource { JavaScript, Network, ConsoleAPI, Security, Other };
+ enum class MessageLevel { Info, Log, Warning, Error, Debug };
+ struct ConsoleMessage {
+ bool operator==(const ConsoleMessage& other)
+ {
+ return source == other.source
+ && level == other.level
+ && message == other.message
+ && lineNumber == other.lineNumber
+ && sourceID == other.sourceID;
+ }
+
+ MessageSource source;
+ MessageLevel level;
+ CString message;
+ unsigned lineNumber;
+ CString sourceID;
+ };
+
+ static void consoleMessageReceivedCallback(WebKitUserContentManager*, WebKitJavascriptResult* message, ConsoleMessageTest* test)
+ {
+ g_assert(message);
+ GUniquePtr<char> messageString(WebViewTest::javascriptResultToCString(message));
+ GRefPtr<GVariant> variant = g_variant_parse(G_VARIANT_TYPE("(uusus)"), messageString.get(), nullptr, nullptr, nullptr);
+ g_assert(variant.get());
+
+ unsigned source, level, lineNumber;
+ const char* messageText;
+ const char* sourceID;
+ g_variant_get(variant.get(), "(uu&su&s)", &source, &level, &messageText, &lineNumber, &sourceID);
+ test->m_consoleMessage = { static_cast<ConsoleMessageTest::MessageSource>(source), static_cast<ConsoleMessageTest::MessageLevel>(level), messageText, lineNumber, sourceID };
+
+ g_main_loop_quit(test->m_mainLoop);
+ }
+
+ ConsoleMessageTest()
+ : WebViewTest(webkit_user_content_manager_new())
+ {
+ WebKitUserContentManager* manager = webkit_web_view_get_user_content_manager(m_webView);
+ webkit_user_content_manager_register_script_message_handler(manager, "console");
+ g_signal_connect(manager, "script-message-received::console", G_CALLBACK(consoleMessageReceivedCallback), this);
+ }
+
+ ~ConsoleMessageTest()
+ {
+ WebKitUserContentManager* manager = webkit_web_view_get_user_content_manager(m_webView);
+ g_signal_handlers_disconnect_matched(manager, G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, this);
+ webkit_user_content_manager_unregister_script_message_handler(manager, "console");
+ }
+
+ void waitUntilConsoleMessageReceived()
+ {
+ g_main_loop_run(m_mainLoop);
+ }
+
+ ConsoleMessage m_consoleMessage;
+};
+
+static void testWebKitConsoleMessageConsoleAPI(ConsoleMessageTest* test, gconstpointer)
+{
+ ConsoleMessageTest::ConsoleMessage referenceMessage = { ConsoleMessageTest::MessageSource::ConsoleAPI, ConsoleMessageTest::MessageLevel::Log, "Log Console Message", 1, "http://foo.com/bar" };
+ test->loadHtml("<html><body onload='console.log(\"Log Console Message\");'></body></html>", "http://foo.com/bar");
+ test->waitUntilConsoleMessageReceived();
+ g_assert(test->m_consoleMessage == referenceMessage);
+
+ referenceMessage.level = ConsoleMessageTest::MessageLevel::Info;
+ referenceMessage.message = "Info Console Message";
+ test->loadHtml("<html><body onload='console.info(\"Info Console Message\");'></body></html>", "http://foo.com/bar");
+ test->waitUntilConsoleMessageReceived();
+ g_assert(test->m_consoleMessage == referenceMessage);
+
+ referenceMessage.level = ConsoleMessageTest::MessageLevel::Warning;
+ referenceMessage.message = "Warning Console Message";
+ test->loadHtml("<html><body onload='console.warn(\"Warning Console Message\");'></body></html>", "http://foo.com/bar");
+ test->waitUntilConsoleMessageReceived();
+ g_assert(test->m_consoleMessage == referenceMessage);
+
+ referenceMessage.level = ConsoleMessageTest::MessageLevel::Error;
+ referenceMessage.message = "Error Console Message";
+ test->loadHtml("<html><body onload='console.error(\"Error Console Message\");'></body></html>", "http://foo.com/bar");
+ test->waitUntilConsoleMessageReceived();
+ g_assert(test->m_consoleMessage == referenceMessage);
+
+ referenceMessage.level = ConsoleMessageTest::MessageLevel::Debug;
+ referenceMessage.message = "Debug Console Message";
+ test->loadHtml("<html><body onload='console.debug(\"Debug Console Message\");'></body></html>", "http://foo.com/bar");
+ test->waitUntilConsoleMessageReceived();
+ g_assert(test->m_consoleMessage == referenceMessage);
+}
+
+static void testWebKitConsoleMessageJavaScriptException(ConsoleMessageTest* test, gconstpointer)
+{
+ ConsoleMessageTest::ConsoleMessage referenceMessage = { ConsoleMessageTest::MessageSource::JavaScript, ConsoleMessageTest::MessageLevel::Error,
+ "ReferenceError: Can't find variable: foo", 1, "http://foo.com/bar" };
+ test->loadHtml("<html><body onload='foo()'></body></html>", "http://foo.com/bar");
+ test->waitUntilConsoleMessageReceived();
+ g_assert(test->m_consoleMessage == referenceMessage);
+}
+
+static void testWebKitConsoleMessageNetworkError(ConsoleMessageTest* test, gconstpointer)
+{
+ ConsoleMessageTest::ConsoleMessage referenceMessage = { ConsoleMessageTest::MessageSource::Network, ConsoleMessageTest::MessageLevel::Error,
+ "Failed to load resource: Error opening file: No such file or directory", 0, "file:///foo/not-found.css" };
+ test->loadHtml("<html><head><link rel='stylesheet' href='not-found.css' type='text/css'></head><body></body></html>", "file:///foo/bar");
+ test->waitUntilConsoleMessageReceived();
+ g_assert(test->m_consoleMessage == referenceMessage);
+}
+
+static void testWebKitConsoleMessageSecurityError(ConsoleMessageTest* test, gconstpointer)
+{
+ ConsoleMessageTest::ConsoleMessage referenceMessage = { ConsoleMessageTest::MessageSource::Security, ConsoleMessageTest::MessageLevel::Error,
+ "Not allowed to load local resource: file:///foo/bar/source.png", 1, "http://foo.com/bar" };
+ test->loadHtml("<html><body><img src=\"file:///foo/bar/source.png\"/></body></html>", "http://foo.com/bar");
+ test->waitUntilConsoleMessageReceived();
+ g_assert(test->m_consoleMessage == referenceMessage);
+}
+
+void beforeAll()
+{
+ ConsoleMessageTest::add("WebKitConsoleMessage", "console-api", testWebKitConsoleMessageConsoleAPI);
+ ConsoleMessageTest::add("WebKitConsoleMessage", "js-exception", testWebKitConsoleMessageJavaScriptException);
+ ConsoleMessageTest::add("WebKitConsoleMessage", "network-error", testWebKitConsoleMessageNetworkError);
+ ConsoleMessageTest::add("WebKitConsoleMessage", "security-error", testWebKitConsoleMessageSecurityError);
+}
+
+void afterAll()
+{
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestContextMenu.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestContextMenu.cpp
index a91e78741..e08ec799d 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestContextMenu.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestContextMenu.cpp
@@ -19,7 +19,8 @@
#include "config.h"
#include "WebViewTest.h"
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/Vector.h>
+#include <wtf/glib/GRefPtr.h>
class ContextMenuTest: public WebViewTest {
public:
@@ -92,17 +93,6 @@ public:
return 0;
}
- bool shouldShowInputMethodsMenu()
- {
- GtkSettings* settings = gtk_widget_get_settings(GTK_WIDGET(m_webView));
- if (!settings)
- return true;
-
- gboolean showInputMethodMenu;
- g_object_get(settings, "gtk-show-input-method-menu", &showInputMethodMenu, NULL);
- return showInputMethodMenu;
- }
-
void checkActionState(GtkAction* action, unsigned state)
{
if (state & Visible)
@@ -239,7 +229,8 @@ public:
LinkImage,
Video,
Audio,
- Editable
+ Editable,
+ Selection
};
ContextMenuDefaultTest()
@@ -257,6 +248,7 @@ public:
g_assert(!webkit_hit_test_result_context_is_image(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_GO_BACK, Visible);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_GO_FORWARD, Visible);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_STOP, Visible);
@@ -267,6 +259,7 @@ public:
g_assert(!webkit_hit_test_result_context_is_image(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK, Visible | Enabled);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK_IN_NEW_WINDOW, Visible | Enabled);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_LINK_TO_DISK, Visible | Enabled);
@@ -277,6 +270,7 @@ public:
g_assert(webkit_hit_test_result_context_is_image(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_IMAGE_IN_NEW_WINDOW, Visible | Enabled);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_IMAGE_TO_DISK, Visible | Enabled);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY_IMAGE_TO_CLIPBOARD, Visible | Enabled);
@@ -287,6 +281,7 @@ public:
g_assert(webkit_hit_test_result_context_is_image(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK, Visible | Enabled);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK_IN_NEW_WINDOW, Visible | Enabled);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_LINK_TO_DISK, Visible | Enabled);
@@ -302,6 +297,7 @@ public:
g_assert(!webkit_hit_test_result_context_is_image(hitTestResult));
g_assert(webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_MEDIA_PLAY, Visible | Enabled);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_MEDIA_MUTE, Visible);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_TOGGLE_MEDIA_CONTROLS, Visible | Enabled | Checked);
@@ -317,6 +313,7 @@ public:
g_assert(!webkit_hit_test_result_context_is_image(hitTestResult));
g_assert(webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_MEDIA_PLAY, Visible | Enabled);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_MEDIA_MUTE, Visible);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_TOGGLE_MEDIA_CONTROLS, Visible | Enabled | Checked);
@@ -332,6 +329,7 @@ public:
g_assert(!webkit_hit_test_result_context_is_image(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(webkit_hit_test_result_context_is_editable(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_CUT, Visible);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY, Visible);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_PASTE, Visible | Enabled);
@@ -339,10 +337,16 @@ public:
iter = checkCurrentItemIsSeparatorAndGetNext(iter);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_SELECT_ALL, Visible | Enabled);
iter = checkCurrentItemIsSeparatorAndGetNext(iter);
- if (shouldShowInputMethodsMenu())
- iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_INPUT_METHODS, Visible | Enabled);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_UNICODE, Visible | Enabled);
break;
+ case Selection:
+ g_assert(!webkit_hit_test_result_context_is_link(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_image(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ g_assert(webkit_hit_test_result_context_is_selection(hitTestResult));
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY, Visible | Enabled);
+ break;
default:
g_assert_not_reached();
}
@@ -366,17 +370,32 @@ static void testContextMenuDefaultMenu(ContextMenuDefaultTest* test, gconstpoint
test->showInWindowAndWaitUntilMapped();
const char* linksHTML =
- "<html><body>"
+ "<html><head>"
+ " <script>"
+ " window.onload = function () {"
+ " window.getSelection().removeAllRanges();"
+ " var select_range = document.createRange();"
+ " select_range.selectNodeContents(document.getElementById('text_to_select'));"
+ " window.getSelection().addRange(select_range);"
+ " }"
+ " </script>"
+ "</head><body>"
" <a style='position:absolute; left:1; top:1' href='http://www.webkitgtk.org' title='WebKitGTK+ Title'>WebKitGTK+ Website</a>"
" <img style='position:absolute; left:1; top:10' src='0xdeadbeef' width=5 height=5></img>"
" <a style='position:absolute; left:1; top:20' href='http://www.webkitgtk.org/logo' title='WebKitGTK+ Logo'><img src='0xdeadbeef' width=5 height=5></img></a>"
" <input style='position:absolute; left:1; top:30' size='10'></input>"
" <video style='position:absolute; left:1; top:50' width='300' height='300' controls='controls' preload='none'><source src='movie.ogg' type='video/ogg' /></video>"
" <audio style='position:absolute; left:1; top:60' width='50' height='20' controls='controls' preload='none'><source src='track.mp3' type='audio/mp3' /></audio>"
+ " <p style='position:absolute; left:1; top:90' id='text_to_select'>Lorem ipsum.</p>"
"</body></html>";
test->loadHtml(linksHTML, "file:///");
test->waitUntilLoadFinished();
+ // Context menu for selection.
+ // This test should always be the first because any other click removes the selection.
+ test->m_expectedMenuType = ContextMenuDefaultTest::Selection;
+ test->showContextMenuAtPositionAndWaitUntilFinished(2, 115);
+
// Context menu for document.
test->m_expectedMenuType = ContextMenuDefaultTest::Navigation;
test->showContextMenuAtPositionAndWaitUntilFinished(0, 0);
@@ -851,6 +870,161 @@ static void testContextMenuSmartSeparators(ContextMenuSmartSeparatorsTest* test,
g_assert(!GTK_IS_SEPARATOR_MENU_ITEM(item) && !gtk_widget_get_visible(item));
}
+class ContextMenuWebExtensionTest: public ContextMenuTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(ContextMenuWebExtensionTest);
+
+ void deserializeContextMenuFromUserData(GVariant* userData)
+ {
+ m_actions.clear();
+ if (!userData)
+ return;
+
+ GVariantIter iter;
+ g_variant_iter_init(&iter, userData);
+ m_actions.reserveInitialCapacity(g_variant_iter_n_children(&iter));
+
+ uint32_t item;
+ while (g_variant_iter_next(&iter, "u", &item))
+ m_actions.uncheckedAppend(static_cast<WebKitContextMenuAction>(item));
+ }
+
+ bool contextMenu(WebKitContextMenu* menu, GdkEvent*, WebKitHitTestResult*)
+ {
+ deserializeContextMenuFromUserData(webkit_context_menu_get_user_data(menu));
+ GList* items = webkit_context_menu_get_items(menu);
+ g_assert_cmpuint(g_list_length(items), ==, m_actions.size());
+
+ unsigned actionIndex = 0;
+ for (GList* it = items; it; it = g_list_next(it)) {
+ WebKitContextMenuItem* item = WEBKIT_CONTEXT_MENU_ITEM(it->data);
+ g_assert_cmpuint(webkit_context_menu_item_get_stock_action(item), ==, m_actions[actionIndex++]);
+ }
+
+ quitMainLoop();
+
+ return true;
+ }
+
+ Vector<WebKitContextMenuAction> m_actions;
+};
+
+static void testContextMenuWebExtensionMenu(ContextMenuWebExtensionTest* test, gconstpointer)
+{
+ test->showInWindowAndWaitUntilMapped();
+ test->loadHtml("<html><body>WebKitGTK+ Context menu tests<br>"
+ "<a style='position:absolute; left:1; top:10' href='http://www.webkitgtk.org'>WebKitGTK+ Website</a></body></html>",
+ "ContextMenuTestDefault");
+ test->waitUntilLoadFinished();
+
+ // Default context menu.
+ test->showContextMenuAtPositionAndWaitUntilFinished(1, 1);
+ g_assert_cmpuint(test->m_actions.size(), ==, 4);
+ g_assert_cmpuint(test->m_actions[0], ==, WEBKIT_CONTEXT_MENU_ACTION_GO_BACK);
+ g_assert_cmpuint(test->m_actions[1], ==, WEBKIT_CONTEXT_MENU_ACTION_GO_FORWARD);
+ g_assert_cmpuint(test->m_actions[2], ==, WEBKIT_CONTEXT_MENU_ACTION_STOP);
+ g_assert_cmpuint(test->m_actions[3], ==, WEBKIT_CONTEXT_MENU_ACTION_RELOAD);
+
+ // Link menu.
+ test->showContextMenuAtPositionAndWaitUntilFinished(1, 11);
+ g_assert_cmpuint(test->m_actions.size(), ==, 4);
+ g_assert_cmpuint(test->m_actions[0], ==, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK);
+ g_assert_cmpuint(test->m_actions[1], ==, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK_IN_NEW_WINDOW);
+ g_assert_cmpuint(test->m_actions[2], ==, WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_LINK_TO_DISK);
+ g_assert_cmpuint(test->m_actions[3], ==, WEBKIT_CONTEXT_MENU_ACTION_COPY_LINK_TO_CLIPBOARD);
+
+ // Custom menu.
+ test->loadHtml("<html><body></body></html>", "ContextMenuTestCustom");
+ test->showContextMenuAndWaitUntilFinished();
+ g_assert_cmpuint(test->m_actions.size(), ==, 4);
+ g_assert_cmpuint(test->m_actions[0], ==, WEBKIT_CONTEXT_MENU_ACTION_STOP);
+ g_assert_cmpuint(test->m_actions[1], ==, WEBKIT_CONTEXT_MENU_ACTION_RELOAD);
+ g_assert_cmpuint(test->m_actions[2], ==, WEBKIT_CONTEXT_MENU_ACTION_NO_ACTION);
+ g_assert_cmpuint(test->m_actions[3], ==, WEBKIT_CONTEXT_MENU_ACTION_INSPECT_ELEMENT);
+
+ // Menu cleared by the web process.
+ test->loadHtml("<html><body></body></html>", "ContextMenuTestClear");
+ test->showContextMenuAndWaitUntilFinished();
+ g_assert_cmpuint(test->m_actions.size(), ==, 0);
+}
+
+class ContextMenuWebExtensionNodeTest: public ContextMenuTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(ContextMenuWebExtensionNodeTest);
+
+ struct Node {
+ enum {
+ NodeUnknown = 0,
+ NodeElement = 1,
+ NodeText = 3
+ };
+ typedef unsigned Type;
+
+ CString name;
+ Type type;
+ CString contents;
+ CString parentName;
+ };
+
+ void deserializeNodeFromUserData(GVariant* userData)
+ {
+ GVariantIter iter;
+ g_variant_iter_init(&iter, userData);
+
+ const char* key;
+ GVariant* value;
+ while (g_variant_iter_next(&iter, "{&sv}", &key, &value)) {
+ if (!strcmp(key, "Name") && g_variant_classify(value) == G_VARIANT_CLASS_STRING)
+ m_node.name = g_variant_get_string(value, nullptr);
+ else if (!strcmp(key, "Type") && g_variant_classify(value) == G_VARIANT_CLASS_UINT32)
+ m_node.type = g_variant_get_uint32(value);
+ else if (!strcmp(key, "Contents") && g_variant_classify(value) == G_VARIANT_CLASS_STRING)
+ m_node.contents = g_variant_get_string(value, nullptr);
+ else if (!strcmp(key, "Parent") && g_variant_classify(value) == G_VARIANT_CLASS_STRING)
+ m_node.parentName = g_variant_get_string(value, nullptr);
+ g_variant_unref(value);
+ }
+ }
+
+ bool contextMenu(WebKitContextMenu* menu, GdkEvent*, WebKitHitTestResult*)
+ {
+ deserializeNodeFromUserData(webkit_context_menu_get_user_data(menu));
+ quitMainLoop();
+
+ return true;
+ }
+
+ Node m_node;
+};
+
+static void testContextMenuWebExtensionNode(ContextMenuWebExtensionNodeTest* test, gconstpointer)
+{
+ test->showInWindowAndWaitUntilMapped();
+ test->loadHtml("<html><body><p style='position:absolute; left:1; top:1'>WebKitGTK+ Context menu tests</p><br>"
+ "<a style='position:absolute; left:1; top:100' href='http://www.webkitgtk.org'>WebKitGTK+ Website</a></body></html>",
+ "ContextMenuTestNode");
+ test->waitUntilLoadFinished();
+
+ test->showContextMenuAtPositionAndWaitUntilFinished(0, 0);
+ g_assert_cmpstr(test->m_node.name.data(), ==, "HTML");
+ g_assert_cmpuint(test->m_node.type, ==, ContextMenuWebExtensionNodeTest::Node::NodeElement);
+ g_assert_cmpstr(test->m_node.contents.data(), ==, "WebKitGTK+ Context menu testsWebKitGTK+ Website");
+ g_assert_cmpstr(test->m_node.parentName.data(), ==, "#document");
+
+ test->showContextMenuAtPositionAndWaitUntilFinished(1, 20);
+ g_assert_cmpstr(test->m_node.name.data(), ==, "#text");
+ g_assert_cmpuint(test->m_node.type, ==, ContextMenuWebExtensionNodeTest::Node::NodeText);
+ g_assert_cmpstr(test->m_node.contents.data(), ==, "WebKitGTK+ Context menu tests");
+ g_assert_cmpstr(test->m_node.parentName.data(), ==, "P");
+
+ // Link menu.
+ test->showContextMenuAtPositionAndWaitUntilFinished(1, 101);
+ g_assert_cmpstr(test->m_node.name.data(), ==, "#text");
+ g_assert_cmpuint(test->m_node.type, ==, ContextMenuWebExtensionNodeTest::Node::NodeText);
+ g_assert_cmpstr(test->m_node.contents.data(), ==, "WebKitGTK+ Website");
+ g_assert_cmpstr(test->m_node.parentName.data(), ==, "A");
+}
+
void beforeAll()
{
ContextMenuDefaultTest::add("WebKitWebView", "default-menu", testContextMenuDefaultMenu);
@@ -860,6 +1034,8 @@ void beforeAll()
ContextMenuSubmenuTest::add("WebKitWebView", "submenu", testContextMenuSubMenu);
ContextMenuDismissedTest::add("WebKitWebView", "menu-dismissed", testContextMenuDismissed);
ContextMenuSmartSeparatorsTest::add("WebKitWebView", "smart-separators", testContextMenuSmartSeparators);
+ ContextMenuWebExtensionTest::add("WebKitWebPage", "context-menu", testContextMenuWebExtensionMenu);
+ ContextMenuWebExtensionNodeTest::add("WebKitWebPage", "context-menu-node", testContextMenuWebExtensionNode);
}
void afterAll()
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestCookieManager.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestCookieManager.cpp
index 2e98645e8..1e842cd04 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestCookieManager.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestCookieManager.cpp
@@ -24,7 +24,6 @@
#include <glib/gstdio.h>
static WebKitTestServer* kServer;
-static char* kTempDirectory;
static const char* kFirstPartyDomain = "127.0.0.1";
static const char* kThirdPartyDomain = "localhost";
@@ -72,12 +71,12 @@ public:
switch (storage) {
case WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT:
if (!m_cookiesTextFile)
- m_cookiesTextFile.reset(g_build_filename(kTempDirectory, "cookies.txt", NULL));
+ m_cookiesTextFile.reset(g_build_filename(Test::dataDirectory(), "cookies.txt", nullptr));
filename = m_cookiesTextFile.get();
break;
case WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE:
if (!m_cookiesSQLiteFile)
- m_cookiesSQLiteFile.reset(g_build_filename(kTempDirectory, "cookies.db", NULL));
+ m_cookiesSQLiteFile.reset(g_build_filename(Test::dataDirectory(), "cookies.db", nullptr));
filename = m_cookiesSQLiteFile.get();
break;
default:
@@ -315,9 +314,6 @@ void beforeAll()
kServer = new WebKitTestServer();
kServer->run(serverCallback);
- kTempDirectory = g_dir_make_tmp("WebKit2Tests-XXXXXX", 0);
- g_assert(kTempDirectory);
-
CookieManagerTest::add("WebKitCookieManager", "accept-policy", testCookieManagerAcceptPolicy);
CookieManagerTest::add("WebKitCookieManager", "delete-cookies", testCookieManagerDeleteCookies);
CookieManagerTest::add("WebKitCookieManager", "cookies-changed", testCookieManagerCookiesChanged);
@@ -327,5 +323,4 @@ void beforeAll()
void afterAll()
{
delete kServer;
- g_rmdir(kTempDirectory);
}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMDOMWindow.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMDOMWindow.cpp
new file mode 100644
index 000000000..98c6e1064
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMDOMWindow.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2013 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2,1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "WebProcessTestRunner.h"
+#include "WebViewTest.h"
+#include <gtk/gtk.h>
+#include <webkit2/webkit2.h>
+
+#define HTML_DOCUMENT "<html><head><title></title></head><style type='text/css'>#test { font-size: 16px; }</style><body><p id='test'>test</p></body></html>"
+
+typedef struct {
+ gboolean loaded;
+ gboolean clicked;
+ WebProcessTestRunner* testRunner;
+ WebViewTest* test;
+} DomDomWindowTestStatus;
+
+static DomDomWindowTestStatus status;
+
+static void signalsNotifyCallback(const gchar *key, const gchar *value, gconstpointer)
+{
+ if (g_str_equal(key, "ready")) {
+ // The document was already loaded in the webprocess, and its "load"
+ // signal couldn't be captured on time (was issued before the test
+ // started). We load it again to force a new "load" signal in the
+ // webprocess, which will be captured this time
+ status.test->loadHtml(HTML_DOCUMENT, 0);
+ }
+
+ if (g_str_equal(key, "loaded")) {
+ status.loaded = TRUE;
+ status.test->showInWindowAndWaitUntilMapped();
+
+ // Click in a known location where the text is
+ status.test->clickMouseButton(20, 18, 1, 0);
+ }
+
+ if (g_str_equal(key, "clicked"))
+ status.clicked = TRUE;
+
+ if (g_str_equal(key, "finish")) {
+ status.test = 0;
+ status.testRunner->finishTest(status.loaded && status.clicked);
+ }
+}
+
+static void dispatchEventNotifyCallback(const gchar *key, const gchar *value, gconstpointer)
+{
+ if (g_str_equal(key, "ready")) {
+ // The document was already loaded in the webprocess, and its "load"
+ // signal couldn't be captured on time (was issued before the test
+ // started). We load it again to force a new "load" signal in the
+ // webprocess, which will be captured this time
+ status.test->loadHtml(HTML_DOCUMENT, 0);
+ }
+
+ if (g_str_equal(key, "loaded"))
+ status.loaded = TRUE;
+
+ if (g_str_equal(key, "clicked"))
+ status.clicked = TRUE;
+
+ if (g_str_equal(key, "finish")) {
+ status.test = 0;
+ status.testRunner->finishTest(status.loaded && status.clicked);
+ }
+}
+
+static void testWebKitDOMDOMWindowSignals(WebViewTest* test, gconstpointer)
+{
+ status.loaded = FALSE;
+ status.clicked = FALSE;
+ status.test = test;
+
+ status.testRunner->setNotifyCallback(G_CALLBACK(signalsNotifyCallback), 0);
+
+ // The HTML document will we loaded later, when the test is "ready" because
+ // we want to test the "load" signal
+
+ GVariantBuilder builder;
+ g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
+ g_variant_builder_add(&builder, "{sv}", "pageID", g_variant_new_uint64(webkit_web_view_get_page_id(status.test->m_webView)));
+ status.testRunner->runTestAndWait("WebKitDOMDOMWindow", "signals", g_variant_builder_end(&builder));
+ g_assert(status.testRunner->getTestResult());
+}
+
+static void testWebKitDOMDOMWindowDispatchEvent(WebViewTest* test, gconstpointer)
+{
+ status.loaded = FALSE;
+ status.clicked = FALSE;
+ status.test = test;
+
+ status.testRunner->setNotifyCallback(G_CALLBACK(dispatchEventNotifyCallback), 0);
+
+ // The HTML document will we loaded later, when the test is "ready" because
+ // we want to test the "load" signal
+
+ GVariantBuilder builder;
+ g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
+ g_variant_builder_add(&builder, "{sv}", "pageID", g_variant_new_uint64(webkit_web_view_get_page_id(status.test->m_webView)));
+ status.testRunner->runTestAndWait("WebKitDOMDOMWindow", "dispatch-event", g_variant_builder_end(&builder));
+ g_assert(status.testRunner->getTestResult());
+}
+
+static void testWebKitDOMDOMWindowGetComputedStyle(WebViewTest* test, gconstpointer)
+{
+ status.loaded = FALSE;
+ status.clicked = FALSE;
+ status.test = test;
+
+ static const char* testHTML = HTML_DOCUMENT;
+ status.test->loadHtml(testHTML, 0);
+ status.test->waitUntilLoadFinished();
+
+ GVariantBuilder builder;
+ g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
+ g_variant_builder_add(&builder, "{sv}", "pageID", g_variant_new_uint64(webkit_web_view_get_page_id(status.test->m_webView)));
+ g_assert(status.testRunner->runTest("WebKitDOMDOMWindow", "get-computed-style", g_variant_builder_end(&builder)));
+}
+
+void beforeAll()
+{
+ status.testRunner = new WebProcessTestRunner();
+ webkit_web_context_set_web_extensions_directory(webkit_web_context_get_default(), WEBKIT_TEST_WEB_EXTENSIONS_DIR);
+
+ WebViewTest::add("WebKitDOMDOMWindow", "signals", testWebKitDOMDOMWindowSignals);
+ WebViewTest::add("WebKitDOMDOMWindow", "dispatch-event", testWebKitDOMDOMWindowDispatchEvent);
+ WebViewTest::add("WebKitDOMDOMWindow", "get-computed-style", testWebKitDOMDOMWindowGetComputedStyle);
+}
+
+void afterAll()
+{
+ delete status.testRunner;
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMNode.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMNode.cpp
index 16db87d98..886356b7e 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMNode.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMNode.cpp
@@ -41,7 +41,7 @@ static void testWebKitDOMNodeInsertion(WebViewTest* test, gconstpointer)
g_assert(test->runWebProcessTest("WebKitDOMNode", "insertion"));
}
-static void testWebKitDOMNodeTagNames(WebViewTest* test, gconstpointer)
+static void prepareDOMForTagNamesTests(WebViewTest* test)
{
static const char* testHTML = "<html><head></head><body>"
"<video id='video' preload='none'>"
@@ -53,19 +53,44 @@ static void testWebKitDOMNodeTagNames(WebViewTest* test, gconstpointer)
" Your browser does not support the video tag."
"</video>"
"<input type='hidden' id='test' name='finish' value='false'></body></html>";
- test->loadHtml(testHTML, 0);
+ test->loadHtml(testHTML, nullptr);
test->waitUntilLoadFinished();
+}
- g_assert(test->runWebProcessTest("WebKitDOMNode", "tag-names"));
+static void testWebKitDOMNodeTagNamesNodeList(WebViewTest* test, gconstpointer)
+{
+ prepareDOMForTagNamesTests(test);
+ g_assert(test->runWebProcessTest("WebKitDOMNode", "tag-names-node-list"));
}
-void beforeAll()
+static void testWebKitDOMNodeTagNamesHTMLCollection(WebViewTest* test, gconstpointer)
+{
+ prepareDOMForTagNamesTests(test);
+ g_assert(test->runWebProcessTest("WebKitDOMNode", "tag-names-html-collection"));
+}
+
+static void testWebKitDOMObjectCache(WebViewTest* test, gconstpointer)
{
- webkit_web_context_set_web_extensions_directory(webkit_web_context_get_default(), WEBKIT_TEST_WEB_EXTENSIONS_DIR);
+ static const char* testHTML = "<html><body><div id='container'><p>DOM Cache test</p><a id='link href='#'>link</a></div></body></html>";
+ // Run the test 3 times to make sure the DOM objects are correctly released when the
+ // document is detached from the frame for every new document created.
+ for (unsigned i = 0; i < 3; ++i) {
+ test->loadHtml(testHTML, nullptr);
+ test->waitUntilLoadFinished();
+
+ g_assert(test->runWebProcessTest("WebKitDOMNode", "dom-cache"));
+ }
+}
+
+
+void beforeAll()
+{
WebViewTest::add("WebKitDOMNode", "hierarchy-navigation", testWebKitDOMNodeHierarchyNavigation);
WebViewTest::add("WebKitDOMNode", "insertion", testWebKitDOMNodeInsertion);
- WebViewTest::add("WebKitDOMNode", "tag-names", testWebKitDOMNodeTagNames);
+ WebViewTest::add("WebKitDOMNode", "tag-names-node-list", testWebKitDOMNodeTagNamesNodeList);
+ WebViewTest::add("WebKitDOMNode", "tag-names-html-collection", testWebKitDOMNodeTagNamesHTMLCollection);
+ WebViewTest::add("WebKitDOMNode", "dom-cache", testWebKitDOMObjectCache);
}
void afterAll()
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMNodeFilter.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMNodeFilter.cpp
new file mode 100644
index 000000000..812946153
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMNodeFilter.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2,1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "WebViewTest.h"
+#include <gtk/gtk.h>
+#include <webkit2/webkit2.h>
+
+static const char* testHTML = "<html id='root'><head><title>DOMNodeTreeWalker</title></head>"
+ "<body><input type='button' name='push' value='push'><input type='button' name='clear' value='clear'><br></body></html>";
+
+static void runTest(WebViewTest* test, const char* name)
+{
+ test->loadHtml(testHTML, nullptr);
+ test->waitUntilLoadFinished();
+
+ g_assert(test->runWebProcessTest("WebKitDOMNodeFilter", name));
+}
+
+static void testWebKitDOMNodeFilterTreeWalker(WebViewTest* test, gconstpointer)
+{
+ runTest(test, "tree-walker");
+}
+
+static void testWebKitDOMNodeFilterNodeIterator(WebViewTest* test, gconstpointer)
+{
+ runTest(test, "node-iterator");
+}
+
+void beforeAll()
+{
+ WebViewTest::add("WebKitDOMNodeFilter", "tree-walker", testWebKitDOMNodeFilterTreeWalker);
+ WebViewTest::add("WebKitDOMNodeFilter", "node-iterator", testWebKitDOMNodeFilterNodeIterator);
+}
+
+void afterAll()
+{
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMXPathNSResolver.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMXPathNSResolver.cpp
new file mode 100644
index 000000000..ff9a77192
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMXPathNSResolver.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2,1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "WebViewTest.h"
+#include <gtk/gtk.h>
+#include <webkit2/webkit2.h>
+
+static void testWebKitDOMXPathNSResolverNative(WebViewTest* test, gconstpointer)
+{
+ static const char* nativeXML = "<root xmlns:foo='http://www.example.org'><foo:child>SUCCESS</foo:child></root>";
+ GRefPtr<GBytes> bytes = adoptGRef(g_bytes_new_static(nativeXML, strlen(nativeXML)));
+ test->loadBytes(bytes.get(), "text/xml", nullptr, nullptr);
+ test->waitUntilLoadFinished();
+ g_assert(test->runWebProcessTest("WebKitDOMXPathNSResolver", "native"));
+}
+
+static void testWebKitDOMXPathNSResolverCustom(WebViewTest* test, gconstpointer)
+{
+ static const char* customXML = "<root xmlns='http://www.example.com'><child>SUCCESS</child></root>";
+ GRefPtr<GBytes> bytes = adoptGRef(g_bytes_new_static(customXML, strlen(customXML)));
+ test->loadBytes(bytes.get(), "text/xml", nullptr, nullptr);
+ test->waitUntilLoadFinished();
+ g_assert(test->runWebProcessTest("WebKitDOMXPathNSResolver", "custom"));
+}
+
+void beforeAll()
+{
+ WebViewTest::add("WebKitDOMXPathNSResolver", "native", testWebKitDOMXPathNSResolverNative);
+ WebViewTest::add("WebKitDOMXPathNSResolver", "custom", testWebKitDOMXPathNSResolverCustom);
+}
+
+void afterAll()
+{
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDownloads.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDownloads.cpp
index a4d27a508..b4f21a130 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDownloads.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDownloads.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Igalia S.L.
+ * Copyright (C) 2012, 2014 Igalia S.L.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -27,12 +27,10 @@
#include <string.h>
#include <webkit2/webkit2.h>
#include <wtf/Vector.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>
-static char* kTempDirectory;
-
class DownloadTest: public Test {
public:
MAKE_GLIB_TEST_FIXTURE(DownloadTest);
@@ -56,6 +54,8 @@ public:
{
g_assert(webkit_download_get_destination(download));
g_assert_cmpstr(webkit_download_get_destination(download), ==, destination);
+ GRefPtr<GFile> file = adoptGRef(g_file_new_for_uri(destination));
+ g_assert(g_file_query_exists(file.get(), nullptr));
test->createdDestination(download, destination);
}
@@ -72,6 +72,14 @@ public:
static void failedCallback(WebKitDownload* download, GError* error, DownloadTest* test)
{
g_assert(error);
+
+ const char* destinationURI = webkit_download_get_destination(download);
+ if (destinationURI) {
+ GUniquePtr<char> tempFileURI(g_strconcat(destinationURI, ".wkdownload", nullptr));
+ GRefPtr<GFile> tempFile = adoptGRef(g_file_new_for_uri(tempFileURI.get()));
+ g_assert(!g_file_query_exists(tempFile.get(), nullptr));
+ }
+
test->failed(download, error);
}
@@ -95,21 +103,23 @@ public:
}
DownloadTest()
- : m_webContext(webkit_web_context_get_default())
- , m_mainLoop(g_main_loop_new(0, TRUE))
+ : m_mainLoop(g_main_loop_new(nullptr, TRUE))
, m_downloadSize(0)
+ , m_allowOverwrite(false)
{
- g_signal_connect(m_webContext, "download-started", G_CALLBACK(downloadStartedCallback), this);
+ g_signal_connect(m_webContext.get(), "download-started", G_CALLBACK(downloadStartedCallback), this);
}
~DownloadTest()
{
- g_signal_handlers_disconnect_matched(m_webContext, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
+ g_signal_handlers_disconnect_matched(m_webContext.get(), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
g_main_loop_unref(m_mainLoop);
}
virtual void started(WebKitDownload* download)
{
+ m_downloadSize = 0;
+ m_downloadEvents.clear();
m_downloadEvents.append(Started);
}
@@ -144,16 +154,20 @@ public:
virtual void decideDestination(WebKitDownload* download, const gchar* suggestedFilename)
{
- GUniquePtr<char> destination(g_build_filename(kTempDirectory, suggestedFilename, NULL));
+ GUniquePtr<char> destination(g_build_filename(Test::dataDirectory(), suggestedFilename, nullptr));
GUniquePtr<char> destinationURI(g_filename_to_uri(destination.get(), 0, 0));
webkit_download_set_destination(download, destinationURI.get());
}
WebKitDownload* downloadURIAndWaitUntilFinishes(const CString& requestURI)
{
- WebKitDownload* download = webkit_web_context_download_uri(m_webContext, requestURI.data());
+ WebKitDownload* download = webkit_web_context_download_uri(m_webContext.get(), requestURI.data());
assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download));
+ g_assert(!webkit_download_get_allow_overwrite(download));
+ webkit_download_set_allow_overwrite(download, m_allowOverwrite);
+ g_assert(webkit_download_get_allow_overwrite(download) == m_allowOverwrite);
+
WebKitURIRequest* request = webkit_download_get_request(download);
g_assert(request);
ASSERT_CMP_CSTRING(webkit_uri_request_get_uri(request), ==, requestURI);
@@ -174,15 +188,15 @@ public:
g_file_delete(destFile.get(), 0, 0);
}
- WebKitWebContext* m_webContext;
GMainLoop* m_mainLoop;
Vector<DownloadEvent> m_downloadEvents;
guint64 m_downloadSize;
+ bool m_allowOverwrite;
};
-static void testDownloadLocalFile(DownloadTest* test, gconstpointer)
+static GRefPtr<WebKitDownload> downloadLocalFileSuccessfully(DownloadTest* test, const char* filename)
{
- GUniquePtr<char> sourcePath(g_build_filename(Test::getWebKit1TestResoucesDir().data(), "test.pdf", NULL));
+ GUniquePtr<char> sourcePath(g_build_filename(Test::getResourcesDir().data(), filename, nullptr));
GRefPtr<GFile> source = adoptGRef(g_file_new_for_path(sourcePath.get()));
GRefPtr<GFileInfo> sourceInfo = adoptGRef(g_file_query_info(source.get(), G_FILE_ATTRIBUTE_STANDARD_SIZE, static_cast<GFileQueryInfoFlags>(0), 0, 0));
GUniquePtr<char> sourceURI(g_file_get_uri(source.get()));
@@ -204,15 +218,50 @@ static void testDownloadLocalFile(DownloadTest* test, gconstpointer)
g_assert_cmpint(test->m_downloadSize, ==, g_file_info_get_size(sourceInfo.get()));
g_assert(webkit_download_get_destination(download.get()));
g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), ==, 1);
- test->checkDestinationAndDeleteFile(download.get(), "test.pdf");
+
+ return download;
+}
+
+static void testDownloadLocalFile(DownloadTest* test, gconstpointer)
+{
+ static const char* filename = "test.pdf";
+ GRefPtr<WebKitDownload> download = downloadLocalFileSuccessfully(test, filename);
+ test->checkDestinationAndDeleteFile(download.get(), filename);
+}
+
+static void createFileAtDestination(const char* filename)
+{
+ GUniquePtr<char> path(g_build_filename(Test::dataDirectory(), filename, nullptr));
+ GRefPtr<GFile> file = adoptGRef(g_file_new_for_path(path.get()));
+ GUniqueOutPtr<GError> error;
+ g_file_create(file.get(), G_FILE_CREATE_NONE, nullptr, &error.outPtr());
+ g_assert(!error);
+ g_assert(g_file_query_exists(file.get(), nullptr));
+}
+
+static void testDownloadOverwriteDestinationAllowed(DownloadTest* test, gconstpointer)
+{
+ static const char* filename = "test.pdf";
+ createFileAtDestination(filename);
+
+ test->m_allowOverwrite = true;
+ GRefPtr<WebKitDownload> download = downloadLocalFileSuccessfully(test, filename);
+ test->checkDestinationAndDeleteFile(download.get(), filename);
}
class DownloadErrorTest: public DownloadTest {
public:
MAKE_GLIB_TEST_FIXTURE(DownloadErrorTest);
+ enum ExpectedError {
+ NetworkError,
+ DownloadCancelled,
+ InvalidDestination,
+ DestinationExists
+ };
+
DownloadErrorTest()
- : m_expectedError(WEBKIT_DOWNLOAD_ERROR_NETWORK)
+ : m_expectedError(NetworkError)
{
}
@@ -223,7 +272,7 @@ public:
void createdDestination(WebKitDownload* download, const char* destination)
{
- if (m_expectedError == WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER)
+ if (m_expectedError == DownloadCancelled)
webkit_download_cancel(download);
else
g_assert_not_reached();
@@ -231,25 +280,64 @@ public:
void failed(WebKitDownload* download, GError* error)
{
- g_assert(g_error_matches(error, WEBKIT_DOWNLOAD_ERROR, m_expectedError));
+ g_assert(g_error_matches(error, WEBKIT_DOWNLOAD_ERROR, expectedErrorToWebKitDownloadError(m_expectedError)));
DownloadTest::failed(download, error);
}
void decideDestination(WebKitDownload* download, const gchar* suggestedFilename)
{
- if (m_expectedError != WEBKIT_DOWNLOAD_ERROR_DESTINATION) {
+ if (m_expectedError != InvalidDestination) {
DownloadTest::decideDestination(download, suggestedFilename);
return;
}
webkit_download_set_destination(download, "file:///foo/bar");
}
- WebKitDownloadError m_expectedError;
+ static WebKitDownloadError expectedErrorToWebKitDownloadError(ExpectedError expected)
+ {
+ switch (expected) {
+ case NetworkError:
+ return WEBKIT_DOWNLOAD_ERROR_NETWORK;
+ case DownloadCancelled:
+ return WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER;
+ case InvalidDestination:
+ return WEBKIT_DOWNLOAD_ERROR_DESTINATION;
+ case DestinationExists:
+ return WEBKIT_DOWNLOAD_ERROR_DESTINATION;
+ default:
+ g_assert_not_reached();
+ }
+ }
+
+ ExpectedError m_expectedError;
};
+static void testDownloadOverwriteDestinationDisallowed(DownloadErrorTest* test, gconstpointer)
+{
+ static const char* filename = "test.pdf";
+ createFileAtDestination(filename);
+
+ test->m_expectedError = DownloadErrorTest::DestinationExists;
+ GUniquePtr<char> sourcePath(g_build_filename(Test::getResourcesDir().data(), filename, nullptr));
+ GRefPtr<GFile> source = adoptGRef(g_file_new_for_path(sourcePath.get()));
+ GUniquePtr<char> sourceURI(g_file_get_uri(source.get()));
+ GRefPtr<WebKitDownload> download = adoptGRef(test->downloadURIAndWaitUntilFinishes(sourceURI.get()));
+ g_assert(!webkit_download_get_web_view(download.get()));
+
+ Vector<DownloadTest::DownloadEvent>& events = test->m_downloadEvents;
+ g_assert_cmpint(events.size(), ==, 4);
+ g_assert_cmpint(events[0], ==, DownloadTest::Started);
+ g_assert_cmpint(events[1], ==, DownloadTest::ReceivedResponse);
+ g_assert_cmpint(events[2], ==, DownloadTest::Failed);
+ g_assert_cmpint(events[3], ==, DownloadTest::Finished);
+ g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), ==, 0);
+
+ test->checkDestinationAndDeleteFile(download.get(), filename);
+}
+
static void testDownloadLocalFileError(DownloadErrorTest* test, gconstpointer)
{
- test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_NETWORK;
+ test->m_expectedError = DownloadErrorTest::NetworkError;
GRefPtr<WebKitDownload> download = adoptGRef(test->downloadURIAndWaitUntilFinishes("file:///foo/bar"));
g_assert(!webkit_download_get_web_view(download.get()));
@@ -261,8 +349,8 @@ static void testDownloadLocalFileError(DownloadErrorTest* test, gconstpointer)
events.clear();
g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1);
- test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_DESTINATION;
- GUniquePtr<char> path(g_build_filename(Test::getWebKit1TestResoucesDir().data(), "test.pdf", NULL));
+ test->m_expectedError = DownloadErrorTest::InvalidDestination;
+ GUniquePtr<char> path(g_build_filename(Test::getResourcesDir().data(), "test.pdf", nullptr));
GRefPtr<GFile> file = adoptGRef(g_file_new_for_path(path.get()));
GUniquePtr<char> uri(g_file_get_uri(file.get()));
download = adoptGRef(test->downloadURIAndWaitUntilFinishes(uri.get()));
@@ -277,7 +365,7 @@ static void testDownloadLocalFileError(DownloadErrorTest* test, gconstpointer)
g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1);
test->checkDestinationAndDeleteFile(download.get(), "bar");
- test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER;
+ test->m_expectedError = DownloadErrorTest::DownloadCancelled;
download = adoptGRef(test->downloadURIAndWaitUntilFinishes(uri.get()));
g_assert(!webkit_download_get_web_view(download.get()));
@@ -329,7 +417,7 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char*
return;
}
- GUniquePtr<char> filePath(g_build_filename(Test::getWebKit1TestResoucesDir().data(), path, NULL));
+ GUniquePtr<char> filePath(g_build_filename(Test::getResourcesDir().data(), path, nullptr));
char* contents;
gsize contentsLength;
if (!g_file_get_contents(filePath.get(), &contents, &contentsLength, 0)) {
@@ -369,7 +457,7 @@ static void testDownloadRemoteFile(DownloadTest* test, gconstpointer)
static void testDownloadRemoteFileError(DownloadErrorTest* test, gconstpointer)
{
- test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_NETWORK;
+ test->m_expectedError = DownloadErrorTest::NetworkError;
GRefPtr<WebKitDownload> download = adoptGRef(test->downloadURIAndWaitUntilFinishes(kServer->getURIForPath("/foo")));
g_assert(!webkit_download_get_web_view(download.get()));
@@ -384,7 +472,7 @@ static void testDownloadRemoteFileError(DownloadErrorTest* test, gconstpointer)
g_assert_cmpuint(webkit_uri_response_get_status_code(response), ==, 404);
g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1);
- test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_DESTINATION;
+ test->m_expectedError = DownloadErrorTest::InvalidDestination;
download = adoptGRef(test->downloadURIAndWaitUntilFinishes(kServer->getURIForPath("/test.pdf")));
g_assert(!webkit_download_get_web_view(download.get()));
@@ -397,7 +485,7 @@ static void testDownloadRemoteFileError(DownloadErrorTest* test, gconstpointer)
g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1);
test->checkDestinationAndDeleteFile(download.get(), "bar");
- test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER;
+ test->m_expectedError = DownloadErrorTest::DownloadCancelled;
download = adoptGRef(test->downloadURIAndWaitUntilFinishes(kServer->getURIForPath("/cancel-after-destination")));
g_assert(!webkit_download_get_web_view(download.get()));
@@ -444,7 +532,7 @@ public:
static gboolean downloadDecideDestinationCallback(WebKitDownload* download, const gchar* suggestedFilename, WebViewDownloadTest* test)
{
- GUniquePtr<char> destination(g_build_filename(kTempDirectory, suggestedFilename, NULL));
+ GUniquePtr<char> destination(g_build_filename(Test::dataDirectory(), suggestedFilename, nullptr));
GUniquePtr<char> destinationURI(g_filename_to_uri(destination.get(), 0, 0));
webkit_download_set_destination(download, destinationURI.get());
return TRUE;
@@ -529,10 +617,9 @@ void beforeAll()
kServer = new WebKitTestServer();
kServer->run(serverCallback);
- kTempDirectory = g_dir_make_tmp("WebKit2Tests-XXXXXX", 0);
- g_assert(kTempDirectory);
-
DownloadTest::add("Downloads", "local-file", testDownloadLocalFile);
+ DownloadTest::add("Downloads", "overwrite-destination-allowed", testDownloadOverwriteDestinationAllowed);
+ DownloadErrorTest::add("Downloads", "overwrite-destination-disallowed", testDownloadOverwriteDestinationDisallowed);
DownloadErrorTest::add("Downloads", "local-file-error", testDownloadLocalFileError);
DownloadTest::add("Downloads", "remote-file", testDownloadRemoteFile);
DownloadErrorTest::add("Downloads", "remote-file-error", testDownloadRemoteFileError);
@@ -543,5 +630,4 @@ void beforeAll()
void afterAll()
{
delete kServer;
- g_rmdir(kTempDirectory);
}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testapplicationcache.c b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestEditor.cpp
index 718f401a7..fc429d4c3 100644
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testapplicationcache.c
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestEditor.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Lukasz Slachciak
+ * Copyright (C) 2015 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -18,32 +18,25 @@
*/
#include "config.h"
-#include <glib.h>
-#include <glib/gprintf.h>
+
+#include "WebViewTest.h"
#include <gtk/gtk.h>
-#include <webkit/webkit.h>
+#include <webkit2/webkit2.h>
-static void test_application_cache_maximum_size()
+static void testWebKitWebEditorSelectionChanged(WebViewTest* test, gconstpointer)
{
- unsigned long long maxSize = 8192;
- webkit_application_cache_set_maximum_size(maxSize);
-
- // Creating a WebView - make sure that it didn't change anything
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- g_object_unref(webView);
+ static const gchar* testHTML = "<html><body>All work and no play make Jack a dull boy.</body></html>";
+ test->loadHtml(testHTML, nullptr);
+ test->waitUntilLoadFinished();
- g_assert(maxSize == webkit_application_cache_get_maximum_size());
+ g_assert(test->runWebProcessTest("WebKitWebEditor", "selection-changed"));
}
-int main(int argc, char** argv)
+void beforeAll()
{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/application_cache/maximum_size",
- test_application_cache_maximum_size);
-
- return g_test_run();
+ WebViewTest::add("WebKitWebEditor", "selection-changed", testWebKitWebEditorSelectionChanged);
}
+void afterAll()
+{
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestFrame.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestFrame.cpp
index 69b5082cd..9145ab813 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestFrame.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestFrame.cpp
@@ -49,8 +49,6 @@ static void testWebKitFrameJavaScriptContext(WebViewTest* test, gconstpointer)
void beforeAll()
{
- webkit_web_context_set_web_extensions_directory(webkit_web_context_get_default(), WEBKIT_TEST_WEB_EXTENSIONS_DIR);
-
WebViewTest::add("WebKitFrame", "main-frame", testWebKitFrameMainFrame);
WebViewTest::add("WebKitFrame", "uri", testWebKitFrameURI);
WebViewTest::add("WebKitFrame", "javascript-context", testWebKitFrameJavaScriptContext);
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestInspector.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestInspector.cpp
index 1f0430389..3d993e24f 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestInspector.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestInspector.cpp
@@ -21,7 +21,7 @@
#include "WebViewTest.h"
#include <wtf/Vector.h>
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
class InspectorTest: public WebViewTest {
public:
@@ -125,10 +125,22 @@ public:
g_main_loop_run(m_mainLoop);
}
+ static void canAttachChanged(InspectorTest* test)
+ {
+ g_main_loop_quit(test->m_mainLoop);
+ }
+
void resizeViewAndAttach()
{
// Resize the view to make room for the inspector.
- resizeView(gMinimumAttachedInspectorWidth, (gMinimumAttachedInspectorHeight + 1) * 4 / 3);
+ if (!webkit_web_inspector_get_can_attach(m_inspector)) {
+ unsigned long handler = g_signal_connect_swapped(m_inspector, "notify::can-attach", G_CALLBACK(canAttachChanged), this);
+ resizeView(gMinimumAttachedInspectorWidth, (gMinimumAttachedInspectorHeight + 1) * 4 / 3);
+ g_main_loop_run(m_mainLoop);
+ g_signal_handler_disconnect(m_inspector, handler);
+ }
+
+ g_assert(webkit_web_inspector_get_can_attach(m_inspector));
webkit_web_inspector_attach(m_inspector);
}
@@ -167,6 +179,7 @@ static void testInspectorDefault(InspectorTest* test, gconstpointer)
test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(inspectorView.get()));
g_assert(!webkit_web_inspector_is_attached(test->m_inspector));
g_assert_cmpuint(webkit_web_inspector_get_attached_height(test->m_inspector), ==, 0);
+ g_assert(!webkit_web_inspector_get_can_attach(test->m_inspector));
Vector<InspectorTest::InspectorEvents>& events = test->m_events;
g_assert_cmpint(events.size(), ==, 1);
g_assert_cmpint(events[0], ==, InspectorTest::OpenWindow);
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestInspectorServer.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestInspectorServer.cpp
index 58fefea5e..bbdd104c5 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestInspectorServer.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestInspectorServer.cpp
@@ -25,7 +25,7 @@
#include "config.h"
#include "WebViewTest.h"
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
#include <wtf/text/WTFString.h>
// Name of the test server application creating the webView object.
@@ -237,12 +237,10 @@ static void openRemoteDebuggingSession(InspectorServerTest* test, gconstpointer)
test->loadURI(resolvedURL.utf8().data());
test->waitUntilLoadFinished();
- javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.document.getElementsByTagName('li')[0].title", &error.outPtr());
- g_assert(javascriptResult);
- g_assert(!error.get());
-
- GUniquePtr<char> title(WebViewTest::javascriptResultToCString(javascriptResult));
- g_assert_cmpstr(title.get(), ==, "http://127.0.0.1:2999/");
+ const char* title = webkit_web_view_get_title(test->m_webView);
+ if (!title || !*title)
+ test->waitUntilTitleChanged();
+ g_assert_cmpstr(webkit_web_view_get_title(test->m_webView), ==, "127.0.0.1");
}
static void sendIncompleteRequest(InspectorServerTest* test, gconstpointer)
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestLoaderClient.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestLoaderClient.cpp
index 331915e00..227b389ff 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestLoaderClient.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestLoaderClient.cpp
@@ -82,6 +82,13 @@ static void testLoadAlternateHTML(LoadTrackingTest* test, gconstpointer)
assertNormalLoadHappened(test->m_loadEvents);
}
+static void testLoadAlternateHTMLForLocalPage(LoadTrackingTest* test, gconstpointer)
+{
+ test->loadAlternateHTML("<html><body>Alternate page</body></html>", "file:///not/actually/loaded.html", 0);
+ test->waitUntilLoadFinished();
+ assertNormalLoadHappened(test->m_loadEvents);
+}
+
static void testLoadPlainText(LoadTrackingTest* test, gconstpointer)
{
test->loadPlainText("Hello WebKit-GTK+");
@@ -89,6 +96,18 @@ static void testLoadPlainText(LoadTrackingTest* test, gconstpointer)
assertNormalLoadHappened(test->m_loadEvents);
}
+static void testLoadBytes(LoadTrackingTest* test, gconstpointer)
+{
+ GUniquePtr<char> filePath(g_build_filename(Test::getResourcesDir().data(), "blank.ico", nullptr));
+ char* contents;
+ gsize contentsLength;
+ g_file_get_contents(filePath.get(), &contents, &contentsLength, nullptr);
+ GRefPtr<GBytes> bytes = adoptGRef(g_bytes_new_take(contents, contentsLength));
+ test->loadBytes(bytes.get(), "image/vnd.microsoft.icon", nullptr, nullptr);
+ test->waitUntilLoadFinished();
+ assertNormalLoadHappened(test->m_loadEvents);
+}
+
static void testLoadRequest(LoadTrackingTest* test, gconstpointer)
{
GRefPtr<WebKitURIRequest> request(webkit_uri_request_new(kServer->getURIForPath("/normal").data()));
@@ -97,6 +116,14 @@ static void testLoadRequest(LoadTrackingTest* test, gconstpointer)
assertNormalLoadHappened(test->m_loadEvents);
}
+static void testLoadFromGResource(LoadTrackingTest* test, gconstpointer)
+{
+ GRefPtr<WebKitURIRequest> request(webkit_uri_request_new("resource:///org/webkit/webkit2gtk/tests/boring.html"));
+ test->loadRequest(request.get());
+ test->waitUntilLoadFinished();
+ assertNormalLoadHappened(test->m_loadEvents);
+}
+
class LoadStopTrackingTest : public LoadTrackingTest {
public:
MAKE_GLIB_TEST_FIXTURE(LoadStopTrackingTest);
@@ -303,7 +330,8 @@ public:
WebPageURITest()
{
- GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy("org.webkit.gtk.WebExtensionTest",
+ GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
+ GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
"/org/webkit/gtk/WebExtensionTest", "org.webkit.gtk.WebExtensionTest", m_mainLoop));
m_uriChangedSignalID = g_dbus_connection_signal_subscribe(
g_dbus_proxy_get_connection(proxy.get()),
@@ -384,6 +412,53 @@ static void testURIRequestHTTPHeaders(WebViewTest* test, gconstpointer)
g_assert(!strncmp(mainResourceData, "1", mainResourceDataSize));
}
+static void testURIRequestHTTPMethod(WebViewTest* test, gconstpointer)
+{
+ GRefPtr<WebKitURIRequest> uriRequest = adoptGRef(webkit_uri_request_new("file:///foo/bar"));
+ g_assert(uriRequest.get());
+ g_assert_cmpstr(webkit_uri_request_get_uri(uriRequest.get()), ==, "file:///foo/bar");
+ g_assert(!webkit_uri_request_get_http_method(uriRequest.get()));
+
+ webkit_uri_request_set_uri(uriRequest.get(), kServer->getURIForPath("/http-get-method").data());
+ test->loadRequest(uriRequest.get());
+ test->waitUntilLoadFinished();
+
+ test->runJavaScriptAndWaitUntilFinished("xhr = new XMLHttpRequest; xhr.open('POST', '/http-post-method', false); xhr.send();", nullptr);
+}
+
+static void testURIResponseHTTPHeaders(WebViewTest* test, gconstpointer)
+{
+ test->loadHtml("<html><body>No HTTP headers</body></html>", "file:///");
+ test->waitUntilLoadFinished();
+ WebKitWebResource* resource = webkit_web_view_get_main_resource(test->m_webView);
+ g_assert(WEBKIT_IS_WEB_RESOURCE(resource));
+ WebKitURIResponse* response = webkit_web_resource_get_response(resource);
+ g_assert(WEBKIT_IS_URI_RESPONSE(response));
+ g_assert(!webkit_uri_response_get_http_headers(response));
+
+ test->loadURI(kServer->getURIForPath("/headers").data());
+ test->waitUntilLoadFinished();
+ resource = webkit_web_view_get_main_resource(test->m_webView);
+ g_assert(WEBKIT_IS_WEB_RESOURCE(resource));
+ response = webkit_web_resource_get_response(resource);
+ g_assert(WEBKIT_IS_URI_RESPONSE(response));
+ SoupMessageHeaders* headers = webkit_uri_response_get_http_headers(response);
+ g_assert(headers);
+ g_assert_cmpstr(soup_message_headers_get_one(headers, "Foo"), ==, "bar");
+}
+
+static void testRedirectToDataURI(WebViewTest* test, gconstpointer)
+{
+ test->loadURI(kServer->getURIForPath("/redirect-to-data").data());
+ test->waitUntilLoadFinished();
+
+ static const char* expectedData = "data-uri";
+ size_t mainResourceDataSize = 0;
+ const char* mainResourceData = test->mainResourceData(mainResourceDataSize);
+ g_assert_cmpint(mainResourceDataSize, ==, strlen(expectedData));
+ g_assert(!strncmp(mainResourceData, expectedData, mainResourceDataSize));
+}
+
static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer)
{
static const char* responseString = "<html><body>Testing!Testing!Testing!Testing!Testing!Testing!Testing!"
@@ -402,7 +477,7 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char*
soup_message_set_status(message, SOUP_STATUS_OK);
- if (g_str_has_prefix(path, "/normal"))
+ if (g_str_has_prefix(path, "/normal") || g_str_has_prefix(path, "/http-get-method"))
soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, responseString, strlen(responseString));
else if (g_str_equal(path, "/error"))
soup_message_set_status(message, SOUP_STATUS_CANT_CONNECT);
@@ -421,6 +496,12 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char*
else
soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, kDNTHeaderNotPresent, strlen(kDNTHeaderNotPresent));
soup_message_set_status(message, SOUP_STATUS_OK);
+ } else if (g_str_equal(path, "/headers")) {
+ soup_message_headers_append(message->response_headers, "Foo", "bar");
+ soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, responseString, strlen(responseString));
+ } else if (g_str_equal(path, "/redirect-to-data")) {
+ soup_message_set_status(message, SOUP_STATUS_MOVED_PERMANENTLY);
+ soup_message_headers_append(message->response_headers, "Location", "data:text/plain;charset=utf-8,data-uri");
} else
soup_message_set_status(message, SOUP_STATUS_NOT_FOUND);
@@ -429,7 +510,6 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char*
void beforeAll()
{
- webkit_web_context_set_web_extensions_directory(webkit_web_context_get_default(), WEBKIT_TEST_WEB_EXTENSIONS_DIR);
bus = new WebKitTestBus();
if (!bus->run())
return;
@@ -441,8 +521,11 @@ void beforeAll()
LoadTrackingTest::add("WebKitWebView", "loading-error", testLoadingError);
LoadTrackingTest::add("WebKitWebView", "load-html", testLoadHtml);
LoadTrackingTest::add("WebKitWebView", "load-alternate-html", testLoadAlternateHTML);
+ LoadTrackingTest::add("WebKitWebView", "load-alternate-html-for-local-page", testLoadAlternateHTMLForLocalPage);
LoadTrackingTest::add("WebKitWebView", "load-plain-text", testLoadPlainText);
+ LoadTrackingTest::add("WebKitWebView", "load-bytes", testLoadBytes);
LoadTrackingTest::add("WebKitWebView", "load-request", testLoadRequest);
+ LoadTrackingTest::add("WebKitWebView", "load-gresource", testLoadFromGResource);
LoadStopTrackingTest::add("WebKitWebView", "stop-loading", testLoadCancelled);
LoadTrackingTest::add("WebKitWebView", "title", testWebViewTitle);
LoadTrackingTest::add("WebKitWebView", "progress", testLoadProgress);
@@ -456,6 +539,9 @@ void beforeAll()
ViewIsLoadingTest::add("WebKitWebView", "is-loading", testWebViewIsLoading);
WebPageURITest::add("WebKitWebPage", "get-uri", testWebPageURI);
WebViewTest::add("WebKitURIRequest", "http-headers", testURIRequestHTTPHeaders);
+ WebViewTest::add("WebKitURIRequest", "http-method", testURIRequestHTTPMethod);
+ WebViewTest::add("WebKitURIResponse", "http-headers", testURIResponseHTTPHeaders);
+ WebViewTest::add("WebKitWebPage", "redirect-to-data-uri", testRedirectToDataURI);
}
void afterAll()
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestMultiprocess.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestMultiprocess.cpp
index f48b6a3b6..020ad3529 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestMultiprocess.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestMultiprocess.cpp
@@ -26,8 +26,6 @@
#include <wtf/Vector.h>
static const unsigned numViews = 2;
-static guint32 nextInitializationId = 1;
-static unsigned initializeWebExtensionsSignalCount;
static WebKitTestBus* bus;
class MultiprocessTest: public Test {
@@ -36,8 +34,18 @@ public:
MultiprocessTest()
: m_mainLoop(g_main_loop_new(nullptr, TRUE))
+ , m_initializeWebExtensionsSignalCount(0)
, m_webViewBusNames(numViews)
- , m_webViews(numViews) { }
+ , m_webViews(numViews)
+ {
+ webkit_web_context_set_process_model(m_webContext.get(), WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES);
+ }
+
+ void initializeWebExtensions() override
+ {
+ Test::initializeWebExtensions();
+ m_initializeWebExtensionsSignalCount++;
+ }
static void loadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent, MultiprocessTest* test)
{
@@ -51,11 +59,11 @@ public:
{
g_assert_cmpuint(index, <, numViews);
- m_webViewBusNames[index] = GUniquePtr<char>(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", nextInitializationId));
-
- m_webViews[index] = WEBKIT_WEB_VIEW(webkit_web_view_new());
+ m_webViews[index] = WEBKIT_WEB_VIEW(webkit_web_view_new_with_context(m_webContext.get()));
assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_webViews[index].get()));
+ m_webViewBusNames[index] = GUniquePtr<char>(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
+
webkit_web_view_load_html(m_webViews[index].get(), "<html></html>", nullptr);
g_signal_connect(m_webViews[index].get(), "load-changed", G_CALLBACK(loadChanged), this);
g_main_loop_run(m_mainLoop);
@@ -88,8 +96,6 @@ public:
void destroyWebViewAndWaitUntilWebProcessFinishes(unsigned index)
{
- // FIXME: This test is disabled because the web processed don't actually die
- // due to bug https://bugs.webkit.org/show_bug.cgi?id=129684.
g_assert_cmpuint(index, <, numViews);
unsigned watcherID = g_bus_watch_name_on_connection(bus->connection(), m_webViewBusNames[index].get(), G_BUS_NAME_WATCHER_FLAGS_NONE,
@@ -100,6 +106,7 @@ public:
}
GMainLoop* m_mainLoop;
+ unsigned m_initializeWebExtensionsSignalCount;
Vector<GUniquePtr<char>, numViews> m_webViewBusNames;
Vector<GRefPtr<WebKitWebView>, numViews> m_webViews;
};
@@ -118,7 +125,7 @@ static void testProcessPerWebView(MultiprocessTest* test, gconstpointer)
g_assert(test->m_webViewBusNames[i]);
}
- g_assert_cmpuint(initializeWebExtensionsSignalCount, ==, numViews);
+ g_assert_cmpuint(test->m_initializeWebExtensionsSignalCount, ==, numViews);
g_assert_cmpstr(test->m_webViewBusNames[0].get(), !=, test->m_webViewBusNames[1].get());
g_assert_cmpuint(test->webProcessPid(0), !=, test->webProcessPid(1));
@@ -130,7 +137,7 @@ static void testProcessPerWebView(MultiprocessTest* test, gconstpointer)
}
}
-class UIClientMultiprocessTest: public WebViewTest {
+class UIClientMultiprocessTest: public Test {
public:
MAKE_GLIB_TEST_FIXTURE(UIClientMultiprocessTest);
@@ -140,7 +147,7 @@ public:
Close
};
- static GtkWidget* viewCreateCallback(WebKitWebView* webView, UIClientMultiprocessTest* test)
+ static GtkWidget* viewCreateCallback(WebKitWebView* webView, WebKitNavigationAction*, UIClientMultiprocessTest* test)
{
return test->viewCreate(webView);
}
@@ -156,14 +163,26 @@ public:
}
UIClientMultiprocessTest()
+ : m_mainLoop(g_main_loop_new(nullptr, TRUE))
+ , m_initializeWebExtensionsSignalCount(0)
{
+ webkit_web_context_set_process_model(m_webContext.get(), WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES);
+ m_webView = WEBKIT_WEB_VIEW(g_object_ref_sink(webkit_web_view_new_with_context(m_webContext.get())));
webkit_settings_set_javascript_can_open_windows_automatically(webkit_web_view_get_settings(m_webView), TRUE);
+
g_signal_connect(m_webView, "create", G_CALLBACK(viewCreateCallback), this);
}
~UIClientMultiprocessTest()
{
g_signal_handlers_disconnect_matched(m_webView, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
+ gtk_widget_destroy(GTK_WIDGET(m_webView));
+ }
+
+ void initializeWebExtensions() override
+ {
+ Test::initializeWebExtensions();
+ m_initializeWebExtensionsSignalCount++;
}
GtkWidget* viewCreate(WebKitWebView* webView)
@@ -201,16 +220,15 @@ public:
g_main_loop_run(m_mainLoop);
}
+ WebKitWebView* m_webView;
+ GMainLoop* m_mainLoop;
+ unsigned m_initializeWebExtensionsSignalCount;
Vector<WebViewEvents> m_webViewEvents;
};
static void testMultiprocessWebViewCreateReadyClose(UIClientMultiprocessTest* test, gconstpointer)
{
- // At this point the web process of the current view has already been created.
- // We save it here to check that after window.open() the number of processes
- // is the same.
- guint32 processCountBefore = nextInitializationId - 1;
- test->loadHtml("<html><body onLoad=\"window.open().close();\"></html>", nullptr);
+ webkit_web_view_load_html(test->m_webView, "<html><body onLoad=\"window.open().close();\"></html>", nullptr);
test->waitUntilNewWebViewClose();
Vector<UIClientMultiprocessTest::WebViewEvents>& events = test->m_webViewEvents;
@@ -219,23 +237,27 @@ static void testMultiprocessWebViewCreateReadyClose(UIClientMultiprocessTest* te
g_assert_cmpint(events[1], ==, UIClientMultiprocessTest::ReadyToShow);
g_assert_cmpint(events[2], ==, UIClientMultiprocessTest::Close);
- guint32 processesCountAfter = nextInitializationId - 1;
- g_assert_cmpuint(processesCountAfter, ==, processCountBefore);
+ g_assert_cmpuint(test->m_initializeWebExtensionsSignalCount, ==, 1);
}
-static void initializeWebExtensions(WebKitWebContext* context, gpointer)
+static void testWebProcessLimit(MultiprocessTest* test, gconstpointer)
{
- initializeWebExtensionsSignalCount++;
- webkit_web_context_set_web_extensions_directory(context, WEBKIT_TEST_WEB_EXTENSIONS_DIR);
- webkit_web_context_set_web_extensions_initialization_user_data(context,
- g_variant_new_uint32(nextInitializationId++));
+ g_assert_cmpuint(webkit_web_context_get_web_process_count_limit(test->m_webContext.get()), ==, 0);
+
+ webkit_web_context_set_web_process_count_limit(test->m_webContext.get(), 1);
+ g_assert_cmpuint(webkit_web_context_get_web_process_count_limit(test->m_webContext.get()), ==, 1);
+
+ // Create two web views but there should be only one web process.
+ for (unsigned i = 0; i < numViews; i++) {
+ test->loadWebViewAndWaitUntilLoaded(i);
+ g_assert(WEBKIT_IS_WEB_VIEW(test->m_webViews[i].get()));
+ }
+
+ g_assert_cmpuint(test->m_initializeWebExtensionsSignalCount, ==, 1);
}
void beforeAll()
{
- g_signal_connect(webkit_web_context_get_default(),
- "initialize-web-extensions", G_CALLBACK(initializeWebExtensions), nullptr);
-
// Check that default setting is the one stated in the documentation
g_assert_cmpuint(webkit_web_context_get_process_model(webkit_web_context_get_default()),
==, WEBKIT_PROCESS_MODEL_SHARED_SECONDARY_PROCESS);
@@ -253,11 +275,10 @@ void beforeAll()
MultiprocessTest::add("WebKitWebContext", "process-per-web-view", testProcessPerWebView);
UIClientMultiprocessTest::add("WebKitWebView", "multiprocess-create-ready-close", testMultiprocessWebViewCreateReadyClose);
+ MultiprocessTest::add("WebKitWebContext", "web-process-limit", testWebProcessLimit);
}
void afterAll()
{
delete bus;
- g_signal_handlers_disconnect_by_func(webkit_web_context_get_default(),
- reinterpret_cast<void*>(initializeWebExtensions), nullptr);
}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestPrinting.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestPrinting.cpp
index 99efa7cfb..c13185427 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestPrinting.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestPrinting.cpp
@@ -20,14 +20,12 @@
#include "config.h"
#include "WebViewTest.h"
#include <glib/gstdio.h>
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
#ifdef HAVE_GTK_UNIX_PRINTING
#include <gtk/gtkunixprint.h>
#endif
-static char* kTempDirectory;
-
static void testPrintOperationPrintSettings(WebViewTest* test, gconstpointer)
{
GRefPtr<WebKitPrintOperation> printOperation = adoptGRef(webkit_print_operation_new(test->m_webView));
@@ -134,7 +132,7 @@ static void testPrintOperationPrint(PrintTest* test, gconstpointer)
return;
}
- GUniquePtr<char> outputFilename(g_build_filename(kTempDirectory, "webkit-print.pdf", NULL));
+ GUniquePtr<char> outputFilename(g_build_filename(Test::dataDirectory(), "webkit-print.pdf", nullptr));
GRefPtr<GFile> outputFile = adoptGRef(g_file_new_for_path(outputFilename.get()));
GUniquePtr<char> outputURI(g_file_get_uri(outputFile.get()));
@@ -194,7 +192,7 @@ class CloseAfterPrintTest: public WebViewTest {
public:
MAKE_GLIB_TEST_FIXTURE(CloseAfterPrintTest);
- static GtkWidget* webViewCreate(WebKitWebView* webView, CloseAfterPrintTest* test)
+ static GtkWidget* webViewCreate(WebKitWebView* webView, WebKitNavigationAction*, CloseAfterPrintTest* test)
{
return test->createWebView();
}
@@ -228,7 +226,7 @@ public:
GtkWidget* createWebView()
{
- GtkWidget* newWebView = webkit_web_view_new();
+ GtkWidget* newWebView = webkit_web_view_new_with_context(m_webContext.get());
g_object_ref_sink(newWebView);
assertObjectIsDeletedWhenTestFinishes(G_OBJECT(newWebView));
@@ -247,7 +245,7 @@ public:
return;
}
- GUniquePtr<char> outputFilename(g_build_filename(kTempDirectory, "webkit-close-after-print.pdf", NULL));
+ GUniquePtr<char> outputFilename(g_build_filename(Test::dataDirectory(), "webkit-close-after-print.pdf", nullptr));
m_outputFile = adoptGRef(g_file_new_for_path(outputFilename.get()));
GUniquePtr<char> outputURI(g_file_get_uri(m_outputFile.get()));
@@ -292,9 +290,6 @@ static void testPrintOperationCloseAfterPrint(CloseAfterPrintTest* test, gconstp
void beforeAll()
{
- kTempDirectory = g_dir_make_tmp("WebKit2Tests-XXXXXX", 0);
- g_assert(kTempDirectory);
-
WebViewTest::add("WebKitPrintOperation", "printing-settings", testPrintOperationPrintSettings);
WebViewTest::add("WebKitWebView", "print", testWebViewPrint);
#ifdef HAVE_GTK_UNIX_PRINTING
@@ -306,5 +301,4 @@ void beforeAll()
void afterAll()
{
- g_rmdir(kTempDirectory);
}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestResources.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestResources.cpp
index 4d97846a2..1510e5d49 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestResources.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestResources.cpp
@@ -22,7 +22,8 @@
#include "WebKitTestServer.h"
#include "WebViewTest.h"
#include <wtf/Vector.h>
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GMutexLocker.h>
+#include <wtf/glib/GRefPtr.h>
static WebKitTestServer* kServer;
@@ -189,6 +190,13 @@ public:
} else if (uri == kServer->getURIForPath("/javascript.js")) {
g_assert_cmpint(m_resourceDataSize, ==, strlen(kJavascript));
g_assert(!strncmp(m_resourceData.get(), kJavascript, m_resourceDataSize));
+ } else if (uri == kServer->getURIForPath("/blank.ico")) {
+ GUniquePtr<char> filePath(g_build_filename(Test::getResourcesDir().data(), "blank.ico", nullptr));
+ GUniqueOutPtr<char> contents;
+ gsize contentsLength;
+ g_file_get_contents(filePath.get(), &contents.outPtr(), &contentsLength, nullptr);
+ g_assert_cmpint(m_resourceDataSize, ==, contentsLength);
+ g_assert(!memcmp(m_resourceData.get(), contents.get(), contentsLength));
} else
g_assert_not_reached();
m_resourceData.reset();
@@ -417,7 +425,7 @@ static void testWebResourceMimeType(SingleResourceLoadTest* test, gconstpointer)
test->loadURI(kServer->getURIForPath("/image.html").data());
response = test->waitUntilResourceLoadFinishedAndReturnURIResponse();
- g_assert_cmpstr(webkit_uri_response_get_mime_type(response), ==, "image/vnd.microsoft.icon");
+ g_assert_cmpstr(webkit_uri_response_get_mime_type(response), ==, "image/x-icon");
test->loadURI(kServer->getURIForPath("/redirected-css.html").data());
response = test->waitUntilResourceLoadFinishedAndReturnURIResponse();
@@ -517,9 +525,7 @@ static void testWebResourceActiveURI(ResourceURITrackingTest* test, gconstpointe
static void testWebResourceGetData(ResourcesTest* test, gconstpointer)
{
test->loadURI(kServer->getURIForPath("/").data());
- // FIXME: this should be 4 instead of 3, but we don't get the css image resource
- // due to bug https://bugs.webkit.org/show_bug.cgi?id=78510.
- test->waitUntilResourcesLoaded(3);
+ test->waitUntilResourcesLoaded(4);
WebKitWebResource* resource = webkit_web_view_get_main_resource(test->m_webView);
g_assert(resource);
@@ -667,6 +673,66 @@ static void testWebResourceSendRequest(SendRequestTest* test, gconstpointer)
events.clear();
}
+static GMutex s_serverMutex;
+static const unsigned s_maxConnectionsPerHost = 6;
+
+class SyncRequestOnMaxConnsTest: public ResourcesTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(SyncRequestOnMaxConnsTest);
+
+ void resourceLoadStarted(WebKitWebResource*, WebKitURIRequest*) override
+ {
+ if (!m_resourcesToStartPending)
+ return;
+
+ if (!--m_resourcesToStartPending)
+ g_main_loop_quit(m_mainLoop);
+ }
+
+ void waitUntilResourcesStarted(unsigned requestCount)
+ {
+ m_resourcesToStartPending = requestCount;
+ g_main_loop_run(m_mainLoop);
+ }
+
+ unsigned m_resourcesToStartPending;
+};
+
+static void testWebViewSyncRequestOnMaxConns(SyncRequestOnMaxConnsTest* test, gconstpointer)
+{
+ WTF::GMutexLocker<GMutex> lock(s_serverMutex);
+ test->loadURI(kServer->getURIForPath("/sync-request-on-max-conns-0").data());
+ test->waitUntilResourcesStarted(s_maxConnectionsPerHost + 1); // s_maxConnectionsPerHost resource + main resource.
+
+ for (unsigned i = 0; i < 2; ++i) {
+ GUniquePtr<char> xhr(g_strdup_printf("xhr = new XMLHttpRequest; xhr.open('GET', '/sync-request-on-max-conns-xhr%u', false); xhr.send();", i));
+ webkit_web_view_run_javascript(test->m_webView, xhr.get(), nullptr, nullptr, nullptr);
+ }
+
+ // By default sync XHRs have a 10 seconds timeout, we don't want to wait all that so use our own timeout.
+ guint timeoutSourceID = g_timeout_add(1000, [] (gpointer) -> gboolean {
+ g_assert_not_reached();
+ return G_SOURCE_REMOVE;
+ }, nullptr);
+
+ struct UnlockServerSourceContext {
+ WTF::GMutexLocker<GMutex>& lock;
+ guint unlockServerSourceID;
+ } context = {
+ lock,
+ g_idle_add_full(G_PRIORITY_DEFAULT, [](gpointer userData) -> gboolean {
+ auto& context = *static_cast<UnlockServerSourceContext*>(userData);
+ context.unlockServerSourceID = 0;
+ context.lock.unlock();
+ return G_SOURCE_REMOVE;
+ }, &context, nullptr)
+ };
+ test->waitUntilResourcesLoaded(s_maxConnectionsPerHost + 3); // s_maxConnectionsPerHost resource + main resource + 2 XHR.
+ g_source_remove(timeoutSourceID);
+ if (context.unlockServerSourceID)
+ g_source_remove(context.unlockServerSourceID);
+}
+
static void addCacheHTTPHeadersToResponse(SoupMessage* message)
{
// The actual date doesn't really matter.
@@ -734,7 +800,7 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char*
static const char* javascriptRelativeHTML = "<html><head><script language='javascript' src='/redirected-to-cancel.js'></script></head><body></body></html>";
soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, javascriptRelativeHTML, strlen(javascriptRelativeHTML));
} else if (g_str_equal(path, "/blank.ico")) {
- GUniquePtr<char> filePath(g_build_filename(Test::getWebKit1TestResoucesDir().data(), path, NULL));
+ GUniquePtr<char> filePath(g_build_filename(Test::getResourcesDir().data(), path, nullptr));
char* contents;
gsize contentsLength;
g_file_get_contents(filePath.get(), &contents, &contentsLength, 0);
@@ -760,18 +826,37 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char*
soup_message_headers_append(message->response_headers, "Location", "/cancel-this.js");
} else if (g_str_equal(path, "/invalid.css"))
soup_message_set_status(message, SOUP_STATUS_CANT_CONNECT);
- else
+ else if (g_str_has_prefix(path, "/sync-request-on-max-conns-")) {
+ char* contents;
+ gsize contentsLength;
+ if (g_str_equal(path, "/sync-request-on-max-conns-0")) {
+ GString* imagesHTML = g_string_new("<html><body>");
+ for (unsigned i = 1; i <= s_maxConnectionsPerHost; ++i)
+ g_string_append_printf(imagesHTML, "<img src='/sync-request-on-max-conns-%u'>", i);
+ g_string_append(imagesHTML, "</body></html>");
+
+ contentsLength = imagesHTML->len;
+ contents = g_string_free(imagesHTML, FALSE);
+ } else {
+ {
+ // We don't actually need to keep the mutex, so we release it as soon as we get it.
+ WTF::GMutexLocker<GMutex> lock(s_serverMutex);
+ }
+
+ GUniquePtr<char> filePath(g_build_filename(Test::getResourcesDir().data(), "blank.ico", nullptr));
+ g_file_get_contents(filePath.get(), &contents, &contentsLength, 0);
+ }
+ soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, contents, contentsLength);
+ } else
soup_message_set_status(message, SOUP_STATUS_NOT_FOUND);
soup_message_body_complete(message->response_body);
}
void beforeAll()
{
- kServer = new WebKitTestServer();
+ kServer = new WebKitTestServer(WebKitTestServer::ServerOptions::ServerRunInThread);
kServer->run(serverCallback);
- webkit_web_context_set_web_extensions_directory(webkit_web_context_get_default(), WEBKIT_TEST_WEB_EXTENSIONS_DIR);
-
ResourcesTest::add("WebKitWebView", "resources", testWebViewResources);
SingleResourceLoadTest::add("WebKitWebResource", "loading", testWebResourceLoading);
SingleResourceLoadTest::add("WebKitWebResource", "response", testWebResourceResponse);
@@ -781,6 +866,9 @@ void beforeAll()
ResourcesTest::add("WebKitWebResource", "get-data", testWebResourceGetData);
SingleResourceLoadTest::add("WebKitWebView", "history-cache", testWebViewResourcesHistoryCache);
SendRequestTest::add("WebKitWebPage", "send-request", testWebResourceSendRequest);
+#if SOUP_CHECK_VERSION(2, 49, 91)
+ SyncRequestOnMaxConnsTest::add("WebKitWebView", "sync-request-on-max-conns", testWebViewSyncRequestOnMaxConns);
+#endif
}
void afterAll()
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestSSL.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestSSL.cpp
index c3075b697..10c5e73b6 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestSSL.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestSSL.cpp
@@ -67,6 +67,10 @@ public:
static void testSSL(SSLTest* test, gconstpointer)
{
+ WebKitWebContext* context = webkit_web_view_get_context(test->m_webView);
+ WebKitTLSErrorsPolicy originalPolicy = webkit_web_context_get_tls_errors_policy(context);
+ webkit_web_context_set_tls_errors_policy(context, WEBKIT_TLS_ERRORS_POLICY_IGNORE);
+
test->loadURI(kHttpsServer->getURIForPath("/").data());
test->waitUntilLoadFinished();
g_assert(test->m_certificate);
@@ -80,6 +84,8 @@ static void testSSL(SSLTest* test, gconstpointer)
test->waitUntilLoadFinished();
g_assert(!test->m_certificate);
g_assert(!test->m_tlsErrors);
+
+ webkit_web_context_set_tls_errors_policy(context, originalPolicy);
}
class InsecureContentTest: public WebViewTest {
@@ -110,38 +116,64 @@ public:
static void testInsecureContent(InsecureContentTest* test, gconstpointer)
{
+ WebKitWebContext* context = webkit_web_view_get_context(test->m_webView);
+ WebKitTLSErrorsPolicy originalPolicy = webkit_web_context_get_tls_errors_policy(context);
+ webkit_web_context_set_tls_errors_policy(context, WEBKIT_TLS_ERRORS_POLICY_IGNORE);
+
test->loadURI(kHttpsServer->getURIForPath("/insecure-content/").data());
test->waitUntilLoadFinished();
- g_assert(test->m_insecureContentRun);
+ g_assert(!test->m_insecureContentRun);
+ // Images are currently always displayed, even bypassing mixed content settings. Check
+ // https://bugs.webkit.org/show_bug.cgi?id=142469
g_assert(test->m_insecureContentDisplayed);
+
+ webkit_web_context_set_tls_errors_policy(context, originalPolicy);
}
+static bool assertIfSSLRequestProcessed = false;
+
static void testTLSErrorsPolicy(SSLTest* test, gconstpointer)
{
WebKitWebContext* context = webkit_web_view_get_context(test->m_webView);
- // TLS errors are ignored by default.
- g_assert(webkit_web_context_get_tls_errors_policy(context) == WEBKIT_TLS_ERRORS_POLICY_IGNORE);
- test->loadURI(kHttpsServer->getURIForPath("/").data());
- test->waitUntilLoadFinished();
- g_assert(!test->m_loadFailed);
+ // TLS errors are treated as transport failures by default.
+ g_assert(webkit_web_context_get_tls_errors_policy(context) == WEBKIT_TLS_ERRORS_POLICY_FAIL);
- webkit_web_context_set_tls_errors_policy(context, WEBKIT_TLS_ERRORS_POLICY_FAIL);
+ assertIfSSLRequestProcessed = true;
test->loadURI(kHttpsServer->getURIForPath("/").data());
test->waitUntilLoadFinished();
g_assert(test->m_loadFailed);
g_assert(test->m_loadEvents.contains(LoadTrackingTest::ProvisionalLoadFailed));
g_assert(!test->m_loadEvents.contains(LoadTrackingTest::LoadCommitted));
+ assertIfSSLRequestProcessed = false;
+
+ webkit_web_context_set_tls_errors_policy(context, WEBKIT_TLS_ERRORS_POLICY_IGNORE);
+ g_assert(webkit_web_context_get_tls_errors_policy(context) == WEBKIT_TLS_ERRORS_POLICY_IGNORE);
+
+ test->m_loadFailed = false;
+ test->loadURI(kHttpsServer->getURIForPath("/").data());
+ test->waitUntilLoadFinished();
+ g_assert(!test->m_loadFailed);
+
+ webkit_web_context_set_tls_errors_policy(context, WEBKIT_TLS_ERRORS_POLICY_FAIL);
+ g_assert(webkit_web_context_get_tls_errors_policy(context) == WEBKIT_TLS_ERRORS_POLICY_FAIL);
}
static void testTLSErrorsRedirect(SSLTest* test, gconstpointer)
{
- webkit_web_context_set_tls_errors_policy(webkit_web_view_get_context(test->m_webView), WEBKIT_TLS_ERRORS_POLICY_FAIL);
+ WebKitWebContext* context = webkit_web_view_get_context(test->m_webView);
+ WebKitTLSErrorsPolicy originalPolicy = webkit_web_context_get_tls_errors_policy(context);
+ webkit_web_context_set_tls_errors_policy(context, WEBKIT_TLS_ERRORS_POLICY_FAIL);
+
+ assertIfSSLRequestProcessed = true;
test->loadURI(kHttpsServer->getURIForPath("/redirect").data());
test->waitUntilLoadFinished();
g_assert(test->m_loadFailed);
g_assert(test->m_loadEvents.contains(LoadTrackingTest::ProvisionalLoadFailed));
g_assert(!test->m_loadEvents.contains(LoadTrackingTest::LoadCommitted));
+ assertIfSSLRequestProcessed = false;
+
+ webkit_web_context_set_tls_errors_policy(context, originalPolicy);
}
static gboolean webViewAuthenticationCallback(WebKitWebView*, WebKitAuthenticationRequest* request)
@@ -153,13 +185,20 @@ static gboolean webViewAuthenticationCallback(WebKitWebView*, WebKitAuthenticati
static void testTLSErrorsHTTPAuth(SSLTest* test, gconstpointer)
{
- webkit_web_context_set_tls_errors_policy(webkit_web_view_get_context(test->m_webView), WEBKIT_TLS_ERRORS_POLICY_FAIL);
+ WebKitWebContext* context = webkit_web_view_get_context(test->m_webView);
+ WebKitTLSErrorsPolicy originalPolicy = webkit_web_context_get_tls_errors_policy(context);
+ webkit_web_context_set_tls_errors_policy(context, WEBKIT_TLS_ERRORS_POLICY_FAIL);
+
+ assertIfSSLRequestProcessed = true;
g_signal_connect(test->m_webView, "authenticate", G_CALLBACK(webViewAuthenticationCallback), NULL);
test->loadURI(kHttpsServer->getURIForPath("/auth").data());
test->waitUntilLoadFinished();
g_assert(test->m_loadFailed);
g_assert(test->m_loadEvents.contains(LoadTrackingTest::ProvisionalLoadFailed));
g_assert(!test->m_loadEvents.contains(LoadTrackingTest::LoadCommitted));
+ assertIfSSLRequestProcessed = false;
+
+ webkit_web_context_set_tls_errors_policy(context, originalPolicy);
}
class TLSErrorsTest: public SSLTest {
@@ -167,69 +206,60 @@ public:
MAKE_GLIB_TEST_FIXTURE(TLSErrorsTest);
TLSErrorsTest()
+ : m_tlsErrors(static_cast<GTlsCertificateFlags>(0))
+ , m_failingURI(nullptr)
{
- g_signal_connect(m_webView, "load-failed-with-tls-errors", G_CALLBACK(runLoadFailedWithTLSErrorsCallback), this);
}
~TLSErrorsTest()
{
- g_signal_handlers_disconnect_matched(m_webView, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
- if (m_certificateInfo)
- webkit_certificate_info_free(m_certificateInfo);
- }
-
- static gboolean runLoadFailedWithTLSErrorsCallback(WebKitWebView*, WebKitCertificateInfo* info, const char* host, TLSErrorsTest* test)
- {
- test->runLoadFailedWithTLSErrors(info, host);
- return TRUE;
- }
-
- void runLoadFailedWithTLSErrors(WebKitCertificateInfo* info, const char* host)
- {
- if (m_certificateInfo)
- webkit_certificate_info_free(m_certificateInfo);
- m_certificateInfo = webkit_certificate_info_copy(info);
- m_host.reset(g_strdup(host));
- g_main_loop_quit(m_mainLoop);
+ if (m_failingURI)
+ soup_uri_free(m_failingURI);
}
- void waitUntilLoadFailedWithTLSErrors()
+ bool loadFailedWithTLSErrors(const char* failingURI, GTlsCertificate* certificate, GTlsCertificateFlags tlsErrors) override
{
- g_main_loop_run(m_mainLoop);
- }
+ LoadTrackingTest::loadFailedWithTLSErrors(failingURI, certificate, tlsErrors);
- WebKitCertificateInfo* certificateInfo()
- {
- return m_certificateInfo;
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(certificate));
+ m_certificate = certificate;
+ m_tlsErrors = tlsErrors;
+ if (m_failingURI)
+ soup_uri_free(m_failingURI);
+ m_failingURI = soup_uri_new(failingURI);
+ return true;
}
- const char* host()
- {
- return m_host.get();
- }
+ GTlsCertificate* certificate() const { return m_certificate.get(); }
+ GTlsCertificateFlags tlsErrors() const { return m_tlsErrors; }
+ const char* host() const { return m_failingURI->host; }
private:
- WebKitCertificateInfo* m_certificateInfo;
- GUniquePtr<char> m_host;
+ GRefPtr<GTlsCertificate> m_certificate;
+ GTlsCertificateFlags m_tlsErrors;
+ SoupURI* m_failingURI;
};
static void testLoadFailedWithTLSErrors(TLSErrorsTest* test, gconstpointer)
{
WebKitWebContext* context = webkit_web_view_get_context(test->m_webView);
+ WebKitTLSErrorsPolicy originalPolicy = webkit_web_context_get_tls_errors_policy(context);
webkit_web_context_set_tls_errors_policy(context, WEBKIT_TLS_ERRORS_POLICY_FAIL);
+ assertIfSSLRequestProcessed = true;
// The load-failed-with-tls-errors signal should be emitted when there is a TLS failure.
test->loadURI(kHttpsServer->getURIForPath("/test-tls/").data());
- test->waitUntilLoadFailedWithTLSErrors();
- // Test the WebKitCertificateInfo API.
- g_assert(G_IS_TLS_CERTIFICATE(webkit_certificate_info_get_tls_certificate(test->certificateInfo())));
- g_assert_cmpuint(webkit_certificate_info_get_tls_errors(test->certificateInfo()), ==, G_TLS_CERTIFICATE_UNKNOWN_CA);
+ test->waitUntilLoadFinished();
+ g_assert(G_IS_TLS_CERTIFICATE(test->certificate()));
+ g_assert_cmpuint(test->tlsErrors(), ==, G_TLS_CERTIFICATE_UNKNOWN_CA);
g_assert_cmpstr(test->host(), ==, soup_uri_get_host(kHttpsServer->baseURI()));
g_assert_cmpint(test->m_loadEvents[0], ==, LoadTrackingTest::ProvisionalLoadStarted);
- g_assert_cmpint(test->m_loadEvents[1], ==, LoadTrackingTest::LoadFinished);
+ g_assert_cmpint(test->m_loadEvents[1], ==, LoadTrackingTest::LoadFailedWithTLSErrors);
+ g_assert_cmpint(test->m_loadEvents[2], ==, LoadTrackingTest::LoadFinished);
+ assertIfSSLRequestProcessed = false;
// Test allowing an exception for this certificate on this host.
- webkit_web_context_allow_tls_certificate_for_host(context, test->certificateInfo(), test->host());
+ webkit_web_context_allow_tls_certificate_for_host(context, test->certificate(), test->host());
// The page should now load without errors.
test->loadURI(kHttpsServer->getURIForPath("/test-tls/").data());
test->waitUntilLoadFinished();
@@ -238,8 +268,76 @@ static void testLoadFailedWithTLSErrors(TLSErrorsTest* test, gconstpointer)
g_assert_cmpint(test->m_loadEvents[1], ==, LoadTrackingTest::LoadCommitted);
g_assert_cmpint(test->m_loadEvents[2], ==, LoadTrackingTest::LoadFinished);
g_assert_cmpstr(webkit_web_view_get_title(test->m_webView), ==, TLSExpectedSuccessTitle);
+
+ webkit_web_context_set_tls_errors_policy(context, originalPolicy);
}
+class TLSSubresourceTest : public WebViewTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(TLSSubresourceTest);
+
+ static void resourceLoadStartedCallback(WebKitWebView* webView, WebKitWebResource* resource, WebKitURIRequest* request, TLSSubresourceTest* test)
+ {
+ if (webkit_web_view_get_main_resource(test->m_webView) == resource)
+ return;
+
+ // Ignore favicons.
+ if (g_str_has_suffix(webkit_uri_request_get_uri(request), "favicon.ico"))
+ return;
+
+ test->subresourceLoadStarted(resource);
+ }
+
+ TLSSubresourceTest()
+ : m_tlsErrors(static_cast<GTlsCertificateFlags>(0))
+ {
+ g_signal_connect(m_webView, "resource-load-started", G_CALLBACK(resourceLoadStartedCallback), this);
+ }
+
+ static void subresourceFailedCallback(WebKitWebResource*, GError*)
+ {
+ g_assert_not_reached();
+ }
+
+ static void subresourceFailedWithTLSErrorsCallback(WebKitWebResource* resource, GTlsCertificate* certificate, GTlsCertificateFlags tlsErrors, TLSSubresourceTest* test)
+ {
+ test->subresourceFailedWithTLSErrors(resource, certificate, tlsErrors);
+ }
+
+ void subresourceLoadStarted(WebKitWebResource* resource)
+ {
+ g_signal_connect(resource, "failed", G_CALLBACK(subresourceFailedCallback), nullptr);
+ g_signal_connect(resource, "failed-with-tls-errors", G_CALLBACK(subresourceFailedWithTLSErrorsCallback), this);
+ }
+
+ void subresourceFailedWithTLSErrors(WebKitWebResource* resource, GTlsCertificate* certificate, GTlsCertificateFlags tlsErrors)
+ {
+ m_certificate = certificate;
+ m_tlsErrors = tlsErrors;
+ g_main_loop_quit(m_mainLoop);
+ }
+
+ void waitUntilSubresourceLoadFail()
+ {
+ g_main_loop_run(m_mainLoop);
+ }
+
+ GRefPtr<GTlsCertificate> m_certificate;
+ GTlsCertificateFlags m_tlsErrors;
+};
+
+static void testSubresourceLoadFailedWithTLSErrors(TLSSubresourceTest* test, gconstpointer)
+{
+ WebKitWebContext* context = webkit_web_view_get_context(test->m_webView);
+ webkit_web_context_set_tls_errors_policy(context, WEBKIT_TLS_ERRORS_POLICY_FAIL);
+
+ assertIfSSLRequestProcessed = true;
+ test->loadURI(kHttpServer->getURIForPath("/").data());
+ test->waitUntilSubresourceLoadFail();
+ g_assert(G_IS_TLS_CERTIFICATE(test->m_certificate.get()));
+ g_assert_cmpuint(test->m_tlsErrors, ==, G_TLS_CERTIFICATE_UNKNOWN_CA);
+ assertIfSSLRequestProcessed = false;
+}
static void httpsServerCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer)
{
@@ -248,6 +346,8 @@ static void httpsServerCallback(SoupServer* server, SoupMessage* message, const
return;
}
+ g_assert(!assertIfSSLRequestProcessed);
+
if (g_str_equal(path, "/")) {
soup_message_set_status(message, SOUP_STATUS_OK);
soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, indexHTML, strlen(indexHTML));
@@ -267,6 +367,10 @@ static void httpsServerCallback(SoupServer* server, SoupMessage* message, const
} else if (g_str_equal(path, "/auth")) {
soup_message_set_status(message, SOUP_STATUS_UNAUTHORIZED);
soup_message_headers_append(message->response_headers, "WWW-Authenticate", "Basic realm=\"HTTPS auth\"");
+ } else if (g_str_equal(path, "/style.css")) {
+ soup_message_set_status(message, SOUP_STATUS_OK);
+ static const char* styleCSS = "body { color: black; }";
+ soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, styleCSS, strlen(styleCSS));
} else
soup_message_set_status(message, SOUP_STATUS_NOT_FOUND);
}
@@ -279,7 +383,7 @@ static void httpServerCallback(SoupServer* server, SoupMessage* message, const c
}
if (g_str_equal(path, "/test-script")) {
- GUniquePtr<char> pathToFile(g_build_filename(Test::getResourcesDir().data(), "link-title.js", NULL));
+ GUniquePtr<char> pathToFile(g_build_filename(Test::getResourcesDir().data(), "link-title.js", nullptr));
char* contents;
gsize length;
g_file_get_contents(pathToFile.get(), &contents, &length, 0);
@@ -288,7 +392,7 @@ static void httpServerCallback(SoupServer* server, SoupMessage* message, const c
soup_message_set_status(message, SOUP_STATUS_OK);
soup_message_body_complete(message->response_body);
} else if (g_str_equal(path, "/test-image")) {
- GUniquePtr<char> pathToFile(g_build_filename(Test::getWebKit1TestResoucesDir().data(), "blank.ico", NULL));
+ GUniquePtr<char> pathToFile(g_build_filename(Test::getResourcesDir().data(), "blank.ico", nullptr));
char* contents;
gsize length;
g_file_get_contents(pathToFile.get(), &contents, &length, 0);
@@ -296,6 +400,12 @@ static void httpServerCallback(SoupServer* server, SoupMessage* message, const c
soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, contents, length);
soup_message_set_status(message, SOUP_STATUS_OK);
soup_message_body_complete(message->response_body);
+ } else if (g_str_equal(path, "/")) {
+ soup_message_set_status(message, SOUP_STATUS_OK);
+ char* responseHTML = g_strdup_printf("<html><head><link rel='stylesheet' href='%s' type='text/css'></head><body>SSL subresource test</body></html>",
+ kHttpsServer->getURIForPath("/style.css").data());
+ soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, responseHTML, strlen(responseHTML));
+ soup_message_body_complete(message->response_body);
} else
soup_message_set_status(message, SOUP_STATUS_NOT_FOUND);
}
@@ -310,12 +420,10 @@ void beforeAll()
SSLTest::add("WebKitWebView", "ssl", testSSL);
InsecureContentTest::add("WebKitWebView", "insecure-content", testInsecureContent);
- // In this case the order of the tests does matter because tls-errors-policy tests the default policy,
- // and expects that no exception will have been added for this certificate and host pair as is
- // done in the tls-permission-request test.
SSLTest::add("WebKitWebView", "tls-errors-policy", testTLSErrorsPolicy);
SSLTest::add("WebKitWebView", "tls-errors-redirect-to-http", testTLSErrorsRedirect);
SSLTest::add("WebKitWebView", "tls-http-auth", testTLSErrorsHTTPAuth);
+ TLSSubresourceTest::add("WebKitWebView", "tls-subresource", testSubresourceLoadFailedWithTLSErrors);
TLSErrorsTest::add("WebKitWebView", "load-failed-with-tls-errors", testLoadFailedWithTLSErrors);
}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestUIClient.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestUIClient.cpp
index d24edc601..fc48fa468 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestUIClient.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestUIClient.cpp
@@ -20,13 +20,14 @@
#include "config.h"
#include "WebViewTest.h"
#include <wtf/HashSet.h>
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
#include <wtf/text/StringHash.h>
static const char* kAlertDialogMessage = "WebKitGTK+ alert dialog message";
static const char* kConfirmDialogMessage = "WebKitGTK+ confirm dialog message";
static const char* kPromptDialogMessage = "WebKitGTK+ prompt dialog message";
static const char* kPromptDialogReturnedText = "WebKitGTK+ prompt dialog returned text";
+static const char* kBeforeUnloadConfirmDialogMessage = "WebKitGTK+ beforeunload dialog message";
class UIClientTest: public WebViewTest {
public:
@@ -117,9 +118,9 @@ public:
test->m_windowPropertiesChanged.add(g_param_spec_get_name(paramSpec));
}
- static GtkWidget* viewCreateCallback(WebKitWebView* webView, UIClientTest* test)
+ static GtkWidget* viewCreateCallback(WebKitWebView* webView, WebKitNavigationAction* navigation, UIClientTest* test)
{
- return test->viewCreate(webView);
+ return test->viewCreate(webView, navigation);
}
static void viewReadyToShowCallback(WebKitWebView* webView, UIClientTest* test)
@@ -146,6 +147,9 @@ public:
case WEBKIT_SCRIPT_DIALOG_PROMPT:
g_assert_cmpstr(webkit_script_dialog_get_message(dialog), ==, kPromptDialogReturnedText);
break;
+ case WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM:
+ g_assert_not_reached();
+ break;
}
g_main_loop_quit(m_mainLoop);
@@ -165,6 +169,13 @@ public:
webkit_script_dialog_prompt_set_text(dialog, kPromptDialogReturnedText);
}
+ void scriptBeforeUnloadConfirm(WebKitScriptDialog* dialog)
+ {
+ g_assert_cmpstr(webkit_script_dialog_get_message(dialog), ==, kBeforeUnloadConfirmDialogMessage);
+ m_scriptDialogConfirmed = true;
+ webkit_script_dialog_confirm_set_confirmed(dialog, m_scriptDialogConfirmed);
+ }
+
static gboolean scriptDialog(WebKitWebView*, WebKitScriptDialog* dialog, UIClientTest* test)
{
switch (webkit_script_dialog_get_dialog_type(dialog)) {
@@ -177,6 +188,9 @@ public:
case WEBKIT_SCRIPT_DIALOG_PROMPT:
test->scriptPrompt(dialog);
break;
+ case WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM:
+ test->scriptBeforeUnloadConfirm(dialog);
+ break;
}
return TRUE;
@@ -197,6 +211,12 @@ public:
g_assert(WEBKIT_IS_PERMISSION_REQUEST(request));
test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request));
+ if (test->m_verifyMediaTypes && WEBKIT_IS_USER_MEDIA_PERMISSION_REQUEST(request)) {
+ WebKitUserMediaPermissionRequest* userMediaRequest = WEBKIT_USER_MEDIA_PERMISSION_REQUEST(request);
+ g_assert(webkit_user_media_permission_is_for_audio_device(userMediaRequest) == test->m_expectedAudioMedia);
+ g_assert(webkit_user_media_permission_is_for_video_device(userMediaRequest) == test->m_expectedVideoMedia);
+ }
+
if (test->m_allowPermissionRequests)
webkit_permission_request_allow(request);
else
@@ -209,6 +229,9 @@ public:
: m_scriptDialogType(WEBKIT_SCRIPT_DIALOG_ALERT)
, m_scriptDialogConfirmed(true)
, m_allowPermissionRequests(false)
+ , m_verifyMediaTypes(false)
+ , m_expectedAudioMedia(false)
+ , m_expectedVideoMedia(false)
, m_mouseTargetModifiers(0)
{
webkit_settings_set_javascript_can_open_windows_automatically(webkit_web_view_get_settings(m_webView), TRUE);
@@ -223,6 +246,24 @@ public:
g_signal_handlers_disconnect_matched(m_webView, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
}
+ static void tryWebViewCloseCallback(UIClientTest* test)
+ {
+ g_main_loop_quit(test->m_mainLoop);
+ }
+
+ void tryCloseAndWaitUntilClosed()
+ {
+ gulong handler = g_signal_connect_swapped(m_webView, "close", G_CALLBACK(tryWebViewCloseCallback), this);
+ // Use an idle because webkit_web_view_try_close can emit the close signal in the
+ // current run loop iteration.
+ g_idle_add([](gpointer data) -> gboolean {
+ webkit_web_view_try_close(WEBKIT_WEB_VIEW(data));
+ return G_SOURCE_REMOVE;
+ }, m_webView);
+ g_main_loop_run(m_mainLoop);
+ g_signal_handler_disconnect(m_webView, handler);
+ }
+
void waitUntilMainLoopFinishes()
{
g_main_loop_run(m_mainLoop);
@@ -240,9 +281,10 @@ public:
return m_mouseTargetHitTestResult.get();
}
- virtual GtkWidget* viewCreate(WebKitWebView* webView)
+ virtual GtkWidget* viewCreate(WebKitWebView* webView, WebKitNavigationAction* navigation)
{
g_assert(webView == m_webView);
+ g_assert(navigation);
GtkWidget* newWebView = webkit_web_view_new_with_context(webkit_web_view_get_context(webView));
g_object_ref_sink(newWebView);
@@ -287,6 +329,9 @@ public:
WebKitScriptDialogType m_scriptDialogType;
bool m_scriptDialogConfirmed;
bool m_allowPermissionRequests;
+ gboolean m_verifyMediaTypes;
+ gboolean m_expectedAudioMedia;
+ gboolean m_expectedVideoMedia;
WindowProperties m_windowProperties;
HashSet<WTF::String> m_windowPropertiesChanged;
GRefPtr<WebKitHitTestResult> m_mouseTargetHitTestResult;
@@ -305,6 +350,91 @@ static void testWebViewCreateReadyClose(UIClientTest* test, gconstpointer)
g_assert_cmpint(events[2], ==, UIClientTest::Close);
}
+class CreateNavigationDataTest: public UIClientTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(CreateNavigationDataTest);
+
+ CreateNavigationDataTest()
+ : m_navigation(nullptr)
+ {
+ }
+
+ ~CreateNavigationDataTest()
+ {
+ clearNavigation();
+ }
+
+ void clearNavigation()
+ {
+ if (m_navigation)
+ webkit_navigation_action_free(m_navigation);
+ m_navigation = nullptr;
+ }
+
+ GtkWidget* viewCreate(WebKitWebView* webView, WebKitNavigationAction* navigation)
+ {
+ g_assert(navigation);
+ g_assert(!m_navigation);
+ m_navigation = webkit_navigation_action_copy(navigation);
+ g_main_loop_quit(m_mainLoop);
+ return nullptr;
+ }
+
+ void loadHTML(const char* html)
+ {
+ clearNavigation();
+ WebViewTest::loadHtml(html, nullptr);
+ }
+
+ void clickAndWaitUntilMainLoopFinishes(int x, int y)
+ {
+ clearNavigation();
+ clickMouseButton(x, y, 1);
+ g_main_loop_run(m_mainLoop);
+ }
+
+ WebKitNavigationAction* m_navigation;
+};
+
+static void testWebViewCreateNavigationData(CreateNavigationDataTest* test, gconstpointer)
+{
+ test->showInWindowAndWaitUntilMapped();
+
+ test->loadHTML(
+ "<html><body>"
+ "<input style=\"position:absolute; left:0; top:0; margin:0; padding:0\" type=\"button\" value=\"click to show a popup\" onclick=\"window.open('data:foo');\"/>"
+ "<a style=\"position:absolute; left:20; top:20;\" href=\"data:bar\" target=\"_blank\">popup link</a>"
+ "</body></html>");
+ test->waitUntilLoadFinished();
+
+ // Click on a button.
+ test->clickAndWaitUntilMainLoopFinishes(5, 5);
+ g_assert_cmpstr(webkit_uri_request_get_uri(webkit_navigation_action_get_request(test->m_navigation)), ==, "data:foo");
+ g_assert_cmpuint(webkit_navigation_action_get_navigation_type(test->m_navigation), ==, WEBKIT_NAVIGATION_TYPE_OTHER);
+ // FIXME: This should be button 1.
+ g_assert_cmpuint(webkit_navigation_action_get_mouse_button(test->m_navigation), ==, 0);
+ g_assert_cmpuint(webkit_navigation_action_get_modifiers(test->m_navigation), ==, 0);
+ g_assert(webkit_navigation_action_is_user_gesture(test->m_navigation));
+
+ // Click on a link.
+ test->clickAndWaitUntilMainLoopFinishes(21, 21);
+ g_assert_cmpstr(webkit_uri_request_get_uri(webkit_navigation_action_get_request(test->m_navigation)), ==, "data:bar");
+ g_assert_cmpuint(webkit_navigation_action_get_navigation_type(test->m_navigation), ==, WEBKIT_NAVIGATION_TYPE_LINK_CLICKED);
+ g_assert_cmpuint(webkit_navigation_action_get_mouse_button(test->m_navigation), ==, 1);
+ g_assert_cmpuint(webkit_navigation_action_get_modifiers(test->m_navigation), ==, 0);
+ g_assert(webkit_navigation_action_is_user_gesture(test->m_navigation));
+
+ // No user interaction.
+ test->loadHTML("<html><body onLoad=\"window.open();\"></html>");
+ test->waitUntilMainLoopFinishes();
+
+ g_assert_cmpstr(webkit_uri_request_get_uri(webkit_navigation_action_get_request(test->m_navigation)), ==, "");
+ g_assert_cmpuint(webkit_navigation_action_get_navigation_type(test->m_navigation), ==, WEBKIT_NAVIGATION_TYPE_OTHER);
+ g_assert_cmpuint(webkit_navigation_action_get_mouse_button(test->m_navigation), ==, 0);
+ g_assert_cmpuint(webkit_navigation_action_get_modifiers(test->m_navigation), ==, 0);
+ g_assert(!webkit_navigation_action_is_user_gesture(test->m_navigation));
+}
+
static gboolean checkMimeTypeForFilter(GtkFileFilter* filter, const gchar* mimeType)
{
GtkFileFilterInfo filterInfo;
@@ -323,11 +453,11 @@ public:
test->m_webViewEvents.append(RunAsModal);
}
- GtkWidget* viewCreate(WebKitWebView* webView)
+ GtkWidget* viewCreate(WebKitWebView* webView, WebKitNavigationAction* navigation)
{
g_assert(webView == m_webView);
- GtkWidget* newWebView = UIClientTest::viewCreate(webView);
+ GtkWidget* newWebView = UIClientTest::viewCreate(webView, navigation);
g_signal_connect(newWebView, "run-as-modal", G_CALLBACK(dialogRunAsModalCallback), this);
return newWebView;
}
@@ -375,24 +505,71 @@ static void testWebViewJavaScriptDialogs(UIClientTest* test, gconstpointer)
static const char* jsAlertFormat = "alert('%s')";
static const char* jsConfirmFormat = "do { confirmed = confirm('%s'); } while (!confirmed); alert('confirmed');";
static const char* jsPromptFormat = "alert(prompt('%s', 'default'));";
+ static const char* htmlOnBeforeUnloadFormat =
+ "<html><body onbeforeunload=\"return beforeUnloadHandler();\"><script>function beforeUnloadHandler() { return \"%s\"; }</script></body></html>";
test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_ALERT;
GUniquePtr<char> alertDialogMessage(g_strdup_printf(jsAlertFormat, kAlertDialogMessage));
GUniquePtr<char> alertHTML(g_strdup_printf(htmlOnLoadFormat, alertDialogMessage.get()));
test->loadHtml(alertHTML.get(), 0);
test->waitUntilMainLoopFinishes();
+ webkit_web_view_stop_loading(test->m_webView);
+ test->waitUntilLoadFinished();
test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_CONFIRM;
GUniquePtr<char> confirmDialogMessage(g_strdup_printf(jsConfirmFormat, kConfirmDialogMessage));
GUniquePtr<char> confirmHTML(g_strdup_printf(htmlOnLoadFormat, confirmDialogMessage.get()));
test->loadHtml(confirmHTML.get(), 0);
test->waitUntilMainLoopFinishes();
+ webkit_web_view_stop_loading(test->m_webView);
+ test->waitUntilLoadFinished();
test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_PROMPT;
GUniquePtr<char> promptDialogMessage(g_strdup_printf(jsPromptFormat, kPromptDialogMessage));
GUniquePtr<char> promptHTML(g_strdup_printf(htmlOnLoadFormat, promptDialogMessage.get()));
test->loadHtml(promptHTML.get(), 0);
test->waitUntilMainLoopFinishes();
+ webkit_web_view_stop_loading(test->m_webView);
+ test->waitUntilLoadFinished();
+
+ test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM;
+ GUniquePtr<char> beforeUnloadDialogHTML(g_strdup_printf(htmlOnBeforeUnloadFormat, kBeforeUnloadConfirmDialogMessage));
+ test->loadHtml(beforeUnloadDialogHTML.get(), nullptr);
+ test->waitUntilLoadFinished();
+
+ // Reload should trigger onbeforeunload.
+#if 0
+ // FIXME: reloading HTML data doesn't emit finished load event.
+ // See https://bugs.webkit.org/show_bug.cgi?id=139089.
+ test->m_scriptDialogConfirmed = false;
+ webkit_web_view_reload(test->m_webView);
+ test->waitUntilLoadFinished();
+ g_assert(test->m_scriptDialogConfirmed);
+#endif
+
+ // Navigation should trigger onbeforeunload.
+ test->m_scriptDialogConfirmed = false;
+ test->loadHtml("<html></html>", nullptr);
+ test->waitUntilLoadFinished();
+ g_assert(test->m_scriptDialogConfirmed);
+
+ // Try close should trigger onbeforeunload.
+ test->m_scriptDialogConfirmed = false;
+ test->loadHtml(beforeUnloadDialogHTML.get(), nullptr);
+ test->waitUntilLoadFinished();
+ test->tryCloseAndWaitUntilClosed();
+ g_assert(test->m_scriptDialogConfirmed);
+
+ // Try close on a page with no unload handlers should not trigger onbeforeunload,
+ // but should actually close the page.
+ test->m_scriptDialogConfirmed = false;
+ test->loadHtml("<html><body></body></html>", nullptr);
+ test->waitUntilLoadFinished();
+ // We got a onbeforeunload of the previous page.
+ g_assert(test->m_scriptDialogConfirmed);
+ test->m_scriptDialogConfirmed = false;
+ test->tryCloseAndWaitUntilClosed();
+ g_assert(!test->m_scriptDialogConfirmed);
}
static void testWebViewWindowProperties(UIClientTest* test, gconstpointer)
@@ -423,13 +600,22 @@ static void testWebViewMouseTarget(UIClientTest* test, gconstpointer)
test->showInWindowAndWaitUntilMapped(GTK_WINDOW_TOPLEVEL);
const char* linksHoveredHTML =
- "<html><body>"
+ "<html><head>"
+ " <script>"
+ " window.onload = function () {"
+ " window.getSelection().removeAllRanges();"
+ " var select_range = document.createRange();"
+ " select_range.selectNodeContents(document.getElementById('text_to_select'));"
+ " window.getSelection().addRange(select_range);"
+ " }"
+ " </script>"
+ "</head><body>"
" <a style='position:absolute; left:1; top:1' href='http://www.webkitgtk.org' title='WebKitGTK+ Title'>WebKitGTK+ Website</a>"
" <img style='position:absolute; left:1; top:10' src='0xdeadbeef' width=5 height=5></img>"
" <a style='position:absolute; left:1; top:20' href='http://www.webkitgtk.org/logo' title='WebKitGTK+ Logo'><img src='0xdeadbeef' width=5 height=5></img></a>"
" <input style='position:absolute; left:1; top:30' size='10'></input>"
- " <div style='position:absolute; left:1; top:50; width:30; height:30; overflow:scroll'>&nbsp;</div>"
" <video style='position:absolute; left:1; top:100' width='300' height='300' controls='controls' preload='none'><source src='movie.ogg' type='video/ogg' /></video>"
+ " <p style='position:absolute; left:1; top:120' id='text_to_select'>Lorem ipsum.</p>"
"</body></html>";
test->loadHtml(linksHoveredHTML, "file:///");
@@ -441,6 +627,7 @@ static void testWebViewMouseTarget(UIClientTest* test, gconstpointer)
g_assert(!webkit_hit_test_result_context_is_image(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
g_assert_cmpstr(webkit_hit_test_result_get_link_uri(hitTestResult), ==, "http://www.webkitgtk.org/");
g_assert_cmpstr(webkit_hit_test_result_get_link_title(hitTestResult), ==, "WebKitGTK+ Title");
g_assert_cmpstr(webkit_hit_test_result_get_link_label(hitTestResult), ==, "WebKitGTK+ Website");
@@ -452,6 +639,7 @@ static void testWebViewMouseTarget(UIClientTest* test, gconstpointer)
g_assert(!webkit_hit_test_result_context_is_image(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
g_assert(!test->m_mouseTargetModifiers);
// Move over image with GDK_CONTROL_MASK.
@@ -460,6 +648,7 @@ static void testWebViewMouseTarget(UIClientTest* test, gconstpointer)
g_assert(webkit_hit_test_result_context_is_image(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_scrollbar(hitTestResult));
g_assert_cmpstr(webkit_hit_test_result_get_image_uri(hitTestResult), ==, "file:///0xdeadbeef");
g_assert(test->m_mouseTargetModifiers & GDK_CONTROL_MASK);
@@ -471,6 +660,7 @@ static void testWebViewMouseTarget(UIClientTest* test, gconstpointer)
g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_scrollbar(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
g_assert_cmpstr(webkit_hit_test_result_get_link_uri(hitTestResult), ==, "http://www.webkitgtk.org/logo");
g_assert_cmpstr(webkit_hit_test_result_get_image_uri(hitTestResult), ==, "file:///0xdeadbeef");
g_assert_cmpstr(webkit_hit_test_result_get_link_title(hitTestResult), ==, "WebKitGTK+ Logo");
@@ -484,6 +674,7 @@ static void testWebViewMouseTarget(UIClientTest* test, gconstpointer)
g_assert(webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_scrollbar(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
g_assert_cmpstr(webkit_hit_test_result_get_media_uri(hitTestResult), ==, "file:///movie.ogg");
g_assert(!test->m_mouseTargetModifiers);
@@ -494,19 +685,32 @@ static void testWebViewMouseTarget(UIClientTest* test, gconstpointer)
g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_scrollbar(hitTestResult));
g_assert(webkit_hit_test_result_context_is_editable(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
g_assert(!test->m_mouseTargetModifiers);
// Move over scrollbar.
- hitTestResult = test->moveMouseAndWaitUntilMouseTargetChanged(5, 75);
+ hitTestResult = test->moveMouseAndWaitUntilMouseTargetChanged(gtk_widget_get_allocated_width(GTK_WIDGET(test->m_webView)) - 4, 5);
g_assert(!webkit_hit_test_result_context_is_link(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_image(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
g_assert(webkit_hit_test_result_context_is_scrollbar(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
g_assert(!test->m_mouseTargetModifiers);
+
+ // Move over selection.
+ hitTestResult = test->moveMouseAndWaitUntilMouseTargetChanged(2, 145);
+ g_assert(!webkit_hit_test_result_context_is_link(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_image(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_scrollbar(hitTestResult));
+ g_assert(webkit_hit_test_result_context_is_selection(hitTestResult));
+ g_assert(!test->m_mouseTargetModifiers);
+
}
-static void testWebViewPermissionRequests(UIClientTest* test, gconstpointer)
+static void testWebViewGeolocationPermissionRequests(UIClientTest* test, gconstpointer)
{
// Some versions of geoclue give a runtime warning because it tries
// to register the error quark twice. See https://bugs.webkit.org/show_bug.cgi?id=89858.
@@ -527,7 +731,7 @@ static void testWebViewPermissionRequests(UIClientTest* test, gconstpointer)
// Test denying a permission request.
test->m_allowPermissionRequests = false;
- test->loadHtml(geolocationRequestHTML, 0);
+ test->loadHtml(geolocationRequestHTML, "http://foo.com/bar");
test->waitUntilTitleChanged();
// According to the Geolocation API specification, '1' is the
@@ -547,6 +751,77 @@ static void testWebViewPermissionRequests(UIClientTest* test, gconstpointer)
test->addLogFatalFlag(G_LOG_LEVEL_WARNING);
}
+#if ENABLE(MEDIA_STREAM)
+static void testWebViewUserMediaPermissionRequests(UIClientTest* test, gconstpointer)
+{
+ WebKitSettings* settings = webkit_web_view_get_settings(test->m_webView);
+ gboolean enabled = webkit_settings_get_enable_media_stream(settings);
+ webkit_settings_set_enable_media_stream(settings, TRUE);
+
+ test->showInWindowAndWaitUntilMapped();
+ static const char* userMediaRequestHTML =
+ "<html>"
+ " <script>"
+ " function runTest()"
+ " {"
+ " navigator.webkitGetUserMedia({audio: true, video: true},"
+ " function(s) { document.title = \"OK\" },"
+ " function(e) { document.title = e.name });"
+ " }"
+ " </script>"
+ " <body onload='runTest();'></body>"
+ "</html>";
+
+ test->m_verifyMediaTypes = TRUE;
+ test->m_expectedAudioMedia = TRUE;
+ test->m_expectedVideoMedia = TRUE;
+
+ // Test denying a permission request.
+ test->m_allowPermissionRequests = false;
+ test->loadHtml(userMediaRequestHTML, nullptr);
+ test->waitUntilTitleChangedTo("PermissionDeniedError");
+
+ // Test allowing a permission request.
+ test->m_allowPermissionRequests = true;
+ test->loadHtml(userMediaRequestHTML, nullptr);
+ test->waitUntilTitleChangedTo("OK");
+
+ webkit_settings_set_enable_media_stream(settings, enabled);
+}
+
+static void testWebViewAudioOnlyUserMediaPermissionRequests(UIClientTest* test, gconstpointer)
+{
+ WebKitSettings* settings = webkit_web_view_get_settings(test->m_webView);
+ gboolean enabled = webkit_settings_get_enable_media_stream(settings);
+ webkit_settings_set_enable_media_stream(settings, TRUE);
+
+ test->showInWindowAndWaitUntilMapped();
+ static const char* userMediaRequestHTML =
+ "<html>"
+ " <script>"
+ " function runTest()"
+ " {"
+ " navigator.webkitGetUserMedia({audio: true, video: false},"
+ " function(s) { document.title = \"OK\" },"
+ " function(e) { document.title = e.name });"
+ " }"
+ " </script>"
+ " <body onload='runTest();'></body>"
+ "</html>";
+
+ test->m_verifyMediaTypes = TRUE;
+ test->m_expectedAudioMedia = TRUE;
+ test->m_expectedVideoMedia = FALSE;
+
+ // Test denying a permission request.
+ test->m_allowPermissionRequests = false;
+ test->loadHtml(userMediaRequestHTML, nullptr);
+ test->waitUntilTitleChangedTo("PermissionDeniedError");
+
+ webkit_settings_set_enable_media_stream(settings, enabled);
+}
+#endif // ENABLE(MEDIA_STREAM)
+
class FileChooserTest: public UIClientTest {
public:
MAKE_GLIB_TEST_FIXTURE(FileChooserTest);
@@ -662,16 +937,124 @@ static void testWebViewFileChooserRequest(FileChooserTest* test, gconstpointer)
webkit_file_chooser_request_cancel(fileChooserRequest);
}
+class ColorChooserTest: public WebViewTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(ColorChooserTest);
+
+ static gboolean runColorChooserCallback(WebKitWebView*, WebKitColorChooserRequest* request, ColorChooserTest* test)
+ {
+ test->runColorChooser(request);
+ return TRUE;
+ }
+
+ static void requestFinishedCallback(WebKitColorChooserRequest* request, ColorChooserTest* test)
+ {
+ g_assert(test->m_request.get() == request);
+ test->m_request = nullptr;
+ if (g_main_loop_is_running(test->m_mainLoop))
+ g_main_loop_quit(test->m_mainLoop);
+ }
+
+ ColorChooserTest()
+ {
+ g_signal_connect(m_webView, "run-color-chooser", G_CALLBACK(runColorChooserCallback), this);
+ }
+
+ void runColorChooser(WebKitColorChooserRequest* request)
+ {
+ g_assert(WEBKIT_IS_COLOR_CHOOSER_REQUEST(request));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request));
+ m_request = request;
+ g_signal_connect(request, "finished", G_CALLBACK(requestFinishedCallback), this);
+ g_main_loop_quit(m_mainLoop);
+ }
+
+ void finishRequest()
+ {
+ g_assert(m_request.get());
+ webkit_color_chooser_request_finish(m_request.get());
+ g_assert(!m_request);
+ }
+
+ void cancelRequest()
+ {
+ g_assert(m_request.get());
+ webkit_color_chooser_request_cancel(m_request.get());
+ g_assert(!m_request);
+ }
+
+ WebKitColorChooserRequest* clickMouseButtonAndWaitForColorChooserRequest(int x, int y)
+ {
+ clickMouseButton(x, y);
+ g_main_loop_run(m_mainLoop);
+ g_assert(m_request.get());
+ return m_request.get();
+ }
+
+private:
+ GRefPtr<WebKitColorChooserRequest> m_request;
+};
+
+static void testWebViewColorChooserRequest(ColorChooserTest* test, gconstpointer)
+{
+ static const char* colorChooserHTMLFormat = "<html><body><input style='position:absolute;left:1;top:1;margin:0;padding:0;width:45;height:25' type='color' %s/></body></html>";
+ test->showInWindowAndWaitUntilMapped();
+
+ GUniquePtr<char> defaultColorHTML(g_strdup_printf(colorChooserHTMLFormat, ""));
+ test->loadHtml(defaultColorHTML.get(), nullptr);
+ test->waitUntilLoadFinished();
+ WebKitColorChooserRequest* request = test->clickMouseButtonAndWaitForColorChooserRequest(5, 5);
+
+ // Default color is black (#000000).
+ GdkRGBA rgba1;
+ GdkRGBA rgba2 = { 0., 0., 0., 1. };
+ webkit_color_chooser_request_get_rgba(request, &rgba1);
+ g_assert(gdk_rgba_equal(&rgba1, &rgba2));
+
+ // Set a different color.
+ rgba2.green = 1;
+ webkit_color_chooser_request_set_rgba(request, &rgba2);
+ webkit_color_chooser_request_get_rgba(request, &rgba1);
+ g_assert(gdk_rgba_equal(&rgba1, &rgba2));
+
+ GdkRectangle rect;
+ webkit_color_chooser_request_get_element_rectangle(request, &rect);
+ g_assert_cmpint(rect.x, == , 1);
+ g_assert_cmpint(rect.y, == , 1);
+ g_assert_cmpint(rect.width, == , 45);
+ g_assert_cmpint(rect.height, == , 25);
+
+ test->finishRequest();
+
+ // Use an initial color.
+ GUniquePtr<char> initialColorHTML(g_strdup_printf(colorChooserHTMLFormat, "value='#FF00FF'"));
+ test->loadHtml(initialColorHTML.get(), nullptr);
+ test->waitUntilLoadFinished();
+ request = test->clickMouseButtonAndWaitForColorChooserRequest(5, 5);
+
+ webkit_color_chooser_request_get_rgba(request, &rgba1);
+ GdkRGBA rgba3 = { 1., 0., 1., 1. };
+ g_assert(gdk_rgba_equal(&rgba1, &rgba3));
+
+ test->cancelRequest();
+}
+
void beforeAll()
{
UIClientTest::add("WebKitWebView", "create-ready-close", testWebViewCreateReadyClose);
+ CreateNavigationDataTest::add("WebKitWebView", "create-navigation-data", testWebViewCreateNavigationData);
ModalDialogsTest::add("WebKitWebView", "allow-modal-dialogs", testWebViewAllowModalDialogs);
ModalDialogsTest::add("WebKitWebView", "disallow-modal-dialogs", testWebViewDisallowModalDialogs);
UIClientTest::add("WebKitWebView", "javascript-dialogs", testWebViewJavaScriptDialogs);
UIClientTest::add("WebKitWebView", "window-properties", testWebViewWindowProperties);
UIClientTest::add("WebKitWebView", "mouse-target", testWebViewMouseTarget);
- UIClientTest::add("WebKitWebView", "permission-requests", testWebViewPermissionRequests);
+ UIClientTest::add("WebKitWebView", "geolocation-permission-requests", testWebViewGeolocationPermissionRequests);
+#if ENABLE(MEDIA_STREAM)
+ UIClientTest::add("WebKitWebView", "usermedia-permission-requests", testWebViewUserMediaPermissionRequests);
+ UIClientTest::add("WebKitWebView", "audio-usermedia-permission-request", testWebViewAudioOnlyUserMediaPermissionRequests);
+#endif
FileChooserTest::add("WebKitWebView", "file-chooser-request", testWebViewFileChooserRequest);
+ ColorChooserTest::add("WebKitWebView", "color-chooser-request", testWebViewColorChooserRequest);
}
void afterAll()
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebExtensions.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebExtensions.cpp
index b02cdfd03..b41e5eb82 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebExtensions.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebExtensions.cpp
@@ -21,7 +21,7 @@
#include "WebKitTestBus.h"
#include "WebViewTest.h"
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
static const char* webExtensionsUserData = "Web Extensions user data";
static WebKitTestBus* bus;
@@ -32,8 +32,9 @@ static void testWebExtensionGetTitle(WebViewTest* test, gconstpointer)
test->loadHtml("<html><head><title>WebKitGTK+ Web Extensions Test</title></head><body></body></html>", 0);
test->waitUntilLoadFinished();
- GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy("org.webkit.gtk.WebExtensionTest",
- "/org/webkit/gtk/WebExtensionTest" , "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
+ GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
+ GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
+ "/org/webkit/gtk/WebExtensionTest", "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
GRefPtr<GVariant> result = adoptGRef(g_dbus_proxy_call_sync(
proxy.get(),
"GetTitle",
@@ -54,7 +55,8 @@ static void documentLoadedCallback(GDBusConnection*, const char*, const char*, c
static void testDocumentLoadedSignal(WebViewTest* test, gconstpointer)
{
- GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy("org.webkit.gtk.WebExtensionTest",
+ GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
+ GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
"/org/webkit/gtk/WebExtensionTest", "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
GDBusConnection* connection = g_dbus_proxy_get_connection(proxy.get());
guint id = g_dbus_connection_signal_subscribe(connection,
@@ -86,10 +88,13 @@ static void testWebKitWebViewProcessCrashed(WebViewTest* test, gconstpointer)
test->loadHtml("<html></html>", 0);
test->waitUntilLoadFinished();
- g_signal_connect(test->m_webView, "web-process-crashed",
+ g_signal_connect_after(test->m_webView, "web-process-crashed",
G_CALLBACK(webProcessCrashedCallback), test);
- GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy("org.webkit.gtk.WebExtensionTest",
+ test->m_expectedWebProcessCrash = true;
+
+ GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
+ GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
"/org/webkit/gtk/WebExtensionTest", "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
GRefPtr<GVariant> result = adoptGRef(g_dbus_proxy_call_sync(
@@ -100,6 +105,7 @@ static void testWebKitWebViewProcessCrashed(WebViewTest* test, gconstpointer)
-1, 0, 0));
g_assert(!result);
g_main_loop_run(test->m_mainLoop);
+ test->m_expectedWebProcessCrash = false;
}
static void testWebExtensionWindowObjectCleared(WebViewTest* test, gconstpointer)
@@ -152,7 +158,8 @@ static void testWebExtensionIsolatedWorld(WebViewTest* test, gconstpointer)
"document.getElementById('console').innerHTML = top.foo;\n"
"window.open = function () { alert('Isolated World'); }\n"
"document.open(1, 2, 3);";
- GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy("org.webkit.gtk.WebExtensionTest",
+ GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
+ GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
"/org/webkit/gtk/WebExtensionTest" , "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
g_dbus_proxy_call(proxy.get(),
"RunJavaScriptInIsolatedWorld",
@@ -173,49 +180,50 @@ static void testWebExtensionIsolatedWorld(WebViewTest* test, gconstpointer)
g_signal_handler_disconnect(test->m_webView, scriptDialogID);
}
-static void testWebExtensionInitializationUserData(WebViewTest* test, gconstpointer)
+static gboolean permissionRequestCallback(WebKitWebView*, WebKitPermissionRequest* request, WebViewTest* test)
{
- test->loadHtml("<html></html>", 0);
- test->waitUntilLoadFinished();
+ if (!WEBKIT_IS_INSTALL_MISSING_MEDIA_PLUGINS_PERMISSION_REQUEST(request))
+ return FALSE;
- GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy("org.webkit.gtk.WebExtensionTest",
- "/org/webkit/gtk/WebExtensionTest", "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
-
- GRefPtr<GVariant> result = adoptGRef(g_dbus_proxy_call_sync(
- proxy.get(),
- "GetInitializationUserData",
- nullptr,
- G_DBUS_CALL_FLAGS_NONE,
- -1, 0, 0));
- g_assert(result);
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request));
+ WebKitInstallMissingMediaPluginsPermissionRequest* missingPluginsRequest = WEBKIT_INSTALL_MISSING_MEDIA_PLUGINS_PERMISSION_REQUEST(request);
+ g_assert(webkit_install_missing_media_plugins_permission_request_get_description(missingPluginsRequest));
+ webkit_permission_request_deny(request);
+ test->quitMainLoop();
- const gchar* userData = nullptr;
- g_variant_get(result.get(), "(&s)", &userData);
- g_assert_cmpstr(userData, ==, webExtensionsUserData);
+ return TRUE;
}
-static void initializeWebExtensions(WebKitWebContext* context, gpointer)
+static void testInstallMissingPluginsPermissionRequest(WebViewTest* test, gconstpointer)
{
- webkit_web_context_set_web_extensions_directory(context, WEBKIT_TEST_WEB_EXTENSIONS_DIR);
- webkit_web_context_set_web_extensions_initialization_user_data(context,
- g_variant_new("&s", webExtensionsUserData));
+ GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
+ GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
+ "/org/webkit/gtk/WebExtensionTest", "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
+ GRefPtr<GVariant> result = adoptGRef(g_dbus_proxy_call_sync(proxy.get(), "RemoveAVPluginsFromGSTRegistry",
+ nullptr, G_DBUS_CALL_FLAGS_NONE, -1, nullptr, nullptr));
+
+ test->showInWindowAndWaitUntilMapped();
+
+ gulong permissionRequestSignalID = g_signal_connect(test->m_webView, "permission-request", G_CALLBACK(permissionRequestCallback), test);
+ // FIXME: the base URI needs to finish with / to work, that shouldn't happen.
+ GUniquePtr<char> baseURI(g_strconcat("file://", Test::getResourcesDir(Test::WebKit2Resources).data(), "/", nullptr));
+ test->loadHtml("<html><body><video src=\"test.mp4\" autoplay></video></body></html>", baseURI.get());
+ g_main_loop_run(test->m_mainLoop);
+ g_signal_handler_disconnect(test->m_webView, permissionRequestSignalID);
}
void beforeAll()
{
- g_signal_connect(webkit_web_context_get_default(),
- "initialize-web-extensions", G_CALLBACK(initializeWebExtensions), nullptr);
-
bus = new WebKitTestBus();
if (!bus->run())
return;
- WebViewTest::add("WebKitWebContext", "initialization-user-data", testWebExtensionInitializationUserData);
WebViewTest::add("WebKitWebExtension", "dom-document-title", testWebExtensionGetTitle);
WebViewTest::add("WebKitWebExtension", "document-loaded-signal", testDocumentLoadedSignal);
WebViewTest::add("WebKitWebView", "web-process-crashed", testWebKitWebViewProcessCrashed);
WebViewTest::add("WebKitWebExtension", "window-object-cleared", testWebExtensionWindowObjectCleared);
WebViewTest::add("WebKitWebExtension", "isolated-world", testWebExtensionIsolatedWorld);
+ WebViewTest::add("WebKitWebView", "install-missing-plugins-permission-request", testInstallMissingPluginsPermissionRequest);
}
void afterAll()
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitAccessibility.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitAccessibility.cpp
index a5d8df9de..ea4a8125f 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitAccessibility.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitAccessibility.cpp
@@ -33,8 +33,8 @@ extern "C" {
#include <signal.h>
#include <unistd.h>
#include <wtf/PassRefPtr.h>
-#include <wtf/gobject/GRefPtr.h>
-#include <wtf/gobject/GUniquePtr.h>
+#include <wtf/glib/GRefPtr.h>
+#include <wtf/glib/GUniquePtr.h>
// Name of the test server application creating the webView object.
static const char* kTestServerAppName = "AccessibilityTestServer";
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFaviconDatabase.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFaviconDatabase.cpp
index 0f5a82042..8d5be9250 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFaviconDatabase.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFaviconDatabase.cpp
@@ -23,21 +23,19 @@
#include "WebViewTest.h"
#include <glib/gstdio.h>
#include <libsoup/soup.h>
-#include <wtf/gobject/GUniquePtr.h>
+#include <wtf/glib/GUniquePtr.h>
static WebKitTestServer* kServer;
-static char* kTempDirectory;
class FaviconDatabaseTest: public WebViewTest {
public:
MAKE_GLIB_TEST_FIXTURE(FaviconDatabaseTest);
FaviconDatabaseTest()
- : m_webContext(webkit_web_context_get_default())
- , m_favicon(0)
+ : m_favicon(nullptr)
, m_faviconNotificationReceived(false)
{
- WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(m_webContext);
+ WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(m_webContext.get());
g_signal_connect(database, "favicon-changed", G_CALLBACK(faviconChangedCallback), this);
}
@@ -46,7 +44,7 @@ public:
if (m_favicon)
cairo_surface_destroy(m_favicon);
- WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(m_webContext);
+ WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(m_webContext.get());
g_signal_handlers_disconnect_matched(database, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
}
@@ -67,7 +65,7 @@ public:
static void getFaviconCallback(GObject* sourceObject, GAsyncResult* result, void* data)
{
FaviconDatabaseTest* test = static_cast<FaviconDatabaseTest*>(data);
- WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(test->m_webContext);
+ WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(test->m_webContext.get());
test->m_favicon = webkit_favicon_database_get_favicon_finish(database, result, &test->m_error.outPtr());
test->quitMainLoop();
}
@@ -87,12 +85,11 @@ public:
m_favicon = 0;
}
- WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(m_webContext);
+ WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(m_webContext.get());
webkit_favicon_database_get_favicon(database, pageURI, 0, getFaviconCallback, this);
g_main_loop_run(m_mainLoop);
}
- WebKitWebContext* m_webContext;
cairo_surface_t* m_favicon;
CString m_faviconURI;
GUniqueOutPtr<GError> m_error;
@@ -116,7 +113,7 @@ serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHash
char* contents;
gsize length;
if (g_str_equal(path, "/icon/favicon.ico")) {
- GUniquePtr<char> pathToFavicon(g_build_filename(Test::getWebKit1TestResoucesDir().data(), "blank.ico", NULL));
+ GUniquePtr<char> pathToFavicon(g_build_filename(Test::getResourcesDir().data(), "blank.ico", nullptr));
g_file_get_contents(pathToFavicon.get(), &contents, &length, 0);
soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, contents, length);
} else if (g_str_equal(path, "/nofavicon")) {
@@ -142,13 +139,13 @@ static void testNotInitialized(FaviconDatabaseTest* test)
static void testSetDirectory(FaviconDatabaseTest* test)
{
- webkit_web_context_set_favicon_database_directory(test->m_webContext, kTempDirectory);
- g_assert_cmpstr(kTempDirectory, ==, webkit_web_context_get_favicon_database_directory(test->m_webContext));
+ webkit_web_context_set_favicon_database_directory(test->m_webContext.get(), Test::dataDirectory());
+ g_assert_cmpstr(Test::dataDirectory(), ==, webkit_web_context_get_favicon_database_directory(test->m_webContext.get()));
}
static void testClearDatabase(FaviconDatabaseTest* test)
{
- WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(test->m_webContext);
+ WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(test->m_webContext.get());
webkit_favicon_database_clear(database);
GUniquePtr<char> iconURI(webkit_favicon_database_get_favicon_uri(database, kServer->getURIForPath("/foo").data()));
@@ -198,7 +195,7 @@ static void testGetFavicon(FaviconDatabaseTest* test)
static void testGetFaviconURI(FaviconDatabaseTest* test)
{
- WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(test->m_webContext);
+ WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(test->m_webContext.get());
CString baseURI = kServer->getURIForPath("/foo");
GUniquePtr<char> iconURI(webkit_favicon_database_get_favicon_uri(database, baseURI.data()));
@@ -243,30 +240,11 @@ void beforeAll()
kServer = new WebKitTestServer();
kServer->run(serverCallback);
- kTempDirectory = g_dir_make_tmp("WebKit2Tests-XXXXXX", 0);
- g_assert(kTempDirectory);
-
// Add tests to the suite.
FaviconDatabaseTest::add("WebKitFaviconDatabase", "favicon-database-test", testFaviconDatabase);
}
-static void webkitFaviconDatabaseFinalizedCallback(gpointer, GObject*)
-{
- if (!g_file_test(kTempDirectory, G_FILE_TEST_IS_DIR))
- return;
-
- GUniquePtr<char> filename(g_build_filename(kTempDirectory, "WebpageIcons.db", nullptr));
- g_unlink(filename.get());
-
- g_rmdir(kTempDirectory);
-}
-
void afterAll()
{
delete kServer;
-
- // Delete the temporary files after the IconDatabase has been
- // closed, that is, once WebKitFaviconDatabase is being destroyed.
- WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(webkit_web_context_get_default());
- g_object_weak_ref(G_OBJECT(database), webkitFaviconDatabaseFinalizedCallback, 0);
}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFindController.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFindController.cpp
index d2eef4ca4..7289fd37f 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFindController.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFindController.cpp
@@ -22,7 +22,7 @@
#include "LoadTrackingTest.h"
#include <gtk/gtk.h>
#include <webkit2/webkit2.h>
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
static const char* testString = "<html><body>first testing second testing secondHalf</body></html>";
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitPolicyClient.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitPolicyClient.cpp
index 209ea045e..9f9515123 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitPolicyClient.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitPolicyClient.cpp
@@ -21,7 +21,7 @@
#include "LoadTrackingTest.h"
#include "WebKitTestServer.h"
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
#include <wtf/text/CString.h>
static WebKitTestServer* kServer;
@@ -117,11 +117,12 @@ static void testNavigationPolicy(PolicyClientTest* test, gconstpointer)
// Ideally we'd like to have a more intensive test here, but it's still pretty tricky
// to trigger different types of navigations with the GTK+ WebKit2 API.
WebKitNavigationPolicyDecision* decision = WEBKIT_NAVIGATION_POLICY_DECISION(test->m_previousPolicyDecision.get());
- g_assert_cmpint(webkit_navigation_policy_decision_get_navigation_type(decision), ==, WEBKIT_NAVIGATION_TYPE_OTHER);
- g_assert_cmpint(webkit_navigation_policy_decision_get_mouse_button(decision), ==, 0);
- g_assert_cmpint(webkit_navigation_policy_decision_get_modifiers(decision), ==, 0);
- g_assert_cmpstr(webkit_navigation_policy_decision_get_frame_name(decision), ==, 0);
- WebKitURIRequest* request = webkit_navigation_policy_decision_get_request(decision);
+ WebKitNavigationAction* navigationAction = webkit_navigation_policy_decision_get_navigation_action(decision);
+ g_assert_cmpint(webkit_navigation_action_get_navigation_type(navigationAction), ==, WEBKIT_NAVIGATION_TYPE_OTHER);
+ g_assert_cmpint(webkit_navigation_action_get_mouse_button(navigationAction), ==, 0);
+ g_assert_cmpint(webkit_navigation_action_get_modifiers(navigationAction), ==, 0);
+ g_assert(!webkit_navigation_policy_decision_get_frame_name(decision));
+ WebKitURIRequest* request = webkit_navigation_action_get_request(navigationAction);
g_assert_cmpstr(webkit_uri_request_get_uri(request), ==, "http://webkitgtk.org/");
test->m_policyDecisionResponse = PolicyClientTest::Use;
@@ -191,7 +192,7 @@ struct CreateCallbackData {
GMainLoop* mainLoop;
};
-static WebKitWebView* createCallback(WebKitWebView* webView, CreateCallbackData* data)
+static WebKitWebView* createCallback(WebKitWebView* webView, WebKitNavigationAction*, CreateCallbackData* data)
{
data->triedToOpenWindow = true;
g_main_loop_quit(data->mainLoop);
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitSettings.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitSettings.cpp
index fb1091889..b3a377270 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitSettings.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitSettings.cpp
@@ -35,7 +35,7 @@
#include "WebKitTestServer.h"
#include <gtk/gtk.h>
#include <webkit2/webkit2.h>
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
static WebKitTestServer* gServer;
@@ -273,6 +273,11 @@ static void testWebKitSettings(Test*, gconstpointer)
webkit_settings_set_enable_mediasource(settings, TRUE);
g_assert(webkit_settings_get_enable_mediasource(settings));
+ // File access from file URLs is not allowed by default.
+ g_assert(!webkit_settings_get_allow_file_access_from_file_urls(settings));
+ webkit_settings_set_allow_file_access_from_file_urls(settings, TRUE);
+ g_assert(webkit_settings_get_allow_file_access_from_file_urls(settings));
+
g_object_unref(G_OBJECT(settings));
}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitUserContentManager.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitUserContentManager.cpp
new file mode 100644
index 000000000..e84cb5c20
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitUserContentManager.cpp
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) 2013-2014 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2,1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "WebKitTestServer.h"
+#include "WebViewTest.h"
+#include <cstdarg>
+#include <gtk/gtk.h>
+#include <webkit2/webkit2.h>
+#include <wtf/glib/GRefPtr.h>
+#include <wtf/glib/GUniquePtr.h>
+
+class UserContentManagerTest : public WebViewTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(UserContentManagerTest);
+
+ UserContentManagerTest()
+ : WebViewTest(webkit_user_content_manager_new())
+ {
+ // A reference is leaked when passing the result of webkit_user_content_manager_new()
+ // directly to webkit_web_view_new_with_user_content_manager() above. Adopting the
+ // reference here avoids the leak.
+ m_userContentManager = adoptGRef(webkit_web_view_get_user_content_manager(m_webView));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_userContentManager.get()));
+ }
+
+ GRefPtr<WebKitUserContentManager> m_userContentManager;
+};
+
+static WebKitTestServer* kServer;
+
+// These are all here so that they can be changed easily, if necessary.
+static const char* kStyleSheetHTML = "<html><div id=\"styledElement\">Sweet stylez!</div></html>";
+static const char* kInjectedStyleSheet = "#styledElement { font-weight: bold; }";
+static const char* kStyleSheetTestScript = "getComputedStyle(document.getElementById('styledElement'))['font-weight']";
+static const char* kStyleSheetTestScriptResult = "bold";
+static const char* kInjectedScript = "document.write('<div id=\"item\">Generated by a script</div>')";
+static const char* kScriptTestScript = "document.getElementById('item').innerText";
+static const char* kScriptTestScriptResult = "Generated by a script";
+
+static void testWebViewNewWithUserContentManager(Test* test, gconstpointer)
+{
+ GRefPtr<WebKitUserContentManager> userContentManager1 = adoptGRef(webkit_user_content_manager_new());
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(userContentManager1.get()));
+ GRefPtr<WebKitWebView> webView1 = WEBKIT_WEB_VIEW(webkit_web_view_new_with_user_content_manager(userContentManager1.get()));
+ g_assert(webkit_web_view_get_user_content_manager(webView1.get()) == userContentManager1.get());
+
+ GRefPtr<WebKitWebView> webView2 = WEBKIT_WEB_VIEW(webkit_web_view_new());
+ g_assert(webkit_web_view_get_user_content_manager(webView2.get()) != userContentManager1.get());
+}
+
+static bool isStyleSheetInjectedForURLAtPath(WebViewTest* test, const char* path)
+{
+ test->loadURI(kServer->getURIForPath(path).data());
+ test->waitUntilLoadFinished();
+
+ GUniqueOutPtr<GError> error;
+ WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished(kStyleSheetTestScript, &error.outPtr());
+ g_assert(javascriptResult);
+ g_assert(!error.get());
+
+ GUniquePtr<char> resultString(WebViewTest::javascriptResultToCString(javascriptResult));
+ return !g_strcmp0(resultString.get(), kStyleSheetTestScriptResult);
+}
+
+static bool isScriptInjectedForURLAtPath(WebViewTest* test, const char* path)
+{
+ test->loadURI(kServer->getURIForPath(path).data());
+ test->waitUntilLoadFinished();
+
+ GUniqueOutPtr<GError> error;
+ if (WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished(kScriptTestScript, &error.outPtr())) {
+ g_assert(!error.get());
+
+ GUniquePtr<char> resultString(WebViewTest::javascriptResultToCString(javascriptResult));
+ return !g_strcmp0(resultString.get(), kScriptTestScriptResult);
+ }
+ return false;
+}
+
+static void fillURLListFromPaths(char** list, const char* path, ...)
+{
+ va_list argumentList;
+ va_start(argumentList, path);
+
+ int i = 0;
+ while (path) {
+ // FIXME: We must use a wildcard for the host here until http://wkbug.com/112476 is fixed.
+ // Until that time patterns with port numbers in them will not properly match URLs with port numbers.
+ list[i++] = g_strdup_printf("http://*/%s*", path);
+ path = va_arg(argumentList, const char*);
+ }
+}
+
+static void removeOldInjectedContentAndResetLists(WebKitUserContentManager* userContentManager, char** whitelist, char** blacklist)
+{
+ webkit_user_content_manager_remove_all_style_sheets(userContentManager);
+ webkit_user_content_manager_remove_all_scripts(userContentManager);
+
+ while (*whitelist) {
+ g_free(*whitelist);
+ *whitelist = 0;
+ whitelist++;
+ }
+
+ while (*blacklist) {
+ g_free(*blacklist);
+ *blacklist = 0;
+ blacklist++;
+ }
+}
+
+static void testUserContentManagerInjectedStyleSheet(UserContentManagerTest* test, gconstpointer)
+{
+ char* whitelist[3] = { 0, 0, 0 };
+ char* blacklist[3] = { 0, 0, 0 };
+
+ removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist);
+
+ // Without a whitelist or a blacklist all URLs should have the injected style sheet.
+ static const char* randomPath = "somerandompath";
+ g_assert(!isStyleSheetInjectedForURLAtPath(test, randomPath));
+ WebKitUserStyleSheet* styleSheet = webkit_user_style_sheet_new(kInjectedStyleSheet, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_STYLE_LEVEL_USER, nullptr, nullptr);
+ webkit_user_content_manager_add_style_sheet(test->m_userContentManager.get(), styleSheet);
+ webkit_user_style_sheet_unref(styleSheet);
+ g_assert(isStyleSheetInjectedForURLAtPath(test, randomPath));
+
+ removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist);
+
+ fillURLListFromPaths(blacklist, randomPath, 0);
+ styleSheet = webkit_user_style_sheet_new(kInjectedStyleSheet, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_STYLE_LEVEL_USER, nullptr, blacklist);
+ webkit_user_content_manager_add_style_sheet(test->m_userContentManager.get(), styleSheet);
+ webkit_user_style_sheet_unref(styleSheet);
+ g_assert(!isStyleSheetInjectedForURLAtPath(test, randomPath));
+ g_assert(isStyleSheetInjectedForURLAtPath(test, "someotherrandompath"));
+
+ removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist);
+
+ static const char* inTheWhiteList = "inthewhitelist";
+ static const char* notInWhitelist = "notinthewhitelist";
+ static const char* inTheWhiteListAndBlackList = "inthewhitelistandblacklist";
+
+ fillURLListFromPaths(whitelist, inTheWhiteList, inTheWhiteListAndBlackList, 0);
+ fillURLListFromPaths(blacklist, inTheWhiteListAndBlackList, 0);
+ styleSheet = webkit_user_style_sheet_new(kInjectedStyleSheet, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_STYLE_LEVEL_USER, whitelist, blacklist);
+ webkit_user_content_manager_add_style_sheet(test->m_userContentManager.get(), styleSheet);
+ webkit_user_style_sheet_unref(styleSheet);
+ g_assert(isStyleSheetInjectedForURLAtPath(test, inTheWhiteList));
+ g_assert(!isStyleSheetInjectedForURLAtPath(test, inTheWhiteListAndBlackList));
+ g_assert(!isStyleSheetInjectedForURLAtPath(test, notInWhitelist));
+
+ // It's important to clean up the environment before other tests.
+ removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist);
+}
+
+static void testUserContentManagerInjectedScript(UserContentManagerTest* test, gconstpointer)
+{
+ char* whitelist[3] = { 0, 0, 0 };
+ char* blacklist[3] = { 0, 0, 0 };
+
+ removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist);
+
+ // Without a whitelist or a blacklist all URLs should have the injected script.
+ static const char* randomPath = "somerandompath";
+ g_assert(!isScriptInjectedForURLAtPath(test, randomPath));
+ WebKitUserScript* script = webkit_user_script_new(kInjectedScript, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_END, nullptr, nullptr);
+ webkit_user_content_manager_add_script(test->m_userContentManager.get(), script);
+ webkit_user_script_unref(script);
+ g_assert(isScriptInjectedForURLAtPath(test, randomPath));
+
+ removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist);
+
+ fillURLListFromPaths(blacklist, randomPath, 0);
+ script = webkit_user_script_new(kInjectedScript, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_END, nullptr, blacklist);
+ webkit_user_content_manager_add_script(test->m_userContentManager.get(), script);
+ webkit_user_script_unref(script);
+ g_assert(!isScriptInjectedForURLAtPath(test, randomPath));
+ g_assert(isScriptInjectedForURLAtPath(test, "someotherrandompath"));
+
+ removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist);
+
+ static const char* inTheWhiteList = "inthewhitelist";
+ static const char* notInWhitelist = "notinthewhitelist";
+ static const char* inTheWhiteListAndBlackList = "inthewhitelistandblacklist";
+
+ fillURLListFromPaths(whitelist, inTheWhiteList, inTheWhiteListAndBlackList, 0);
+ fillURLListFromPaths(blacklist, inTheWhiteListAndBlackList, 0);
+ script = webkit_user_script_new(kInjectedScript, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_END, whitelist, blacklist);
+ webkit_user_content_manager_add_script(test->m_userContentManager.get(), script);
+ webkit_user_script_unref(script);
+ g_assert(isScriptInjectedForURLAtPath(test, inTheWhiteList));
+ g_assert(!isScriptInjectedForURLAtPath(test, inTheWhiteListAndBlackList));
+ g_assert(!isScriptInjectedForURLAtPath(test, notInWhitelist));
+
+ // It's important to clean up the environment before other tests.
+ removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist);
+}
+
+class UserScriptMessageTest : public UserContentManagerTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(UserScriptMessageTest);
+
+ UserScriptMessageTest()
+ : UserContentManagerTest()
+ , m_userScriptMessage(nullptr)
+ {
+ }
+
+ ~UserScriptMessageTest()
+ {
+ if (m_userScriptMessage)
+ webkit_javascript_result_unref(m_userScriptMessage);
+ }
+
+ bool registerHandler(const char* handlerName)
+ {
+ return webkit_user_content_manager_register_script_message_handler(m_userContentManager.get(), handlerName);
+ }
+
+ void unregisterHandler(const char* handlerName)
+ {
+ webkit_user_content_manager_unregister_script_message_handler(m_userContentManager.get(), handlerName);
+ }
+
+ static void scriptMessageReceived(WebKitUserContentManager* userContentManager, WebKitJavascriptResult* jsResult, UserScriptMessageTest* test)
+ {
+ g_signal_handlers_disconnect_by_func(userContentManager, reinterpret_cast<gpointer>(scriptMessageReceived), test);
+ g_main_loop_quit(test->m_mainLoop);
+
+ g_assert(!test->m_userScriptMessage);
+ test->m_userScriptMessage = webkit_javascript_result_ref(jsResult);
+ }
+
+ WebKitJavascriptResult* waitUntilMessageReceived(const char* handlerName)
+ {
+ if (m_userScriptMessage) {
+ webkit_javascript_result_unref(m_userScriptMessage);
+ m_userScriptMessage = nullptr;
+ }
+
+ GUniquePtr<char> signalName(g_strdup_printf("script-message-received::%s", handlerName));
+ g_signal_connect(m_userContentManager.get(), signalName.get(), G_CALLBACK(scriptMessageReceived), this);
+
+ g_main_loop_run(m_mainLoop);
+ g_assert(m_userScriptMessage);
+ return m_userScriptMessage;
+ }
+
+ WebKitJavascriptResult* postMessageAndWaitUntilReceived(const char* handlerName, const char* javascriptValueAsText)
+ {
+ GUniquePtr<char> javascriptSnippet(g_strdup_printf("window.webkit.messageHandlers.%s.postMessage(%s);", handlerName, javascriptValueAsText));
+ webkit_web_view_run_javascript(m_webView, javascriptSnippet.get(), nullptr, nullptr, nullptr);
+ return waitUntilMessageReceived(handlerName);
+ }
+
+private:
+ WebKitJavascriptResult* m_userScriptMessage;
+};
+
+static void testUserContentManagerScriptMessageReceived(UserScriptMessageTest* test, gconstpointer)
+{
+ g_assert(test->registerHandler("msg"));
+
+ // Trying to register the same handler a second time must fail.
+ g_assert(!test->registerHandler("msg"));
+
+ test->loadHtml("<html></html>", nullptr);
+ test->waitUntilLoadFinished();
+
+ // Check that the "window.webkit.messageHandlers" namespace exists.
+ GUniqueOutPtr<GError> error;
+ WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.webkit.messageHandlers ? 'y' : 'n';", &error.outPtr());
+ g_assert(javascriptResult);
+ g_assert(!error.get());
+ GUniquePtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult));
+ g_assert_cmpstr(valueString.get(), ==, "y");
+
+ // Check that the "document.webkit.messageHandlers.msg" namespace exists.
+ javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.webkit.messageHandlers.msg ? 'y' : 'n';", &error.outPtr());
+ g_assert(javascriptResult);
+ g_assert(!error.get());
+ valueString.reset(WebViewTest::javascriptResultToCString(javascriptResult));
+ g_assert_cmpstr(valueString.get(), ==, "y");
+
+ valueString.reset(WebViewTest::javascriptResultToCString(test->postMessageAndWaitUntilReceived("msg", "'user message'")));
+ g_assert_cmpstr(valueString.get(), ==, "user message");
+
+ // Messages should arrive despite of other handlers being registered.
+ g_assert(test->registerHandler("anotherHandler"));
+
+ // Check that the "document.webkit.messageHandlers.msg" namespace still exists.
+ javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.webkit.messageHandlers.msg ? 'y' : 'n';", &error.outPtr());
+ g_assert(javascriptResult);
+ g_assert(!error.get());
+ valueString.reset(WebViewTest::javascriptResultToCString(javascriptResult));
+ g_assert_cmpstr(valueString.get(), ==, "y");
+
+ // Check that the "document.webkit.messageHandlers.anotherHandler" namespace exists.
+ javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.webkit.messageHandlers.anotherHandler ? 'y' : 'n';", &error.outPtr());
+ g_assert(javascriptResult);
+ g_assert(!error.get());
+ valueString.reset(WebViewTest::javascriptResultToCString(javascriptResult));
+ g_assert_cmpstr(valueString.get(), ==, "y");
+
+ valueString.reset(WebViewTest::javascriptResultToCString(test->postMessageAndWaitUntilReceived("msg", "'handler: msg'")));
+ g_assert_cmpstr(valueString.get(), ==, "handler: msg");
+
+ valueString.reset(WebViewTest::javascriptResultToCString(test->postMessageAndWaitUntilReceived("anotherHandler", "'handler: anotherHandler'")));
+ g_assert_cmpstr(valueString.get(), ==, "handler: anotherHandler");
+
+ // Unregistering a handler and re-registering again under the same name should work.
+ test->unregisterHandler("msg");
+
+ javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.webkit.messageHandlers.msg.postMessage('42');", &error.outPtr());
+ g_assert(!javascriptResult);
+ g_assert(error.get());
+
+ // Re-registering a handler that has been unregistered must work
+ g_assert(test->registerHandler("msg"));
+ valueString.reset(WebViewTest::javascriptResultToCString(test->postMessageAndWaitUntilReceived("msg", "'handler: msg'")));
+ g_assert_cmpstr(valueString.get(), ==, "handler: msg");
+
+ test->unregisterHandler("anotherHandler");
+}
+
+static void testUserContentManagerScriptMessageFromDOMBindings(UserScriptMessageTest* test, gconstpointer)
+{
+ g_assert(test->registerHandler("dom"));
+
+ test->loadHtml("<html>1</html>", nullptr);
+ WebKitJavascriptResult* javascriptResult = test->waitUntilMessageReceived("dom");
+ g_assert(javascriptResult);
+ GUniquePtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult));
+ g_assert_cmpstr(valueString.get(), ==, "DocumentLoaded");
+
+ test->unregisterHandler("dom");
+
+ g_assert(test->registerHandler("dom-convenience"));
+
+ test->loadHtml("<html>2</html>", nullptr);
+ javascriptResult = test->waitUntilMessageReceived("dom-convenience");
+ g_assert(javascriptResult);
+ valueString.reset(WebViewTest::javascriptResultToCString(javascriptResult));
+ g_assert_cmpstr(valueString.get(), ==, "DocumentLoaded");
+
+ test->unregisterHandler("dom-convenience");
+}
+
+static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer)
+{
+ soup_message_set_status(message, SOUP_STATUS_OK);
+ soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, kStyleSheetHTML, strlen(kStyleSheetHTML));
+ soup_message_body_complete(message->response_body);
+}
+
+void beforeAll()
+{
+ kServer = new WebKitTestServer();
+ kServer->run(serverCallback);
+
+ Test::add("WebKitWebView", "new-with-user-content-manager", testWebViewNewWithUserContentManager);
+ UserContentManagerTest::add("WebKitUserContentManager", "injected-style-sheet", testUserContentManagerInjectedStyleSheet);
+ UserContentManagerTest::add("WebKitUserContentManager", "injected-script", testUserContentManagerInjectedScript);
+ UserScriptMessageTest::add("WebKitUserContentManager", "script-message-received", testUserContentManagerScriptMessageReceived);
+ UserScriptMessageTest::add("WebKitUserContentManager", "script-message-from-dom-bindings", testUserContentManagerScriptMessageFromDOMBindings);
+}
+
+void afterAll()
+{
+ delete kServer;
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebContext.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebContext.cpp
index 74e8d6817..2d1d216f4 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebContext.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebContext.cpp
@@ -24,8 +24,9 @@
#include <gtk/gtk.h>
#include <webkit2/webkit2.h>
#include <wtf/HashMap.h>
-#include <wtf/gobject/GRefPtr.h>
-#include <wtf/gobject/GUniquePtr.h>
+#include <wtf/glib/GRefPtr.h>
+#include <wtf/glib/GUniquePtr.h>
+#include <wtf/text/StringBuilder.h>
#include <wtf/text/StringHash.h>
static WebKitTestServer* kServer;
@@ -34,6 +35,89 @@ static void testWebContextDefault(Test* test, gconstpointer)
{
// Check there's a single instance of the default web context.
g_assert(webkit_web_context_get_default() == webkit_web_context_get_default());
+ g_assert(webkit_web_context_get_default() != test->m_webContext.get());
+}
+
+static void testWebContextConfiguration(WebViewTest* test, gconstpointer)
+{
+ WebKitWebsiteDataManager* manager = webkit_web_context_get_website_data_manager(test->m_webContext.get());
+ g_assert(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager));
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(manager));
+
+ // Base directories are not used by TestMain.
+ g_assert(!webkit_website_data_manager_get_base_data_directory(manager));
+ g_assert(!webkit_website_data_manager_get_base_cache_directory(manager));
+
+ GUniquePtr<char> localStorageDirectory(g_build_filename(Test::dataDirectory(), "local-storage", nullptr));
+ g_assert_cmpstr(localStorageDirectory.get(), ==, webkit_website_data_manager_get_local_storage_directory(manager));
+ g_assert(g_file_test(localStorageDirectory.get(), G_FILE_TEST_IS_DIR));
+
+ test->loadURI(kServer->getURIForPath("/empty").data());
+ test->waitUntilLoadFinished();
+ test->runJavaScriptAndWaitUntilFinished("window.indexedDB.open('TestDatabase');", nullptr);
+ GUniquePtr<char> indexedDBDirectory(g_build_filename(Test::dataDirectory(), "indexeddb", nullptr));
+ g_assert_cmpstr(indexedDBDirectory.get(), ==, webkit_website_data_manager_get_indexeddb_directory(manager));
+ g_assert(g_file_test(indexedDBDirectory.get(), G_FILE_TEST_IS_DIR));
+
+ test->loadURI(kServer->getURIForPath("/appcache").data());
+ test->waitUntilLoadFinished();
+ GUniquePtr<char> applicationCacheDirectory(g_build_filename(Test::dataDirectory(), "appcache", nullptr));
+ g_assert_cmpstr(applicationCacheDirectory.get(), ==, webkit_website_data_manager_get_offline_application_cache_directory(manager));
+ GUniquePtr<char> applicationCacheDatabase(g_build_filename(applicationCacheDirectory.get(), "ApplicationCache.db", nullptr));
+ unsigned triesCount = 4;
+ while (!g_file_test(applicationCacheDatabase.get(), G_FILE_TEST_IS_REGULAR) && --triesCount)
+ test->wait(0.25);
+ g_assert(triesCount);
+
+
+ GUniquePtr<char> webSQLDirectory(g_build_filename(Test::dataDirectory(), "websql", nullptr));
+ g_assert_cmpstr(webSQLDirectory.get(), ==, webkit_website_data_manager_get_websql_directory(manager));
+ test->runJavaScriptAndWaitUntilFinished("db = openDatabase(\"TestDatabase\", \"1.0\", \"TestDatabase\", 1);", nullptr);
+ g_assert(g_file_test(webSQLDirectory.get(), G_FILE_TEST_IS_DIR));
+
+ GUniquePtr<char> diskCacheDirectory(g_build_filename(Test::dataDirectory(), "disk-cache", nullptr));
+ g_assert_cmpstr(diskCacheDirectory.get(), ==, webkit_website_data_manager_get_disk_cache_directory(manager));
+ g_assert(g_file_test(diskCacheDirectory.get(), G_FILE_TEST_IS_DIR));
+
+ // The default context should have a different manager with different configuration.
+ WebKitWebsiteDataManager* defaultManager = webkit_web_context_get_website_data_manager(webkit_web_context_get_default());
+ g_assert(WEBKIT_IS_WEBSITE_DATA_MANAGER(defaultManager));
+ g_assert(manager != defaultManager);
+ g_assert_cmpstr(webkit_website_data_manager_get_local_storage_directory(manager), !=, webkit_website_data_manager_get_local_storage_directory(defaultManager));
+ g_assert_cmpstr(webkit_website_data_manager_get_indexeddb_directory(manager), !=, webkit_website_data_manager_get_indexeddb_directory(defaultManager));
+ g_assert_cmpstr(webkit_website_data_manager_get_disk_cache_directory(manager), !=, webkit_website_data_manager_get_disk_cache_directory(defaultManager));
+ g_assert_cmpstr(webkit_website_data_manager_get_offline_application_cache_directory(manager), !=, webkit_website_data_manager_get_offline_application_cache_directory(defaultManager));
+ g_assert_cmpstr(webkit_website_data_manager_get_websql_directory(manager), !=, webkit_website_data_manager_get_websql_directory(defaultManager));
+
+ // Using Test::dataDirectory() we get the default configuration but for a differrent prefix.
+ GRefPtr<WebKitWebsiteDataManager> baseDataManager = adoptGRef(webkit_website_data_manager_new("base-data-directory", Test::dataDirectory(), "base-cache-directory", Test::dataDirectory(), nullptr));
+ g_assert(WEBKIT_IS_WEBSITE_DATA_MANAGER(baseDataManager.get()));
+
+ localStorageDirectory.reset(g_build_filename(Test::dataDirectory(), "localstorage", nullptr));
+ g_assert_cmpstr(webkit_website_data_manager_get_local_storage_directory(baseDataManager.get()), ==, localStorageDirectory.get());
+
+ indexedDBDirectory.reset(g_build_filename(Test::dataDirectory(), "databases", "indexeddb", nullptr));
+ g_assert_cmpstr(webkit_website_data_manager_get_indexeddb_directory(baseDataManager.get()), ==, indexedDBDirectory.get());
+
+ applicationCacheDirectory.reset(g_build_filename(Test::dataDirectory(), "applications", nullptr));
+ g_assert_cmpstr(webkit_website_data_manager_get_offline_application_cache_directory(baseDataManager.get()), ==, applicationCacheDirectory.get());
+
+ webSQLDirectory.reset(g_build_filename(Test::dataDirectory(), "databases", nullptr));
+ g_assert_cmpstr(webkit_website_data_manager_get_websql_directory(baseDataManager.get()), ==, webSQLDirectory.get());
+
+ g_assert_cmpstr(webkit_website_data_manager_get_disk_cache_directory(baseDataManager.get()), ==, Test::dataDirectory());
+
+ // Any specific configuration provided takes precedence over base dirs.
+ indexedDBDirectory.reset(g_build_filename(Test::dataDirectory(), "mycustomindexeddb", nullptr));
+ applicationCacheDirectory.reset(g_build_filename(Test::dataDirectory(), "mycustomappcache", nullptr));
+ baseDataManager = adoptGRef(webkit_website_data_manager_new("base-data-directory", Test::dataDirectory(), "base-cache-directory", Test::dataDirectory(),
+ "indexeddb-directory", indexedDBDirectory.get(), "offline-application-cache-directory", applicationCacheDirectory.get(), nullptr));
+ g_assert_cmpstr(webkit_website_data_manager_get_indexeddb_directory(baseDataManager.get()), ==, indexedDBDirectory.get());
+ g_assert_cmpstr(webkit_website_data_manager_get_offline_application_cache_directory(baseDataManager.get()), ==, applicationCacheDirectory.get());
+ // The resutl should be the same as previous manager.
+ g_assert_cmpstr(webkit_website_data_manager_get_local_storage_directory(baseDataManager.get()), ==, localStorageDirectory.get());
+ g_assert_cmpstr(webkit_website_data_manager_get_websql_directory(baseDataManager.get()), ==, webSQLDirectory.get());
+ g_assert_cmpstr(webkit_website_data_manager_get_disk_cache_directory(baseDataManager.get()), ==, Test::dataDirectory());
}
class PluginsTest: public Test {
@@ -41,11 +125,10 @@ public:
MAKE_GLIB_TEST_FIXTURE(PluginsTest);
PluginsTest()
- : m_context(webkit_web_context_get_default())
- , m_mainLoop(g_main_loop_new(0, TRUE))
- , m_plugins(0)
+ : m_mainLoop(g_main_loop_new(nullptr, TRUE))
+ , m_plugins(nullptr)
{
- webkit_web_context_set_additional_plugins_directory(m_context, WEBKIT_TEST_PLUGIN_DIR);
+ webkit_web_context_set_additional_plugins_directory(m_webContext.get(), WEBKIT_TEST_PLUGIN_DIR);
}
~PluginsTest()
@@ -56,19 +139,18 @@ public:
static void getPluginsAsyncReadyCallback(GObject*, GAsyncResult* result, PluginsTest* test)
{
- test->m_plugins = webkit_web_context_get_plugins_finish(test->m_context, result, 0);
+ test->m_plugins = webkit_web_context_get_plugins_finish(test->m_webContext.get(), result, nullptr);
g_main_loop_quit(test->m_mainLoop);
}
GList* getPlugins()
{
g_list_free_full(m_plugins, g_object_unref);
- webkit_web_context_get_plugins(m_context, 0, reinterpret_cast<GAsyncReadyCallback>(getPluginsAsyncReadyCallback), this);
+ webkit_web_context_get_plugins(m_webContext.get(), nullptr, reinterpret_cast<GAsyncReadyCallback>(getPluginsAsyncReadyCallback), this);
g_main_loop_run(m_mainLoop);
return m_plugins;
}
- WebKitWebContext* m_context;
GMainLoop* m_mainLoop;
GList* m_plugins;
};
@@ -116,7 +198,10 @@ static const char* kBarHTML = "<html><body>Bar</body></html>";
static const char* kEchoHTMLFormat = "<html><body>%s</body></html>";
static const char* errorDomain = "test";
static const int errorCode = 10;
-static const char* errorMessage = "Error message.";
+
+static const char* genericErrorMessage = "Error message.";
+static const char* beforeReceiveResponseErrorMessage = "Error before didReceiveResponse.";
+static const char* afterInitialChunkErrorMessage = "Error after reading the initial chunk.";
class URISchemeTest: public LoadTrackingTest {
public:
@@ -148,23 +233,38 @@ public:
g_assert(webkit_uri_scheme_request_get_web_view(request) == test->m_webView);
- GRefPtr<GInputStream> inputStream = adoptGRef(g_memory_input_stream_new());
- test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(inputStream.get()));
-
const char* scheme = webkit_uri_scheme_request_get_scheme(request);
g_assert(scheme);
g_assert(test->m_handlersMap.contains(String::fromUTF8(scheme)));
+ const URISchemeHandler& handler = test->m_handlersMap.get(String::fromUTF8(scheme));
+
+ GRefPtr<GInputStream> inputStream = adoptGRef(g_memory_input_stream_new());
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(inputStream.get()));
+
+ const gchar* requestPath = webkit_uri_scheme_request_get_path(request);
+
if (!g_strcmp0(scheme, "error")) {
- GUniquePtr<GError> error(g_error_new_literal(g_quark_from_string(errorDomain), errorCode, errorMessage));
- webkit_uri_scheme_request_finish_error(request, error.get());
+ if (!g_strcmp0(requestPath, "before-response")) {
+ GUniquePtr<GError> error(g_error_new_literal(g_quark_from_string(errorDomain), errorCode, beforeReceiveResponseErrorMessage));
+ // We call finish() and then finish_error() to make sure that not even
+ // the didReceiveResponse message is processed at the time of failing.
+ webkit_uri_scheme_request_finish(request, G_INPUT_STREAM(inputStream.get()), handler.replyLength, handler.mimeType.data());
+ webkit_uri_scheme_request_finish_error(request, error.get());
+ } else if (!g_strcmp0(requestPath, "after-first-chunk")) {
+ g_memory_input_stream_add_data(G_MEMORY_INPUT_STREAM(inputStream.get()), handler.reply.data(), handler.reply.length(), 0);
+ webkit_uri_scheme_request_finish(request, inputStream.get(), handler.replyLength, handler.mimeType.data());
+ // We need to wait until we reach the load-committed state before calling webkit_uri_scheme_request_finish_error(),
+ // so we rely on the test using finishOnCommittedAndWaitUntilLoadFinished() to actually call it from loadCommitted().
+ } else {
+ GUniquePtr<GError> error(g_error_new_literal(g_quark_from_string(errorDomain), errorCode, genericErrorMessage));
+ webkit_uri_scheme_request_finish_error(request, error.get());
+ }
return;
}
- const URISchemeHandler& handler = test->m_handlersMap.get(String::fromUTF8(scheme));
-
if (!g_strcmp0(scheme, "echo")) {
- char* replyHTML = g_strdup_printf(handler.reply.data(), webkit_uri_scheme_request_get_path(request));
+ char* replyHTML = g_strdup_printf(handler.reply.data(), requestPath);
g_memory_input_stream_add_data(G_MEMORY_INPUT_STREAM(inputStream.get()), replyHTML, strlen(replyHTML), g_free);
} else if (!g_strcmp0(scheme, "closed"))
g_input_stream_close(inputStream.get(), 0, 0);
@@ -177,13 +277,58 @@ public:
void registerURISchemeHandler(const char* scheme, const char* reply, int replyLength, const char* mimeType)
{
m_handlersMap.set(String::fromUTF8(scheme), URISchemeHandler(reply, replyLength, mimeType));
- webkit_web_context_register_uri_scheme(webkit_web_context_get_default(), scheme, uriSchemeRequestCallback, this, 0);
+ webkit_web_context_register_uri_scheme(m_webContext.get(), scheme, uriSchemeRequestCallback, this, 0);
+ }
+
+ virtual void loadCommitted() override
+ {
+ if (m_finishOnCommitted) {
+ GUniquePtr<GError> error(g_error_new_literal(g_quark_from_string(errorDomain), errorCode, afterInitialChunkErrorMessage));
+ webkit_uri_scheme_request_finish_error(m_uriSchemeRequest.get(), error.get());
+ }
+
+ LoadTrackingTest::loadCommitted();
+ }
+
+ void finishOnCommittedAndWaitUntilLoadFinished()
+ {
+ m_finishOnCommitted = true;
+ waitUntilLoadFinished();
+ m_finishOnCommitted = false;
}
GRefPtr<WebKitURISchemeRequest> m_uriSchemeRequest;
HashMap<String, URISchemeHandler> m_handlersMap;
+ bool m_finishOnCommitted { false };
};
+String generateHTMLContent(unsigned contentLength)
+{
+ String baseString("abcdefghijklmnopqrstuvwxyz0123457890");
+ unsigned baseLength = baseString.length();
+
+ StringBuilder builder;
+ builder.append("<html><body>");
+
+ if (contentLength <= baseLength)
+ builder.append(baseString, 0, contentLength);
+ else {
+ unsigned currentLength = 0;
+ while (currentLength < contentLength) {
+ if ((currentLength + baseLength) <= contentLength)
+ builder.append(baseString);
+ else
+ builder.append(baseString, 0, contentLength - currentLength);
+
+ // Account for the 12 characters of the '<html><body>' prefix.
+ currentLength = builder.length() - 12;
+ }
+ }
+ builder.append("</body></html>");
+
+ return builder.toString();
+}
+
static void testWebContextURIScheme(URISchemeTest* test, gconstpointer)
{
test->registerURISchemeHandler("foo", kBarHTML, strlen(kBarHTML), "text/html");
@@ -203,6 +348,16 @@ static void testWebContextURIScheme(URISchemeTest* test, gconstpointer)
g_assert_cmpint(mainResourceDataSize, ==, strlen(echoHTML.get()));
g_assert(!strncmp(mainResourceData, echoHTML.get(), mainResourceDataSize));
+ test->loadURI("echo:with#fragment");
+ test->waitUntilLoadFinished();
+ g_assert_cmpstr(webkit_uri_scheme_request_get_path(test->m_uriSchemeRequest.get()), ==, "with");
+ g_assert_cmpstr(webkit_uri_scheme_request_get_uri(test->m_uriSchemeRequest.get()), ==, "echo:with#fragment");
+ echoHTML.reset(g_strdup_printf(kEchoHTMLFormat, webkit_uri_scheme_request_get_path(test->m_uriSchemeRequest.get())));
+ mainResourceDataSize = 0;
+ mainResourceData = test->mainResourceData(mainResourceDataSize);
+ g_assert_cmpint(mainResourceDataSize, ==, strlen(echoHTML.get()));
+ g_assert(!strncmp(mainResourceData, echoHTML.get(), mainResourceDataSize));
+
test->registerURISchemeHandler("nomime", kBarHTML, -1, 0);
test->m_loadEvents.clear();
test->loadURI("nomime:foo-bar");
@@ -216,14 +371,35 @@ static void testWebContextURIScheme(URISchemeTest* test, gconstpointer)
g_assert(!test->m_loadEvents.contains(LoadTrackingTest::ProvisionalLoadFailed));
g_assert(!test->m_loadEvents.contains(LoadTrackingTest::LoadFailed));
- test->registerURISchemeHandler("error", 0, 0, 0);
+ // Anything over 8192 bytes will get multiple calls to g_input_stream_read_async in
+ // WebKitURISchemeRequest when reading data, but we still need way more than that to
+ // ensure that we reach the load-committed state before failing, so we use an 8MB HTML.
+ String longHTMLContent = generateHTMLContent(8 * 1024 * 1024);
+ test->registerURISchemeHandler("error", longHTMLContent.utf8().data(), -1, "text/html");
test->m_loadEvents.clear();
test->loadURI("error:error");
test->waitUntilLoadFinished();
g_assert(test->m_loadEvents.contains(LoadTrackingTest::ProvisionalLoadFailed));
g_assert(test->m_loadFailed);
g_assert_error(test->m_error.get(), g_quark_from_string(errorDomain), errorCode);
- g_assert_cmpstr(test->m_error->message, ==, errorMessage);
+ g_assert_cmpstr(test->m_error->message, ==, genericErrorMessage);
+
+ test->m_loadEvents.clear();
+ test->loadURI("error:before-response");
+ test->waitUntilLoadFinished();
+ g_assert(test->m_loadEvents.contains(LoadTrackingTest::ProvisionalLoadFailed));
+ g_assert(test->m_loadFailed);
+ g_assert_error(test->m_error.get(), g_quark_from_string(errorDomain), errorCode);
+ g_assert_cmpstr(test->m_error->message, ==, beforeReceiveResponseErrorMessage);
+
+ test->m_loadEvents.clear();
+ test->loadURI("error:after-first-chunk");
+ test->finishOnCommittedAndWaitUntilLoadFinished();
+ g_assert(!test->m_loadEvents.contains(LoadTrackingTest::ProvisionalLoadFailed));
+ g_assert(test->m_loadEvents.contains(LoadTrackingTest::LoadFailed));
+ g_assert(test->m_loadFailed);
+ g_assert_error(test->m_error.get(), g_quark_from_string(errorDomain), errorCode);
+ g_assert_cmpstr(test->m_error->message, ==, afterInitialChunkErrorMessage);
test->registerURISchemeHandler("closed", 0, 0, 0);
test->m_loadEvents.clear();
@@ -236,7 +412,7 @@ static void testWebContextURIScheme(URISchemeTest* test, gconstpointer)
static void testWebContextSpellChecker(Test* test, gconstpointer)
{
- WebKitWebContext* webContext = webkit_web_context_get_default();
+ WebKitWebContext* webContext = test->m_webContext.get();
// Check what happens if no spell checking language has been set.
const gchar* const* currentLanguage = webkit_web_context_get_spell_checking_languages(webContext);
@@ -302,7 +478,7 @@ static void testWebContextLanguages(WebViewTest* test, gconstpointer)
g_ptr_array_add(languages.get(), const_cast<gpointer>(static_cast<const void*>("ES_es")));
g_ptr_array_add(languages.get(), const_cast<gpointer>(static_cast<const void*>("dE")));
g_ptr_array_add(languages.get(), 0);
- webkit_web_context_set_preferred_languages(webkit_web_context_get_default(), reinterpret_cast<const char* const*>(languages->pdata));
+ webkit_web_context_set_preferred_languages(test->m_webContext.get(), reinterpret_cast<const char* const*>(languages->pdata));
static const char* expectedLanguages = "en, es-es;q=0.90, de;q=0.80";
test->loadURI(kServer->getURIForPath("/").data());
@@ -325,6 +501,25 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char*
soup_message_set_status(message, SOUP_STATUS_OK);
soup_message_body_append(message->response_body, SOUP_MEMORY_COPY, acceptLanguage, strlen(acceptLanguage));
soup_message_body_complete(message->response_body);
+ } else if (g_str_equal(path, "/empty")) {
+ const char* emptyHTML = "<html><body></body></html>";
+ soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, emptyHTML, strlen(emptyHTML));
+ soup_message_body_complete(message->response_body);
+ soup_message_set_status(message, SOUP_STATUS_OK);
+ } else if (g_str_equal(path, "/appcache")) {
+ const char* appcacheHTML = "<html manifest=appcache.manifest><body></body></html>";
+ soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, appcacheHTML, strlen(appcacheHTML));
+ soup_message_body_complete(message->response_body);
+ soup_message_set_status(message, SOUP_STATUS_OK);
+ } else if (g_str_equal(path, "/appcache.manifest")) {
+ const char* appcacheManifest = "CACHE MANIFEST\nCACHE:\nappcache/foo.txt\n";
+ soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, appcacheManifest, strlen(appcacheManifest));
+ soup_message_body_complete(message->response_body);
+ soup_message_set_status(message, SOUP_STATUS_OK);
+ } else if (g_str_equal(path, "/appcache/foo.txt")) {
+ soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, "foo", 3);
+ soup_message_body_complete(message->response_body);
+ soup_message_set_status(message, SOUP_STATUS_OK);
} else
soup_message_set_status(message, SOUP_STATUS_NOT_FOUND);
}
@@ -343,7 +538,7 @@ public:
};
SecurityPolicyTest()
- : m_manager(webkit_web_context_get_security_manager(webkit_web_context_get_default()))
+ : m_manager(webkit_web_context_get_security_manager(m_webContext.get()))
{
}
@@ -406,17 +601,52 @@ static void testWebContextSecurityPolicy(SecurityPolicyTest* test, gconstpointer
| SecurityPolicyTest::CORSEnabled | SecurityPolicyTest::EmptyDocument);
}
+static void testWebContextSecurityFileXHR(WebViewTest* test, gconstpointer)
+{
+ GUniquePtr<char> fileURL(g_strdup_printf("file://%s/simple.html", Test::getResourcesDir(Test::WebKit2Resources).data()));
+ test->loadURI(fileURL.get());
+ test->waitUntilLoadFinished();
+
+ GUniquePtr<char> jsonURL(g_strdup_printf("file://%s/simple.json", Test::getResourcesDir().data()));
+ GUniquePtr<char> xhr(g_strdup_printf("var xhr = new XMLHttpRequest; xhr.open(\"GET\", \"%s\"); xhr.send();", jsonURL.get()));
+
+ // By default file access is not allowed, this will fail with a cross-origin error.
+ GUniqueOutPtr<GError> error;
+ WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished(xhr.get(), &error.outPtr());
+ g_assert(!javascriptResult);
+ g_assert_error(error.get(), WEBKIT_JAVASCRIPT_ERROR, WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED);
+
+ // Allow file access from file URLs.
+ webkit_settings_set_allow_file_access_from_file_urls(webkit_web_view_get_settings(test->m_webView), TRUE);
+ test->loadURI(fileURL.get());
+ test->waitUntilLoadFinished();
+ javascriptResult = test->runJavaScriptAndWaitUntilFinished(xhr.get(), &error.outPtr());
+ g_assert(javascriptResult);
+ g_assert(!error);
+
+ // It isn't still possible to load file from an HTTP URL.
+ test->loadURI(kServer->getURIForPath("/").data());
+ test->waitUntilLoadFinished();
+ javascriptResult = test->runJavaScriptAndWaitUntilFinished(xhr.get(), &error.outPtr());
+ g_assert(!javascriptResult);
+ g_assert_error(error.get(), WEBKIT_JAVASCRIPT_ERROR, WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED);
+
+ webkit_settings_set_allow_file_access_from_file_urls(webkit_web_view_get_settings(test->m_webView), FALSE);
+}
+
void beforeAll()
{
kServer = new WebKitTestServer();
kServer->run(serverCallback);
Test::add("WebKitWebContext", "default-context", testWebContextDefault);
+ WebViewTest::add("WebKitWebContext", "configuration", testWebContextConfiguration);
PluginsTest::add("WebKitWebContext", "get-plugins", testWebContextGetPlugins);
URISchemeTest::add("WebKitWebContext", "uri-scheme", testWebContextURIScheme);
Test::add("WebKitWebContext", "spell-checker", testWebContextSpellChecker);
WebViewTest::add("WebKitWebContext", "languages", testWebContextLanguages);
SecurityPolicyTest::add("WebKitSecurityManager", "security-policy", testWebContextSecurityPolicy);
+ WebViewTest::add("WebKitSecurityManager", "file-xhr", testWebContextSecurityFileXHR);
}
void afterAll()
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp
index 334f8dafe..9248097ab 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2011 Igalia S.L.
+ * Copyright (C) 2014 Collabora Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -18,38 +19,106 @@
*/
#include "config.h"
+#include "WebKitTestServer.h"
#include "WebViewTest.h"
#include <JavaScriptCore/JSStringRef.h>
#include <JavaScriptCore/JSValueRef.h>
#include <glib/gstdio.h>
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
-static void testWebViewDefaultContext(WebViewTest* test, gconstpointer)
+class IsPlayingAudioWebViewTest : public WebViewTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(IsPlayingAudioWebViewTest);
+
+ static void isPlayingAudioChanged(GObject*, GParamSpec*, IsPlayingAudioWebViewTest* test)
+ {
+ g_signal_handlers_disconnect_by_func(test->m_webView, reinterpret_cast<void*>(isPlayingAudioChanged), test);
+ g_main_loop_quit(test->m_mainLoop);
+ }
+
+ void waitUntilIsPlayingAudioChanged()
+ {
+ g_signal_connect(m_webView, "notify::is-playing-audio", G_CALLBACK(isPlayingAudioChanged), this);
+ g_main_loop_run(m_mainLoop);
+ }
+};
+
+static WebKitTestServer* gServer;
+
+static void testWebViewWebContext(WebViewTest* test, gconstpointer)
{
- g_assert(webkit_web_view_get_context(test->m_webView) == webkit_web_context_get_default());
+ g_assert(webkit_web_view_get_context(test->m_webView) == test->m_webContext.get());
+ g_assert(webkit_web_context_get_default() != test->m_webContext.get());
// Check that a web view created with g_object_new has the default context.
- GRefPtr<WebKitWebView> webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, NULL));
+ GRefPtr<WebKitWebView> webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, nullptr));
g_assert(webkit_web_view_get_context(webView.get()) == webkit_web_context_get_default());
+
+ // Check that a web view created with a related view has the related view context.
+ webView = WEBKIT_WEB_VIEW(webkit_web_view_new_with_related_view(test->m_webView));
+ g_assert(webkit_web_view_get_context(webView.get()) == test->m_webContext.get());
+
+ // Check that a web context given as construct parameter is ignored if a related view is also provided.
+ webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW,
+ "web-context", webkit_web_context_get_default(), "related-view", test->m_webView, nullptr));
+ g_assert(webkit_web_view_get_context(webView.get()) == test->m_webContext.get());
+}
+
+static void testWebViewWebContextLifetime(WebViewTest* test, gconstpointer)
+{
+ WebKitWebContext* webContext = webkit_web_context_new();
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(webContext));
+
+ GtkWidget* webView = webkit_web_view_new_with_context(webContext);
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(webView));
+
+ g_object_ref_sink(webView);
+ g_object_unref(webContext);
+
+ // Check that the web view still has a valid context.
+ WebKitWebContext* tmpContext = webkit_web_view_get_context(WEBKIT_WEB_VIEW(webView));
+ g_assert_true(WEBKIT_IS_WEB_CONTEXT(tmpContext));
+ g_object_unref(webView);
+
+ WebKitWebContext* webContext2 = webkit_web_context_new();
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(webContext2));
+
+ GtkWidget* webView2 = webkit_web_view_new_with_context(webContext2);
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(webView2));
+
+ g_object_ref_sink(webView2);
+ g_object_unref(webView2);
+
+ // Check that the context is still valid.
+ g_assert_true(WEBKIT_IS_WEB_CONTEXT(webContext2));
+ g_object_unref(webContext2);
}
static void testWebViewCustomCharset(WebViewTest* test, gconstpointer)
{
+ test->loadURI(gServer->getURIForPath("/").data());
+ test->waitUntilLoadFinished();
g_assert(!webkit_web_view_get_custom_charset(test->m_webView));
webkit_web_view_set_custom_charset(test->m_webView, "utf8");
+ // Changing the charset reloads the page, so wait until reloaded.
+ test->waitUntilLoadFinished();
g_assert_cmpstr(webkit_web_view_get_custom_charset(test->m_webView), ==, "utf8");
- // Go back to the default charset.
- webkit_web_view_set_custom_charset(test->m_webView, 0);
+
+ // Go back to the default charset and wait until reloaded.
+ webkit_web_view_set_custom_charset(test->m_webView, nullptr);
+ test->waitUntilLoadFinished();
g_assert(!webkit_web_view_get_custom_charset(test->m_webView));
}
static void testWebViewSettings(WebViewTest* test, gconstpointer)
{
WebKitSettings* defaultSettings = webkit_web_view_get_settings(test->m_webView);
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(defaultSettings));
g_assert(defaultSettings);
g_assert(webkit_settings_get_enable_javascript(defaultSettings));
GRefPtr<WebKitSettings> newSettings = adoptGRef(webkit_settings_new());
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(newSettings.get()));
g_object_set(G_OBJECT(newSettings.get()), "enable-javascript", FALSE, NULL);
webkit_web_view_set_settings(test->m_webView, newSettings.get());
@@ -63,10 +132,15 @@ static void testWebViewSettings(WebViewTest* test, gconstpointer)
g_assert(webkit_web_view_get_settings(WEBKIT_WEB_VIEW(webView2.get())) == settings);
GRefPtr<WebKitSettings> newSettings2 = adoptGRef(webkit_settings_new());
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(newSettings2.get()));
webkit_web_view_set_settings(WEBKIT_WEB_VIEW(webView2.get()), newSettings2.get());
settings = webkit_web_view_get_settings(WEBKIT_WEB_VIEW(webView2.get()));
g_assert(settings == newSettings2.get());
g_assert(webkit_settings_get_enable_javascript(settings));
+
+ GRefPtr<GtkWidget> webView3 = webkit_web_view_new_with_settings(newSettings2.get());
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(webView3.get()));
+ g_assert(webkit_web_view_get_settings(WEBKIT_WEB_VIEW(webView3.get())) == newSettings2.get());
}
static void testWebViewZoomLevel(WebViewTest* test, gconstpointer)
@@ -407,7 +481,7 @@ static void testWebViewSave(SaveWebViewTest* test, gconstpointer)
gchar buffer[512] = { 0 };
gssize readBytes = 0;
gssize totalBytesFromStream = 0;
- while (readBytes = g_input_stream_read(test->m_inputStream.get(), &buffer, 512, 0, &error.outPtr())) {
+ while ((readBytes = g_input_stream_read(test->m_inputStream.get(), &buffer, 512, 0, &error.outPtr()))) {
g_assert(!error);
totalBytesFromStream += readBytes;
}
@@ -417,28 +491,7 @@ static void testWebViewSave(SaveWebViewTest* test, gconstpointer)
g_assert_cmpint(g_file_info_get_size(fileInfo.get()), ==, totalBytesFromStream);
}
-static void testWebViewMode(WebViewTest* test, gconstpointer)
-{
- static const char* indexHTML = "<html><body><p>Test Web View Mode</p></body></html>";
-
- // Web mode.
- g_assert_cmpuint(webkit_web_view_get_view_mode(test->m_webView), ==, WEBKIT_VIEW_MODE_WEB);
- test->loadHtml(indexHTML, 0);
- test->waitUntilLoadFinished();
- WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.document.body.textContent;", 0);
- GUniquePtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult));
- g_assert_cmpstr(valueString.get(), ==, "Test Web View Mode");
-
- // Source mode.
- webkit_web_view_set_view_mode(test->m_webView, WEBKIT_VIEW_MODE_SOURCE);
- test->loadHtml(indexHTML, 0);
- test->waitUntilLoadFinished();
- javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.document.body.textContent;", 0);
- valueString.reset(WebViewTest::javascriptResultToCString(javascriptResult));
- g_assert_cmpstr(valueString.get(), ==, indexHTML);
-}
-
-// To test page visibility API. Currently only 'visible' and 'hidden' states are implemented fully in WebCore.
+// To test page visibility API. Currently only 'visible', 'hidden' and 'prerender' states are implemented fully in WebCore.
// See also http://www.w3.org/TR/2011/WD-page-visibility-20110602/ and https://developers.google.com/chrome/whitepapers/pagevisibility
static void testWebViewPageVisibility(WebViewTest* test, gconstpointer)
{
@@ -453,7 +506,7 @@ static void testWebViewPageVisibility(WebViewTest* test, gconstpointer)
"</body></html>",
0);
- // Wait untill the page is loaded. Initial visibility should be 'hidden'.
+ // Wait until the page is loaded. Initial visibility should be 'prerender'.
test->waitUntilLoadFinished();
GUniqueOutPtr<GError> error;
@@ -461,7 +514,7 @@ static void testWebViewPageVisibility(WebViewTest* test, gconstpointer)
g_assert(javascriptResult);
g_assert(!error.get());
GUniquePtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult));
- g_assert_cmpstr(valueString.get(), ==, "hidden");
+ g_assert_cmpstr(valueString.get(), ==, "prerender");
javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.hidden;", &error.outPtr());
g_assert(javascriptResult);
@@ -564,15 +617,263 @@ static void testWebViewSnapshot(SnapshotWebViewTest* test, gconstpointer)
g_assert_cmpint(cairo_image_surface_get_width(surface1), ==, cairo_image_surface_get_width(surface2));
g_assert_cmpint(cairo_image_surface_get_height(surface1), ==, cairo_image_surface_get_height(surface2));
g_assert(!Test::cairoSurfacesEqual(surface1, surface2));
+
+ // Get a snpashot with a transparent background, the result must be different.
+ surface2 = test->getSnapshotAndWaitUntilReady(WEBKIT_SNAPSHOT_REGION_VISIBLE, WEBKIT_SNAPSHOT_OPTIONS_TRANSPARENT_BACKGROUND);
+ g_assert_cmpuint(cairo_surface_get_type(surface2), ==, CAIRO_SURFACE_TYPE_IMAGE);
+ g_assert_cmpint(cairo_image_surface_get_width(surface1), ==, cairo_image_surface_get_width(surface2));
+ g_assert_cmpint(cairo_image_surface_get_height(surface1), ==, cairo_image_surface_get_height(surface2));
+ g_assert(!Test::cairoSurfacesEqual(surface1, surface2));
cairo_surface_destroy(surface1);
// Test that cancellation works.
g_assert(test->getSnapshotAndCancel());
}
+class NotificationWebViewTest: public WebViewTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(NotificationWebViewTest);
+
+ enum NotificationEvent {
+ None,
+ Permission,
+ Shown,
+ Clicked,
+ OnClicked,
+ Closed,
+ OnClosed,
+ };
+
+ static gboolean permissionRequestCallback(WebKitWebView*, WebKitPermissionRequest *request, NotificationWebViewTest* test)
+ {
+ g_assert(WEBKIT_IS_NOTIFICATION_PERMISSION_REQUEST(request));
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request));
+
+ test->m_event = Permission;
+
+ webkit_permission_request_allow(request);
+
+ g_main_loop_quit(test->m_mainLoop);
+
+ return TRUE;
+ }
+
+ static gboolean notificationClosedCallback(WebKitNotification* notification, NotificationWebViewTest* test)
+ {
+ g_assert(test->m_notification == notification);
+ test->m_notification = nullptr;
+ test->m_event = Closed;
+ if (g_main_loop_is_running(test->m_mainLoop))
+ g_main_loop_quit(test->m_mainLoop);
+ return TRUE;
+ }
+
+ static gboolean notificationClickedCallback(WebKitNotification* notification, NotificationWebViewTest* test)
+ {
+ g_assert(test->m_notification == notification);
+ test->m_event = Clicked;
+ return TRUE;
+ }
+
+ static gboolean showNotificationCallback(WebKitWebView*, WebKitNotification* notification, NotificationWebViewTest* test)
+ {
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(notification));
+ test->m_notification = notification;
+ g_signal_connect(notification, "closed", G_CALLBACK(notificationClosedCallback), test);
+ g_signal_connect(notification, "clicked", G_CALLBACK(notificationClickedCallback), test);
+ test->m_event = Shown;
+ g_main_loop_quit(test->m_mainLoop);
+ return TRUE;
+ }
+
+ static void notificationsMessageReceivedCallback(WebKitUserContentManager* userContentManager, WebKitJavascriptResult* javascriptResult, NotificationWebViewTest* test)
+ {
+ GUniquePtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult));
+
+ if (g_str_equal(valueString.get(), "clicked"))
+ test->m_event = OnClicked;
+ else if (g_str_equal(valueString.get(), "closed"))
+ test->m_event = OnClosed;
+
+ g_main_loop_quit(test->m_mainLoop);
+ }
+
+ NotificationWebViewTest()
+ : WebViewTest(webkit_user_content_manager_new())
+ , m_notification(nullptr)
+ , m_event(None)
+ {
+ g_signal_connect(m_webView, "permission-request", G_CALLBACK(permissionRequestCallback), this);
+ g_signal_connect(m_webView, "show-notification", G_CALLBACK(showNotificationCallback), this);
+ WebKitUserContentManager* manager = webkit_web_view_get_user_content_manager(m_webView);
+ webkit_user_content_manager_register_script_message_handler(manager, "notifications");
+ g_signal_connect(manager, "script-message-received::notifications", G_CALLBACK(notificationsMessageReceivedCallback), this);
+ }
+
+ ~NotificationWebViewTest()
+ {
+ g_signal_handlers_disconnect_matched(m_webView, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
+ WebKitUserContentManager* manager = webkit_web_view_get_user_content_manager(m_webView);
+ g_signal_handlers_disconnect_matched(manager, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
+ webkit_user_content_manager_unregister_script_message_handler(manager, "notifications");
+ }
+
+ void requestPermissionAndWaitUntilGiven()
+ {
+ m_event = None;
+ webkit_web_view_run_javascript(m_webView, "Notification.requestPermission();", nullptr, nullptr, nullptr);
+ g_main_loop_run(m_mainLoop);
+ }
+
+ void requestNotificationAndWaitUntilShown(const char* title, const char* body)
+ {
+ m_event = None;
+
+ GUniquePtr<char> jscode(g_strdup_printf("n = new Notification('%s', { body: '%s'});", title, body));
+ webkit_web_view_run_javascript(m_webView, jscode.get(), nullptr, nullptr, nullptr);
+
+ g_main_loop_run(m_mainLoop);
+ }
+
+ void clickNotificationAndWaitUntilClicked()
+ {
+ m_event = None;
+ runJavaScriptAndWaitUntilFinished("n.onclick = function() { window.webkit.messageHandlers.notifications.postMessage('clicked'); }", nullptr);
+ webkit_notification_clicked(m_notification);
+ g_assert(m_event == Clicked);
+ g_main_loop_run(m_mainLoop);
+ }
+
+ void closeNotificationAndWaitUntilClosed()
+ {
+ m_event = None;
+ webkit_web_view_run_javascript(m_webView, "n.close()", nullptr, nullptr, nullptr);
+ g_main_loop_run(m_mainLoop);
+ }
+
+ void closeNotificationAndWaitUntilOnClosed()
+ {
+ g_assert(m_notification);
+ m_event = None;
+ runJavaScriptAndWaitUntilFinished("n.onclose = function() { window.webkit.messageHandlers.notifications.postMessage('closed'); }", nullptr);
+ webkit_notification_close(m_notification);
+ g_assert(m_event == Closed);
+ g_main_loop_run(m_mainLoop);
+ }
+
+ NotificationEvent m_event;
+ WebKitNotification* m_notification;
+};
+
+static void testWebViewNotification(NotificationWebViewTest* test, gconstpointer)
+{
+ // Notifications don't work with local or special schemes.
+ test->loadURI(gServer->getURIForPath("/").data());
+ test->waitUntilLoadFinished();
+
+ test->requestPermissionAndWaitUntilGiven();
+ g_assert(test->m_event == NotificationWebViewTest::Permission);
+
+ static const char* title = "This is a notification";
+ static const char* body = "This is the body.";
+ test->requestNotificationAndWaitUntilShown(title, body);
+
+ g_assert(test->m_event == NotificationWebViewTest::Shown);
+ g_assert(test->m_notification);
+ g_assert_cmpstr(webkit_notification_get_title(test->m_notification), ==, title);
+ g_assert_cmpstr(webkit_notification_get_body(test->m_notification), ==, body);
+
+ test->clickNotificationAndWaitUntilClicked();
+ g_assert(test->m_event == NotificationWebViewTest::OnClicked);
+
+ test->closeNotificationAndWaitUntilClosed();
+ g_assert(test->m_event == NotificationWebViewTest::Closed);
+
+ test->requestNotificationAndWaitUntilShown(title, body);
+ g_assert(test->m_event == NotificationWebViewTest::Shown);
+
+ test->closeNotificationAndWaitUntilOnClosed();
+ g_assert(test->m_event == NotificationWebViewTest::OnClosed);
+
+ test->requestNotificationAndWaitUntilShown(title, body);
+ g_assert(test->m_event == NotificationWebViewTest::Shown);
+
+ test->loadURI(gServer->getURIForPath("/").data());
+ test->waitUntilLoadFinished();
+ g_assert(test->m_event == NotificationWebViewTest::Closed);
+}
+
+static void testWebViewIsPlayingAudio(IsPlayingAudioWebViewTest* test, gconstpointer)
+{
+ // The web view must be realized for the video to start playback and
+ // trigger changes in WebKitWebView::is-playing-audio.
+ test->showInWindowAndWaitUntilMapped(GTK_WINDOW_TOPLEVEL);
+
+ // Initially, web views should always report no audio being played.
+ g_assert(!webkit_web_view_is_playing_audio(test->m_webView));
+
+ GUniquePtr<char> resourcePath(g_build_filename(Test::getResourcesDir(Test::WebKit2Resources).data(), "file-with-video.html", nullptr));
+ GUniquePtr<char> resourceURL(g_filename_to_uri(resourcePath.get(), nullptr, nullptr));
+ webkit_web_view_load_uri(test->m_webView, resourceURL.get());
+ test->waitUntilLoadFinished();
+ g_assert(!webkit_web_view_is_playing_audio(test->m_webView));
+
+ webkit_web_view_run_javascript(test->m_webView, "playVideo();", nullptr, nullptr, nullptr);
+ test->waitUntilIsPlayingAudioChanged();
+ g_assert(webkit_web_view_is_playing_audio(test->m_webView));
+
+ // Pause the video, and check again.
+ webkit_web_view_run_javascript(test->m_webView, "document.getElementById('test-video').pause();", nullptr, nullptr, nullptr);
+ test->waitUntilIsPlayingAudioChanged();
+ g_assert(!webkit_web_view_is_playing_audio(test->m_webView));
+}
+
+static void testWebViewBackgroundColor(WebViewTest* test, gconstpointer)
+{
+ // White is the default background.
+ GdkRGBA rgba;
+ webkit_web_view_get_background_color(test->m_webView, &rgba);
+ g_assert_cmpfloat(rgba.red, ==, 1);
+ g_assert_cmpfloat(rgba.green, ==, 1);
+ g_assert_cmpfloat(rgba.blue, ==, 1);
+ g_assert_cmpfloat(rgba.alpha, ==, 1);
+
+ // Set a different (semi-transparent red).
+ rgba.red = 1;
+ rgba.green = 0;
+ rgba.blue = 0;
+ rgba.alpha = 0.5;
+ webkit_web_view_set_background_color(test->m_webView, &rgba);
+ g_assert_cmpfloat(rgba.red, ==, 1);
+ g_assert_cmpfloat(rgba.green, ==, 0);
+ g_assert_cmpfloat(rgba.blue, ==, 0);
+ g_assert_cmpfloat(rgba.alpha, ==, 0.5);
+
+ // The actual rendering can't be tested using unit tests, use
+ // MiniBrowser --bg-color="<color-value>" for manually testing this API.
+}
+
+static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer)
+{
+ if (message->method != SOUP_METHOD_GET) {
+ soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED);
+ return;
+ }
+
+ if (g_str_equal(path, "/")) {
+ soup_message_set_status(message, SOUP_STATUS_OK);
+ soup_message_body_complete(message->response_body);
+ } else
+ soup_message_set_status(message, SOUP_STATUS_NOT_FOUND);
+}
+
void beforeAll()
{
- WebViewTest::add("WebKitWebView", "default-context", testWebViewDefaultContext);
+ gServer = new WebKitTestServer();
+ gServer->run(serverCallback);
+
+ WebViewTest::add("WebKitWebView", "web-context", testWebViewWebContext);
+ WebViewTest::add("WebKitWebView", "web-context-lifetime", testWebViewWebContextLifetime);
WebViewTest::add("WebKitWebView", "custom-charset", testWebViewCustomCharset);
WebViewTest::add("WebKitWebView", "settings", testWebViewSettings);
WebViewTest::add("WebKitWebView", "zoom-level", testWebViewZoomLevel);
@@ -581,9 +882,11 @@ void beforeAll()
WebViewTest::add("WebKitWebView", "can-show-mime-type", testWebViewCanShowMIMEType);
FormClientTest::add("WebKitWebView", "submit-form", testWebViewSubmitForm);
SaveWebViewTest::add("WebKitWebView", "save", testWebViewSave);
- WebViewTest::add("WebKitWebView", "view-mode", testWebViewMode);
SnapshotWebViewTest::add("WebKitWebView", "snapshot", testWebViewSnapshot);
WebViewTest::add("WebKitWebView", "page-visibility", testWebViewPageVisibility);
+ NotificationWebViewTest::add("WebKitWebView", "notification", testWebViewNotification);
+ IsPlayingAudioWebViewTest::add("WebKitWebView", "is-playing-audio", testWebViewIsPlayingAudio);
+ WebViewTest::add("WebKitWebView", "background-color", testWebViewBackgroundColor);
}
void afterAll()
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebViewGroup.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebViewGroup.cpp
deleted file mode 100644
index 448abd2fe..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebViewGroup.cpp
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2013 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2,1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-
-#include "WebKitTestServer.h"
-#include "WebViewTest.h"
-#include <cstdarg>
-#include <gtk/gtk.h>
-#include <webkit2/webkit2.h>
-#include <wtf/gobject/GRefPtr.h>
-
-static WebKitTestServer* kServer;
-
-// These are all here so that they can be changed easily, if necessary.
-static const char* kStyleSheetHTML = "<html><div id=\"styledElement\">Sweet stylez!</div></html>";
-static const char* kInjectedStyleSheet = "#styledElement { font-weight: bold; }";
-static const char* kStyleSheetTestScript = "getComputedStyle(document.getElementById('styledElement'))['font-weight']";
-static const char* kStyleSheetTestScriptResult = "bold";
-
-static void testWebViewGroupDefault(Test* test, gconstpointer)
-{
- // Default group is shared by all WebViews by default.
- GRefPtr<WebKitWebView> webView1 = WEBKIT_WEB_VIEW(webkit_web_view_new());
- GRefPtr<WebKitWebView> webView2 = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_assert(webkit_web_view_get_group(webView1.get()) == webkit_web_view_get_group(webView2.get()));
-
- // Settings are shared by all web view in the same group.
- g_assert(webkit_web_view_get_settings(webView1.get()) == webkit_web_view_get_settings(webView2.get()));
- g_assert(webkit_web_view_get_settings(webView1.get()) == webkit_web_view_group_get_settings(webkit_web_view_get_group(webView2.get())));
-}
-
-static void testWebViewGroupNewGroup(Test* test, gconstpointer)
-{
- // Passing 0 as group name generates the name automatically.
- GRefPtr<WebKitWebViewGroup> viewGroup1 = adoptGRef(webkit_web_view_group_new(0));
- test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(viewGroup1.get()));
- g_assert(webkit_web_view_group_get_name(viewGroup1.get()));
-
- // New group with a given name.
- GRefPtr<WebKitWebViewGroup> viewGroup2 = adoptGRef(webkit_web_view_group_new("TestGroup2"));
- test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(viewGroup2.get()));
- g_assert_cmpstr(webkit_web_view_group_get_name(viewGroup2.get()), ==, "TestGroup2");
- g_assert_cmpstr(webkit_web_view_group_get_name(viewGroup2.get()), !=, webkit_web_view_group_get_name(viewGroup1.get()));
-
- // Every group has its own settings.
- g_assert(webkit_web_view_group_get_settings(viewGroup1.get()) != webkit_web_view_group_get_settings(viewGroup2.get()));
-}
-
-static void testWebViewNewWithGroup(Test* test, gconstpointer)
-{
- GRefPtr<WebKitWebViewGroup> viewGroup1 = adoptGRef(webkit_web_view_group_new("TestGroup1"));
- test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(viewGroup1.get()));
- GRefPtr<WebKitWebView> webView1 = WEBKIT_WEB_VIEW(webkit_web_view_new_with_group(viewGroup1.get()));
- g_assert(webkit_web_view_get_group(webView1.get()) == viewGroup1.get());
-
- GRefPtr<WebKitWebView> webView2 = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_assert(webkit_web_view_get_group(webView2.get()) != viewGroup1.get());
-
- // Settings should be different for views in different groups.
- g_assert(webkit_web_view_get_settings(webView1.get()) != webkit_web_view_get_settings(webView2.get()));
-}
-
-static void testWebViewGroupSettings(Test* test, gconstpointer)
-{
- GRefPtr<WebKitWebViewGroup> viewGroup1 = adoptGRef(webkit_web_view_group_new("TestGroup1"));
- test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(viewGroup1.get()));
- GRefPtr<WebKitSettings> newSettings = adoptGRef(webkit_settings_new_with_settings("enable-javascript", FALSE, nullptr));
- test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(newSettings.get()));
- webkit_web_view_group_set_settings(viewGroup1.get(), newSettings.get());
- g_assert(webkit_web_view_group_get_settings(viewGroup1.get()) == newSettings.get());
-
- GRefPtr<WebKitWebView> webView1 = WEBKIT_WEB_VIEW(webkit_web_view_new_with_group(viewGroup1.get()));
- GRefPtr<WebKitWebView> webView2 = WEBKIT_WEB_VIEW(webkit_web_view_new());
- WebKitSettings* webView1Settings = webkit_web_view_get_settings(webView1.get());
- WebKitSettings* webView2Settings = webkit_web_view_get_settings(webView2.get());
- g_assert(webView1Settings != webView2Settings);
- g_assert(webkit_settings_get_enable_javascript(webView1Settings) != webkit_settings_get_enable_javascript(webView2Settings));
-
- webkit_web_view_set_settings(webView1.get(), webView2Settings);
- g_assert(webkit_web_view_get_settings(webView1.get()) == webView2Settings);
- g_assert(webkit_web_view_group_get_settings(webkit_web_view_get_group(webView1.get())) == webView2Settings);
-}
-
-static bool isStyleSheetInjectedForURLAtPath(WebViewTest* test, const char* path)
-{
- test->loadURI(kServer->getURIForPath(path).data());
- test->waitUntilLoadFinished();
-
- GUniqueOutPtr<GError> error;
- WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished(kStyleSheetTestScript, &error.outPtr());
- g_assert(javascriptResult);
- g_assert(!error.get());
-
- GUniquePtr<char> resultString(WebViewTest::javascriptResultToCString(javascriptResult));
- return !g_strcmp0(resultString.get(), kStyleSheetTestScriptResult);
-}
-
-static void fillURLListFromPaths(char** list, const char* path, ...)
-{
- va_list argumentList;
- va_start(argumentList, path);
-
- int i = 0;
- while (path) {
- // FIXME: We must use a wildcard for the host here until http://wkbug.com/112476 is fixed.
- // Until that time patterns with port numbers in them will not properly match URLs with port numbers.
- list[i++] = g_strdup_printf("http://*/%s*", path);
- path = va_arg(argumentList, const char*);
- }
-}
-
-static void removeOldInjectedStyleSheetsAndResetLists(WebKitWebViewGroup* group, char** whitelist, char** blacklist)
-{
- webkit_web_view_group_remove_all_user_style_sheets(group);
-
- while (*whitelist) {
- g_free(*whitelist);
- *whitelist = 0;
- whitelist++;
- }
-
- while (*blacklist) {
- g_free(*blacklist);
- *blacklist = 0;
- blacklist++;
- }
-}
-
-static void testWebViewGroupInjectedStyleSheet(WebViewTest* test, gconstpointer)
-{
- WebKitWebViewGroup* group = webkit_web_view_get_group(test->m_webView);
- char* whitelist[3] = { 0, 0, 0 };
- char* blacklist[3] = { 0, 0, 0 };
-
- removeOldInjectedStyleSheetsAndResetLists(group, whitelist, blacklist);
-
- // Without a whitelist or a blacklist all URLs should have the injected style sheet.
- static const char* randomPath = "somerandompath";
- g_assert(!isStyleSheetInjectedForURLAtPath(test, randomPath));
- webkit_web_view_group_add_user_style_sheet(group, kInjectedStyleSheet, 0, 0, 0, WEBKIT_INJECTED_CONTENT_FRAMES_ALL);
- g_assert(isStyleSheetInjectedForURLAtPath(test, randomPath));
-
- removeOldInjectedStyleSheetsAndResetLists(group, whitelist, blacklist);
-
- fillURLListFromPaths(blacklist, randomPath, 0);
- webkit_web_view_group_add_user_style_sheet(group, kInjectedStyleSheet, 0, 0, blacklist, WEBKIT_INJECTED_CONTENT_FRAMES_ALL);
- g_assert(!isStyleSheetInjectedForURLAtPath(test, randomPath));
- g_assert(isStyleSheetInjectedForURLAtPath(test, "someotherrandompath"));
-
- removeOldInjectedStyleSheetsAndResetLists(group, whitelist, blacklist);
-
- static const char* inTheWhiteList = "inthewhitelist";
- static const char* notInWhitelist = "notinthewhitelist";
- static const char* inTheWhiteListAndBlackList = "inthewhitelistandblacklist";
-
- fillURLListFromPaths(whitelist, inTheWhiteList, inTheWhiteListAndBlackList, 0);
- fillURLListFromPaths(blacklist, inTheWhiteListAndBlackList, 0);
- webkit_web_view_group_add_user_style_sheet(group, kInjectedStyleSheet, 0, whitelist, blacklist, WEBKIT_INJECTED_CONTENT_FRAMES_ALL);
- g_assert(isStyleSheetInjectedForURLAtPath(test, inTheWhiteList));
- g_assert(!isStyleSheetInjectedForURLAtPath(test, inTheWhiteListAndBlackList));
- g_assert(!isStyleSheetInjectedForURLAtPath(test, notInWhitelist));
-
- // It's important to clean up the environment before other tests.
- removeOldInjectedStyleSheetsAndResetLists(group, whitelist, blacklist);
-}
-
-static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer)
-{
- soup_message_set_status(message, SOUP_STATUS_OK);
- soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, kStyleSheetHTML, strlen(kStyleSheetHTML));
- soup_message_body_complete(message->response_body);
-}
-
-void beforeAll()
-{
- kServer = new WebKitTestServer();
- kServer->run(serverCallback);
-
- Test::add("WebKitWebViewGroup", "default-group", testWebViewGroupDefault);
- Test::add("WebKitWebViewGroup", "new-group", testWebViewGroupNewGroup);
- Test::add("WebKitWebView", "new-with-group", testWebViewNewWithGroup);
- Test::add("WebKitWebViewGroup", "settings", testWebViewGroupSettings);
- WebViewTest::add("WebKitWebViewGroup", "injected-style-sheet", testWebViewGroupInjectedStyleSheet);
-}
-
-void afterAll()
-{
- delete kServer;
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebViewEditor.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebViewEditor.cpp
index 9e69bfa48..d20c7944f 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebViewEditor.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebViewEditor.cpp
@@ -19,7 +19,7 @@
#include "config.h"
#include "WebViewTest.h"
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
class EditorTest: public WebViewTest {
public:
@@ -32,6 +32,7 @@ public:
: m_clipboard(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD))
, m_canExecuteEditingCommand(false)
, m_triesCount(0)
+ , m_editorState(nullptr)
{
gtk_clipboard_clear(m_clipboard);
}
@@ -73,25 +74,71 @@ public:
g_main_loop_run(m_mainLoop);
}
+ gchar* cutSelection()
+ {
+ g_assert(canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_CUT));
+ g_assert(canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_PASTE));
+
+ webkit_web_view_execute_editing_command(m_webView, WEBKIT_EDITING_COMMAND_CUT);
+ // There's no way to know when the selection has been cut to
+ // the clipboard, so use a timeout source to query the clipboard.
+ m_triesCount = 0;
+ g_timeout_add(kClipboardWaitTimeout, reinterpret_cast<GSourceFunc>(waitForClipboardText), this);
+ g_main_loop_run(m_mainLoop);
+
+ return gtk_clipboard_wait_for_text(m_clipboard);
+ }
+
+ WebKitEditorState* editorState()
+ {
+ if (m_editorState)
+ return m_editorState;
+
+ m_editorState = webkit_web_view_get_editor_state(m_webView);
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_editorState));
+ return m_editorState;
+ }
+
+ static void quitMainLoopInCallback(EditorTest* test)
+ {
+ g_main_loop_quit(test->m_mainLoop);
+ }
+
+ unsigned typingAttributes()
+ {
+ return webkit_editor_state_get_typing_attributes(editorState());
+ }
+
+ unsigned waitUntilTypingAttributesChanged()
+ {
+ unsigned long handlerID = g_signal_connect_swapped(editorState(), "notify::typing-attributes", G_CALLBACK(quitMainLoopInCallback), this);
+ g_main_loop_run(m_mainLoop);
+ g_signal_handler_disconnect(m_editorState, handlerID);
+ return typingAttributes();
+ }
+
GtkClipboard* m_clipboard;
bool m_canExecuteEditingCommand;
size_t m_triesCount;
+ WebKitEditorState* m_editorState;
};
+static const char* selectedSpanHTMLFormat =
+ "<html><body contentEditable=\"%s\">"
+ "<span id=\"mainspan\">All work and no play <span id=\"subspan\">make Jack a dull</span> boy.</span>"
+ "<script>document.getSelection().collapse();\n"
+ "document.getSelection().selectAllChildren(document.getElementById('subspan'));\n"
+ "</script></body></html>";
+
static void testWebViewEditorCutCopyPasteNonEditable(EditorTest* test, gconstpointer)
{
- static const char* selectedSpanHTML = "<html><body contentEditable=\"false\">"
- "<span id=\"mainspan\">All work and no play <span id=\"subspan\">make Jack a dull</span> boy.</span>"
- "<script>document.getSelection().collapse();\n"
- "document.getSelection().selectAllChildren(document.getElementById('subspan'));\n"
- "</script></body></html>";
-
// Nothing loaded yet.
g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_CUT));
g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_COPY));
g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_PASTE));
- test->loadHtml(selectedSpanHTML, 0);
+ GUniquePtr<char> selectedSpanHTML(g_strdup_printf(selectedSpanHTMLFormat, "false"));
+ test->loadHtml(selectedSpanHTML.get(), nullptr);
test->waitUntilLoadFinished();
g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_COPY));
@@ -107,18 +154,17 @@ static void testWebViewEditorCutCopyPasteNonEditable(EditorTest* test, gconstpoi
static void testWebViewEditorCutCopyPasteEditable(EditorTest* test, gconstpointer)
{
- static const char* selectedSpanHTML = "<html><body contentEditable=\"true\">"
- "<span id=\"mainspan\">All work and no play <span>make Jack a dull</span> boy.</span>"
- "<script>document.getSelection().collapse();\n"
- "document.getSelection().selectAllChildren(document.getElementById('mainspan'));\n"
- "</script></body></html>";
-
// Nothing loaded yet.
g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_CUT));
g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_COPY));
g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_PASTE));
- test->loadHtml(selectedSpanHTML, 0);
+ g_assert(!test->isEditable());
+ test->setEditable(true);
+ g_assert(test->isEditable());
+
+ GUniquePtr<char> selectedSpanHTML(g_strdup_printf(selectedSpanHTMLFormat, "false"));
+ test->loadHtml(selectedSpanHTML.get(), nullptr);
test->waitUntilLoadFinished();
// There's a selection.
@@ -128,20 +174,15 @@ static void testWebViewEditorCutCopyPasteEditable(EditorTest* test, gconstpointe
test->copyClipboard();
GUniquePtr<char> clipboardText(gtk_clipboard_wait_for_text(test->m_clipboard));
- g_assert_cmpstr(clipboardText.get(), ==, "All work and no play make Jack a dull boy.");
+ g_assert_cmpstr(clipboardText.get(), ==, "make Jack a dull");
}
static void testWebViewEditorSelectAllNonEditable(EditorTest* test, gconstpointer)
{
- static const char* selectedSpanHTML = "<html><body contentEditable=\"false\">"
- "<span id=\"mainspan\">All work and no play <span id=\"subspan\">make Jack a dull</span> boy.</span>"
- "<script>document.getSelection().collapse();\n"
- "document.getSelection().selectAllChildren(document.getElementById('subspan'));\n"
- "</script></body></html>";
-
g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_SELECT_ALL));
- test->loadHtml(selectedSpanHTML, 0);
+ GUniquePtr<char> selectedSpanHTML(g_strdup_printf(selectedSpanHTMLFormat, "false"));
+ test->loadHtml(selectedSpanHTML.get(), nullptr);
test->waitUntilLoadFinished();
g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_SELECT_ALL));
@@ -162,15 +203,14 @@ static void testWebViewEditorSelectAllNonEditable(EditorTest* test, gconstpointe
static void testWebViewEditorSelectAllEditable(EditorTest* test, gconstpointer)
{
- static const char* selectedSpanHTML = "<html><body contentEditable=\"true\">"
- "<span id=\"mainspan\">All work and no play <span id=\"subspan\">make Jack a dull</span> boy.</span>"
- "<script>document.getSelection().collapse();\n"
- "document.getSelection().selectAllChildren(document.getElementById('subspan'));\n"
- "</script></body></html>";
-
g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_SELECT_ALL));
- test->loadHtml(selectedSpanHTML, 0);
+ g_assert(!test->isEditable());
+ test->setEditable(true);
+ g_assert(test->isEditable());
+
+ GUniquePtr<char> selectedSpanHTML(g_strdup_printf(selectedSpanHTMLFormat, "false"));
+ test->loadHtml(selectedSpanHTML.get(), nullptr);
test->waitUntilLoadFinished();
g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_SELECT_ALL));
@@ -189,12 +229,240 @@ static void testWebViewEditorSelectAllEditable(EditorTest* test, gconstpointer)
g_assert_cmpstr(clipboardText.get(), ==, "All work and no play make Jack a dull boy.");
}
+static void loadContentsAndTryToCutSelection(EditorTest* test, bool contentEditable)
+{
+ // View is not editable by default.
+ g_assert(!test->isEditable());
+
+ GUniquePtr<char> selectedSpanHTML(g_strdup_printf(selectedSpanHTMLFormat, contentEditable ? "true" : "false"));
+ test->loadHtml(selectedSpanHTML.get(), nullptr);
+ test->waitUntilLoadFinished();
+
+ g_assert(!test->isEditable());
+ test->setEditable(true);
+ g_assert(test->isEditable());
+
+ // Cut the selection to the clipboard to see if the view is indeed editable.
+ GUniquePtr<char> clipboardText(test->cutSelection());
+ g_assert_cmpstr(clipboardText.get(), ==, "make Jack a dull");
+
+ // Reset the editable for next test.
+ test->setEditable(false);
+ g_assert(!test->isEditable());
+}
+
+static void testWebViewEditorNonEditable(EditorTest* test)
+{
+ GUniquePtr<char> selectedSpanHTML(g_strdup_printf(selectedSpanHTMLFormat, "false"));
+ test->loadHtml(selectedSpanHTML.get(), nullptr);
+ test->waitUntilLoadFinished();
+
+ g_assert(!test->isEditable());
+ test->setEditable(true);
+ g_assert(test->isEditable());
+ test->setEditable(false);
+ g_assert(!test->isEditable());
+
+ // Check if view is indeed non-editable.
+ g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_CUT));
+ g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_PASTE));
+}
+
+static void testWebViewEditorEditable(EditorTest* test, gconstpointer)
+{
+ testWebViewEditorNonEditable(test);
+
+ // Reset the editable for next test.
+ test->setEditable(false);
+ g_assert(!test->isEditable());
+
+ loadContentsAndTryToCutSelection(test, true);
+
+ // Reset the editable for next test.
+ test->setEditable(false);
+ g_assert(!test->isEditable());
+
+ loadContentsAndTryToCutSelection(test, false);
+}
+
+static void testWebViewEditorEditorStateTypingAttributes(EditorTest* test, gconstpointer)
+{
+ static const char* typingAttributesHTML =
+ "<html><body>"
+ "normal <b>bold </b><i>italic </i><u>underline </u><strike>strike </strike>"
+ "<b><i>boldanditalic </i></b>"
+ "</body></html>";
+
+ test->loadHtml(typingAttributesHTML, nullptr);
+ test->waitUntilLoadFinished();
+ test->setEditable(true);
+
+ unsigned typingAttributes = test->typingAttributes();
+ g_assert_cmpuint(typingAttributes, ==, WEBKIT_EDITOR_TYPING_ATTRIBUTE_NONE);
+
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ typingAttributes = test->waitUntilTypingAttributesChanged();
+ g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD);
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH));
+
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ typingAttributes = test->waitUntilTypingAttributesChanged();
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD));
+ g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC);
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH));
+
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ typingAttributes = test->waitUntilTypingAttributesChanged();
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC));
+ g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE);
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH));
+
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ typingAttributes = test->waitUntilTypingAttributesChanged();
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE));
+ g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH);
+
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ typingAttributes = test->waitUntilTypingAttributesChanged();
+ g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD);
+ g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC);
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH));
+
+ // Selections.
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveToBeginningOfDocument");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForwardAndModifySelection");
+ typingAttributes = test->waitUntilTypingAttributesChanged();
+ g_assert_cmpuint(typingAttributes, ==, WEBKIT_EDITOR_TYPING_ATTRIBUTE_NONE);
+
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForwardAndModifySelection");
+ typingAttributes = test->waitUntilTypingAttributesChanged();
+ g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD);
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH));
+
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForwardAndModifySelection");
+ typingAttributes = test->waitUntilTypingAttributesChanged();
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD));
+ g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC);
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH));
+
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForwardAndModifySelection");
+ typingAttributes = test->waitUntilTypingAttributesChanged();
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC));
+ g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE);
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH));
+
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForwardAndModifySelection");
+ typingAttributes = test->waitUntilTypingAttributesChanged();
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE));
+ g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH);
+
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForwardAndModifySelection");
+ typingAttributes = test->waitUntilTypingAttributesChanged();
+ g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD);
+ g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC);
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH));
+
+ webkit_web_view_execute_editing_command(test->m_webView, "SelectAll");
+ typingAttributes = test->waitUntilTypingAttributesChanged();
+ g_assert_cmpuint(typingAttributes, ==, WEBKIT_EDITOR_TYPING_ATTRIBUTE_NONE);
+}
+
+static void testWebViewEditorInsertImage(EditorTest* test, gconstpointer)
+{
+ test->loadHtml("<html><body></body></html>", "file:///");
+ test->waitUntilLoadFinished();
+ test->setEditable(true);
+
+ GUniquePtr<char> imagePath(g_build_filename(Test::getResourcesDir().data(), "blank.ico", nullptr));
+ GUniquePtr<char> imageURI(g_filename_to_uri(imagePath.get(), nullptr, nullptr));
+ webkit_web_view_execute_editing_command_with_argument(test->m_webView, WEBKIT_EDITING_COMMAND_INSERT_IMAGE, imageURI.get());
+ GUniqueOutPtr<GError> error;
+ WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementsByTagName('IMG')[0].src", &error.outPtr());
+ g_assert(javascriptResult);
+ g_assert(!error);
+ GUniquePtr<char> resultString(WebViewTest::javascriptResultToCString(javascriptResult));
+ g_assert_cmpstr(resultString.get(), ==, imageURI.get());
+}
+
+static void testWebViewEditorCreateLink(EditorTest* test, gconstpointer)
+{
+ test->loadHtml("<html><body onload=\"document.getSelection().selectAllChildren(document.body);\">webkitgtk.org</body></html>", nullptr);
+ test->waitUntilLoadFinished();
+ test->setEditable(true);
+
+ static const char* webkitGTKURL = "http://www.webkitgtk.org/";
+ webkit_web_view_execute_editing_command_with_argument(test->m_webView, WEBKIT_EDITING_COMMAND_CREATE_LINK, webkitGTKURL);
+ GUniqueOutPtr<GError> error;
+ WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementsByTagName('A')[0].href;", &error.outPtr());
+ g_assert(javascriptResult);
+ g_assert(!error);
+ GUniquePtr<char> resultString(WebViewTest::javascriptResultToCString(javascriptResult));
+ g_assert_cmpstr(resultString.get(), ==, webkitGTKURL);
+ javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementsByTagName('A')[0].innerText;", &error.outPtr());
+ g_assert(javascriptResult);
+ g_assert(!error);
+ resultString.reset(WebViewTest::javascriptResultToCString(javascriptResult));
+ g_assert_cmpstr(resultString.get(), ==, "webkitgtk.org");
+
+ // When there isn't text selected, the URL is used as link text.
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveToEndOfLine");
+ webkit_web_view_execute_editing_command_with_argument(test->m_webView, WEBKIT_EDITING_COMMAND_CREATE_LINK, webkitGTKURL);
+ javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementsByTagName('A')[1].href;", &error.outPtr());
+ g_assert(javascriptResult);
+ g_assert(!error);
+ resultString.reset(WebViewTest::javascriptResultToCString(javascriptResult));
+ g_assert_cmpstr(resultString.get(), ==, webkitGTKURL);
+ javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementsByTagName('A')[1].innerText;", &error.outPtr());
+ g_assert(javascriptResult);
+ g_assert(!error);
+ resultString.reset(WebViewTest::javascriptResultToCString(javascriptResult));
+ g_assert_cmpstr(resultString.get(), ==, webkitGTKURL);
+}
+
void beforeAll()
{
+ EditorTest::add("WebKitWebView", "editable/editable", testWebViewEditorEditable);
EditorTest::add("WebKitWebView", "cut-copy-paste/non-editable", testWebViewEditorCutCopyPasteNonEditable);
EditorTest::add("WebKitWebView", "cut-copy-paste/editable", testWebViewEditorCutCopyPasteEditable);
EditorTest::add("WebKitWebView", "select-all/non-editable", testWebViewEditorSelectAllNonEditable);
EditorTest::add("WebKitWebView", "select-all/editable", testWebViewEditorSelectAllEditable);
+ EditorTest::add("WebKitWebView", "editor-state/typing-attributes", testWebViewEditorEditorStateTypingAttributes);
+ EditorTest::add("WebKitWebView", "insert/image", testWebViewEditorInsertImage);
+ EditorTest::add("WebKitWebView", "insert/link", testWebViewEditorCreateLink);
}
void afterAll()
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp
index 757532f7a..372cfea7c 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp
@@ -22,17 +22,21 @@
#include <JavaScriptCore/JSContextRef.h>
#include <JavaScriptCore/JSRetainPtr.h>
#include <gio/gio.h>
+#include <gst/gst.h>
#include <stdlib.h>
#include <string.h>
#include <webkit2/webkit-web-extension.h>
#include <wtf/Deque.h>
-#include <wtf/OwnPtr.h>
-#include <wtf/PassOwnPtr.h>
#include <wtf/ProcessID.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>
+#define WEBKIT_DOM_USE_UNSTABLE_API
+#include <webkitdom/WebKitDOMWebKitNamespace.h>
+#include <webkitdom/WebKitDOMUserMessageHandlersNamespace.h>
+#include <webkitdom/WebKitDOMUserMessageHandler.h>
+
static const char introspectionXML[] =
"<node>"
" <interface name='org.webkit.gtk.WebExtensionTest'>"
@@ -46,12 +50,11 @@ static const char introspectionXML[] =
" <arg type='t' name='pageID' direction='in'/>"
" <arg type='s' name='script' direction='in'/>"
" </method>"
- " <method name='GetInitializationUserData'>"
- " <arg type='s' name='userData' direction='out'/>"
- " </method>"
" <method name='GetProcessIdentifier'>"
" <arg type='u' name='identifier' direction='out'/>"
" </method>"
+ " <method name='RemoveAVPluginsFromGSTRegistry'>"
+ " </method>"
" <signal name='DocumentLoaded'/>"
" <signal name='URIChanged'>"
" <arg type='s' name='uri' direction='out'/>"
@@ -59,8 +62,6 @@ static const char introspectionXML[] =
" </interface>"
"</node>";
-static GRefPtr<GVariant> initializationUserData;
-
typedef enum {
DocumentLoadedSignal,
@@ -83,7 +84,7 @@ struct DelayedSignal {
CString uri;
};
-Deque<OwnPtr<DelayedSignal>> delayedSignalsQueue;
+Deque<DelayedSignal> delayedSignalsQueue;
static void emitDocumentLoaded(GDBusConnection* connection)
{
@@ -98,13 +99,24 @@ static void emitDocumentLoaded(GDBusConnection* connection)
g_assert(ok);
}
-static void documentLoadedCallback(WebKitWebPage*, WebKitWebExtension* extension)
+static void documentLoadedCallback(WebKitWebPage* webPage, WebKitWebExtension* extension)
{
+ // FIXME: Too much code just to send a message, we need convenient custom API for this.
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(webPage);
+ GRefPtr<WebKitDOMDOMWindow> window = adoptGRef(webkit_dom_document_get_default_view(document));
+ if (WebKitDOMWebKitNamespace* webkit = webkit_dom_dom_window_get_webkit_namespace(window.get())) {
+ WebKitDOMUserMessageHandlersNamespace* messageHandlers = webkit_dom_webkit_namespace_get_message_handlers(webkit);
+ if (WebKitDOMUserMessageHandler* handler = webkit_dom_user_message_handlers_namespace_get_handler(messageHandlers, "dom"))
+ webkit_dom_user_message_handler_post_message(handler, "DocumentLoaded", nullptr);
+ }
+
+ webkit_dom_dom_window_webkit_message_handlers_post_message(window.get(), "dom-convenience", "DocumentLoaded");
+
gpointer data = g_object_get_data(G_OBJECT(extension), "dbus-connection");
if (data)
emitDocumentLoaded(G_DBUS_CONNECTION(data));
else
- delayedSignalsQueue.append(adoptPtr(new DelayedSignal(DocumentLoadedSignal)));
+ delayedSignalsQueue.append(DelayedSignal(DocumentLoadedSignal));
}
static void emitURIChanged(GDBusConnection* connection, const char* uri)
@@ -126,11 +138,12 @@ static void uriChangedCallback(WebKitWebPage* webPage, GParamSpec* pspec, WebKit
if (data)
emitURIChanged(G_DBUS_CONNECTION(data), webkit_web_page_get_uri(webPage));
else
- delayedSignalsQueue.append(adoptPtr(new DelayedSignal(URIChangedSignal, webkit_web_page_get_uri(webPage))));
+ delayedSignalsQueue.append(DelayedSignal(URIChangedSignal, webkit_web_page_get_uri(webPage)));
}
static gboolean sendRequestCallback(WebKitWebPage*, WebKitURIRequest* request, WebKitURIResponse* redirectResponse, gpointer)
{
+ gboolean returnValue = FALSE;
const char* requestURI = webkit_uri_request_get_uri(request);
g_assert(requestURI);
@@ -153,17 +166,93 @@ static gboolean sendRequestCallback(WebKitWebPage*, WebKitURIRequest* request, W
SoupMessageHeaders* headers = webkit_uri_request_get_http_headers(request);
g_assert(headers);
soup_message_headers_append(headers, "DNT", "1");
+ } else if (g_str_has_suffix(requestURI, "/http-get-method")) {
+ g_assert_cmpstr(webkit_uri_request_get_http_method(request), ==, "GET");
+ g_assert(webkit_uri_request_get_http_method(request) == SOUP_METHOD_GET);
+ } else if (g_str_has_suffix(requestURI, "/http-post-method")) {
+ g_assert_cmpstr(webkit_uri_request_get_http_method(request), ==, "POST");
+ g_assert(webkit_uri_request_get_http_method(request) == SOUP_METHOD_POST);
+ returnValue = TRUE;
} else if (g_str_has_suffix(requestURI, "/cancel-this.js"))
+ returnValue = TRUE;
+
+ return returnValue;
+}
+
+static GVariant* serializeContextMenu(WebKitContextMenu* menu)
+{
+ GVariantBuilder builder;
+ g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
+ GList* items = webkit_context_menu_get_items(menu);
+ for (GList* it = items; it; it = g_list_next(it))
+ g_variant_builder_add(&builder, "u", webkit_context_menu_item_get_stock_action(WEBKIT_CONTEXT_MENU_ITEM(it->data)));
+ return g_variant_builder_end(&builder);
+}
+
+static GVariant* serializeNode(WebKitDOMNode* node)
+{
+ GVariantBuilder builder;
+ g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
+ g_variant_builder_add(&builder, "{sv}", "Name", g_variant_new_take_string(webkit_dom_node_get_node_name(node)));
+ g_variant_builder_add(&builder, "{sv}", "Type", g_variant_new_uint32(webkit_dom_node_get_node_type(node)));
+ g_variant_builder_add(&builder, "{sv}", "Contents", g_variant_new_take_string(webkit_dom_node_get_text_content(node)));
+ WebKitDOMNode* parent = webkit_dom_node_get_parent_node(node);
+ g_variant_builder_add(&builder, "{sv}", "Parent", parent ? g_variant_new_take_string(webkit_dom_node_get_node_name(parent)) : g_variant_new_string("ROOT"));
+ return g_variant_builder_end(&builder);
+}
+
+static gboolean contextMenuCallback(WebKitWebPage* page, WebKitContextMenu* menu, WebKitWebHitTestResult* hitTestResult, gpointer)
+{
+ const char* pageURI = webkit_web_page_get_uri(page);
+ if (!g_strcmp0(pageURI, "ContextMenuTestDefault")) {
+ webkit_context_menu_set_user_data(menu, serializeContextMenu(menu));
+ return FALSE;
+ }
+
+ if (!g_strcmp0(pageURI, "ContextMenuTestCustom")) {
+ // Remove Back and Forward, and add Inspector action.
+ webkit_context_menu_remove(menu, webkit_context_menu_first(menu));
+ webkit_context_menu_remove(menu, webkit_context_menu_first(menu));
+ webkit_context_menu_append(menu, webkit_context_menu_item_new_separator());
+ webkit_context_menu_append(menu, webkit_context_menu_item_new_from_stock_action(WEBKIT_CONTEXT_MENU_ACTION_INSPECT_ELEMENT));
+ webkit_context_menu_set_user_data(menu, serializeContextMenu(menu));
+ return TRUE;
+ }
+
+ if (!g_strcmp0(pageURI, "ContextMenuTestClear")) {
+ webkit_context_menu_remove_all(menu);
+ return TRUE;
+ }
+
+ if (!g_strcmp0(pageURI, "ContextMenuTestNode")) {
+ WebKitDOMNode* node = webkit_web_hit_test_result_get_node(hitTestResult);
+ g_assert(WEBKIT_DOM_IS_NODE(node));
+ webkit_context_menu_set_user_data(menu, serializeNode(node));
return TRUE;
+ }
return FALSE;
}
+static void consoleMessageSentCallback(WebKitWebPage* webPage, WebKitConsoleMessage* consoleMessage)
+{
+ g_assert(consoleMessage);
+ GRefPtr<GVariant> variant = g_variant_new("(uusus)", webkit_console_message_get_source(consoleMessage),
+ webkit_console_message_get_level(consoleMessage), webkit_console_message_get_text(consoleMessage),
+ webkit_console_message_get_line(consoleMessage), webkit_console_message_get_source_id(consoleMessage));
+ GUniquePtr<char> messageString(g_variant_print(variant.get(), FALSE));
+ GRefPtr<WebKitDOMDOMWindow> window = adoptGRef(webkit_dom_document_get_default_view(webkit_web_page_get_dom_document(webPage)));
+ g_assert(WEBKIT_DOM_IS_DOM_WINDOW(window.get()));
+ webkit_dom_dom_window_webkit_message_handlers_post_message(window.get(), "console", messageString.get());
+}
+
static void pageCreatedCallback(WebKitWebExtension* extension, WebKitWebPage* webPage, gpointer)
{
g_signal_connect(webPage, "document-loaded", G_CALLBACK(documentLoadedCallback), extension);
g_signal_connect(webPage, "notify::uri", G_CALLBACK(uriChangedCallback), extension);
- g_signal_connect(webPage, "send-request", G_CALLBACK(sendRequestCallback), 0);
+ g_signal_connect(webPage, "send-request", G_CALLBACK(sendRequestCallback), nullptr);
+ g_signal_connect(webPage, "context-menu", G_CALLBACK(contextMenuCallback), nullptr);
+ g_signal_connect(webPage, "console-message-sent", G_CALLBACK(consoleMessageSentCallback), nullptr);
}
static JSValueRef echoCallback(JSContextRef jsContext, JSObjectRef, JSObjectRef, size_t argumentCount, const JSValueRef arguments[], JSValueRef*)
@@ -233,14 +322,20 @@ static void methodCallCallback(GDBusConnection* connection, const char* sender,
g_dbus_method_invocation_return_value(invocation, 0);
} else if (!g_strcmp0(methodName, "AbortProcess")) {
abort();
- } else if (!g_strcmp0(methodName, "GetInitializationUserData")) {
- g_assert(initializationUserData);
- g_assert(g_variant_is_of_type(initializationUserData.get(), G_VARIANT_TYPE_STRING));
- g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)",
- g_variant_get_string(initializationUserData.get(), nullptr)));
} else if (!g_strcmp0(methodName, "GetProcessIdentifier")) {
g_dbus_method_invocation_return_value(invocation,
g_variant_new("(u)", static_cast<guint32>(getCurrentProcessID())));
+ } else if (!g_strcmp0(methodName, "RemoveAVPluginsFromGSTRegistry")) {
+ gst_init(nullptr, nullptr);
+ static const char* avPlugins[] = { "libav", "omx", "vaapi", nullptr };
+ GstRegistry* registry = gst_registry_get();
+ for (unsigned i = 0; avPlugins[i]; ++i) {
+ if (GstPlugin* plugin = gst_registry_find_plugin(registry, avPlugins[i])) {
+ gst_registry_remove_plugin(registry, plugin);
+ gst_object_unref(plugin);
+ }
+ }
+ g_dbus_method_invocation_return_value(invocation, nullptr);
}
}
@@ -268,38 +363,38 @@ static void busAcquiredCallback(GDBusConnection* connection, const char* name, g
g_object_set_data(G_OBJECT(userData), "dbus-connection", connection);
while (delayedSignalsQueue.size()) {
- OwnPtr<DelayedSignal> delayedSignal = delayedSignalsQueue.takeFirst();
- switch (delayedSignal->type) {
+ DelayedSignal delayedSignal = delayedSignalsQueue.takeFirst();
+ switch (delayedSignal.type) {
case DocumentLoadedSignal:
emitDocumentLoaded(connection);
break;
case URIChangedSignal:
- emitURIChanged(connection, delayedSignal->uri.data());
+ emitURIChanged(connection, delayedSignal.uri.data());
break;
}
}
}
-static GUniquePtr<char> makeBusName(GVariant* userData)
+static void registerGResource(void)
{
- // When the web extension is used by TestMultiprocess, an uint32
- // identifier is passed as user data. It uniquely identifies
- // the web process, and the UI side expects it added as suffix to
- // the bus name.
- if (userData && g_variant_is_of_type(userData, G_VARIANT_TYPE_UINT32))
- return GUniquePtr<char>(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", g_variant_get_uint32(userData)));
-
- return GUniquePtr<char>(g_strdup("org.webkit.gtk.WebExtensionTest"));
+ GUniquePtr<char> resourcesPath(g_build_filename(WEBKIT_EXEC_PATH, "TestWebKitAPI", "WebKit2Gtk", "resources", "webkit2gtk-tests-resources.gresource", nullptr));
+ GResource* resource = g_resource_load(resourcesPath.get(), nullptr);
+ g_assert(resource);
+
+ g_resources_register(resource);
+ g_resource_unref(resource);
}
extern "C" void webkit_web_extension_initialize_with_user_data(WebKitWebExtension* extension, GVariant* userData)
{
- initializationUserData = userData;
-
g_signal_connect(extension, "page-created", G_CALLBACK(pageCreatedCallback), extension);
g_signal_connect(webkit_script_world_get_default(), "window-object-cleared", G_CALLBACK(windowObjectCleared), 0);
- GUniquePtr<char> busName(makeBusName(userData));
+ registerGResource();
+
+ g_assert(userData);
+ g_assert(g_variant_is_of_type(userData, G_VARIANT_TYPE_UINT32));
+ GUniquePtr<char> busName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", g_variant_get_uint32(userData)));
g_bus_own_name(
G_BUS_TYPE_SESSION,
busName.get(),
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebProcessTest.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebProcessTest.cpp
index 09d0785aa..bc058693d 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebProcessTest.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebProcessTest.cpp
@@ -22,8 +22,11 @@
#include <JavaScriptCore/JSRetainPtr.h>
#include <gio/gio.h>
+#include <wtf/HashSet.h>
#include <wtf/NeverDestroyed.h>
-#include <wtf/gobject/GUniquePtr.h>
+#include <wtf/glib/GUniquePtr.h>
+
+static HashSet<GObject*> s_watchedObjects;
typedef HashMap<String, std::function<std::unique_ptr<WebProcessTest> ()>> TestsMap;
static TestsMap& testsMap()
@@ -34,7 +37,15 @@ static TestsMap& testsMap()
void WebProcessTest::add(const String& testName, std::function<std::unique_ptr<WebProcessTest> ()> closure)
{
- testsMap().add(testName, std::move(closure));
+ testsMap().add(testName, WTFMove(closure));
+}
+
+void WebProcessTest::assertObjectIsDeletedWhenTestFinishes(GObject* object)
+{
+ s_watchedObjects.add(object);
+ g_object_weak_ref(object, [](gpointer, GObject* finalizedObject) {
+ s_watchedObjects.remove(finalizedObject);
+ }, nullptr);
}
std::unique_ptr<WebProcessTest> WebProcessTest::create(const String& testName)
@@ -53,6 +64,14 @@ static JSValueRef runTest(JSContextRef context, JSObjectRef function, JSObjectRe
WebKitWebPage* webPage = WEBKIT_WEB_PAGE(JSObjectGetPrivate(thisObject));
g_assert(WEBKIT_IS_WEB_PAGE(webPage));
+ // Test /WebKitDOMNode/dom-cache is an exception, because it's called 3 times, so
+ // the WebPage is destroyed after the third time.
+ if (g_str_equal(testPath.get(), "WebKitDOMNode/dom-cache")) {
+ static unsigned domCacheTestRunCount = 0;
+ if (++domCacheTestRunCount == 3)
+ WebProcessTest::assertObjectIsDeletedWhenTestFinishes(G_OBJECT(webPage));
+ } else
+ WebProcessTest::assertObjectIsDeletedWhenTestFinishes(G_OBJECT(webPage));
std::unique_ptr<WebProcessTest> test = WebProcessTest::create(String::fromUTF8(testPath.get()));
return JSValueMakeBoolean(context, test->runTest(g_strrstr(testPath.get(), "/") + 1, webPage));
@@ -67,6 +86,16 @@ static const JSStaticFunction webProcessTestRunnerStaticFunctions[] =
static void webProcessTestRunnerFinalize(JSObjectRef object)
{
g_object_unref(JSObjectGetPrivate(object));
+
+ if (s_watchedObjects.isEmpty())
+ return;
+
+ g_print("Leaked objects in WebProcess:");
+ for (const auto object : s_watchedObjects)
+ g_print(" %s(%p)", g_type_name_from_instance(reinterpret_cast<GTypeInstance*>(object)), object);
+ g_print("\n");
+
+ g_assert(s_watchedObjects.isEmpty());
}
static void windowObjectClearedCallback(WebKitScriptWorld* world, WebKitWebPage* webPage, WebKitFrame* frame, WebKitWebExtension* extension)
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebProcessTest.h b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebProcessTest.h
index fb4dd5d33..3715eb91e 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebProcessTest.h
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebProcessTest.h
@@ -19,7 +19,7 @@
#include <webkit2/webkit-web-extension.h>
#include <wtf/HashMap.h>
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
#include <wtf/text/StringHash.h>
#include <wtf/text/WTFString.h>
@@ -28,6 +28,8 @@ public:
virtual ~WebProcessTest() { }
virtual bool runTest(const char* testName, WebKitWebPage*) = 0;
+ static void assertObjectIsDeletedWhenTestFinishes(GObject*);
+
static void add(const String& testName, std::function<std::unique_ptr<WebProcessTest> ()>);
static std::unique_ptr<WebProcessTest> create(const String& testName);
};
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/blank.ico b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/blank.ico
new file mode 100644
index 000000000..ea848b991
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/blank.ico
Binary files differ
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/boring.html b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/boring.html
new file mode 100644
index 000000000..c0eeb49ee
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/boring.html
@@ -0,0 +1 @@
+<p>This is a boring HTML file.</p>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/link-title.js b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/link-title.js
new file mode 100644
index 000000000..2c824da38
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/link-title.js
@@ -0,0 +1 @@
+window.document.getElementById('WebKitLink').title;
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/test-cert.pem b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/test-cert.pem
new file mode 100644
index 000000000..b34301f25
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/test-cert.pem
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIIB9jCCAV+gAwIBAgIJALeuXBo+vwz9MA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV
+BAMMCTEyNy4wLjAuMTAeFw0xMjA3MTIxMjQ4MjRaFw0yMjA3MTAxMjQ4MjRaMBQx
+EjAQBgNVBAMMCTEyNy4wLjAuMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
+0TUzOQxHBIKDD2mkuq+tU92mQvDZg73B0G+Nhr2T2G6MbcLqIwjg1QYtBZWJ83tZ
+xMMEfiweHLF85Z9ohavAgxJlKG7YmvZO79KkFpmjV2W5CVRm0eYMPnzmxNCoaYqo
+DLl0zsH6KZOLPKu/fX4eDX9XpAP1f83hWB1UFBmHKN8CAwEAAaNQME4wHQYDVR0O
+BBYEFDHv5ZQ1BdmhzTsDUEoY55EXyUdKMB8GA1UdIwQYMBaAFDHv5ZQ1BdmhzTsD
+UEoY55EXyUdKMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAh3qMBx7v
+jSodMf3OyTqTLE7deLnmnCeBVpgzxRZEoizcGqYcjiqO27i5N5Z6KVQsnITnLiyC
+mUtuR5KnF69uTKUw4m/ugZe5whjig5Mq2l410KVK6EeG4tdLlfXR+wi4U5K4KjP6
+p4nchQUXLa2zcbJn+VBexJn6/9wdhr+DUGY=
+-----END CERTIFICATE-----
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/test-key.pem b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/test-key.pem
new file mode 100644
index 000000000..9036222ce
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/test-key.pem
@@ -0,0 +1,16 @@
+-----BEGIN PRIVATE KEY-----
+MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANE1MzkMRwSCgw9p
+pLqvrVPdpkLw2YO9wdBvjYa9k9hujG3C6iMI4NUGLQWVifN7WcTDBH4sHhyxfOWf
+aIWrwIMSZShu2Jr2Tu/SpBaZo1dluQlUZtHmDD585sTQqGmKqAy5dM7B+imTizyr
+v31+Hg1/V6QD9X/N4VgdVBQZhyjfAgMBAAECgYB2QwOUsRsIMprRwJ9tJNfvO7G7
+z5i1/zOrlxPC4jHMPBnIBlICwgcOhLI4oOLdr5H8R12n0VqoT7DRwP396iwlJipF
+iO1heDMn/8z8LPGwkCK/+ck04rMDksxWIdMwYKBXt9ahnJ/xRLzQ1/3AJiAGnoe5
+/QLXQweofd4mmfsjKQJBAO2CwT7uMP6nMjXgtVMJq5QP8UbeCS1sEOPJJbHuDxJB
+/HePQHBjq4kzG6CL4oO7T+5fDv4g+fIIHzuXerZ0imsCQQDhfmiTIc9OucEIfg6/
+ms0JiKSmWc+qoiOCtrILuQvFoNwJRciQANqeJs6wpaDvevSUvBLGfG/7b3HvaE5X
+iqBdAkBEQIvp2qcHtuJN60oQF7pPrRknxUyb2e8sljQX4pJAK+gyL19ULMAxiBdL
+Vod8VYqNtJFpY+6Pp9fZ1xjzb6ALAkEA4JzrDAw0lQXA+3WduUw4ixOadr2ldyG0
+36KebcDwsfZO18m0Q4UmPz0Gy7zgN0wxzuochaw0W6+iPUiYKOlEXQJBAMWQrPlu
+rrinoZS2f8doJ9BNNUa+RNpMug6UXc55qoUJlyiXEh+tu4AaMOtxuGIyC0sAcuw6
+XdAPVPXKd7Mne70=
+-----END PRIVATE KEY-----
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/webkit2gtk-tests.gresource.xml b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/webkit2gtk-tests.gresource.xml
new file mode 100644
index 000000000..87bc50158
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/webkit2gtk-tests.gresource.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/webkit/webkit2gtk/tests/">
+ <file alias="boring.html">Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/boring.html</file>
+ <file alias="link-title.js">Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/link-title.js</file>
+ </gresource>
+</gresources>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2ObjC/CustomProtocolsInvalidScheme_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2ObjC/CustomProtocolsInvalidScheme_Bundle.cpp
new file mode 100644
index 000000000..287f32ff5
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2ObjC/CustomProtocolsInvalidScheme_Bundle.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2013 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"
+
+#if WK_HAVE_C_SPI
+
+#include "InjectedBundleTest.h"
+#include <WebKit/WKBundlePage.h>
+
+namespace TestWebKitAPI {
+
+static WKBundlePagePolicyAction decidePolicyForNavigationAction(WKBundlePageRef, WKBundleFrameRef, WKBundleNavigationActionRef, WKURLRequestRef request, WKTypeRef*, const void*)
+{
+ if (WKBundlePageCanHandleRequest(request))
+ return WKBundlePagePolicyActionUse;
+ return WKBundlePagePolicyActionPassThrough;
+}
+
+class CustomProtocolInvalidSchemeTest : public InjectedBundleTest {
+public:
+ CustomProtocolInvalidSchemeTest(const std::string& identifier)
+ : InjectedBundleTest(identifier)
+ {
+ }
+
+private:
+ virtual void didCreatePage(WKBundleRef, WKBundlePageRef bundlePage) override
+ {
+ WKBundlePagePolicyClientV0 policyClient;
+ memset(&policyClient, 0, sizeof(policyClient));
+
+ policyClient.base.version = 0;
+ policyClient.decidePolicyForNavigationAction = decidePolicyForNavigationAction;
+
+ WKBundlePageSetPolicyClient(bundlePage, &policyClient.base);
+ }
+};
+
+static InjectedBundleTest::Register<CustomProtocolInvalidSchemeTest> registrar("CustomProtocolInvalidSchemeTest");
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2ObjC/PreventImageLoadWithAutoResizing_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2ObjC/PreventImageLoadWithAutoResizing_Bundle.cpp
new file mode 100644
index 000000000..dde94407a
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2ObjC/PreventImageLoadWithAutoResizing_Bundle.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2013 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"
+
+#if WK_HAVE_C_SPI
+
+#include "InjectedBundleTest.h"
+#include "PlatformUtilities.h"
+#include "Test.h"
+
+#include <WebKit/WKBundlePage.h>
+
+#include <wtf/Assertions.h>
+
+namespace TestWebKitAPI {
+
+class DenyWillSendRequestTest : public InjectedBundleTest {
+public:
+ DenyWillSendRequestTest(const std::string& identifier)
+ : InjectedBundleTest(identifier)
+ {
+ }
+
+ static WKURLRequestRef willSendRequestForFrame(WKBundlePageRef, WKBundleFrameRef frame, uint64_t resourceIdentifier, WKURLRequestRef request, WKURLResponseRef redirectResponse, const void *clientInfo)
+ {
+ return 0;
+ }
+
+ virtual void didCreatePage(WKBundleRef bundle, WKBundlePageRef page)
+ {
+ WKBundlePageResourceLoadClientV0 resourceLoadClient;
+ memset(&resourceLoadClient, 0, sizeof(resourceLoadClient));
+
+ resourceLoadClient.base.version = 0;
+ resourceLoadClient.willSendRequestForFrame = willSendRequestForFrame;
+
+ WKBundlePageSetResourceLoadClient(page, &resourceLoadClient.base);
+
+ }
+};
+
+static InjectedBundleTest::Register<DenyWillSendRequestTest> registrar("DenyWillSendRequestTest");
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/test_utils.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/test_utils.c
deleted file mode 100644
index 6bb645d0d..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/test_utils.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2010 Arno Renevier
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "test_utils.h"
-
-#include <glib.h>
-#include <glib/gstdio.h>
-
-int testutils_relative_chdir(const gchar *targetFilename, const gchar *executablePath)
-{
- /* user can set location of the webkit repository directory if it differs from build directory */
- const gchar *repoPath = g_getenv("WEBKITREPODIR");
- if (repoPath) {
- if (g_chdir(repoPath))
- return -1;
- } else if (g_chdir(g_path_get_dirname(executablePath)))
- return -1;
-
- while (!g_file_test(targetFilename, G_FILE_TEST_EXISTS)) {
- gchar *pathName;
- if (g_chdir(".."))
- return -1;
- g_assert(!g_str_equal((pathName = g_get_current_dir()), "/"));
- g_free(pathName);
- }
-
- gchar *dirName = g_path_get_dirname(targetFilename);
- if (g_chdir(dirName)) {
- g_free(dirName);
- return -1;
- }
-
- g_free(dirName);
- return 0;
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testatk.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testatk.c
deleted file mode 100644
index 2a2db6146..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testatk.c
+++ /dev/null
@@ -1,1476 +0,0 @@
-/*
- * Copyright (C) 2009 Igalia S.L.
- * Copyright (C) 2013 Samsung Electronics. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <errno.h>
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <gtk/gtk.h>
-#include <locale.h>
-#include <unistd.h>
-#include <webkit/webkit.h>
-
-static const char* centeredContents = "<html><body><p style='text-align: center;'>Short line</p><p style='text-align: center;'>Long-size line with some foo bar baz content</p><p style='text-align: center;'>Short line</p><p style='text-align: center;'>This is a multi-line paragraph<br />where the first line<br />is the biggest one</p></body></html>";
-
-static const char* contents = "<html><body><p>This is a test. This is the second sentence. And this the third.</p></body></html>";
-
-static const char* contentsInTableWithHeaders = "<html><body><table><tr><th>foo</th><th>bar</th><th colspan='2'>baz</th></tr><tr><th>qux</th><td>1</td><td>2</td><td>3</td></tr><tr><th rowspan='2'>quux</th><td>4</td><td>5</td><td>6</td></tr><tr><td>6</td><td>7</td><td>8</td></tr><tr><th>corge</th><td>9</td><td>10</td><td>11</td></tr></table><table><tr><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr></table></body></html>";
-
-static const char* contentsWithExtraneousWhiteSpaces = "<html><head><body><p>This\n paragraph\n is\n borked!</p></body></html>";
-
-static const char* comboBoxSelector = "<html><body><select><option selected value='foo'>foo</option><option value='bar'>bar</option></select></body></html>";
-
-static const char* embeddedObjects = "<html><body><p>Choose: <input value='foo' type='checkbox'/>foo <input value='bar' type='checkbox'/>bar (pick one)</p><p>Choose: <select name='foo'><option>bar</option><option>baz</option></select> (pick one)</p><p><input name='foobarbutton' value='foobar' type='button'/></p></body></html>";
-
-static const char* formWithTextInputs = "<html><body><form><input type='text' name='entry' /><input type='password' name='passwordEntry' /></form></body></html>";
-
-static const char* hypertextAndHyperlinks = "<html><body><p>A paragraph with no links at all</p><p><a href='http://foo.bar.baz/'>A line</a> with <a href='http://bar.baz.foo/'>a link in the middle</a> as well as at the beginning and <a href='http://baz.foo.bar/'>at the end</a></p><ol><li>List item with a <span><a href='http://foo.bar.baz/'>link inside a span node</a></span></li></ol></body></html>";
-
-static const char* layoutAndDataTables = "<html><body><table><tr><th>Odd</th><th>Even</th></tr><tr><td>1</td><td>2</td></tr></table><table><tr><td>foo</td><td>bar</td></tr></table></body></html>";
-
-static const char* linksWithInlineImages = "<html><head><style>a.http:before {content: url(no-image.png);}</style><body><p><a class='http' href='foo'>foo</a> bar baz</p><p>foo <a class='http' href='bar'>bar</a> baz</p><p>foo bar <a class='http' href='baz'>baz</a></p></body></html>";
-
-static const char* listsOfItems = "<html><body><ul><li>text only</li><li><a href='foo'>link only</a></li><li>text and a <a href='bar'>link</a></li></ul><ol><li>text only</li><li><a href='foo'>link only</a></li><li>text and a <a href='bar'>link</a></li></ol></body></html>";
-
-static const char* textForCaretBrowsing = "<html><body><h1>A text header</h1><p>A paragraph <a href='http://foo.bar.baz/'>with a link</a> in the middle</p><ol><li>A list item</li><li><span style='display:block;'>Block span in a list item</span><span>Inline span in a list item</span></li><li><a href='foo'><span style='display:block;'>Block span in a link in a list item</span><span>Inline span in a link in a list item</span></a></li></ol><select><option selected value='foo'>An option in a combo box</option></select><input type='text' name='foo' value='foo bar baz' /><table><tr><td>a table cell</td><td></td><td><a href='foo'><span style='display:block;'>Block span in a link in a table cell</span><span>Inline span in a link in a table cell</span></a></td><td><span style='display:block;'>Block span in a table cell</span><span>Inline span in a table cell</span></td></tr></table><h4><a href='foo'><span style='display:block;'>Block span in a link in a heading</span><span>Inline span in a link in a heading</span></h4><h4><span style='display:block;'>Block span in a heading</span><span>Inline span in a heading</span></h4></body></html>";
-
-static const char* textForSelections = "<html><body><p>A paragraph with plain text</p><p>A paragraph with <a href='http://webkit.org'>a link</a> in the middle</p><ol><li>A list item</li></ol><select></body></html>";
-
-static const char* textWithAttributes = "<html><head><style>.st1 {font-family: monospace; color:rgb(120,121,122);} .st2 {text-decoration:underline; background-color:rgb(80,81,82);}</style></head><body><p style=\"font-size:14; text-align:right;\">This is the <i>first</i><b> sentence of this text.</b></p><p class=\"st1\">This sentence should have an style applied <span class=\"st2\">and this part should have another one</span>.</p><p>x<sub>1</sub><sup>2</sup>=x<sub>2</sub><sup>3</sup></p><p style=\"text-align:center;\">This sentence is the <strike>last</strike> one.</p></body></html>";
-
-static AtkObject* getWebAreaObject(WebKitWebView* webView)
-{
- /* Manually spin the main context to make sure the accessible
- objects are properly created before continuing. */
- while (g_main_context_pending(0))
- g_main_context_iteration(0, TRUE);
-
- AtkObject* rootObject = gtk_widget_get_accessible(GTK_WIDGET(webView));
- if (!rootObject)
- return NULL;
-
- AtkObject* webAreaObject = atk_object_ref_accessible_child(rootObject, 0);
- if (!webAreaObject)
- return NULL;
-
- /* We don't need the extra ref here. */
- g_object_unref(webAreaObject);
-
- return webAreaObject;
-}
-
-static gchar* textCaretMovedResult = 0;
-
-static void textCaretMovedCallback(AtkText* text, gint pos, gpointer data)
-{
- g_assert(ATK_IS_TEXT(text));
-
- g_free(textCaretMovedResult);
- AtkRole role = atk_object_get_role(ATK_OBJECT(text));
- textCaretMovedResult = g_strdup_printf("|%s|%d|", atk_role_get_name(role), pos);
-}
-
-static void testWebkitAtkCaretOffsets()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, textForCaretBrowsing, 0, 0, 0);
-
- AtkObject* object = getWebAreaObject(webView);
- g_assert(object);
-
- AtkObject* header = atk_object_ref_accessible_child(object, 0);
- g_assert(ATK_IS_TEXT(header));
- g_signal_connect(header, "text-caret-moved", G_CALLBACK(textCaretMovedCallback), 0);
-
- /* It should be possible to place the caret inside a header. */
- gboolean result = atk_text_set_caret_offset(ATK_TEXT(header), 5);
- g_assert_cmpint(result, ==, TRUE);
- gint offset = atk_text_get_caret_offset(ATK_TEXT(header));
- g_assert_cmpint(offset, ==, 5);
- g_assert_cmpstr(textCaretMovedResult, ==, "|heading|5|");
-
- AtkObject* paragraph = atk_object_ref_accessible_child(object, 1);
- g_assert(ATK_IS_TEXT(paragraph));
- g_signal_connect(paragraph, "text-caret-moved", G_CALLBACK(textCaretMovedCallback), 0);
-
- /* It should be possible to place the caret inside a paragraph and a link. */
- result = atk_text_set_caret_offset(ATK_TEXT(paragraph), 5);
- g_assert_cmpint(result, ==, TRUE);
- offset = atk_text_get_caret_offset(ATK_TEXT(paragraph));
- g_assert_cmpint(offset, ==, 5);
- g_assert_cmpstr(textCaretMovedResult, ==, "|paragraph|5|");
-
- result = atk_text_set_caret_offset(ATK_TEXT(paragraph), 20);
- g_assert_cmpint(result, ==, TRUE);
- offset = atk_text_get_caret_offset(ATK_TEXT(paragraph));
- g_assert_cmpint(offset, ==, 20);
- g_assert_cmpstr(textCaretMovedResult, ==, "|paragraph|20|");
-
- result = atk_text_set_caret_offset(ATK_TEXT(paragraph), 30);
- g_assert_cmpint(result, ==, TRUE);
- offset = atk_text_get_caret_offset(ATK_TEXT(paragraph));
- g_assert_cmpint(offset, ==, 30);
- g_assert_cmpstr(textCaretMovedResult, ==, "|paragraph|30|");
-
- AtkObject* link = atk_object_ref_accessible_child(paragraph, 0);
- g_assert(ATK_IS_TEXT(link));
-
- result = atk_text_set_caret_offset(ATK_TEXT(link), 5);
- g_assert_cmpint(result, ==, TRUE);
- offset = atk_text_get_caret_offset(ATK_TEXT(link));
- g_assert_cmpint(offset, ==, 5);
- /* Positions inside links are reported relative to the paragraph. */
- g_assert_cmpstr(textCaretMovedResult, ==, "|paragraph|17|");
-
- AtkObject* list = atk_object_ref_accessible_child(object, 2);
- g_assert(ATK_OBJECT(list));
- g_assert(atk_object_get_role(list) == ATK_ROLE_LIST);
- g_assert_cmpint(atk_object_get_n_accessible_children(list), ==, 3);
-
- AtkObject* listItem = atk_object_ref_accessible_child(list, 0);
- listItem = atk_object_ref_accessible_child(list, 2);
- g_assert(ATK_IS_TEXT(listItem));
-
- /* It's not possible to place the caret inside an item's marker. */
- result = atk_text_set_caret_offset(ATK_TEXT(listItem), 1);
- g_assert_cmpint(result, ==, FALSE);
-
- /* It should be possible to place the caret inside an item's text. */
- result = atk_text_set_caret_offset(ATK_TEXT(listItem), 5);
- g_assert_cmpint(result, ==, TRUE);
- offset = atk_text_get_caret_offset(ATK_TEXT(listItem));
- g_assert_cmpint(offset, ==, 5);
-
- AtkObject* panel = atk_object_ref_accessible_child(object, 3);
- g_assert(ATK_IS_OBJECT(panel));
- g_assert(atk_object_get_role(panel) == ATK_ROLE_PANEL);
-
- AtkObject* comboBox = atk_object_ref_accessible_child(panel, 0);
- g_assert(ATK_IS_OBJECT(comboBox));
- g_assert(atk_object_get_role(comboBox) == ATK_ROLE_COMBO_BOX);
-
- AtkObject* menuPopup = atk_object_ref_accessible_child(comboBox, 0);
- g_assert(ATK_IS_OBJECT(menuPopup));
- g_assert(atk_object_get_role(menuPopup) == ATK_ROLE_MENU);
-
- AtkObject* comboBoxOption = atk_object_ref_accessible_child(menuPopup, 0);
- g_assert(ATK_IS_OBJECT(comboBoxOption));
- g_assert(atk_object_get_role(comboBoxOption) == ATK_ROLE_MENU_ITEM);
-
- /* It's not possible to place the caret inside an option for a combobox. */
- result = atk_text_set_caret_offset(ATK_TEXT(comboBoxOption), 1);
- g_assert_cmpint(result, ==, FALSE);
-
- AtkObject* textEntry = atk_object_ref_accessible_child(panel, 1);
- g_assert(ATK_IS_OBJECT(textEntry));
- g_assert(atk_object_get_role(textEntry) == ATK_ROLE_ENTRY);
-
- result = atk_text_set_caret_offset(ATK_TEXT(textEntry), 5);
- g_assert_cmpint(result, ==, TRUE);
- offset = atk_text_get_caret_offset(ATK_TEXT(textEntry));
- g_assert_cmpint(offset, ==, 5);
-
- AtkObject* table = atk_object_ref_accessible_child(object, 4);
- g_assert(ATK_IS_OBJECT(table));
- g_assert(atk_object_get_role(table) == ATK_ROLE_TABLE);
- g_assert_cmpint(atk_object_get_n_accessible_children(table), ==, 4);
-
- AtkObject* tableCell = atk_object_ref_accessible_child(table, 0);
- g_assert(atk_object_get_role(tableCell) == ATK_ROLE_TABLE_CELL);
- result = atk_text_set_caret_offset(ATK_TEXT(tableCell), 2);
- g_assert_cmpint(result, ==, TRUE);
- offset = atk_text_get_caret_offset(ATK_TEXT(tableCell));
- g_assert_cmpint(offset, ==, 2);
-
- g_free(textCaretMovedResult);
-
- g_object_unref(paragraph);
- g_object_unref(link);
- g_object_unref(list);
- g_object_unref(listItem);
- g_object_unref(panel);
- g_object_unref(comboBox);
- g_object_unref(menuPopup);
- g_object_unref(comboBoxOption);
- g_object_unref(textEntry);
- g_object_unref(table);
- g_object_unref(tableCell);
- g_object_unref(webView);
-}
-
-static void testWebkitAtkCaretOffsetsAndExtranousWhiteSpaces()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, contentsWithExtraneousWhiteSpaces, 0, 0, 0);
-
- /* Enable caret browsing. */
- WebKitWebSettings* settings = webkit_web_view_get_settings(webView);
- g_object_set(G_OBJECT(settings), "enable-caret-browsing", TRUE, NULL);
-
- /* Get to the inner AtkText object. */
- AtkObject* object = getWebAreaObject(webView);
- g_assert(object);
- object = atk_object_ref_accessible_child(object, 0);
- g_assert(object);
-
- AtkText* textObject = ATK_TEXT(object);
- g_assert(ATK_IS_TEXT(textObject));
-
- gint characterCount = atk_text_get_character_count(textObject);
- g_assert_cmpint(characterCount, ==, 25);
-
- gboolean result = atk_text_set_caret_offset(textObject, characterCount - 1);
- g_assert_cmpint(result, ==, TRUE);
-
- gint caretOffset = atk_text_get_caret_offset(textObject);
- g_assert_cmpint(caretOffset, ==, characterCount - 1);
-
- result = atk_text_set_caret_offset(textObject, characterCount);
- g_assert_cmpint(result, ==, TRUE);
-
- caretOffset = atk_text_get_caret_offset(textObject);
- g_assert_cmpint(caretOffset, ==, characterCount);
-
- g_object_unref(object);
- g_object_unref(webView);
-}
-
-static void testWebkitAtkComboBox()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, comboBoxSelector, 0, 0, 0);
-
- AtkObject* object = getWebAreaObject(webView);
- g_assert(object);
-
- AtkObject* formObject = atk_object_ref_accessible_child(object, 0);
- g_assert(formObject);
-
- AtkObject* comboBox = atk_object_ref_accessible_child(formObject, 0);
- g_assert(ATK_IS_OBJECT(comboBox));
-
- AtkObject* menuPopup = atk_object_ref_accessible_child(comboBox, 0);
- g_assert(ATK_IS_OBJECT(menuPopup));
-
- AtkObject* item1 = atk_object_ref_accessible_child(menuPopup, 0);
- g_assert(ATK_IS_OBJECT(item1));
-
- AtkObject* item2 = atk_object_ref_accessible_child(menuPopup, 1);
- g_assert(ATK_IS_OBJECT(item2));
-
- /* Check roles. */
- g_assert(atk_object_get_role(comboBox) == ATK_ROLE_COMBO_BOX);
- g_assert(atk_object_get_role(menuPopup) == ATK_ROLE_MENU);
- g_assert(atk_object_get_role(item1) == ATK_ROLE_MENU_ITEM);
- g_assert(atk_object_get_role(item2) == ATK_ROLE_MENU_ITEM);
-
- /* Check the implementation of the AtkSelection interface. */
- g_assert(ATK_IS_SELECTION(comboBox));
- AtkSelection* atkSelection = ATK_SELECTION(comboBox);
- g_assert_cmpint(atk_selection_get_selection_count(atkSelection), ==, 1);
- g_assert(atk_selection_is_child_selected(atkSelection, 0));
- g_assert(!atk_selection_is_child_selected(atkSelection, 1));
- AtkObject* selectedItem = atk_selection_ref_selection(atkSelection, 0);
- g_assert(selectedItem == item1);
- g_object_unref(selectedItem);
-
- /* Check that the menu popup has 0 links and doesn't crash from checking. */
- gint nLinks = atk_hypertext_get_n_links(ATK_HYPERTEXT(menuPopup));
- g_assert_cmpint(nLinks, ==, 0);
-
- /* Check the implementations of the AtkAction interface. */
- g_assert(ATK_IS_ACTION(comboBox));
- AtkAction* atkAction = ATK_ACTION(comboBox);
- g_assert_cmpint(atk_action_get_n_actions(atkAction), ==, 1);
- g_assert(atk_action_do_action(atkAction, 0));
-
- g_assert(ATK_IS_ACTION(menuPopup));
- atkAction = ATK_ACTION(menuPopup);
- g_assert_cmpint(atk_action_get_n_actions(atkAction), ==, 1);
- g_assert(atk_action_do_action(atkAction, 0));
-
- g_assert(ATK_IS_ACTION(item1));
- atkAction = ATK_ACTION(item1);
- g_assert_cmpint(atk_action_get_n_actions(atkAction), ==, 1);
- g_assert(atk_action_do_action(atkAction, 0));
-
- g_assert(ATK_IS_ACTION(item2));
- atkAction = ATK_ACTION(item2);
- g_assert_cmpint(atk_action_get_n_actions(atkAction), ==, 1);
- g_assert(atk_action_do_action(atkAction, 0));
-
- /* After selecting the second item, selection should have changed. */
- g_assert_cmpint(atk_selection_get_selection_count(atkSelection), ==, 1);
- g_assert(!atk_selection_is_child_selected(atkSelection, 0));
- g_assert(atk_selection_is_child_selected(atkSelection, 1));
- selectedItem = atk_selection_ref_selection(atkSelection, 0);
- g_assert(selectedItem == item2);
- g_object_unref(selectedItem);
-
- g_object_unref(formObject);
- g_object_unref(comboBox);
- g_object_unref(menuPopup);
- g_object_unref(item1);
- g_object_unref(item2);
- g_object_unref(webView);
-}
-
-static gchar* loadingEventsResult = 0;
-
-static void updateLoadingEventsResult(const gchar* signalName)
-{
- g_assert(signalName);
-
- gchar* previousResult = loadingEventsResult;
- loadingEventsResult = g_strdup_printf("%s|%s", previousResult, signalName);
- g_free(previousResult);
-}
-
-static gboolean documentLoadingEventCallback(GSignalInvocationHint *signalHint, guint numParamValues, const GValue *paramValues, gpointer data)
-{
- // At least we should receive the instance emitting the signal.
- if (numParamValues < 1)
- return TRUE;
-
- GSignalQuery signal_query;
- g_signal_query(signalHint->signal_id, &signal_query);
-
- updateLoadingEventsResult(signal_query.signal_name);
- return TRUE;
-}
-
-static void testWebkitAtkDocumentLoadingEvents()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
-
- /* Connect globally to see those events during a future load. */
- guint loadCompleteListenerId = atk_add_global_event_listener(documentLoadingEventCallback, "ATK:AtkDocument:load-complete");
-
- /* Do the load, so we can see those events happening. */
- loadingEventsResult = g_strdup("");
- webkit_web_view_load_string(webView, contents, 0, 0, 0);
-
- /* Trigger the creation of the full accessibility hierarchy by
- asking for the webArea object, so we can listen to events. */
- getWebAreaObject(webView);
-
- atk_remove_global_event_listener(loadCompleteListenerId);
-
- g_assert_cmpstr(loadingEventsResult, ==, "|load-complete");
-
- g_free(loadingEventsResult);
- g_object_unref(webView);
-}
-
-static void testWebkitAtkEmbeddedObjects()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, embeddedObjects, 0, 0, 0);
-
- AtkObject* object = getWebAreaObject(webView);
- g_assert(object);
-
- AtkText* paragraph1 = ATK_TEXT(atk_object_ref_accessible_child(object, 0));
- g_assert(ATK_IS_TEXT(paragraph1));
- g_assert(ATK_IS_HYPERTEXT(paragraph1));
-
- gint nLinks = atk_hypertext_get_n_links(ATK_HYPERTEXT(paragraph1));
- g_assert_cmpint(nLinks, ==, 2);
-
- AtkHyperlink* hLink = atk_hypertext_get_link(ATK_HYPERTEXT(paragraph1), 0);
- g_assert(ATK_HYPERLINK(hLink));
- AtkObject* hLinkObject = atk_hyperlink_get_object(hLink, 0);
- g_assert(ATK_OBJECT(hLinkObject));
- g_assert(atk_object_get_role(hLinkObject) == ATK_ROLE_CHECK_BOX);
- g_assert_cmpint(atk_hyperlink_get_start_index(hLink), ==, 8);
- g_assert_cmpint(atk_hyperlink_get_end_index(hLink), ==, 9);
- g_assert_cmpint(atk_hyperlink_get_n_anchors(hLink), ==, 1);
- g_assert_cmpstr(atk_hyperlink_get_uri(hLink, 0), ==, 0);
-
- AtkText* paragraph2 = ATK_TEXT(atk_object_ref_accessible_child(object, 1));
- g_assert(ATK_IS_HYPERTEXT(paragraph2));
-
- nLinks = atk_hypertext_get_n_links(ATK_HYPERTEXT(paragraph2));
- g_assert_cmpint(nLinks, ==, 1);
-
- hLink = atk_hypertext_get_link(ATK_HYPERTEXT(paragraph2), 0);
- g_assert(ATK_HYPERLINK(hLink));
- hLinkObject = atk_hyperlink_get_object(hLink, 0);
- g_assert(ATK_OBJECT(hLinkObject));
- g_assert(atk_object_get_role(hLinkObject) == ATK_ROLE_COMBO_BOX);
- g_assert_cmpint(atk_hyperlink_get_start_index(hLink), ==, 8);
- g_assert_cmpint(atk_hyperlink_get_end_index(hLink), ==, 9);
- g_assert_cmpint(atk_hyperlink_get_n_anchors(hLink), ==, 1);
- g_assert_cmpstr(atk_hyperlink_get_uri(hLink, 0), ==, 0);
-
- AtkText* paragraph3 = ATK_TEXT(atk_object_ref_accessible_child(object, 2));
- g_assert(ATK_IS_HYPERTEXT(paragraph3));
-
- nLinks = atk_hypertext_get_n_links(ATK_HYPERTEXT(paragraph3));
- g_assert_cmpint(nLinks, ==, 1);
-
- hLink = atk_hypertext_get_link(ATK_HYPERTEXT(paragraph3), 0);
- g_assert(ATK_HYPERLINK(hLink));
- hLinkObject = atk_hyperlink_get_object(hLink, 0);
- g_assert(ATK_OBJECT(hLinkObject));
- g_assert(atk_object_get_role(hLinkObject) == ATK_ROLE_PUSH_BUTTON);
- g_assert_cmpint(atk_hyperlink_get_start_index(hLink), ==, 0);
- g_assert_cmpint(atk_hyperlink_get_end_index(hLink), ==, 1);
- g_assert_cmpint(atk_hyperlink_get_n_anchors(hLink), ==, 1);
- g_assert_cmpstr(atk_hyperlink_get_uri(hLink, 0), ==, 0);
-
- g_object_unref(paragraph1);
- g_object_unref(paragraph2);
- g_object_unref(paragraph3);
- g_object_unref(webView);
-}
-
-static void testWebkitAtkGetHeadersInTable()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, contentsInTableWithHeaders, 0, 0, 0);
-
- AtkObject* axWebView = getWebAreaObject(webView);
- g_assert(axWebView);
-
- /* Check table with both column and row headers. */
- AtkObject* table = atk_object_ref_accessible_child(axWebView, 0);
- g_assert(table);
- g_assert(atk_object_get_role(table) == ATK_ROLE_TABLE);
-
- AtkObject* colHeader = atk_table_get_column_header(ATK_TABLE(table), 0);
- g_assert(colHeader);
- g_assert(atk_object_get_role(colHeader) == ATK_ROLE_TABLE_CELL);
- g_assert(atk_object_get_index_in_parent(colHeader) == 0);
-
- colHeader = atk_table_get_column_header(ATK_TABLE(table), 1);
- g_assert(colHeader);
- g_assert(atk_object_get_role(colHeader) == ATK_ROLE_TABLE_CELL);
- g_assert(atk_object_get_index_in_parent(colHeader) == 1);
-
- colHeader = atk_table_get_column_header(ATK_TABLE(table), 2);
- g_assert(colHeader);
- g_assert(atk_object_get_role(colHeader) == ATK_ROLE_TABLE_CELL);
- g_assert(atk_object_get_index_in_parent(colHeader) == 2);
-
- colHeader = atk_table_get_column_header(ATK_TABLE(table), 3);
- g_assert(colHeader);
- g_assert(atk_object_get_role(colHeader) == ATK_ROLE_TABLE_CELL);
- g_assert(atk_object_get_index_in_parent(colHeader) == 2);
-
- AtkObject* rowHeader = atk_table_get_row_header(ATK_TABLE(table), 0);
- g_assert(rowHeader);
- g_assert(atk_object_get_role(rowHeader) == ATK_ROLE_TABLE_CELL);
- g_assert(atk_object_get_index_in_parent(rowHeader) == 0);
-
- rowHeader = atk_table_get_row_header(ATK_TABLE(table), 1);
- g_assert(rowHeader);
- g_assert(atk_object_get_role(rowHeader) == ATK_ROLE_TABLE_CELL);
- g_assert(atk_object_get_index_in_parent(rowHeader) == 3);
-
- rowHeader = atk_table_get_row_header(ATK_TABLE(table), 2);
- g_assert(rowHeader);
- g_assert(atk_object_get_role(rowHeader) == ATK_ROLE_TABLE_CELL);
- g_assert(atk_object_get_index_in_parent(rowHeader) == 7);
-
- rowHeader = atk_table_get_row_header(ATK_TABLE(table), 3);
- g_assert(rowHeader);
- g_assert(atk_object_get_role(rowHeader) == ATK_ROLE_TABLE_CELL);
- g_assert(atk_object_get_index_in_parent(rowHeader) == 7);
-
- g_object_unref(table);
-
- /* Check table with no headers at all. */
- table = atk_object_ref_accessible_child(axWebView, 1);
- g_assert(table);
- g_assert(atk_object_get_role(table) == ATK_ROLE_TABLE);
-
- colHeader = atk_table_get_column_header(ATK_TABLE(table), 0);
- g_assert(colHeader == 0);
-
- colHeader = atk_table_get_column_header(ATK_TABLE(table), 1);
- g_assert(colHeader == 0);
-
- rowHeader = atk_table_get_row_header(ATK_TABLE(table), 0);
- g_assert(rowHeader == 0);
-
- rowHeader = atk_table_get_row_header(ATK_TABLE(table), 1);
- g_assert(rowHeader == 0);
-
- g_object_unref(table);
- g_object_unref(webView);
-}
-
-static gint compAtkAttribute(AtkAttribute* a1, AtkAttribute* a2)
-{
- gint strcmpVal = g_strcmp0(a1->name, a2->name);
- if (strcmpVal)
- return strcmpVal;
- return g_strcmp0(a1->value, a2->value);
-}
-
-static gint compAtkAttributeName(AtkAttribute* a1, AtkAttribute* a2)
-{
- return g_strcmp0(a1->name, a2->name);
-}
-
-static gboolean atkAttributeSetAttributeNameHasValue(AtkAttributeSet* set, const gchar* attributeName, const gchar* value)
-{
- AtkAttribute at;
- at.name = (gchar*)attributeName;
- GSList* element = g_slist_find_custom(set, &at, (GCompareFunc)compAtkAttributeName);
- return element && !g_strcmp0(((AtkAttribute*)(element->data))->value, value);
-}
-
-static gboolean atkAttributeSetContainsAttributeName(AtkAttributeSet* set, const gchar* attributeName)
-{
- AtkAttribute at;
- at.name = (gchar*)attributeName;
- return g_slist_find_custom(set, &at, (GCompareFunc)compAtkAttributeName) ? true : false;
-}
-
-static gboolean atkAttributeSetAttributeHasValue(AtkAttributeSet* set, AtkTextAttribute attribute, const gchar* value)
-{
- return atkAttributeSetAttributeNameHasValue(set, atk_text_attribute_get_name(attribute), value);
-}
-
-static gboolean atkAttributeSetAreEqual(AtkAttributeSet* set1, AtkAttributeSet* set2)
-{
- if (!set1)
- return !set2;
-
- set1 = g_slist_sort(set1, (GCompareFunc)compAtkAttribute);
- set2 = g_slist_sort(set2, (GCompareFunc)compAtkAttribute);
-
- while (set1) {
- if (!set2 || compAtkAttribute(set1->data, set2->data))
- return FALSE;
-
- set1 = set1->next;
- set2 = set2->next;
- }
-
- return (!set2);
-}
-
-static void testWebkitAtkTextAttributes()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, textWithAttributes, 0, 0, 0);
-
- AtkObject* object = getWebAreaObject(webView);
- g_assert(object);
-
- AtkObject* child = atk_object_ref_accessible_child(object, 0);
- g_assert(child && ATK_IS_TEXT(child));
- AtkText* childText = ATK_TEXT(child);
-
- gint startOffset;
- gint endOffset;
- AtkAttributeSet* set1 = atk_text_get_run_attributes(childText, 0, &startOffset, &endOffset);
- g_assert_cmpint(startOffset, ==, 0);
- g_assert_cmpint(endOffset, ==, 12);
- g_assert(atkAttributeSetAreEqual(set1, 0));
-
- AtkAttributeSet* set2 = atk_text_get_run_attributes(childText, 15, &startOffset, &endOffset);
- g_assert_cmpint(startOffset, ==, 12);
- g_assert_cmpint(endOffset, ==, 17);
- g_assert(atkAttributeSetAttributeHasValue(set2, ATK_TEXT_ATTR_STYLE, "italic"));
-
- AtkAttributeSet* set3 = atk_text_get_run_attributes(childText, 17, &startOffset, &endOffset);
- g_assert_cmpint(startOffset, ==, 17);
- g_assert_cmpint(endOffset, ==, 40);
- g_assert(atkAttributeSetAttributeHasValue(set3, ATK_TEXT_ATTR_WEIGHT, "700"));
-
- AtkAttributeSet* set4 = atk_text_get_default_attributes(childText);
- g_assert(atkAttributeSetAttributeHasValue(set4, ATK_TEXT_ATTR_STYLE, "normal"));
- g_assert(atkAttributeSetAttributeHasValue(set4, ATK_TEXT_ATTR_JUSTIFICATION, "right"));
- g_assert(atkAttributeSetAttributeHasValue(set4, ATK_TEXT_ATTR_SIZE, "14"));
- atk_attribute_set_free(set1);
- atk_attribute_set_free(set2);
- atk_attribute_set_free(set3);
- atk_attribute_set_free(set4);
-
- g_object_unref(child);
- child = atk_object_ref_accessible_child(object, 1);
- g_assert(child && ATK_IS_TEXT(child));
- childText = ATK_TEXT(child);
-
- set1 = atk_text_get_default_attributes(childText);
- g_assert(atkAttributeSetAttributeHasValue(set1, ATK_TEXT_ATTR_FAMILY_NAME, "monospace"));
- g_assert(atkAttributeSetAttributeHasValue(set1, ATK_TEXT_ATTR_STYLE, "normal"));
- g_assert(atkAttributeSetAttributeHasValue(set1, ATK_TEXT_ATTR_STRIKETHROUGH, "false"));
- g_assert(atkAttributeSetAttributeHasValue(set1, ATK_TEXT_ATTR_WEIGHT, "400"));
- g_assert(atkAttributeSetAttributeHasValue(set1, ATK_TEXT_ATTR_FG_COLOR, "120,121,122"));
-
- set2 = atk_text_get_run_attributes(childText, 43, &startOffset, &endOffset);
- g_assert_cmpint(startOffset, ==, 43);
- g_assert_cmpint(endOffset, ==, 80);
- /* Checks that default attributes of text are not returned when called to atk_text_get_run_attributes. */
- g_assert(!atkAttributeSetAttributeHasValue(set2, ATK_TEXT_ATTR_FG_COLOR, "120,121,122"));
- g_assert(atkAttributeSetAttributeHasValue(set2, ATK_TEXT_ATTR_UNDERLINE, "single"));
- g_assert(atkAttributeSetAttributeHasValue(set2, ATK_TEXT_ATTR_BG_COLOR, "80,81,82"));
- atk_attribute_set_free(set1);
- atk_attribute_set_free(set2);
- g_object_unref(child);
-
- child = atk_object_ref_accessible_child(object, 2);
- g_assert(child && ATK_IS_TEXT(child));
- childText = ATK_TEXT(child);
-
- set1 = atk_text_get_run_attributes(childText, 0, &startOffset, &endOffset);
- set2 = atk_text_get_run_attributes(childText, 3, &startOffset, &endOffset);
- g_assert(atkAttributeSetAreEqual(set1, set2));
- atk_attribute_set_free(set2);
-
- set2 = atk_text_get_run_attributes(childText, 1, &startOffset, &endOffset);
- set3 = atk_text_get_run_attributes(childText, 5, &startOffset, &endOffset);
- g_assert(atkAttributeSetAreEqual(set2, set3));
- g_assert(!atkAttributeSetAreEqual(set1, set2));
- atk_attribute_set_free(set3);
-
- set3 = atk_text_get_run_attributes(childText, 2, &startOffset, &endOffset);
- set4 = atk_text_get_run_attributes(childText, 6, &startOffset, &endOffset);
- g_assert(atkAttributeSetAreEqual(set3, set4));
- g_assert(!atkAttributeSetAreEqual(set1, set3));
- g_assert(!atkAttributeSetAreEqual(set2, set3));
- atk_attribute_set_free(set1);
- atk_attribute_set_free(set2);
- atk_attribute_set_free(set3);
- atk_attribute_set_free(set4);
- g_object_unref(child);
-
- child = atk_object_ref_accessible_child(object, 3);
- g_assert(child && ATK_IS_TEXT(child));
- childText = ATK_TEXT(child);
- set1 = atk_text_get_run_attributes(childText, 24, &startOffset, &endOffset);
- g_assert_cmpint(startOffset, ==, 21);
- g_assert_cmpint(endOffset, ==, 25);
- g_assert(atkAttributeSetAttributeHasValue(set1, ATK_TEXT_ATTR_STRIKETHROUGH, "true"));
-
- set2 = atk_text_get_run_attributes(childText, 25, &startOffset, &endOffset);
- g_assert_cmpint(startOffset, ==, 25);
- g_assert_cmpint(endOffset, ==, 30);
- g_assert(atkAttributeSetAreEqual(set2, 0));
-
- set3 = atk_text_get_default_attributes(childText);
- g_assert(atkAttributeSetAttributeHasValue(set3, ATK_TEXT_ATTR_JUSTIFICATION, "center"));
- atk_attribute_set_free(set1);
- atk_attribute_set_free(set2);
- atk_attribute_set_free(set3);
-
- g_object_unref(child);
-}
-
-static gchar* textSelectionChangedResult = 0;
-
-static void textSelectionChangedCallback(AtkText* text, gpointer data)
-{
- g_assert(ATK_IS_TEXT(text));
-
- g_free(textSelectionChangedResult);
- AtkRole role = atk_object_get_role(ATK_OBJECT(text));
- int startOffset = 0;
- int endOffset = 0;
- atk_text_get_selection(ATK_TEXT(text), 0, &startOffset, &endOffset);
- textSelectionChangedResult = g_strdup_printf("|%s|%d|%d|", atk_role_get_name(role), startOffset, endOffset);
-}
-
-static void testWebkitAtkTextSelections()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, textForSelections, 0, 0, 0);
-
- AtkObject* object = getWebAreaObject(webView);
- g_assert(object);
-
- AtkText* paragraph1 = ATK_TEXT(atk_object_ref_accessible_child(object, 0));
- g_assert(ATK_IS_TEXT(paragraph1));
- g_signal_connect(paragraph1, "text-selection-changed", G_CALLBACK(textSelectionChangedCallback), 0);
-
- AtkText* paragraph2 = ATK_TEXT(atk_object_ref_accessible_child(object, 1));
- g_assert(ATK_IS_TEXT(paragraph2));
- g_signal_connect(paragraph2, "text-selection-changed", G_CALLBACK(textSelectionChangedCallback), 0);
-
- AtkText* link = ATK_TEXT(atk_object_ref_accessible_child(ATK_OBJECT(paragraph2), 0));
- g_assert(ATK_IS_TEXT(link));
-
- AtkObject* list = atk_object_ref_accessible_child(object, 2);
- g_assert(ATK_OBJECT(list));
-
- AtkText* listItem = ATK_TEXT(atk_object_ref_accessible_child(list, 0));
- g_assert(ATK_IS_TEXT(listItem));
-
- /* First paragraph (simple text). */
-
- /* Basic initial checks. */
- g_assert_cmpint(atk_text_get_n_selections(paragraph1), ==, 0);
-
- gint startOffset;
- gint endOffset;
- gchar* selectedText = atk_text_get_selection(paragraph1, 0, &startOffset, &endOffset);
- g_assert_cmpint(startOffset, ==, 0);
- g_assert_cmpint(endOffset, ==, 0);
- g_assert_cmpstr(selectedText, ==, 0);
- g_free (selectedText);
-
- /* Try removing a non existing (yet) selection. */
- gboolean result = atk_text_remove_selection(paragraph1, 0);
- g_assert(!result);
-
- /* Try setting a 0-char selection. */
- result = atk_text_set_selection(paragraph1, 0, 5, 5);
- g_assert(result);
-
- /* Make a selection and test it. */
- result = atk_text_set_selection(paragraph1, 0, 5, 25);
- g_assert(result);
- g_assert_cmpint(atk_text_get_n_selections(paragraph1), ==, 1);
- g_assert_cmpstr(textSelectionChangedResult, ==, "|paragraph|5|25|");
- selectedText = atk_text_get_selection(paragraph1, 0, &startOffset, &endOffset);
- g_assert_cmpint(startOffset, ==, 5);
- g_assert_cmpint(endOffset, ==, 25);
- g_assert_cmpstr(selectedText, ==, "agraph with plain te");
- g_free (selectedText);
-
- /* Try removing the selection from other AtkText object (should fail). */
- result = atk_text_remove_selection(paragraph2, 0);
- g_assert(!result);
-
- /* Remove the selection and test everything again. */
- result = atk_text_remove_selection(paragraph1, 0);
- g_assert(result);
- g_assert_cmpint(atk_text_get_n_selections(paragraph1), ==, 0);
- selectedText = atk_text_get_selection(paragraph1, 0, &startOffset, &endOffset);
- /* Now offsets should be the same, set to the last position of the caret. */
- g_assert_cmpint(startOffset, ==, endOffset);
- g_assert_cmpint(startOffset, ==, 25);
- g_assert_cmpint(endOffset, ==, 25);
- g_assert_cmpstr(selectedText, ==, 0);
- g_free (selectedText);
-
- /* Second paragraph (text + link + text). */
-
- /* Set a selection partially covering the link and test it. */
- result = atk_text_set_selection(paragraph2, 0, 7, 21);
- g_assert(result);
-
- /* Test the paragraph first. */
- g_assert_cmpint(atk_text_get_n_selections(paragraph2), ==, 1);
- selectedText = atk_text_get_selection(paragraph2, 0, &startOffset, &endOffset);
- g_assert_cmpint(startOffset, ==, 7);
- g_assert_cmpint(endOffset, ==, 21);
- g_assert_cmpstr(selectedText, ==, "raph with a li");
- g_free (selectedText);
-
- /* Now test just the link. */
- g_assert_cmpint(atk_text_get_n_selections(link), ==, 1);
- selectedText = atk_text_get_selection(link, 0, &startOffset, &endOffset);
- g_assert_cmpint(startOffset, ==, 0);
- g_assert_cmpint(endOffset, ==, 4);
- g_assert_cmpstr(selectedText, ==, "a li");
- g_free (selectedText);
-
- /* Make a selection after the link and check selection for the whole paragraph. */
- result = atk_text_set_selection(paragraph2, 0, 27, 37);
- g_assert(result);
- g_assert_cmpint(atk_text_get_n_selections(paragraph2), ==, 1);
- g_assert_cmpstr(textSelectionChangedResult, ==, "|paragraph|27|37|");
- selectedText = atk_text_get_selection(paragraph2, 0, &startOffset, &endOffset);
- g_assert_cmpint(startOffset, ==, 27);
- g_assert_cmpint(endOffset, ==, 37);
- g_assert_cmpstr(selectedText, ==, "the middle");
- g_free (selectedText);
-
- /* Remove selections and text everything again. */
- result = atk_text_remove_selection(paragraph2, 0);
- g_assert(result);
- g_assert_cmpint(atk_text_get_n_selections(paragraph2), ==, 0);
- selectedText = atk_text_get_selection(paragraph2, 0, &startOffset, &endOffset);
- /* Now offsets should be the same (no selection). */
- g_assert_cmpint(startOffset, ==, endOffset);
- g_assert_cmpstr(selectedText, ==, 0);
- g_free (selectedText);
-
- g_assert_cmpint(atk_text_get_n_selections(link), ==, 0);
- selectedText = atk_text_get_selection(link, 0, &startOffset, &endOffset);
- /* Now offsets should be the same (no selection). */
- g_assert_cmpint(startOffset, ==, endOffset);
- g_assert_cmpstr(selectedText, ==, 0);
- g_free (selectedText);
-
- /* List item */
-
- g_assert(atk_object_get_role(list) == ATK_ROLE_LIST);
- g_assert_cmpint(atk_object_get_n_accessible_children(list), ==, 1);
-
- /* It's not possible to select text inside an item's marker. */
- result = atk_text_set_selection (listItem, 0, 0, 9);
- g_assert(!result);
- result = atk_text_set_selection (listItem, 0, 9, 1);
- g_assert(!result);
-
- /* It should be possible to select text inside an item's text. */
- result = atk_text_set_selection (listItem, 0, 3, 9);
- g_assert(result);
-
- g_assert_cmpint(atk_text_get_n_selections(listItem), ==, 1);
- selectedText = atk_text_get_selection(listItem, 0, &startOffset, &endOffset);
- g_assert_cmpint(startOffset, ==, 3);
- g_assert_cmpint(endOffset, ==, 9);
- g_assert_cmpstr(selectedText, ==, "A list");
- g_free (selectedText);
-
- g_free(textSelectionChangedResult);
-
- g_object_unref(paragraph1);
- g_object_unref(paragraph2);
- g_object_unref(link);
- g_object_unref(list);
- g_object_unref(listItem);
- g_object_unref(webView);
-}
-
-static void testWebkitAtkGetExtents()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, centeredContents, 0, 0, 0);
-
- AtkObject* object = getWebAreaObject(webView);
- g_assert(object);
-
- AtkText* shortText1 = ATK_TEXT(atk_object_ref_accessible_child(object, 0));
- g_assert(ATK_IS_TEXT(shortText1));
- AtkText* longText = ATK_TEXT(atk_object_ref_accessible_child(object, 1));
- g_assert(ATK_IS_TEXT(longText));
- AtkText* shortText2 = ATK_TEXT(atk_object_ref_accessible_child(object, 2));
- g_assert(ATK_IS_TEXT(shortText2));
- AtkText* multilineText = ATK_TEXT(atk_object_ref_accessible_child(object, 3));
- g_assert(ATK_IS_TEXT(multilineText));
-
- /* Start with window extents. */
- AtkTextRectangle sline_window1, sline_window2, lline_window, mline_window;
- atk_text_get_range_extents(shortText1, 0, 10, ATK_XY_WINDOW, &sline_window1);
- atk_text_get_range_extents(longText, 0, 44, ATK_XY_WINDOW, &lline_window);
- atk_text_get_range_extents(shortText2, 0, 10, ATK_XY_WINDOW, &sline_window2);
- atk_text_get_range_extents(multilineText, 0, 60, ATK_XY_WINDOW, &mline_window);
-
- /* Check vertical line position. */
- g_assert_cmpint(sline_window1.y + sline_window1.height, <=, lline_window.y);
- g_assert_cmpint(lline_window.y + lline_window.height + sline_window2.height, <=, mline_window.y);
-
- /* Paragraphs 1 and 3 have identical text and alignment. */
- g_assert_cmpint(sline_window1.x, ==, sline_window2.x);
- g_assert_cmpint(sline_window1.width, ==, sline_window2.width);
- g_assert_cmpint(sline_window1.height, ==, sline_window2.height);
-
- /* All lines should be the same height; line 2 is the widest line. */
- g_assert_cmpint(sline_window1.height, ==, lline_window.height);
- g_assert_cmpint(sline_window1.width, <, lline_window.width);
-
- /* Make sure the character extents jive with the range extents. */
- gint x;
- gint y;
- gint width;
- gint height;
-
- /* First paragraph (short text). */
- atk_text_get_character_extents(shortText1, 0, &x, &y, &width, &height, ATK_XY_WINDOW);
- g_assert_cmpint(x, ==, sline_window1.x);
- g_assert_cmpint(y, ==, sline_window1.y);
- g_assert_cmpint(height, ==, sline_window1.height);
-
- atk_text_get_character_extents(shortText1, 9, &x, &y, &width, &height, ATK_XY_WINDOW);
- g_assert_cmpint(x, ==, sline_window1.x + sline_window1.width - width);
- g_assert_cmpint(y, ==, sline_window1.y);
- g_assert_cmpint(height, ==, sline_window1.height);
-
- /* Second paragraph (long text). */
- atk_text_get_character_extents(longText, 0, &x, &y, &width, &height, ATK_XY_WINDOW);
- g_assert_cmpint(x, ==, lline_window.x);
- g_assert_cmpint(y, ==, lline_window.y);
- g_assert_cmpint(height, ==, lline_window.height);
-
- atk_text_get_character_extents(longText, 43, &x, &y, &width, &height, ATK_XY_WINDOW);
- g_assert_cmpint(x, ==, lline_window.x + lline_window.width - width);
- g_assert_cmpint(y, ==, lline_window.y);
- g_assert_cmpint(height, ==, lline_window.height);
-
- /* Third paragraph (short text). */
- atk_text_get_character_extents(shortText2, 0, &x, &y, &width, &height, ATK_XY_WINDOW);
- g_assert_cmpint(x, ==, sline_window2.x);
- g_assert_cmpint(y, ==, sline_window2.y);
- g_assert_cmpint(height, ==, sline_window2.height);
-
- atk_text_get_character_extents(shortText2, 9, &x, &y, &width, &height, ATK_XY_WINDOW);
- g_assert_cmpint(x, ==, sline_window2.x + sline_window2.width - width);
- g_assert_cmpint(y, ==, sline_window2.y);
- g_assert_cmpint(height, ==, sline_window2.height);
-
- /* Four paragraph (3 lines multi-line text). */
- atk_text_get_character_extents(multilineText, 0, &x, &y, &width, &height, ATK_XY_WINDOW);
- g_assert_cmpint(x, ==, mline_window.x);
- g_assert_cmpint(y, ==, mline_window.y);
- g_assert_cmpint(3 * height, ==, mline_window.height);
-
- atk_text_get_character_extents(multilineText, 59, &x, &y, &width, &height, ATK_XY_WINDOW);
- /* Last line won't fill the whole width of the rectangle. */
- g_assert_cmpint(x, <=, mline_window.x + mline_window.width - width);
- g_assert_cmpint(y, ==, mline_window.y + mline_window.height - height);
- g_assert_cmpint(height, <=, mline_window.height);
-
- /* Check that extent for a full line are the same height than for
- a partial section of the same line */
- gint startOffset;
- gint endOffset;
-
-#if !ATK_CHECK_VERSION(2, 10, 0)
- gchar* text = atk_text_get_text_at_offset(multilineText, 0, ATK_TEXT_BOUNDARY_LINE_START, &startOffset, &endOffset);
- g_free(text);
-#else
- gchar* text = atk_text_get_string_at_offset(multilineText, 0, ATK_TEXT_GRANULARITY_LINE, &startOffset, &endOffset);
- g_free(text);
-#endif
-
- AtkTextRectangle fline_window;
- AtkTextRectangle afline_window;
- atk_text_get_range_extents(multilineText, startOffset, endOffset, ATK_XY_WINDOW, &fline_window);
- atk_text_get_range_extents(multilineText, startOffset, endOffset - 1, ATK_XY_WINDOW, &afline_window);
- g_assert_cmpint(fline_window.x, ==, afline_window.x);
- g_assert_cmpint(fline_window.y, ==, afline_window.y);
- g_assert_cmpint(fline_window.height, ==, afline_window.height);
-
- g_object_unref(shortText1);
- g_object_unref(shortText2);
- g_object_unref(longText);
- g_object_unref(multilineText);
- g_object_unref(webView);
-}
-
-static void testWebkitAtkLayoutAndDataTables()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, layoutAndDataTables, 0, 0, 0);
-
- AtkObject* object = getWebAreaObject(webView);
- g_assert(object);
-
- /* Check the non-layout table (data table). */
-
- AtkObject* table1 = atk_object_ref_accessible_child(object, 0);
- g_assert(ATK_IS_TABLE(table1));
- AtkAttributeSet* set1 = atk_object_get_attributes(table1);
- g_assert(set1);
- g_assert(!atkAttributeSetContainsAttributeName(set1, "layout-guess"));
- atk_attribute_set_free(set1);
-
- /* Check the layout table. */
-
- AtkObject* table2 = atk_object_ref_accessible_child(object, 1);
- g_assert(ATK_IS_TABLE(table2));
- AtkAttributeSet* set2 = atk_object_get_attributes(table2);
- g_assert(set2);
- g_assert(atkAttributeSetContainsAttributeName(set2, "layout-guess"));
- g_assert(atkAttributeSetAttributeNameHasValue(set2, "layout-guess", "true"));
- atk_attribute_set_free(set2);
-
- g_object_unref(table1);
- g_object_unref(table2);
- g_object_unref(webView);
-}
-
-static void testWebkitAtkLinksWithInlineImages()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, linksWithInlineImages, 0, 0, 0);
-
- AtkObject* object = getWebAreaObject(webView);
- g_assert(object);
-
- /* First paragraph (link at the beginning). */
- AtkObject* paragraph = atk_object_ref_accessible_child(object, 0);
- g_assert(ATK_IS_TEXT(paragraph));
- gint startOffset;
- gint endOffset;
-
-#if !ATK_CHECK_VERSION(2, 10, 0)
- gchar* text = atk_text_get_text_at_offset(ATK_TEXT(paragraph), 0, ATK_TEXT_BOUNDARY_LINE_START, &startOffset, &endOffset);
- g_assert(text);
- g_assert_cmpstr(text, ==, "foo bar baz");
- g_assert_cmpint(startOffset, ==, 0);
- g_assert_cmpint(endOffset, ==, 11);
- g_free(text);
-#else
- gchar* text = atk_text_get_string_at_offset(ATK_TEXT(paragraph), 0, ATK_TEXT_GRANULARITY_LINE, &startOffset, &endOffset);
- g_assert(text);
- g_assert_cmpstr(text, ==, "foo bar baz");
- g_assert_cmpint(startOffset, ==, 0);
- g_assert_cmpint(endOffset, ==, 11);
- g_free(text);
-#endif
-
- g_object_unref(paragraph);
-
- /* Second paragraph (link in the middle). */
- paragraph = atk_object_ref_accessible_child(object, 1);
- g_assert(ATK_IS_TEXT(paragraph));
-
-#if !ATK_CHECK_VERSION(2, 10, 0)
- text = atk_text_get_text_at_offset(ATK_TEXT(paragraph), 0, ATK_TEXT_BOUNDARY_LINE_START, &startOffset, &endOffset);
- g_assert(text);
- g_assert_cmpstr(text, ==, "foo bar baz");
- g_assert_cmpint(startOffset, ==, 0);
- g_assert_cmpint(endOffset, ==, 11);
- g_free(text);
-#else
- text = atk_text_get_string_at_offset(ATK_TEXT(paragraph), 0, ATK_TEXT_GRANULARITY_LINE, &startOffset, &endOffset);
- g_assert(text);
- g_assert_cmpstr(text, ==, "foo bar baz");
- g_assert_cmpint(startOffset, ==, 0);
- g_assert_cmpint(endOffset, ==, 11);
- g_free(text);
-#endif
-
- g_object_unref(paragraph);
-
- /* Third paragraph (link at the end). */
- paragraph = atk_object_ref_accessible_child(object, 2);
- g_assert(ATK_IS_TEXT(paragraph));
-
-#if !ATK_CHECK_VERSION(2, 10, 0)
- text = atk_text_get_text_at_offset(ATK_TEXT(paragraph), 0, ATK_TEXT_BOUNDARY_LINE_START, &startOffset, &endOffset);
- g_assert(text);
- g_assert_cmpstr(text, ==, "foo bar baz");
- g_assert_cmpint(startOffset, ==, 0);
- g_assert_cmpint(endOffset, ==, 11);
- g_free(text);
-#else
- text = atk_text_get_string_at_offset(ATK_TEXT(paragraph), 0, ATK_TEXT_GRANULARITY_LINE, &startOffset, &endOffset);
- g_assert(text);
- g_assert_cmpstr(text, ==, "foo bar baz");
- g_assert_cmpint(startOffset, ==, 0);
- g_assert_cmpint(endOffset, ==, 11);
- g_free(text);
-#endif
-
- g_object_unref(paragraph);
- g_object_unref(webView);
-}
-
-static void testWebkitAtkHypertextAndHyperlinks()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, hypertextAndHyperlinks, 0, 0, 0);
-
- AtkObject* object = getWebAreaObject(webView);
- g_assert(object);
-
- AtkObject* paragraph1 = atk_object_ref_accessible_child(object, 0);
- g_assert(ATK_OBJECT(paragraph1));
- g_assert(atk_object_get_role(paragraph1) == ATK_ROLE_PARAGRAPH);
- g_assert(ATK_IS_HYPERTEXT(paragraph1));
-
- /* No links in the first paragraph. */
- gint nLinks = atk_hypertext_get_n_links(ATK_HYPERTEXT(paragraph1));
- g_assert_cmpint(nLinks, ==, 0);
-
- AtkObject* paragraph2 = atk_object_ref_accessible_child(object, 1);
- g_assert(ATK_OBJECT(paragraph2));
- g_assert(atk_object_get_role(paragraph2) == ATK_ROLE_PARAGRAPH);
- g_assert(ATK_IS_HYPERTEXT(paragraph2));
-
- /* Check links in the second paragraph.
- nLinks = atk_hypertext_get_n_links(ATK_HYPERTEXT(paragraph2));
- g_assert_cmpint(nLinks, ==, 3); */
-
- AtkHyperlink* hLink1 = atk_hypertext_get_link(ATK_HYPERTEXT(paragraph2), 0);
- g_assert(ATK_HYPERLINK(hLink1));
- AtkObject* hLinkObject1 = atk_hyperlink_get_object(hLink1, 0);
- g_assert(ATK_OBJECT(hLinkObject1));
- g_assert(atk_object_get_role(hLinkObject1) == ATK_ROLE_LINK);
- g_assert_cmpint(atk_hyperlink_get_start_index(hLink1), ==, 0);
- g_assert_cmpint(atk_hyperlink_get_end_index(hLink1), ==, 6);
- g_assert_cmpint(atk_hyperlink_get_n_anchors(hLink1), ==, 1);
- g_assert_cmpstr(atk_hyperlink_get_uri(hLink1, 0), ==, "http://foo.bar.baz/");
-
- AtkHyperlink* hLink2 = atk_hypertext_get_link(ATK_HYPERTEXT(paragraph2), 1);
- g_assert(ATK_HYPERLINK(hLink2));
- AtkObject* hLinkObject2 = atk_hyperlink_get_object(hLink2, 0);
- g_assert(ATK_OBJECT(hLinkObject2));
- g_assert(atk_object_get_role(hLinkObject2) == ATK_ROLE_LINK);
- g_assert_cmpint(atk_hyperlink_get_start_index(hLink2), ==, 12);
- g_assert_cmpint(atk_hyperlink_get_end_index(hLink2), ==, 32);
- g_assert_cmpint(atk_hyperlink_get_n_anchors(hLink2), ==, 1);
- g_assert_cmpstr(atk_hyperlink_get_uri(hLink2, 0), ==, "http://bar.baz.foo/");
-
- AtkHyperlink* hLink3 = atk_hypertext_get_link(ATK_HYPERTEXT(paragraph2), 2);
- g_assert(ATK_HYPERLINK(hLink3));
- AtkObject* hLinkObject3 = atk_hyperlink_get_object(hLink3, 0);
- g_assert(ATK_OBJECT(hLinkObject3));
- g_assert(atk_object_get_role(hLinkObject3) == ATK_ROLE_LINK);
- g_assert_cmpint(atk_hyperlink_get_start_index(hLink3), ==, 65);
- g_assert_cmpint(atk_hyperlink_get_end_index(hLink3), ==, 75);
- g_assert_cmpint(atk_hyperlink_get_n_anchors(hLink3), ==, 1);
- g_assert_cmpstr(atk_hyperlink_get_uri(hLink3, 0), ==, "http://baz.foo.bar/");
-
- AtkObject* list = atk_object_ref_accessible_child(object, 2);
- g_assert(ATK_OBJECT(list));
- g_assert(atk_object_get_role(list) == ATK_ROLE_LIST);
- g_assert_cmpint(atk_object_get_n_accessible_children(list), ==, 1);
-
- AtkObject* listItem = atk_object_ref_accessible_child(list, 0);
- g_assert(ATK_IS_TEXT(listItem));
- g_assert(ATK_IS_HYPERTEXT(listItem));
-
- AtkHyperlink* hLinkInListItem = atk_hypertext_get_link(ATK_HYPERTEXT(listItem), 0);
- g_assert(ATK_HYPERLINK(hLinkInListItem));
- AtkObject* hLinkObject = atk_hyperlink_get_object(hLinkInListItem, 0);
- g_assert(ATK_OBJECT(hLinkObject));
- g_assert(atk_object_get_role(hLinkObject) == ATK_ROLE_LINK);
- g_assert_cmpint(atk_hyperlink_get_start_index(hLinkInListItem), ==, 20);
- g_assert_cmpint(atk_hyperlink_get_end_index(hLinkInListItem), ==, 43);
- g_assert_cmpint(atk_hyperlink_get_n_anchors(hLinkInListItem), ==, 1);
- g_assert_cmpstr(atk_hyperlink_get_uri(hLinkInListItem, 0), ==, "http://foo.bar.baz/");
-
- /* Finally check the AtkAction interface for a given AtkHyperlink. */
- g_assert(ATK_IS_ACTION(hLink1));
- g_assert_cmpint(atk_action_get_n_actions(ATK_ACTION(hLink1)), ==, 1);
- g_assert_cmpstr(atk_action_get_keybinding(ATK_ACTION(hLink1), 0), ==, "");
- g_assert_cmpstr(atk_action_get_name(ATK_ACTION(hLink1), 0), ==, "jump");
- g_assert(atk_action_do_action(ATK_ACTION(hLink1), 0));
-
- g_object_unref(paragraph1);
- g_object_unref(paragraph2);
- g_object_unref(list);
- g_object_unref(listItem);
- g_object_unref(webView);
-}
-
-static void testWebkitAtkListsOfItems()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, listsOfItems, 0, 0, 0);
-
- AtkObject* object = getWebAreaObject(webView);
- g_assert(object);
-
- /* Unordered list. */
-
- AtkObject* uList = atk_object_ref_accessible_child(object, 0);
- g_assert(ATK_OBJECT(uList));
- g_assert(atk_object_get_role(uList) == ATK_ROLE_LIST);
- g_assert_cmpint(atk_object_get_n_accessible_children(uList), ==, 3);
-
- AtkObject* item1 = atk_object_ref_accessible_child(uList, 0);
- AtkObject* item2 = atk_object_ref_accessible_child(uList, 1);
- AtkObject* item3 = atk_object_ref_accessible_child(uList, 2);
-
- g_assert_cmpint(atk_object_get_n_accessible_children(item1), ==, 0);
- g_assert_cmpint(atk_object_get_n_accessible_children(item2), ==, 1);
- g_assert_cmpint(atk_object_get_n_accessible_children(item3), ==, 1);
-
- g_object_unref(item1);
- g_object_unref(item2);
- g_object_unref(item3);
-
- /* Ordered list. */
-
- AtkObject* oList = atk_object_ref_accessible_child(object, 1);
- g_assert(ATK_OBJECT(oList));
- g_assert(atk_object_get_role(oList) == ATK_ROLE_LIST);
- g_assert_cmpint(atk_object_get_n_accessible_children(oList), ==, 3);
-
- item1 = atk_object_ref_accessible_child(oList, 0);
- item2 = atk_object_ref_accessible_child(oList, 1);
- item3 = atk_object_ref_accessible_child(oList, 2);
-
- g_assert_cmpint(atk_object_get_n_accessible_children(item1), ==, 0);
- g_assert_cmpint(atk_object_get_n_accessible_children(item2), ==, 1);
- g_assert_cmpint(atk_object_get_n_accessible_children(item3), ==, 1);
-
- g_object_unref(item1);
- g_object_unref(item2);
- g_object_unref(item3);
-
- g_object_unref(uList);
- g_object_unref(oList);
- g_object_unref(webView);
-}
-
-typedef enum {
- TEXT_CHANGE_INSERT = 1,
- TEXT_CHANGE_REMOVE = 2
-} TextChangeType;
-
-static gchar* textChangedResult = 0;
-
-static void textChangedCb(AtkText* text, gint pos, gint len, gchar* modifiedText, gpointer data)
-{
- g_assert(text && ATK_IS_OBJECT(text));
-
- TextChangeType type = GPOINTER_TO_INT(data);
- g_free(textChangedResult);
- textChangedResult = g_strdup_printf("|%d|%d|%d|'%s'|", type, pos, len, modifiedText);
-}
-
-static void testWebkitAtkTextChangedNotifications()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, formWithTextInputs, 0, 0, 0);
-
- AtkObject* object = getWebAreaObject(webView);
- g_assert(object);
-
- AtkObject* form = atk_object_ref_accessible_child(object, 0);
- g_assert(ATK_IS_OBJECT(form));
-
- /* First check normal text entries. */
- AtkObject* textEntry = atk_object_ref_accessible_child(form, 0);
- g_assert(ATK_IS_EDITABLE_TEXT(textEntry));
- g_assert(atk_object_get_role(ATK_OBJECT(textEntry)) == ATK_ROLE_ENTRY);
-
- g_signal_connect(textEntry, "text-insert",
- G_CALLBACK(textChangedCb),
- GINT_TO_POINTER(TEXT_CHANGE_INSERT));
- g_signal_connect(textEntry, "text-remove",
- G_CALLBACK(textChangedCb),
- GINT_TO_POINTER(TEXT_CHANGE_REMOVE));
-
- gint pos = 0;
- atk_editable_text_insert_text(ATK_EDITABLE_TEXT(textEntry), "foo bar baz", 11, &pos);
- char* text = atk_text_get_text(ATK_TEXT(textEntry), 0, -1);
- g_assert_cmpstr(text, ==, "foo bar baz");
- g_assert_cmpstr(textChangedResult, ==, "|1|0|11|'foo bar baz'|");
- g_free(text);
-
- atk_editable_text_delete_text(ATK_EDITABLE_TEXT(textEntry), 4, 7);
- text = atk_text_get_text(ATK_TEXT(textEntry), 0, -1);
- g_assert_cmpstr(text, ==, "foo baz");
- g_assert_cmpstr(textChangedResult, ==, "|2|4|3|'bar'|");
- g_free(text);
-
- pos = 4;
- atk_editable_text_insert_text(ATK_EDITABLE_TEXT(textEntry), "qux quux tobeignored", 8, &pos);
- text = atk_text_get_text(ATK_TEXT(textEntry), 0, -1);
- g_assert_cmpstr(text, ==, "foo qux quux baz");
- g_assert_cmpstr(textChangedResult, ==, "|1|4|8|'qux quux'|");
- g_free(text);
-
- /* Now check for password entries. */
- AtkObject* passwordEntry = atk_object_ref_accessible_child(form, 1);
- g_assert(ATK_IS_EDITABLE_TEXT(passwordEntry));
- g_assert(atk_object_get_role(ATK_OBJECT(passwordEntry)) == ATK_ROLE_PASSWORD_TEXT);
-
- g_signal_connect(passwordEntry, "text-insert",
- G_CALLBACK(textChangedCb),
- GINT_TO_POINTER(TEXT_CHANGE_INSERT));
- g_signal_connect(passwordEntry, "text-remove",
- G_CALLBACK(textChangedCb),
- GINT_TO_POINTER(TEXT_CHANGE_REMOVE));
-
- pos = 0;
- /* A single bullet character is '\342\200\242' */
- atk_editable_text_insert_text(ATK_EDITABLE_TEXT(passwordEntry), "foobar", 6, &pos);
- g_assert_cmpstr(textChangedResult, ==, "|1|0|6|'\342\200\242\342\200\242\342\200\242\342\200\242\342\200\242\342\200\242'|");
- text = atk_text_get_text(ATK_TEXT(passwordEntry), 0, -1);
- g_assert_cmpstr(text, ==, "\342\200\242\342\200\242\342\200\242\342\200\242\342\200\242\342\200\242");
- g_free(text);
-
- atk_editable_text_delete_text(ATK_EDITABLE_TEXT(passwordEntry), 2, 4);
- g_assert_cmpstr(textChangedResult, ==, "|2|2|2|'\342\200\242\342\200\242'|");
-
- text = atk_text_get_text(ATK_TEXT(passwordEntry), 0, -1);
- g_assert_cmpstr(text, ==, "\342\200\242\342\200\242\342\200\242\342\200\242");
- g_free(text);
-
- pos = 3;
- atk_editable_text_insert_text(ATK_EDITABLE_TEXT(passwordEntry), "qux tobeignored", 3, &pos);
- g_assert_cmpstr(textChangedResult, ==, "|1|3|3|'\342\200\242\342\200\242\342\200\242'|");
-
- text = atk_text_get_text(ATK_TEXT(passwordEntry), 0, -1);
- g_assert_cmpstr(text, ==, "\342\200\242\342\200\242\342\200\242\342\200\242\342\200\242\342\200\242\342\200\242");
- g_free(text);
-
- g_free(textChangedResult);
-
- g_object_unref(form);
- g_object_unref(textEntry);
- g_object_unref(passwordEntry);
- g_object_unref(webView);
-}
-
-static void testWebkitAtkParentForRootObject()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, contents, 0, 0, 0);
-
- /* We need a parent container widget for the webview. */
- GtkWidget* parentContainer = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- g_object_ref_sink(parentContainer);
- gtk_container_add(GTK_CONTAINER(parentContainer), GTK_WIDGET(webView));
-
- AtkObject* axParent = gtk_widget_get_accessible(parentContainer);
- g_assert(ATK_IS_OBJECT(axParent));
-
- AtkObject* axRoot = gtk_widget_get_accessible(GTK_WIDGET(webView));
- g_assert(ATK_IS_OBJECT(axRoot));
-
- /* The child for the parent container's accessibility object
- should be the accessibility object for the WebView's root. */
- AtkObject* axParentChild = atk_object_ref_accessible_child(axParent, 0);
- g_assert(axParentChild == axRoot);
-
- /* Bottom-up navigation should match top-down one. */
- g_assert(atk_object_get_parent(axParentChild) == axParent);
-
- g_object_unref(axParentChild);
- g_object_unref(parentContainer);
-}
-
-static void testWebkitAtkSetParentForObject()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, contents, 0, 0, 0);
-
- /* Put the webview in a parent container widget to check that the
- normal behaviour keeps working as expected by default. */
- GtkWidget* parentContainer = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- g_object_ref_sink(parentContainer);
- gtk_container_add(GTK_CONTAINER(parentContainer), GTK_WIDGET(webView));
-
- AtkObject* axRoot = gtk_widget_get_accessible(GTK_WIDGET(webView));
- g_assert(ATK_IS_OBJECT(axRoot));
-
- AtkObject* axParent = gtk_widget_get_accessible(parentContainer);
- g_assert(ATK_IS_OBJECT(axParent));
-
- /* The parent of the root object is the parent container's a11y object. */
- g_assert(atk_object_get_parent(axRoot) == axParent);
-
- /* We now need to use something as a an alternative parent for
- the a11y object associated with the root of the DOM tree. */
- GtkWidget* alternativeParent = gtk_button_new();
- g_object_ref_sink(alternativeParent);
-
- AtkObject* axAlternativeParent = gtk_widget_get_accessible(alternativeParent);
- g_assert(ATK_IS_OBJECT(axAlternativeParent));
-
- /* Manually set the alternative parent's accessibility object as
- the parent for the WebKit accessibility root object and check. */
- atk_object_set_parent(axRoot, axAlternativeParent);
- g_assert(atk_object_get_parent(axRoot) == axAlternativeParent);
-
- g_object_unref(alternativeParent);
- g_object_unref(parentContainer);
-}
-
-#ifdef GTK_API_VERSION_2
-static void initializeTestingFramework(int argc, char** argv)
-{
- /* Ensure GAIL is the only module loaded. */
- g_setenv("GTK_MODULES", "gail", TRUE);
-
- /* Following lines were taken from gtk_test_init(). */
- g_test_init(&argc, &argv, 0);
- gtk_disable_setlocale();
- setlocale(LC_ALL, "C");
-
- gtk_init(&argc, &argv);
-}
-#endif
-
-int main(int argc, char** argv)
-{
-#ifdef GTK_API_VERSION_2
- /* We can't just call to gtk_test_init() in this case because its
- implementation makes sure that no GTK+ module will be loaded, and
- we will need to load GAIL for tests that need to use AtkObjects
- from non-WebKit GtkWidgets (e.g parentForRootObject).*/
- initializeTestingFramework(argc, argv);
-#else
- gtk_test_init(&argc, &argv, NULL);
-#endif
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/atk/caretOffsets", testWebkitAtkCaretOffsets);
- g_test_add_func("/webkit/atk/caretOffsetsAndExtranousWhiteSpaces", testWebkitAtkCaretOffsetsAndExtranousWhiteSpaces);
- g_test_add_func("/webkit/atk/comboBox", testWebkitAtkComboBox);
- g_test_add_func("/webkit/atk/documentLoadingEvents", testWebkitAtkDocumentLoadingEvents);
- g_test_add_func("/webkit/atk/embeddedObjects", testWebkitAtkEmbeddedObjects);
- g_test_add_func("/webkit/atk/getHeadersInTable", testWebkitAtkGetHeadersInTable);
- g_test_add_func("/webkit/atk/textAttributes", testWebkitAtkTextAttributes);
- g_test_add_func("/webkit/atk/textSelections", testWebkitAtkTextSelections);
- g_test_add_func("/webkit/atk/getExtents", testWebkitAtkGetExtents);
- g_test_add_func("/webkit/atk/hypertextAndHyperlinks", testWebkitAtkHypertextAndHyperlinks);
- g_test_add_func("/webkit/atk/layoutAndDataTables", testWebkitAtkLayoutAndDataTables);
- g_test_add_func("/webkit/atk/linksWithInlineImages", testWebkitAtkLinksWithInlineImages);
- g_test_add_func("/webkit/atk/listsOfItems", testWebkitAtkListsOfItems);
- g_test_add_func("/webkit/atk/textChangedNotifications", testWebkitAtkTextChangedNotifications);
- g_test_add_func("/webkit/atk/parentForRootObject", testWebkitAtkParentForRootObject);
- g_test_add_func("/webkit/atk/setParentForObject", testWebkitAtkSetParentForObject);
- return g_test_run ();
-}
-
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testatkroles.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testatkroles.c
deleted file mode 100644
index 88817cf8a..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testatkroles.c
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
- * Copyright © 2010 Joanmarie Diggs
- * Copyright © 2010 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-/* Non form roles */
-#define HTML_DOCUMENT_FRAME "<html><body>This is a test.</body></html>"
-#define HTML_HEADING "<html><body><h1>1</h1><h2>2</h2><h3>3</h3><h4>4</h4><h5>5</h5><h6>6</h6></body></html>"
-#define HTML_IMAGE "<html><body><img src='foobar.png' alt='This is a test.'/></body></html>"
-#define HTML_LINK_TEXT "<html><body><a href='foobar.html'>This is a test.</a></body></html>"
-#define HTML_LIST "<html><body><ul><li>1</li><li>2</li></ul><ol><li>1</li><li>2</li></ol></body></html>"
-#define HTML_PARAGRAPH "<html><body><p>This is a test.</p></body></html>"
-#define HTML_SECTION "<html><body><div>This is a test.</div></body></html>"
-#define HTML_TABLE "<html><body><table border='1'><tr><td>This is</td><td>a test.</td></tr></table></body></html>"
-#define HTML_SEPARATOR "<html><body><hr/></body></html>"
-#define HTML_COMBOBOX "<html><body><select size='1'><option>one</option><option>two</option><option>three</option></select></body></html>"
-/* Form roles */
-#define HTML_FORM "<html><body><form>This is a test.</form></body></html>"
-#define HTML_CHECK_BOX "<html><body><input type='checkbox' />This is a test.</body></html>"
-#define HTML_LABELED_ENTRY "<html><body><label for='foo'>Name:</label><input type='text' id='foo' /></body></html>"
-#define HTML_LISTBOX "<html><body><select size='3'><option>one</option><option>two</option><option>three</option></select></body></html>"
-#define HTML_PASSWORD_TEXT "<html><body><input type='password' /></body></html>"
-#define HTML_PUSH_BUTTON "<html><body><input type='submit' value='ok' />This is a test.</body></html>"
-#define HTML_RADIO_BUTTON "<html><body><input type='radio' />This is a test.</body></html>"
-
-typedef struct {
- AtkObject* document;
- AtkObject* obj;
- AtkRole role;
- GtkWidget* webView;
- GtkAllocation alloc;
- GMainLoop* loop;
-} AtkRolesFixture;
-
-static gboolean finish_loading(AtkRolesFixture* fixture)
-{
- if (g_main_loop_is_running(fixture->loop))
- g_main_loop_quit(fixture->loop);
-
- // With the change to support WK2 accessibility, the root object
- // has changed and it's no longer the document frame, but a scroll
- // pane containing the document frame as its only child. See the
- // bug 72390 for more details on this change.
- // https://bugs.webkit.org/show_bug.cgi?id=72390
- AtkObject* rootObject = gtk_widget_get_accessible(fixture->webView);
- fixture->document = atk_object_ref_accessible_child(rootObject, 0);
- g_assert(fixture->document);
-
- // Remove the reference added by ref_accessible_child() and
- // return, since we don't need to keep that extra ref at all.
- g_object_unref(fixture->document);
- return FALSE;
-}
-
-static void atk_roles_fixture_setup(AtkRolesFixture* fixture, gconstpointer data)
-{
- fixture->loop = g_main_loop_new(NULL, TRUE);
- fixture->alloc = (GtkAllocation) { 0, 0, 800, 600 };
- fixture->webView = webkit_web_view_new();
- g_object_ref_sink(fixture->webView);
-
- gtk_widget_size_allocate(fixture->webView, &fixture->alloc);
-
- if (data != NULL)
- webkit_web_view_load_string(WEBKIT_WEB_VIEW (fixture->webView), (const char*) data, NULL, NULL, NULL);
-
- g_idle_add((GSourceFunc) finish_loading, fixture);
- g_main_loop_run(fixture->loop);
-}
-
-static void atk_roles_fixture_teardown(AtkRolesFixture* fixture, gconstpointer data)
-{
- g_object_unref(fixture->webView);
- g_main_loop_unref(fixture->loop);
-}
-
-static void get_child_and_test_role(AtkObject* obj, gint pos, AtkRole role)
-{
- AtkObject* child;
- AtkRole child_role;
-
- child = atk_object_ref_accessible_child(obj, pos);
- g_assert(child);
- child_role = atk_object_get_role(child);
- g_assert(child_role == role);
-
- g_object_unref(child);
-}
-
-static void test_webkit_atk_get_role_document_frame(AtkRolesFixture* fixture, gconstpointer data)
-{
- fixture->role = atk_object_get_role(fixture->document);
- g_assert(fixture->role == ATK_ROLE_DOCUMENT_WEB);
-}
-
-static void test_webkit_atk_get_role_heading(AtkRolesFixture* fixture, gconstpointer data)
-{
- get_child_and_test_role(fixture->document, 0, ATK_ROLE_HEADING);
- get_child_and_test_role(fixture->document, 1, ATK_ROLE_HEADING);
- get_child_and_test_role(fixture->document, 2, ATK_ROLE_HEADING);
- get_child_and_test_role(fixture->document, 3, ATK_ROLE_HEADING);
- get_child_and_test_role(fixture->document, 4, ATK_ROLE_HEADING);
- get_child_and_test_role(fixture->document, 5, ATK_ROLE_HEADING);
-}
-
-static void test_webkit_atk_get_role_image(AtkRolesFixture* fixture, gconstpointer data)
-{
- // This is an extraneous object of ATK_ROLE_PANEL which we should get rid of.
- fixture->obj = atk_object_ref_accessible_child(fixture->document, 0);
- g_assert(fixture->obj);
-
- get_child_and_test_role(fixture->obj, 0, ATK_ROLE_IMAGE);
-
- g_object_unref(fixture->obj);
-}
-
-static void test_webkit_atk_get_role_link(AtkRolesFixture* fixture, gconstpointer data)
-{
- // This is an extraneous object of ATK_ROLE_PANEL which we should get rid of.
- fixture->obj = atk_object_ref_accessible_child(fixture->document, 0);
- g_assert(fixture->obj);
-
- get_child_and_test_role(fixture->obj, 0, ATK_ROLE_LINK);
-
- g_object_unref(fixture->obj);
-}
-
-static void test_webkit_atk_get_role_list_and_item(AtkRolesFixture* fixture, gconstpointer data)
-{
- AtkObject* listObj;
-
- listObj = atk_object_ref_accessible_child(fixture->document, 0);
- g_assert(listObj);
- fixture->role = atk_object_get_role(listObj);
- g_assert(fixture->role == ATK_ROLE_LIST);
-
- get_child_and_test_role(listObj, 0, ATK_ROLE_LIST_ITEM);
- get_child_and_test_role(listObj, 1, ATK_ROLE_LIST_ITEM);
- g_object_unref(listObj);
-
- listObj = atk_object_ref_accessible_child(fixture->document, 1);
- g_assert(listObj);
- fixture->role = atk_object_get_role(listObj);
- g_assert(fixture->role == ATK_ROLE_LIST);
-
- get_child_and_test_role(listObj, 0, ATK_ROLE_LIST_ITEM);
- get_child_and_test_role(listObj, 1, ATK_ROLE_LIST_ITEM);
- g_object_unref(listObj);
-}
-
-static void test_webkit_atk_get_role_paragraph(AtkRolesFixture* fixture, gconstpointer data)
-{
- get_child_and_test_role(fixture->document, 0, ATK_ROLE_PARAGRAPH);
-}
-
-static void test_webkit_atk_get_role_section(AtkRolesFixture* fixture, gconstpointer data)
-{
- get_child_and_test_role(fixture->document, 0, ATK_ROLE_SECTION);
-}
-
-// Does not yet test table cells because of bug 30895.
-static void test_webkit_atk_get_role_table(AtkRolesFixture* fixture, gconstpointer data)
-{
- get_child_and_test_role(fixture->document, 0, ATK_ROLE_TABLE);
-}
-
-static void test_webkit_atk_get_role_separator(AtkRolesFixture *fixture, gconstpointer data)
-{
- get_child_and_test_role(fixture->document, 0, ATK_ROLE_SEPARATOR);
-}
-
-static void test_webkit_atk_get_role_combobox(AtkRolesFixture *fixture, gconstpointer data)
-{
- AtkObject* comboboxMenu;
-
- // This is an extraneous object of ATK_ROLE_PANEL which we should get rid of.
- fixture->obj = atk_object_ref_accessible_child(fixture->document, 0);
- g_assert(fixture->obj);
-
- fixture->obj = atk_object_ref_accessible_child(fixture->obj, 0);
- g_assert(fixture->obj);
- fixture->role = atk_object_get_role(fixture->obj);
- g_assert(fixture->role == ATK_ROLE_COMBO_BOX);
-
- comboboxMenu = atk_object_ref_accessible_child(fixture->obj, 0);
- g_assert(comboboxMenu);
- fixture->role = atk_object_get_role(comboboxMenu);
- g_assert(fixture->role == ATK_ROLE_MENU);
-
- get_child_and_test_role(comboboxMenu, 0, ATK_ROLE_MENU_ITEM);
- get_child_and_test_role(comboboxMenu, 1, ATK_ROLE_MENU_ITEM);
- get_child_and_test_role(comboboxMenu, 2, ATK_ROLE_MENU_ITEM);
-
- g_object_unref(fixture->obj);
- g_object_unref(comboboxMenu);
-}
-
-/* Form roles */
-static void test_webkit_atk_get_role_form(AtkRolesFixture *fixture, gconstpointer data)
-{
- get_child_and_test_role(fixture->document, 0, ATK_ROLE_FORM);
-}
-
-static void test_webkit_atk_get_role_check_box(AtkRolesFixture* fixture, gconstpointer data)
-{
- // This is an extraneous object of ATK_ROLE_PANEL which we should get rid of.
- fixture->obj = atk_object_ref_accessible_child(fixture->document, 0);
- g_assert(fixture->obj);
-
- get_child_and_test_role(fixture->obj, 0, ATK_ROLE_CHECK_BOX);
-
- g_object_unref(fixture->obj);
-}
-
-static void test_webkit_atk_get_role_entry(AtkRolesFixture* fixture, gconstpointer data)
-{
- // This is an extraneous object of ATK_ROLE_PANEL which we should get rid of.
- fixture->obj = atk_object_ref_accessible_child(fixture->document, 0);
- g_assert(fixture->obj);
-
- get_child_and_test_role(fixture->obj, 1, ATK_ROLE_ENTRY);
-
- g_object_unref(fixture->obj);
-}
-
-static void test_webkit_atk_get_role_label(AtkRolesFixture* fixture, gconstpointer data)
-{
- // This is an extraneous object of ATK_ROLE_PANEL which we should get rid of.
- fixture->obj = atk_object_ref_accessible_child(fixture->document, 0);
- g_assert(fixture->obj);
-
- get_child_and_test_role(fixture->obj, 0, ATK_ROLE_LABEL);
-
- g_object_unref(fixture->obj);
-}
-
-static void test_webkit_atk_get_role_listbox(AtkRolesFixture* fixture, gconstpointer data)
-{
- AtkObject* listboxObj;
- // This is an extraneous object of ATK_ROLE_PANEL which we should get rid of.
- fixture->obj = atk_object_ref_accessible_child(fixture->document, 0);
- g_assert(fixture->obj);
-
- listboxObj = atk_object_ref_accessible_child(fixture->obj, 0);
- g_assert(listboxObj);
- fixture->role = atk_object_get_role(listboxObj);
- g_assert(fixture->role == ATK_ROLE_LIST);
-
- get_child_and_test_role(listboxObj, 0, ATK_ROLE_LIST_ITEM);
- get_child_and_test_role(listboxObj, 1, ATK_ROLE_LIST_ITEM);
- get_child_and_test_role(listboxObj, 2, ATK_ROLE_LIST_ITEM);
-
- g_object_unref(fixture->obj);
- g_object_unref(listboxObj);
-}
-
-static void test_webkit_atk_get_role_password_text(AtkRolesFixture* fixture, gconstpointer data)
-{
- // This is an extraneous object of ATK_ROLE_PANEL which we should get rid of.
- fixture->obj = atk_object_ref_accessible_child(fixture->document, 0);
- g_assert(fixture->obj);
-
- get_child_and_test_role(fixture->obj, 0, ATK_ROLE_PASSWORD_TEXT);
-
- g_object_unref(fixture->obj);
-}
-
-static void test_webkit_atk_get_role_push_button(AtkRolesFixture* fixture, gconstpointer data)
-{
- // This is an extraneous object of ATK_ROLE_PANEL which we should get rid of.
- fixture->obj = atk_object_ref_accessible_child(fixture->document, 0);
- g_assert(fixture->obj);
-
- get_child_and_test_role(fixture->obj, 0, ATK_ROLE_PUSH_BUTTON);
-
- g_object_unref(fixture->obj);
-}
-
-static void test_webkit_atk_get_role_radio_button(AtkRolesFixture* fixture, gconstpointer data)
-{
- // This is an extraneous object of ATK_ROLE_PANEL which we should get rid of.
- fixture->obj = atk_object_ref_accessible_child(fixture->document, 0);
- g_assert(fixture->obj);
-
- get_child_and_test_role(fixture->obj, 0, ATK_ROLE_RADIO_BUTTON);
-
- g_object_unref(fixture->obj);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_document_frame",
- AtkRolesFixture, HTML_DOCUMENT_FRAME,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_document_frame,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_heading",
- AtkRolesFixture, HTML_HEADING,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_heading,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_image",
- AtkRolesFixture, HTML_IMAGE,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_image,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_link",
- AtkRolesFixture, HTML_LINK_TEXT,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_link,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_list_and_item",
- AtkRolesFixture, HTML_LIST,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_list_and_item,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_paragraph",
- AtkRolesFixture, HTML_PARAGRAPH,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_paragraph,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_section",
- AtkRolesFixture, HTML_SECTION,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_section,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_table",
- AtkRolesFixture, HTML_TABLE,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_table,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_separator",
- AtkRolesFixture, HTML_SEPARATOR,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_separator,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_combobox",
- AtkRolesFixture, HTML_COMBOBOX,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_combobox,
- atk_roles_fixture_teardown);
-
- /* Form roles */
- g_test_add("/webkit/atk/test_webkit_atk_get_role_form",
- AtkRolesFixture, HTML_FORM,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_form,
- atk_roles_fixture_teardown);
- g_test_add("/webkit/atk/test_webkit_atk_get_role_check_box",
- AtkRolesFixture, HTML_CHECK_BOX,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_check_box,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_entry",
- AtkRolesFixture, HTML_LABELED_ENTRY,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_entry,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_label",
- AtkRolesFixture, HTML_LABELED_ENTRY,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_label,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_listbox",
- AtkRolesFixture, HTML_LISTBOX,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_listbox,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_password_text",
- AtkRolesFixture, HTML_PASSWORD_TEXT,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_password_text,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_push_button",
- AtkRolesFixture, HTML_PUSH_BUTTON,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_push_button,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_radio_button",
- AtkRolesFixture, HTML_RADIO_BUTTON,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_radio_button,
- atk_roles_fixture_teardown);
-
- return g_test_run();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testcontextmenu.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testcontextmenu.c
deleted file mode 100644
index bc941a756..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testcontextmenu.c
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Copyright (C) 2012 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2,1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <webkit/webkit.h>
-
-typedef struct {
- char *data;
- guint flag;
-} TestInfo;
-
-static GMainLoop *loop;
-
-typedef struct {
- WebKitWebView *webView;
- TestInfo *info;
-} ContextMenuFixture;
-
-static TestInfo *testInfoNew(const char *data, guint flag)
-{
- TestInfo *info = g_slice_new(TestInfo);
- info->data = g_strdup(data);
- info->flag = flag;
-
- return info;
-}
-
-static void testInfoDestroy(TestInfo *info)
-{
- g_free(info->data);
- g_slice_free(TestInfo, info);
-}
-
-static void contextMenuFixtureSetup(ContextMenuFixture *fixture, gconstpointer data)
-{
- fixture->webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- loop = g_main_loop_new(NULL, TRUE);
- fixture->info = (TestInfo *)data;
-}
-
-static void contextMenuFixtureTeardown(ContextMenuFixture *fixture, gconstpointer data)
-{
- g_object_unref(fixture->webView);
- g_main_loop_unref(loop);
- testInfoDestroy(fixture->info);
-}
-
-static GList *checkAction(GList *iter, WebKitContextMenuAction action)
-{
- GtkMenuItem *item = (GtkMenuItem *)iter->data;
-
- g_assert(GTK_IS_MENU_ITEM(item));
- g_assert(webkit_context_menu_item_get_action(item) == action);
-
- return iter->next;
-}
-
-static GList *checkActionWithSubmenu(GList *iter, WebKitContextMenuAction action)
-{
- GtkMenuItem *item = (GtkMenuItem *)iter->data;
-
- g_assert(GTK_IS_MENU_ITEM(item));
- g_assert(webkit_context_menu_item_get_action(item) == action);
- g_assert(GTK_IS_MENU(gtk_menu_item_get_submenu(item)));
-
- return iter->next;
-}
-
-static GList *checkSeparator(GList *iter)
-{
- GtkMenuItem *item = (GtkMenuItem *)iter->data;
-
- g_assert(GTK_IS_SEPARATOR_MENU_ITEM(item));
-
- return iter->next;
-}
-
-static gboolean contextMenuCallback(WebKitWebView *webView, GtkWidget *defaultMenu, WebKitHitTestResult *hitTestResult, gboolean keyboardMode, gpointer userData)
-{
- TestInfo *info = (TestInfo *)userData;
- guint context;
- GList *items;
- GList *iter;
-
- /* Check signal parameters */
- g_assert(WEBKIT_IS_WEB_VIEW(webView));
- g_assert(GTK_IS_MENU(defaultMenu));
- g_assert(WEBKIT_IS_HIT_TEST_RESULT(hitTestResult));
- g_assert(!keyboardMode);
-
- g_object_get(hitTestResult, "context", &context, NULL);
- g_assert(context & info->flag);
-
- items = gtk_container_get_children(GTK_CONTAINER(defaultMenu));
- switch (info->flag) {
- case WEBKIT_HIT_TEST_RESULT_CONTEXT_DOCUMENT:
- iter = items;
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_GO_BACK);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_GO_FORWARD);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_STOP);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_RELOAD);
- g_assert(!iter);
-
- break;
- case WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE:
- iter = items;
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_IMAGE_IN_NEW_WINDOW);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_IMAGE_TO_DISK);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY_IMAGE_TO_CLIPBOARD);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY_IMAGE_URL_TO_CLIPBOARD);
- g_assert(!iter);
-
- break;
- case WEBKIT_HIT_TEST_RESULT_CONTEXT_EDITABLE:
- iter = items;
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_CUT);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_PASTE);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_DELETE);
- iter = checkSeparator(iter);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_SELECT_ALL);
- iter = checkSeparator(iter);
- iter = checkActionWithSubmenu(iter, WEBKIT_CONTEXT_MENU_ACTION_INPUT_METHODS);
- iter = checkActionWithSubmenu(iter, WEBKIT_CONTEXT_MENU_ACTION_UNICODE);
- g_assert(!iter);
-
- break;
- case WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK:
- iter = items;
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK_IN_NEW_WINDOW);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_LINK_TO_DISK);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY_LINK_TO_CLIPBOARD);
- g_assert(!iter);
-
- break;
- default:
- g_assert_not_reached();
- }
-
- g_list_free(items);
- g_main_loop_quit(loop);
-
- return TRUE;
-}
-
-static void pushEvent(WebKitWebView *webView)
-{
- GdkEvent *event = gdk_event_new(GDK_BUTTON_PRESS);
-#if GTK_CHECK_VERSION(3, 0, 0)
- GdkDeviceManager *deviceManager;
-#endif
-
- event->any.window = g_object_ref(gtk_widget_get_window(GTK_WIDGET(webView)));
- event->any.send_event = FALSE;
- event->button.time = GDK_CURRENT_TIME;
- event->button.button = 3;
- event->button.x = event->button.y = 5;
- event->button.x_root = event->button.x;
- event->button.y_root = event->button.y;
-#if GTK_CHECK_VERSION(3, 0, 0)
- deviceManager = gdk_display_get_device_manager(gdk_display_get_default());
- event->button.device = gdk_device_manager_get_client_pointer(deviceManager);
-#endif
-
- gdk_event_put(event);
- gdk_event_free(event);
-}
-
-static void loadStatusCallback(WebKitWebView *webView, GParamSpec *spec, gpointer data)
-{
- WebKitLoadStatus status = webkit_web_view_get_load_status(webView);
- TestInfo *info = (TestInfo *)data;
-
- g_assert(status != WEBKIT_LOAD_FAILED);
-
- if (status != WEBKIT_LOAD_FINISHED)
- return;
-
- g_signal_connect(webView, "context-menu", G_CALLBACK(contextMenuCallback), info);
- pushEvent(webView);
-}
-
-static gboolean mapEventCallback(GtkWidget *widget, GdkEvent *event, gpointer data)
-{
- gtk_widget_grab_focus(widget);
- ContextMenuFixture *fixture = (ContextMenuFixture *)data;
- webkit_web_view_load_string(fixture->webView,
- fixture->info->data,
- "text/html",
- "utf-8",
- "file://");
- g_signal_connect(fixture->webView, "notify::load-status", G_CALLBACK(loadStatusCallback), fixture->info);
- return FALSE;
-}
-
-static void testContextMenu(ContextMenuFixture *fixture, gconstpointer data)
-{
- GtkAllocation allocation = { 0, 0, 50, 50 };
- GtkWidget *window = gtk_window_new(GTK_WINDOW_POPUP);
-
- gtk_window_resize(GTK_WINDOW(window), 50, 50);
- gtk_window_move(GTK_WINDOW(window), 0, 0);
- gtk_widget_size_allocate(GTK_WIDGET(fixture->webView), &allocation);
- gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(fixture->webView));
- g_signal_connect(window, "map-event", G_CALLBACK(mapEventCallback), fixture);
- gtk_widget_show_all(window);
-
- g_main_loop_run(loop);
-}
-
-static gboolean contextMenuCustomItemCallback(WebKitWebView *webView, GtkWidget *defaultMenu, WebKitHitTestResult *hitTestResult, gboolean keyboardMode, gpointer userData)
-{
- TestInfo *info = (TestInfo *)userData;
- guint context;
- GList *items;
- GList *iter;
- GtkWidget *menuItem;
- GtkAction *action;
-
- /* Check signal parameters */
- g_assert(WEBKIT_IS_WEB_VIEW(webView));
- g_assert(GTK_IS_MENU(defaultMenu));
- g_assert(WEBKIT_IS_HIT_TEST_RESULT(hitTestResult));
- g_assert(!keyboardMode);
-
- g_object_get(hitTestResult, "context", &context, NULL);
- g_assert(context & info->flag);
-
- action = gtk_action_new("TestAction", "Custom Action", "Custom Action Tooltip", NULL);
- menuItem = gtk_action_create_menu_item(action);
- g_object_unref(action);
-
- gtk_menu_shell_append(GTK_MENU_SHELL(defaultMenu), menuItem);
- gtk_widget_show(menuItem);
-
- items = gtk_container_get_children(GTK_CONTAINER(defaultMenu));
- iter = items;
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_GO_BACK);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_GO_FORWARD);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_STOP);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_RELOAD);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_NO_ACTION);
- g_assert(!iter);
-
- g_list_free(items);
- g_main_loop_quit(loop);
-
- return TRUE;
-}
-
-static void testContextMenuCustomItem(ContextMenuFixture *fixture, gconstpointer data)
-{
- GtkWidget *window = gtk_window_new(GTK_WINDOW_POPUP);
- gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(fixture->webView));
- gtk_widget_show_all(window);
- gtk_widget_grab_focus(GTK_WIDGET(fixture->webView));
-
- webkit_web_view_load_string(fixture->webView,
- fixture->info->data,
- "text/html",
- "utf-8",
- "file://");
- g_signal_connect(fixture->webView, "context-menu", G_CALLBACK(contextMenuCustomItemCallback), fixture->info);
- pushEvent(fixture->webView);
-}
-
-int main(int argc, char **argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- // Get rid of runtime warnings about deprecated properties and signals, since they break the tests.
- g_setenv("G_ENABLE_DIAGNOSTIC", "0", TRUE);
-
- g_test_bug_base("https://bugs.webkit.org/");
-
- g_test_add("/webkit/testcontextmenu/document", ContextMenuFixture,
- testInfoNew("<html><body><h1>WebKitGTK+!</h1></body></html>",
- WEBKIT_HIT_TEST_RESULT_CONTEXT_DOCUMENT),
- contextMenuFixtureSetup, testContextMenu, contextMenuFixtureTeardown);
- /* We hardcode all elements to be at 0,0 so that we know where to generate the button events */
- g_test_add("/webkit/testcontextmenu/image", ContextMenuFixture,
- testInfoNew("<html><body><img style='position:absolute; left:0; top:0' src='0xdeadbeef' width=50 height=50></img></body></html>",
- WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE),
- contextMenuFixtureSetup, testContextMenu, contextMenuFixtureTeardown);
- g_test_add("/webkit/testcontextmenu/editable", ContextMenuFixture,
- testInfoNew("<html><body><input style='position:absolute; left:0; top:0' size='35'></input>></body></html>",
- WEBKIT_HIT_TEST_RESULT_CONTEXT_EDITABLE),
- contextMenuFixtureSetup, testContextMenu, contextMenuFixtureTeardown);
- g_test_add("/webkit/testcontextmenu/link", ContextMenuFixture,
- testInfoNew("<html><body><a style='position:absolute; left:0; top:0' href='http://www.example.com'>HELLO WORLD</a></body></html>",
- WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK),
- contextMenuFixtureSetup, testContextMenu, contextMenuFixtureTeardown);
- g_test_add("/webkit/testcontextmenu/customitem", ContextMenuFixture,
- testInfoNew("<html><body><h1>WebKitGTK+!</h1></body></html>",
- WEBKIT_HIT_TEST_RESULT_CONTEXT_DOCUMENT),
- contextMenuFixtureSetup, testContextMenuCustomItem, contextMenuFixtureTeardown);
-
- return g_test_run();
-}
-
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testcopyandpaste.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testcopyandpaste.c
deleted file mode 100644
index bb38ea66b..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testcopyandpaste.c
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright (C) 2010 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2,1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <glib/gstdio.h>
-#include <webkit/webkit.h>
-#include <JavaScriptCore/JSStringRef.h>
-#include <JavaScriptCore/JSContextRef.h>
-
-typedef struct {
- char* page;
- char* expectedContent;
-} TestInfo;
-
-typedef struct {
- GtkWidget* window;
- WebKitWebView* webView;
- GMainLoop* loop;
- TestInfo* info;
-} CopyAndPasteFixture;
-
-TestInfo*
-test_info_new(const char* page, const char* expectedContent)
-{
- TestInfo* info;
- info = g_slice_new0(TestInfo);
- info->page = g_strdup(page);
- if (expectedContent)
- info->expectedContent = g_strdup(expectedContent);
- return info;
-}
-
-void
-test_info_destroy(TestInfo* info)
-{
- g_free(info->page);
- g_free(info->expectedContent);
- g_slice_free(TestInfo, info);
-}
-
-static void copy_and_paste_fixture_setup(CopyAndPasteFixture* fixture, gconstpointer data)
-{
- fixture->loop = g_main_loop_new(NULL, TRUE);
-
- fixture->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- fixture->webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
-
- gtk_container_add(GTK_CONTAINER(fixture->window), GTK_WIDGET(fixture->webView));
-}
-
-static void copy_and_paste_fixture_teardown(CopyAndPasteFixture* fixture, gconstpointer data)
-{
- gtk_widget_destroy(fixture->window);
- g_main_loop_unref(fixture->loop);
- test_info_destroy(fixture->info);
-}
-
-static void load_status_cb(WebKitWebView* webView, GParamSpec* spec, gpointer data)
-{
- CopyAndPasteFixture* fixture = (CopyAndPasteFixture*)data;
- WebKitLoadStatus status = webkit_web_view_get_load_status(webView);
- if (status != WEBKIT_LOAD_FINISHED)
- return;
-
- GtkClipboard* clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
- gtk_clipboard_clear(clipboard);
-
- webkit_web_view_copy_clipboard(webView);
-
- gchar* text = gtk_clipboard_wait_for_text(clipboard);
- g_assert(text || !fixture->info->expectedContent);
- g_assert(!text || !strcmp(text, fixture->info->expectedContent));
- g_free(text);
-
- // Verify that the markup starts with the proper content-type meta tag prefix.
- GtkSelectionData* selectionData = gtk_clipboard_wait_for_contents(clipboard, gdk_atom_intern("text/html", FALSE));
- if (selectionData) {
- static const char* markupPrefix = "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">";
- char* markup = g_strndup((const char*) gtk_selection_data_get_data(selectionData),
- gtk_selection_data_get_length(selectionData));
- g_assert(strlen(markupPrefix) <= strlen(markup));
- g_assert(!strncmp(markupPrefix, markup, strlen(markupPrefix)));
- g_free(markup);
- }
-
- g_assert(!gtk_clipboard_wait_is_uris_available(clipboard));
- g_assert(!gtk_clipboard_wait_is_image_available(clipboard));
-
- g_main_loop_quit(fixture->loop);
-}
-
-gboolean map_event_cb(GtkWidget *widget, GdkEvent* event, gpointer data)
-{
- CopyAndPasteFixture* fixture = (CopyAndPasteFixture*)data;
- webkit_web_view_load_string(fixture->webView, fixture->info->page,
- "text/html", "utf-8", "file://");
- return FALSE;
-}
-
-static void test_copy_and_paste(CopyAndPasteFixture* fixture, gconstpointer data)
-{
- fixture->info = (TestInfo*)data;
- g_signal_connect(fixture->window, "map-event",
- G_CALLBACK(map_event_cb), fixture);
-
- gtk_widget_show(fixture->window);
- gtk_widget_show(GTK_WIDGET(fixture->webView));
- gtk_window_present(GTK_WINDOW(fixture->window));
- gtk_widget_grab_focus(GTK_WIDGET(fixture->webView));
-
- g_signal_connect(fixture->webView, "notify::load-status",
- G_CALLBACK(load_status_cb), fixture);
-
- g_main_loop_run(fixture->loop);
-}
-
-static CopyAndPasteFixture* currentFixture;
-static JSValueRef runPasteTestCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- gtk_widget_grab_focus(GTK_WIDGET(currentFixture->webView));
-
- // Simulate a paste keyboard sequence.
- GdkEvent* event = gdk_event_new(GDK_KEY_PRESS);
- event->key.keyval = gdk_unicode_to_keyval('v');
- event->key.state = GDK_CONTROL_MASK;
- event->key.window = gtk_widget_get_window(GTK_WIDGET(currentFixture->webView));
- g_object_ref(event->key.window);
-#ifndef GTK_API_VERSION_2
- GdkDeviceManager* manager = gdk_display_get_device_manager(gdk_window_get_display(event->key.window));
- gdk_event_set_device(event, gdk_device_manager_get_client_pointer(manager));
-#endif
-
- GdkKeymapKey* keys;
- gint n_keys;
- if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), event->key.keyval, &keys, &n_keys)) {
- event->key.hardware_keycode = keys[0].keycode;
- g_free(keys);
- }
-
- gtk_main_do_event(event);
- event->key.type = GDK_KEY_RELEASE;
- gtk_main_do_event(event);
- gdk_event_free(event);
-
- JSStringRef scriptString = JSStringCreateWithUTF8CString("document.body.innerHTML;");
- JSValueRef value = JSEvaluateScript(context, scriptString, 0, 0, 0, 0);
- JSStringRelease(scriptString);
-
- g_assert(JSValueIsString(context, value));
- JSStringRef actual = JSValueToStringCopy(context, value, exception);
- g_assert(!exception || !*exception);
- g_assert(currentFixture->info->expectedContent);
- JSStringRef expected = JSStringCreateWithUTF8CString(currentFixture->info->expectedContent);
- g_assert(JSStringIsEqual(expected, actual));
-
- JSStringRelease(expected);
- JSStringRelease(actual);
- g_main_loop_quit(currentFixture->loop);
- return JSValueMakeUndefined(context);
-}
-
-static void window_object_cleared_callback(WebKitWebView* web_view, WebKitWebFrame* web_frame, JSGlobalContextRef context, JSObjectRef window_object, gpointer data)
-{
- JSStringRef name = JSStringCreateWithUTF8CString("runTest");
- JSObjectRef testComplete = JSObjectMakeFunctionWithCallback(context, name, runPasteTestCallback);
- JSObjectSetProperty(context, window_object, name, testComplete, kJSPropertyAttributeNone, 0);
- JSStringRelease(name);
-}
-
-static void pasting_test_get_data_callback(GtkClipboard* clipboard, GtkSelectionData* selection_data, guint info, gpointer data)
-{
- gtk_selection_data_set(selection_data, gdk_atom_intern("text/html", FALSE), 8, (const guchar*) data, strlen((char*)data) + 1);
-}
-
-static void pasting_test_clear_data_callback(GtkClipboard* clipboard, gpointer data)
-{
- g_free(data);
-}
-
-static void test_pasting_markup(CopyAndPasteFixture* fixture, gconstpointer data)
-{
- fixture->info = (TestInfo*)data;
- currentFixture = fixture;
-
- GtkTargetList* targetList = gtk_target_list_new(0, 0);
- gtk_target_list_add(targetList, gdk_atom_intern("text/html", FALSE), 0, 0);
-
- int numberOfTargets = 1;
- GtkTargetEntry* targetTable = gtk_target_table_new_from_list(targetList, &numberOfTargets);
- gtk_clipboard_set_with_data(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD),
- targetTable, numberOfTargets,
- pasting_test_get_data_callback,
- pasting_test_clear_data_callback,
- g_strdup(fixture->info->expectedContent));
- gtk_target_list_unref(targetList);
- gtk_target_table_free(targetTable, numberOfTargets);
-
- g_signal_connect(fixture->window, "map-event",
- G_CALLBACK(map_event_cb), fixture);
- g_signal_connect(fixture->webView, "window-object-cleared",
- G_CALLBACK(window_object_cleared_callback), fixture);
-
- gtk_widget_show(fixture->window);
- gtk_widget_show(GTK_WIDGET(fixture->webView));
- gtk_window_present(GTK_WINDOW(fixture->window));
-
- g_main_loop_run(fixture->loop);
-}
-
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- const char* selected_span_html = "<html><body>"
- "<span id=\"mainspan\">All work and no play <span>make Jack a dull</span> boy.</span>"
- "<script>document.getSelection().collapse();\n"
- "document.getSelection().selectAllChildren(document.getElementById('mainspan'));\n"
- "</script></body></html>";
- const char* no_selection_html = "<html><body>"
- "<span id=\"mainspan\">All work and no play <span>make Jack a dull</span> boy</span>"
- "<script>document.getSelection().collapse();\n"
- "</script></body></html>";
-
- g_test_add("/webkit/copyandpaste/selection", CopyAndPasteFixture,
- test_info_new(selected_span_html, "All work and no play make Jack a dull boy."),
- copy_and_paste_fixture_setup,
- test_copy_and_paste,
- copy_and_paste_fixture_teardown);
- g_test_add("/webkit/copyandpaste/no-selection", CopyAndPasteFixture,
- test_info_new(no_selection_html, 0),
- copy_and_paste_fixture_setup,
- test_copy_and_paste,
- copy_and_paste_fixture_teardown);
-
- const char* paste_test_html = "<html>"
- "<body onLoad=\"document.body.focus(); runTest();\" contentEditable=\"true\">"
- "</body></html>";
- g_test_add("/webkit/copyandpaste/paste-markup", CopyAndPasteFixture,
- test_info_new(paste_test_html, "bobby"),
- copy_and_paste_fixture_setup,
- test_pasting_markup,
- copy_and_paste_fixture_teardown);
-
- return g_test_run();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testdomdocument.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testdomdocument.c
deleted file mode 100644
index 8e46c030d..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testdomdocument.c
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- * Copyright (C) 2010 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "test_utils.h"
-
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-#define HTML_DOCUMENT_TITLE "<html><head><title>This is the title</title></head><body></body></html>"
-#define HTML_DOCUMENT_ELEMENTS "<html><body><ul><li>1</li><li>2</li><li>3</li></ul></body></html>"
-#define HTML_DOCUMENT_ELEMENTS_CLASS "<html><body><div class=\"test\"></div><div class=\"strange\"></div><div class=\"test\"></div></body></html>"
-#define HTML_DOCUMENT_ELEMENTS_ID "<html><body><div id=\"testok\"></div><div id=\"testbad\">first</div><div id=\"testbad\">second</div></body></html>"
-#define HTML_DOCUMENT_LINKS "<html><head><title>Title</title></head><body><a href=\"about:blank\">blank</a><a href=\"http://www.google.com\">google</a><a href=\"http://www.webkit.org\">webkit</a></body></html>"
-#define HTML_DOCUMENT_IFRAME "<html><head><title>IFrame</title></head><body><iframe id='iframe'></iframe><div id='test'></div></body></html>"
-#define HTML_DOCUMENT_TABLE "<html><body><table id=\"table\"></table></body></html>"
-#define HTML_DOCUMENT_EVALUATE "<html><head><title></title></head><body><div>First div</div><div>Second div</div></body></html>"
-
-typedef struct {
- GtkWidget* webView;
- GMainLoop* loop;
-} DomDocumentFixture;
-
-static gboolean finish_loading(DomDocumentFixture* fixture)
-{
- if (g_main_loop_is_running(fixture->loop))
- g_main_loop_quit(fixture->loop);
-
- return FALSE;
-}
-
-static void dom_document_fixture_setup(DomDocumentFixture* fixture, gconstpointer data)
-{
- fixture->loop = g_main_loop_new(NULL, TRUE);
- fixture->webView = webkit_web_view_new();
- g_object_ref_sink(fixture->webView);
-
- if (data != NULL)
- webkit_web_view_load_string(WEBKIT_WEB_VIEW (fixture->webView), (const char*) data, NULL, NULL, NULL);
-
- g_idle_add((GSourceFunc)finish_loading, fixture);
- g_main_loop_run(fixture->loop);
-}
-
-static void dom_document_fixture_teardown(DomDocumentFixture* fixture, gconstpointer data)
-{
- if (fixture->webView)
- g_object_unref(fixture->webView);
- g_main_loop_unref(fixture->loop);
-}
-
-static void test_dom_document_title(DomDocumentFixture* fixture, gconstpointer data)
-{
- g_assert(fixture);
- WebKitWebView* view = (WebKitWebView*)fixture->webView;
- g_assert(view);
- WebKitDOMDocument* document = webkit_web_view_get_dom_document(view);
- g_assert(document);
- gchar* title = webkit_dom_document_get_title(document);
- g_assert(title);
- g_assert_cmpstr(title, ==, "This is the title");
- g_free(title);
- webkit_dom_document_set_title(document, "This is the second title");
- title = webkit_dom_document_get_title(document);
- g_assert(title);
- g_assert_cmpstr(title, ==, "This is the second title");
- g_free(title);
-}
-
-static void test_dom_document_get_elements_by_tag_name(DomDocumentFixture* fixture, gconstpointer data)
-{
- g_assert(fixture);
- WebKitWebView* view = (WebKitWebView*)fixture->webView;
- g_assert(view);
- WebKitDOMDocument* document = webkit_web_view_get_dom_document(view);
- g_assert(document);
- WebKitDOMNodeList* list = webkit_dom_document_get_elements_by_tag_name(document, "li");
- g_assert(list);
- gulong length = webkit_dom_node_list_get_length(list);
- g_assert_cmpint(length, ==, 3);
-
- guint i;
-
- for (i = 0; i < length; i++) {
- WebKitDOMNode* item = webkit_dom_node_list_item(list, i);
- g_assert(item);
- WebKitDOMElement* element = (WebKitDOMElement*)item;
- g_assert(element);
- g_assert_cmpstr(webkit_dom_element_get_tag_name(element), ==, "LI");
- WebKitDOMHTMLElement* htmlElement = (WebKitDOMHTMLElement*)element;
- char* n = g_strdup_printf("%d", i+1);
- g_assert_cmpstr(webkit_dom_html_element_get_inner_text(htmlElement), ==, n);
- g_free(n);
- }
-
- g_object_unref(list);
-}
-
-static void test_dom_document_get_elements_by_class_name(DomDocumentFixture* fixture, gconstpointer data)
-{
- g_assert(fixture);
- WebKitWebView* view = (WebKitWebView*)fixture->webView;
- g_assert(view);
- WebKitDOMDocument* document = webkit_web_view_get_dom_document(view);
- g_assert(document);
- WebKitDOMNodeList* list = webkit_dom_document_get_elements_by_class_name(document, "test");
- g_assert(list);
- gulong length = webkit_dom_node_list_get_length(list);
- g_assert_cmpint(length, ==, 2);
-
- guint i;
-
- for (i = 0; i < length; i++) {
- WebKitDOMNode* item = webkit_dom_node_list_item(list, i);
- g_assert(item);
- WebKitDOMElement* element = (WebKitDOMElement*)item;
- g_assert(element);
- g_assert_cmpstr(webkit_dom_element_get_tag_name(element), ==, "DIV");
- }
-
- g_object_unref(list);
-}
-
-static void test_dom_document_get_element_by_id(DomDocumentFixture* fixture, gconstpointer data)
-{
- g_assert(fixture);
- WebKitWebView* view = (WebKitWebView*)fixture->webView;
- g_assert(view);
- WebKitDOMDocument* document = webkit_web_view_get_dom_document(view);
- g_assert(document);
- WebKitDOMElement* element = webkit_dom_document_get_element_by_id(document, "testok");
- g_assert(element);
- element = webkit_dom_document_get_element_by_id(document, "this-id-does-not-exist");
- g_assert(element == 0);
- /* The DOM spec says the return value is undefined when there's
- * more than one element with the same id; in our case the first
- * one will be returned */
- element = webkit_dom_document_get_element_by_id(document, "testbad");
- g_assert(element);
- WebKitDOMHTMLElement* htmlElement = (WebKitDOMHTMLElement*)element;
- g_assert_cmpstr(webkit_dom_html_element_get_inner_text(htmlElement), ==, "first");
-}
-
-static void test_dom_document_get_links(DomDocumentFixture* fixture, gconstpointer data)
-{
- g_assert(fixture);
- WebKitWebView* view = (WebKitWebView*)fixture->webView;
- g_assert(view);
- WebKitDOMDocument* document = webkit_web_view_get_dom_document(view);
- g_assert(document);
- WebKitDOMHTMLCollection *collection = webkit_dom_document_get_links(document);
- g_assert(collection);
- gulong length = webkit_dom_html_collection_get_length(collection);
- g_assert_cmpint(length, ==, 3);
-
- guint i;
-
- for (i = 0; i < length; i++) {
- static const char* names[] = { "blank", "google", "webkit" };
- static const char* uris[] = { "about:blank", "http://www.google.com/", "http://www.webkit.org/" };
- WebKitDOMNode *node = webkit_dom_html_collection_item(collection, i);
- g_assert(node);
- WebKitDOMElement* element = (WebKitDOMElement*)node;
- g_assert_cmpstr(webkit_dom_element_get_tag_name(element), ==, "A");
- WebKitDOMHTMLElement *htmlElement = (WebKitDOMHTMLElement*)element;
- g_assert_cmpstr(webkit_dom_html_element_get_inner_text(htmlElement), ==, names[i]);
- WebKitDOMHTMLAnchorElement *anchor = (WebKitDOMHTMLAnchorElement*)element;
- g_assert_cmpstr(webkit_dom_html_anchor_element_get_href(anchor), ==, uris[i]);
- }
- g_object_unref(collection);
-}
-
-static void test_dom_document_insert_row(DomDocumentFixture* fixture, gconstpointer data)
-{
- g_assert(fixture);
- WebKitWebView* view = (WebKitWebView*)fixture->webView;
- g_assert(view);
- WebKitDOMDocument* document = webkit_web_view_get_dom_document(view);
- g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
- WebKitDOMElement* table = webkit_dom_document_get_element_by_id(document, "table");
- g_assert(WEBKIT_DOM_IS_HTML_ELEMENT(table));
- WebKitDOMHTMLCollection* rows = webkit_dom_html_table_element_get_rows(WEBKIT_DOM_HTML_TABLE_ELEMENT(table));
- g_assert(WEBKIT_DOM_IS_HTML_COLLECTION(rows));
-
- // Table is initially empty.
- g_assert_cmpint(webkit_dom_html_collection_get_length(rows), ==, 0);
- WebKitDOMHTMLElement* row = webkit_dom_html_table_element_insert_row(WEBKIT_DOM_HTML_TABLE_ELEMENT(table), -1, NULL);
- g_assert(WEBKIT_DOM_IS_HTML_TABLE_ROW_ELEMENT(row));
- rows = webkit_dom_html_table_element_get_rows(WEBKIT_DOM_HTML_TABLE_ELEMENT(table));
- g_assert(WEBKIT_DOM_IS_HTML_COLLECTION(rows));
- g_assert_cmpint(webkit_dom_html_collection_get_length(rows), ==, 1);
-}
-
-static void test_dom_document_evaluate(DomDocumentFixture* fixture, gconstpointer data)
-{
- g_assert(fixture);
- WebKitWebView* view = (WebKitWebView*)fixture->webView;
- g_assert(view);
- WebKitDOMDocument* document = webkit_web_view_get_dom_document(view);
- g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
- WebKitDOMNodeList* list = webkit_dom_document_get_elements_by_tag_name(document, "html");
- g_assert(list);
- gulong length = webkit_dom_node_list_get_length(list);
- g_assert_cmpint(length, ==, 1);
- WebKitDOMNode* html = webkit_dom_node_list_item(list, 0);
- g_assert(WEBKIT_DOM_IS_NODE(html));
-
- WebKitDOMXPathResult* result = webkit_dom_document_evaluate(document, "//div", html, NULL, 0, NULL, NULL);
- g_assert(WEBKIT_DOM_IS_XPATH_RESULT(result));
-
- int i = 0;
- WebKitDOMNode* node;
- while ( (node = webkit_dom_xpath_result_iterate_next(result, NULL)) != NULL) {
- g_assert(node);
- WebKitDOMElement* element = (WebKitDOMElement*)node;
- g_assert_cmpstr(webkit_dom_element_get_tag_name(element), ==, "DIV");
- i++;
- }
- g_assert_cmpint(i, ==, 2);
-
- g_object_unref(list);
-}
-
-static void weak_notify(gpointer data, GObject* zombie)
-{
- guint* count = (guint*)data;
- (*count)++;
-}
-
-static void test_dom_document_garbage_collection(DomDocumentFixture* fixture, gconstpointer data)
-{
- guint count = 0;
- g_assert(fixture);
- WebKitWebView* view = (WebKitWebView*)fixture->webView;
- g_assert(view);
- WebKitDOMDocument* document = webkit_web_view_get_dom_document(view);
- g_assert(document);
- g_object_weak_ref(G_OBJECT(document), (GWeakNotify)weak_notify, &count);
- WebKitDOMHTMLHeadElement* head = webkit_dom_document_get_head(document);
- g_assert(head);
- g_object_weak_ref(G_OBJECT(head), (GWeakNotify)weak_notify, &count);
- WebKitDOMHTMLElement* body = webkit_dom_document_get_body(document);
- g_assert(body);
- g_object_weak_ref(G_OBJECT(body), (GWeakNotify)weak_notify, &count);
- WebKitDOMHTMLCollection *collection = webkit_dom_document_get_links(document);
- g_assert(collection);
- g_object_weak_ref(G_OBJECT(collection), (GWeakNotify)weak_notify, &count);
-
- webkit_web_view_load_string(WEBKIT_WEB_VIEW(view), HTML_DOCUMENT_LINKS, NULL, NULL, NULL);
-
- while (g_main_context_pending(NULL))
- g_main_context_iteration(NULL, FALSE);
-
- g_assert_cmpuint(count, ==, 3);
-
- g_object_unref(collection);
- g_assert_cmpuint(count, ==, 4);
-
- count = 0;
-
- document = webkit_web_view_get_dom_document(view);
- g_assert(document);
- g_object_weak_ref(G_OBJECT(document), (GWeakNotify)weak_notify, &count);
- head = webkit_dom_document_get_head(document);
- g_assert(head);
- g_object_weak_ref(G_OBJECT(head), (GWeakNotify)weak_notify, &count);
- body = webkit_dom_document_get_body(document);
- g_assert(body);
- g_object_weak_ref(G_OBJECT(body), (GWeakNotify)weak_notify, &count);
- collection = webkit_dom_document_get_links(document);
- g_assert(collection);
- g_object_weak_ref(G_OBJECT(collection), (GWeakNotify)weak_notify, &count);
- /* Ask twice for the same object */
- WebKitDOMHTMLCollection* collection2 = webkit_dom_document_get_links(document);
- g_assert(collection2);
- g_object_weak_ref(G_OBJECT(collection2), (GWeakNotify)weak_notify, &count);
-
- g_object_unref(document);
- g_object_unref(head);
- g_object_unref(body);
- g_object_unref(collection);
- g_object_unref(collection2);
-
- g_assert_cmpuint(count, ==, 5);
-
- webkit_web_view_load_string(WEBKIT_WEB_VIEW(view), HTML_DOCUMENT_IFRAME, NULL, NULL, NULL);
-
- while (g_main_context_pending(NULL))
- g_main_context_iteration(NULL, FALSE);
-
- count = 0;
-
- document = webkit_web_view_get_dom_document(view);
- body = webkit_dom_document_get_body(document);
- WebKitDOMElement* p = webkit_dom_document_create_element(document, "P", NULL);
- webkit_dom_node_append_child(WEBKIT_DOM_NODE(body), WEBKIT_DOM_NODE(p), NULL);
- g_object_weak_ref(G_OBJECT(p), (GWeakNotify)weak_notify, &count);
- /* This is wrong, p is transfer none and owned by the cache, but we shouldn't crash in that case. */
- g_object_unref(p);
-
- webkit_web_view_load_string(WEBKIT_WEB_VIEW(view), HTML_DOCUMENT_IFRAME, NULL, NULL, NULL);
-
- while (g_main_context_pending(NULL))
- g_main_context_iteration(NULL, FALSE);
-
- g_assert_cmpuint(count, ==, 1);
-
- count = 0;
-
- document = webkit_web_view_get_dom_document(view);
- WebKitDOMElement* div = webkit_dom_document_get_element_by_id(document, "test");
- g_assert(div);
- g_object_weak_ref(G_OBJECT(div), (GWeakNotify)weak_notify, &count);
- WebKitDOMElement* iframe = webkit_dom_document_get_element_by_id(document, "iframe");
- g_assert(iframe);
-
- webkit_dom_element_set_attribute(iframe, "src", "data:<html><head></head></html>", NULL);
-
- while (g_main_context_pending(NULL))
- g_main_context_iteration(NULL, FALSE);
-
- WebKitDOMDocument* iframeDocument = webkit_dom_html_iframe_element_get_content_document(WEBKIT_DOM_HTML_IFRAME_ELEMENT(iframe));
- g_assert(iframeDocument);
- head = webkit_dom_document_get_head(iframeDocument);
- g_assert(head);
- g_object_weak_ref(G_OBJECT(head), (GWeakNotify)weak_notify, &count);
-
- webkit_dom_element_set_attribute(iframe, "src", "about:blank", NULL);
-
- while (g_main_context_pending(NULL))
- g_main_context_iteration(NULL, FALSE);
-
- g_assert_cmpuint(count, ==, 1);
-
- webkit_web_view_load_string(WEBKIT_WEB_VIEW(view), HTML_DOCUMENT_LINKS, NULL, NULL, NULL);
-
- while (g_main_context_pending(NULL))
- g_main_context_iteration(NULL, FALSE);
-
- g_assert_cmpuint(count, ==, 2);
-
- count = 0;
-
- document = webkit_web_view_get_dom_document(view);
- g_assert(document);
- g_object_weak_ref(G_OBJECT(document), (GWeakNotify)weak_notify, &count);
- /* Ask twice for the Document */
- WebKitDOMDocument* document2 = webkit_web_view_get_dom_document(view);
- g_assert(document2);
- g_object_weak_ref(G_OBJECT(document2), (GWeakNotify)weak_notify, &count);
- head = webkit_dom_document_get_head(document);
- g_assert(head);
- g_object_weak_ref(G_OBJECT(head), (GWeakNotify)weak_notify, &count);
- body = webkit_dom_document_get_body(document);
- g_assert(body);
- g_object_weak_ref(G_OBJECT(body), (GWeakNotify)weak_notify, &count);
- collection = webkit_dom_document_get_links(document);
- g_assert(collection);
- g_object_weak_ref(G_OBJECT(collection), (GWeakNotify)weak_notify, &count);
-
- gtk_widget_destroy(fixture->webView);
- fixture->webView = NULL;
-
- g_assert_cmpuint(count, ==, 4);
-
- g_object_unref(collection);
-
- g_assert_cmpuint(count, ==, 5);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
-
- g_test_add("/webkit/domdocument/test_title",
- DomDocumentFixture, HTML_DOCUMENT_TITLE,
- dom_document_fixture_setup,
- test_dom_document_title,
- dom_document_fixture_teardown);
-
- g_test_add("/webkit/domdocument/test_get_elements_by_tag_name",
- DomDocumentFixture, HTML_DOCUMENT_ELEMENTS,
- dom_document_fixture_setup,
- test_dom_document_get_elements_by_tag_name,
- dom_document_fixture_teardown);
-
- g_test_add("/webkit/domdocument/test_get_elements_by_class_name",
- DomDocumentFixture, HTML_DOCUMENT_ELEMENTS_CLASS,
- dom_document_fixture_setup,
- test_dom_document_get_elements_by_class_name,
- dom_document_fixture_teardown);
-
- g_test_add("/webkit/domdocument/test_get_element_by_id",
- DomDocumentFixture, HTML_DOCUMENT_ELEMENTS_ID,
- dom_document_fixture_setup,
- test_dom_document_get_element_by_id,
- dom_document_fixture_teardown);
-
- g_test_add("/webkit/domdocument/test_get_links",
- DomDocumentFixture, HTML_DOCUMENT_LINKS,
- dom_document_fixture_setup,
- test_dom_document_get_links,
- dom_document_fixture_teardown);
-
- g_test_add("/webkit/domdocument/test_table_insert_row",
- DomDocumentFixture, HTML_DOCUMENT_TABLE,
- dom_document_fixture_setup,
- test_dom_document_insert_row,
- dom_document_fixture_teardown);
-
- g_test_add("/webkit/domdocument/test_document_evaluate",
- DomDocumentFixture, HTML_DOCUMENT_EVALUATE,
- dom_document_fixture_setup,
- test_dom_document_evaluate,
- dom_document_fixture_teardown);
-
- g_test_add("/webkit/domdocument/test_garbage_collection",
- DomDocumentFixture, HTML_DOCUMENT_LINKS,
- dom_document_fixture_setup,
- test_dom_document_garbage_collection,
- dom_document_fixture_teardown);
-
- return g_test_run();
-}
-
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testdomdomwindow.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testdomdomwindow.c
deleted file mode 100644
index 14fcd186a..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testdomdomwindow.c
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Copyright (C) 2010 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "test_utils.h"
-
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-#define HTML_DOCUMENT "<html><head><title></title></head><style type='text/css'>#test { font-size: 16px; }</style><body><p id='test'>test</p></body></html>"
-
-typedef struct {
- GtkWidget* webView;
- GtkWidget* window;
- WebKitDOMDOMWindow* domWindow;
- GMainLoop* loop;
-
- gboolean loaded;
- gboolean clicked;
- gconstpointer data;
-} DomDomviewFixture;
-
-static gboolean finish_loading(DomDomviewFixture* fixture)
-{
- if (g_main_loop_is_running(fixture->loop))
- g_main_loop_quit(fixture->loop);
-
- return FALSE;
-}
-
-static void dom_domview_fixture_setup(DomDomviewFixture* fixture, gconstpointer data)
-{
- fixture->loop = g_main_loop_new(NULL, TRUE);
- fixture->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- fixture->webView = webkit_web_view_new();
- fixture->data = data;
-
- gtk_container_add(GTK_CONTAINER(fixture->window), GTK_WIDGET(fixture->webView));
-}
-
-static void dom_domview_fixture_teardown(DomDomviewFixture* fixture, gconstpointer data)
-{
- gtk_widget_destroy(fixture->window);
- g_main_loop_unref(fixture->loop);
-}
-
-static void dom_dom_window_fixture_setup(DomDomviewFixture* fixture, gconstpointer data)
-{
- fixture->loop = g_main_loop_new(NULL, TRUE);
- fixture->webView = webkit_web_view_new();
- g_object_ref_sink(fixture->webView);
-
- if (data != NULL)
- webkit_web_view_load_string(WEBKIT_WEB_VIEW (fixture->webView), (const char*) data, NULL, NULL, NULL);
-
- g_idle_add((GSourceFunc)finish_loading, fixture);
- g_main_loop_run(fixture->loop);
-}
-
-static void dom_dom_window_fixture_teardown(DomDomviewFixture* fixture, gconstpointer data)
-{
- if (fixture->webView)
- g_object_unref(fixture->webView);
- g_main_loop_unref(fixture->loop);
-}
-
-static gboolean loadedCallback(WebKitDOMDOMWindow* view, WebKitDOMEvent* event, DomDomviewFixture* fixture)
-{
- g_assert(fixture->loaded == FALSE);
- fixture->loaded = TRUE;
-
- return FALSE;
-}
-
-static gboolean clickedCallback(WebKitDOMDOMWindow* view, WebKitDOMEvent* event, DomDomviewFixture* fixture)
-{
- WebKitDOMEventTarget* target;
- gushort phase;
-
- g_assert(event);
- g_assert(WEBKIT_DOM_IS_EVENT(event));
-
- // We should catch this in the bubbling up phase, since we are connecting to the toplevel object
- phase = webkit_dom_event_get_event_phase(event);
- g_assert_cmpint(phase, ==, 3);
-
- target = webkit_dom_event_get_current_target(event);
- g_assert(target == WEBKIT_DOM_EVENT_TARGET(view));
-
- g_assert(fixture->clicked == FALSE);
- fixture->clicked = TRUE;
-
- finish_loading(fixture);
-
- return FALSE;
-}
-
-gboolean map_event_cb(GtkWidget *widget, GdkEvent* event, DomDomviewFixture* fixture)
-{
- webkit_web_view_load_string(WEBKIT_WEB_VIEW (fixture->webView), (const char*)fixture->data, NULL, NULL, NULL);
-
- return FALSE;
-}
-
-static void load_event_callback(WebKitWebView* webView, GParamSpec* spec, DomDomviewFixture* fixture)
-{
- WebKitLoadStatus status = webkit_web_view_get_load_status(webView);
- if (status == WEBKIT_LOAD_FINISHED) {
- webkit_dom_event_target_add_event_listener(WEBKIT_DOM_EVENT_TARGET(fixture->domWindow), "click", G_CALLBACK(clickedCallback), false, fixture);
-
- g_assert(fixture->clicked == FALSE);
- gtk_test_widget_click(GTK_WIDGET(fixture->webView), 1, 0);
- }
-
-}
-
-static void test_dom_domview_signals(DomDomviewFixture* fixture, gconstpointer data)
-{
- g_assert(fixture);
- WebKitWebView* view = (WebKitWebView*)fixture->webView;
- g_assert(view);
- WebKitDOMDocument* document = webkit_web_view_get_dom_document(view);
- g_assert(document);
- WebKitDOMDOMWindow* domWindow = webkit_dom_document_get_default_view(document);
- g_assert(domWindow);
-
- fixture->domWindow = domWindow;
-
- webkit_dom_event_target_add_event_listener(WEBKIT_DOM_EVENT_TARGET(fixture->domWindow), "load", G_CALLBACK(loadedCallback), false, fixture);
- g_signal_connect(fixture->window, "map-event", G_CALLBACK(map_event_cb), fixture);
- g_signal_connect(fixture->webView, "notify::load-status", G_CALLBACK(load_event_callback), fixture);
-
- gtk_widget_show_all(fixture->window);
- gtk_window_present(GTK_WINDOW(fixture->window));
-
- g_main_loop_run(fixture->loop);
-
- g_assert(fixture->loaded);
- g_assert(fixture->clicked);
-}
-
-static gboolean
-clicked_cb(WebKitDOMEventTarget* target, WebKitDOMEvent* event, DomDomviewFixture* fixture)
-{
- g_assert(fixture->clicked == FALSE);
- fixture->clicked = TRUE;
- finish_loading(fixture);
- return FALSE;
-}
-
-static void load_status_callback(WebKitWebView* webView, GParamSpec* spec, DomDomviewFixture* fixture)
-{
- WebKitLoadStatus status = webkit_web_view_get_load_status(webView);
- if (status == WEBKIT_LOAD_FINISHED) {
- WebKitDOMDocument* document;
- WebKitDOMDOMWindow* domWindow;
- WebKitDOMElement* element;
- WebKitDOMEvent* event;
- glong clientX, clientY;
-
- document = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(fixture->webView));
- g_assert(document);
- domWindow = webkit_dom_document_get_default_view(document);
- g_assert(domWindow);
- fixture->domWindow = domWindow;
-
- element = webkit_dom_document_get_element_by_id(document, "test");
- g_assert(element);
- event = webkit_dom_document_create_event(document, "MouseEvent", NULL);
- g_assert(event);
- g_assert(WEBKIT_DOM_IS_EVENT(event));
- g_assert(WEBKIT_DOM_IS_MOUSE_EVENT(event));
- clientX = webkit_dom_element_get_client_left(element);
- clientY = webkit_dom_element_get_client_top(element);
- webkit_dom_mouse_event_init_mouse_event(WEBKIT_DOM_MOUSE_EVENT(event),
- "click", TRUE, TRUE,
- fixture->domWindow, 0, 0, 0, clientX, clientY,
- FALSE, FALSE, FALSE, FALSE,
- 1, WEBKIT_DOM_EVENT_TARGET(element));
- webkit_dom_event_target_add_event_listener(WEBKIT_DOM_EVENT_TARGET(element), "click", G_CALLBACK(clicked_cb), false, fixture);
- g_assert(fixture->clicked == FALSE);
- webkit_dom_event_target_dispatch_event(WEBKIT_DOM_EVENT_TARGET(element), event, NULL);
- }
-
-}
-
-static void test_dom_domview_dispatch_event(DomDomviewFixture* fixture, gconstpointer data)
-{
- g_signal_connect(fixture->window, "map-event", G_CALLBACK(map_event_cb), fixture);
- g_signal_connect(fixture->webView, "notify::load-status", G_CALLBACK(load_status_callback), fixture);
-
- gtk_widget_show_all(fixture->window);
- gtk_window_present(GTK_WINDOW(fixture->window));
-
- g_main_loop_run (fixture->loop);
- g_assert(fixture->clicked);
-}
-
-static void test_dom_dom_window_get_computed_style(DomDomviewFixture* fixture, gconstpointer data)
-{
- WebKitDOMDocument* document = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(fixture->webView));
- g_assert(document);
- WebKitDOMDOMWindow* domWindow = webkit_dom_document_get_default_view(document);
- g_assert(domWindow);
-
- WebKitDOMElement* element = webkit_dom_document_get_element_by_id(document, "test");
- g_assert(element);
- g_assert(WEBKIT_DOM_IS_ELEMENT(element));
- WebKitDOMCSSStyleDeclaration* cssStyle = webkit_dom_dom_window_get_computed_style(domWindow, element, NULL);
- gchar* fontSize = webkit_dom_css_style_declaration_get_property_value(cssStyle, "font-size");
- g_assert_cmpstr(fontSize, ==, "16px");
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
-
- g_test_add("/webkit/domdomview/signals",
- DomDomviewFixture, HTML_DOCUMENT,
- dom_domview_fixture_setup,
- test_dom_domview_signals,
- dom_domview_fixture_teardown);
-
- g_test_add("/webkit/domdomview/dispatch_event",
- DomDomviewFixture, HTML_DOCUMENT,
- dom_domview_fixture_setup,
- test_dom_domview_dispatch_event,
- dom_domview_fixture_teardown);
-
- g_test_add("/webkit/domdomwindow/get_computed_style",
- DomDomviewFixture, HTML_DOCUMENT,
- dom_dom_window_fixture_setup,
- test_dom_dom_window_get_computed_style,
- dom_dom_window_fixture_teardown);
-
- return g_test_run();
-}
-
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testdomnode.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testdomnode.c
deleted file mode 100644
index ed4bcbdaa..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testdomnode.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (C) 2010 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "test_utils.h"
-
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-#define HTML_DOCUMENT_HIERARCHY_NAVIGATION "<html><head><title>This is the title</title></head><body><p>1</p><p>2</p><p>3</p></body></html>"
-#define HTML_DOCUMENT_NODE_INSERTION "<html><body></body></html>"
-
-typedef struct {
- GtkWidget* webView;
- GMainLoop* loop;
-} DomNodeFixture;
-
-static gboolean finish_loading(DomNodeFixture* fixture)
-{
- if (g_main_loop_is_running(fixture->loop))
- g_main_loop_quit(fixture->loop);
-
- return FALSE;
-}
-
-static void dom_node_fixture_setup(DomNodeFixture* fixture, gconstpointer data)
-{
- fixture->loop = g_main_loop_new(NULL, TRUE);
- fixture->webView = webkit_web_view_new();
- g_object_ref_sink(fixture->webView);
-
- if (data != NULL)
- webkit_web_view_load_string(WEBKIT_WEB_VIEW(fixture->webView), (const char*)data, NULL, NULL, NULL);
-
- g_idle_add((GSourceFunc)finish_loading, fixture);
- g_main_loop_run(fixture->loop);
-}
-
-static void dom_node_fixture_teardown(DomNodeFixture* fixture, gconstpointer data)
-{
- g_object_unref(fixture->webView);
- g_main_loop_unref(fixture->loop);
-}
-
-static void test_dom_node_hierarchy_navigation(DomNodeFixture* fixture, gconstpointer data)
-{
- WebKitDOMDocument* document;
- WebKitDOMHTMLHeadElement* head;
- WebKitDOMHTMLBodyElement* body;
- WebKitDOMNodeList* list;
- WebKitDOMNode* ptr;
- gulong i, length;
-
- document = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(fixture->webView));
- g_assert(document);
- g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
- head = webkit_dom_document_get_head(document);
- g_assert(head);
- g_assert(WEBKIT_DOM_IS_HTML_HEAD_ELEMENT(head));
-
- /* Title, head's child */
- g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(head)));
- list = webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(head));
- g_assert_cmpint(webkit_dom_node_list_get_length(list), ==, 1);
- ptr = webkit_dom_node_list_item(list, 0);
- g_assert(ptr);
- g_assert(WEBKIT_DOM_IS_HTML_TITLE_ELEMENT(ptr));
- g_object_unref(list);
-
- /* Body, Head sibling */
- ptr = webkit_dom_node_get_next_sibling(WEBKIT_DOM_NODE(head));
- g_assert(ptr);
- body = WEBKIT_DOM_HTML_BODY_ELEMENT(ptr);
- g_assert(WEBKIT_DOM_IS_HTML_BODY_ELEMENT(body));
-
- /* There is no third sibling */
- ptr = webkit_dom_node_get_next_sibling(ptr);
- g_assert(ptr == NULL);
-
- /* Body's previous sibling is Head */
- ptr = webkit_dom_node_get_previous_sibling(WEBKIT_DOM_NODE(body));
- g_assert(ptr);
- g_assert(WEBKIT_DOM_IS_HTML_HEAD_ELEMENT(ptr));
-
- /* Body has 3 children */
- g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(body)));
- list = webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(body));
- length = webkit_dom_node_list_get_length(list);
- g_assert_cmpint(length, ==, 3);
-
- /* The three of them are P tags */
- for (i = 0; i < length; i++) {
- ptr = webkit_dom_node_list_item(list, i);
- g_assert(ptr);
- g_assert(WEBKIT_DOM_IS_HTML_PARAGRAPH_ELEMENT(ptr));
- }
-
- /* Go backwards */
- for (i = 0; ptr; ptr = webkit_dom_node_get_previous_sibling(ptr), i++)
- /* Nothing */;
-
- g_assert_cmpint(i, ==, 3);
- g_object_unref(list);
-}
-
-static void test_dom_node_insertion(DomNodeFixture* fixture, gconstpointer data)
-{
- WebKitDOMDocument* document;
- WebKitDOMHTMLElement* body;
- WebKitDOMElement* p, *div;
- WebKitDOMNodeList* list;
- WebKitDOMNode* node;
-
- document = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(fixture->webView));
- g_assert(document);
- body = webkit_dom_document_get_body(document);
- g_assert(body);
- g_assert(WEBKIT_DOM_IS_HTML_ELEMENT(body));
-
- /* Body shouldn't have any children at this point */
- g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(body)) == FALSE);
-
- /* Insert one P element */
- p = webkit_dom_document_create_element(document, "P", NULL);
- webkit_dom_node_append_child(WEBKIT_DOM_NODE(body), WEBKIT_DOM_NODE(p), NULL);
-
- /* Now it should have one, the same that we inserted */
- g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(body)));
- list = webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(body));
- g_assert_cmpint(webkit_dom_node_list_get_length(list), ==, 1);
- node = webkit_dom_node_list_item(list, 0);
- g_assert(node);
- g_assert(webkit_dom_node_is_same_node(WEBKIT_DOM_NODE(p), node));
- g_object_unref(list);
-
- /* Replace the P tag with a DIV tag */
- div = webkit_dom_document_create_element(document, "DIV", NULL);
- webkit_dom_node_replace_child(WEBKIT_DOM_NODE(body), WEBKIT_DOM_NODE(div), WEBKIT_DOM_NODE(p), NULL);
- g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(body)));
- list = webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(body));
- g_assert_cmpint(webkit_dom_node_list_get_length(list), ==, 1);
- node = webkit_dom_node_list_item(list, 0);
- g_assert(node);
- g_assert(webkit_dom_node_is_same_node(WEBKIT_DOM_NODE(div), node));
- g_object_unref(list);
-
- /* Now remove the tag */
- webkit_dom_node_remove_child(WEBKIT_DOM_NODE(body), node, NULL);
- list = webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(body));
- g_assert_cmpint(webkit_dom_node_list_get_length(list), ==, 0);
- g_object_unref(list);
-
- /* Test insert_before */
-
- /* If refChild is null, insert newChild as last element of parent */
- div = webkit_dom_document_create_element(document, "DIV", NULL);
- webkit_dom_node_insert_before(WEBKIT_DOM_NODE(body), WEBKIT_DOM_NODE(div), NULL, NULL);
- g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(body)));
- list = webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(body));
- g_assert_cmpint(webkit_dom_node_list_get_length(list), ==, 1);
- node = webkit_dom_node_list_item(list, 0);
- g_assert(node);
- g_assert(webkit_dom_node_is_same_node(WEBKIT_DOM_NODE(div), node));
- g_object_unref(list);
-
- /* Now insert a 'p' before 'div' */
- p = webkit_dom_document_create_element(document, "P", NULL);
- webkit_dom_node_insert_before(WEBKIT_DOM_NODE(body), WEBKIT_DOM_NODE(p), WEBKIT_DOM_NODE(div), NULL);
- g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(body)));
- list = webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(body));
- g_assert_cmpint(webkit_dom_node_list_get_length(list), ==, 2);
- node = webkit_dom_node_list_item(list, 0);
- g_assert(node);
- g_assert(webkit_dom_node_is_same_node(WEBKIT_DOM_NODE(p), node));
- node = webkit_dom_node_list_item(list, 1);
- g_assert(node);
- g_assert(webkit_dom_node_is_same_node(WEBKIT_DOM_NODE(div), node));
- g_object_unref(list);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
-
- g_test_add("/webkit/domnode/test_hierarchy_navigation",
- DomNodeFixture, HTML_DOCUMENT_HIERARCHY_NAVIGATION,
- dom_node_fixture_setup,
- test_dom_node_hierarchy_navigation,
- dom_node_fixture_teardown);
-
- g_test_add("/webkit/domnode/test_insertion",
- DomNodeFixture, HTML_DOCUMENT_NODE_INSERTION,
- dom_node_fixture_setup,
- test_dom_node_insertion,
- dom_node_fixture_teardown);
-
- return g_test_run();
-}
-
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testdownload.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testdownload.c
deleted file mode 100644
index e34d63230..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testdownload.c
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright (C) 2009 Christian Dywan <christian@twotoasts.de>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2,1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <errno.h>
-#include <unistd.h>
-#include <glib/gstdio.h>
-#include <webkit/webkit.h>
-
-GMainLoop* loop;
-char* temporaryFilename = NULL;
-WebKitDownload* theDownload = NULL;
-
-static void
-test_webkit_download_create(void)
-{
- WebKitNetworkRequest* request;
- WebKitDownload* download;
- const gchar* uri = "http://example.com";
- gchar* tmpDir;
-
- request = webkit_network_request_new(uri);
- download = webkit_download_new(request);
- g_object_unref(request);
- g_assert_cmpstr(webkit_download_get_uri(download), ==, uri);
- g_assert(webkit_download_get_network_request(download) == request);
- g_assert(g_strrstr(uri, webkit_download_get_suggested_filename(download)));
- g_assert(webkit_download_get_status(download) == WEBKIT_DOWNLOAD_STATUS_CREATED);
- g_assert(!webkit_download_get_total_size(download));
- g_assert(!webkit_download_get_current_size(download));
- g_assert(!webkit_download_get_progress(download));
- g_assert(!webkit_download_get_elapsed_time(download));
- tmpDir = g_filename_to_uri(g_get_tmp_dir(), NULL, NULL);
- webkit_download_set_destination_uri(download, tmpDir);
- g_assert_cmpstr(tmpDir, ==, webkit_download_get_destination_uri(download));;
- g_free(tmpDir);
- g_object_unref(download);
-}
-
-static gboolean
-navigation_policy_decision_requested_cb(WebKitWebView* web_view,
- WebKitWebFrame* web_frame,
- WebKitNetworkRequest* request,
- WebKitWebNavigationAction* action,
- WebKitWebPolicyDecision* decision,
- gpointer data)
-{
- webkit_web_policy_decision_download(decision);
- return TRUE;
-}
-
-static void
-notify_status_cb(GObject* object, GParamSpec* pspec, gpointer data)
-{
- WebKitDownload* download = WEBKIT_DOWNLOAD(object);
- switch (webkit_download_get_status(download)) {
- case WEBKIT_DOWNLOAD_STATUS_FINISHED:
- case WEBKIT_DOWNLOAD_STATUS_ERROR:
- g_main_loop_quit(loop);
- break;
- case WEBKIT_DOWNLOAD_STATUS_CANCELLED:
- g_assert_not_reached();
- break;
- default:
- break;
- }
-}
-
-static gboolean
-set_filename(gchar* filename)
-{
- gchar *uri = g_filename_to_uri(filename, NULL, NULL);
-
- webkit_download_set_destination_uri(theDownload, uri);
- g_free(uri);
-
- webkit_download_start(theDownload);
- return FALSE;
-}
-
-static void
-handle_download_requested_cb(WebKitDownload* download,
- gboolean* beenThere,
- gboolean asynch)
-{
- theDownload = download;
- *beenThere = TRUE;
-
- if (temporaryFilename) {
- if (asynch) {
- g_idle_add((GSourceFunc)set_filename, temporaryFilename);
- } else {
- gchar *uri = g_filename_to_uri(temporaryFilename, NULL, NULL);
- if (uri)
- webkit_download_set_destination_uri(download, uri);
- g_free(uri);
- }
- }
-
- g_signal_connect(download, "notify::status",
- G_CALLBACK(notify_status_cb), NULL);
-}
-
-static gboolean
-download_requested_cb(WebKitWebView* web_view,
- WebKitDownload* download,
- gboolean* beenThere)
-{
- handle_download_requested_cb(download, beenThere, FALSE);
- return TRUE;
-}
-
-static gboolean
-download_requested_asynch_cb(WebKitWebView* web_view,
- WebKitDownload* download,
- gboolean* beenThere)
-{
- handle_download_requested_cb(download, beenThere, TRUE);
- return TRUE;
-}
-
-static void
-test_webkit_download_perform(gboolean asynch)
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- GCallback downloadRequestCallback = NULL;
-
- g_object_ref_sink(G_OBJECT(webView));
-
- g_signal_connect(webView, "navigation-policy-decision-requested",
- G_CALLBACK(navigation_policy_decision_requested_cb),
- NULL);
-
- if (asynch)
- downloadRequestCallback = G_CALLBACK(download_requested_asynch_cb);
- else
- downloadRequestCallback = G_CALLBACK(download_requested_cb);
-
- gboolean beenThere = FALSE;
- g_signal_connect(webView, "download-requested",
- downloadRequestCallback, &beenThere);
-
- /* Preparation; FIXME: we should move this code to a test
- * utilities file, because we have a very similar one in
- * testwebframe.c */
- GError *error = NULL;
- gchar* filename;
- int fd = g_file_open_tmp("webkit-testwebdownload-XXXXXX", &filename, &error);
- close(fd);
-
- if (error)
- g_critical("Failed to open a temporary file for writing: %s.", error->message);
-
- if (g_unlink(filename) == -1)
- g_critical("Failed to delete the temporary file: %s.", g_strerror(errno));
-
- theDownload = NULL;
- temporaryFilename = filename;
-
- loop = g_main_loop_new(NULL, TRUE);
- webkit_web_view_load_uri(webView, "http://gnome.org/");
- g_main_loop_run(loop);
-
- g_assert_cmpint(beenThere, ==, TRUE);
-
- g_assert_cmpint(g_file_test(temporaryFilename, G_FILE_TEST_IS_REGULAR), ==, TRUE);
-
- g_unlink(temporaryFilename);
- g_free(temporaryFilename);
- temporaryFilename = NULL;
-
- g_main_loop_unref(loop);
- g_object_unref(webView);
-}
-
-static void
-test_webkit_download_synch(void)
-{
- test_webkit_download_perform(FALSE);
-}
-
-static void
-test_webkit_download_asynch(void)
-{
- test_webkit_download_perform(TRUE);
-}
-
-static gboolean mime_type_policy_decision_requested_cb(WebKitWebView* view, WebKitWebFrame* frame,
- WebKitNetworkRequest* request, const char* mime_type,
- WebKitWebPolicyDecision* decision, gpointer data)
-{
- webkit_web_policy_decision_download(decision);
- return TRUE;
-}
-
-static void idle_quit_loop_cb(WebKitWebView* web_view, GParamSpec* pspec, gpointer data)
-{
- if (webkit_web_view_get_load_status(web_view) == WEBKIT_LOAD_FINISHED ||
- webkit_web_view_get_load_status(web_view) == WEBKIT_LOAD_FAILED)
- g_main_loop_quit(loop);
-}
-
-static void
-test_webkit_download_data(void)
-{
- gboolean beenThere = FALSE;
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
-
- g_signal_connect(webView, "download-requested",
- G_CALLBACK(download_requested_cb),
- &beenThere);
-
- g_signal_connect(webView, "notify::load-status",
- G_CALLBACK(idle_quit_loop_cb),
- NULL);
-
- g_signal_connect(webView, "mime-type-policy-decision-requested",
- G_CALLBACK(mime_type_policy_decision_requested_cb),
- NULL);
-
- loop = g_main_loop_new(NULL, TRUE);
-
- /* We're testing for a crash, so just not crashing is a pass */
- webkit_web_view_load_uri(webView, "data:application/octect-stream,");
- g_main_loop_run(loop);
-
- g_assert_cmpint(beenThere, ==, TRUE);
-
- g_main_loop_unref(loop);
- g_object_unref(webView);
-}
-
-static void notifyDownloadStatusCallback(GObject *object, GParamSpec *pspec, gpointer data)
-{
- WebKitDownload *download = WEBKIT_DOWNLOAD(object);
- WebKitNetworkResponse *response = webkit_download_get_network_response(download);
- SoupMessage *message = webkit_network_response_get_message(response);
-
- switch (webkit_download_get_status(download)) {
- case WEBKIT_DOWNLOAD_STATUS_ERROR:
- g_assert_cmpint(message->status_code, ==, 404);
- g_main_loop_quit(loop);
- break;
- case WEBKIT_DOWNLOAD_STATUS_FINISHED:
- case WEBKIT_DOWNLOAD_STATUS_CANCELLED:
- g_assert_not_reached();
- break;
- default:
- break;
- }
-}
-
-static void serverCallback(SoupServer *server, SoupMessage *message, const char *path, GHashTable *query, SoupClientContext *context, gpointer userData)
-{
- if (message->method != SOUP_METHOD_GET) {
- soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED);
- return;
- }
-
- soup_message_set_status(message, SOUP_STATUS_NOT_FOUND);
- soup_message_body_complete(message->response_body);
-}
-
-static void test_webkit_download_not_found(void)
-{
- SoupServer *server = soup_server_new(SOUP_SERVER_PORT, 0, NULL);
- soup_server_run_async(server);
- soup_server_add_handler(server, NULL, serverCallback, NULL, NULL);
- SoupURI *baseURI = soup_uri_new("http://127.0.0.1/");
- soup_uri_set_port(baseURI, soup_server_get_port(server));
-
- SoupURI *uri = soup_uri_new_with_base(baseURI, "/foo");
- char *uriString = soup_uri_to_string(uri, FALSE);
- soup_uri_free(uri);
-
- loop = g_main_loop_new(NULL, TRUE);
- WebKitNetworkRequest *request = webkit_network_request_new(uriString);
- g_free (uriString);
- WebKitDownload *download = webkit_download_new(request);
- g_object_unref(request);
-
- webkit_download_set_destination_uri(download, "file:///tmp/foo");
- g_signal_connect(download, "notify::status", G_CALLBACK(notifyDownloadStatusCallback), NULL);
-
- webkit_download_start(download);
- g_main_loop_run(loop);
-
- g_object_unref(download);
- g_main_loop_unref(loop);
- soup_uri_free(baseURI);
- g_object_unref(server);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- // Get rid of runtime warnings about deprecated properties and signals, since they break the tests.
- g_setenv("G_ENABLE_DIAGNOSTIC", "0", TRUE);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/download/create", test_webkit_download_create);
- g_test_add_func("/webkit/download/synch", test_webkit_download_synch);
- g_test_add_func("/webkit/download/asynch", test_webkit_download_asynch);
- g_test_add_func("/webkit/download/data", test_webkit_download_data);
- g_test_add_func("/webkit/download/not-found", test_webkit_download_not_found);
- return g_test_run ();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testfavicondatabase.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testfavicondatabase.c
deleted file mode 100644
index 393732b85..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testfavicondatabase.c
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (C) 2012 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "test_utils.h"
-#include <glib/gstdio.h>
-#include <gtk/gtk.h>
-#include <string.h>
-#include <webkit/webkit.h>
-
-const int gIconSize = 16;
-
-GMainLoop *loop;
-char *baseURI;
-
-static void
-serverCallback(SoupServer *server, SoupMessage *message, const char *path, GHashTable *query, SoupClientContext *context, void *data)
-{
- if (message->method != SOUP_METHOD_GET) {
- soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED);
- return;
- }
-
- soup_message_set_status(message, SOUP_STATUS_OK);
-
- char *contents;
- gsize length;
- if (g_str_equal(path, "/favicon.ico")) {
- GError *error = NULL;
-
- g_file_get_contents("blank.ico", &contents, &length, &error);
- g_assert(!error);
- } else {
- contents = g_strdup("<html><body>test</body></html>");
- length = strlen(contents);
- }
-
- soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, contents, length);
- soup_message_body_complete(message->response_body);
-}
-
-static void deleteDatabaseFileIfExists(const char *databasePath)
-{
- if (!g_file_test(databasePath, G_FILE_TEST_IS_DIR))
- return;
-
- char *databaseFilename = g_build_filename(databasePath, "WebpageIcons.db", NULL);
- if (g_unlink(databaseFilename) == -1) {
- g_free(databaseFilename);
- return;
- }
-
- g_free(databaseFilename);
- g_rmdir(databasePath);
-}
-
-static void testWebKitFaviconDatabaseSetPath()
-{
- char *databasePath = g_build_filename(g_get_tmp_dir(), "webkit-testfavicondatabase", NULL);
- deleteDatabaseFileIfExists(databasePath);
-
- WebKitFaviconDatabase *database = webkit_get_favicon_database();
- webkit_favicon_database_set_path(database, databasePath);
-
- g_assert_cmpstr(databasePath, ==, webkit_favicon_database_get_path(database));
-
- g_free(databasePath);
-}
-
-// See the comment in main() function that goes with this same guard.
-#ifdef NDEBUG
-
-static void faviconDatabaseGetValidFaviconCallback(GObject *sourceObject, GAsyncResult *result, void *userData)
-{
- gboolean *beenHere = (gboolean*)userData;
- GError *error = NULL;
- GdkPixbuf *icon = webkit_favicon_database_get_favicon_pixbuf_finish(WEBKIT_FAVICON_DATABASE(sourceObject), result, &error);
- g_assert(icon);
- g_object_unref(icon);
-
- *beenHere = TRUE;
-
- g_main_loop_quit(loop);
-}
-
-static void faviconDatabaseGetInvalidFaviconCallback(GObject *sourceObject, GAsyncResult *result, void *userData)
-{
- gboolean *beenHere = (gboolean*)userData;
- GError *error = NULL;
- GdkPixbuf *icon = webkit_favicon_database_get_favicon_pixbuf_finish(WEBKIT_FAVICON_DATABASE(sourceObject), result, &error);
- g_assert(!icon);
-
- *beenHere = TRUE;
-
- g_main_loop_quit(loop);
-}
-
-static void faviconDatabaseGetFaviconCancelledCallback(GObject *sourceObject, GAsyncResult *result, void *userData)
-{
- gboolean *beenHere = (gboolean*)userData;
- GError *error = NULL;
- GdkPixbuf *icon = webkit_favicon_database_get_favicon_pixbuf_finish(WEBKIT_FAVICON_DATABASE(sourceObject), result, &error);
- g_assert(!icon);
- g_assert(error && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED));
-
- *beenHere = TRUE;
-
- g_main_loop_quit(loop);
-}
-
-static inline void quitMainLoopIfLoadCompleted(gboolean *iconOrPageLoaded)
-{
- if (*iconOrPageLoaded)
- g_main_loop_quit(loop);
- else
- *iconOrPageLoaded = TRUE;
-}
-
-static void idleQuitLoopCallback(WebKitWebView *webView, GParamSpec *paramSpec, gboolean *iconOrPageLoaded)
-{
- WebKitLoadStatus status = webkit_web_view_get_load_status(webView);
-
- if (status == WEBKIT_LOAD_FINISHED || status == WEBKIT_LOAD_FAILED)
- quitMainLoopIfLoadCompleted(iconOrPageLoaded);
-}
-
-static void webkitWebViewIconLoaded(WebKitFaviconDatabase *database, const char *frameURI, gboolean *iconOrPageLoaded)
-{
- quitMainLoopIfLoadCompleted(iconOrPageLoaded);
-}
-
-static void loadURI(const char *uri)
-{
- WebKitWebView *view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- gboolean iconOrPageLoaded = FALSE;
-
- webkit_web_view_load_uri(view, uri);
-
- g_signal_connect(view, "notify::load-status", G_CALLBACK(idleQuitLoopCallback), &iconOrPageLoaded);
- g_signal_connect(view, "icon-loaded", G_CALLBACK(webkitWebViewIconLoaded), &iconOrPageLoaded);
-
- g_main_loop_run(loop);
-
- g_signal_handlers_disconnect_matched(view, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, &iconOrPageLoaded);
-}
-
-static gboolean faviconDatabaseGetValidFaviconIdle(void *userData)
-{
- webkit_favicon_database_get_favicon_pixbuf(webkit_get_favicon_database(), baseURI,
- gIconSize, gIconSize, NULL,
- faviconDatabaseGetValidFaviconCallback, userData);
- return FALSE;
-}
-
-static gboolean faviconDatabaseGetInvalidFaviconIdle(void *userData)
-{
- webkit_favicon_database_get_favicon_pixbuf(webkit_get_favicon_database(), "http://www.webkitgtk.org/",
- gIconSize, gIconSize, NULL,
- faviconDatabaseGetInvalidFaviconCallback, userData);
- return FALSE;
-}
-
-static gboolean faviconDatabaseGetFaviconCancelledIdle(void *userData)
-{
- GCancellable *cancellable = g_cancellable_new();
- webkit_favicon_database_get_favicon_pixbuf(webkit_get_favicon_database(), baseURI,
- gIconSize, gIconSize, cancellable,
- faviconDatabaseGetFaviconCancelledCallback, userData);
- g_cancellable_cancel(cancellable);
- g_object_unref(cancellable);
- return FALSE;
-}
-
-static void testWebKitFaviconDatabaseGetFavicon()
-{
- gboolean beenToIconCallback;
-
- loop = g_main_loop_new(NULL, TRUE);
-
- /* Load uri to make sure favicon is added to database. */
- loadURI(baseURI);
-
- beenToIconCallback = FALSE;
- g_idle_add((GSourceFunc)faviconDatabaseGetValidFaviconIdle, &beenToIconCallback);
- g_main_loop_run(loop);
- g_assert(beenToIconCallback);
-
- beenToIconCallback = FALSE;
- g_idle_add((GSourceFunc)faviconDatabaseGetInvalidFaviconIdle, &beenToIconCallback);
- g_main_loop_run(loop);
- g_assert(beenToIconCallback);
-
- beenToIconCallback = FALSE;
- g_idle_add((GSourceFunc)faviconDatabaseGetFaviconCancelledIdle, &beenToIconCallback);
- g_main_loop_run(loop);
- g_assert(beenToIconCallback);
-}
-
-static void testWebKitFaviconDatabaseGetFaviconURI()
-{
- char *iconURI = webkit_favicon_database_get_favicon_uri(webkit_get_favicon_database(), baseURI);
- char *expectedURI = g_strdup_printf("%sfavicon.ico", baseURI);
- g_assert_cmpstr(iconURI, ==, expectedURI);
- g_free(expectedURI);
- g_free(iconURI);
-}
-
-#endif
-
-static void testWebKitFaviconDatabaseRemoveAll(void)
-{
- WebKitFaviconDatabase *database = webkit_get_favicon_database();
- webkit_favicon_database_clear(database);
- char *iconURI = webkit_favicon_database_get_favicon_uri(database, baseURI);
- g_assert(!iconURI);
- g_free(iconURI);
-}
-
-static void testWebKitFaviconDatabaseCloseDatabase(void)
-{
- WebKitFaviconDatabase *database = webkit_get_favicon_database();
- char *databasePath = g_strdup(webkit_favicon_database_get_path(database));
- webkit_favicon_database_set_path(database, 0);
- deleteDatabaseFileIfExists(databasePath);
- g_free(databasePath);
-}
-
-int main(int argc, char **argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- // Get rid of runtime warnings about deprecated properties and signals, since they break the tests.
- g_setenv("G_ENABLE_DIAGNOSTIC", "0", TRUE);
-
- /* This hopefully makes the test independent of the path it's called from. */
- testutils_relative_chdir("Tools/TestWebKitAPI/Tests/WebKitGtk/resources/test.html", argv[0]);
-
- SoupServer *server = soup_server_new(SOUP_SERVER_PORT, 0, NULL);
- soup_server_run_async(server);
-
- soup_server_add_handler(server, NULL, serverCallback, NULL, NULL);
-
- SoupURI *soupURI = soup_uri_new("http://127.0.0.1/");
- soup_uri_set_port(soupURI, soup_server_get_port(server));
-
- baseURI = soup_uri_to_string(soupURI, FALSE);
- soup_uri_free(soupURI);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/favicondatabase/set-path", testWebKitFaviconDatabaseSetPath);
-
- // These two tests will trigger an ASSERTION on debug builds due
- // to http://webkit.org/b/67582. Remove the guards once the bug is fixed.
-#ifdef NDEBUG
- g_test_add_func("/webkit/favicondatabase/get-favicon", testWebKitFaviconDatabaseGetFavicon);
- g_test_add_func("/webkit/favicondatabase/get-favicon-uri", testWebKitFaviconDatabaseGetFaviconURI);
-#endif
-
- g_test_add_func("/webkit/favicondatabase/remove-all", testWebKitFaviconDatabaseRemoveAll);
- g_test_add_func("/webkit/favicondatabase/close-db", testWebKitFaviconDatabaseCloseDatabase);
-
- return g_test_run();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testglobals.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testglobals.c
deleted file mode 100644
index 4b9ec4fcf..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testglobals.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2010 Collabora Ltd.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <gtk/gtk.h>
-#include <libsoup/soup.h>
-#include <webkit/webkit.h>
-
-// Make sure the session is initialized properly when webkit_get_default_session() is called.
-static void test_globals_default_session()
-{
- g_test_bug("36754");
-
- SoupSession* session = webkit_get_default_session();
- soup_session_remove_feature_by_type(session, WEBKIT_TYPE_SOUP_AUTH_DIALOG);
-
- // This makes sure our initialization ran.
- g_assert(soup_session_get_feature(session, SOUP_TYPE_CONTENT_DECODER) != NULL);
-
- // Creating a WebView should make sure the session is
- // initialized, and not mess with our changes.
- WebKitWebView* web_view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(web_view);
- g_object_unref(web_view);
-
- // These makes sure our modification was kept.
- g_assert(soup_session_get_feature(session, SOUP_TYPE_CONTENT_DECODER) != NULL);
- g_assert(soup_session_get_feature(session, WEBKIT_TYPE_SOUP_AUTH_DIALOG) == NULL);
-}
-
-static void test_globals_security_policy()
-{
- // Check default policy for well known schemes.
- WebKitSecurityPolicy policy = webkit_get_security_policy_for_uri_scheme("http");
- guint mask = WEBKIT_SECURITY_POLICY_CORS_ENABLED;
- g_assert_cmpuint(policy & mask, ==, mask);
-
- policy = webkit_get_security_policy_for_uri_scheme("https");
- mask = WEBKIT_SECURITY_POLICY_SECURE | WEBKIT_SECURITY_POLICY_CORS_ENABLED;
- g_assert_cmpuint(policy & mask, ==, mask);
-
- policy = webkit_get_security_policy_for_uri_scheme("file");
- mask = WEBKIT_SECURITY_POLICY_LOCAL;
- g_assert_cmpuint(policy & mask, ==, mask);
-
- policy = webkit_get_security_policy_for_uri_scheme("data");
- mask = WEBKIT_SECURITY_POLICY_NO_ACCESS_TO_OTHER_SCHEME | WEBKIT_SECURITY_POLICY_SECURE;
- g_assert_cmpuint(policy & mask, ==, mask);
-
- policy = webkit_get_security_policy_for_uri_scheme("about");
- mask = WEBKIT_SECURITY_POLICY_NO_ACCESS_TO_OTHER_SCHEME | WEBKIT_SECURITY_POLICY_SECURE | WEBKIT_SECURITY_POLICY_EMPTY_DOCUMENT;
- g_assert_cmpuint(policy & mask, ==, mask);
-
- // Custom scheme.
- policy = webkit_get_security_policy_for_uri_scheme("foo");
- g_assert(!policy);
-
- policy |= WEBKIT_SECURITY_POLICY_LOCAL;
- webkit_set_security_policy_for_uri_scheme("foo", policy);
- g_assert_cmpuint(webkit_get_security_policy_for_uri_scheme("foo"), ==, policy);
-
- policy |= WEBKIT_SECURITY_POLICY_NO_ACCESS_TO_OTHER_SCHEME;
- webkit_set_security_policy_for_uri_scheme("foo", policy);
- g_assert_cmpuint(webkit_get_security_policy_for_uri_scheme("foo"), ==, policy);
-
- policy |= WEBKIT_SECURITY_POLICY_DISPLAY_ISOLATED;
- webkit_set_security_policy_for_uri_scheme("foo", policy);
- g_assert_cmpuint(webkit_get_security_policy_for_uri_scheme("foo"), ==, policy);
-
- policy |= WEBKIT_SECURITY_POLICY_SECURE;
- webkit_set_security_policy_for_uri_scheme("foo", policy);
- g_assert_cmpuint(webkit_get_security_policy_for_uri_scheme("foo"), ==, policy);
-
- policy |= WEBKIT_SECURITY_POLICY_CORS_ENABLED;
- webkit_set_security_policy_for_uri_scheme("foo", policy);
- g_assert_cmpuint(webkit_get_security_policy_for_uri_scheme("foo"), ==, policy);
-
- policy |= WEBKIT_SECURITY_POLICY_EMPTY_DOCUMENT;
- webkit_set_security_policy_for_uri_scheme("foo", policy);
- g_assert_cmpuint(webkit_get_security_policy_for_uri_scheme("foo"), ==, policy);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/globals/default_session",
- test_globals_default_session);
- g_test_add_func("/webkit/globals/security-policy",
- test_globals_security_policy);
- return g_test_run();
-}
-
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testhittestresult.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testhittestresult.c
deleted file mode 100644
index eac34c47b..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testhittestresult.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2009 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2,1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <errno.h>
-#include <unistd.h>
-#include <glib/gstdio.h>
-#include <webkit/webkit.h>
-
-typedef struct {
- char* data;
- guint flag;
-} TestInfo;
-
-static GMainLoop* loop;
-
-typedef struct {
- WebKitWebView* webView;
- TestInfo* info;
-} HitTestResultFixture;
-
-TestInfo*
-test_info_new(const char* data, guint flag)
-{
- TestInfo* info;
-
- info = g_slice_new(TestInfo);
- info->data = g_strdup(data);
- info->flag = flag;
-
- return info;
-}
-
-void
-test_info_destroy(TestInfo* info)
-{
- g_free(info->data);
- g_slice_free(TestInfo, info);
-}
-
-static void hit_test_result_fixture_setup(HitTestResultFixture* fixture, gconstpointer data)
-{
- fixture->webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(fixture->webView);
- loop = g_main_loop_new(NULL, TRUE);
- fixture->info = (TestInfo*)data;
-}
-
-static void hit_test_result_fixture_teardown(HitTestResultFixture* fixture, gconstpointer data)
-{
- g_object_unref(fixture->webView);
- g_main_loop_unref(loop);
- test_info_destroy(fixture->info);
-}
-
-static void
-load_status_cb(WebKitWebView* webView,
- GParamSpec* spec,
- gpointer data)
-{
- WebKitLoadStatus status = webkit_web_view_get_load_status(webView);
- TestInfo* info = (TestInfo*)data;
-
- if (status == WEBKIT_LOAD_FINISHED) {
- WebKitHitTestResult* result;
- guint context;
- GdkEvent* event = gdk_event_new(GDK_BUTTON_PRESS);
- WebKitDOMNode* node;
- gint x, y;
-
- /* Close enough to 0,0 */
- event->button.x = 5;
- event->button.y = 5;
-
- result = webkit_web_view_get_hit_test_result(webView, (GdkEventButton*) event);
- gdk_event_free(event);
- g_assert(result);
-
- g_object_get(result, "context", &context, NULL);
- g_assert(context & info->flag);
-
- g_object_get(result, "inner-node", &node, NULL);
- g_assert(node);
- g_assert(WEBKIT_DOM_IS_NODE(node));
-
- g_object_get(result, "x", &x, "y", &y, NULL);
- g_assert_cmpint(x, ==, 5);
- g_assert_cmpint(y, ==, 5);
-
- /* We can only test these node types at the moment. In the
- * input case there seems to be an extra layer with a DIV on
- * top of the input, which gets assigned to the inner-node.
- * tag */
- if (info->flag == WEBKIT_HIT_TEST_RESULT_CONTEXT_DOCUMENT)
- g_assert(WEBKIT_DOM_IS_HTML_HTML_ELEMENT(node));
- else if (info->flag == WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE)
- g_assert(WEBKIT_DOM_IS_HTML_IMAGE_ELEMENT(node));
- else if (info->flag == WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK) {
- /* The hit test will give us the inner text node, we want
- * the A tag */
- WebKitDOMNode* parent = webkit_dom_node_get_parent_node(node);
- g_assert(WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT(parent));
- }
-
- g_object_unref(result);
- g_main_loop_quit(loop);
- }
-}
-
-static void
-test_webkit_hit_test_result(HitTestResultFixture* fixture, gconstpointer data)
-{
- TestInfo* info = (TestInfo*)data;
- GtkAllocation allocation = { 0, 0, 50, 50 };
-
- webkit_web_view_load_string(fixture->webView,
- info->data,
- "text/html",
- "utf-8",
- "file://");
- gtk_widget_size_allocate(GTK_WIDGET(fixture->webView), &allocation);
- g_signal_connect(fixture->webView, "notify::load-status", G_CALLBACK(load_status_cb), info);
- g_main_loop_run(loop);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
- // Get rid of runtime warnings about deprecated properties and signals, since they break the tests.
- g_setenv("G_ENABLE_DIAGNOSTIC", "0", TRUE);
-
- g_test_bug_base("https://bugs.webkit.org/");
-
- g_test_add("/webkit/hittestresult/document", HitTestResultFixture,
- test_info_new("<html><body><h1>WebKitGTK+!</h1></body></html>",
- WEBKIT_HIT_TEST_RESULT_CONTEXT_DOCUMENT),
- hit_test_result_fixture_setup, test_webkit_hit_test_result, hit_test_result_fixture_teardown);
- /* We hardcode all elements to be at 0,0 so that we know where to
- * generate the button events */
- g_test_add("/webkit/hittestresult/image", HitTestResultFixture,
- test_info_new("<html><body><img style='position:absolute; left:0; top:0'src='0xdeadbeef' width=50 height=50></img></body></html>",
- WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE),
- hit_test_result_fixture_setup, test_webkit_hit_test_result, hit_test_result_fixture_teardown);
- g_test_add("/webkit/hittestresult/editable", HitTestResultFixture,
- test_info_new("<html><body><input style='position:absolute; left:0; top:0' size='35'></input>></body></html>",
- WEBKIT_HIT_TEST_RESULT_CONTEXT_EDITABLE),
- hit_test_result_fixture_setup, test_webkit_hit_test_result, hit_test_result_fixture_teardown);
- g_test_add("/webkit/hittestresult/link", HitTestResultFixture,
- test_info_new("<html><body><a style='position:absolute; left:0; top:0' href='http://www.example.com'>HELLO WORLD</a></body></html>",
- WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK),
- hit_test_result_fixture_setup, test_webkit_hit_test_result, hit_test_result_fixture_teardown);
-
- return g_test_run ();
-}
-
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testhttpbackend.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testhttpbackend.c
deleted file mode 100644
index 93776879b..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testhttpbackend.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2009 Gustavo Noronha Silva
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <errno.h>
-#include <unistd.h>
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-// Not yet public API
-SoupMessage* webkit_network_request_get_message(WebKitNetworkRequest* request);
-
-static gboolean navigation_policy_decision_requested_cb(WebKitWebView* web_view,
- WebKitWebFrame* web_frame,
- WebKitNetworkRequest* request,
- WebKitWebNavigationAction* action,
- WebKitWebPolicyDecision* decision,
- gpointer data)
-{
- SoupMessage* message = webkit_network_request_get_message(request);
-
- /* 1 -> webkit_network_request_with_core_request
- *
- * The SoupMessage is created exclusively for the emission of this
- * signal.
- */
- g_assert_cmpint(G_OBJECT(message)->ref_count, ==, 1);
-
- return FALSE;
-}
-
-static void test_soup_message_lifetime()
-{
- WebKitWebView* web_view = WEBKIT_WEB_VIEW(webkit_web_view_new());
-
- g_object_ref_sink(web_view);
-
- g_signal_connect(web_view, "navigation-policy-decision-requested",
- G_CALLBACK(navigation_policy_decision_requested_cb),
- NULL);
-
- /* load_uri will trigger the navigation-policy-decision-requested
- * signal emission;
- */
- webkit_web_view_load_uri(web_view, "http://127.0.0.1/");
-
- g_object_unref(web_view);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/soupmessage/lifetime", test_soup_message_lifetime);
- return g_test_run ();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testkeyevents.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testkeyevents.c
deleted file mode 100644
index acd01f35f..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testkeyevents.c
+++ /dev/null
@@ -1,390 +0,0 @@
-/*
- * Copyright (C) 2009, 2010 Martin Robinson <mrobinson@webkit.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2,1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <glib/gstdio.h>
-#include <webkit/webkit.h>
-#include <JavaScriptCore/JSStringRef.h>
-#include <JavaScriptCore/JSContextRef.h>
-
-typedef struct {
- char* page;
- char* text;
- gboolean shouldBeHandled;
-} TestInfo;
-
-typedef struct {
- GtkWidget* window;
- WebKitWebView* webView;
- GMainLoop* loop;
- TestInfo* info;
-} KeyEventFixture;
-
-TestInfo*
-test_info_new(const char* page, gboolean shouldBeHandled)
-{
- TestInfo* info;
-
- info = g_slice_new(TestInfo);
- info->page = g_strdup(page);
- info->shouldBeHandled = shouldBeHandled;
- info->text = 0;
-
- return info;
-}
-
-void
-test_info_destroy(TestInfo* info)
-{
- g_free(info->page);
- g_free(info->text);
- g_slice_free(TestInfo, info);
-}
-
-static void key_event_fixture_setup(KeyEventFixture* fixture, gconstpointer data)
-{
- fixture->loop = g_main_loop_new(NULL, TRUE);
-
- fixture->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- fixture->webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
-
- gtk_container_add(GTK_CONTAINER(fixture->window), GTK_WIDGET(fixture->webView));
-}
-
-static void key_event_fixture_teardown(KeyEventFixture* fixture, gconstpointer data)
-{
- gtk_widget_destroy(fixture->window);
- g_main_loop_unref(fixture->loop);
- test_info_destroy(fixture->info);
-}
-
-static gboolean key_press_event_cb(WebKitWebView* webView, GdkEvent* event, gpointer data)
-{
- KeyEventFixture* fixture = (KeyEventFixture*)data;
- gboolean handled = GTK_WIDGET_GET_CLASS(fixture->webView)->key_press_event(GTK_WIDGET(fixture->webView), &event->key);
- g_assert_cmpint(handled, ==, fixture->info->shouldBeHandled);
-
- return FALSE;
-}
-
-static gboolean key_release_event_cb(WebKitWebView* webView, GdkEvent* event, gpointer data)
-{
- // WebCore never seems to mark keyup events as handled.
- KeyEventFixture* fixture = (KeyEventFixture*)data;
- gboolean handled = GTK_WIDGET_GET_CLASS(fixture->webView)->key_press_event(GTK_WIDGET(fixture->webView), &event->key);
- g_assert(!handled);
-
- g_main_loop_quit(fixture->loop);
-
- return FALSE;
-}
-
-static void test_keypress_events_load_status_cb(WebKitWebView* webView, GParamSpec* spec, gpointer data)
-{
- KeyEventFixture* fixture = (KeyEventFixture*)data;
- WebKitLoadStatus status = webkit_web_view_get_load_status(webView);
- if (status == WEBKIT_LOAD_FINISHED) {
- g_signal_connect(fixture->webView, "key-press-event",
- G_CALLBACK(key_press_event_cb), fixture);
- g_signal_connect(fixture->webView, "key-release-event",
- G_CALLBACK(key_release_event_cb), fixture);
- if (!gtk_test_widget_send_key(GTK_WIDGET(fixture->webView),
- gdk_unicode_to_keyval('a'), 0))
- g_assert_not_reached();
- }
-
-}
-
-gboolean map_event_cb(GtkWidget *widget, GdkEvent* event, gpointer data)
-{
- KeyEventFixture* fixture = (KeyEventFixture*)data;
- webkit_web_view_load_string(fixture->webView, fixture->info->page,
- "text/html", "utf-8", "file://");
- return FALSE;
-}
-
-static void setup_keyevent_test(KeyEventFixture* fixture, gconstpointer data, GCallback load_event_callback)
-{
- fixture->info = (TestInfo*)data;
- g_signal_connect(fixture->window, "map-event",
- G_CALLBACK(map_event_cb), fixture);
-
- gtk_widget_grab_focus(GTK_WIDGET(fixture->webView));
- gtk_widget_show(fixture->window);
- gtk_widget_show(GTK_WIDGET(fixture->webView));
- gtk_window_present(GTK_WINDOW(fixture->window));
-
- g_signal_connect(fixture->webView, "notify::load-status",
- load_event_callback, fixture);
-
- g_main_loop_run(fixture->loop);
-}
-
-static void test_keypress_events(KeyEventFixture* fixture, gconstpointer data)
-{
- setup_keyevent_test(fixture, data, G_CALLBACK(test_keypress_events_load_status_cb));
-}
-
-static gboolean element_text_equal_to(JSContextRef context, const gchar* text)
-{
- JSStringRef scriptString = JSStringCreateWithUTF8CString(
- "window.document.getElementById(\"in\").value;");
- JSValueRef value = JSEvaluateScript(context, scriptString, 0, 0, 0, 0);
- JSStringRelease(scriptString);
-
- // If the value isn't a string, the element is probably a div
- // so grab the innerText instead.
- if (!JSValueIsString(context, value)) {
- JSStringRef scriptString = JSStringCreateWithUTF8CString(
- "window.document.getElementById(\"in\").innerText;");
- value = JSEvaluateScript(context, scriptString, 0, 0, 0, 0);
- JSStringRelease(scriptString);
- }
-
- g_assert(JSValueIsString(context, value));
- JSStringRef inputString = JSValueToStringCopy(context, value, 0);
- g_assert(inputString);
-
- gint size = JSStringGetMaximumUTF8CStringSize(inputString);
- gchar* cString = g_malloc(size);
- JSStringGetUTF8CString(inputString, cString, size);
- JSStringRelease(inputString);
-
- gboolean result = g_utf8_collate(cString, text) == 0;
- g_free(cString);
- return result;
-}
-
-static void test_ime_load_status_cb(WebKitWebView* webView, GParamSpec* spec, gpointer data)
-{
- KeyEventFixture* fixture = (KeyEventFixture*)data;
- WebKitLoadStatus status = webkit_web_view_get_load_status(webView);
- if (status != WEBKIT_LOAD_FINISHED)
- return;
-
- JSGlobalContextRef context = webkit_web_frame_get_global_context(
- webkit_web_view_get_main_frame(webView));
- g_assert(context);
-
- GtkIMContext* imContext = 0;
- g_object_get(webView, "im-context", &imContext, NULL);
- g_assert(imContext);
-
- // Test that commits that happen outside of key events
- // change the text field immediately. This closely replicates
- // the behavior of SCIM.
- g_assert(element_text_equal_to(context, ""));
- g_signal_emit_by_name(imContext, "commit", "a");
- g_assert(element_text_equal_to(context, "a"));
- g_signal_emit_by_name(imContext, "commit", "b");
- g_assert(element_text_equal_to(context, "ab"));
- g_signal_emit_by_name(imContext, "commit", "c");
- g_assert(element_text_equal_to(context, "abc"));
-
- g_object_unref(imContext);
- g_main_loop_quit(fixture->loop);
-}
-
-static void test_ime(KeyEventFixture* fixture, gconstpointer data)
-{
- setup_keyevent_test(fixture, data, G_CALLBACK(test_ime_load_status_cb));
-}
-
-static gboolean verify_contents(gpointer data)
-{
- KeyEventFixture* fixture = (KeyEventFixture*)data;
- JSGlobalContextRef context = webkit_web_frame_get_global_context(
- webkit_web_view_get_main_frame(fixture->webView));
- g_assert(context);
-
- g_assert(element_text_equal_to(context, fixture->info->text));
- g_main_loop_quit(fixture->loop);
- return FALSE;
-}
-
-static void test_blocking_load_status_cb(WebKitWebView* webView, GParamSpec* spec, gpointer data)
-{
- KeyEventFixture* fixture = (KeyEventFixture*)data;
- WebKitLoadStatus status = webkit_web_view_get_load_status(webView);
- if (status != WEBKIT_LOAD_FINISHED)
- return;
-
- // The first keypress event should not modify the field.
- fixture->info->text = g_strdup("bc");
- if (!gtk_test_widget_send_key(GTK_WIDGET(fixture->webView),
- gdk_unicode_to_keyval('a'), 0))
- g_assert_not_reached();
- if (!gtk_test_widget_send_key(GTK_WIDGET(fixture->webView),
- gdk_unicode_to_keyval('b'), 0))
- g_assert_not_reached();
- if (!gtk_test_widget_send_key(GTK_WIDGET(fixture->webView),
- gdk_unicode_to_keyval('c'), 0))
- g_assert_not_reached();
-
- g_idle_add(verify_contents, fixture);
-}
-
-static void test_blocking(KeyEventFixture* fixture, gconstpointer data)
-{
- setup_keyevent_test(fixture, data, G_CALLBACK(test_blocking_load_status_cb));
-}
-
-#if defined(GDK_WINDOWING_X11)
-static void test_xim_load_status_cb(WebKitWebView* webView, GParamSpec* spec, gpointer data)
-{
- KeyEventFixture* fixture = (KeyEventFixture*)data;
- WebKitLoadStatus status = webkit_web_view_get_load_status(webView);
- if (status != WEBKIT_LOAD_FINISHED)
- return;
-
- GtkIMContext* imContext = 0;
- g_object_get(webView, "im-context", &imContext, NULL);
- g_assert(imContext);
-
- gchar* originalId = g_strdup(gtk_im_multicontext_get_context_id(GTK_IM_MULTICONTEXT(imContext)));
- gtk_im_multicontext_set_context_id(GTK_IM_MULTICONTEXT(imContext), "xim");
-
- // Test that commits that happen outside of key events
- // change the text field immediately. This closely replicates
- // the behavior of SCIM.
- fixture->info->text = g_strdup("debian");
- if (!gtk_test_widget_send_key(GTK_WIDGET(fixture->webView),
- gdk_unicode_to_keyval('d'), 0))
- g_assert_not_reached();
- if (!gtk_test_widget_send_key(GTK_WIDGET(fixture->webView),
- gdk_unicode_to_keyval('e'), 0))
- g_assert_not_reached();
- if (!gtk_test_widget_send_key(GTK_WIDGET(fixture->webView),
- gdk_unicode_to_keyval('b'), 0))
- g_assert_not_reached();
- if (!gtk_test_widget_send_key(GTK_WIDGET(fixture->webView),
- gdk_unicode_to_keyval('i'), 0))
- g_assert_not_reached();
- if (!gtk_test_widget_send_key(GTK_WIDGET(fixture->webView),
- gdk_unicode_to_keyval('a'), 0))
- g_assert_not_reached();
- if (!gtk_test_widget_send_key(GTK_WIDGET(fixture->webView),
- gdk_unicode_to_keyval('n'), 0))
- g_assert_not_reached();
-
- gtk_im_multicontext_set_context_id(GTK_IM_MULTICONTEXT(imContext), originalId);
- g_free(originalId);
- g_object_unref(imContext);
-
- g_idle_add(verify_contents, fixture);
-}
-
-static void test_xim(KeyEventFixture* fixture, gconstpointer data)
-{
- setup_keyevent_test(fixture, data, G_CALLBACK(test_xim_load_status_cb));
-}
-#endif
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
-
-
- // We'll test input on a slew of different node types. Key events to
- // text inputs and editable divs should be marked as handled. Key events
- // to buttons and links should not.
- const char* textinput_html = "<html><body><input id=\"in\" type=\"text\">"
- "<script>document.getElementById('in').focus();</script></body></html>";
- const char* button_html = "<html><body><input id=\"in\" type=\"button\">"
- "<script>document.getElementById('in').focus();</script></body></html>";
- const char* link_html = "<html><body><a href=\"http://www.gnome.org\" id=\"in\">"
- "LINKY MCLINKERSON</a><script>document.getElementById('in').focus();</script>"
- "</body></html>";
- const char* div_html = "<html><body><div id=\"in\" contenteditable=\"true\">"
- "<script>document.getElementById('in').focus();</script></body></html>";
-
- // These are similar to the blocks above, but they should block the first
- // keypress modifying the editable node.
- const char* textinput_html_blocking = "<html><body>"
- "<input id=\"in\" type=\"text\" "
- "onkeypress=\"if (first) {event.preventDefault();first=false;}\">"
- "<script>first = true;\ndocument.getElementById('in').focus();</script>\n"
- "</script></body></html>";
- const char* div_html_blocking = "<html><body>"
- "<div id=\"in\" contenteditable=\"true\" "
- "onkeypress=\"if (first) {event.preventDefault();first=false;}\">"
- "<script>first = true; document.getElementById('in').focus();</script>\n"
- "</script></body></html>";
-
- g_test_add("/webkit/keyevents/event-textinput", KeyEventFixture,
- test_info_new(textinput_html, TRUE),
- key_event_fixture_setup,
- test_keypress_events,
- key_event_fixture_teardown);
- g_test_add("/webkit/keyevents/event-buttons", KeyEventFixture,
- test_info_new(button_html, FALSE),
- key_event_fixture_setup,
- test_keypress_events,
- key_event_fixture_teardown);
- g_test_add("/webkit/keyevents/event-link", KeyEventFixture,
- test_info_new(link_html, FALSE),
- key_event_fixture_setup,
- test_keypress_events,
- key_event_fixture_teardown);
- g_test_add("/webkit/keyevent/event-div", KeyEventFixture,
- test_info_new(div_html, TRUE),
- key_event_fixture_setup,
- test_keypress_events,
- key_event_fixture_teardown);
- g_test_add("/webkit/keyevent/ime-textinput", KeyEventFixture,
- test_info_new(textinput_html, TRUE),
- key_event_fixture_setup,
- test_ime,
- key_event_fixture_teardown);
- g_test_add("/webkit/keyevent/ime-div", KeyEventFixture,
- test_info_new(div_html, TRUE),
- key_event_fixture_setup,
- test_ime,
- key_event_fixture_teardown);
- g_test_add("/webkit/keyevent/block-textinput", KeyEventFixture,
- test_info_new(textinput_html_blocking, TRUE),
- key_event_fixture_setup,
- test_blocking,
- key_event_fixture_teardown);
- g_test_add("/webkit/keyevent/block-div", KeyEventFixture,
- test_info_new(div_html_blocking, TRUE),
- key_event_fixture_setup,
- test_blocking,
- key_event_fixture_teardown);
-#if defined(GDK_WINDOWING_X11)
- g_test_add("/webkit/keyevent/xim-textinput", KeyEventFixture,
- test_info_new(textinput_html, TRUE),
- key_event_fixture_setup,
- test_xim,
- key_event_fixture_teardown);
- g_test_add("/webkit/keyevent/xim-div", KeyEventFixture,
- test_info_new(div_html, TRUE),
- key_event_fixture_setup,
- test_xim,
- key_event_fixture_teardown);
-#endif
-
- return g_test_run();
-}
-
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testloading.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testloading.c
deleted file mode 100644
index 95246ec28..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testloading.c
+++ /dev/null
@@ -1,437 +0,0 @@
-/*
- * Copyright (C) 2009, 2010 Gustavo Noronha Silva
- * Copyright (C) 2009 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <gtk/gtk.h>
-#include <libsoup/soup.h>
-#include <string.h>
-#include <webkit/webkit.h>
-
-/* This string has to be rather big because of the cancelled test - it
- * looks like soup refuses to send or receive a too small chunk */
-#define HTML_STRING "<html><body>Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!</body></html>"
-
-SoupURI* base_uri;
-
-/* For real request testing */
-static void
-server_callback(SoupServer* server, SoupMessage* msg,
- const char* path, GHashTable* query,
- SoupClientContext* context, gpointer data)
-{
- if (msg->method != SOUP_METHOD_GET) {
- soup_message_set_status(msg, SOUP_STATUS_NOT_IMPLEMENTED);
- return;
- }
-
- soup_message_set_status(msg, SOUP_STATUS_OK);
-
- if (g_str_equal(path, "/test_loading_status") || g_str_equal(path, "/test_loading_status2"))
- soup_message_body_append(msg->response_body, SOUP_MEMORY_STATIC, HTML_STRING, strlen(HTML_STRING));
- else if (g_str_equal(path, "/test_load_error")) {
- soup_message_set_status(msg, SOUP_STATUS_CANT_CONNECT);
- } else if (g_str_equal(path, "/test_loading_cancelled")) {
- soup_message_headers_set_encoding(msg->response_headers, SOUP_ENCODING_CHUNKED);
- soup_message_body_append(msg->response_body, SOUP_MEMORY_STATIC, HTML_STRING, strlen(HTML_STRING));
- soup_server_unpause_message(server, msg);
- return;
- }
-
- soup_message_body_complete(msg->response_body);
-}
-
-typedef struct {
- WebKitWebView* webView;
- GMainLoop *loop;
- gboolean has_been_provisional;
- gboolean has_been_committed;
- gboolean has_been_first_visually_non_empty_layout;
- gboolean has_been_finished;
- gboolean has_been_failed;
- gboolean has_been_load_error;
-} WebLoadingFixture;
-
-static void web_loading_fixture_setup(WebLoadingFixture* fixture, gconstpointer data)
-{
- fixture->webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- fixture->loop = g_main_loop_new(NULL, TRUE);
- g_object_ref_sink(fixture->webView);
- fixture->has_been_provisional = FALSE;
- fixture->has_been_committed = FALSE;
- fixture->has_been_first_visually_non_empty_layout = FALSE;
- fixture->has_been_finished = FALSE;
- fixture->has_been_failed = FALSE;
- fixture->has_been_load_error = FALSE;
-}
-
-static void web_loading_fixture_teardown(WebLoadingFixture* fixture, gconstpointer data)
-{
- g_object_unref(fixture->webView);
- g_main_loop_unref(fixture->loop);
-}
-
-static char* get_uri_for_path(const char* path)
-{
- SoupURI* uri;
- char* uri_string;
-
- uri = soup_uri_new_with_base(base_uri, path);
- uri_string = soup_uri_to_string(uri, FALSE);
- soup_uri_free (uri);
-
- return uri_string;
-}
-
-static void load_finished_cb(WebKitWebView* web_view, WebKitWebFrame* web_frame, WebLoadingFixture* fixture)
-{
- g_assert(fixture->has_been_provisional);
- g_assert(fixture->has_been_committed);
- g_assert(fixture->has_been_first_visually_non_empty_layout);
-
- g_main_loop_quit(fixture->loop);
-}
-
-
-static void status_changed_cb(GObject* object, GParamSpec* pspec, WebLoadingFixture* fixture)
-{
- WebKitLoadStatus status = webkit_web_view_get_load_status(WEBKIT_WEB_VIEW(object));
-
- switch (status) {
- case WEBKIT_LOAD_PROVISIONAL:
- g_assert(!fixture->has_been_provisional);
- g_assert(!fixture->has_been_committed);
- g_assert(!fixture->has_been_first_visually_non_empty_layout);
- fixture->has_been_provisional = TRUE;
- break;
- case WEBKIT_LOAD_COMMITTED:
- g_assert(fixture->has_been_provisional);
- g_assert(!fixture->has_been_committed);
- g_assert(!fixture->has_been_first_visually_non_empty_layout);
- fixture->has_been_committed = TRUE;
- break;
- case WEBKIT_LOAD_FIRST_VISUALLY_NON_EMPTY_LAYOUT:
- g_assert(fixture->has_been_provisional);
- g_assert(fixture->has_been_committed);
- g_assert(!fixture->has_been_first_visually_non_empty_layout);
- fixture->has_been_first_visually_non_empty_layout = TRUE;
- break;
- case WEBKIT_LOAD_FINISHED:
- g_assert(fixture->has_been_provisional);
- g_assert(fixture->has_been_committed);
- g_assert(fixture->has_been_first_visually_non_empty_layout);
- break;
- default:
- g_assert_not_reached();
- }
-}
-
-static void test_loading_status(WebLoadingFixture* fixture, gconstpointer data)
-{
- char* uri_string;
-
- g_assert_cmpint(webkit_web_view_get_load_status(fixture->webView), ==, WEBKIT_LOAD_PROVISIONAL);
-
- g_object_connect(G_OBJECT(fixture->webView),
- "signal::notify::load-status", G_CALLBACK(status_changed_cb), fixture,
- "signal::load-finished", G_CALLBACK(load_finished_cb), fixture,
- NULL);
-
- uri_string = get_uri_for_path("/test_loading_status");
-
- /* load_uri will trigger the navigation-policy-decision-requested
- * signal emission;
- */
- webkit_web_view_load_uri(fixture->webView, uri_string);
- g_free(uri_string);
-
- g_main_loop_run(fixture->loop);
-}
-
-static void load_error_status_changed_cb(GObject* object, GParamSpec* pspec, WebLoadingFixture* fixture)
-{
- WebKitLoadStatus status = webkit_web_view_get_load_status(WEBKIT_WEB_VIEW(object));
-
- switch(status) {
- case WEBKIT_LOAD_PROVISIONAL:
- g_assert(!fixture->has_been_provisional);
- fixture->has_been_provisional = TRUE;
- break;
- case WEBKIT_LOAD_COMMITTED:
- g_assert(!fixture->has_been_committed);
- fixture->has_been_committed = TRUE;
- break;
- case WEBKIT_LOAD_FINISHED:
- g_assert(fixture->has_been_provisional);
- g_assert(fixture->has_been_load_error);
- g_assert(fixture->has_been_failed);
- g_assert(!fixture->has_been_finished);
- fixture->has_been_finished = TRUE;
- break;
- case WEBKIT_LOAD_FAILED:
- g_assert(!fixture->has_been_failed);
- fixture->has_been_failed = TRUE;
- g_main_loop_quit(fixture->loop);
- break;
- default:
- break;
- }
-}
-
-static gboolean load_error_cb(WebKitWebView* webView, WebKitWebFrame* frame, const char* uri, GError *error, WebLoadingFixture* fixture)
-{
- g_assert(fixture->has_been_provisional);
- g_assert(!fixture->has_been_load_error);
- fixture->has_been_load_error = TRUE;
-
- return FALSE;
-}
-
-static void test_loading_error(WebLoadingFixture* fixture, gconstpointer data)
-{
- char* uri_string;
-
- g_test_bug("28842");
-
- g_signal_connect(fixture->webView, "load-error", G_CALLBACK(load_error_cb), fixture);
- g_signal_connect(fixture->webView, "notify::load-status", G_CALLBACK(load_error_status_changed_cb), fixture);
-
- uri_string = get_uri_for_path("/test_load_error");
- webkit_web_view_load_uri(fixture->webView, uri_string);
- g_free(uri_string);
-
- g_main_loop_run(fixture->loop);
-
- g_assert(fixture->has_been_provisional);
- g_assert(!fixture->has_been_committed);
- g_assert(fixture->has_been_load_error);
- g_assert(fixture->has_been_failed);
- g_assert(!fixture->has_been_finished);
-}
-
-/* Cancelled load */
-
-static gboolean load_cancelled_cb(WebKitWebView* webView, WebKitWebFrame* frame, const char* uri, GError *error, WebLoadingFixture* fixture)
-{
- g_assert(fixture->has_been_provisional);
- g_assert(fixture->has_been_failed);
- g_assert(!fixture->has_been_load_error);
- g_assert(error->code == WEBKIT_NETWORK_ERROR_CANCELLED);
- fixture->has_been_load_error = TRUE;
-
- return TRUE;
-}
-
-static gboolean stop_load (gpointer data)
-{
- webkit_web_view_stop_loading(WEBKIT_WEB_VIEW(data));
- return FALSE;
-}
-
-static void load_cancelled_status_changed_cb(GObject* object, GParamSpec* pspec, WebLoadingFixture* fixture)
-{
- WebKitLoadStatus status = webkit_web_view_get_load_status(WEBKIT_WEB_VIEW(object));
-
- switch(status) {
- case WEBKIT_LOAD_PROVISIONAL:
- g_assert(!fixture->has_been_provisional);
- g_assert(!fixture->has_been_failed);
- fixture->has_been_provisional = TRUE;
- break;
- case WEBKIT_LOAD_COMMITTED:
- g_idle_add (stop_load, object);
- break;
- case WEBKIT_LOAD_FAILED:
- g_assert(fixture->has_been_provisional);
- g_assert(!fixture->has_been_failed);
- g_assert(!fixture->has_been_load_error);
- fixture->has_been_failed = TRUE;
- g_main_loop_quit(fixture->loop);
- break;
- case WEBKIT_LOAD_FINISHED:
- g_assert_not_reached();
- break;
- default:
- break;
- }
-}
-
-static void test_loading_cancelled(WebLoadingFixture* fixture, gconstpointer data)
-{
- char* uri_string;
-
- g_test_bug("29644");
-
- g_signal_connect(fixture->webView, "load-error", G_CALLBACK(load_cancelled_cb), fixture);
- g_signal_connect(fixture->webView, "notify::load-status", G_CALLBACK(load_cancelled_status_changed_cb), fixture);
-
- uri_string = get_uri_for_path("/test_loading_cancelled");
- webkit_web_view_load_uri(fixture->webView, uri_string);
- g_free(uri_string);
-
- g_main_loop_run(fixture->loop);
-}
-
-static void load_goback_status_changed_cb(GObject* object, GParamSpec* pspec, WebLoadingFixture* fixture)
-{
- WebKitLoadStatus status = webkit_web_view_get_load_status(WEBKIT_WEB_VIEW(object));
-
- switch(status) {
- case WEBKIT_LOAD_PROVISIONAL:
- g_assert(!fixture->has_been_provisional);
- fixture->has_been_provisional = TRUE;
- break;
- case WEBKIT_LOAD_COMMITTED:
- g_assert(fixture->has_been_provisional);
- fixture->has_been_committed = TRUE;
- break;
- case WEBKIT_LOAD_FAILED:
- g_assert_not_reached();
- break;
- case WEBKIT_LOAD_FINISHED:
- g_assert(fixture->has_been_provisional);
- g_assert(fixture->has_been_committed);
- fixture->has_been_finished = TRUE;
- g_main_loop_quit(fixture->loop);
- break;
- default:
- break;
- }
-}
-
-static void load_wentback_status_changed_cb(GObject* object, GParamSpec* pspec, WebLoadingFixture* fixture)
-{
- WebKitLoadStatus status = webkit_web_view_get_load_status(WEBKIT_WEB_VIEW(object));
- char* uri_string;
- char* uri_string2;
-
- uri_string = get_uri_for_path("/test_loading_status");
- uri_string2 = get_uri_for_path("/test_loading_status2");
-
- switch(status) {
- case WEBKIT_LOAD_PROVISIONAL:
- g_assert_cmpstr(webkit_web_view_get_uri(fixture->webView), ==, uri_string2);
- break;
- case WEBKIT_LOAD_COMMITTED:
- g_assert_cmpstr(webkit_web_view_get_uri(fixture->webView), ==, uri_string);
- break;
- case WEBKIT_LOAD_FAILED:
- g_assert_not_reached();
- break;
- case WEBKIT_LOAD_FINISHED:
- g_assert_cmpstr(webkit_web_view_get_uri(fixture->webView), ==, uri_string);
- g_main_loop_quit(fixture->loop);
- break;
- default:
- break;
- }
-
- g_free(uri_string);
- g_free(uri_string2);
-}
-
-static void load_error_test(WebKitWebView* webview, WebKitWebFrame* frame, const char* uri, GError* error)
-{
- g_debug("Error: %s", error->message);
-}
-
-static void test_loading_goback(WebLoadingFixture* fixture, gconstpointer data)
-{
- char* uri_string;
-
- g_signal_connect(fixture->webView, "notify::load-status", G_CALLBACK(load_goback_status_changed_cb), fixture);
-
- g_signal_connect(fixture->webView, "load-error", G_CALLBACK(load_error_test), fixture);
-
- uri_string = get_uri_for_path("/test_loading_status");
- webkit_web_view_load_uri(fixture->webView, uri_string);
- g_free(uri_string);
-
- g_main_loop_run(fixture->loop);
-
- fixture->has_been_provisional = FALSE;
- fixture->has_been_committed = FALSE;
- fixture->has_been_first_visually_non_empty_layout = FALSE;
- fixture->has_been_finished = FALSE;
- fixture->has_been_failed = FALSE;
- fixture->has_been_load_error = FALSE;
-
- uri_string = get_uri_for_path("/test_loading_status2");
- webkit_web_view_load_uri(fixture->webView, uri_string);
- g_free(uri_string);
-
- g_main_loop_run(fixture->loop);
-
- g_signal_handlers_disconnect_by_func(fixture->webView, load_goback_status_changed_cb, fixture);
-
- fixture->has_been_provisional = FALSE;
- fixture->has_been_committed = FALSE;
- fixture->has_been_first_visually_non_empty_layout = FALSE;
- fixture->has_been_finished = FALSE;
- fixture->has_been_failed = FALSE;
- fixture->has_been_load_error = FALSE;
-
- g_signal_connect(fixture->webView, "notify::load-status", G_CALLBACK(load_wentback_status_changed_cb), fixture);
- webkit_web_view_go_back(fixture->webView);
-
- g_main_loop_run(fixture->loop);
-
- g_signal_handlers_disconnect_by_func(fixture->webView, load_wentback_status_changed_cb, fixture);
-}
-
-int main(int argc, char** argv)
-{
- SoupServer* server;
-
- gtk_test_init(&argc, &argv, NULL);
- // Get rid of runtime warnings about deprecated properties and signals, since they break the tests.
- g_setenv("G_ENABLE_DIAGNOSTIC", "0", TRUE);
-
- server = soup_server_new(SOUP_SERVER_PORT, 0, NULL);
- soup_server_run_async(server);
-
- soup_server_add_handler(server, NULL, server_callback, NULL, NULL);
-
- base_uri = soup_uri_new("http://127.0.0.1/");
- soup_uri_set_port(base_uri, soup_server_get_port(server));
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add("/webkit/loading/status",
- WebLoadingFixture, NULL,
- web_loading_fixture_setup,
- test_loading_status,
- web_loading_fixture_teardown);
- g_test_add("/webkit/loading/error",
- WebLoadingFixture, NULL,
- web_loading_fixture_setup,
- test_loading_error,
- web_loading_fixture_teardown);
- g_test_add("/webkit/loading/cancelled",
- WebLoadingFixture, NULL,
- web_loading_fixture_setup,
- test_loading_cancelled,
- web_loading_fixture_teardown);
- g_test_add("/webkit/loading/goback",
- WebLoadingFixture, NULL,
- web_loading_fixture_setup,
- test_loading_goback,
- web_loading_fixture_teardown);
- return g_test_run();
-}
-
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testmimehandling.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testmimehandling.c
deleted file mode 100644
index 82568caf2..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testmimehandling.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2009 Jan Michael Alonzo
- * Copyright (C) 2009 Gustavo Noronha Silva
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "test_utils.h"
-
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <libsoup/soup.h>
-#include <string.h>
-#include <webkit/webkit.h>
-#include <unistd.h>
-
-GMainLoop* loop;
-SoupSession *session;
-char* base_uri;
-
-/* For real request testing */
-static void
-server_callback(SoupServer *server, SoupMessage *msg,
- const char *path, GHashTable *query,
- SoupClientContext *context, gpointer data)
-{
- if (msg->method != SOUP_METHOD_GET) {
- soup_message_set_status(msg, SOUP_STATUS_NOT_IMPLEMENTED);
- return;
- }
-
- soup_message_set_status(msg, SOUP_STATUS_OK);
-
- /* PDF */
- if (g_str_equal(path, "/pdf")) {
- char* contents;
- gsize length;
- GError* error = NULL;
-
- g_file_get_contents("test.pdf", &contents, &length, &error);
- g_assert(!error);
-
- soup_message_body_append(msg->response_body, SOUP_MEMORY_TAKE, contents, length);
- } else if (g_str_equal(path, "/html")) {
- char* contents;
- gsize length;
- GError* error = NULL;
-
- g_file_get_contents("test.html", &contents, &length, &error);
- g_assert(!error);
-
- soup_message_body_append(msg->response_body, SOUP_MEMORY_TAKE, contents, length);
- } else if (g_str_equal(path, "/text")) {
- char* contents;
- gsize length;
- GError* error = NULL;
-
- soup_message_headers_append(msg->response_headers, "Content-Disposition", "attachment; filename=test.txt");
-
- g_file_get_contents("test.txt", &contents, &length, &error);
- g_assert(!error);
-
- soup_message_body_append(msg->response_body, SOUP_MEMORY_TAKE, contents, length);
- }
-
- soup_message_body_complete(msg->response_body);
-}
-
-static void idle_quit_loop_cb(WebKitWebView* web_view, GParamSpec* pspec, gpointer data)
-{
- if (webkit_web_view_get_load_status(web_view) == WEBKIT_LOAD_FINISHED ||
- webkit_web_view_get_load_status(web_view) == WEBKIT_LOAD_FAILED)
- g_main_loop_quit(loop);
-}
-
-static gboolean mime_type_policy_decision_requested_cb(WebKitWebView* view, WebKitWebFrame* frame,
- WebKitNetworkRequest* request, const char* mime_type,
- WebKitWebPolicyDecision* decision, gpointer data)
-{
- char* type = (char*)data;
-
- if (g_str_equal(type, "pdf")) {
- g_assert_cmpstr(mime_type, ==, "application/pdf");
- g_assert(!webkit_web_view_can_show_mime_type(view, mime_type));
- } else if (g_str_equal(type, "html")) {
- g_assert_cmpstr(mime_type, ==, "text/html");
- g_assert(webkit_web_view_can_show_mime_type(view, mime_type));
- } else if (g_str_equal(type, "text")) {
- WebKitNetworkResponse* response = webkit_web_frame_get_network_response(frame);
- SoupMessage* message = webkit_network_response_get_message(response);
- char* disposition;
-
- g_assert(message);
- soup_message_headers_get_content_disposition(message->response_headers,
- &disposition, NULL);
- g_object_unref(response);
-
- g_assert_cmpstr(disposition, ==, "attachment");
- g_free(disposition);
-
- g_assert_cmpstr(mime_type, ==, "text/plain");
- g_assert(webkit_web_view_can_show_mime_type(view, mime_type));
- }
-
- g_free(type);
-
- return FALSE;
-}
-
-static void testRemoteMimeType(const void* data)
-{
- const char* name = (const char*) data;
- WebKitWebView* view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(G_OBJECT(view));
-
- loop = g_main_loop_new(NULL, TRUE);
-
- g_object_connect(G_OBJECT(view),
- "signal::notify::load-status", idle_quit_loop_cb, NULL,
- "signal::mime-type-policy-decision-requested", mime_type_policy_decision_requested_cb, g_strdup(name),
- NULL);
-
- char* effective_uri = g_strdup_printf("%s%s", base_uri, name);
- webkit_web_view_load_uri(view, effective_uri);
- g_free(effective_uri);
-
- g_main_loop_run(loop);
-
- g_object_unref(view);
-}
-
-static void testLocalMimeType(const void* data)
-{
- const char* typeName = (const char*) data;
- WebKitWebView* view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(G_OBJECT(view));
-
- loop = g_main_loop_new(NULL, TRUE);
-
- g_object_connect(G_OBJECT(view),
- "signal::notify::load-status", idle_quit_loop_cb, NULL,
- "signal::mime-type-policy-decision-requested", mime_type_policy_decision_requested_cb, g_strdup(typeName),
- NULL);
-
- gchar* filename = g_strdup_printf("test.%s", typeName);
- GFile* file = g_file_new_for_path(filename);
- g_free(filename);
-
- gchar* fileURI = g_file_get_uri(file);
- g_object_unref(file);
-
- webkit_web_view_load_uri(view, fileURI);
- g_free(fileURI);
-
- g_main_loop_run(loop);
- g_object_unref(view);
-}
-
-int main(int argc, char** argv)
-{
- SoupServer* server;
- SoupURI* soup_uri;
-
- gtk_test_init(&argc, &argv, NULL);
-
- // Get rid of runtime warnings about deprecated properties and signals, since they break the tests.
- g_setenv("G_ENABLE_DIAGNOSTIC", "0", TRUE);
-
- /* Hopefully make test independent of the path it's called from. */
- testutils_relative_chdir("Tools/TestWebKitAPI/Tests/WebKitGtk/resources/test.html", argv[0]);
-
- server = soup_server_new(SOUP_SERVER_PORT, 0, NULL);
- soup_server_run_async(server);
-
- soup_server_add_handler(server, NULL, server_callback, NULL, NULL);
-
- soup_uri = soup_uri_new("http://127.0.0.1/");
- soup_uri_set_port(soup_uri, soup_server_get_port(server));
-
- base_uri = soup_uri_to_string(soup_uri, FALSE);
- soup_uri_free(soup_uri);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_data_func("/webkit/mime/remote-PDF", "pdf", testRemoteMimeType);
- g_test_add_data_func("/webkit/mime/remote-HTML", "html", testRemoteMimeType);
- g_test_add_data_func("/webkit/mime/remote-TEXT", "text", testRemoteMimeType);
- g_test_add_data_func("/webkit/mime/local-PDF", "pdf", testLocalMimeType);
- g_test_add_data_func("/webkit/mime/local-HTML", "html", testLocalMimeType);
- g_test_add_data_func("/webkit/mime/local-TEXT", "text", testLocalMimeType);
-
- return g_test_run();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testnetworkrequest.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testnetworkrequest.c
deleted file mode 100644
index 1b2c90f2d..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testnetworkrequest.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2009 Gustavo Noronha Silva
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <errno.h>
-#include <unistd.h>
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <gtk/gtk.h>
-#include <stdlib.h>
-#include <webkit/webkit.h>
-
-static void test_network_request_create_destroy()
-{
- WebKitNetworkRequest* request;
- SoupMessage* message;
-
- /* Test creation with URI */
- request = WEBKIT_NETWORK_REQUEST(g_object_new(WEBKIT_TYPE_NETWORK_REQUEST, "uri", "http://debian.org/", NULL));
- g_assert(WEBKIT_IS_NETWORK_REQUEST(request));
- message = webkit_network_request_get_message(request);
- g_assert(!message);
- g_object_unref(request);
-
- /* Test creation with SoupMessage */
- message = soup_message_new("GET", "http://debian.org/");
- request = WEBKIT_NETWORK_REQUEST(g_object_new(WEBKIT_TYPE_NETWORK_REQUEST, "message", message, NULL));
- g_assert(WEBKIT_IS_NETWORK_REQUEST(request));
- g_assert_cmpint(G_OBJECT(message)->ref_count, ==, 2);
- g_object_unref(request);
- g_assert_cmpint(G_OBJECT(message)->ref_count, ==, 1);
- g_object_unref(message);
-
- /* Test creation with both SoupMessage and URI */
- message = soup_message_new("GET", "http://debian.org/");
- request = WEBKIT_NETWORK_REQUEST(g_object_new(WEBKIT_TYPE_NETWORK_REQUEST, "message", message, "uri", "http://gnome.org/", NULL));
- g_assert(WEBKIT_IS_NETWORK_REQUEST(request));
- g_assert_cmpint(G_OBJECT(message)->ref_count, ==, 2);
- g_assert_cmpstr(webkit_network_request_get_uri(request), ==, "http://gnome.org/");
- g_object_unref(request);
- g_assert_cmpint(G_OBJECT(message)->ref_count, ==, 1);
- g_object_unref(message);
-}
-
-static void test_network_request_properties()
-{
- WebKitNetworkRequest* request;
- SoupMessage* message;
- gchar* soupURI;
-
- /* Test URI is set correctly when creating with URI */
- request = webkit_network_request_new("http://debian.org/");
- g_assert(WEBKIT_IS_NETWORK_REQUEST(request));
- g_assert_cmpstr(webkit_network_request_get_uri(request), ==, "http://debian.org/");
- g_object_unref(request);
-
- /* Test URI is set correctly when creating with Message */
- message = soup_message_new("GET", "http://debian.org/");
- request = WEBKIT_NETWORK_REQUEST(g_object_new(WEBKIT_TYPE_NETWORK_REQUEST, "message", message, NULL));
- g_assert(WEBKIT_IS_NETWORK_REQUEST(request));
- g_object_unref(message);
-
- message = webkit_network_request_get_message(request);
- soupURI = soup_uri_to_string(soup_message_get_uri(message), FALSE);
- g_assert_cmpstr(soupURI, ==, "http://debian.org/");
- g_free(soupURI);
-
- g_assert_cmpstr(webkit_network_request_get_uri(request), ==, "http://debian.org/");
- g_object_unref(request);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/networkrequest/createdestroy", test_network_request_create_destroy);
- g_test_add_func("/webkit/networkrequest/properties", test_network_request_properties);
- return g_test_run ();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testnetworkresponse.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testnetworkresponse.c
deleted file mode 100644
index b806aa111..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testnetworkresponse.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2009 Gustavo Noronha Silva
- * Copyright (C) 2009 Collabora Ltd.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <errno.h>
-#include <unistd.h>
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <gtk/gtk.h>
-#include <stdlib.h>
-#include <webkit/webkit.h>
-
-static void test_network_response_create_destroy()
-{
- WebKitNetworkResponse* response;
- SoupMessage* message;
-
- /* Test creation with URI */
- response = WEBKIT_NETWORK_RESPONSE(g_object_new(WEBKIT_TYPE_NETWORK_RESPONSE, "uri", "http://debian.org/", NULL));
- g_assert(WEBKIT_IS_NETWORK_RESPONSE(response));
- message = webkit_network_response_get_message(response);
- g_assert(!message);
- g_object_unref(response);
-
- /* Test creation with SoupMessage */
- message = soup_message_new("GET", "http://debian.org/");
- response = WEBKIT_NETWORK_RESPONSE(g_object_new(WEBKIT_TYPE_NETWORK_RESPONSE, "message", message, NULL));
- g_assert(WEBKIT_IS_NETWORK_RESPONSE(response));
- g_assert_cmpint(G_OBJECT(message)->ref_count, ==, 2);
- g_object_unref(response);
- g_assert_cmpint(G_OBJECT(message)->ref_count, ==, 1);
- g_object_unref(message);
-
- /* Test creation with both SoupMessage and URI */
- message = soup_message_new("GET", "http://debian.org/");
- response = WEBKIT_NETWORK_RESPONSE(g_object_new(WEBKIT_TYPE_NETWORK_RESPONSE, "message", message, "uri", "http://gnome.org/", NULL));
- g_assert(WEBKIT_IS_NETWORK_RESPONSE(response));
- g_assert_cmpint(G_OBJECT(message)->ref_count, ==, 2);
- g_assert_cmpstr(webkit_network_response_get_uri(response), ==, "http://gnome.org/");
- g_object_unref(response);
- g_assert_cmpint(G_OBJECT(message)->ref_count, ==, 1);
- g_object_unref(message);
-}
-
-static void test_network_response_properties()
-{
- WebKitNetworkResponse* response;
- SoupMessage* message;
- gchar* soupURI;
-
- /* Test URI is set correctly when creating with URI */
- response = webkit_network_response_new("http://debian.org/");
- g_assert(WEBKIT_IS_NETWORK_RESPONSE(response));
- g_assert_cmpstr(webkit_network_response_get_uri(response), ==, "http://debian.org/");
- g_object_unref(response);
-
- /* Test URI is set correctly when creating with Message */
- message = soup_message_new("GET", "http://debian.org/");
- response = WEBKIT_NETWORK_RESPONSE(g_object_new(WEBKIT_TYPE_NETWORK_RESPONSE, "message", message, NULL));
- g_assert(WEBKIT_IS_NETWORK_RESPONSE(response));
- g_object_unref(message);
-
- message = webkit_network_response_get_message(response);
- soupURI = soup_uri_to_string(soup_message_get_uri(message), FALSE);
- g_assert_cmpstr(soupURI, ==, "http://debian.org/");
- g_free(soupURI);
-
- g_assert_cmpstr(webkit_network_response_get_uri(response), ==, "http://debian.org/");
- g_object_unref(response);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/networkresponse/createdestroy", test_network_response_create_destroy);
- g_test_add_func("/webkit/networkresponse/properties", test_network_response_properties);
- return g_test_run ();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebbackforwardlist.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebbackforwardlist.c
deleted file mode 100644
index 7782d4070..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebbackforwardlist.c
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * Copyright (C) 2008 Holger Hans Peter Freyther
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <glib.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-static void test_webkit_web_history_item_lifetime(void)
-{
- WebKitWebView* webView;
- WebKitWebBackForwardList* backForwardList;
- WebKitWebHistoryItem* currentItem;
- WebKitWebHistoryItem* forwardItem;
- WebKitWebHistoryItem* backItem;
- WebKitWebHistoryItem* nthItem;
- WebKitWebHistoryItem* item1;
- WebKitWebHistoryItem* item2;
- WebKitWebHistoryItem* item3;
- WebKitWebHistoryItem* item4;
- GList* backList = NULL;
- GList* forwardList = NULL;
- g_test_bug("19898");
-
- webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- backForwardList = webkit_web_view_get_back_forward_list(webView);
- g_assert_cmpint(G_OBJECT(backForwardList)->ref_count, ==, 1);
-
- /* add test items */
- item1 = webkit_web_history_item_new_with_data("http://example.com/1/", "Site 1");
- webkit_web_back_forward_list_add_item(backForwardList, item1);
- g_object_unref(item1);
-
- item2 = webkit_web_history_item_new_with_data("http://example.com/2/", "Site 2");
- webkit_web_back_forward_list_add_item(backForwardList, item2);
- g_object_unref(item2);
-
- item3 = webkit_web_history_item_new_with_data("http://example.com/3/", "Site 3");
- webkit_web_back_forward_list_add_item(backForwardList, item3);
- g_object_unref(item3);
-
- item4 = webkit_web_history_item_new_with_data("http://example.com/4/", "Site 4");
- webkit_web_back_forward_list_add_item(backForwardList, item4);
- g_object_unref(item4);
-
- /* make sure these functions don't add unnecessary ref to the history item */
- backItem = webkit_web_back_forward_list_get_back_item(backForwardList);
- g_object_ref(backItem);
- g_assert_cmpint(G_OBJECT(backItem)->ref_count, ==, 2);
- g_object_unref(backItem);
- g_assert_cmpint(G_OBJECT(backItem)->ref_count, ==, 1);
-
- currentItem = webkit_web_back_forward_list_get_current_item(backForwardList);
- g_object_ref(currentItem);
- g_assert_cmpint(G_OBJECT(currentItem)->ref_count, ==, 2);
- g_object_unref(currentItem);
- g_assert_cmpint(G_OBJECT(currentItem)->ref_count, ==, 1);
-
- webkit_web_back_forward_list_go_to_item(backForwardList, item2);
- forwardItem = webkit_web_back_forward_list_get_forward_item(backForwardList);
- g_object_ref(forwardItem);
- g_assert_cmpint(G_OBJECT(forwardItem)->ref_count, ==, 2);
- g_object_unref(forwardItem);
- g_assert_cmpint(G_OBJECT(forwardItem)->ref_count, ==, 1);
-
- nthItem = webkit_web_back_forward_list_get_nth_item(backForwardList, 1);
- g_object_ref(nthItem);
- g_assert_cmpint(G_OBJECT(nthItem)->ref_count, ==, 2);
- g_object_unref(nthItem);
- g_assert_cmpint(G_OBJECT(nthItem)->ref_count, ==, 1);
-
- backList = webkit_web_back_forward_list_get_back_list_with_limit(backForwardList, 5);
- for (; backList; backList = backList->next)
- g_assert_cmpint(G_OBJECT(backList->data)->ref_count, ==, 1);
-
- forwardList = webkit_web_back_forward_list_get_forward_list_with_limit(backForwardList, 5);
- for (; forwardList; forwardList = forwardList->next)
- g_assert_cmpint(G_OBJECT(forwardList->data)->ref_count, ==, 1);
-
- g_list_free(forwardList);
- g_list_free(backList);
- g_assert_cmpint(G_OBJECT(item1)->ref_count, ==, 1);
- g_assert_cmpint(G_OBJECT(item2)->ref_count, ==, 1);
- g_assert_cmpint(G_OBJECT(item3)->ref_count, ==, 1);
- g_assert_cmpint(G_OBJECT(item4)->ref_count, ==, 1);
- g_assert_cmpint(G_OBJECT(backForwardList)->ref_count, ==, 1);
- g_object_unref(webView);
-}
-
-static void test_webkit_web_back_forward_list_order(void)
-{
- WebKitWebView* webView;
- WebKitWebBackForwardList* webBackForwardList;
- WebKitWebHistoryItem* item1;
- WebKitWebHistoryItem* item2;
- WebKitWebHistoryItem* item3;
- WebKitWebHistoryItem* item4;
- WebKitWebHistoryItem* currentItem;
- GList* backList = NULL;
- GList* forwardList = NULL;
- g_test_bug("22694");
-
- webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
-
- webkit_web_view_set_maintains_back_forward_list(webView, TRUE);
- webBackForwardList = webkit_web_view_get_back_forward_list(webView);
- g_assert(webBackForwardList);
-
- // Check that there is no item.
- g_assert(!webkit_web_back_forward_list_get_current_item(webBackForwardList));
- g_assert_cmpint(webkit_web_back_forward_list_get_forward_length(webBackForwardList), ==, 0);
- g_assert_cmpint(webkit_web_back_forward_list_get_back_length(webBackForwardList), ==, 0);
- g_assert(!webkit_web_view_can_go_forward(webView));
- g_assert(!webkit_web_view_can_go_back(webView));
-
- // Add a new items
- item1 = webkit_web_history_item_new_with_data("http://example.com/1/", "Site 1");
- webkit_web_back_forward_list_add_item(webBackForwardList, item1);
- g_object_unref(item1);
- g_assert(webkit_web_back_forward_list_contains_item(webBackForwardList, item1));
-
- item2 = webkit_web_history_item_new_with_data("http://example.com/2/", "Site 2");
- webkit_web_back_forward_list_add_item(webBackForwardList, item2);
- g_object_unref(item2);
- g_assert(webkit_web_back_forward_list_contains_item(webBackForwardList, item2));
-
- item3 = webkit_web_history_item_new_with_data("http://example.com/3/", "Site 3");
- webkit_web_back_forward_list_add_item(webBackForwardList, item3);
- g_object_unref(item3);
- g_assert(webkit_web_back_forward_list_contains_item(webBackForwardList, item3));
-
- item4 = webkit_web_history_item_new_with_data("http://example.com/4/", "Site 4");
- webkit_web_back_forward_list_add_item(webBackForwardList, item4);
- g_object_unref(item4);
- g_assert(webkit_web_back_forward_list_contains_item(webBackForwardList, item4));
-
- // check the back list order
- backList = webkit_web_back_forward_list_get_back_list_with_limit(webBackForwardList, 5);
- g_assert(backList);
-
- currentItem = WEBKIT_WEB_HISTORY_ITEM(backList->data);
- g_assert_cmpstr(webkit_web_history_item_get_uri(currentItem), ==, "http://example.com/3/");
- g_assert_cmpstr(webkit_web_history_item_get_title(currentItem), ==, "Site 3");
- backList = backList->next;
-
- currentItem = WEBKIT_WEB_HISTORY_ITEM(backList->data);
- g_assert_cmpstr(webkit_web_history_item_get_uri(currentItem), ==, "http://example.com/2/");
- g_assert_cmpstr(webkit_web_history_item_get_title(currentItem), ==, "Site 2");
- backList = backList->next;
-
- currentItem = WEBKIT_WEB_HISTORY_ITEM(backList->data);
- g_assert_cmpstr(webkit_web_history_item_get_uri(currentItem), ==, "http://example.com/1/");
- g_assert_cmpstr(webkit_web_history_item_get_title(currentItem), ==, "Site 1");
- g_list_free(backList);
-
- // check the forward list order
- g_assert(webkit_web_view_go_to_back_forward_item(webView, item1));
- forwardList = webkit_web_back_forward_list_get_forward_list_with_limit(webBackForwardList,5);
- g_assert(forwardList);
-
- currentItem = WEBKIT_WEB_HISTORY_ITEM(forwardList->data);
- g_assert_cmpstr(webkit_web_history_item_get_uri(currentItem), ==, "http://example.com/4/");
- g_assert_cmpstr(webkit_web_history_item_get_title(currentItem), ==, "Site 4");
- forwardList = forwardList->next;
-
- currentItem = WEBKIT_WEB_HISTORY_ITEM(forwardList->data);
- g_assert_cmpstr(webkit_web_history_item_get_uri(currentItem), ==, "http://example.com/3/");
- g_assert_cmpstr(webkit_web_history_item_get_title(currentItem), ==, "Site 3");
- forwardList = forwardList->next;
-
- currentItem = WEBKIT_WEB_HISTORY_ITEM(forwardList->data);
- g_assert_cmpstr(webkit_web_history_item_get_uri(currentItem), ==, "http://example.com/2/");
- g_assert_cmpstr(webkit_web_history_item_get_title(currentItem), ==, "Site 2");
-
- g_list_free(forwardList);
- g_object_unref(webView);
-}
-
-static void test_webkit_web_back_forward_list_add_item(void)
-{
- WebKitWebView* webView;
- WebKitWebBackForwardList* webBackForwardList;
- WebKitWebHistoryItem* addItem1;
- WebKitWebHistoryItem* addItem2;
- WebKitWebHistoryItem* backItem;
- WebKitWebHistoryItem* currentItem;
- g_test_bug("22988");
-
- webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
-
- webkit_web_view_set_maintains_back_forward_list(webView, TRUE);
- webBackForwardList = webkit_web_view_get_back_forward_list(webView);
- g_assert(webBackForwardList);
-
- // Check that there is no item.
- g_assert(!webkit_web_back_forward_list_get_current_item(webBackForwardList));
- g_assert_cmpint(webkit_web_back_forward_list_get_forward_length(webBackForwardList), ==, 0);
- g_assert_cmpint(webkit_web_back_forward_list_get_back_length(webBackForwardList), ==, 0);
- g_assert(!webkit_web_view_can_go_forward(webView));
- g_assert(!webkit_web_view_can_go_back(webView));
-
- // Add a new item
- addItem1 = webkit_web_history_item_new_with_data("http://example.com/", "Added site");
- webkit_web_back_forward_list_add_item(webBackForwardList, addItem1);
- g_object_unref(addItem1);
- g_assert(webkit_web_back_forward_list_contains_item(webBackForwardList, addItem1));
-
- // Check that the added item is the current item.
- currentItem = webkit_web_back_forward_list_get_current_item(webBackForwardList);
- g_assert(currentItem);
- g_assert_cmpint(webkit_web_back_forward_list_get_forward_length(webBackForwardList), ==, 0);
- g_assert_cmpint(webkit_web_back_forward_list_get_back_length(webBackForwardList), ==, 0);
- g_assert(!webkit_web_view_can_go_forward(webView));
- g_assert(!webkit_web_view_can_go_back(webView));
- g_assert_cmpstr(webkit_web_history_item_get_uri(currentItem), ==, "http://example.com/");
- g_assert_cmpstr(webkit_web_history_item_get_title(currentItem), ==, "Added site");
-
- // Add another item.
- addItem2 = webkit_web_history_item_new_with_data("http://example.com/2/", "Added site 2");
- webkit_web_back_forward_list_add_item(webBackForwardList, addItem2);
- g_object_unref(addItem2);
- g_assert(webkit_web_back_forward_list_contains_item(webBackForwardList, addItem2));
-
- // Check that the added item is new current item.
- currentItem = webkit_web_back_forward_list_get_current_item(webBackForwardList);
- g_assert(currentItem);
- g_assert_cmpint(webkit_web_back_forward_list_get_forward_length(webBackForwardList), ==, 0);
- g_assert_cmpint(webkit_web_back_forward_list_get_back_length(webBackForwardList), ==, 1);
- g_assert(!webkit_web_view_can_go_forward(webView));
- g_assert(webkit_web_view_can_go_back(webView));
- g_assert_cmpstr(webkit_web_history_item_get_uri(currentItem), ==, "http://example.com/2/");
- g_assert_cmpstr(webkit_web_history_item_get_title(currentItem), ==, "Added site 2");
-
- backItem = webkit_web_back_forward_list_get_back_item(webBackForwardList);
- g_assert(backItem);
- g_assert_cmpstr(webkit_web_history_item_get_uri(backItem), ==, "http://example.com/");
- g_assert_cmpstr(webkit_web_history_item_get_title(backItem), ==, "Added site");
-
- // Go to the first added item.
- g_assert(webkit_web_view_go_to_back_forward_item(webView, addItem1));
- g_assert_cmpint(webkit_web_back_forward_list_get_forward_length(webBackForwardList), ==, 1);
- g_assert_cmpint(webkit_web_back_forward_list_get_back_length(webBackForwardList), ==, 0);
- g_assert(webkit_web_view_can_go_forward(webView));
- g_assert(!webkit_web_view_can_go_back(webView));
-
- g_object_unref(webView);
-}
-
-static void test_webkit_web_back_forward_list_clear(void)
-{
- WebKitWebView* webView;
- WebKitWebBackForwardList* webBackForwardList;
- WebKitWebHistoryItem* addItem;
- g_test_bug("36173");
-
- webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
-
- webBackForwardList = webkit_web_view_get_back_forward_list(webView);
- g_assert(webBackForwardList);
-
- // Check that there is no item.
- g_assert_cmpint(webkit_web_back_forward_list_get_forward_length(webBackForwardList), ==, 0);
- g_assert_cmpint(webkit_web_back_forward_list_get_back_length(webBackForwardList), ==, 0);
- g_assert(!webkit_web_back_forward_list_get_current_item(webBackForwardList));
- g_assert(!webkit_web_view_can_go_forward(webView));
- g_assert(!webkit_web_view_can_go_back(webView));
-
- // Check that clearing the empty list does not modify counters
- webkit_web_back_forward_list_clear(webBackForwardList);
- g_assert_cmpint(webkit_web_back_forward_list_get_forward_length(webBackForwardList), ==, 0);
- g_assert_cmpint(webkit_web_back_forward_list_get_back_length(webBackForwardList), ==, 0);
- g_assert(!webkit_web_back_forward_list_get_current_item(webBackForwardList));
- g_assert(!webkit_web_view_can_go_forward(webView));
- g_assert(!webkit_web_view_can_go_back(webView));
-
- // Add a new item
- addItem = webkit_web_history_item_new_with_data("http://example.com/", "Added site");
- webkit_web_back_forward_list_add_item(webBackForwardList, addItem);
- g_object_unref(addItem);
- g_assert(webkit_web_back_forward_list_contains_item(webBackForwardList, addItem));
-
- // Check that after clearing the list the added item is no longer in the list
- webkit_web_back_forward_list_clear(webBackForwardList);
- g_assert(!webkit_web_back_forward_list_contains_item(webBackForwardList, addItem));
-
- // Check that after clearing it, the list is empty
- g_assert_cmpint(webkit_web_back_forward_list_get_forward_length(webBackForwardList), ==, 0);
- g_assert_cmpint(webkit_web_back_forward_list_get_back_length(webBackForwardList), ==, 0);
- g_assert(!webkit_web_back_forward_list_get_current_item(webBackForwardList));
- g_assert(!webkit_web_view_can_go_forward(webView));
- g_assert(!webkit_web_view_can_go_back(webView));
-
- g_object_unref(webView);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/webbackforwardlist/add_item", test_webkit_web_back_forward_list_add_item);
- g_test_add_func("/webkit/webbackforwardlist/list_order", test_webkit_web_back_forward_list_order);
- g_test_add_func("/webkit/webhistoryitem/lifetime", test_webkit_web_history_item_lifetime);
- g_test_add_func("/webkit/webbackforwardlist/clear", test_webkit_web_back_forward_list_clear);
- return g_test_run ();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebdatasource.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebdatasource.c
deleted file mode 100644
index 056625744..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebdatasource.c
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright (C) 2009 Jan Michael Alonzo
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <glib.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-static const gshort defaultTimeout = 10;
-guint waitTimer;
-gboolean shouldWait;
-
-typedef struct {
- WebKitWebView* webView;
- WebKitWebFrame* mainFrame;
-} WebDataSourceFixture;
-
-static void test_webkit_web_data_source_get_initial_request()
-{
- WebKitWebView* view;
- WebKitWebFrame* frame;
- WebKitWebDataSource* dataSource;
- WebKitNetworkRequest* initialRequest;
-
- view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(view);
- frame = webkit_web_view_get_main_frame(view);
-
- WebKitNetworkRequest* request = webkit_network_request_new("http://www.google.com");
- webkit_web_frame_load_request(frame, request);
- g_object_unref(request);
-
- dataSource = webkit_web_frame_get_provisional_data_source(frame);
- g_assert(dataSource);
- initialRequest = webkit_web_data_source_get_initial_request(dataSource);
- g_assert_cmpstr(webkit_network_request_get_uri(initialRequest), ==, "http://www.google.com/");
-
- g_object_unref(view);
-}
-
-static void notify_load_status_unreachable_cb(WebKitWebView* view, GParamSpec* pspec, GMainLoop* loop)
-{
- WebKitLoadStatus status = webkit_web_view_get_load_status (view);
- WebKitWebFrame* frame = webkit_web_view_get_main_frame(view);
-
- g_assert(status != WEBKIT_LOAD_FINISHED);
-
- if (status != WEBKIT_LOAD_FAILED)
- return;
-
- WebKitWebDataSource* datasource = webkit_web_frame_get_data_source(frame);
-
- g_assert_cmpstr("http://this.host.does.not.exist/doireallyexist.html", ==,
- webkit_web_data_source_get_unreachable_uri(datasource));
-
- g_main_loop_quit(loop);
-}
-
-static void notify_load_status_cb(WebKitWebView* view, GParamSpec* pspec, GMainLoop* loop)
-{
- WebKitLoadStatus status = webkit_web_view_get_load_status (view);
- WebKitWebFrame* frame = webkit_web_view_get_main_frame(view);
- WebKitWebDataSource* dataSource = webkit_web_frame_get_data_source(frame);
-
- if (status == WEBKIT_LOAD_COMMITTED) {
- g_assert(webkit_web_data_source_is_loading(dataSource));
- return;
- }
- else if (status != WEBKIT_LOAD_FINISHED)
- return;
-
- /* Test get_request */
- g_test_message("Testing webkit_web_data_source_get_request");
- WebKitNetworkRequest* request = webkit_web_data_source_get_request(dataSource);
- g_assert_cmpstr(webkit_network_request_get_uri(request), ==, "http://www.webkit.org/");
-
- /* Test get_main_resource */
- g_test_message("Testing webkit_web_data_source_get_main_resource");
- WebKitWebResource* resource = webkit_web_data_source_get_main_resource(dataSource);
- g_assert_cmpstr("text/html", ==, webkit_web_resource_get_mime_type(resource));
- g_assert_cmpstr("http://www.webkit.org/", ==, webkit_web_resource_get_uri(resource));
-
- /* Test get_data. We just test if data has certain size for the mean time */
- g_test_message("Testing webkit_web_data_source_get_data has certain size");
- GString* data = webkit_web_data_source_get_data(dataSource);
- g_assert(data->len > 100);
-
- /* FIXME: Add test for get_encoding */
-
- g_main_loop_quit(loop);
-}
-
-static gboolean wait_timer_fired(GMainLoop* loop)
-{
- waitTimer = 0;
- g_main_loop_quit(loop);
-
- return FALSE;
-}
-
-static void test_webkit_web_data_source()
-{
- WebKitWebView* view;
- GMainLoop* loop;
-
- view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(view);
- loop = g_main_loop_new(NULL, TRUE);
- g_signal_connect(view, "notify::load-status", G_CALLBACK(notify_load_status_cb), loop);
- webkit_web_view_load_uri(view, "http://www.webkit.org");
-
- waitTimer = g_timeout_add_seconds(defaultTimeout, (GSourceFunc)wait_timer_fired, loop);
-
- g_main_loop_run(loop);
-
- if (waitTimer)
- g_source_remove(waitTimer);
-
- waitTimer = 0;
-
- g_main_loop_unref(loop);
- g_object_unref(view);
-}
-
-static void notify_load_status_lifetime_cb(WebKitWebView* view, GParamSpec* pspec, GMainLoop* loop)
-{
- WebKitLoadStatus status = webkit_web_view_get_load_status (view);
- WebKitWebFrame* frame = webkit_web_view_get_main_frame(view);
- WebKitWebDataSource* dataSource = webkit_web_frame_get_data_source(frame);
-
- if (status == WEBKIT_LOAD_COMMITTED) {
- g_assert(webkit_web_data_source_is_loading(dataSource));
- return;
- } else if (status != WEBKIT_LOAD_FINISHED)
- return;
-
- g_main_loop_quit(loop);
-}
-
-static void test_webkit_web_data_source_lifetime()
-{
- WebKitWebView* view;
- GMainLoop* loop;
-
- view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(view);
- loop = g_main_loop_new(NULL, TRUE);
- g_signal_connect(view, "notify::load-status", G_CALLBACK(notify_load_status_lifetime_cb), loop);
- webkit_web_view_load_uri(view, "http://www.webkit.org");
-
- waitTimer = g_timeout_add_seconds(defaultTimeout, (GSourceFunc)wait_timer_fired, loop);
-
- g_main_loop_run(loop);
-
- WebKitWebDataSource* dataSource = webkit_web_frame_get_data_source(webkit_web_view_get_main_frame(view));
- GList* subResources = webkit_web_data_source_get_subresources(dataSource);
- gint numberOfResources = g_list_length(subResources);
- g_list_free(subResources);
-
- g_assert_cmpint(webkit_web_view_get_load_status(view), ==, WEBKIT_LOAD_FINISHED);
-
- webkit_web_view_load_uri(view, "http://gnome.org");
-
- g_assert_cmpint(webkit_web_view_get_load_status(view), ==, WEBKIT_LOAD_PROVISIONAL);
-
- webkit_web_view_stop_loading(view);
-
- g_assert_cmpint(webkit_web_view_get_load_status(view), ==, WEBKIT_LOAD_FAILED);
-
- subResources = webkit_web_data_source_get_subresources(dataSource);
- g_assert_cmpint(numberOfResources, ==, g_list_length(subResources));
- g_list_free(subResources);
-
- if (waitTimer)
- g_source_remove(waitTimer);
-
- waitTimer = 0;
-
- g_main_loop_unref(loop);
- g_object_unref(view);
-}
-
-static void test_webkit_web_data_source_unreachable_uri()
-{
- /* FIXME: this test fails currently. */
- return;
-
- WebKitWebView* view;
- GMainLoop* loop;
-
- view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(view);
- loop = g_main_loop_new(NULL, TRUE);
- g_signal_connect(view, "notify::load-status", G_CALLBACK(notify_load_status_unreachable_cb), loop);
- webkit_web_view_load_uri(view, "http://this.host.does.not.exist/doireallyexist.html");
-
- waitTimer = g_timeout_add_seconds(defaultTimeout, (GSourceFunc)wait_timer_fired, loop);
-
- g_main_loop_run(loop);
-
- if (waitTimer)
- g_source_remove(waitTimer);
-
- waitTimer = 0;
-
- g_main_loop_unref(loop);
- g_object_unref(view);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_bug("24758");
- g_test_add_func("/webkit/webdatasource/get_initial_request",
- test_webkit_web_data_source_get_initial_request);
- g_test_add_func("/webkit/webdatasource/api",
- test_webkit_web_data_source);
- g_test_add_func("/webkit/webdatasource/unreachable_uri",
- test_webkit_web_data_source_unreachable_uri);
- g_test_add_func("/webkit/webdatasource/lifetime",
- test_webkit_web_data_source_lifetime);
-
- return g_test_run ();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebframe.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebframe.c
deleted file mode 100644
index 1131873d4..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebframe.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright (C) 2008 Holger Hans Peter Freyther
- * Copyright (C) 2009 Collabora Ltd.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <errno.h>
-#include <unistd.h>
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-static int numberOfFramesCreated = 0;
-
-static void createFrameSignalTestFrameCreatedCallback(WebKitWebView* webView, WebKitWebFrame* frame, gpointer data)
-{
- numberOfFramesCreated++;
-}
-
-static gboolean createFrameSignalTestTimeout(gpointer data)
-{
- g_assert_cmpint(numberOfFramesCreated, ==, 2);
- g_main_loop_quit((GMainLoop*) data);
- return FALSE;
-}
-
-static void test_webkit_web_frame_created_signal(void)
-{
- GtkWidget* webView;
- GtkWidget* window;
- GMainLoop* loop = g_main_loop_new(NULL, TRUE);
-
- window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-
- webView = webkit_web_view_new();
- g_signal_connect(webView, "frame-created", G_CALLBACK(createFrameSignalTestFrameCreatedCallback), loop);
-
- // We want to ensure that exactly two create-frame signals are
- // fired and no more, so we set a timeout here. There does not appear
- // to be a simple way via the API to figure out when all frames have
- // loaded.
- g_timeout_add(500, createFrameSignalTestTimeout, loop);
-
- gtk_container_add(GTK_CONTAINER(window), webView);
- gtk_widget_show(window);
- gtk_widget_show(webView);
-
- webkit_web_view_load_string(WEBKIT_WEB_VIEW(webView),
- "<html><body>Frames!"
- "<iframe></iframe>"
- "<iframe></iframe>"
- "</body></html>",
- "text/html", "utf-8", "file://");
- g_main_loop_run(loop);
-}
-
-static void test_webkit_web_frame_create_destroy(void)
-{
- GtkWidget *webView;
- GtkWidget *window;
-
- g_test_bug("21837");
- webView = webkit_web_view_new();
- g_object_ref_sink(webView);
- g_assert_cmpint(G_OBJECT(webView)->ref_count, ==, 1);
- // This crashed with the original version
- g_object_unref(webView);
-
- g_test_bug("25042");
- window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- webView = webkit_web_view_new();
- gtk_container_add(GTK_CONTAINER(window), webView);
- gtk_widget_show(window);
- gtk_widget_show(webView);
- gtk_widget_destroy(webView);
-}
-
-static void test_webkit_web_frame_lifetime(void)
-{
- WebKitWebView* webView;
- WebKitWebFrame* webFrame;
- g_test_bug("21837");
-
- webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- g_assert_cmpint(G_OBJECT(webView)->ref_count, ==, 1);
- webFrame = webkit_web_view_get_main_frame(webView);
- g_assert_cmpint(G_OBJECT(webFrame)->ref_count, ==, 1);
-
- // Add dummy reference on the WebKitWebFrame to keep it alive
- g_object_ref(webFrame);
- g_assert_cmpint(G_OBJECT(webFrame)->ref_count, ==, 2);
-
- // This crashed with the original version
- g_object_unref(webView);
-
- // Make sure that the frame got deleted as well. We did this
- // by adding an extra ref on the WebKitWebFrame and we should
- // be the one holding the last reference.
- g_assert_cmpint(G_OBJECT(webFrame)->ref_count, ==, 1);
- g_object_unref(webFrame);
-}
-
-static gboolean print_requested_cb(WebKitWebView* webView, WebKitWebFrame* webFrame, GMainLoop* loop)
-{
- g_object_set_data(G_OBJECT(webView), "signal-handled", GINT_TO_POINTER(TRUE));
- g_main_loop_quit(loop);
- return TRUE;
-}
-
-static void print_timeout(GMainLoop* loop)
-{
- if (g_main_loop_is_running(loop))
- g_main_loop_quit(loop);
-}
-
-static void test_webkit_web_frame_printing(void)
-{
- WebKitWebView* webView;
-
- webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- g_assert_cmpint(G_OBJECT(webView)->ref_count, ==, 1);
-
- webkit_web_view_load_string(webView,
- "<html><body><h1>WebKitGTK+!</h1></body></html>",
- "text/html",
- "utf-8",
- "file://");
-
- GMainLoop* loop = g_main_loop_new(NULL, TRUE);
-
- // Does javascript print() work correctly?
- g_signal_connect(webView, "print-requested",
- G_CALLBACK(print_requested_cb),
- loop);
-
- g_object_set_data(G_OBJECT(webView), "signal-handled", GINT_TO_POINTER(FALSE));
- webkit_web_view_execute_script (webView, "print();");
-
- // Give javascriptcore some time to process the print request, but
- // prepare a timeout to avoid it running forever in case the signal is
- // never emitted.
- g_timeout_add(1000, (GSourceFunc)print_timeout, loop);
- g_main_loop_run(loop);
-
- g_assert_cmpint(GPOINTER_TO_INT(g_object_get_data(G_OBJECT(webView), "signal-handled")), ==, TRUE);
-
- // Does printing directly to a file?
- GError *error = NULL;
- gchar* temporaryFilename = NULL;
- gint fd = g_file_open_tmp ("webkit-testwebframe-XXXXXX", &temporaryFilename, &error);
- close(fd);
-
- if (error) {
- g_critical("Failed to open a temporary file for writing: %s.", error->message);
- g_error_free(error);
- goto cleanup;
- }
-
- // We delete the file, so that we can easily figure out that the
- // file got printed;
- if (g_unlink(temporaryFilename) == -1) {
- g_warning("Failed to delete the temporary file: %s.\nThis may cause the test to be bogus.", g_strerror(errno));
- }
-
- WebKitWebFrame* webFrame = webkit_web_view_get_main_frame(webView);
- GtkPrintOperation* operation = gtk_print_operation_new();
- GtkPrintOperationAction action = GTK_PRINT_OPERATION_ACTION_EXPORT;
- GtkPrintOperationResult result;
-
- gtk_print_operation_set_export_filename(operation, temporaryFilename);
- result = webkit_web_frame_print_full (webFrame, operation, action, NULL);
-
- g_assert_cmpint(result, ==, GTK_PRINT_OPERATION_RESULT_APPLY);
- g_assert_cmpint(g_file_test(temporaryFilename, G_FILE_TEST_IS_REGULAR), ==, TRUE);
-
- g_unlink(temporaryFilename);
- g_object_unref(operation);
-cleanup:
- g_object_unref(webView);
- g_free(temporaryFilename);
-}
-
-static void test_webkit_web_frame_response()
-{
- WebKitWebFrame* frame = g_object_new(WEBKIT_TYPE_WEB_FRAME, NULL);
- WebKitNetworkResponse* response = webkit_web_frame_get_network_response(frame);
- g_assert(!response);
- g_object_unref(frame);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/webview/create_destroy", test_webkit_web_frame_create_destroy);
- g_test_add_func("/webkit/webview/frame-created_signal", test_webkit_web_frame_created_signal);
- g_test_add_func("/webkit/webframe/lifetime", test_webkit_web_frame_lifetime);
- g_test_add_func("/webkit/webview/printing", test_webkit_web_frame_printing);
- g_test_add_func("/webkit/webview/response", test_webkit_web_frame_response);
- return g_test_run ();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebhistoryitem.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebhistoryitem.c
deleted file mode 100644
index 82e191c20..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebhistoryitem.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2009 Jan Michael Alonzo
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <glib.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-typedef struct {
- WebKitWebHistoryItem* item;
-} WebHistoryItemFixture;
-
-static void web_history_item_fixture_setup(WebHistoryItemFixture* fixture,
- gconstpointer data)
-{
- fixture->item = webkit_web_history_item_new_with_data("http://example.com/", "Example1");
- g_assert_cmpint(G_OBJECT(fixture->item)->ref_count, == , 1);
- g_assert(fixture->item != NULL);
-}
-
-static void web_history_item_fixture_teardown(WebHistoryItemFixture* fixture,
- gconstpointer data)
-{
- g_assert(fixture->item != NULL);
- g_assert_cmpint(G_OBJECT(fixture->item)->ref_count, ==, 1);
-}
-
-static void test_webkit_web_history_item_get_data(WebHistoryItemFixture* fixture,
- gconstpointer data)
-{
- g_assert_cmpstr(webkit_web_history_item_get_title(fixture->item), ==, "Example1");
- g_assert_cmpstr(webkit_web_history_item_get_uri(fixture->item), ==, "http://example.com/");
-}
-
-static void test_webkit_web_history_item_alternate_title(WebHistoryItemFixture* fixture,
- gconstpointer data)
-{
- webkit_web_history_item_set_alternate_title(fixture->item, "Alternate title");
- g_assert_cmpstr(webkit_web_history_item_get_alternate_title(fixture->item), ==, "Alternate title");
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add("/webkit/webhistoryitem/get_data",
- WebHistoryItemFixture, 0, web_history_item_fixture_setup,
- test_webkit_web_history_item_get_data, web_history_item_fixture_teardown);
- g_test_add("/webkit/webhistoryitem/alternate_title",
- WebHistoryItemFixture, 0, web_history_item_fixture_setup,
- test_webkit_web_history_item_alternate_title, web_history_item_fixture_teardown);
- return g_test_run ();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebinspector.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebinspector.c
deleted file mode 100644
index a74382ff3..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebinspector.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (C) 2012 Gustavo Noronha Silva <gns@gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "test_utils.h"
-
-#include <string.h>
-#include <glib.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-GMainLoop *loop;
-GtkWidget *window;
-
-static gboolean quitLoop(gpointer data)
-{
- g_main_loop_quit(loop);
- return TRUE;
-}
-
-/* Ignore simple translation-related messages and upgrade other
- * messages to warnings.
- */
-static gboolean consoleMessageCallback(WebKitWebView* webView, const char* message, unsigned int line, const char* sourceId)
-{
- if (strstr(message, "Localized string") || strstr(message, "Protocol Error: the message is for non-existing domain 'Profiler'") ||
- strstr(message, "Didn't find a TreeElement for a representedObject"))
- return TRUE;
-
- g_warning("Console: %s @%d: %s\n", sourceId, line, message);
- return TRUE;
-}
-
-static WebKitWebView* inspectElementCallback(WebKitWebInspector *inspector, WebKitWebView *inspectedWebView, int *timesElementInspected)
-{
- *timesElementInspected = *timesElementInspected + 1;
-
- window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-
- GtkWidget *newWebView = webkit_web_view_new();
- gtk_container_add(GTK_CONTAINER(window), newWebView);
-
- g_signal_connect(newWebView, "console-message",
- G_CALLBACK(consoleMessageCallback), NULL);
-
- return WEBKIT_WEB_VIEW(newWebView);
-}
-
-static gboolean closeInspector(WebKitWebInspector *inspector, int *timesClosed)
-{
- *timesClosed = *timesClosed + 1;
-
- gtk_widget_destroy(window);
- return TRUE;
-}
-
-static gboolean showInspector(WebKitWebInspector *inspector, gpointer data)
-{
- g_idle_add(quitLoop, NULL);
- return TRUE;
-}
-
-static void loadFinished(WebKitWebView *webView, WebKitWebFrame *frame, gboolean *isLoadFinished)
-{
- *isLoadFinished = TRUE;
- if (g_main_loop_is_running(loop))
- g_main_loop_quit(loop);
-}
-
-static void test_webkit_web_inspector_close_and_inspect()
-{
- WebKitWebView *webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- loop = g_main_loop_new(NULL, TRUE);
-
- gboolean isLoadFinished = FALSE;
- g_signal_connect(webView, "load-finished", G_CALLBACK(loadFinished), &isLoadFinished);
- webkit_web_view_load_string(webView,
- "<html><body><p>woohoo</p></body></html>",
- "text/html", "UTF-8", "file://");
- if (!isLoadFinished)
- g_main_loop_run(loop);
-
- g_object_set(webkit_web_view_get_settings(webView), "enable-developer-extras", TRUE, NULL);
- WebKitWebInspector *inspector = webkit_web_view_get_inspector(webView);
-
- int timesElementInspected = 0;
- int timesClosed = 0;
- g_object_connect(inspector,
- "signal::inspect-web-view", G_CALLBACK(inspectElementCallback), &timesElementInspected,
- "signal::show-window", G_CALLBACK(showInspector), NULL,
- "signal::close-window", G_CALLBACK(closeInspector), &timesClosed,
- NULL);
-
- webkit_web_inspector_inspect_coordinates(inspector, 0.0, 0.0);
- g_assert_cmpint(timesElementInspected, ==, 1);
-
- g_main_loop_run(loop);
-
- webkit_web_inspector_close(inspector);
- g_assert_cmpint(timesClosed, ==, 1);
-
- webkit_web_inspector_inspect_coordinates(inspector, 0.0, 0.0);
- g_assert_cmpint(timesElementInspected, ==, 2);
-
- g_main_loop_run(loop);
-
- gtk_widget_destroy(GTK_WIDGET(webView));
- g_assert_cmpint(timesClosed, ==, 2);
-
- g_main_loop_unref(loop);
-}
-
-static void test_webkit_web_inspector_destroy_inspected_web_view()
-{
- WebKitWebView *webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- loop = g_main_loop_new(NULL, TRUE);
-
- gboolean isLoadFinished = FALSE;
- g_signal_connect(webView, "load-finished", G_CALLBACK(loadFinished), &isLoadFinished);
- webkit_web_view_load_string(webView,
- "<html><body><p>woohoo</p></body></html>",
- "text/html", "UTF-8", "file://");
- if (!isLoadFinished)
- g_main_loop_run(loop);
-
- g_object_set(webkit_web_view_get_settings(webView), "enable-developer-extras", TRUE, NULL);
- WebKitWebInspector *inspector = webkit_web_view_get_inspector(webView);
-
- int timesElementInspected = 0;
- int timesClosed = 0;
- g_object_connect(inspector,
- "signal::inspect-web-view", G_CALLBACK(inspectElementCallback), &timesElementInspected,
- "signal::show-window", G_CALLBACK(showInspector), NULL,
- "signal::close-window", G_CALLBACK(closeInspector), &timesClosed,
- NULL);
-
- webkit_web_inspector_inspect_coordinates(inspector, 0.0, 0.0);
- g_assert_cmpint(timesElementInspected, ==, 1);
-
- g_main_loop_run(loop);
-
- gtk_widget_destroy(GTK_WIDGET(webView));
- g_assert_cmpint(timesClosed, ==, 1);
-
- g_main_loop_unref(loop);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/webinspector/destroy-inspected-web-view", test_webkit_web_inspector_destroy_inspected_web_view);
- g_test_add_func("/webkit/webinspector/close-and-inspect", test_webkit_web_inspector_close_and_inspect);
-
- return g_test_run();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebplugindatabase.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebplugindatabase.c
deleted file mode 100644
index 652811b13..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebplugindatabase.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2010 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <errno.h>
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-/* This function is not public, so we need an extern declaration */
-extern void webkit_web_settings_add_extra_plugin_directory(WebKitWebView* view, const gchar* directory);
-
-static void test_webkit_web_plugin_database_get_plugins()
-{
- WebKitWebView* view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- WebKitWebPluginDatabase* database;
- GSList* pluginList, *p;
- gboolean found = FALSE;
- gboolean enabled = FALSE;
-
- webkit_web_settings_add_extra_plugin_directory(view, TEST_PLUGIN_DIR);
- g_object_ref_sink(G_OBJECT(view));
-
- database = webkit_get_web_plugin_database();
- pluginList = webkit_web_plugin_database_get_plugins(database);
- for (p = pluginList; p; p = p->next) {
- WebKitWebPlugin* plugin = (WebKitWebPlugin*)p->data;
- if (!g_strcmp0(webkit_web_plugin_get_name(plugin), "WebKit Test PlugIn") &&
- !g_strcmp0(webkit_web_plugin_get_description(plugin), "Simple Netscape® plug-in that handles test content for WebKit")) {
- found = TRUE;
- enabled = webkit_web_plugin_get_enabled(plugin);
- webkit_web_plugin_set_enabled(plugin, FALSE);
- }
- }
- webkit_web_plugin_database_plugins_list_free(pluginList);
- g_assert(found);
- g_assert(enabled);
-
- webkit_web_plugin_database_refresh(database);
- pluginList = webkit_web_plugin_database_get_plugins(database);
-
- for (p = pluginList; p; p = p->next) {
- WebKitWebPlugin* plugin = (WebKitWebPlugin*)p->data;
- if (!g_strcmp0(webkit_web_plugin_get_name(plugin), "WebKit Test PlugIn") &&
- !g_strcmp0(webkit_web_plugin_get_description(plugin), "Simple Netscape® plug-in that handles test content for WebKit"))
- enabled = webkit_web_plugin_get_enabled(plugin);
- }
- webkit_web_plugin_database_plugins_list_free(pluginList);
- g_assert(!enabled);
-
- g_object_unref(view);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/webplugindatabase/getplugins", test_webkit_web_plugin_database_get_plugins);
- return g_test_run ();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebresource.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebresource.c
deleted file mode 100644
index 35d09476d..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebresource.c
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Copyright (C) 2009 Jan Michael Alonzo
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <glib.h>
-#include <gtk/gtk.h>
-#include <libsoup/soup.h>
-#include <string.h>
-#include <webkit/webkit.h>
-
-#define INDEX_HTML "<html></html>"
-#define MAIN_HTML "<html><head><script language=\"javascript\" src=\"/javascript.js\"></script></head><body><h1>hah</h1></html>"
-#define JAVASCRIPT "function blah () { var a = 1; }"
-
-GMainLoop* loop;
-SoupSession *session;
-char *base_uri;
-WebKitWebResource* main_resource;
-WebKitWebResource* sub_resource;
-
-typedef struct {
- WebKitWebResource* webResource;
- WebKitWebView* webView;
-} WebResourceFixture;
-
-/* For real request testing */
-static void
-server_callback (SoupServer *server, SoupMessage *msg,
- const char *path, GHashTable *query,
- SoupClientContext *context, gpointer data)
-{
- if (msg->method != SOUP_METHOD_GET) {
- soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
- return;
- }
-
- soup_message_set_status (msg, SOUP_STATUS_OK);
-
- /* Redirect */
- if (g_str_equal (path, "/")) {
- soup_message_set_status (msg, SOUP_STATUS_MOVED_PERMANENTLY);
-
- soup_message_headers_append (msg->response_headers,
- "Location", "/index.html");
- } else if (g_str_equal (path, "/index.html")) {
- soup_message_body_append (msg->response_body,
- SOUP_MEMORY_COPY,
- INDEX_HTML,
- strlen (INDEX_HTML));
- } else if (g_str_equal (path, "/main.html")) {
- soup_message_body_append (msg->response_body,
- SOUP_MEMORY_COPY,
- MAIN_HTML,
- strlen (MAIN_HTML));
- } else if (g_str_equal (path, "/javascript.js")) {
- soup_message_body_append (msg->response_body,
- SOUP_MEMORY_COPY,
- JAVASCRIPT,
- strlen (JAVASCRIPT));
- }
-
-
- soup_message_body_complete (msg->response_body);
-}
-
-static void web_resource_fixture_setup(WebResourceFixture* fixture, gconstpointer data)
-{
- fixture->webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(fixture->webView);
- const gchar* webData = "<html></html>";
- fixture->webResource = webkit_web_resource_new(webData, strlen(webData), "http://example.com/", "text/html", "utf8", "Example.com");
- g_assert(fixture->webResource);
-}
-
-static void web_resource_fixture_teardown(WebResourceFixture* fixture, gconstpointer data)
-{
- g_assert(fixture->webResource);
- g_object_unref(fixture->webResource);
- g_object_unref(fixture->webView);
-}
-
-static void test_webkit_web_resource_get_url(WebResourceFixture* fixture, gconstpointer data)
-{
- gchar* url;
- g_object_get(G_OBJECT(fixture->webResource), "uri", &url, NULL);
- g_assert_cmpstr(url, ==, "http://example.com/");
- g_assert_cmpstr(webkit_web_resource_get_uri(fixture->webResource) ,==,"http://example.com/");
- g_free(url);
-}
-
-static void test_webkit_web_resource_get_data(WebResourceFixture* fixture, gconstpointer data)
-{
- GString* charData = webkit_web_resource_get_data(fixture->webResource);
- g_assert_cmpstr(charData->str, ==, "<html></html>");
-}
-
-static void test_webkit_web_resource_get_mime_type(WebResourceFixture* fixture, gconstpointer data)
-{
- gchar* mime_type;
- g_object_get(G_OBJECT(fixture->webResource), "mime-type", &mime_type, NULL);
- g_assert_cmpstr(mime_type, ==, "text/html");
- g_assert_cmpstr(webkit_web_resource_get_mime_type(fixture->webResource),==,"text/html");
- g_free(mime_type);
-}
-
-static void test_webkit_web_resource_get_encoding(WebResourceFixture* fixture, gconstpointer data)
-{
- gchar* text_encoding;
- g_object_get(G_OBJECT(fixture->webResource), "encoding", &text_encoding, NULL);
- g_assert_cmpstr(text_encoding, ==, "utf8");
- g_assert_cmpstr(webkit_web_resource_get_encoding(fixture->webResource),==,"utf8");
- g_free(text_encoding);
-}
-
-static void test_webkit_web_resource_get_frame_name(WebResourceFixture* fixture, gconstpointer data)
-{
- gchar* frame_name;
- g_object_get(G_OBJECT(fixture->webResource), "frame-name", &frame_name, NULL);
- g_assert_cmpstr(frame_name, ==, "Example.com");
- g_assert_cmpstr(webkit_web_resource_get_frame_name(fixture->webResource),==,"Example.com");
- g_free(frame_name);
-}
-
-static void resource_request_starting_cb(WebKitWebView* web_view, WebKitWebFrame* web_frame, WebKitWebResource* web_resource, WebKitNetworkRequest* request, WebKitNetworkResponse* response, gpointer data)
-{
- gint* been_there = data;
- *been_there = *been_there + 1;
-
- if (*been_there == 1) {
- g_assert(!main_resource);
- main_resource = g_object_ref(web_resource);
-
- g_assert_cmpstr(webkit_web_resource_get_uri(web_resource), ==, base_uri);
-
- /* This should be a redirect, so the response must be NULL */
- g_assert(!response);
- } else if (*been_there == 2) {
- char* uri = g_strdup_printf("%sindex.html", base_uri);
-
- g_assert_cmpstr(webkit_web_resource_get_uri(web_resource), ==, uri);
-
- /* Cancel the request. */
- webkit_network_request_set_uri(request, "about:blank");
-
- g_free(uri);
- }
-}
-
-static void notify_load_status_cb(WebKitWebView* web_view, GParamSpec* pspec, gpointer data)
-{
- if (webkit_web_view_get_load_status(web_view) == WEBKIT_LOAD_FINISHED) {
- gboolean* been_there = data;
- *been_there = TRUE;
-
- g_assert_cmpstr(webkit_web_view_get_uri(web_view), ==, "about:blank");
-
- g_main_loop_quit(loop);
- }
-}
-
-static void test_web_resource_loading()
-{
- WebKitWebView* web_view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- gint been_to_resource_request_starting = 0;
- gboolean been_to_load_finished = FALSE;
- WebKitWebFrame* web_frame;
- WebKitWebDataSource* data_source;
-
- loop = g_main_loop_new(NULL, TRUE);
-
- g_object_ref_sink(web_view);
-
- g_signal_connect(web_view, "resource-request-starting",
- G_CALLBACK(resource_request_starting_cb),
- &been_to_resource_request_starting);
-
- g_signal_connect(web_view, "notify::load-status",
- G_CALLBACK(notify_load_status_cb),
- &been_to_load_finished);
-
- webkit_web_view_load_uri(web_view, base_uri);
-
- /* We won't get finished immediately, because of the redirect */
- g_main_loop_run(loop);
-
- web_frame = webkit_web_view_get_main_frame(web_view);
- data_source = webkit_web_frame_get_data_source(web_frame);
-
- g_assert(main_resource);
- g_assert(webkit_web_data_source_get_main_resource(data_source) == main_resource);
- g_object_unref(main_resource);
-
- g_assert_cmpint(been_to_resource_request_starting, ==, 2);
- g_assert_cmpint(been_to_load_finished, ==, TRUE);
-
- g_object_unref(web_view);
- g_main_loop_unref(loop);
-}
-
-static void resource_request_starting_sub_cb(WebKitWebView* web_view, WebKitWebFrame* web_frame, WebKitWebResource* web_resource, WebKitNetworkRequest* request, WebKitNetworkResponse* response, gpointer data)
-{
- if (!main_resource)
- main_resource = g_object_ref(web_resource);
- else if (!sub_resource)
- sub_resource = g_object_ref(web_resource);
-}
-
-static void notify_load_status_sub_cb(WebKitWebView* web_view, GParamSpec* pspec, gpointer data)
-{
- if (webkit_web_view_get_load_status(web_view) == WEBKIT_LOAD_FINISHED)
- g_main_loop_quit(loop);
-}
-
-static gboolean idle_quit_loop_cb(gpointer data)
-{
- g_main_loop_quit(loop);
- return FALSE;
-}
-
-static void test_web_resource_sub_resource_loading()
-{
- WebKitWebView* web_view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- WebKitWebFrame* web_frame;
- WebKitWebDataSource* data_source;
- GList* sub_resources;
- char* uri = g_strdup_printf("%smain.html", base_uri);
-
- main_resource = NULL;
-
- loop = g_main_loop_new(NULL, TRUE);
-
- g_object_ref_sink(web_view);
-
- g_signal_connect(web_view, "resource-request-starting",
- G_CALLBACK(resource_request_starting_sub_cb),
- NULL);
-
- g_signal_connect(web_view, "notify::load-status",
- G_CALLBACK(notify_load_status_sub_cb),
- NULL);
-
- webkit_web_view_load_uri(web_view, uri);
-
- g_main_loop_run(loop);
-
- /* The main resource should be loaded; now let's wait for the sub-resource to load */
- g_idle_add(idle_quit_loop_cb, NULL);
- g_main_loop_run(loop);
-
- g_assert(main_resource && sub_resource);
- g_assert(main_resource != sub_resource);
-
- web_frame = webkit_web_view_get_main_frame(web_view);
- data_source = webkit_web_frame_get_data_source(web_frame);
-
- g_assert(webkit_web_data_source_get_main_resource(data_source) == main_resource);
- g_object_unref(main_resource);
-
- sub_resources = webkit_web_data_source_get_subresources(data_source);
- // Expected resources: javascripts.js, favicon.ico
- g_assert(sub_resources);
- g_assert(sub_resources->next);
- g_assert(!sub_resources->next->next);
-
- // Test that the object we got from the data source is the same
- // that went through resource-request-starting. Note that the order is
- // not important (and not guaranteed since the resources are stored in a
- // hashtable).
- g_assert(WEBKIT_WEB_RESOURCE(sub_resources->data) == sub_resource
- || WEBKIT_WEB_RESOURCE(sub_resources->next->data) == sub_resource);
-
- g_object_unref(web_view);
- g_main_loop_unref(loop);
-}
-
-int main(int argc, char** argv)
-{
- SoupServer* server;
- SoupURI* soup_uri;
-
- gtk_test_init(&argc, &argv, NULL);
-
- // Get rid of runtime warnings about deprecated properties and signals, since they break the tests.
- g_setenv("G_ENABLE_DIAGNOSTIC", "0", TRUE);
-
- server = soup_server_new(SOUP_SERVER_PORT, 0, NULL);
- soup_server_run_async(server);
-
- soup_server_add_handler(server, NULL, server_callback, NULL, NULL);
-
- soup_uri = soup_uri_new("http://127.0.0.1/");
- soup_uri_set_port(soup_uri, soup_server_get_port(server));
-
- base_uri = soup_uri_to_string(soup_uri, FALSE);
- soup_uri_free(soup_uri);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add("/webkit/webresource/get_url",
- WebResourceFixture, 0, web_resource_fixture_setup,
- test_webkit_web_resource_get_url, web_resource_fixture_teardown);
- g_test_add("/webkit/webresource/get_mime_type",
- WebResourceFixture, 0, web_resource_fixture_setup,
- test_webkit_web_resource_get_mime_type, web_resource_fixture_teardown);
- g_test_add("/webkit/webresource/get_text_encoding_name",
- WebResourceFixture, 0, web_resource_fixture_setup,
- test_webkit_web_resource_get_encoding, web_resource_fixture_teardown);
- g_test_add("/webkit/webresource/get_frame_name",
- WebResourceFixture, 0, web_resource_fixture_setup,
- test_webkit_web_resource_get_frame_name, web_resource_fixture_teardown);
- g_test_add("/webkit/webresource/get_data",
- WebResourceFixture, 0, web_resource_fixture_setup,
- test_webkit_web_resource_get_data, web_resource_fixture_teardown);
-
- g_test_add_func("/webkit/webresource/loading", test_web_resource_loading);
- g_test_add_func("/webkit/webresource/sub_resource_loading", test_web_resource_sub_resource_loading);
-
- return g_test_run ();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebsettings.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebsettings.c
deleted file mode 100644
index e557e133c..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebsettings.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2009 Jan Michael Alonzo
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <glib.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-static void test_webkit_web_settings_copy(void)
-{
- WebKitWebSettings *settings = webkit_web_settings_new();
-
- // Set some non-default settings to verify that settings are properly copied.
- g_object_set(settings,
- "enable-webgl", TRUE,
- "enable-fullscreen", TRUE,
- "auto-load-images", FALSE,
- "default-encoding", "utf-8",
- "enable-mediasource", TRUE,
- NULL);
-
- WebKitWebSettings *copy = webkit_web_settings_copy(settings);
-
- gboolean enableWebGL = FALSE;
- gboolean enableFullscreen = FALSE;
- gboolean autoLoadImages = FALSE;
- gboolean enableMediaSource = FALSE;
- char *defaultEncoding = 0;
- g_object_get(copy,
- "enable-fullscreen", &enableFullscreen,
- "enable-webgl", &enableWebGL,
- "auto-load-images", &autoLoadImages,
- "default-encoding", &defaultEncoding,
- "enable-mediasource", &enableMediaSource,
- NULL);
-
- g_assert(enableWebGL);
- g_assert(enableFullscreen);
- g_assert(!autoLoadImages);
- g_assert_cmpstr(defaultEncoding, ==, "utf-8");
- g_assert(enableMediaSource);
- g_free(defaultEncoding);
-}
-
-static void test_webkit_web_settings_user_agent(void)
-{
- WebKitWebSettings *settings;
- GtkWidget *webView;
- char *defaultUserAgent;
- char *userAgent = 0;
- g_test_bug("17375");
-
- webView = webkit_web_view_new();
- g_object_ref_sink(webView);
-
- settings = webkit_web_view_get_settings(WEBKIT_WEB_VIEW(webView));
- defaultUserAgent = g_strdup(webkit_web_settings_get_user_agent(settings));
-
- g_assert(g_strstr_len(defaultUserAgent, -1, "Version/8.0 Safari/"));
- g_assert(g_strstr_len(defaultUserAgent, -1, "Version/8.0") < g_strstr_len(defaultUserAgent, -1, "Safari/"));
-
- // test a custom UA string
- userAgent = 0;
- g_object_set(settings, "user-agent", "testwebsettings/0.1", NULL);
- g_object_get(settings,"user-agent", &userAgent, NULL);
- g_assert_cmpstr(userAgent, ==, "testwebsettings/0.1");
- g_free(userAgent);
-
- // setting it to NULL or an empty value should give us the default UA string
- userAgent = 0;
- g_object_set(settings, "user-agent", 0, NULL);
- g_object_get(settings,"user-agent", &userAgent, NULL);
- g_assert_cmpstr(userAgent, ==, defaultUserAgent);
- g_free(userAgent);
-
- userAgent = 0;
- g_object_set(settings, "user-agent", "", NULL);
- g_object_get(settings,"user-agent", &userAgent, NULL);
- g_assert_cmpstr(userAgent, ==, defaultUserAgent);
- g_free(userAgent);
-
- g_free(defaultUserAgent);
- g_object_unref(webView);
-}
-
-int main(int argc, char **argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/websettings/user_agent", test_webkit_web_settings_user_agent);
- g_test_add_func("/webkit/websettings/copy", test_webkit_web_settings_copy);
- return g_test_run ();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebview.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebview.c
deleted file mode 100644
index 86057867c..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebview.c
+++ /dev/null
@@ -1,749 +0,0 @@
-/*
- * Copyright (C) 2008 Holger Hans Peter Freyther
- * Copyright (C) 2009, 2010 Collabora Ltd.
- * Copyright (C) 2012 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "test_utils.h"
-
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <gdk/gdk.h>
-#include <gdk/gdkkeysyms.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-GMainLoop* loop;
-SoupSession *session;
-char* base_uri;
-
-/* For real request testing */
-static void
-server_callback(SoupServer* server, SoupMessage* msg,
- const char* path, GHashTable* query,
- SoupClientContext* context, gpointer data)
-{
- if (msg->method != SOUP_METHOD_GET) {
- soup_message_set_status(msg, SOUP_STATUS_NOT_IMPLEMENTED);
- return;
- }
-
- soup_message_set_status(msg, SOUP_STATUS_OK);
-
- if (g_str_equal(path, "/favicon.ico")) {
- char* contents;
- gsize length;
- GError* error = NULL;
-
- g_file_get_contents("blank.ico", &contents, &length, &error);
- g_assert(!error);
-
- soup_message_body_append(msg->response_body, SOUP_MEMORY_TAKE, contents, length);
- } else if (g_str_equal(path, "/bigdiv.html")) {
- char* contents = g_strdup("<html><body><a id=\"link\" href=\"http://abc.def\">test</a><div style=\"background-color: green; height: 1200px;\"></div></body></html>");
- soup_message_body_append(msg->response_body, SOUP_MEMORY_TAKE, contents, strlen(contents));
- } else if (g_str_equal(path, "/iframe.html")) {
- char* contents = g_strdup("<html><body id=\"some-content\"><div style=\"background-color: green; height: 50px;\"></div><iframe src=\"bigdiv.html\"></iframe></body></html>");
- soup_message_body_append(msg->response_body, SOUP_MEMORY_TAKE, contents, strlen(contents));
- } else {
- char* contents = g_strdup("<html><body>test</body></html>");
- soup_message_body_append(msg->response_body, SOUP_MEMORY_TAKE, contents, strlen(contents));
- }
-
- soup_message_body_complete(msg->response_body);
-}
-
-static void idle_quit_loop_cb(WebKitWebView* web_view, GParamSpec* pspec, gpointer data)
-{
- if (webkit_web_view_get_load_status(web_view) == WEBKIT_LOAD_FINISHED ||
- webkit_web_view_get_load_status(web_view) == WEBKIT_LOAD_FAILED)
- g_main_loop_quit(loop);
-}
-
-static gboolean timeout_cb(gpointer data)
-{
- g_error("Didn't get icon-uri before timing out.");
- return FALSE;
-}
-
-static void icon_uri_changed_cb(WebKitWebView* web_view, GParamSpec* pspec, gpointer data)
-{
- char* expected_uri;
-
- g_assert_cmpstr(g_param_spec_get_name(pspec), ==, "icon-uri");
-
- expected_uri = g_strdup_printf("%sfavicon.ico", base_uri);
- g_assert_cmpstr(webkit_web_view_get_icon_uri(web_view), ==, expected_uri);
- g_free(expected_uri);
-
- g_main_loop_quit(loop);
-}
-
-static void icon_loaded_cb(WebKitWebView* web_view, char* icon_uri, gpointer data)
-{
- gboolean* been_here = (gboolean*)data;
- char* expected_uri = g_strdup_printf("%sfavicon.ico", base_uri);
- g_assert_cmpstr(icon_uri, ==, expected_uri);
- g_free(expected_uri);
-
- g_assert_cmpstr(icon_uri, ==, webkit_web_view_get_icon_uri(web_view));
-
- *been_here = TRUE;
-}
-
-static void test_webkit_web_view_icon_uri()
-{
- gboolean been_to_icon_loaded = FALSE;
- WebKitWebView* view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(G_OBJECT(view));
-
- loop = g_main_loop_new(NULL, TRUE);
-
- g_object_connect(G_OBJECT(view),
- "signal::notify::icon-uri", icon_uri_changed_cb, NULL,
- "signal::icon-loaded", icon_loaded_cb, &been_to_icon_loaded,
- NULL);
-
- webkit_web_view_load_uri(view, base_uri);
-
- guint timeout_id = g_timeout_add(500, timeout_cb, 0);
-
- g_main_loop_run(loop);
-
- g_source_remove(timeout_id);
-
- g_assert(been_to_icon_loaded);
-
- g_object_unref(view);
-}
-
-static gboolean map_event_cb(GtkWidget *widget, GdkEvent* event, gpointer data)
-{
- GMainLoop* loop = (GMainLoop*)data;
- g_main_loop_quit(loop);
-
- return FALSE;
-}
-
-static gboolean quit_after_short_delay_cb(gpointer data)
-{
- g_main_loop_quit((GMainLoop*)data);
- return FALSE;
-}
-
-static void test_webkit_web_view_grab_focus()
-{
- char* uri = g_strconcat(base_uri, "iframe.html", NULL);
- GtkWidget* window = gtk_window_new(GTK_WINDOW_POPUP);
- GtkWidget* scrolled_window = gtk_scrolled_window_new(NULL, NULL);
- WebKitWebView* view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- GtkAdjustment* adjustment;
-
- gtk_window_set_default_size(GTK_WINDOW(window), 400, 200);
-
- gtk_container_add(GTK_CONTAINER(window), scrolled_window);
- gtk_container_add(GTK_CONTAINER(scrolled_window), GTK_WIDGET(view));
-
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-
- loop = g_main_loop_new(NULL, TRUE);
-
- g_signal_connect(view, "notify::load-status", G_CALLBACK(idle_quit_loop_cb), NULL);
-
- /* Wait for window to show up */
- gtk_widget_show_all(window);
- g_signal_connect(window, "map-event",
- G_CALLBACK(map_event_cb), loop);
- g_main_loop_run(loop);
-
- /* Load a page with a big div that will cause scrollbars to appear */
- webkit_web_view_load_uri(view, uri);
- g_main_loop_run(loop);
-
- adjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(scrolled_window));
- g_assert_cmpfloat(gtk_adjustment_get_value(adjustment), ==, 0.0);
-
- /* Since webkit_web_view_execute_script does not return a value,
- it is impossible to know if an inner document has focus after
- a node of it was focused via .focus() method.
- The code below is an workaround: if the node has focus, a scroll
- action is performed and afterward it is checked if the adjustment
- has to be different from 0.
- */
- char script[] = "var innerDoc = document.defaultView.frames[0].document; \
- innerDoc.getElementById(\"link\").focus(); \
- if (innerDoc.hasFocus()) \
- window.scrollBy(0, 100);";
-
- /* Focus an element using JavaScript */
- webkit_web_view_execute_script(view, script);
-
- /* Adjustments update asynchronously, so we must wait a bit. */
- g_timeout_add(100, quit_after_short_delay_cb, loop);
- g_main_loop_run(loop);
-
- /* Make sure the ScrolledWindow noticed the scroll */
- g_assert_cmpfloat(gtk_adjustment_get_value(adjustment), !=, 0.0);
-
- g_free(uri);
- gtk_widget_destroy(window);
-}
-
-static void do_test_webkit_web_view_adjustments(gboolean with_page_cache)
-{
- char* effective_uri = g_strconcat(base_uri, "bigdiv.html", NULL);
- char* second_uri = g_strconcat(base_uri, "iframe.html", NULL);
- GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- GtkWidget* scrolled_window = gtk_scrolled_window_new(NULL, NULL);
- WebKitWebView* view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- GtkAdjustment* adjustment;
- double lower;
- double upper;
-
- if (with_page_cache) {
- WebKitWebSettings* settings = webkit_web_view_get_settings(view);
- g_object_set(settings, "enable-page-cache", TRUE, NULL);
- }
-
- gtk_window_set_default_size(GTK_WINDOW(window), 400, 200);
-
- gtk_container_add(GTK_CONTAINER(window), scrolled_window);
- gtk_container_add(GTK_CONTAINER(scrolled_window), GTK_WIDGET(view));
-
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-
- loop = g_main_loop_new(NULL, TRUE);
-
- g_object_connect(G_OBJECT(view),
- "signal::notify::load-status", idle_quit_loop_cb, NULL,
- NULL);
-
- /* Wait for window to show up */
- gtk_widget_show_all(window);
- g_signal_connect(window, "map-event",
- G_CALLBACK(map_event_cb), loop);
- g_main_loop_run(loop);
-
- /* Load a page with a big div that will cause scrollbars to appear */
- webkit_web_view_load_uri(view, effective_uri);
- g_main_loop_run(loop);
-
- /* Adjustments update asynchronously, so we must wait a bit. */
- g_timeout_add(100, quit_after_short_delay_cb, loop);
- g_main_loop_run(loop);
-
- adjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(scrolled_window));
- g_assert_cmpfloat(gtk_adjustment_get_value(adjustment), ==, 0.0);
-
- lower = gtk_adjustment_get_lower(adjustment);
- upper = gtk_adjustment_get_upper(adjustment);
-
- /* Scroll the view using JavaScript */
- webkit_web_view_execute_script(view, "window.scrollBy(0, 100)");
-
- /* Adjustments update asynchronously, so we must wait a bit. */
- g_timeout_add(100, quit_after_short_delay_cb, loop);
- g_main_loop_run(loop);
-
- /* Make sure the ScrolledWindow noticed the scroll */
- g_assert_cmpfloat(gtk_adjustment_get_value(adjustment), ==, 100.0);
-
- /* Load a second URI */
- webkit_web_view_load_uri(view, second_uri);
- g_main_loop_run(loop);
-
- /* The page loaded but the adjustments may not be updated yet. Wait a bit. */
- g_timeout_add(100, quit_after_short_delay_cb, loop);
- g_main_loop_run(loop);
-
- /* Make sure the scrollbar has been reset */
- g_assert_cmpfloat(gtk_adjustment_get_value(adjustment), ==, 0.0);
-
- /* Go back */
- webkit_web_view_go_back(view);
-
- /* When using page cache, go_back will return syncronously */
- if (!with_page_cache)
- g_main_loop_run(loop);
-
- /* Make sure GTK+ has time to process the changes in size, for the adjusments */
- while (gtk_events_pending())
- gtk_main_iteration();
-
- /* Make sure upper and lower bounds have been restored correctly */
- g_assert_cmpfloat(lower, ==, gtk_adjustment_get_lower(adjustment));
- g_assert_cmpfloat(upper, ==, gtk_adjustment_get_upper(adjustment));
- g_assert_cmpfloat(gtk_adjustment_get_value(adjustment), ==, 100.0);
-
- g_free(effective_uri);
- g_free(second_uri);
-
- gtk_widget_destroy(window);
-}
-
-static void test_webkit_web_view_adjustments()
-{
- /* Test this with page cache disabled, and enabled. */
- do_test_webkit_web_view_adjustments(FALSE);
- do_test_webkit_web_view_adjustments(TRUE);
-}
-
-gboolean delayed_destroy(gpointer data)
-{
- gtk_widget_destroy(GTK_WIDGET(data));
- g_main_loop_quit(loop);
- return FALSE;
-}
-
-static void test_webkit_web_view_destroy()
-{
- GtkWidget* window;
- GtkWidget* web_view;
-
- window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- web_view = webkit_web_view_new();
-
- gtk_container_add(GTK_CONTAINER(window), web_view);
-
- gtk_widget_show_all(window);
-
- loop = g_main_loop_new(NULL, TRUE);
-
- g_signal_connect(window, "map-event",
- G_CALLBACK(map_event_cb), loop);
- g_main_loop_run(loop);
-
- g_idle_add(delayed_destroy, web_view);
- g_main_loop_run(loop);
-
- gtk_widget_destroy(window);
-}
-
-static void test_webkit_web_view_window_features()
-{
- GtkWidget* window;
- GtkWidget* web_view;
-
- window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- web_view = webkit_web_view_new();
-
- gtk_container_add(GTK_CONTAINER(window), web_view);
-
- gtk_widget_show_all(window);
-
- loop = g_main_loop_new(NULL, TRUE);
-
- g_signal_connect(window, "map-event",
- G_CALLBACK(map_event_cb), loop);
- g_main_loop_run(loop);
-
- /* Bug #36144 */
- g_object_set(G_OBJECT(web_view), "window-features", NULL, NULL);
-
- gtk_widget_destroy(window);
-}
-
-static void test_webkit_web_view_in_offscreen_window_does_not_crash()
-{
- loop = g_main_loop_new(NULL, TRUE);
-
- GtkWidget *window = gtk_offscreen_window_new();
- GtkWidget *web_view = webkit_web_view_new();
-
- gtk_container_add(GTK_CONTAINER(window), web_view);
- gtk_widget_show_all(window);
- g_signal_connect(web_view, "notify::load-status", G_CALLBACK(idle_quit_loop_cb), NULL);
- webkit_web_view_load_uri(WEBKIT_WEB_VIEW(web_view), base_uri);
-
- g_main_loop_run(loop);
-
- gtk_widget_destroy(window);
- g_main_loop_unref(loop);
-}
-
-static void test_webkit_web_view_does_not_steal_focus()
-{
- loop = g_main_loop_new(NULL, TRUE);
-
- GtkWidget *window = gtk_offscreen_window_new();
- GtkWidget *webView = webkit_web_view_new();
- GtkWidget *entry = gtk_entry_new();
-
-#ifdef GTK_API_VERSION_2
- GtkWidget *box = gtk_hbox_new(FALSE, 0);
-#else
- GtkWidget *box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
-#endif
-
- gtk_container_add(GTK_CONTAINER(box), webView);
- gtk_container_add(GTK_CONTAINER(box), entry);
- gtk_container_add(GTK_CONTAINER(window), box);
- gtk_widget_show_all(window);
-
- gtk_widget_grab_focus(entry);
- g_assert(gtk_widget_is_focus(entry));
-
- g_signal_connect(webView, "notify::load-status", G_CALLBACK(idle_quit_loop_cb), NULL);
- webkit_web_view_load_html_string(WEBKIT_WEB_VIEW(webView),
- "<html><body>"
- " <input id=\"entry\" type=\"text\"/>"
- " <script>"
- " document.getElementById(\"entry\").focus();"
- " </script>"
- "</body></html>", "file://");
-
- g_main_loop_run(loop);
-
- g_assert(gtk_widget_is_focus(entry));
-
- gtk_widget_destroy(window);
- g_main_loop_unref(loop);
-}
-
-static gboolean emitKeyStroke(WebKitWebView* webView)
-{
- GdkEvent* pressEvent = gdk_event_new(GDK_KEY_PRESS);
- pressEvent->key.keyval = GDK_KEY_f;
- GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(webView));
- pressEvent->key.window = window;
- g_object_ref(pressEvent->key.window);
-
-#ifndef GTK_API_VERSION_2
- GdkDeviceManager* manager = gdk_display_get_device_manager(gdk_window_get_display(window));
- gdk_event_set_device(pressEvent, gdk_device_manager_get_client_pointer(manager));
-#endif
-
- // When synthesizing an event, an invalid hardware_keycode value
- // can cause it to be badly processed by Gtk+.
- GdkKeymapKey* keys;
- gint n_keys;
- if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), GDK_KEY_f, &keys, &n_keys)) {
- pressEvent->key.hardware_keycode = keys[0].keycode;
- g_free(keys);
- }
-
- GdkEvent* releaseEvent = gdk_event_copy(pressEvent);
- gtk_main_do_event(pressEvent);
- gdk_event_free(pressEvent);
- releaseEvent->key.type = GDK_KEY_RELEASE;
- gtk_main_do_event(releaseEvent);
- gdk_event_free(releaseEvent);
-
- return FALSE;
-}
-
-static gboolean entering_fullscreen_cb(WebKitWebView* webView, GObject* element, gboolean blocked)
-{
- if (blocked)
- g_main_loop_quit(loop);
- else
- g_timeout_add(200, (GSourceFunc) emitKeyStroke, webView);
- return blocked;
-}
-
-static gboolean leaving_fullscreen_cb(WebKitWebView* webView, GObject* element, gpointer data)
-{
- g_main_loop_quit(loop);
- return FALSE;
-}
-
-static void test_webkit_web_view_fullscreen(gconstpointer blocked)
-{
- GtkWidget* window;
- GtkWidget* web_view;
- WebKitWebSettings *settings;
-
- window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- web_view = webkit_web_view_new();
-
- settings = webkit_web_view_get_settings(WEBKIT_WEB_VIEW(web_view));
- g_object_set(settings, "enable-fullscreen", TRUE, NULL);
- webkit_web_view_set_settings(WEBKIT_WEB_VIEW(web_view), settings);
-
- gtk_container_add(GTK_CONTAINER(window), web_view);
-
- gtk_widget_show_all(window);
-
- loop = g_main_loop_new(NULL, TRUE);
-
- g_signal_connect(web_view, "entering-fullscreen", G_CALLBACK(entering_fullscreen_cb), (gpointer) blocked);
- g_signal_connect(web_view, "leaving-fullscreen", G_CALLBACK(leaving_fullscreen_cb), NULL);
-
- webkit_web_view_load_string(WEBKIT_WEB_VIEW(web_view), "<html><body>"
- "<script>"
- "var eventName = 'keypress';"
- "document.addEventListener(eventName, function () {"
- " document.documentElement.webkitRequestFullScreen();"
- "}, false);"
- "</script></body></html>", NULL, NULL, NULL);
-
- g_timeout_add(100, (GSourceFunc) emitKeyStroke, WEBKIT_WEB_VIEW(web_view));
- g_main_loop_run(loop);
-
- gtk_widget_destroy(window);
-}
-
-static gboolean checkMimeTypeForFilter(GtkFileFilter* filter, const gchar* mimeType)
-{
- GtkFileFilterInfo filter_info;
- filter_info.contains = GTK_FILE_FILTER_MIME_TYPE;
- filter_info.mime_type = mimeType;
- return gtk_file_filter_filter(filter, &filter_info);
-}
-
-static gboolean runFileChooserCbNoMultiselNoMime(WebKitWebView* webview, WebKitFileChooserRequest* request, gpointer data)
-{
- g_assert(!webkit_file_chooser_request_get_select_multiple(request));
-
- const gchar* const* mimeTypes = webkit_file_chooser_request_get_mime_types(request);
- g_assert(!mimeTypes);
- GtkFileFilter* filter = webkit_file_chooser_request_get_mime_types_filter(request);
- g_assert(!filter);
-
- const gchar* const* selectedFiles = webkit_file_chooser_request_get_selected_files(request);
- g_assert(!selectedFiles);
-
- g_main_loop_quit(loop);
- return TRUE;
-}
-
-static gboolean runFileChooserCbMultiselNoMime(WebKitWebView* webview, WebKitFileChooserRequest* request, gpointer data)
-{
- g_assert(webkit_file_chooser_request_get_select_multiple(request));
-
- const gchar* const* mimeTypes = webkit_file_chooser_request_get_mime_types(request);
- g_assert(!mimeTypes);
- GtkFileFilter* filter = webkit_file_chooser_request_get_mime_types_filter(request);
- g_assert(!filter);
- const gchar* const* selectedFiles = webkit_file_chooser_request_get_selected_files(request);
- g_assert(!selectedFiles);
-
- // Select some files.
- const gchar* filesToSelect[4] = { "/foo", "/foo/bar", "/foo/bar/baz", 0 };
- webkit_file_chooser_request_select_files(request, filesToSelect);
-
- // Check the files that have been just selected.
- selectedFiles = webkit_file_chooser_request_get_selected_files(request);
- g_assert(selectedFiles);
- g_assert_cmpstr(selectedFiles[0], ==, "/foo");
- g_assert_cmpstr(selectedFiles[1], ==, "/foo/bar");
- g_assert_cmpstr(selectedFiles[2], ==, "/foo/bar/baz");
- g_assert(!selectedFiles[3]);
-
- g_main_loop_quit(loop);
- return TRUE;
-}
-
-static gboolean runFileChooserCbSelectionRetained(WebKitWebView* webview, WebKitFileChooserRequest* request, gpointer data)
-{
- const gchar* const* selectedFiles = webkit_file_chooser_request_get_selected_files(request);
- g_assert(selectedFiles);
- g_assert_cmpstr(selectedFiles[0], ==, "/foo");
- g_assert_cmpstr(selectedFiles[1], ==, "/foo/bar");
- g_assert_cmpstr(selectedFiles[2], ==, "/foo/bar/baz");
- g_assert(!selectedFiles[3]);
-
- g_main_loop_quit(loop);
- return TRUE;
-}
-
-static gboolean runFileChooserCbNoMultiselAcceptTypes(WebKitWebView* webview, WebKitFileChooserRequest* request, gpointer data)
-{
- g_assert(!webkit_file_chooser_request_get_select_multiple(request));
-
- const gchar* const* mimeTypes = webkit_file_chooser_request_get_mime_types(request);
- g_assert(mimeTypes);
- g_assert_cmpstr(mimeTypes[0], ==, "audio/*");
- g_assert_cmpstr(mimeTypes[1], ==, "video/*");
- g_assert_cmpstr(mimeTypes[2], ==, "image/*");
- g_assert(!mimeTypes[3]);
-
- GtkFileFilter* filter = webkit_file_chooser_request_get_mime_types_filter(request);
- g_assert(GTK_IS_FILE_FILTER(filter));
- g_assert(checkMimeTypeForFilter(filter, "audio/*"));
- g_assert(checkMimeTypeForFilter(filter, "video/*"));
- g_assert(checkMimeTypeForFilter(filter, "image/*"));
-
- const gchar* const* selectedFiles = webkit_file_chooser_request_get_selected_files(request);
- g_assert(!selectedFiles);
-
- g_main_loop_quit(loop);
- return TRUE;
-}
-
-void doMouseButtonEvent(GtkWidget* widget, GdkEventType eventType, int x, int y, unsigned int button, unsigned int modifiers)
-{
- g_assert(gtk_widget_get_realized(widget));
-
- GdkEvent* event = gdk_event_new(eventType);
- event->button.window = gtk_widget_get_window(widget);
- g_object_ref(event->button.window);
-
- event->button.time = GDK_CURRENT_TIME;
- event->button.x = x;
- event->button.y = y;
- event->button.axes = 0;
- event->button.state = modifiers;
- event->button.button = button;
-
-#ifndef GTK_API_VERSION_2
- event->button.device = gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gtk_widget_get_display(widget)));
-#endif
-
- int xRoot, yRoot;
- gdk_window_get_root_coords(gtk_widget_get_window(widget), x, y, &xRoot, &yRoot);
- event->button.x_root = xRoot;
- event->button.y_root = yRoot;
- gtk_main_do_event(event);
-}
-
-static void clickMouseButton(GtkWidget* widget, int x, int y, unsigned int button, unsigned int modifiers)
-{
- doMouseButtonEvent(widget, GDK_BUTTON_PRESS, x, y, button, modifiers);
- doMouseButtonEvent(widget, GDK_BUTTON_RELEASE, x, y, button, modifiers);
-}
-
-static gboolean clickMouseButtonAndWaitForFileChooserRequest(WebKitWebView* webView)
-{
- clickMouseButton(GTK_WIDGET(webView), 5, 5, 1, 0);
- return TRUE;
-}
-
-static void test_webkit_web_view_file_chooser()
-{
- const gchar* htmlFormatBase = "<html><body>"
- "<input style='position:absolute;left:0;top:0;margin:0;padding:0' type='file' %s/>"
- "</body></html>";
-
- GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- GtkWidget* webView = webkit_web_view_new();
- gtk_container_add(GTK_CONTAINER(window), webView);
- gtk_widget_show_all(window);
-
- loop = g_main_loop_new(NULL, TRUE);
-
- // Multiple selections not allowed, no MIME filtering.
- gulong handler = g_signal_connect(webView, "run-file-chooser", G_CALLBACK(runFileChooserCbNoMultiselNoMime), NULL);
- gchar* htmlFormat = g_strdup_printf(htmlFormatBase, "");
- webkit_web_view_load_string(WEBKIT_WEB_VIEW(webView), htmlFormat, NULL, NULL, NULL);
- g_free(htmlFormat);
-
- g_timeout_add(100, (GSourceFunc) clickMouseButtonAndWaitForFileChooserRequest, WEBKIT_WEB_VIEW(webView));
- g_main_loop_run(loop);
-
- g_signal_handler_disconnect(webView, handler);
-
- // Multiple selections allowed, no MIME filtering, some pre-selected files.
- handler = g_signal_connect(webView, "run-file-chooser", G_CALLBACK(runFileChooserCbMultiselNoMime), NULL);
- htmlFormat = g_strdup_printf(htmlFormatBase, "multiple");
- webkit_web_view_load_string(WEBKIT_WEB_VIEW(webView), htmlFormat, NULL, NULL, NULL);
- g_free(htmlFormat);
-
- g_timeout_add(100, (GSourceFunc) clickMouseButtonAndWaitForFileChooserRequest, WEBKIT_WEB_VIEW(webView));
- g_main_loop_run(loop);
-
- g_signal_handler_disconnect(webView, handler);
-
- // Perform another request to check if the list of files selected
- // in the previous step appears now as part of the new request.
- handler = g_signal_connect(webView, "run-file-chooser", G_CALLBACK(runFileChooserCbSelectionRetained), NULL);
- g_timeout_add(100, (GSourceFunc) clickMouseButtonAndWaitForFileChooserRequest, WEBKIT_WEB_VIEW(webView));
- g_main_loop_run(loop);
-
- g_signal_handler_disconnect(webView, handler);
-
- // Multiple selections not allowed, only accept images, audio and video files.
- handler = g_signal_connect(webView, "run-file-chooser", G_CALLBACK(runFileChooserCbNoMultiselAcceptTypes), NULL);
- htmlFormat = g_strdup_printf(htmlFormatBase, "accept='audio/*,video/*,image/*'");
- webkit_web_view_load_string(WEBKIT_WEB_VIEW(webView), htmlFormat, NULL, NULL, NULL);
- g_free(htmlFormat);
-
- g_timeout_add(100, (GSourceFunc) clickMouseButtonAndWaitForFileChooserRequest, WEBKIT_WEB_VIEW(webView));
- g_main_loop_run(loop);
-
- g_signal_handler_disconnect(webView, handler);
- gtk_widget_destroy(window);
-}
-
-static void test_webkit_web_view_source_mode()
-{
- GtkWidget* web_view;
-
- web_view = webkit_web_view_new();
-
- webkit_web_view_load_string(WEBKIT_WEB_VIEW(web_view), "<html><body></body></html>", NULL, NULL, NULL);
-
- g_assert(!webkit_web_view_get_view_source_mode(WEBKIT_WEB_VIEW(web_view)));
-
- webkit_web_view_set_view_source_mode(WEBKIT_WEB_VIEW(web_view), TRUE);
-
- g_assert(webkit_web_view_get_view_source_mode(WEBKIT_WEB_VIEW(web_view)));
-
- webkit_web_view_set_view_source_mode(WEBKIT_WEB_VIEW(web_view), FALSE);
-
- g_assert(!webkit_web_view_get_view_source_mode(WEBKIT_WEB_VIEW(web_view)));
-
- gtk_widget_destroy(web_view);
-}
-
-int main(int argc, char** argv)
-{
- SoupServer* server;
- SoupURI* soup_uri;
-
- gtk_test_init(&argc, &argv, NULL);
-
- // Get rid of runtime warnings about deprecated properties and signals, since they break the tests.
- g_setenv("G_ENABLE_DIAGNOSTIC", "0", TRUE);
-
- /* Hopefully make test independent of the path it's called from. */
- testutils_relative_chdir("Tools/TestWebKitAPI/Tests/WebKitGtk/resources/test.html", argv[0]);
-
- server = soup_server_new(SOUP_SERVER_PORT, 0, NULL);
- soup_server_run_async(server);
-
- soup_server_add_handler(server, NULL, server_callback, NULL, NULL);
-
- soup_uri = soup_uri_new("http://127.0.0.1/");
- soup_uri_set_port(soup_uri, soup_server_get_port(server));
-
- base_uri = soup_uri_to_string(soup_uri, FALSE);
- soup_uri_free(soup_uri);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/webview/icon-uri", test_webkit_web_view_icon_uri);
- g_test_add_func("/webkit/webview/adjustments", test_webkit_web_view_adjustments);
- g_test_add_func("/webkit/webview/destroy", test_webkit_web_view_destroy);
- g_test_add_func("/webkit/webview/grab_focus", test_webkit_web_view_grab_focus);
- g_test_add_func("/webkit/webview/window-features", test_webkit_web_view_window_features);
- g_test_add_func("/webkit/webview/webview-in-offscreen-window-does-not-crash", test_webkit_web_view_in_offscreen_window_does_not_crash);
- g_test_add_func("/webkit/webview/webview-does-not-steal-focus", test_webkit_web_view_does_not_steal_focus);
- g_test_add_data_func("/webkit/webview/fullscreen", GINT_TO_POINTER(FALSE), test_webkit_web_view_fullscreen);
- g_test_add_data_func("/webkit/webview/fullscreen-blocked", GINT_TO_POINTER(TRUE), test_webkit_web_view_fullscreen);
- g_test_add_func("/webkit/webview/file-chooser", test_webkit_web_view_file_chooser);
- g_test_add_func("/webkit/webview/source-mode", test_webkit_web_view_source_mode);
-
- return g_test_run ();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwindow.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testwindow.c
deleted file mode 100644
index 5eda47b12..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwindow.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2009 Collabora Ltd.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-static void notify_load_status_cb(WebKitWebView* web_view, GParamSpec* pspec, gpointer data)
-{
- if (webkit_web_view_get_load_status(web_view) == WEBKIT_LOAD_FINISHED) {
- GMainLoop* loop = (GMainLoop*)data;
-
- g_main_loop_quit(loop);
- }
-}
-
-static void test_webkit_window_scrollbar_policy(void)
-{
- GMainLoop* loop;
- GtkWidget* scrolledWindow;
- GtkWidget* webView;
- WebKitWebFrame* mainFrame;
- GtkPolicyType horizontalPolicy;
- GtkPolicyType verticalPolicy;
-
- loop = g_main_loop_new(NULL, TRUE);
-
- scrolledWindow = gtk_scrolled_window_new(NULL, NULL);
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledWindow),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-
- webView = webkit_web_view_new();
- g_object_ref_sink(webView);
-
- g_signal_connect(webView, "notify::load-status",
- G_CALLBACK(notify_load_status_cb), loop);
-
- gtk_container_add(GTK_CONTAINER(scrolledWindow), webView);
-
- mainFrame = webkit_web_view_get_main_frame(WEBKIT_WEB_VIEW(webView));
-
- /* Test we correctly apply policy for not having scrollbars; This
- * case is special, because we turn the policy from NEVER to
- * AUTOMATIC, since we cannot easily represent the same thing
- * using GtkScrolledWindow */
- webkit_web_view_load_html_string(WEBKIT_WEB_VIEW(webView),
- "<html><body>WebKit!</body><script>document.getElementsByTagName('body')[0].style.overflow = 'hidden';</script></html>",
- "file://");
-
- g_main_loop_run(loop);
-
- gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(scrolledWindow),
- &horizontalPolicy, &verticalPolicy);
-
- g_assert(horizontalPolicy == GTK_POLICY_AUTOMATIC);
- g_assert(verticalPolicy == GTK_POLICY_AUTOMATIC);
-
- g_assert(GTK_POLICY_NEVER == webkit_web_frame_get_horizontal_scrollbar_policy(mainFrame));
- g_assert(GTK_POLICY_NEVER == webkit_web_frame_get_vertical_scrollbar_policy(mainFrame));
-
- /* Test we correctly apply policy for always having scrollbars */
- webkit_web_view_load_html_string(WEBKIT_WEB_VIEW(webView),
- "<html><body>WebKit!</body><script>document.getElementsByTagName('body')[0].style.overflow = 'scroll';</script></html>",
- "file://");
-
- g_main_loop_run(loop);
-
- gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(scrolledWindow),
- &horizontalPolicy, &verticalPolicy);
-
- g_assert(horizontalPolicy == GTK_POLICY_ALWAYS);
- g_assert(verticalPolicy == GTK_POLICY_ALWAYS);
-
- g_assert(horizontalPolicy == webkit_web_frame_get_horizontal_scrollbar_policy(mainFrame));
- g_assert(verticalPolicy == webkit_web_frame_get_vertical_scrollbar_policy(mainFrame));
-
- /* Test we correctly apply policy for having scrollbars when needed */
- webkit_web_view_load_html_string(WEBKIT_WEB_VIEW(webView),
- "<html><body>WebKit!</body><script>document.getElementsByTagName('body')[0].style.overflow = 'auto';</script></html>",
- "file://");
-
- g_main_loop_run(loop);
-
- gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(scrolledWindow),
- &horizontalPolicy, &verticalPolicy);
-
- g_assert(horizontalPolicy == GTK_POLICY_AUTOMATIC);
- g_assert(verticalPolicy == GTK_POLICY_AUTOMATIC);
-
- g_assert(horizontalPolicy == webkit_web_frame_get_horizontal_scrollbar_policy(mainFrame));
- g_assert(verticalPolicy == webkit_web_frame_get_vertical_scrollbar_policy(mainFrame));
-
- g_object_unref(webView);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/window/scrollbar_policy", test_webkit_window_scrollbar_policy);
- return g_test_run ();
-}
diff --git a/Tools/TestWebKitAPI/TestsController.cpp b/Tools/TestWebKitAPI/TestsController.cpp
index 29dcc714e..913305d7b 100644
--- a/Tools/TestWebKitAPI/TestsController.cpp
+++ b/Tools/TestWebKitAPI/TestsController.cpp
@@ -30,9 +30,33 @@
namespace TestWebKitAPI {
-TestsController& TestsController::shared()
+class Printer : public ::testing::EmptyTestEventListener {
+ virtual void OnTestPartResult(const ::testing::TestPartResult& test_part_result)
+ {
+ if (!test_part_result.failed())
+ return;
+
+ std::stringstream stream;
+ stream << "\n" << test_part_result.file_name() << ":" << test_part_result.line_number() << "\n" << test_part_result.summary() << "\n\n";
+ failures += stream.str();
+ }
+
+ virtual void OnTestEnd(const ::testing::TestInfo& test_info)
+ {
+ if (test_info.result()->Passed())
+ std::cout << "**PASS** " << test_info.test_case_name() << "." << test_info.name() << "\n";
+ else
+ std::cout << "**FAIL** " << test_info.test_case_name() << "." << test_info.name() << "\n" << failures;
+
+ failures = std::string();
+ }
+
+ std::string failures;
+};
+
+TestsController& TestsController::singleton()
{
- static TestsController& shared = *new TestsController;
+ static NeverDestroyed<TestsController> shared;
return shared;
}
@@ -48,6 +72,11 @@ TestsController::TestsController()
bool TestsController::run(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
+
+ ::testing::TestEventListeners& listeners = ::testing::UnitTest::GetInstance()->listeners();
+ delete listeners.Release(listeners.default_result_printer());
+ listeners.Append(new Printer);
+
return !RUN_ALL_TESTS();
}
diff --git a/Tools/TestWebKitAPI/TestsController.h b/Tools/TestWebKitAPI/TestsController.h
index c73e3ac4d..ea8496853 100644
--- a/Tools/TestWebKitAPI/TestsController.h
+++ b/Tools/TestWebKitAPI/TestsController.h
@@ -26,17 +26,21 @@
#ifndef TestsController_h
#define TestsController_h
+#include <wtf/NeverDestroyed.h>
+
namespace TestWebKitAPI {
class TestsController {
public:
- static TestsController& shared();
+ static TestsController& singleton();
bool run(int argc, char** argv);
private:
TestsController();
~TestsController();
+
+ friend class WTF::NeverDestroyed<TestsController>;
};
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/WKWebViewConfigurationExtras.h b/Tools/TestWebKitAPI/WKWebViewConfigurationExtras.h
new file mode 100644
index 000000000..782da85d4
--- /dev/null
+++ b/Tools/TestWebKitAPI/WKWebViewConfigurationExtras.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#import <WebKit/WKWebViewConfiguration.h>
+
+#if WK_API_ENABLED
+
+@interface WKWebViewConfiguration (TestWebKitAPIExtras)
++ (instancetype)testwebkitapi_configurationWithTestPlugInClassName:(NSString *)className;
+@end
+
+#endif // WK_API_ENABLED
diff --git a/Tools/TestWebKitAPI/config.h b/Tools/TestWebKitAPI/config.h
index 0fb19e1c3..2a62583bc 100644
--- a/Tools/TestWebKitAPI/config.h
+++ b/Tools/TestWebKitAPI/config.h
@@ -23,16 +23,11 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H
-#ifdef BUILDING_WITH_CMAKE
+#if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H && defined(BUILDING_WITH_CMAKE)
#include "cmakeconfig.h"
-#else
-#include "autotoolsconfig.h"
-#endif
#endif
-#include <wtf/Platform.h>
-#include <wtf/ExportMacros.h>
+#include <WebCore/PlatformExportMacros.h>
#include <runtime/JSExportMacros.h>
#if defined(__APPLE__) && __APPLE__
@@ -52,16 +47,16 @@
#endif
#if PLATFORM(WIN_CAIRO)
-#undef WTF_USE_CG
-#define WTF_USE_CAIRO 1
-#define WTF_USE_CURL 1
+#undef USE_CG
+#define USE_CAIRO 1
+#define USE_CURL 1
#ifndef _WINSOCKAPI_
#define _WINSOCKAPI_ // Prevent inclusion of winsock.h in windows.h
#endif
-#elif !OS(WINCE)
-#define WTF_USE_CG 1
-#undef WTF_USE_CAIRO
-#undef WTF_USE_CURL
+#else
+#define USE_CG 1
+#undef USE_CAIRO
+#undef USE_CURL
#endif
#endif // PLATFORM(WIN)
@@ -69,7 +64,7 @@
#include <stdint.h>
#if !PLATFORM(IOS) && !PLATFORM(WIN) && !(PLATFORM(GTK) && !defined(BUILDING_WEBKIT2__))
-#include <WebKit2/WebKit2_C.h>
+#include <WebKit/WebKit2_C.h>
#endif
#ifdef __clang__
@@ -87,6 +82,13 @@
#pragma clang diagnostic pop
#endif
-#if PLATFORM(MAC) && defined(__OBJC__)
+#if PLATFORM(COCOA) && defined(__OBJC__)
+// FIXME: Get Cocoa tests working with CMake on Mac.
+#if !defined(BUILDING_WITH_CMAKE)
#import <WebKit/WebKit.h>
#endif
+#endif
+
+#if !PLATFORM(IOS)
+#define WK_HAVE_C_SPI 1
+#endif
diff --git a/Tools/TestWebKitAPI/gtk/PlatformUtilitiesGtk.cpp b/Tools/TestWebKitAPI/gtk/PlatformUtilitiesGtk.cpp
index ee65dcab2..f7b231fcc 100644
--- a/Tools/TestWebKitAPI/gtk/PlatformUtilitiesGtk.cpp
+++ b/Tools/TestWebKitAPI/gtk/PlatformUtilitiesGtk.cpp
@@ -27,8 +27,8 @@
#include "PlatformUtilities.h"
#include <gtk/gtk.h>
-#include <wtf/gobject/GRefPtr.h>
-#include <wtf/gobject/GUniquePtr.h>
+#include <wtf/glib/GRefPtr.h>
+#include <wtf/glib/GUniquePtr.h>
namespace TestWebKitAPI {
namespace Util {
@@ -68,7 +68,7 @@ static char* getFilenameFromEnvironmentVariableAsUTF8(const char* variableName)
WKStringRef createInjectedBundlePath()
{
GUniquePtr<char> injectedBundlePath(getFilenameFromEnvironmentVariableAsUTF8("TEST_WEBKIT_API_WEBKIT2_INJECTED_BUNDLE_PATH"));
- GUniquePtr<char> injectedBundleFilename(g_build_filename(injectedBundlePath.get(), "libTestWebKitAPIInjectedBundle.la", nullptr));
+ GUniquePtr<char> injectedBundleFilename(g_build_filename(injectedBundlePath.get(), "libTestWebKitAPIInjectedBundle.so", nullptr));
return WKStringCreateWithUTF8CString(injectedBundleFilename.get());
}
diff --git a/Tools/TestWebKitAPI/gtk/PlatformWebViewGtk.cpp b/Tools/TestWebKitAPI/gtk/PlatformWebViewGtk.cpp
index 03160419e..b37ced74e 100644
--- a/Tools/TestWebKitAPI/gtk/PlatformWebViewGtk.cpp
+++ b/Tools/TestWebKitAPI/gtk/PlatformWebViewGtk.cpp
@@ -27,18 +27,35 @@
#include "PlatformWebView.h"
#include <WebCore/GUniquePtrGtk.h>
+#include <WebKit/WKRetainPtr.h>
+#include <WebKit/WKView.h>
#include <gtk/gtk.h>
-#include <wtf/gobject/GUniquePtr.h>
+#include <wtf/glib/GUniquePtr.h>
namespace TestWebKitAPI {
PlatformWebView::PlatformWebView(WKContextRef contextRef, WKPageGroupRef pageGroupRef)
{
- m_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- m_view = WKViewCreate(contextRef, pageGroupRef);
- gtk_container_add(GTK_CONTAINER(m_window), GTK_WIDGET(m_view));
- gtk_widget_show(GTK_WIDGET(m_view));
- gtk_widget_show(m_window);
+ WKRetainPtr<WKPageConfigurationRef> configuration = adoptWK(WKPageConfigurationCreate());
+ WKPageConfigurationSetContext(configuration.get(), contextRef);
+ WKPageConfigurationSetPageGroup(configuration.get(), pageGroupRef);
+
+ initialize(configuration.get());
+}
+
+PlatformWebView::PlatformWebView(WKPageConfigurationRef configuration)
+{
+ initialize(configuration);
+}
+
+PlatformWebView::PlatformWebView(WKPageRef relatedPage)
+{
+ WKRetainPtr<WKPageConfigurationRef> configuration = adoptWK(WKPageConfigurationCreate());
+ WKPageConfigurationSetContext(configuration.get(), WKPageGetContext(relatedPage));
+ WKPageConfigurationSetPageGroup(configuration.get(), WKPageGetPageGroup(relatedPage));
+ WKPageConfigurationSetRelatedPage(configuration.get(), relatedPage);
+
+ initialize(configuration.get());
}
PlatformWebView::~PlatformWebView()
@@ -46,6 +63,15 @@ PlatformWebView::~PlatformWebView()
gtk_widget_destroy(m_window);
}
+void PlatformWebView::initialize(WKPageConfigurationRef configuration)
+{
+ m_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ m_view = WKViewCreate(configuration);
+ gtk_container_add(GTK_CONTAINER(m_window), GTK_WIDGET(m_view));
+ gtk_widget_show(GTK_WIDGET(m_view));
+ gtk_widget_show(m_window);
+}
+
WKPageRef PlatformWebView::page() const
{
return WKViewGetPage(m_view);
diff --git a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/LoadTrackingTest.cpp b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/LoadTrackingTest.cpp
index 211fa8b82..e78ce45ee 100644
--- a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/LoadTrackingTest.cpp
+++ b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/LoadTrackingTest.cpp
@@ -50,9 +50,15 @@ static void loadChangedCallback(WebKitWebView* webView, WebKitLoadEvent loadEven
break;
}
case WEBKIT_LOAD_FINISHED:
- g_assert(!webkit_web_view_is_loading(webView));
- if (!test->m_loadFailed)
+ if (!test->m_loadFailed) {
+ g_assert(!webkit_web_view_is_loading(webView));
g_assert_cmpstr(test->m_activeURI.data(), ==, webkit_web_view_get_uri(webView));
+ } else if (!g_error_matches(test->m_error.get(), WEBKIT_NETWORK_ERROR, WEBKIT_NETWORK_ERROR_CANCELLED)) {
+ // When a new load is started before the previous one has finished, we receive the load-finished signal
+ // of the ongoing load while we already have a provisional URL for the new load. This is the only case
+ // where isloading is true when the load has finished.
+ g_assert(!webkit_web_view_is_loading(webView));
+ }
test->loadFinished();
break;
default:
@@ -63,19 +69,24 @@ static void loadChangedCallback(WebKitWebView* webView, WebKitLoadEvent loadEven
static void loadFailedCallback(WebKitWebView* webView, WebKitLoadEvent loadEvent, const char* failingURI, GError* error, LoadTrackingTest* test)
{
test->m_loadFailed = true;
+
+ g_assert(error);
test->m_error.reset(g_error_copy(error));
+ if (!g_error_matches(error, WEBKIT_NETWORK_ERROR, WEBKIT_NETWORK_ERROR_CANCELLED)) {
+ // When a new load is started before the previous one has finished, we receive the load-failed signal
+ // of the ongoing load while we already have a provisional URL for the new load. This is the only case
+ // where is-loading is true when the load has failed.
+ g_assert(!webkit_web_view_is_loading(webView));
+ }
+
switch (loadEvent) {
case WEBKIT_LOAD_STARTED:
- g_assert(!webkit_web_view_is_loading(webView));
- g_assert_cmpstr(test->m_activeURI.data(), ==, webkit_web_view_get_uri(webView));
- g_assert(error);
+ g_assert_cmpstr(test->m_activeURI.data(), ==, failingURI);
test->provisionalLoadFailed(failingURI, error);
break;
case WEBKIT_LOAD_COMMITTED:
- g_assert(!webkit_web_view_is_loading(webView));
g_assert_cmpstr(test->m_activeURI.data(), ==, webkit_web_view_get_uri(webView));
- g_assert(error);
test->loadFailed(failingURI, error);
break;
default:
@@ -83,6 +94,16 @@ static void loadFailedCallback(WebKitWebView* webView, WebKitLoadEvent loadEvent
}
}
+static gboolean loadFailedWithTLSErrorsCallback(WebKitWebView* webView, const char* failingURI, GTlsCertificate* certificate, GTlsCertificateFlags tlsErrors, LoadTrackingTest* test)
+{
+ test->m_loadFailed = true;
+ g_assert(!webkit_web_view_is_loading(webView));
+ g_assert_cmpstr(test->m_activeURI.data(), ==, failingURI);
+ g_assert(G_IS_TLS_CERTIFICATE(certificate));
+ g_assert(tlsErrors);
+ return test->loadFailedWithTLSErrors(failingURI, certificate, tlsErrors);
+}
+
static void estimatedProgressChangedCallback(GObject*, GParamSpec*, LoadTrackingTest* test)
{
test->estimatedProgressChanged();
@@ -94,6 +115,7 @@ LoadTrackingTest::LoadTrackingTest()
{
g_signal_connect(m_webView, "load-changed", G_CALLBACK(loadChangedCallback), this);
g_signal_connect(m_webView, "load-failed", G_CALLBACK(loadFailedCallback), this);
+ g_signal_connect(m_webView, "load-failed-with-tls-errors", G_CALLBACK(loadFailedWithTLSErrorsCallback), this);
g_signal_connect(m_webView, "notify::estimated-load-progress", G_CALLBACK(estimatedProgressChangedCallback), this);
g_assert(!webkit_web_view_get_uri(m_webView));
@@ -143,6 +165,12 @@ void LoadTrackingTest::loadFailed(const gchar* failingURI, GError* error)
m_loadEvents.append(LoadFailed);
}
+bool LoadTrackingTest::loadFailedWithTLSErrors(const gchar* /*failingURI*/, GTlsCertificate*, GTlsCertificateFlags)
+{
+ m_loadEvents.append(LoadFailedWithTLSErrors);
+ return false;
+}
+
void LoadTrackingTest::estimatedProgressChanged()
{
double progress = webkit_web_view_get_estimated_load_progress(m_webView);
@@ -152,56 +180,57 @@ void LoadTrackingTest::estimatedProgressChanged()
void LoadTrackingTest::loadURI(const char* uri)
{
- m_loadEvents.clear();
- m_estimatedProgress = 0;
- m_error.reset();
+ reset();
WebViewTest::loadURI(uri);
}
void LoadTrackingTest::loadHtml(const char* html, const char* baseURI)
{
- m_loadEvents.clear();
- m_estimatedProgress = 0;
- m_error.reset();
+ reset();
WebViewTest::loadHtml(html, baseURI);
}
void LoadTrackingTest::loadPlainText(const char* plainText)
{
- m_loadEvents.clear();
- m_estimatedProgress = 0;
- m_error.reset();
+ reset();
WebViewTest::loadPlainText(plainText);
}
+void LoadTrackingTest::loadBytes(GBytes* bytes, const char* mimeType, const char* encoding, const char* baseURI)
+{
+ reset();
+ WebViewTest::loadBytes(bytes, mimeType, encoding, baseURI);
+}
+
void LoadTrackingTest::loadRequest(WebKitURIRequest* request)
{
- m_loadEvents.clear();
- m_estimatedProgress = 0;
- m_error.reset();
+ reset();
WebViewTest::loadRequest(request);
}
void LoadTrackingTest::reload()
{
- m_loadEvents.clear();
- m_estimatedProgress = 0;
- m_error.reset();
+ reset();
webkit_web_view_reload(m_webView);
}
void LoadTrackingTest::goBack()
{
- m_loadEvents.clear();
- m_estimatedProgress = 0;
- m_error.reset();
+ reset();
WebViewTest::goBack();
}
void LoadTrackingTest::goForward()
{
+ reset();
+ WebViewTest::goForward();
+}
+
+void LoadTrackingTest::reset()
+{
+ m_runLoadUntilCompletion = false;
+ m_loadFailed = false;
m_loadEvents.clear();
m_estimatedProgress = 0;
m_error.reset();
- WebViewTest::goForward();
}
diff --git a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/LoadTrackingTest.h b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/LoadTrackingTest.h
index d0ed1e57f..d6f3129b0 100644
--- a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/LoadTrackingTest.h
+++ b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/LoadTrackingTest.h
@@ -34,6 +34,7 @@ public:
virtual void provisionalLoadStarted();
virtual void provisionalLoadReceivedServerRedirect();
virtual void provisionalLoadFailed(const gchar* failingURI, GError*);
+ virtual bool loadFailedWithTLSErrors(const gchar* failingURI, GTlsCertificate*, GTlsCertificateFlags);
virtual void loadCommitted();
virtual void loadFinished();
virtual void loadFailed(const char* failingURI, GError*);
@@ -43,9 +44,11 @@ public:
void loadHtml(const char* html, const char* baseURI);
void loadPlainText(const char* plainText);
void loadRequest(WebKitURIRequest*);
+ void loadBytes(GBytes*, const char* mimeType, const char* encoding, const char* baseURI);
void reload();
void goBack();
void goForward();
+ void reset();
void setRedirectURI(const char* uri) { m_redirectURI = uri; }
@@ -55,7 +58,8 @@ public:
ProvisionalLoadFailed,
LoadCommitted,
LoadFinished,
- LoadFailed
+ LoadFailed,
+ LoadFailedWithTLSErrors
};
bool m_runLoadUntilCompletion;
bool m_loadFailed;
diff --git a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.cpp b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.cpp
index 61331a3d3..80809400d 100644
--- a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.cpp
+++ b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.cpp
@@ -22,12 +22,19 @@
#include <glib/gstdio.h>
#include <gtk/gtk.h>
-#include <webkit2/webkit2.h>
-#include <wtf/gobject/GUniquePtr.h>
+
+uint32_t Test::s_webExtensionID = 0;
void beforeAll();
void afterAll();
+static GUniquePtr<char> testDataDirectory(g_dir_make_tmp("WebKit2GtkTests-XXXXXX", nullptr));
+
+const char* Test::dataDirectory()
+{
+ return testDataDirectory.get();
+}
+
static void registerGResource(void)
{
GUniquePtr<char> resourcesPath(g_build_filename(WEBKIT_EXEC_PATH, "TestWebKitAPI", "WebKit2Gtk", "resources", "webkit2gtk-tests-resources.gresource", nullptr));
@@ -45,7 +52,10 @@ static void removeNonEmptyDirectory(const char* directoryPath)
const char* fileName;
while ((fileName = g_dir_read_name(directory))) {
GUniquePtr<char> filePath(g_build_filename(directoryPath, fileName, nullptr));
- g_unlink(filePath.get());
+ if (g_file_test(filePath.get(), G_FILE_TEST_IS_DIR))
+ removeNonEmptyDirectory(filePath.get());
+ else
+ g_unlink(filePath.get());
}
g_dir_close(directory);
g_rmdir(directoryPath);
@@ -66,15 +76,12 @@ int main(int argc, char** argv)
registerGResource();
- GUniquePtr<char> diskCacheTempDirectory(g_dir_make_tmp("WebKit2TestsDiskCache-XXXXXX", 0));
- g_assert(diskCacheTempDirectory.get());
- webkit_web_context_set_disk_cache_directory(webkit_web_context_get_default(), diskCacheTempDirectory.get());
-
beforeAll();
int returnValue = g_test_run();
afterAll();
- removeNonEmptyDirectory(diskCacheTempDirectory.get());
+ removeNonEmptyDirectory(testDataDirectory.get());
return returnValue;
}
+
diff --git a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.h b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.h
index 9fab0b2ff..6054fe09d 100644
--- a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.h
+++ b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.h
@@ -22,8 +22,10 @@
#include <cairo.h>
#include <glib-object.h>
+#include <webkit2/webkit2.h>
#include <wtf/HashSet.h>
-#include <wtf/gobject/GUniquePtr.h>
+#include <wtf/glib/GRefPtr.h>
+#include <wtf/glib/GUniquePtr.h>
#include <wtf/text/CString.h>
#define MAKE_GLIB_TEST_FIXTURE(ClassName) \
@@ -56,8 +58,33 @@ class Test {
public:
MAKE_GLIB_TEST_FIXTURE(Test);
+ static const char* dataDirectory();
+
+ static void initializeWebExtensionsCallback(WebKitWebContext* context, Test* test)
+ {
+ test->initializeWebExtensions();
+ }
+
+ Test()
+ {
+ GUniquePtr<char> localStorageDirectory(g_build_filename(dataDirectory(), "local-storage", nullptr));
+ GUniquePtr<char> indexedDBDirectory(g_build_filename(dataDirectory(), "indexeddb", nullptr));
+ GUniquePtr<char> diskCacheDirectory(g_build_filename(dataDirectory(), "disk-cache", nullptr));
+ GUniquePtr<char> applicationCacheDirectory(g_build_filename(dataDirectory(), "appcache", nullptr));
+ GUniquePtr<char> webSQLDirectory(g_build_filename(dataDirectory(), "websql", nullptr));
+ GRefPtr<WebKitWebsiteDataManager> websiteDataManager = adoptGRef(webkit_website_data_manager_new(
+ "local-storage-directory", localStorageDirectory.get(), "indexeddb-directory", indexedDBDirectory.get(),
+ "disk-cache-directory", diskCacheDirectory.get(), "offline-application-cache-directory", applicationCacheDirectory.get(),
+ "websql-directory", webSQLDirectory.get(), nullptr));
+
+ m_webContext = adoptGRef(webkit_web_context_new_with_website_data_manager(websiteDataManager.get()));
+ g_signal_connect(m_webContext.get(), "initialize-web-extensions", G_CALLBACK(initializeWebExtensionsCallback), this);
+ }
+
~Test()
{
+ g_signal_handlers_disconnect_matched(m_webContext.get(), G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, this);
+ m_webContext = nullptr;
if (m_watchedObjects.isEmpty())
return;
@@ -70,6 +97,12 @@ public:
g_assert(m_watchedObjects.isEmpty());
}
+ virtual void initializeWebExtensions()
+ {
+ webkit_web_context_set_web_extensions_directory(m_webContext.get(), WEBKIT_TEST_WEB_EXTENSIONS_DIR);
+ webkit_web_context_set_web_extensions_initialization_user_data(m_webContext.get(), g_variant_new_uint32(++s_webExtensionID));
+ }
+
static void objectFinalized(Test* test, GObject* finalizedObject)
{
test->m_watchedObjects.remove(finalizedObject);
@@ -81,16 +114,24 @@ public:
g_object_weak_ref(object, reinterpret_cast<GWeakNotify>(objectFinalized), this);
}
- static CString getWebKit1TestResoucesDir()
- {
- GUniquePtr<char> resourcesDir(g_build_filename(WEBKIT_SRC_DIR, "Tools", "TestWebKitAPI", "Tests", "WebKitGtk", "resources", nullptr));
- return resourcesDir.get();
- }
- static CString getResourcesDir()
+ enum ResourcesDir {
+ WebKit2GTKResources,
+ WebKit2Resources,
+ };
+
+ static CString getResourcesDir(ResourcesDir resourcesDir = WebKit2GTKResources)
{
- GUniquePtr<char> resourcesDir(g_build_filename(WEBKIT_SRC_DIR, "Tools", "TestWebKitAPI", "Tests", "WebKit2Gtk", "resources", nullptr));
- return resourcesDir.get();
+ switch (resourcesDir) {
+ case WebKit2GTKResources: {
+ GUniquePtr<char> resourcesDir(g_build_filename(WEBKIT_SRC_DIR, "Tools", "TestWebKitAPI", "Tests", "WebKit2Gtk", "resources", nullptr));
+ return resourcesDir.get();
+ }
+ case WebKit2Resources: {
+ GUniquePtr<char> resourcesDir(g_build_filename(WEBKIT_SRC_DIR, "Tools", "TestWebKitAPI", "Tests", "WebKit2", nullptr));
+ return resourcesDir.get();
+ }
+ }
}
void addLogFatalFlag(unsigned flag)
@@ -119,6 +160,8 @@ public:
}
HashSet<GObject*> m_watchedObjects;
+ GRefPtr<WebKitWebContext> m_webContext;
+ static uint32_t s_webExtensionID;
};
#endif // TestMain_h
diff --git a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.cpp b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.cpp
index 35bcf1bd6..1cf241461 100644
--- a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.cpp
+++ b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.cpp
@@ -20,7 +20,7 @@
#include "config.h"
#include "WebKitTestBus.h"
-#include <wtf/gobject/GUniquePtr.h>
+#include <wtf/glib/GUniquePtr.h>
#include <wtf/text/WTFString.h>
WebKitTestBus::WebKitTestBus()
diff --git a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.h b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.h
index b9f856b27..03bcc3ae5 100644
--- a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.h
+++ b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.h
@@ -21,7 +21,7 @@
#define WebKitTestBus_h
#include <gio/gio.h>
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
#include <wtf/text/CString.h>
class WebKitTestBus {
diff --git a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestServer.cpp b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestServer.cpp
index 8736771fa..de9466c39 100644
--- a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestServer.cpp
+++ b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestServer.cpp
@@ -21,13 +21,19 @@
#include "WebKitTestServer.h"
#include "TestMain.h"
-#include <wtf/gobject/GUniquePtr.h>
+#include <wtf/Threading.h>
+#include <wtf/glib/GUniquePtr.h>
-WebKitTestServer::WebKitTestServer(ServerType type)
+WebKitTestServer::WebKitTestServer(ServerOptions options)
{
+ if (options & ServerRunInThread) {
+ WTF::initializeThreading();
+ m_queue = WorkQueue::create("WebKitTestServer");
+ }
+
GUniquePtr<char> sslCertificateFile;
GUniquePtr<char> sslKeyFile;
- if (type == ServerHTTPS) {
+ if (options & ServerHTTPS) {
CString resourcesDir = Test::getResourcesDir();
sslCertificateFile.reset(g_build_filename(resourcesDir.data(), "test-cert.pem", NULL));
sslKeyFile.reset(g_build_filename(resourcesDir.data(), "test-key.pem", NULL));
@@ -37,9 +43,10 @@ WebKitTestServer::WebKitTestServer(ServerType type)
soup_address_resolve_sync(address.get(), 0);
m_soupServer = adoptGRef(soup_server_new(SOUP_SERVER_INTERFACE, address.get(),
+ SOUP_SERVER_ASYNC_CONTEXT, m_queue ? m_queue->runLoop().mainContext() : nullptr,
SOUP_SERVER_SSL_CERT_FILE, sslCertificateFile.get(),
SOUP_SERVER_SSL_KEY_FILE, sslKeyFile.get(), nullptr));
- m_baseURI = type == ServerHTTPS ? soup_uri_new("https://127.0.0.1/") : soup_uri_new("http://127.0.0.1/");
+ m_baseURI = options & ServerHTTPS ? soup_uri_new("https://127.0.0.1/") : soup_uri_new("http://127.0.0.1/");
soup_uri_set_port(m_baseURI, soup_server_get_port(m_soupServer.get()));
}
@@ -50,8 +57,15 @@ WebKitTestServer::~WebKitTestServer()
void WebKitTestServer::run(SoupServerCallback serverCallback)
{
- soup_server_run_async(m_soupServer.get());
- soup_server_add_handler(m_soupServer.get(), 0, serverCallback, 0, 0);
+ if (m_queue) {
+ m_queue->dispatch([this, serverCallback] {
+ soup_server_run_async(m_soupServer.get());
+ soup_server_add_handler(m_soupServer.get(), nullptr, serverCallback, nullptr, nullptr);
+ });
+ } else {
+ soup_server_run_async(m_soupServer.get());
+ soup_server_add_handler(m_soupServer.get(), nullptr, serverCallback, nullptr, nullptr);
+ }
}
CString WebKitTestServer::getURIForPath(const char* path)
diff --git a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestServer.h b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestServer.h
index 502f7fad0..58f019fab 100644
--- a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestServer.h
+++ b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestServer.h
@@ -22,18 +22,20 @@
#include <libsoup/soup.h>
#include <webkit2/webkit2.h>
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/WorkQueue.h>
+#include <wtf/glib/GRefPtr.h>
#include <wtf/text/CString.h>
class WebKitTestServer {
public:
- enum ServerType {
- ServerHTTP,
- ServerHTTPS
+ enum ServerOptions {
+ ServerHTTP = 0,
+ ServerHTTPS = 1 << 1,
+ ServerRunInThread = 1 << 2,
};
- WebKitTestServer(ServerType = ServerHTTP);
+ WebKitTestServer(ServerOptions = ServerHTTP);
virtual ~WebKitTestServer();
SoupURI* baseURI() { return m_baseURI; }
@@ -44,6 +46,7 @@ public:
private:
GRefPtr<SoupServer> m_soupServer;
SoupURI* m_baseURI;
+ RefPtr<WorkQueue> m_queue;
};
#endif // WebKitTestServer_h
diff --git a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.cpp b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.cpp
index f08bb4694..b0217ae2b 100644
--- a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.cpp
+++ b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.cpp
@@ -24,15 +24,17 @@
#include <JavaScriptCore/JSRetainPtr.h>
#include <WebCore/GUniquePtrGtk.h>
-WebViewTest::WebViewTest()
- : m_webView(WEBKIT_WEB_VIEW(g_object_ref_sink(webkit_web_view_new())))
- , m_mainLoop(g_main_loop_new(0, TRUE))
- , m_parentWindow(0)
- , m_javascriptResult(0)
+WebViewTest::WebViewTest(WebKitUserContentManager* userContentManager)
+ : m_webView(WEBKIT_WEB_VIEW(g_object_ref_sink(g_object_new(WEBKIT_TYPE_WEB_VIEW, "web-context", m_webContext.get(), "user-content-manager", userContentManager, nullptr))))
+ , m_mainLoop(g_main_loop_new(nullptr, TRUE))
+ , m_parentWindow(nullptr)
+ , m_javascriptResult(nullptr)
, m_resourceDataSize(0)
- , m_surface(0)
+ , m_surface(nullptr)
+ , m_expectedWebProcessCrash(false)
{
assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_webView));
+ g_signal_connect(m_webView, "web-process-crashed", G_CALLBACK(WebViewTest::webProcessCrashed), this);
}
WebViewTest::~WebViewTest()
@@ -47,10 +49,22 @@ WebViewTest::~WebViewTest()
g_main_loop_unref(m_mainLoop);
}
+gboolean WebViewTest::webProcessCrashed(WebKitWebView*, WebViewTest* test)
+{
+ if (test->m_expectedWebProcessCrash) {
+ test->m_expectedWebProcessCrash = false;
+ return FALSE;
+ }
+ g_assert_not_reached();
+ return TRUE;
+}
+
void WebViewTest::loadURI(const char* uri)
{
m_activeURI = uri;
webkit_web_view_load_uri(m_webView, uri);
+ g_assert(webkit_web_view_is_loading(m_webView));
+ g_assert_cmpstr(webkit_web_view_get_uri(m_webView), ==, m_activeURI.data());
}
void WebViewTest::loadHtml(const char* html, const char* baseURI)
@@ -60,29 +74,49 @@ void WebViewTest::loadHtml(const char* html, const char* baseURI)
else
m_activeURI = baseURI;
webkit_web_view_load_html(m_webView, html, baseURI);
+ g_assert(webkit_web_view_is_loading(m_webView));
+ g_assert_cmpstr(webkit_web_view_get_uri(m_webView), ==, m_activeURI.data());
}
void WebViewTest::loadPlainText(const char* plainText)
{
m_activeURI = "about:blank";
webkit_web_view_load_plain_text(m_webView, plainText);
+ g_assert(webkit_web_view_is_loading(m_webView));
+ g_assert_cmpstr(webkit_web_view_get_uri(m_webView), ==, m_activeURI.data());
+}
+
+void WebViewTest::loadBytes(GBytes* bytes, const char* mimeType, const char* encoding, const char* baseURI)
+{
+ if (!baseURI)
+ m_activeURI = "about:blank";
+ else
+ m_activeURI = baseURI;
+ webkit_web_view_load_bytes(m_webView, bytes, mimeType, encoding, baseURI);
+ g_assert(webkit_web_view_is_loading(m_webView));
+ g_assert_cmpstr(webkit_web_view_get_uri(m_webView), ==, m_activeURI.data());
}
void WebViewTest::loadRequest(WebKitURIRequest* request)
{
m_activeURI = webkit_uri_request_get_uri(request);
webkit_web_view_load_request(m_webView, request);
+ g_assert(webkit_web_view_is_loading(m_webView));
+ g_assert_cmpstr(webkit_web_view_get_uri(m_webView), ==, m_activeURI.data());
}
void WebViewTest::loadAlternateHTML(const char* html, const char* contentURI, const char* baseURI)
{
m_activeURI = contentURI;
webkit_web_view_load_alternate_html(m_webView, html, contentURI, baseURI);
+ g_assert(webkit_web_view_is_loading(m_webView));
+ g_assert_cmpstr(webkit_web_view_get_uri(m_webView), ==, m_activeURI.data());
}
void WebViewTest::goBack()
{
- if (webkit_web_view_can_go_back(m_webView)) {
+ bool canGoBack = webkit_web_view_can_go_back(m_webView);
+ if (canGoBack) {
WebKitBackForwardList* list = webkit_web_view_get_back_forward_list(m_webView);
WebKitBackForwardListItem* item = webkit_back_forward_list_get_nth_item(list, -1);
m_activeURI = webkit_back_forward_list_item_get_original_uri(item);
@@ -90,11 +124,16 @@ void WebViewTest::goBack()
// Call go_back even when can_go_back returns FALSE to check nothing happens.
webkit_web_view_go_back(m_webView);
+ if (canGoBack) {
+ g_assert(webkit_web_view_is_loading(m_webView));
+ g_assert_cmpstr(webkit_web_view_get_uri(m_webView), ==, m_activeURI.data());
+ }
}
void WebViewTest::goForward()
{
- if (webkit_web_view_can_go_forward(m_webView)) {
+ bool canGoForward = webkit_web_view_can_go_forward(m_webView);
+ if (canGoForward) {
WebKitBackForwardList* list = webkit_web_view_get_back_forward_list(m_webView);
WebKitBackForwardListItem* item = webkit_back_forward_list_get_nth_item(list, 1);
m_activeURI = webkit_back_forward_list_item_get_original_uri(item);
@@ -102,12 +141,18 @@ void WebViewTest::goForward()
// Call go_forward even when can_go_forward returns FALSE to check nothing happens.
webkit_web_view_go_forward(m_webView);
+ if (canGoForward) {
+ g_assert(webkit_web_view_is_loading(m_webView));
+ g_assert_cmpstr(webkit_web_view_get_uri(m_webView), ==, m_activeURI.data());
+ }
}
void WebViewTest::goToBackForwardListItem(WebKitBackForwardListItem* item)
{
m_activeURI = webkit_back_forward_list_item_get_original_uri(item);
webkit_web_view_go_to_back_forward_list_item(m_webView, item);
+ g_assert(webkit_web_view_is_loading(m_webView));
+ g_assert_cmpstr(webkit_web_view_get_uri(m_webView), ==, m_activeURI.data());
}
void WebViewTest::quitMainLoop()
@@ -122,15 +167,12 @@ void WebViewTest::quitMainLoopAfterProcessingPendingEvents()
quitMainLoop();
}
-static gboolean quitMainLoopIdleCallback(WebViewTest* test)
-{
- test->quitMainLoop();
- return FALSE;
-}
-
void WebViewTest::wait(double seconds)
{
- g_timeout_add_seconds(seconds, reinterpret_cast<GSourceFunc>(quitMainLoopIdleCallback), this);
+ g_timeout_add(seconds * 1000, [](gpointer userData) -> gboolean {
+ static_cast<WebViewTest*>(userData)->quitMainLoop();
+ return G_SOURCE_REMOVE;
+ }, this);
g_main_loop_run(m_mainLoop);
}
@@ -217,6 +259,16 @@ void WebViewTest::selectAll()
webkit_web_view_execute_editing_command(m_webView, "SelectAll");
}
+bool WebViewTest::isEditable()
+{
+ return webkit_web_view_is_editable(m_webView);
+}
+
+void WebViewTest::setEditable(bool editable)
+{
+ webkit_web_view_set_editable(m_webView, editable);
+}
+
static void resourceGetDataCallback(GObject* object, GAsyncResult* result, gpointer userData)
{
size_t dataSize;
diff --git a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.h b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.h
index 93a78a4d7..3f99d21ec 100644
--- a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.h
+++ b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.h
@@ -28,13 +28,14 @@
class WebViewTest: public Test {
public:
MAKE_GLIB_TEST_FIXTURE(WebViewTest);
- WebViewTest();
+ WebViewTest(WebKitUserContentManager* = nullptr);
virtual ~WebViewTest();
virtual void loadURI(const char* uri);
virtual void loadHtml(const char* html, const char* baseURI);
virtual void loadPlainText(const char* plainText);
virtual void loadRequest(WebKitURIRequest*);
+ virtual void loadBytes(GBytes*, const char* mimeType, const char* encoding, const char* baseURI);
void loadAlternateHTML(const char* html, const char* contentURI, const char* baseURI);
void goBack();
void goForward();
@@ -52,6 +53,9 @@ public:
void selectAll();
const char* mainResourceData(size_t& mainResourceDataSize);
+ bool isEditable();
+ void setEditable(bool);
+
void mouseMoveTo(int x, int y, unsigned mouseModifiers = 0);
void clickMouseButton(int x, int y, unsigned button = 1, unsigned mouseModifiers = 0);
void keyStroke(unsigned keyVal, unsigned keyModifiers = 0);
@@ -70,6 +74,12 @@ public:
bool runWebProcessTest(const char* suiteName, const char* testName);
+ // Prohibit overrides because this is called when the web view is created
+ // in our constructor, before a derived class's vtable is ready.
+ void initializeWebExtensions() override final { Test::initializeWebExtensions(); }
+
+ static gboolean webProcessCrashed(WebKitWebView*, WebViewTest*);
+
WebKitWebView* m_webView;
GMainLoop* m_mainLoop;
CString m_activeURI;
@@ -80,6 +90,7 @@ public:
GUniquePtr<char> m_resourceData;
size_t m_resourceDataSize;
cairo_surface_t* m_surface;
+ bool m_expectedWebProcessCrash;
private:
void doMouseButtonEvent(GdkEventType, int, int, unsigned, unsigned);
diff --git a/Tools/TestWebKitAPI/gtk/main.cpp b/Tools/TestWebKitAPI/gtk/main.cpp
index 1b7fef64f..2c6856595 100644
--- a/Tools/TestWebKitAPI/gtk/main.cpp
+++ b/Tools/TestWebKitAPI/gtk/main.cpp
@@ -32,5 +32,5 @@ int main(int argc, char** argv)
{
gtk_init(&argc, &argv);
- return TestWebKitAPI::TestsController::shared().run(argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE;
+ return TestWebKitAPI::TestsController::singleton().run(argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE;
}
diff --git a/Tools/WebKitTestRunner/CMakeLists.txt b/Tools/WebKitTestRunner/CMakeLists.txt
new file mode 100644
index 000000000..b81377a6d
--- /dev/null
+++ b/Tools/WebKitTestRunner/CMakeLists.txt
@@ -0,0 +1,126 @@
+set(WEBKIT_TESTRUNNER_DIR "${TOOLS_DIR}/WebKitTestRunner")
+set(WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR "${TOOLS_DIR}/WebKitTestRunner/InjectedBundle")
+set(WEBKIT_TESTRUNNER_UISCRIPTCONTEXT_DIR "${TOOLS_DIR}/WebKitTestRunner/UIScriptContext")
+
+file(MAKE_DIRECTORY ${DERIVED_SOURCES_DIR}/InjectedBundle)
+file(MAKE_DIRECTORY ${DERIVED_SOURCES_DIR}/UIScriptContext)
+
+set(WebKitTestRunner_SOURCES
+ ${WEBKIT_TESTRUNNER_DIR}/CyclicRedundancyCheck.cpp
+ ${WEBKIT_TESTRUNNER_DIR}/GeolocationProviderMock.cpp
+ ${WEBKIT_TESTRUNNER_DIR}/Options.cpp
+ ${WEBKIT_TESTRUNNER_DIR}/PixelDumpSupport.cpp
+ ${WEBKIT_TESTRUNNER_DIR}/TestController.cpp
+ ${WEBKIT_TESTRUNNER_DIR}/TestInvocation.cpp
+ ${WEBKIT_TESTRUNNER_DIR}/TestOptions.cpp
+ ${WEBKIT_TESTRUNNER_DIR}/WebNotificationProvider.cpp
+ ${WEBKIT_TESTRUNNER_DIR}/WorkQueueManager.cpp
+ ${WEBKIT_TESTRUNNER_UISCRIPTCONTEXT_DIR}/UIScriptContext.cpp
+ ${WEBKIT_TESTRUNNER_UISCRIPTCONTEXT_DIR}/UIScriptController.cpp
+
+ ${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/Bindings/JSWrapper.cpp
+)
+
+set(WebKitTestRunner_LIBRARIES
+ JavaScriptCore
+ WebCore
+ WebCoreTestSupport
+ WebKit2
+)
+
+set(WebKitTestRunner_INCLUDE_DIRECTORIES
+ ${WEBKIT_TESTRUNNER_DIR}
+ ${WEBKIT_TESTRUNNER_DIR}/InjectedBundle
+ ${WEBKIT_TESTRUNNER_DIR}/InjectedBundle/Bindings
+ ${WEBKIT_TESTRUNNER_DIR}/InjectedBundle/atk
+ ${WEBKIT_TESTRUNNER_UISCRIPTCONTEXT_DIR}
+ ${WEBKIT_TESTRUNNER_UISCRIPTCONTEXT_DIR}/Bindings
+ ${JAVASCRIPTCORE_DIR}
+ ${JAVASCRIPTCORE_DIR}/ForwardingHeaders
+ ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}
+ ${WEBCORE_DIR}/editing
+ ${WEBCORE_DIR}/platform
+ ${WEBCORE_DIR}/platform/graphics
+ ${WEBCORE_DIR}/platform/graphics/harfbuzz
+ ${WEBCORE_DIR}/platform/graphics/harfbuzz/ng
+ ${WEBCORE_DIR}/platform/network
+ ${WEBCORE_DIR}/platform/text
+ ${WEBCORE_DIR}/testing/js
+ ${WEBKIT2_DIR}/Platform/IPC
+ ${WEBKIT2_DIR}/Shared
+ ${WEBKIT2_DIR}/Shared/API/c
+ ${WEBKIT2_DIR}/Shared/Plugins
+ ${WEBKIT2_DIR}/UIProcess
+ ${WEBKIT2_DIR}/UIProcess/API/C/soup
+ ${WEBKIT2_DIR}/WebProcess/InjectedBundle
+ ${WEBKIT2_DIR}/WebProcess/InjectedBundle/API/c
+ ${WTF_DIR}
+ ${DERIVED_SOURCES_DIR}/InjectedBundle
+ ${DERIVED_SOURCES_DIR}/UIScriptContext
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_SOURCE_DIR}/Source
+)
+
+set(WebKitTestRunner_SYSTEM_INCLUDE_DIRECTORIES
+ ${LIBSOUP_INCLUDE_DIRS}
+)
+
+set(WebKitTestRunnerInjectedBundle_SOURCES
+ ${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/AccessibilityController.cpp
+ ${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/AccessibilityTextMarker.cpp
+ ${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/AccessibilityTextMarkerRange.cpp
+ ${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/AccessibilityUIElement.cpp
+ ${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/EventSendingController.cpp
+ ${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/GCController.cpp
+ ${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/InjectedBundle.cpp
+ ${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/InjectedBundleMain.cpp
+ ${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/InjectedBundlePage.cpp
+ ${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/TestRunner.cpp
+ ${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/TextInputController.cpp
+
+ ${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/Bindings/JSWrapper.cpp
+)
+
+set(WebKitTestRunnerInjectedBundle_IDL_FILES
+ "${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/Bindings/AccessibilityController.idl"
+ "${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/Bindings/AccessibilityTextMarker.idl"
+ "${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/Bindings/AccessibilityTextMarkerRange.idl"
+ "${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/Bindings/AccessibilityUIElement.idl"
+ "${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/Bindings/EventSendingController.idl"
+ "${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/Bindings/GCController.idl"
+ "${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/Bindings/TestRunner.idl"
+ "${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/Bindings/TextInputController.idl"
+)
+
+set(WebKitTestRunner_IDL_FILES
+ "${WEBKIT_TESTRUNNER_DIR}/UIScriptContext/Bindings/UIScriptController.idl"
+)
+
+GENERATE_BINDINGS(WebKitTestRunnerInjectedBundle_SOURCES
+ "${WebKitTestRunnerInjectedBundle_IDL_FILES}"
+ "${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/Bindings"
+ "--include=${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/Bindings"
+ "${FEATURE_DEFINES_WITH_SPACE_SEPARATOR}"
+ ${DERIVED_SOURCES_DIR}/InjectedBundle JS TestRunner cpp
+ ${WEBCORE_DIR}/bindings/scripts/IDLAttributes.txt)
+
+GENERATE_BINDINGS(WebKitTestRunner_SOURCES
+ "${WebKitTestRunner_IDL_FILES}"
+ "${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/Bindings"
+ "--include=${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/Bindings"
+ "${FEATURE_DEFINES_WITH_SPACE_SEPARATOR}"
+ ${DERIVED_SOURCES_DIR}/UIScriptContext JS TestRunner cpp
+ ${WEBCORE_DIR}/bindings/scripts/IDLAttributes.txt)
+
+WEBKIT_INCLUDE_CONFIG_FILES_IF_EXISTS()
+
+include_directories(${WebKitTestRunner_INCLUDE_DIRECTORIES})
+include_directories(SYSTEM ${WebKitTestRunner_SYSTEM_INCLUDE_DIRECTORIES})
+
+add_library(TestRunnerInjectedBundle SHARED ${WebKitTestRunnerInjectedBundle_SOURCES})
+target_link_libraries(TestRunnerInjectedBundle ${WebKitTestRunner_LIBRARIES})
+
+add_executable(WebKitTestRunner ${WebKitTestRunner_SOURCES})
+target_link_libraries(WebKitTestRunner ${WebKitTestRunner_LIBRARIES})
+
+add_dependencies(WebKit2 ${ForwardingHeadersForWebKitTestRunner_NAME})
diff --git a/Tools/WebKitTestRunner/DerivedSources.make b/Tools/WebKitTestRunner/DerivedSources.make
new file mode 100644
index 000000000..fe9a077ba
--- /dev/null
+++ b/Tools/WebKitTestRunner/DerivedSources.make
@@ -0,0 +1,62 @@
+# 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.
+
+VPATH = \
+ $(WebKitTestRunner)/InjectedBundle/Bindings \
+ $(WebKitTestRunner)/UIScriptContext/Bindings \
+#
+
+INJECTED_BUNDLE_INTERFACES = \
+ AccessibilityController \
+ AccessibilityTextMarker \
+ AccessibilityTextMarkerRange \
+ AccessibilityUIElement \
+ EventSendingController \
+ GCController \
+ TestRunner \
+ TextInputController \
+#
+
+UICONTEXT_INTERFACES = \
+ UIScriptController \
+#
+
+SCRIPTS = \
+ $(WebCoreScripts)/CodeGenerator.pm \
+ $(WebKitTestRunner)/InjectedBundle/Bindings/CodeGeneratorTestRunner.pm \
+ $(WebCoreScripts)/IDLParser.pm \
+ $(WebCoreScripts)/generate-bindings.pl \
+#
+
+.PHONY : all
+
+JS%.h JS%.cpp : %.idl $(SCRIPTS)
+ @echo Generating bindings for $*...
+ @perl -I $(WebCoreScripts) -I $(WebKitTestRunner)/InjectedBundle/Bindings -I $(WebKitTestRunner)/UIScriptContext/Bindings $(WebCoreScripts)/generate-bindings.pl --defines "" --include InjectedBundle/Bindings --include UIScriptContext/Bindings --outputDir . --generator TestRunner $<
+
+all : \
+ $(INJECTED_BUNDLE_INTERFACES:%=JS%.h) \
+ $(INJECTED_BUNDLE_INTERFACES:%=JS%.cpp) \
+ $(UICONTEXT_INTERFACES:%=JS%.h) \
+ $(UICONTEXT_INTERFACES:%=JS%.cpp) \
+#
diff --git a/Tools/WebKitTestRunner/EventSenderProxy.h b/Tools/WebKitTestRunner/EventSenderProxy.h
index db2c58b0d..70d94014c 100644
--- a/Tools/WebKitTestRunner/EventSenderProxy.h
+++ b/Tools/WebKitTestRunner/EventSenderProxy.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2014 Apple Inc. All rights reserved.
* Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
*
* Redistribution and use in source and binary forms, with or without
@@ -29,6 +29,7 @@
#include <wtf/Deque.h>
#include <wtf/HashMap.h>
+#include <wtf/RetainPtr.h>
#include <wtf/Vector.h>
#if PLATFORM(GTK)
@@ -36,7 +37,11 @@
#include <gdk/gdk.h>
#include <wtf/HashSet.h>
#elif PLATFORM(EFL)
-#include <WebKit2/EWebKit2.h>
+#include "EWebKit2.h"
+#endif
+
+#if PLATFORM(COCOA)
+OBJC_CLASS NSEvent;
#endif
namespace WTR {
@@ -58,8 +63,15 @@ public:
void mouseDown(unsigned button, WKEventModifiers);
void mouseUp(unsigned button, WKEventModifiers);
+ void mouseForceDown();
+ void mouseForceUp();
+ void mouseForceChanged(float);
+ void mouseForceClick();
+ void startAndCancelMouseForceClick();
void mouseMoveTo(double x, double y);
void mouseScrollBy(int x, int y);
+ void mouseScrollByWithWheelAndMomentumPhases(int x, int y, int phase, int momentum);
+ void swipeGestureWithWheelAndMomentumPhases(int x, int y, int phase, int momentum);
void continuousMouseScrollBy(int x, int y, bool paged);
void leapForward(int milliseconds);
@@ -91,8 +103,17 @@ private:
void replaySavedEvents();
#endif
+ void sendMouseDownToStartPressureEvents();
+#if PLATFORM(COCOA)
+ enum class PressureChangeDirection { Increasing, Decreasing };
+ RetainPtr<NSEvent> beginPressureEvent(int stage);
+ RetainPtr<NSEvent> pressureChangeEvent(int stage, PressureChangeDirection);
+ RetainPtr<NSEvent> pressureChangeEvent(int stage, float pressure, PressureChangeDirection);
+#endif
+
#if PLATFORM(GTK)
void sendOrQueueEvent(GdkEvent*);
+ void dispatchEvent(GdkEvent*);
GdkEvent* createMouseButtonEvent(GdkEventType, unsigned button, WKEventModifiers);
GUniquePtr<GdkEvent> createTouchEvent(GdkEventType, int id);
void sendUpdatedTouchEvents();
@@ -111,7 +132,7 @@ private:
double m_clickTime;
WKPoint m_clickPosition;
WKEventMouseButton m_clickButton;
-#if PLATFORM(MAC)
+#if PLATFORM(COCOA)
int eventNumber;
#elif PLATFORM(GTK)
Deque<WTREventQueueItem> m_eventQueue;
diff --git a/Tools/WebKitTestRunner/FontWithFeatures.otf b/Tools/WebKitTestRunner/FontWithFeatures.otf
new file mode 100644
index 000000000..3e5069995
--- /dev/null
+++ b/Tools/WebKitTestRunner/FontWithFeatures.otf
Binary files differ
diff --git a/Tools/WebKitTestRunner/FontWithFeatures.ttf b/Tools/WebKitTestRunner/FontWithFeatures.ttf
new file mode 100644
index 000000000..42c332a13
--- /dev/null
+++ b/Tools/WebKitTestRunner/FontWithFeatures.ttf
Binary files differ
diff --git a/Tools/WebKitTestRunner/GNUmakefile.am b/Tools/WebKitTestRunner/GNUmakefile.am
deleted file mode 100644
index 28a2d5747..000000000
--- a/Tools/WebKitTestRunner/GNUmakefile.am
+++ /dev/null
@@ -1,175 +0,0 @@
-
-stamp-webkittestrunner-forwarding-headers: $(WebKit2)/Scripts/generate-forwarding-headers.pl $(Programs_WebKitTestRunner_SOURCES) $(Libraries_libTestRunnerInjectedBundle_la_SOURCES)
- $(AM_V_GEN)$(PERL) $< $(srcdir)/Tools/WebKitTestRunner $(GENSOURCES_WEBKIT2)/include gtk \
- && echo timestamp > $(@F)
-
-BUILT_SOURCES += $(top_builddir)/stamp-webkittestrunner-forwarding-headers
-
-if ENABLE_WEBKIT2
-noinst_PROGRAMS += \
- Programs/WebKitTestRunner
-endif
-
-Programs_WebKitTestRunner_SOURCES = \
- Tools/WebKitTestRunner/EventSenderProxy.h \
- Tools/WebKitTestRunner/gtk/main.cpp \
- Tools/WebKitTestRunner/gtk/EventSenderProxyGtk.cpp \
- Tools/WebKitTestRunner/gtk/PlatformWebViewGtk.cpp \
- Tools/WebKitTestRunner/gtk/TestControllerGtk.cpp \
- Tools/WebKitTestRunner/cairo/TestInvocationCairo.cpp \
- Tools/WebKitTestRunner/CyclicRedundancyCheck.cpp \
- Tools/WebKitTestRunner/CyclicRedundancyCheck.h \
- Tools/WebKitTestRunner/GeolocationProviderMock.cpp \
- Tools/WebKitTestRunner/GeolocationProviderMock.h \
- Tools/WebKitTestRunner/Options.cpp \
- Tools/WebKitTestRunner/Options.h \
- Tools/WebKitTestRunner/PixelDumpSupport.cpp \
- Tools/WebKitTestRunner/PixelDumpSupport.h \
- Tools/WebKitTestRunner/PlatformWebView.h \
- Tools/WebKitTestRunner/StringFunctions.h \
- Tools/WebKitTestRunner/TestController.cpp \
- Tools/WebKitTestRunner/TestController.h \
- Tools/WebKitTestRunner/TestInvocation.cpp \
- Tools/WebKitTestRunner/TestInvocation.h \
- Tools/WebKitTestRunner/WebNotificationProvider.cpp \
- Tools/WebKitTestRunner/WebNotificationProvider.h \
- Tools/WebKitTestRunner/WebKitTestRunnerPrefix.h \
- Tools/WebKitTestRunner/WorkQueueManager.cpp \
- Tools/WebKitTestRunner/WorkQueueManager.h
-
-Programs_WebKitTestRunner_CPPFLAGS = \
- -include Tools/WebKitTestRunner/WebKitTestRunnerPrefix.h \
- -I$(srcdir)/Tools/WebKitTestRunner \
- -I$(srcdir)/Source/WebCore/platform/gtk \
- -I$(top_builddir)/DerivedSources/WebKit2/include \
- $(global_cppflags) \
- $(javascriptcore_cppflags) \
- $(webcore_cppflags) \
- $(CAIRO_CFLAGS) \
- $(GTK_CFLAGS) \
- $(LIBSOUP_CFLAGS)
-Programs_WebKitTestRunner_CXXFLAGS = $(global_cxxflags)
-Programs_WebKitTestRunner_CFLAGS = $(global_cflags)
-
-Programs_WebKitTestRunner_LDADD = \
- libjavascriptcoregtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \
- libwebkit2gtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \
- $(CAIRO_LIBS) \
- $(GTK_LIBS) \
- $(GLIB_LIBS) \
- $(LIBSOUP_LIBS) \
- $(FREETYPE_LIBS) \
- $(WINMM_LIBS) \
- $(XRENDER_LIBS) \
- $(XT_LIBS)
-
-Programs_WebKitTestRunner_LDFLAGS = \
- -no-install
-
-# The InjectedBundle library allows the render process to load harness code.
-if ENABLE_WEBKIT2
-noinst_LTLIBRARIES += Libraries/libTestRunnerInjectedBundle.la
-endif
-
-webkittestrunner_built_sources += \
- DerivedSources/InjectedBundle/JSAccessibilityController.cpp \
- DerivedSources/InjectedBundle/JSAccessibilityTextMarker.cpp \
- DerivedSources/InjectedBundle/JSAccessibilityTextMarkerRange.cpp \
- DerivedSources/InjectedBundle/JSAccessibilityUIElement.cpp \
- DerivedSources/InjectedBundle/JSEventSendingController.cpp \
- DerivedSources/InjectedBundle/JSGCController.cpp \
- DerivedSources/InjectedBundle/JSTestRunner.cpp \
- DerivedSources/InjectedBundle/JSTextInputController.cpp
-nodist_Libraries_libTestRunnerInjectedBundle_la_SOURCES = $(webkittestrunner_built_sources)
-BUILT_SOURCES += $(webkittestrunner_built_sources)
-
-Libraries_libTestRunnerInjectedBundle_la_SOURCES = \
- Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.cpp \
- Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.h \
- Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarker.cpp \
- Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarker.h \
- Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarkerRange.cpp \
- Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarkerRange.h \
- Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp \
- Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h \
- Tools/WebKitTestRunner/InjectedBundle/ActivateFonts.h \
- Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityControllerAtk.cpp \
- Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.cpp \
- Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.h \
- Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityUIElementAtk.cpp \
- Tools/WebKitTestRunner/InjectedBundle/Bindings/JSWrappable.h \
- Tools/WebKitTestRunner/InjectedBundle/Bindings/JSWrapper.cpp \
- Tools/WebKitTestRunner/InjectedBundle/Bindings/JSWrapper.h \
- Tools/WebKitTestRunner/InjectedBundle/EventSendingController.cpp \
- Tools/WebKitTestRunner/InjectedBundle/EventSendingController.h \
- Tools/WebKitTestRunner/InjectedBundle/GCController.cpp \
- Tools/WebKitTestRunner/InjectedBundle/GCController.h \
- Tools/WebKitTestRunner/InjectedBundle/gtk/ActivateFontsGtk.cpp \
- Tools/WebKitTestRunner/InjectedBundle/gtk/InjectedBundleGtk.cpp \
- Tools/WebKitTestRunner/InjectedBundle/gtk/InjectedBundleUtilities.cpp \
- Tools/WebKitTestRunner/InjectedBundle/gtk/InjectedBundleUtilities.h \
- Tools/WebKitTestRunner/InjectedBundle/gtk/TestRunnerGtk.cpp \
- Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp \
- Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h \
- Tools/WebKitTestRunner/InjectedBundle/InjectedBundleMain.cpp \
- Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp \
- Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.h \
- Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp \
- Tools/WebKitTestRunner/InjectedBundle/TestRunner.h \
- Tools/WebKitTestRunner/InjectedBundle/TextInputController.cpp \
- Tools/WebKitTestRunner/InjectedBundle/TextInputController.h
-
-Libraries_libTestRunnerInjectedBundle_la_LIBADD = \
- libWebCoreInternals.la
-
-Libraries_libTestRunnerInjectedBundle_la_LDFLAGS = \
- -rpath ${shell pwd}/$(top_builddir)/../unix/TestNetscapePlugin/.libs \
- $(no_undefined) \
- -avoid-version \
- -module
-
-Libraries_libTestRunnerInjectedBundle_la_CPPFLAGS = \
- -DFONTS_CONF_DIR=\"${shell pwd}/${srcdir}/Tools/DumpRenderTree/gtk/fonts\" \
- -DTOP_LEVEL_DIR=\"${shell pwd}/${srcdir}\" \
- -include Tools/WebKitTestRunner/WebKitTestRunnerPrefix.h \
- -I$(srcdir)/Tools/WebKitTestRunner \
- -I$(srcdir)/Tools/WebKitTestRunner/InjectedBundle \
- -I$(srcdir)/Tools/WebKitTestRunner/InjectedBundle/Bindings \
- -I$(srcdir)/Tools/WebKitTestRunner/InjectedBundle/atk \
- -I$(srcdir)/Source/WebCore/testing/js \
- -I$(top_builddir)/DerivedSources/InjectedBundle \
- -I$(top_builddir)/DerivedSources/WebKit2/include \
- $(global_cppflags) \
- $(javascriptcore_cppflags) \
- $(webcore_cppflags) \
- $(CAIRO_CFLAGS) \
- $(GLIB_CFLAGS) \
- $(GTK_CFLAGS) \
- $(LIBSOUP_CFLAGS)
-Libraries_libTestRunnerInjectedBundle_la_CXXFLAGS = $(global_cxxflags)
-Libraries_libTestRunnerInjectedBundle_la_CFLAGS = $(global_cflags)
-
-code_generation_dependencies = \
- Tools/WebKitTestRunner/InjectedBundle/Bindings/CodeGeneratorTestRunner.pm \
- Source/WebCore/bindings/scripts/CodeGenerator.pm \
- Source/WebCore/bindings/scripts/IDLParser.pm \
- Source/WebCore/bindings/scripts/InFilesParser.pm \
- Source/WebCore/bindings/scripts/generate-bindings.pl
-
-DerivedSources/InjectedBundle/JS%.cpp: Tools/WebKitTestRunner/InjectedBundle/Bindings/%.idl $(code_generation_dependencies)
- $(AM_V_GEN)$(PERL) \
- -I $(srcdir)/Source/WebCore/bindings/scripts \
- -I $(srcdir)/Tools/WebKitTestRunner/InjectedBundle/Bindings \
- $(srcdir)/Source/WebCore/bindings/scripts/generate-bindings.pl \
- --defines "$(feature_defines)" --generator TestRunner \
- --include $(srcdir)/Tools/InjectedBundle/Bindings \
- --outputDir $(top_builddir)/DerivedSources/InjectedBundle \
- $<
-
-EXTRA_DIST += \
- $(srcdir)/Tools/WebKitTestRunner/InjectedBundle/Bindings/CodeGeneratorTestRunner.pm \
- $(srcdir)/Source/WebCore/bindings/scripts/CodeGenerator.pm \
- $(srcdir)/Source/WebCore/bindings/scripts/IDLParser.pm \
- $(srcdir)/Source/WebCore/bindings/scripts/InFilesParser.pm \
- $(srcdir)/Source/WebCore/bindings/scripts/generate-bindings.pl \
- $(shell ls $(srcdir)/Tools/WebKitTestRunner/InjectedBundle/Bindings/*.idl)
diff --git a/Tools/WebKitTestRunner/GeolocationProviderMock.cpp b/Tools/WebKitTestRunner/GeolocationProviderMock.cpp
index 9120258c7..ad4164966 100644
--- a/Tools/WebKitTestRunner/GeolocationProviderMock.cpp
+++ b/Tools/WebKitTestRunner/GeolocationProviderMock.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "GeolocationProviderMock.h"
-#include <WebKit2/WKGeolocationManager.h>
+#include <WebKit/WKGeolocationManager.h>
#include <string.h>
#include <wtf/Assertions.h>
#include <wtf/CurrentTime.h>
@@ -52,7 +52,7 @@ GeolocationProviderMock::GeolocationProviderMock(WKContextRef context)
m_geolocationManager = WKContextGetGeolocationManager(context);
WKGeolocationProviderV1 providerCallback;
- memset(&providerCallback, 0, sizeof(WKGeolocationProvider));
+ memset(&providerCallback, 0, sizeof(WKGeolocationProviderV1));
providerCallback.base.version = 1;
providerCallback.base.clientInfo = this;
providerCallback.startUpdating = startUpdatingCallback;
diff --git a/Tools/WebKitTestRunner/GeolocationProviderMock.h b/Tools/WebKitTestRunner/GeolocationProviderMock.h
index ff5537e46..802223ec3 100644
--- a/Tools/WebKitTestRunner/GeolocationProviderMock.h
+++ b/Tools/WebKitTestRunner/GeolocationProviderMock.h
@@ -26,7 +26,7 @@
#ifndef GeolocationProviderMock_h
#define GeolocationProviderMock_h
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace WTR {
@@ -41,6 +41,8 @@ public:
void startUpdating(WKGeolocationManagerRef);
void stopUpdating(WKGeolocationManagerRef);
+ bool isActive() const { return m_isActive; }
+
private:
void sendPositionIfNeeded();
void sendErrorIfNeeded();
diff --git a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.cpp b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.cpp
index f5d1bd58b..8b223fe4c 100644
--- a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.cpp
+++ b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.cpp
@@ -32,9 +32,9 @@
#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 {
@@ -61,10 +61,20 @@ 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()
{
- WKBundlePageRef page = InjectedBundle::shared().page()->page();
+ WKBundlePageRef page = InjectedBundle::singleton().page()->page();
void* root = WKAccessibilityRootObject(page);
return AccessibilityUIElement::create(static_cast<PlatformUIElement>(root));
@@ -72,7 +82,7 @@ PassRefPtr<AccessibilityUIElement> AccessibilityController::rootElement()
PassRefPtr<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));
@@ -87,7 +97,7 @@ PassRefPtr<AccessibilityUIElement> AccessibilityController::elementAtPoint(int x
// 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)
+#if (!PLATFORM(GTK) && !PLATFORM(COCOA) && !PLATFORM(EFL)) || !HAVE(ACCESSIBILITY)
bool AccessibilityController::addNotificationListener(JSValueRef) { return false; }
bool AccessibilityController::removeNotificationListener() { return false; }
PassRefPtr<AccessibilityUIElement> AccessibilityController::accessibleElementById(JSStringRef attribute) { return nullptr; }
diff --git a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.h b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.h
index 7ce1a45c3..e099544a1 100644
--- a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.h
+++ b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityController.h
@@ -44,6 +44,10 @@ public:
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.
@@ -66,7 +70,7 @@ public:
private:
AccessibilityController();
-#if PLATFORM(MAC)
+#if PLATFORM(COCOA) || PLATFORM(IOS)
RetainPtr<NotificationHandler> m_globalNotificationHandler;
#endif
diff --git a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarker.cpp b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarker.cpp
index a7a4b7def..051114db1 100644
--- a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarker.cpp
+++ b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarker.cpp
@@ -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..74341718c 100644
--- a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarker.h
+++ b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarker.h
@@ -31,7 +31,7 @@
#include <wtf/PassRefPtr.h>
#include <wtf/Platform.h>
-#if PLATFORM(MAC)
+#if PLATFORM(COCOA)
#include <wtf/RetainPtr.h>
typedef CFTypeRef PlatformTextMarker;
#else
@@ -59,14 +59,14 @@ 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
diff --git a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarkerRange.cpp b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarkerRange.cpp
index 3613f3728..53d8bfbe8 100644
--- a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarkerRange.cpp
+++ b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarkerRange.cpp
@@ -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..d3e685b2d 100644
--- a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarkerRange.h
+++ b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityTextMarkerRange.h
@@ -31,7 +31,7 @@
#include <wtf/PassRefPtr.h>
#include <wtf/Platform.h>
-#if PLATFORM(MAC)
+#if PLATFORM(COCOA)
#include <wtf/RetainPtr.h>
typedef CFTypeRef PlatformTextMarkerRange;
#else
@@ -57,14 +57,14 @@ 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
diff --git a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp
index 00e965ff3..e5b293a5c 100644
--- a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp
+++ b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp
@@ -53,6 +53,30 @@ 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() { }
+PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::linkedElement() { return nullptr; }
+PassRefPtr<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; }
+PassRefPtr<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; }
@@ -61,7 +85,7 @@ JSRetainPtr<JSStringRef> AccessibilityUIElement::lineAtOffset(int) { return 0; }
JSRetainPtr<JSStringRef> AccessibilityUIElement::sentenceAtOffset(int) { return 0; }
#endif
-#if (!PLATFORM(MAC) && !PLATFORM(GTK) && !PLATFORM(EFL)) || !HAVE(ACCESSIBILITY)
+#if (!PLATFORM(COCOA) && !PLATFORM(GTK) && !PLATFORM(EFL)) || !HAVE(ACCESSIBILITY)
AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement) { }
AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement&) { }
AccessibilityUIElement::~AccessibilityUIElement() { }
@@ -99,6 +123,7 @@ 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::computedRoleString() { return 0; }
JSRetainPtr<JSStringRef> AccessibilityUIElement::title() { return 0; }
JSRetainPtr<JSStringRef> AccessibilityUIElement::description() { return 0; }
JSRetainPtr<JSStringRef> AccessibilityUIElement::language() { return 0; }
@@ -125,6 +150,8 @@ bool AccessibilityUIElement::isSelectedOptionActive() const { return false; }
bool AccessibilityUIElement::isSelectable() const { return false; }
bool AccessibilityUIElement::isMultiSelectable() const { return false; }
void AccessibilityUIElement::setSelectedChild(AccessibilityUIElement*) const { }
+void AccessibilityUIElement::setSelectedChildAtIndex(unsigned) const { }
+void AccessibilityUIElement::removeSelectionAtIndex(unsigned) const { }
unsigned AccessibilityUIElement::selectedChildrenCount() const { return 0; }
PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::selectedChildAtIndex(unsigned) const { return 0; }
bool AccessibilityUIElement::isExpanded() const { return false; }
@@ -153,12 +180,15 @@ JSRetainPtr<JSStringRef> AccessibilityUIElement::rowIndexRange() { return 0; }
JSRetainPtr<JSStringRef> AccessibilityUIElement::columnIndexRange() { return 0; }
int AccessibilityUIElement::rowCount() { return 0; }
int AccessibilityUIElement::columnCount() { return 0; }
+JSValueRef AccessibilityUIElement::rowHeaders() const { return nullptr; }
+JSValueRef AccessibilityUIElement::columnHeaders() const { return nullptr; }
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; }
+PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::ariaControlsElementAtIndex(unsigned) { return nullptr; }
bool AccessibilityUIElement::ariaIsGrabbed() const { return false; }
JSRetainPtr<JSStringRef> AccessibilityUIElement::ariaDropEffects() const { return 0; }
JSRetainPtr<JSStringRef> AccessibilityUIElement::classList() const { return 0; }
@@ -167,16 +197,19 @@ 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; }
+bool AccessibilityUIElement::setSelectedVisibleTextRange(AccessibilityTextMarkerRange*) { 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; }
+unsigned AccessibilityUIElement::uiElementCountForSearchPredicate(JSContextRef, AccessibilityUIElement*, bool, JSValueRef, JSStringRef, bool, bool) { return 0; }
+PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::uiElementForSearchPredicate(JSContextRef, AccessibilityUIElement*, bool, JSValueRef, JSStringRef, bool, bool) { return 0; }
+JSRetainPtr<JSStringRef> AccessibilityUIElement::selectTextWithCriteria(JSContextRef, JSStringRef, JSValueRef, JSStringRef, JSStringRef) { return nullptr; }
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::lineTextMarkerRangeForTextMarker(AccessibilityTextMarker*) { return nullptr; }
PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::textMarkerRangeForElement(AccessibilityUIElement*) { return 0; }
int AccessibilityUIElement::textMarkerRangeLength(AccessibilityTextMarkerRange*) { return 0; }
PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::textMarkerRangeForMarkers(AccessibilityTextMarker*, AccessibilityTextMarker*) { return 0; }
@@ -196,6 +229,8 @@ int AccessibilityUIElement::indexForTextMarker(AccessibilityTextMarker*) { retur
bool AccessibilityUIElement::isTextMarkerValid(AccessibilityTextMarker*) { return false; }
PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::textMarkerForIndex(int) { return 0; }
void AccessibilityUIElement::scrollToMakeVisible() { }
+void AccessibilityUIElement::scrollToGlobalPoint(int, int) { }
+void AccessibilityUIElement::scrollToMakeVisibleWithSubFocus(int, int, int, int) { }
JSRetainPtr<JSStringRef> AccessibilityUIElement::supportedActions() const { return 0; }
JSRetainPtr<JSStringRef> AccessibilityUIElement::mathPostscriptsDescription() const { return 0; }
JSRetainPtr<JSStringRef> AccessibilityUIElement::mathPrescriptsDescription() const { return 0; }
@@ -203,5 +238,24 @@ JSRetainPtr<JSStringRef> AccessibilityUIElement::pathDescription() const { retur
#endif
+#if !PLATFORM(MAC) || !HAVE(ACCESSIBILITY)
+PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::selectedTextMarkerRange() { return nullptr; }
+void AccessibilityUIElement::resetSelectedTextMarkerRange() { }
+void AccessibilityUIElement::setBoolAttributeValue(JSStringRef, bool) { }
+#endif
+
+#if (!PLATFORM(MAC) && !PLATFORM(IOS)) || !HAVE(ACCESSIBILITY)
+PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::leftWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*) { return nullptr; }
+PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*) { return nullptr; }
+PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::previousWordStartTextMarkerForTextMarker(AccessibilityTextMarker*) { return nullptr; }
+PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::nextWordEndTextMarkerForTextMarker(AccessibilityTextMarker*) { return nullptr; }
+PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::paragraphTextMarkerRangeForTextMarker(AccessibilityTextMarker*) { return nullptr; }
+PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::nextParagraphEndTextMarkerForTextMarker(AccessibilityTextMarker*) { return nullptr; }
+PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::previousParagraphStartTextMarkerForTextMarker(AccessibilityTextMarker*) { return nullptr; }
+PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::sentenceTextMarkerRangeForTextMarker(AccessibilityTextMarker*) { return nullptr; }
+PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::nextSentenceEndTextMarkerForTextMarker(AccessibilityTextMarker*) { return nullptr; }
+PassRefPtr<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..3f39a1781 100644
--- a/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h
+++ b/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h
@@ -35,7 +35,7 @@
#include <wtf/Platform.h>
#include <wtf/Vector.h>
-#if PLATFORM(MAC)
+#if PLATFORM(COCOA)
#ifdef __OBJC__
typedef id PlatformUIElement;
#else
@@ -44,13 +44,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
@@ -105,6 +105,7 @@ public:
JSValueRef uiElementArrayAttributeValue(JSStringRef attribute) const;
PassRefPtr<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 +114,7 @@ public:
JSRetainPtr<JSStringRef> role();
JSRetainPtr<JSStringRef> subrole();
JSRetainPtr<JSStringRef> roleDescription();
+ JSRetainPtr<JSStringRef> computedRoleString();
JSRetainPtr<JSStringRef> title();
JSRetainPtr<JSStringRef> description();
JSRetainPtr<JSStringRef> language();
@@ -140,6 +142,8 @@ public:
bool isSelectable() const;
bool isMultiSelectable() const;
void setSelectedChild(AccessibilityUIElement*) const;
+ void setSelectedChildAtIndex(unsigned) const;
+ void removeSelectionAtIndex(unsigned) const;
unsigned selectedChildrenCount() const;
PassRefPtr<AccessibilityUIElement> selectedChildAtIndex(unsigned) const;
@@ -187,6 +191,7 @@ public:
// ARIA specific
PassRefPtr<AccessibilityUIElement> ariaOwnsElementAtIndex(unsigned);
PassRefPtr<AccessibilityUIElement> ariaFlowToElementAtIndex(unsigned);
+ PassRefPtr<AccessibilityUIElement> ariaControlsElementAtIndex(unsigned);
// ARIA Drag and Drop
bool ariaIsGrabbed() const;
@@ -202,8 +207,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);
+ PassRefPtr<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);
@@ -219,10 +225,15 @@ public:
PassRefPtr<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> lineTextMarkerRangeForTextMarker(AccessibilityTextMarker*);
PassRefPtr<AccessibilityTextMarkerRange> textMarkerRangeForElement(AccessibilityUIElement*);
PassRefPtr<AccessibilityTextMarkerRange> textMarkerRangeForMarkers(AccessibilityTextMarker* startMarker, AccessibilityTextMarker* endMarker);
+ PassRefPtr<AccessibilityTextMarkerRange> selectedTextMarkerRange();
+ void resetSelectedTextMarkerRange();
PassRefPtr<AccessibilityTextMarker> startTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange*);
PassRefPtr<AccessibilityTextMarker> endTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange*);
PassRefPtr<AccessibilityTextMarker> endTextMarkerForBounds(int x, int y, int width, int height);
@@ -239,6 +250,17 @@ public:
PassRefPtr<AccessibilityTextMarker> textMarkerForIndex(int);
PassRefPtr<AccessibilityTextMarker> startTextMarker();
PassRefPtr<AccessibilityTextMarker> endTextMarker();
+ bool setSelectedVisibleTextRange(AccessibilityTextMarkerRange*);
+ PassRefPtr<AccessibilityTextMarkerRange> leftWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*);
+ PassRefPtr<AccessibilityTextMarkerRange> rightWordTextMarkerRangeForTextMarker(AccessibilityTextMarker*);
+ PassRefPtr<AccessibilityTextMarker> previousWordStartTextMarkerForTextMarker(AccessibilityTextMarker*);
+ PassRefPtr<AccessibilityTextMarker> nextWordEndTextMarkerForTextMarker(AccessibilityTextMarker*);
+ PassRefPtr<AccessibilityTextMarkerRange> paragraphTextMarkerRangeForTextMarker(AccessibilityTextMarker*);
+ PassRefPtr<AccessibilityTextMarker> nextParagraphEndTextMarkerForTextMarker(AccessibilityTextMarker*);
+ PassRefPtr<AccessibilityTextMarker> previousParagraphStartTextMarkerForTextMarker(AccessibilityTextMarker*);
+ PassRefPtr<AccessibilityTextMarkerRange> sentenceTextMarkerRangeForTextMarker(AccessibilityTextMarker*);
+ PassRefPtr<AccessibilityTextMarker> nextSentenceEndTextMarkerForTextMarker(AccessibilityTextMarker*);
+ PassRefPtr<AccessibilityTextMarker> previousSentenceStartTextMarkerForTextMarker(AccessibilityTextMarker*);
// Returns an ordered list of supported actions for an element.
JSRetainPtr<JSStringRef> supportedActions() const;
@@ -253,6 +275,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();
+ PassRefPtr<AccessibilityUIElement> linkedElement();
+ PassRefPtr<AccessibilityUIElement> headerElementAtIndex(unsigned index);
+ void assistiveTechnologySimulatedFocus();
+ bool isSearchField() const;
+ bool isTextArea() const;
+
+ bool scrollPageUp();
+ bool scrollPageDown();
+ bool scrollPageLeft();
+ bool scrollPageRight();
+
+ // Fieldset
+ bool hasContainedByFieldsetTrait();
+ PassRefPtr<AccessibilityUIElement> fieldsetAncestorElement();
+
private:
AccessibilityUIElement(PlatformUIElement);
AccessibilityUIElement(const AccessibilityUIElement&);
@@ -261,7 +306,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 +315,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
diff --git a/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityController.idl b/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityController.idl
new file mode 100644
index 000000000..3831154e0
--- /dev/null
+++ b/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityController.idl
@@ -0,0 +1,45 @@
+/*
+ * 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 AccessibilityController {
+ void enableEnhancedAccessibility(boolean enable);
+ readonly attribute boolean enhancedAccessibilityEnabled;
+
+ readonly attribute DOMString platformName;
+ readonly attribute AccessibilityUIElement rootElement;
+ readonly attribute AccessibilityUIElement focusedElement;
+ AccessibilityUIElement elementAtPoint(int x, int y);
+ AccessibilityUIElement accessibleElementById(DOMString id);
+
+ boolean addNotificationListener(object functionCallback);
+ boolean removeNotificationListener();
+
+ void logFocusEvents();
+ void logValueChangeEvents();
+ void logScrollingStartEvents();
+ void logAccessibilityEvents();
+ void resetToConsistentState();
+};
+
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..2398be687
--- /dev/null
+++ b/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl
@@ -0,0 +1,246 @@
+/*
+ * 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(int x, int 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);
+ 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 int 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 int intValue;
+ readonly attribute int minValue;
+ readonly attribute int 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 isOffScreen;
+ readonly attribute boolean isValid;
+ readonly attribute int hierarchicalLevel;
+ readonly attribute boolean ariaIsGrabbed;
+ readonly attribute DOMString ariaDropEffects;
+ readonly attribute DOMString classList;
+
+ readonly attribute int x;
+ readonly attribute int y;
+ readonly attribute int width;
+ readonly attribute int height;
+ readonly attribute int clickPointX;
+ readonly attribute int clickPointY;
+
+ readonly attribute int childrenCount;
+ readonly attribute int selectedChildrenCount;
+ readonly attribute int rowCount;
+ readonly attribute int columnCount;
+
+ // Actions.
+ void increment();
+ void decrement();
+ void press();
+ void showMenu();
+
+ // Attribute info.
+ DOMString allAttributes();
+ DOMString attributesOfChildren();
+ DOMString attributesOfLinkedUIElements();
+ DOMString attributesOfDocumentLinks();
+
+ // Text info.
+ DOMString characterAtOffset(int offset);
+ DOMString wordAtOffset(int offset);
+ DOMString lineAtOffset(int offset);
+ DOMString sentenceAtOffset(int 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);
+ int indexInTable();
+ DOMString rowIndexRange();
+ DOMString columnIndexRange();
+ int rowCount();
+ int columnCount();
+ object columnHeaders();
+ object rowHeaders();
+
+ AccessibilityUIElement ariaOwnsElementAtIndex(unsigned long index);
+ AccessibilityUIElement ariaFlowToElementAtIndex(unsigned long index);
+ AccessibilityUIElement ariaControlsElementAtIndex(unsigned long index);
+
+ // Paramaterized attributes.
+ DOMString parameterizedAttributeNames();
+ int lineForIndex(int index);
+ DOMString rangeForLine(int index);
+ DOMString rangeForPosition(int x, int 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 int 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(int x, int y);
+ void scrollToMakeVisibleWithSubFocus(int x, int y, int width, int 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(int x, int y, int width, int height);
+ AccessibilityTextMarker startTextMarkerForBounds(int x, int y, int width, int height);
+ AccessibilityTextMarker textMarkerForPoint(int x, int y);
+ AccessibilityTextMarker previousTextMarker(AccessibilityTextMarker marker);
+ AccessibilityTextMarker nextTextMarker(AccessibilityTextMarker marker);
+ AccessibilityUIElement accessibilityElementForTextMarker(AccessibilityTextMarker marker);
+ DOMString stringForTextMarkerRange(AccessibilityTextMarkerRange range);
+ int textMarkerRangeLength(AccessibilityTextMarkerRange range);
+ boolean attributedStringForTextMarkerRangeContainsAttribute(DOMString attr, AccessibilityTextMarkerRange range);
+ int indexForTextMarker(AccessibilityTextMarker marker);
+ boolean isTextMarkerValid(AccessibilityTextMarker marker);
+ AccessibilityTextMarker textMarkerForIndex(int 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 int elementTextPosition;
+ readonly attribute int 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..19486c485
--- /dev/null
+++ b/Tools/WebKitTestRunner/InjectedBundle/Bindings/CodeGeneratorTestRunner.pm
@@ -0,0 +1,570 @@
+# 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;
+
+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)) {
+ open(FILE, ">", File::Spec->catfile($outputDir, $$file{name})) or die "Failed to open $$file{name} for writing: $!";
+ print FILE @{$$file{contents}};
+ close(FILE) or die "Failed to close $$file{name} after writing: $!";
+ }
+}
+
+sub _className
+{
+ my ($idlType) = @_;
+
+ return "JS" . _implementationClassName($idlType);
+}
+
+sub _classRefGetter
+{
+ my ($self, $idlType) = @_;
+ return $$self{codeGenerator}->WK_lcfirst(_implementationClassName($idlType)) . "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 $idlType = $interface->name;
+ my $className = _className($idlType);
+ my $implementationClassName = _implementationClassName($idlType);
+ 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($idlType)]}();
+
+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->signature->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 $idlType = $interface->name;
+ my $className = _className($idlType);
+ my $implementationClassName = _implementationClassName($idlType);
+ my $filename = $className . ".cpp";
+
+ push(@contentsPrefix, $self->_licenseBlock());
+
+ my $classRefGetter = $self->_classRefGetter($idlType);
+ 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 = "${idlType}";
+ 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->signature->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->signature->extendedAttributes->{"CustomArgumentHandling"}) {
+ $functionCall = "impl->" . $function->signature->name . "(context, argumentCount, arguments, exception)";
+ } else {
+ my @parameters = ();
+ my @specifiedParameters = @{$function->parameters};
+
+ $self->_includeHeaders(\%contentsIncludes, $function->signature->type, $function->signature);
+
+ if ($function->signature->extendedAttributes->{"PassContext"}) {
+ push(@parameters, "context");
+ }
+
+ foreach my $i (0..$#specifiedParameters) {
+ my $parameter = $specifiedParameters[$i];
+
+ $self->_includeHeaders(\%contentsIncludes, $idlType, $parameter);
+
+ push(@contents, " " . $self->_platformTypeVariableDeclaration($parameter, $parameter->name, "arguments[$i]", "argumentCount > $i") . "\n");
+
+ push(@parameters, $self->_parameterExpression($parameter));
+ }
+
+ $functionCall = "impl->" . $function->signature->name . "(" . join(", ", @parameters) . ")";
+ }
+
+ push(@contents, " ${functionCall};\n\n") if $function->signature->type eq "void";
+ push(@contents, " return " . $self->_returnExpression($function->signature, $functionCall) . ";\n}\n");
+ }
+ }
+
+ if (my @attributes = @{$interface->attributes}) {
+ push(@contents, "\n// Attributes\n");
+ foreach my $attribute (@attributes) {
+ $self->_includeHeaders(\%contentsIncludes, $attribute->signature->type, $attribute->signature);
+
+ 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->signature, $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->signature, "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) = @_;
+
+ my $signature = $attribute->signature;
+ my $name = $signature->name;
+
+ return $name;
+}
+
+sub _includeHeaders
+{
+ my ($self, $headers, $idlType, $signature) = @_;
+
+ return unless defined $idlType;
+ return if $idlType eq "boolean";
+ return if $idlType eq "object";
+ return if $$self{codeGenerator}->IsNonPointerType($idlType);
+ return if $$self{codeGenerator}->IsStringType($idlType);
+
+ $$headers{_className($idlType) . ".h"} = 1;
+ $$headers{_implementationClassName($idlType) . ".h"} = 1;
+}
+
+sub _implementationClassName
+{
+ my ($idlType) = @_;
+
+ return $idlType;
+}
+
+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->parent;
+}
+
+sub _platformType
+{
+ my ($self, $idlType, $signature) = @_;
+
+ return undef unless defined $idlType;
+
+ return "bool" if $idlType eq "boolean";
+ return "JSValueRef" if $idlType eq "object";
+ return "JSRetainPtr<JSStringRef>" if $$self{codeGenerator}->IsStringType($idlType);
+ return "double" if $$self{codeGenerator}->IsNonPointerType($idlType);
+ return _implementationClassName($idlType);
+}
+
+sub _platformTypeConstructor
+{
+ my ($self, $signature, $argumentName) = @_;
+
+ my $idlType = $signature->type;
+
+ return "JSValueToBoolean(context, $argumentName)" if $idlType eq "boolean";
+ return "$argumentName" if $idlType eq "object";
+ return "JSRetainPtr<JSStringRef>(Adopt, JSValueToStringCopy(context, $argumentName, 0))" if $$self{codeGenerator}->IsStringType($idlType);
+ return "JSValueToNumber(context, $argumentName, 0)" if $$self{codeGenerator}->IsNonPointerType($idlType);
+ return "to" . _implementationClassName($idlType) . "(context, $argumentName)";
+}
+
+sub _platformTypeVariableDeclaration
+{
+ my ($self, $signature, $variableName, $argumentName, $condition) = @_;
+
+ my $platformType = $self->_platformType($signature->type, $signature);
+ my $constructor = $self->_platformTypeConstructor($signature, $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, $signature, $expression) = @_;
+
+ my $returnIDLType = $signature->type;
+
+ return "JSValueMakeUndefined(context)" if $returnIDLType eq "void";
+ return "JSValueMakeBoolean(context, ${expression})" if $returnIDLType eq "boolean";
+ return "${expression}" if $returnIDLType eq "object";
+ return "JSValueMakeNumber(context, ${expression})" if $$self{codeGenerator}->IsNonPointerType($returnIDLType);
+ return "JSValueMakeStringOrNull(context, ${expression}.get())" if $$self{codeGenerator}->IsStringType($returnIDLType);
+ return "toJS(context, WTF::getPtr(${expression}))";
+}
+
+sub _parameterExpression
+{
+ my ($self, $parameter) = @_;
+
+ my $idlType = $parameter->type;
+ my $name = $parameter->name;
+
+ return "${name}.get()" if $$self{codeGenerator}->IsStringType($idlType);
+ return $name;
+}
+
+sub _setterName
+{
+ my ($self, $attribute) = @_;
+
+ my $name = $attribute->signature->name;
+
+ return "set" . $$self{codeGenerator}->WK_ucfirst($name);
+}
+
+sub _staticFunctionsGetterImplementation
+{
+ my ($self, $interface) = @_;
+
+ my $mapFunction = sub {
+ my $name = $_->signature->name;
+ my @attributes = qw(kJSPropertyAttributeDontDelete kJSPropertyAttributeReadOnly);
+ push(@attributes, "kJSPropertyAttributeDontEnum") if $_->signature->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->name);
+ 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 $_->signature->extendedAttributes->{"NoImplementation"};
+
+ my $attributeName = $_->signature->name;
+ my $getterName = $self->_getterName($_);
+ my $setterName = $_->isReadOnly ? "0" : $self->_setterName($_);
+ my @attributes = qw(kJSPropertyAttributeDontDelete);
+ push(@attributes, "kJSPropertyAttributeReadOnly") if $_->isReadOnly;
+ push(@attributes, "kJSPropertyAttributeDontEnum") if $_->signature->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/GCController.idl b/Tools/WebKitTestRunner/InjectedBundle/Bindings/GCController.idl
new file mode 100644
index 000000000..fb933834d
--- /dev/null
+++ b/Tools/WebKitTestRunner/InjectedBundle/Bindings/GCController.idl
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+interface GCController {
+ void collect();
+ void collectOnAlternateThread(boolean waitUntilDone);
+ unsigned long long getJSObjectCount();
+};
+
diff --git a/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl b/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl
new file mode 100644
index 000000000..a86202b28
--- /dev/null
+++ b/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2010, 2011, 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+interface TestRunner {
+ // The basics.
+ void dumpAsText(boolean dumpPixels);
+ void dumpChildFramesAsText();
+ void waitForPolicyDelegate();
+ void waitUntilDone();
+ void notifyDone();
+ double preciseTime();
+
+ // 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 setPluginsEnabled(boolean value);
+ void setJavaScriptCanAccessClipboard(boolean value);
+ void setPrivateBrowsingEnabled(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(int model);
+ void setAsynchronousSpellCheckingEnabled(boolean value);
+ void setPrinting();
+ void setShouldDecideNavigationPolicyAfterDelay(boolean value);
+ void setNavigationGesturesEnabled(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(int 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);
+
+ void clearTestRunnerCallbacks();
+
+ void setBackingScaleFactor(double backingScaleFactor, object callback);
+
+ void setWindowIsKey(boolean isKey);
+
+ // 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, [Default=Undefined] optional object altitude, optional object altitudeAccuracy, optional object heading, optional object speed);
+ void setMockGeolocationPositionUnavailableError(DOMString errorMessage);
+ boolean isGeolocationProviderActive();
+
+ // MediaStream
+ void setUserMediaPermission(boolean value);
+ void setUserMediaPermissionForOrigin(boolean permission, DOMString url);
+
+ // 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 setHandlesAuthenticationChallenges(boolean value);
+ void setAuthenticationUsername(DOMString username);
+ void setAuthenticationPassword(DOMString password);
+
+ // 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);
+
+ // UI Process Testing
+ void runUIScript(DOMString script, object callback);
+};
+
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..0faa2f398 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 {
@@ -208,7 +208,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 +217,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 +230,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 +250,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 +332,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 +344,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 +375,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 +383,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 +391,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 +411,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 +534,40 @@ 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)
+#if PLATFORM(GTK) || PLATFORM(EFL)
// Do mouse context click.
mouseDown(2, 0);
mouseUp(2, 0);
-
WKRetainPtr<WKArrayRef> menuEntries = adoptWK(WKBundlePageCopyContextMenuItems(page));
+#else
+ WKRetainPtr<WKArrayRef> menuEntries = adoptWK(WKBundlePageCopyContextMenuAtPointInWindow(page, m_position));
+#endif
+ JSValueRef arrayResult = JSObjectMakeArray(context, 0, 0, 0);
+ if (!menuEntries)
+ return arrayResult;
+
+ 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 +575,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 +685,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 +709,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 +739,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 +760,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 +772,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 +784,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 +796,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 +808,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 +820,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 +836,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 +852,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..c23c36dfa 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
@@ -27,8 +27,8 @@
#define EventSendingController_h
#include "JSWrappable.h"
-#include <WebKit2/WKEvent.h>
-#include <WebKit2/WKGeometry.h>
+#include <WebKit/WKEvent.h>
+#include <WebKit/WKGeometry.h>
#include <wtf/PassRefPtr.h>
namespace WTR {
@@ -46,11 +46,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,6 +88,7 @@ public:
private:
EventSendingController();
+ WKPoint m_position;
};
} // namespace WTR
diff --git a/Tools/WebKitTestRunner/InjectedBundle/GCController.cpp b/Tools/WebKitTestRunner/InjectedBundle/GCController.cpp
index 10c21dba8..fd0cc3a78 100644
--- a/Tools/WebKitTestRunner/InjectedBundle/GCController.cpp
+++ b/Tools/WebKitTestRunner/InjectedBundle/GCController.cpp
@@ -28,7 +28,7 @@
#include "InjectedBundle.h"
#include "JSGCController.h"
-#include <WebKit2/WKBundlePrivate.h>
+#include <WebKit/WKBundlePrivate.h>
namespace WTR {
@@ -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/InjectedBundle.cpp b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp
index f71fe9360..72c045830 100644
--- a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp
+++ b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp
@@ -29,20 +29,19 @@
#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 <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 +100,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] (const std::unique_ptr<InjectedBundlePage>& current) {
+ return current->page() == page;
+ });
}
void InjectedBundle::didInitializePageGroup(WKBundlePageGroupRef pageGroup)
@@ -139,6 +133,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());
@@ -155,11 +156,13 @@ void InjectedBundle::didReceiveMessage(WKStringRef messageName, WKTypeRef messag
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 +173,93 @@ 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();
- 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, "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());
-}
-
-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)
@@ -238,8 +286,6 @@ void InjectedBundle::beginTesting(WKDictionaryRef settings)
m_textInputController = TextInputController::create();
m_accessibilityController = AccessibilityController::create();
- 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);
@@ -250,13 +296,10 @@ void InjectedBundle::beginTesting(WKDictionaryRef settings)
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*/);
- WKBundleRemoveAllUserContent(m_bundle, m_pageGroup);
+#if PLATFORM(IOS)
+ WKBundlePageSetUseTestingViewportConfiguration(page()->page(), !booleanForKey(settings, "UseFlexibleViewport"));
+#endif
m_testRunner->setShouldDumpFrameLoadCallbacks(booleanForKey(settings, "DumpFrameLoadDelegates"));
m_testRunner->setUserStyleSheetEnabled(false);
@@ -264,13 +307,15 @@ void InjectedBundle::beginTesting(WKDictionaryRef settings)
m_testRunner->setCloseRemainingWindowsWhenComplete(false);
m_testRunner->setAcceptsEditing(true);
m_testRunner->setTabKeyCyclesThroughElements(true);
+ m_testRunner->clearTestRunnerCallbacks();
- m_testRunner->setCustomTimeout(m_timeout);
+ 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 +332,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 +354,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();
@@ -334,60 +387,67 @@ 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::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 +500,45 @@ 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());
+}
+
+void InjectedBundle::setUserMediaPermission(bool enabled)
+{
+ auto messageName = adoptWK(WKStringCreateWithUTF8CString("SetUserMediaPermission"));
+ auto messageBody = adoptWK(WKBooleanCreate(enabled));
+ WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
+}
+
+void InjectedBundle::setUserMediaPermissionForOrigin(bool permission, WKStringRef url)
+{
+ auto messageName = adoptWK(WKStringCreateWithUTF8CString("SetUserMediaPermissionForOrigin"));
+ 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> urlKeyWK(AdoptWK, WKStringCreateWithUTF8CString("url"));
+ WKDictionarySetItem(messageBody.get(), urlKeyWK.get(), url);
+
+ WKBundlePagePostMessage(page()->page(), messageName.get(), messageBody.get());
}
void InjectedBundle::setCustomPolicyDelegate(bool enabled, bool permissive)
@@ -463,23 +555,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 +584,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 +593,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 +602,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 +611,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 +628,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 +656,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 +664,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 +672,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 +680,14 @@ 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));
}
} // namespace WTR
diff --git a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h
index 170c8ac70..0f0e1f130 100644
--- a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h
+++ b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h
@@ -31,11 +31,10 @@
#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>
@@ -45,7 +44,7 @@ class InjectedBundlePage;
class InjectedBundle {
public:
- static InjectedBundle& shared();
+ static InjectedBundle& singleton();
// Initialize the InjectedBundle.
void initialize(WKBundleRef, WKTypeRef initializationUserData);
@@ -67,7 +66,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; }
@@ -86,29 +86,40 @@ public:
void postSetBackingScaleFactor(double);
void postSetWindowIsKey(bool);
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 setUserMediaPermissionForOrigin(bool permission, WKStringRef url);
// 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);
+
private:
InjectedBundle();
~InjectedBundle();
@@ -134,7 +145,7 @@ private:
WKBundleRef m_bundle;
WKBundlePageGroupRef m_pageGroup;
- Vector<OwnPtr<InjectedBundlePage> > m_pages;
+ Vector<std::unique_ptr<InjectedBundlePage>> m_pages;
RefPtr<AccessibilityController> m_accessibilityController;
RefPtr<TestRunner> m_testRunner;
@@ -155,10 +166,13 @@ private:
bool m_useWaitToDumpWatchdogTimer;
bool m_useWorkQueue;
int m_timeout;
+ bool m_pixelResultIsPending { false };
WKRetainPtr<WKDataRef> m_audioResult;
WKRetainPtr<WKImageRef> m_pixelResult;
WKRetainPtr<WKArrayRef> m_repaintRects;
+
+ Vector<String> m_allowedHosts;
};
} // namespace WTR
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..d3a3638f6 100644
--- a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp
+++ b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp
@@ -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);
@@ -417,9 +419,17 @@ void InjectedBundlePage::prepare()
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 +467,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 +656,61 @@ 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");
+ if (WKErrorGetErrorCode(error) == kWKErrorCodeCannotShowURL)
+ dumpLoadEvent(frame, "(kWKErrorCodeCannotShowURL)");
+ }
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 +718,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 };
@@ -823,9 +846,8 @@ void InjectedBundlePage::dumpDOMAsWebArchive(WKBundleFrameRef frame, StringBuild
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 +858,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 +883,52 @@ 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::shared().shouldDumpPixels() && InjectedBundle::shared().testRunner()->shouldDumpPixels()) {
- WKSnapshotOptions options = kWKSnapshotOptionsShareable | kWKSnapshotOptionsInViewCoordinates;
- if (InjectedBundle::shared().testRunner()->shouldDumpSelectionRect())
- options |= kWKSnapshotOptionsPaintSelectionRectangle;
+ if (injectedBundle.shouldDumpPixels() && injectedBundle.testRunner()->shouldDumpPixels()) {
+#if PLATFORM(IOS)
+ // IOS doesn't implement PlatformWebView::windowSnapshotImage() yet, so we need to generate the snapshot in the web process.
+ bool shouldCreateSnapshot = true;
+#else
+ bool shouldCreateSnapshot = injectedBundle.testRunner()->isPrinting();
+#endif
+ if (shouldCreateSnapshot) {
+ WKSnapshotOptions options = kWKSnapshotOptionsShareable;
+ WKRect snapshotRect = WKBundleFrameGetVisibleContentBounds(WKBundlePageGetMainFrame(m_page));
+
+ 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 +936,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 +948,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 +983,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 +1007,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 +1019,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 +1053,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 +1109,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 +1126,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 +1147,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 +1181,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 +1206,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 +1224,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 +1252,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,10 +1298,26 @@ 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())
+ 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())
return WKBundlePagePolicyActionUse;
WKRetainPtr<WKURLRef> url = adoptWK(WKURLRequestCopyURL(request));
@@ -1239,10 +1342,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 +1357,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 +1433,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 +1456,49 @@ void InjectedBundlePage::willAddMessageToConsole(WKStringRef message, uint32_t l
}
stringBuilder.append(messageString);
stringBuilder.append('\n');
- InjectedBundle::shared().outputText(stringBuilder.toString());
+ 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 +1509,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 +1528,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 +1567,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 +1632,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 +1674,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 +1683,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 +1700,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 +1709,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 +1745,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 +1756,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 +1862,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 +1874,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 +1988,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..e3f8f563c 100644
--- a/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp
+++ b/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp
@@ -33,20 +33,20 @@
#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 <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/WKRetainPtr.h>
+#include <WebKit/WKSerializedScriptValue.h>
+#include <WebKit/WebKit2_C.h>
#include <wtf/CurrentTime.h>
#include <wtf/HashMap.h>
#include <wtf/StdLibExtras.h>
@@ -55,8 +55,6 @@
namespace WTR {
-const double TestRunner::waitToDumpWatchdogTimerInterval = 30;
-
PassRefPtr<TestRunner> TestRunner::create()
{
return adoptRef(new TestRunner);
@@ -93,10 +91,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 +114,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 +132,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()
@@ -142,39 +144,39 @@ void TestRunner::waitForPolicyDelegate()
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();
+ 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();
- m_waitToDump = false;
-}
+ // 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.
-void TestRunner::setCustomTimeout(int timeout)
-{
- m_timeout = timeout;
+ m_waitToDump = false;
}
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 +184,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 +235,37 @@ 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());
}
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 +277,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();
- WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(InjectedBundle::shared().page()->page());
+ WKRetainPtr<WKArrayRef> origins(AdoptWK, WKBundlePageCopyOriginsWithApplicationCache(page));
+
+ WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(page);
JSContextRef context = WKBundleFrameGetJavaScriptContext(mainFrame);
return stringArrayToJS(context, origins.get());
@@ -297,7 +302,7 @@ 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)
@@ -309,58 +314,67 @@ void TestRunner::setCanOpenWindows(bool)
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::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::setPluginsEnabled(bool enabled)
{
- WKBundleSetPluginsEnabled(InjectedBundle::shared().bundle(), InjectedBundle::shared().pageGroup(), enabled);
+ auto& injectedBundle = InjectedBundle::singleton();
+ WKBundleSetPluginsEnabled(injectedBundle.bundle(), injectedBundle.pageGroup(), 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::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 +388,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 +415,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 +463,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 +478,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 +513,12 @@ enum {
AddChromeInputFieldCallbackID = 1,
RemoveChromeInputFieldCallbackID,
FocusWebViewCallbackID,
- SetBackingScaleFactorCallbackID
+ SetBackingScaleFactorCallbackID,
+ DidBeginSwipeCallbackID,
+ WillEndSwipeCallbackID,
+ DidEndSwipeCallbackID,
+ DidRemoveSwipeSnapshotCallbackID,
+ FirstUIScriptCallbackID = 100
};
static void cacheTestRunnerCallback(unsigned index, JSValueRef callback)
@@ -519,50 +526,67 @@ 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::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::callAddChromeInputFieldCallback()
@@ -592,13 +616,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(), 0);
}
double TestRunner::preciseTime()
@@ -612,7 +641,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 +655,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 +760,51 @@ 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::setUserMediaPermissionForOrigin(bool permission, JSStringRef url)
+{
+ WKRetainPtr<WKStringRef> urlWK = toWK(url);
+ InjectedBundle::singleton().setUserMediaPermissionForOrigin(permission, urlWK.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 +813,45 @@ 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::setHandlesAuthenticationChallenges(bool handlesAuthenticationChallenges)
{
WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("SetHandlesAuthenticationChallenge"));
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::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 +859,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 +867,119 @@ 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());
+}
+
+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);
+}
+
} // namespace WTR
diff --git a/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h b/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h
index cefb6a5d1..67c5c6c8b 100644
--- a/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h
+++ b/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h
@@ -27,24 +27,25 @@
#define TestRunner_h
#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/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
@@ -61,6 +62,8 @@ public:
void makeWindowObject(JSContextRef, JSObjectRef windowObject, JSValueRef* exception);
// 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; }
@@ -84,6 +87,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; }
@@ -181,6 +185,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; }
@@ -198,7 +203,8 @@ public:
void showWebInspector();
void closeWebInspector();
- void evaluateInWebInspector(long callId, JSStringRef script);
+ void evaluateInWebInspector(JSStringRef script);
+ JSRetainPtr<JSStringRef> inspectorTestStubURL();
void setPOSIXLocale(JSStringRef);
@@ -206,6 +212,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);
@@ -256,18 +264,23 @@ public:
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 setUserMediaPermissionForOrigin(bool permission, JSStringRef url);
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);
@@ -275,17 +288,36 @@ public:
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 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();
+
+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 +338,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 +348,7 @@ private:
bool m_willSendRequestReturnsNull;
bool m_willSendRequestReturnsNullOnRedirect;
bool m_shouldStopProvisionalFrameLoads;
+ String m_willSendRequestHTTPBody;
bool m_policyDelegateEnabled;
bool m_policyDelegatePermissive;
@@ -327,9 +361,13 @@ private:
double m_databaseDefaultQuota;
double m_databaseMaxQuota;
+ bool m_shouldDecideNavigationPolicyAfterDelay { false };
+
bool m_userStyleSheetEnabled;
WKRetainPtr<WKStringRef> m_userStyleSheetLocation;
+ WKRetainPtr<WKArrayRef> m_allowedHosts;
+
PlatformTimerRef m_waitToDumpWatchdogTimer;
};
diff --git a/Tools/WebKitTestRunner/InjectedBundle/TextInputController.cpp b/Tools/WebKitTestRunner/InjectedBundle/TextInputController.cpp
index 0087aa301..f4e68f695 100644
--- a/Tools/WebKitTestRunner/InjectedBundle/TextInputController.cpp
+++ b/Tools/WebKitTestRunner/InjectedBundle/TextInputController.cpp
@@ -30,7 +30,7 @@
#include "InjectedBundlePage.h"
#include "JSTextInputController.h"
#include "StringFunctions.h"
-#include <WebKit2/WKBundlePagePrivate.h>
+#include <WebKit/WKBundlePagePrivate.h>
namespace WTR {
@@ -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/atk/AccessibilityControllerAtk.cpp b/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityControllerAtk.cpp
index 3573a2a5c..c1cb34951 100644
--- a/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityControllerAtk.cpp
+++ b/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityControllerAtk.cpp
@@ -33,33 +33,18 @@
#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);
+ // No longer implemented for ATK. Use addNotificationListener() instead to
+ // check that relevant ATK signals are being emmitted in response to events.
}
void AccessibilityController::resetToConsistentState()
@@ -99,7 +84,7 @@ static AtkObject* childElementById(AtkObject* parent, const char* id)
PassRefPtr<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;
@@ -122,7 +107,7 @@ JSRetainPtr<JSStringRef> AccessibilityController::platformName()
PassRefPtr<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));
@@ -130,7 +115,7 @@ PassRefPtr<AccessibilityUIElement> AccessibilityController::rootElement()
PassRefPtr<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..11988ba98 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,36 @@ 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(&paramValues[1])));
- signalValue.reset(g_strdup_printf("%d", g_value_get_boolean(&paramValues[2])));
if (!g_strcmp0(g_value_get_string(&paramValues[1]), "checked"))
notificationName = "CheckedStateChanged";
else if (!g_strcmp0(g_value_get_string(&paramValues[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(&paramValues[1])));
if (g_value_get_boolean(&paramValues[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(&paramValues[1])));
notificationName = !g_strcmp0(childrenChangedDetail, "add") ? "AXChildrenAdded" : "AXChildrenRemoved";
} else if (!g_strcmp0(signalQuery.signal_name, "property-change")) {
- signalName.reset(g_strdup_printf("property-change:%s", g_quark_to_string(signalHint->detail)));
if (!g_strcmp0(g_quark_to_string(signalHint->detail), "accessible-value"))
notificationName = "AXValueChanged";
} else if (!g_strcmp0(signalQuery.signal_name, "load-complete"))
notificationName = "AXLoadComplete";
else 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(&paramValues[1])));
+ GUniquePtr<char> signalValue(g_strdup_printf("%d", g_value_get_int(&paramValues[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 +140,6 @@ AccessibilityNotificationHandler::~AccessibilityNotificationHandler()
disconnectAccessibilityCallbacks();
}
-void AccessibilityNotificationHandler::logAccessibilityEvents()
-{
- connectAccessibilityCallbacks();
- loggingAccessibilityEvents = true;
-}
-
void AccessibilityNotificationHandler::setNotificationFunctionCallback(JSValueRef notificationFunctionCallback)
{
if (!notificationFunctionCallback) {
@@ -191,7 +151,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 +182,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 +217,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 +234,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..bb3869ecd 100644
--- a/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.h
+++ b/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityNotificationHandlerAtk.h
@@ -27,7 +27,7 @@
#include <atk/atkobject.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
namespace WTR {
@@ -42,7 +42,6 @@ public:
GRefPtr<AtkObject> platformElement() const { return m_platformElement; }
void setNotificationFunctionCallback(JSValueRef);
JSValueRef notificationFunctionCallback() const { return m_notificationFunctionCallback; }
- void logAccessibilityEvents();
private:
AccessibilityNotificationHandler();
diff --git a/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityUIElementAtk.cpp b/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityUIElementAtk.cpp
index 440377937..ded3a329d 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" },
@@ -172,9 +186,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 +197,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 +221,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 +236,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 +257,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 +273,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()), &currentValue, 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()), &currentValue);
@@ -258,6 +295,7 @@ void alterCurrentValue(PlatformUIElement element, int factor)
g_value_unset(&newValue);
g_value_unset(&increment);
g_value_unset(&currentValue);
+#endif
}
gchar* replaceCharactersForResults(gchar* str)
@@ -283,17 +321,17 @@ 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, "search"))
return landmarkStringSearch;
}
#endif
@@ -305,6 +343,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:
@@ -420,6 +460,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 +474,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 +485,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 +506,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 +625,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)
@@ -644,28 +764,16 @@ PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::childAtIndex(unsigned
return nullptr;
}
-PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
-{
- // FIXME: implement
- return nullptr;
-}
-
-PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
-{
- // FIXME: implement
- return nullptr;
-}
-
-PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index)
+static PassRefPtr<AccessibilityUIElement> accessibilityElementAtIndex(AtkObject* element, AtkRelationType relationType, 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,34 +781,71 @@ 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;
}
-PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::disclosedRowAtIndex(unsigned index)
+PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
{
// FIXME: implement
return nullptr;
}
-PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::rowAtIndex(unsigned index)
+PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
{
// FIXME: implement
return nullptr;
}
-PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::selectedChildAtIndex(unsigned index) const
+PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index)
+{
+ return accessibilityElementAtIndex(m_element.get(), ATK_RELATION_FLOWS_TO, index);
+}
+
+PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::ariaControlsElementAtIndex(unsigned index)
+{
+ return accessibilityElementAtIndex(m_element.get(), ATK_RELATION_CONTROLLER_FOR, index);
+}
+
+PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::disclosedRowAtIndex(unsigned index)
{
// FIXME: implement
return nullptr;
}
+PassRefPtr<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)) : nullptr;
+ }
+ }
+
+ return nullptr;
+}
+
+PassRefPtr<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()) : 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)
@@ -786,7 +931,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 +963,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,14 +987,40 @@ 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
@@ -852,8 +1041,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;
}
@@ -902,6 +1134,15 @@ JSRetainPtr<JSStringRef> AccessibilityUIElement::roleDescription()
return JSStringCreateWithCharacters(0, 0);
}
+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);
+}
+
JSRetainPtr<JSStringRef> AccessibilityUIElement::title()
{
if (!ATK_IS_OBJECT(m_element.get()))
@@ -1008,8 +1249,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 +1263,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 +1277,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 +1291,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 +1305,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 +1321,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 +1338,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 +1369,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,12 +1386,16 @@ 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()
@@ -1142,7 +1416,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 +1516,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 +1536,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 +1557,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 +1588,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)
+PassRefPtr<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;
@@ -1445,6 +1760,22 @@ 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);
+}
+
JSRetainPtr<JSStringRef> AccessibilityUIElement::accessibilityValue() const
{
// FIXME: implement
@@ -1558,7 +1889,7 @@ bool AccessibilityUIElement::hasPopup() const
return false;
String hasPopupValue = getAttributeSetValueForId(ATK_OBJECT(m_element.get()), ObjectAttributeType, "haspopup");
- return equalIgnoringCase(hasPopupValue, "true");
+ return equalLettersIgnoringASCIICase(hasPopupValue, "true");
}
void AccessibilityUIElement::takeFocus()
@@ -1582,6 +1913,12 @@ void AccessibilityUIElement::removeSelection()
}
// Text markers
+PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::lineTextMarkerRangeForTextMarker(AccessibilityTextMarker* textMarker)
+{
+ // FIXME: implement
+ return nullptr;
+}
+
PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::textMarkerRangeForElement(AccessibilityUIElement* element)
{
// FIXME: implement
@@ -1690,10 +2027,25 @@ PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::endTextMarker()
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
diff --git a/Tools/WebKitTestRunner/Options.cpp b/Tools/WebKitTestRunner/Options.cpp
index 8fa6e6e0f..53f0253ac 100644
--- a/Tools/WebKitTestRunner/Options.cpp
+++ b/Tools/WebKitTestRunner/Options.cpp
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2013 University of Szeged. All rights reserved.
* Copyright (C) 2013 Samsung Electronics. All rights reserved.
+ * Copyright (C) 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
@@ -31,10 +32,8 @@
namespace WTR {
-Options::Options(double defaultLongTimeout, double defaultShortTimeout)
- : longTimeout(defaultLongTimeout)
- , shortTimeout(defaultShortTimeout)
- , useWaitToDumpWatchdogTimer(true)
+Options::Options()
+ : useWaitToDumpWatchdogTimer(true)
, forceNoTimeout(false)
, verbose(false)
, gcBetweenTests(false)
@@ -43,28 +42,13 @@ Options::Options(double defaultLongTimeout, double defaultShortTimeout)
, forceComplexText(false)
, shouldUseAcceleratedDrawing(false)
, shouldUseRemoteLayerTree(false)
- , defaultLongTimeout(defaultLongTimeout)
- , defaultShortTimeout(defaultShortTimeout)
+ , shouldShowWebView(false)
{
}
-bool handleOptionTimeout(Options& options, const char*, const char* argument)
-{
- options.longTimeout = atoi(argument);
- // Scale up the short timeout to match.
- options.shortTimeout = options.defaultShortTimeout * options.longTimeout / options.defaultLongTimeout;
- return true;
-}
-
bool handleOptionNoTimeout(Options& options, const char*, const char*)
{
options.useWaitToDumpWatchdogTimer = false;
- return true;
-}
-
-bool handleOptionNoTimeoutAtAll(Options& options, const char*, const char*)
-{
- options.useWaitToDumpWatchdogTimer = false;
options.forceNoTimeout = true;
return true;
}
@@ -111,6 +95,18 @@ bool handleOptionRemoteLayerTree(Options& options, const char*, const char*)
return true;
}
+bool handleOptionShowWebView(Options& options, const char*, const char*)
+{
+ options.shouldShowWebView = true;
+ return true;
+}
+
+bool handleOptionAllowedHost(Options& options, const char*, const char* host)
+{
+ options.allowedHosts.push_back(host);
+ return true;
+}
+
bool handleOptionUnmatched(Options& options, const char* option, const char*)
{
if (option[0] && option[1] && option[0] == '-' && option[1] == '-')
@@ -122,9 +118,7 @@ bool handleOptionUnmatched(Options& options, const char* option, const char*)
OptionsHandler::OptionsHandler(Options& o)
: options(o)
{
- optionList.append(Option("--timeout", "Sets long timeout to <param> and scales short timeout.", handleOptionTimeout, true));
- optionList.append(Option("--no-timeout", "Disables timeout.", handleOptionNoTimeout));
- optionList.append(Option("--no-timeout-at-all", "Disables all timeouts.", handleOptionNoTimeoutAtAll));
+ optionList.append(Option("--no-timeout", "Disables all timeouts.", handleOptionNoTimeout));
optionList.append(Option("--verbose", "Turns on messages.", handleOptionVerbose));
optionList.append(Option("--gc-between-tests", "Garbage collection between tests.", handleOptionGcBetweenTests));
optionList.append(Option("--pixel-tests", "Check pixels.", handleOptionPixelTests));
@@ -133,6 +127,9 @@ OptionsHandler::OptionsHandler(Options& o)
optionList.append(Option("--complex-text", "Force complex tests.", handleOptionComplexText));
optionList.append(Option("--accelerated-drawing", "Use accelerated drawing.", handleOptionAcceleratedDrawing));
optionList.append(Option("--remote-layer-tree", "Use remote layer tree.", handleOptionRemoteLayerTree));
+ optionList.append(Option("--allowed-host", "Allows access to the specified host from tests.", handleOptionAllowedHost, true));
+ optionList.append(Option("--show-webview", "Show the WebView during test runs (for Debugging)", handleOptionShowWebView));
+
optionList.append(Option(0, 0, handleOptionUnmatched));
}
diff --git a/Tools/WebKitTestRunner/Options.h b/Tools/WebKitTestRunner/Options.h
index a89d25c77..5549fe464 100644
--- a/Tools/WebKitTestRunner/Options.h
+++ b/Tools/WebKitTestRunner/Options.h
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2013 University of Szeged. All rights reserved.
* Copyright (C) 2013 Samsung Electronics. All rights reserved.
+ * Copyright (C) 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
@@ -36,9 +37,7 @@
namespace WTR {
struct Options {
- Options(double, double);
- double longTimeout;
- double shortTimeout;
+ Options();
bool useWaitToDumpWatchdogTimer;
bool forceNoTimeout;
bool verbose;
@@ -48,9 +47,9 @@ struct Options {
bool forceComplexText;
bool shouldUseAcceleratedDrawing;
bool shouldUseRemoteLayerTree;
+ bool shouldShowWebView;
std::vector<std::string> paths;
- double defaultLongTimeout;
- double defaultShortTimeout;
+ std::vector<std::string> allowedHosts;
};
class Option {
diff --git a/Tools/WebKitTestRunner/PixelDumpSupport.cpp b/Tools/WebKitTestRunner/PixelDumpSupport.cpp
index 76974737f..37b3047cb 100644
--- a/Tools/WebKitTestRunner/PixelDumpSupport.cpp
+++ b/Tools/WebKitTestRunner/PixelDumpSupport.cpp
@@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
diff --git a/Tools/WebKitTestRunner/PixelDumpSupport.h b/Tools/WebKitTestRunner/PixelDumpSupport.h
index 41c6e38ea..324667f10 100644
--- a/Tools/WebKitTestRunner/PixelDumpSupport.h
+++ b/Tools/WebKitTestRunner/PixelDumpSupport.h
@@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
diff --git a/Tools/WebKitTestRunner/PlatformGTK.cmake b/Tools/WebKitTestRunner/PlatformGTK.cmake
new file mode 100644
index 000000000..84c9a86fa
--- /dev/null
+++ b/Tools/WebKitTestRunner/PlatformGTK.cmake
@@ -0,0 +1,60 @@
+add_custom_target(WebKitTestRunner-forwarding-headers
+ COMMAND ${PERL_EXECUTABLE} ${WEBKIT2_DIR}/Scripts/generate-forwarding-headers.pl --include-path ${WEBKIT_TESTRUNNER_DIR} --output ${FORWARDING_HEADERS_DIR} --platform gtk --platform soup
+)
+
+set(ForwardingHeadersForWebKitTestRunner_NAME WebKitTestRunner-forwarding-headers)
+
+list(APPEND WebKitTestRunner_SOURCES
+ ${WEBKIT_TESTRUNNER_DIR}/cairo/TestInvocationCairo.cpp
+
+ ${WEBKIT_TESTRUNNER_DIR}/gtk/EventSenderProxyGtk.cpp
+ ${WEBKIT_TESTRUNNER_DIR}/gtk/PlatformWebViewGtk.cpp
+ ${WEBKIT_TESTRUNNER_DIR}/gtk/TestControllerGtk.cpp
+ ${WEBKIT_TESTRUNNER_DIR}/gtk/main.cpp
+)
+
+list(APPEND WebKitTestRunner_INCLUDE_DIRECTORIES
+ ${FORWARDING_HEADERS_DIR}
+ ${WTF_DIR}/wtf/glib
+)
+
+list(APPEND WebKitTestRunner_SYSTEM_INCLUDE_DIRECTORIES
+ ${ATK_INCLUDE_DIRS}
+ ${CAIRO_INCLUDE_DIRS}
+ ${GTK3_INCLUDE_DIRS}
+ ${GLIB_INCLUDE_DIRS}
+)
+
+list(APPEND WebKitTestRunner_LIBRARIES
+ ${ATK_LIBRARIES}
+ ${CAIRO_LIBRARIES}
+ ${GTK3_LIBRARIES}
+ ${GLIB_LIBRARIES}
+ WTF
+ WebCorePlatformGTK
+)
+
+set(WebKitTestRunnerInjectedBundle_LIBRARIES
+ ${ATK_LIBRARIES}
+ ${FONTCONFIG_LIBRARIES}
+ ${GLIB_LIBRARIES}
+ ${GTK3_LIBRARIES}
+ WebCoreTestSupport
+ WebKit2
+)
+
+list(APPEND WebKitTestRunnerInjectedBundle_SOURCES
+ ${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/atk/AccessibilityControllerAtk.cpp
+ ${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/atk/AccessibilityNotificationHandlerAtk.cpp
+ ${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/atk/AccessibilityUIElementAtk.cpp
+
+ ${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/gtk/ActivateFontsGtk.cpp
+ ${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/gtk/InjectedBundleGtk.cpp
+ ${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/gtk/InjectedBundleUtilities.cpp
+ ${WEBKIT_TESTRUNNER_INJECTEDBUNDLE_DIR}/gtk/TestRunnerGtk.cpp
+)
+
+add_definitions(
+ -DFONTS_CONF_DIR="${TOOLS_DIR}/WebKitTestRunner/gtk/fonts"
+ -DTOP_LEVEL_DIR="${CMAKE_SOURCE_DIR}"
+)
diff --git a/Tools/WebKitTestRunner/PlatformWebView.h b/Tools/WebKitTestRunner/PlatformWebView.h
index fa8d1236c..c826a1ab8 100644
--- a/Tools/WebKitTestRunner/PlatformWebView.h
+++ b/Tools/WebKitTestRunner/PlatformWebView.h
@@ -26,29 +26,28 @@
#ifndef PlatformWebView_h
#define PlatformWebView_h
-#include <WebKit2/WKRetainPtr.h>
+#include "TestOptions.h"
+#include <WebKit/WKRetainPtr.h>
-#if defined(__APPLE__) && __APPLE__
-#ifdef __OBJC__
-@class WKView;
-@class WebKitTestRunnerWindow;
+#if PLATFORM(COCOA) && !defined(BUILDING_GTK__)
+#include <WebKit/WKFoundation.h>
+OBJC_CLASS NSView;
+OBJC_CLASS UIView;
+OBJC_CLASS TestRunnerWKWebView;
+OBJC_CLASS WKWebViewConfiguration;
+OBJC_CLASS WebKitTestRunnerWindow;
+
+#if WK_API_ENABLED
+typedef TestRunnerWKWebView *PlatformWKView;
#else
-class WKView;
-class WebKitTestRunnerWindow;
+typedef NSView *PlatformWKView;
#endif
-typedef WKView* PlatformWKView;
-typedef WebKitTestRunnerWindow* PlatformWindow;
+typedef WebKitTestRunnerWindow *PlatformWindow;
#elif defined(BUILDING_GTK__)
typedef struct _GtkWidget GtkWidget;
typedef WKViewRef PlatformWKView;
typedef GtkWidget* PlatformWindow;
#elif PLATFORM(EFL)
-typedef struct _Ecore_Evas Ecore_Evas;
-#if USE(EO)
-typedef struct _Eo_Opaque Evas_Object;
-#else
-typedef struct _Evas_Object Evas_Object;
-#endif
typedef Evas_Object* PlatformWKView;
typedef Ecore_Evas* PlatformWindow;
#endif
@@ -57,7 +56,11 @@ namespace WTR {
class PlatformWebView {
public:
- PlatformWebView(WKContextRef, WKPageGroupRef, WKPageRef relatedPage, WKDictionaryRef options = 0);
+#if PLATFORM(COCOA)
+ PlatformWebView(WKWebViewConfiguration*, const TestOptions&);
+#else
+ PlatformWebView(WKPageConfigurationRef, const TestOptions&);
+#endif
~PlatformWebView();
WKPageRef page();
@@ -66,9 +69,6 @@ public:
void resizeTo(unsigned width, unsigned height);
void focus();
- // Window snapshot is always enabled by default on all other platform.
- static bool windowSnapshotEnabled() { return true; }
-
WKRect windowFrame();
void setWindowFrame(WKRect);
@@ -77,23 +77,29 @@ public:
void addChromeInputField();
void removeChromeInputField();
void makeWebViewFirstResponder();
- void setWindowIsKey(bool isKey) { m_windowIsKey = isKey; }
+ void setWindowIsKey(bool);
bool windowIsKey() const { return m_windowIsKey; }
-#if PLATFORM(MAC) || PLATFORM(EFL)
- bool viewSupportsOptions(WKDictionaryRef) const;
-#else
- bool viewSupportsOptions(WKDictionaryRef) const { return true; }
-#endif
+ bool viewSupportsOptions(const TestOptions&) const;
WKRetainPtr<WKImageRef> windowSnapshotImage();
- WKDictionaryRef options() const { return m_options.get(); }
+ const TestOptions& options() const { return m_options; }
+
+ void changeWindowScaleIfNeeded(float newScale);
+ void setNavigationGesturesEnabled(bool);
+
+#if PLATFORM(GTK)
+ void dismissAllPopupMenus();
+#endif
private:
+ void forceWindowFramesChanged();
+
PlatformWKView m_view;
PlatformWindow m_window;
bool m_windowIsKey;
- WKRetainPtr<WKDictionaryRef> m_options;
+ const TestOptions m_options;
+
#if PLATFORM(EFL)
bool m_usingFixedLayout;
#endif
diff --git a/Tools/WebKitTestRunner/StringFunctions.h b/Tools/WebKitTestRunner/StringFunctions.h
index 551d86740..dce761b36 100644
--- a/Tools/WebKitTestRunner/StringFunctions.h
+++ b/Tools/WebKitTestRunner/StringFunctions.h
@@ -29,12 +29,12 @@
#include <JavaScriptCore/JSRetainPtr.h>
#include <JavaScriptCore/JavaScript.h>
+#include <WebKit/WKRetainPtr.h>
+#include <WebKit/WKString.h>
+#include <WebKit/WKStringPrivate.h>
+#include <WebKit/WKURL.h>
#include <sstream>
#include <string>
-#include <WebKit2/WKRetainPtr.h>
-#include <WebKit2/WKString.h>
-#include <WebKit2/WKStringPrivate.h>
-#include <WebKit2/WKURL.h>
#include <wtf/Platform.h>
#include <wtf/StdLibExtras.h>
#include <wtf/Vector.h>
diff --git a/Tools/WebKitTestRunner/TestController.cpp b/Tools/WebKitTestRunner/TestController.cpp
index 397815e63..ba20bbd0d 100644
--- a/Tools/WebKitTestRunner/TestController.cpp
+++ b/Tools/WebKitTestRunner/TestController.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010, 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
@@ -31,33 +31,49 @@
#include "PlatformWebView.h"
#include "StringFunctions.h"
#include "TestInvocation.h"
-#include <WebKit2/WKAuthenticationChallenge.h>
-#include <WebKit2/WKAuthenticationDecisionListener.h>
-#include <WebKit2/WKContextPrivate.h>
-#include <WebKit2/WKCredential.h>
-#include <WebKit2/WKIconDatabase.h>
-#include <WebKit2/WKNotification.h>
-#include <WebKit2/WKNotificationManager.h>
-#include <WebKit2/WKNotificationPermissionRequest.h>
-#include <WebKit2/WKNumber.h>
-#include <WebKit2/WKPageGroup.h>
-#include <WebKit2/WKPagePrivate.h>
-#include <WebKit2/WKPreferencesPrivate.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKArray.h>
+#include <WebKit/WKAuthenticationChallenge.h>
+#include <WebKit/WKAuthenticationDecisionListener.h>
+#include <WebKit/WKContextConfigurationRef.h>
+#include <WebKit/WKContextPrivate.h>
+#include <WebKit/WKCookieManager.h>
+#include <WebKit/WKCredential.h>
+#include <WebKit/WKIconDatabase.h>
+#include <WebKit/WKNavigationResponseRef.h>
+#include <WebKit/WKNotification.h>
+#include <WebKit/WKNotificationManager.h>
+#include <WebKit/WKNotificationPermissionRequest.h>
+#include <WebKit/WKNumber.h>
+#include <WebKit/WKPageGroup.h>
+#include <WebKit/WKPageInjectedBundleClient.h>
+#include <WebKit/WKPagePrivate.h>
+#include <WebKit/WKPluginInformation.h>
+#include <WebKit/WKPreferencesRefPrivate.h>
+#include <WebKit/WKProtectionSpace.h>
+#include <WebKit/WKRetainPtr.h>
+#include <WebKit/WKSecurityOriginRef.h>
+#include <WebKit/WKUserMediaPermissionCheck.h>
#include <algorithm>
#include <cstdio>
#include <ctype.h>
+#include <fstream>
+#include <runtime/InitializeThreading.h>
#include <stdlib.h>
#include <string>
-#include <wtf/PassOwnPtr.h>
+#include <unistd.h>
+#include <wtf/MainThread.h>
+#include <wtf/RunLoop.h>
+#include <wtf/TemporaryChange.h>
#include <wtf/text/CString.h>
+#include <wtf/text/WTFString.h>
-#if PLATFORM(MAC)
-#include <WebKit2/WKPagePrivateMac.h>
+#if PLATFORM(COCOA)
+#include <WebKit/WKContextPrivateMac.h>
+#include <WebKit/WKPagePrivateMac.h>
#endif
-#if !PLATFORM(MAC)
-#include <WebKit2/WKTextChecker.h>
+#if !PLATFORM(COCOA)
+#include <WebKit/WKTextChecker.h>
#endif
namespace WTR {
@@ -68,12 +84,13 @@ const unsigned TestController::viewHeight = 600;
const unsigned TestController::w3cSVGViewWidth = 480;
const unsigned TestController::w3cSVGViewHeight = 360;
-// defaultLongTimeout + defaultShortTimeout should be less than 80,
-// the default timeout value of the test harness so we can detect an
-// unresponsive web process.
-static const double defaultLongTimeout = 60;
-static const double defaultShortTimeout = 15;
-static const double defaultNoTimeout = -1;
+#if ASAN_ENABLED
+const double TestController::shortTimeout = 10.0;
+#else
+const double TestController::shortTimeout = 5.0;
+#endif
+
+const double TestController::noTimeout = -1;
static WKURLRef blankURL()
{
@@ -81,9 +98,15 @@ static WKURLRef blankURL()
return staticBlankURL;
}
+static WKDataRef copyWebCryptoMasterKey(WKPageRef, const void*)
+{
+ // Any 128 bit key would do, all we need for testing is to implement the callback.
+ return WKDataCreate((const uint8_t*)"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", 16);
+}
+
static TestController* controller;
-TestController& TestController::shared()
+TestController& TestController::singleton()
{
ASSERT(controller);
return *controller;
@@ -97,12 +120,8 @@ TestController::TestController(int argc, const char* argv[])
, m_shouldDumpPixelsForAllTests(false)
, m_state(Initial)
, m_doneResetting(false)
- , m_longTimeout(defaultLongTimeout)
- , m_shortTimeout(defaultShortTimeout)
- , m_noTimeout(defaultNoTimeout)
, m_useWaitToDumpWatchdogTimer(true)
, m_forceNoTimeout(false)
- , m_timeout(0)
, m_didPrintWebProcessCrashedMessage(false)
, m_shouldExitWhenWebProcessCrashes(true)
, m_beforeUnloadReturnValue(true)
@@ -115,6 +134,8 @@ TestController::TestController(int argc, const char* argv[])
, m_forceComplexText(false)
, m_shouldUseAcceleratedDrawing(false)
, m_shouldUseRemoteLayerTree(false)
+ , m_shouldLogHistoryClientCallbacks(false)
+ , m_shouldShowWebView(false)
{
initialize(argc, argv);
controller = this;
@@ -124,7 +145,9 @@ TestController::TestController(int argc, const char* argv[])
TestController::~TestController()
{
- WKIconDatabaseClose(WKContextGetIconDatabase(m_context.get()));
+ // The context will be null if WebKitTestRunner was in server mode, but ran no tests.
+ if (m_context)
+ WKIconDatabaseClose(WKContextGetIconDatabase(m_context.get()));
platformDestroy();
}
@@ -144,7 +167,7 @@ static void setWindowFrame(WKPageRef page, WKRect frame, const void* clientInfo)
static bool runBeforeUnloadConfirmPanel(WKPageRef page, WKStringRef message, WKFrameRef frame, const void*)
{
printf("CONFIRM NAVIGATION: %s\n", toSTD(message).c_str());
- return TestController::shared().beforeUnloadReturnValue();
+ return TestController::singleton().beforeUnloadReturnValue();
}
void TestController::runModal(WKPageRef page, const void* clientInfo)
@@ -177,34 +200,39 @@ static void unfocus(WKPageRef page, const void* clientInfo)
static void decidePolicyForGeolocationPermissionRequest(WKPageRef, WKFrameRef, WKSecurityOriginRef, WKGeolocationPermissionRequestRef permissionRequest, const void* clientInfo)
{
- TestController::shared().handleGeolocationPermissionRequest(permissionRequest);
+ TestController::singleton().handleGeolocationPermissionRequest(permissionRequest);
}
-int TestController::getCustomTimeout()
+static void decidePolicyForUserMediaPermissionRequest(WKPageRef, WKFrameRef, WKSecurityOriginRef origin, WKUserMediaPermissionRequestRef permissionRequest, const void* clientInfo)
{
- return m_timeout;
+ TestController::singleton().handleUserMediaPermissionRequest(origin, permissionRequest);
}
-WKPageRef TestController::createOtherPage(WKPageRef oldPage, WKURLRequestRef, WKDictionaryRef, WKEventModifiers, WKEventMouseButton, const void* clientInfo)
+static void checkUserMediaPermissionForOrigin(WKPageRef, WKFrameRef, WKSecurityOriginRef origin, WKUserMediaPermissionCheckRef checkRequest, const void*)
+{
+ TestController::singleton().handleCheckOfUserMediaPermissionForOrigin(origin, checkRequest);
+}
+
+WKPageRef TestController::createOtherPage(WKPageRef oldPage, WKPageConfigurationRef configuration, WKNavigationActionRef navigationAction, WKWindowFeaturesRef windowFeatures, const void *clientInfo)
{
PlatformWebView* parentView = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
- PlatformWebView* view = new PlatformWebView(WKPageGetContext(oldPage), WKPageGetPageGroup(oldPage), oldPage, parentView->options());
+ PlatformWebView* view = platformCreateOtherPage(parentView, configuration, parentView->options());
WKPageRef newPage = view->page();
view->resizeTo(800, 600);
- WKPageUIClientV2 otherPageUIClient = {
- { 2, view },
+ WKPageUIClientV6 otherPageUIClient = {
+ { 6, view },
0, // createNewPage_deprecatedForUseWithV0
0, // showPage
closeOtherPage,
0, // takeFocus
focus,
unfocus,
- 0, // runJavaScriptAlert
- 0, // runJavaScriptConfirm
- 0, // runJavaScriptPrompt
+ 0, // runJavaScriptAlert_deprecatedForUseWithV0
+ 0, // runJavaScriptAlert_deprecatedForUseWithV0
+ 0, // runJavaScriptAlert_deprecatedForUseWithV0
0, // setStatusText
0, // mouseDidMoveOverElement_deprecatedForUseWithV0
0, // missingPluginButtonClicked
@@ -235,18 +263,62 @@ WKPageRef TestController::createOtherPage(WKPageRef oldPage, WKURLRequestRef, WK
0, // didCompleteRubberBandForMainFrame
0, // saveDataToFileInDownloadsFolder
0, // shouldInterruptJavaScript
- createOtherPage,
+ 0, // createNewPage_deprecatedForUseWithV1
0, // mouseDidMoveOverElement
0, // decidePolicyForNotificationPermissionRequest
0, // unavailablePluginButtonClicked_deprecatedForUseWithV1
0, // showColorPicker
0, // hideColorPicker
0, // unavailablePluginButtonClicked
+ 0, // pinnedStateDidChange
+ 0, // didBeginTrackingPotentialLongMousePress
+ 0, // didRecognizeLongMousePress
+ 0, // didCancelTrackingPotentialLongMousePress
+ 0, // isPlayingAudioDidChange
+ decidePolicyForUserMediaPermissionRequest,
+ 0, // didClickAutofillButton
+ 0, // runJavaScriptAlert
+ 0, // runJavaScriptConfirm
+ 0, // runJavaScriptPrompt
+ 0, // mediaSessionMetadataDidChange
+ createOtherPage,
+ 0, // runJavaScriptAlert
+ 0, // runJavaScriptConfirm
+ 0, // runJavaScriptPrompt
+ checkUserMediaPermissionForOrigin,
};
WKPageSetPageUIClient(newPage, &otherPageUIClient.base);
+
+ WKPageNavigationClientV0 pageNavigationClient = {
+ { 0, &TestController::singleton() },
+ decidePolicyForNavigationAction,
+ decidePolicyForNavigationResponse,
+ decidePolicyForPluginLoad,
+ 0, // didStartProvisionalNavigation
+ 0, // didReceiveServerRedirectForProvisionalNavigation
+ 0, // didFailProvisionalNavigation
+ 0, // didCommitNavigation
+ 0, // didFinishNavigation
+ 0, // didFailNavigation
+ 0, // didFailProvisionalLoadInSubframe
+ 0, // didFinishDocumentLoad
+ 0, // didSameDocumentNavigation
+ 0, // renderingProgressDidChange
+ canAuthenticateAgainstProtectionSpace,
+ didReceiveAuthenticationChallenge,
+ processDidCrash,
+ copyWebCryptoMasterKey,
+ didBeginNavigationGesture,
+ willEndNavigationGesture,
+ didEndNavigationGesture,
+ didRemoveNavigationGestureSnapshot
+ };
+ WKPageSetPageNavigationClient(newPage, &pageNavigationClient.base);
view->didInitializeClients();
+ TestController::singleton().updateWindowScaleForTest(view, *TestController::singleton().m_currentInvocation);
+
WKRetain(newPage);
return newPage;
}
@@ -262,12 +334,15 @@ const char* TestController::libraryPathForTesting()
return platformLibraryPathForTesting();
}
-
void TestController::initialize(int argc, const char* argv[])
{
+ JSC::initializeThreading();
+ WTF::initializeMainThread();
+ RunLoop::initializeMainRunLoop();
+
platformInitialize();
- Options options(defaultLongTimeout, defaultShortTimeout);
+ Options options;
OptionsHandler optionsHandler(options);
if (argc < 2) {
@@ -277,8 +352,6 @@ void TestController::initialize(int argc, const char* argv[])
if (!optionsHandler.parse(argc, argv))
exit(1);
- m_longTimeout = options.longTimeout;
- m_shortTimeout = options.shortTimeout;
m_useWaitToDumpWatchdogTimer = options.useWaitToDumpWatchdogTimer;
m_forceNoTimeout = options.forceNoTimeout;
m_verbose = options.verbose;
@@ -288,6 +361,8 @@ void TestController::initialize(int argc, const char* argv[])
m_shouldUseAcceleratedDrawing = options.shouldUseAcceleratedDrawing;
m_shouldUseRemoteLayerTree = options.shouldUseRemoteLayerTree;
m_paths = options.paths;
+ m_allowedHosts = options.allowedHosts;
+ m_shouldShowWebView = options.shouldShowWebView;
if (options.printSupportedFeatures) {
// FIXME: On Windows, DumpRenderTree uses this to expose whether it supports 3d
@@ -307,28 +382,42 @@ void TestController::initialize(int argc, const char* argv[])
WKRetainPtr<WKStringRef> pageGroupIdentifier(AdoptWK, WKStringCreateWithUTF8CString("WebKitTestRunnerPageGroup"));
m_pageGroup.adopt(WKPageGroupCreateWithIdentifier(pageGroupIdentifier.get()));
+}
- m_context.adopt(WKContextCreateWithInjectedBundlePath(injectedBundlePath()));
- m_geolocationProvider = adoptPtr(new GeolocationProviderMock(m_context.get()));
-
-#if PLATFORM(IOS) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED > 1080)
- WKContextSetUsesNetworkProcess(m_context.get(), true);
- WKContextSetProcessModel(m_context.get(), kWKProcessModelMultipleSecondaryProcesses);
-#endif
+WKRetainPtr<WKContextConfigurationRef> TestController::generateContextConfiguration() const
+{
+ auto configuration = adoptWK(WKContextConfigurationCreate());
+ WKContextConfigurationSetInjectedBundlePath(configuration.get(), injectedBundlePath());
+ WKContextConfigurationSetFullySynchronousModeIsAllowedForTesting(configuration.get(), true);
if (const char* dumpRenderTreeTemp = libraryPathForTesting()) {
String temporaryFolder = String::fromUTF8(dumpRenderTreeTemp);
- // WebCore::pathByAppendingComponent is not used here because of the namespace,
- // which leads us to this ugly #ifdef and file path concatenation.
const char separator = '/';
- WKContextSetApplicationCacheDirectory(m_context.get(), toWK(temporaryFolder + separator + "ApplicationCache").get());
- WKContextSetDatabaseDirectory(m_context.get(), toWK(temporaryFolder + separator + "Databases").get());
- WKContextSetLocalStorageDirectory(m_context.get(), toWK(temporaryFolder + separator + "LocalStorage").get());
- WKContextSetDiskCacheDirectory(m_context.get(), toWK(temporaryFolder + separator + "Cache").get());
- WKContextSetCookieStorageDirectory(m_context.get(), toWK(temporaryFolder + separator + "Cookies").get());
- WKContextSetIconDatabasePath(m_context.get(), toWK(temporaryFolder + separator + "IconDatabase" + separator + "WebpageIcons.db").get());
+ WKContextConfigurationSetApplicationCacheDirectory(configuration.get(), toWK(temporaryFolder + separator + "ApplicationCache").get());
+ WKContextConfigurationSetDiskCacheDirectory(configuration.get(), toWK(temporaryFolder + separator + "Cache").get());
+ WKContextConfigurationSetIndexedDBDatabaseDirectory(configuration.get(), toWK(temporaryFolder + separator + "Databases" + separator + "IndexedDB").get());
+ WKContextConfigurationSetLocalStorageDirectory(configuration.get(), toWK(temporaryFolder + separator + "LocalStorage").get());
+ WKContextConfigurationSetWebSQLDatabaseDirectory(configuration.get(), toWK(temporaryFolder + separator + "Databases" + separator + "WebSQL").get());
+ WKContextConfigurationSetMediaKeysStorageDirectory(configuration.get(), toWK(temporaryFolder + separator + "MediaKeys").get());
+ }
+ return configuration;
+}
+
+WKRetainPtr<WKPageConfigurationRef> TestController::generatePageConfiguration(WKContextConfigurationRef configuration)
+{
+ m_context = platformAdjustContext(adoptWK(WKContextCreateWithConfiguration(configuration)).get(), configuration);
+
+ m_geolocationProvider = std::make_unique<GeolocationProviderMock>(m_context.get());
+
+ if (const char* dumpRenderTreeTemp = libraryPathForTesting()) {
+ String temporaryFolder = String::fromUTF8(dumpRenderTreeTemp);
+
+ // FIXME: This should be migrated to WKContextConfigurationRef.
+ // Disable icon database to avoid fetching <http://127.0.0.1:8000/favicon.ico> and making tests flaky.
+ // Invividual tests can enable it using testRunner.setIconDatabaseEnabled, although it's not currently supported in WebKitTestRunner.
+ WKContextSetIconDatabasePath(m_context.get(), toWK(emptyString()).get());
}
WKContextUseTestingNetworkSession(m_context.get());
@@ -344,6 +433,25 @@ void TestController::initialize(int argc, const char* argv[])
};
WKContextSetInjectedBundleClient(m_context.get(), &injectedBundleClient.base);
+ WKContextClientV1 contextClient = {
+ { 1, this },
+ 0, // plugInAutoStartOriginHashesChanged
+ networkProcessDidCrash,
+ 0, // plugInInformationBecameAvailable
+ 0, // copyWebCryptoMasterKey
+ };
+ WKContextSetClient(m_context.get(), &contextClient.base);
+
+ WKContextHistoryClientV0 historyClient = {
+ { 0, this },
+ didNavigateWithNavigationData,
+ didPerformClientRedirect,
+ didPerformServerRedirect,
+ didUpdateHistoryTitle,
+ 0, // populateVisitedLinks
+ };
+ WKContextSetHistoryClient(m_context.get(), &historyClient.base);
+
WKNotificationManagerRef notificationManager = WKContextGetNotificationManager(m_context.get());
WKNotificationProviderV0 notificationKit = m_webNotificationProvider.provider();
WKNotificationManagerSetProvider(notificationManager, &notificationKit.base);
@@ -354,34 +462,40 @@ void TestController::initialize(int argc, const char* argv[])
if (m_forceComplexText)
WKContextSetAlwaysUsesComplexTextCodePath(m_context.get(), true);
- // Some preferences (notably mock scroll bars setting) currently cannot be re-applied to an existing view, so we need to set them now.
- resetPreferencesToConsistentValues();
-
- WKRetainPtr<WKMutableDictionaryRef> viewOptions;
- if (m_shouldUseRemoteLayerTree) {
- viewOptions = adoptWK(WKMutableDictionaryCreate());
- WKRetainPtr<WKStringRef> useRemoteLayerTreeKey = adoptWK(WKStringCreateWithUTF8CString("RemoteLayerTree"));
- WKRetainPtr<WKBooleanRef> useRemoteLayerTreeValue = adoptWK(WKBooleanCreate(m_shouldUseRemoteLayerTree));
- WKDictionarySetItem(viewOptions.get(), useRemoteLayerTreeKey.get(), useRemoteLayerTreeValue.get());
- }
-
- createWebViewWithOptions(viewOptions.get());
+ auto pageConfiguration = adoptWK(WKPageConfigurationCreate());
+ WKPageConfigurationSetContext(pageConfiguration.get(), m_context.get());
+ WKPageConfigurationSetPageGroup(pageConfiguration.get(), m_pageGroup.get());
+ WKPageConfigurationSetUserContentController(pageConfiguration.get(), adoptWK(WKUserContentControllerCreate()).get());
+ return pageConfiguration;
}
-void TestController::createWebViewWithOptions(WKDictionaryRef options)
+void TestController::createWebViewWithOptions(const TestOptions& options)
{
- m_mainWebView = adoptPtr(new PlatformWebView(m_context.get(), m_pageGroup.get(), 0, options));
- WKPageUIClientV2 pageUIClient = {
- { 2, m_mainWebView.get() },
+ auto contextConfiguration = generateContextConfiguration();
+
+ WKRetainPtr<WKMutableArrayRef> overrideLanguages = adoptWK(WKMutableArrayCreate());
+ for (auto& language : options.overrideLanguages)
+ WKArrayAppendItem(overrideLanguages.get(), adoptWK(WKStringCreateWithUTF8CString(language.utf8().data())).get());
+ WKContextConfigurationSetOverrideLanguages(contextConfiguration.get(), overrideLanguages.get());
+
+ auto configuration = generatePageConfiguration(contextConfiguration.get());
+
+ // Some preferences (notably mock scroll bars setting) currently cannot be re-applied to an existing view, so we need to set them now.
+ // FIXME: Migrate these preferences to WKContextConfigurationRef.
+ resetPreferencesToConsistentValues();
+
+ platformCreateWebView(configuration.get(), options);
+ WKPageUIClientV6 pageUIClient = {
+ { 6, m_mainWebView.get() },
0, // createNewPage_deprecatedForUseWithV0
0, // showPage
0, // close
0, // takeFocus
focus,
unfocus,
- 0, // runJavaScriptAlert
- 0, // runJavaScriptConfirm
- 0, // runJavaScriptPrompt
+ 0, // runJavaScriptAlert_deprecatedForUseWithV0
+ 0, // runJavaScriptAlert_deprecatedForUseWithV0
+ 0, // runJavaScriptAlert_deprecatedForUseWithV0
0, // setStatusText
0, // mouseDidMoveOverElement_deprecatedForUseWithV0
0, // missingPluginButtonClicked
@@ -412,98 +526,109 @@ void TestController::createWebViewWithOptions(WKDictionaryRef options)
0, // didCompleteRubberBandForMainFrame
0, // saveDataToFileInDownloadsFolder
0, // shouldInterruptJavaScript
- createOtherPage,
+ 0, // createNewPage_deprecatedForUseWithV1
0, // mouseDidMoveOverElement
decidePolicyForNotificationPermissionRequest, // decidePolicyForNotificationPermissionRequest
0, // unavailablePluginButtonClicked_deprecatedForUseWithV1
0, // showColorPicker
0, // hideColorPicker
unavailablePluginButtonClicked,
+ 0, // pinnedStateDidChange
+ 0, // didBeginTrackingPotentialLongMousePress
+ 0, // didRecognizeLongMousePress
+ 0, // didCancelTrackingPotentialLongMousePress
+ 0, // isPlayingAudioDidChange
+ decidePolicyForUserMediaPermissionRequest,
+ 0, // didClickAutofillButton
+ 0, // runJavaScriptAlert
+ 0, // runJavaScriptConfirm
+ 0, // runJavaScriptPrompt
+ 0, // mediaSessionMetadataDidChange
+ createOtherPage,
+ 0, // runJavaScriptAlert
+ 0, // runJavaScriptConfirm
+ 0, // runJavaScriptPrompt
+ checkUserMediaPermissionForOrigin,
};
WKPageSetPageUIClient(m_mainWebView->page(), &pageUIClient.base);
- WKPageLoaderClientV4 pageLoaderClient = {
- { 4, this },
- 0, // didStartProvisionalLoadForFrame
- 0, // didReceiveServerRedirectForProvisionalLoadForFrame
- 0, // didFailProvisionalLoadWithErrorForFrame
- didCommitLoadForFrame,
- 0, // didFinishDocumentLoadForFrame
- didFinishLoadForFrame,
- 0, // didFailLoadWithErrorForFrame
- 0, // didSameDocumentNavigationForFrame
- 0, // didReceiveTitleForFrame
- 0, // didFirstLayoutForFrame
- 0, // didFirstVisuallyNonEmptyLayoutForFrame
- 0, // didRemoveFrameFromHierarchy
- 0, // didFailToInitializePlugin
- 0, // didDisplayInsecureContentForFrame
- 0, // canAuthenticateAgainstProtectionSpaceInFrame
- didReceiveAuthenticationChallengeInFrame, // didReceiveAuthenticationChallengeInFrame
- 0, // didStartProgress
- 0, // didChangeProgress
- 0, // didFinishProgress
- 0, // didBecomeUnresponsive
- 0, // didBecomeResponsive
+ WKPageNavigationClientV0 pageNavigationClient = {
+ { 0, this },
+ decidePolicyForNavigationAction,
+ decidePolicyForNavigationResponse,
+ decidePolicyForPluginLoad,
+ 0, // didStartProvisionalNavigation
+ 0, // didReceiveServerRedirectForProvisionalNavigation
+ 0, // didFailProvisionalNavigation
+ didCommitNavigation,
+ didFinishNavigation,
+ 0, // didFailNavigation
+ 0, // didFailProvisionalLoadInSubframe
+ 0, // didFinishDocumentLoad
+ 0, // didSameDocumentNavigation
+ 0, // renderingProgressDidChange
+ canAuthenticateAgainstProtectionSpace,
+ didReceiveAuthenticationChallenge,
processDidCrash,
- 0, // didChangeBackForwardList
- 0, // shouldGoToBackForwardListItem
- 0, // didRunInsecureContentForFrame
- 0, // didDetectXSSForFrame
- 0, // didNewFirstVisuallyNonEmptyLayout_unavailable
- 0, // willGoToBackForwardListItem
- 0, // interactionOccurredWhileProcessUnresponsive
- 0, // pluginDidFail_deprecatedForUseWithV1
- 0, // didReceiveIntentForFrame
- 0, // registerIntentServiceForFrame
- 0, // didLayout
- 0, // pluginLoadPolicy_deprecatedForUseWithV2
- 0, // pluginDidFail
- pluginLoadPolicy, // pluginLoadPolicy
- 0, // webGLLoadPolicy
+ copyWebCryptoMasterKey,
+ didBeginNavigationGesture,
+ willEndNavigationGesture,
+ didEndNavigationGesture,
+ didRemoveNavigationGestureSnapshot
};
- WKPageSetPageLoaderClient(m_mainWebView->page(), &pageLoaderClient.base);
+ WKPageSetPageNavigationClient(m_mainWebView->page(), &pageNavigationClient.base);
- WKPagePolicyClientV1 pagePolicyClient = {
- { 1, this },
- 0, // decidePolicyForNavigationAction_deprecatedForUseWithV0
- 0, // decidePolicyForNewWindowAction
- 0, // decidePolicyForResponse_deprecatedForUseWithV0
- 0, // unableToImplementPolicy
- decidePolicyForNavigationAction,
- decidePolicyForResponse,
+
+ // this should just be done on the page?
+ WKPageInjectedBundleClientV0 injectedBundleClient = {
+ { 0, this },
+ didReceivePageMessageFromInjectedBundle,
+ didReceiveSynchronousPageMessageFromInjectedBundle
};
- WKPageSetPagePolicyClient(m_mainWebView->page(), &pagePolicyClient.base);
+ WKPageSetPageInjectedBundleClient(m_mainWebView->page(), &injectedBundleClient.base);
m_mainWebView->didInitializeClients();
+
+ // Generally, the tests should default to running at 1x. updateWindowScaleForTest() will adjust the scale to
+ // something else for specific tests that need to run at a different window scale.
+ m_mainWebView->changeWindowScaleIfNeeded(1);
}
-void TestController::ensureViewSupportsOptions(WKDictionaryRef options)
+void TestController::ensureViewSupportsOptionsForTest(const TestInvocation& test)
{
- if (m_mainWebView && !m_mainWebView->viewSupportsOptions(options)) {
- WKPageSetPageUIClient(m_mainWebView->page(), 0);
- WKPageSetPageLoaderClient(m_mainWebView->page(), 0);
- WKPageSetPagePolicyClient(m_mainWebView->page(), 0);
+ auto options = test.options();
+
+ if (m_mainWebView) {
+ if (m_mainWebView->viewSupportsOptions(options))
+ return;
+
+ WKPageSetPageUIClient(m_mainWebView->page(), nullptr);
+ WKPageSetPageNavigationClient(m_mainWebView->page(), nullptr);
WKPageClose(m_mainWebView->page());
-
- m_mainWebView = nullptr;
- createWebViewWithOptions(options);
- resetStateToConsistentValues();
+ m_mainWebView = nullptr;
}
+
+ createWebViewWithOptions(options);
+
+ if (!resetStateToConsistentValues())
+ TestInvocation::dumpWebProcessUnresponsiveness("<unknown> - TestController::run - Failed to reset state to consistent values\n");
}
void TestController::resetPreferencesToConsistentValues()
{
// Reset preferences
- WKPreferencesRef preferences = WKPageGroupGetPreferences(m_pageGroup.get());
+ WKPreferencesRef preferences = platformPreferences();
WKPreferencesResetTestRunnerOverrides(preferences);
+ WKPreferencesSetPageVisibilityBasedProcessSuppressionEnabled(preferences, false);
WKPreferencesSetOfflineWebApplicationCacheEnabled(preferences, true);
WKPreferencesSetFontSmoothingLevel(preferences, kWKFontSmoothingLevelNoSubpixelAntiAliasing);
+ WKPreferencesSetAntialiasedFontDilationEnabled(preferences, false);
WKPreferencesSetXSSAuditorEnabled(preferences, false);
WKPreferencesSetWebAudioEnabled(preferences, true);
+ WKPreferencesSetMediaStreamEnabled(preferences, true);
WKPreferencesSetDeveloperExtrasEnabled(preferences, true);
- WKPreferencesSetJavaScriptExperimentsEnabled(preferences, true);
+ WKPreferencesSetJavaScriptRuntimeFlags(preferences, kWKJavaScriptRuntimeFlagsAllEnabled);
WKPreferencesSetJavaScriptCanOpenWindowsAutomatically(preferences, true);
WKPreferencesSetJavaScriptCanAccessClipboard(preferences, true);
WKPreferencesSetDOMPasteAllowed(preferences, true);
@@ -520,6 +645,9 @@ void TestController::resetPreferencesToConsistentValues()
WKPreferencesSetInteractiveFormValidationEnabled(preferences, true);
WKPreferencesSetMockScrollbarsEnabled(preferences, true);
+ static WKStringRef defaultTextEncoding = WKStringCreateWithUTF8CString("ISO-8859-1");
+ WKPreferencesSetDefaultTextEncodingName(preferences, defaultTextEncoding);
+
static WKStringRef standardFontFamily = WKStringCreateWithUTF8CString("Times");
static WKStringRef cursiveFontFamily = WKStringCreateWithUTF8CString("Apple Chancery");
static WKStringRef fantasyFontFamily = WKStringCreateWithUTF8CString("Papyrus");
@@ -535,21 +663,36 @@ void TestController::resetPreferencesToConsistentValues()
WKPreferencesSetPictographFontFamily(preferences, pictographFontFamily);
WKPreferencesSetSansSerifFontFamily(preferences, sansSerifFontFamily);
WKPreferencesSetSerifFontFamily(preferences, serifFontFamily);
- WKPreferencesSetScreenFontSubstitutionEnabled(preferences, true);
WKPreferencesSetAsynchronousSpellCheckingEnabled(preferences, false);
#if ENABLE(WEB_AUDIO)
WKPreferencesSetMediaSourceEnabled(preferences, true);
#endif
+ WKPreferencesSetHiddenPageDOMTimerThrottlingEnabled(preferences, false);
+ WKPreferencesSetHiddenPageCSSAnimationSuspensionEnabled(preferences, false);
+
WKPreferencesSetAcceleratedDrawingEnabled(preferences, m_shouldUseAcceleratedDrawing);
+ // FIXME: We should be testing the default.
+ WKPreferencesSetStorageBlockingPolicy(preferences, kWKAllowAllStorage);
+
+ WKPreferencesSetMediaPlaybackAllowsInline(preferences, true);
+ WKPreferencesSetInlineMediaPlaybackRequiresPlaysInlineAttribute(preferences, false);
+
+ WKCookieManagerDeleteAllCookies(WKContextGetCookieManager(m_context.get()));
+
+ platformResetPreferencesToConsistentValues();
}
bool TestController::resetStateToConsistentValues()
{
- m_state = Resetting;
-
+ TemporaryChange<State> changeState(m_state, Resetting);
m_beforeUnloadReturnValue = true;
+ // This setting differs between the antique and modern Mac WebKit2 API.
+ // For now, maintain the antique behavior, because some tests depend on it!
+ // FIXME: We should be testing the default.
+ WKPageSetBackgroundExtendsBeyondPage(m_mainWebView->page(), false);
+
WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("Reset"));
WKRetainPtr<WKMutableDictionaryRef> resetMessageBody = adoptWK(WKMutableDictionaryCreate());
@@ -557,32 +700,44 @@ bool TestController::resetStateToConsistentValues()
WKRetainPtr<WKBooleanRef> shouldGCValue = adoptWK(WKBooleanCreate(m_gcBetweenTests));
WKDictionarySetItem(resetMessageBody.get(), shouldGCKey.get(), shouldGCValue.get());
- WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), resetMessageBody.get());
+ WKRetainPtr<WKStringRef> allowedHostsKey = adoptWK(WKStringCreateWithUTF8CString("AllowedHosts"));
+ WKRetainPtr<WKMutableArrayRef> allowedHostsValue = adoptWK(WKMutableArrayCreate());
+ for (auto& host : m_allowedHosts) {
+ WKRetainPtr<WKStringRef> wkHost = adoptWK(WKStringCreateWithUTF8CString(host.c_str()));
+ WKArrayAppendItem(allowedHostsValue.get(), wkHost.get());
+ }
+ WKDictionarySetItem(resetMessageBody.get(), allowedHostsKey.get(), allowedHostsValue.get());
+
+ WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), resetMessageBody.get());
+
+ WKContextSetShouldUseFontSmoothing(TestController::singleton().context(), false);
- WKContextSetShouldUseFontSmoothing(TestController::shared().context(), false);
+ WKContextSetCacheModel(TestController::singleton().context(), kWKCacheModelDocumentBrowser);
- WKContextSetCacheModel(TestController::shared().context(), kWKCacheModelDocumentBrowser);
+ WKContextClearCachedCredentials(TestController::singleton().context());
// FIXME: This function should also ensure that there is only one page open.
// Reset the EventSender for each test.
- m_eventSenderProxy = adoptPtr(new EventSenderProxy(this));
+ m_eventSenderProxy = std::make_unique<EventSenderProxy>(this);
// FIXME: Is this needed? Nothing in TestController changes preferences during tests, and if there is
// some other code doing this, it should probably be responsible for cleanup too.
resetPreferencesToConsistentValues();
-#if !PLATFORM(MAC)
+#if !PLATFORM(COCOA)
WKTextCheckerContinuousSpellCheckingEnabledStateChanged(true);
#endif
- // in the case that a test using the chrome input field failed, be sure to clean up for the next test
+ // In the case that a test using the chrome input field failed, be sure to clean up for the next test.
m_mainWebView->removeChromeInputField();
m_mainWebView->focus();
// Re-set to the default backing scale factor by setting the custom scale factor to 0.
WKPageSetCustomBackingScaleFactor(m_mainWebView->page(), 0);
+ WKPageClearWheelEventTestTrigger(m_mainWebView->page());
+
#if PLATFORM(EFL)
// EFL use a real window while other ports such as Qt don't.
// In EFL, we need to resize the window to the original size after calls to window.resizeTo.
@@ -598,6 +753,12 @@ bool TestController::resetStateToConsistentValues()
m_isGeolocationPermissionSet = false;
m_isGeolocationPermissionAllowed = false;
+ // Reset UserMedia permissions.
+ m_userMediaPermissionRequests.clear();
+ m_userMediaOriginPermissions = nullptr;
+ m_isUserMediaPermissionSet = false;
+ m_isUserMediaPermissionAllowed = false;
+
// Reset Custom Policy Delegate.
setCustomPolicyDelegate(false, false);
@@ -609,14 +770,200 @@ bool TestController::resetStateToConsistentValues()
m_shouldBlockAllPlugins = false;
+ m_shouldLogHistoryClientCallbacks = false;
+
+ setHidden(false);
+
+ platformResetStateToConsistentValues();
+
// Reset main page back to about:blank
m_doneResetting = false;
+ m_shouldDecideNavigationPolicyAfterDelay = false;
+
+ setNavigationGesturesEnabled(false);
+
WKPageLoadURL(m_mainWebView->page(), blankURL());
- runUntil(m_doneResetting, ShortTimeout);
+ runUntil(m_doneResetting, shortTimeout);
return m_doneResetting;
}
+void TestController::terminateWebContentProcess()
+{
+ WKPageTerminate(m_mainWebView->page());
+}
+
+void TestController::reattachPageToWebProcess()
+{
+ // Loading a web page is the only way to reattach an existing page to a process.
+ m_doneResetting = false;
+ WKPageLoadURL(m_mainWebView->page(), blankURL());
+ runUntil(m_doneResetting, shortTimeout);
+}
+
+const char* TestController::webProcessName()
+{
+ // FIXME: Find a way to not hardcode the process name.
+#if PLATFORM(COCOA)
+ return "com.apple.WebKit.WebContent.Development";
+#else
+ return "WebProcess";
+#endif
+}
+
+const char* TestController::networkProcessName()
+{
+ // FIXME: Find a way to not hardcode the process name.
+#if PLATFORM(COCOA)
+ return "com.apple.WebKit.Networking.Development";
+#else
+ return "NetworkProcess";
+#endif
+}
+
+static std::string testPath(WKURLRef url)
+{
+ auto scheme = adoptWK(WKURLCopyScheme(url));
+ if (WKStringIsEqualToUTF8CStringIgnoringCase(scheme.get(), "file")) {
+ auto path = adoptWK(WKURLCopyPath(url));
+ auto buffer = std::vector<char>(WKStringGetMaximumUTF8CStringSize(path.get()));
+ auto length = WKStringGetUTF8CString(path.get(), buffer.data(), buffer.size());
+ return std::string(buffer.data(), length);
+ }
+ return std::string();
+}
+
+static WKURLRef createTestURL(const char* pathOrURL)
+{
+ if (strstr(pathOrURL, "http://") || strstr(pathOrURL, "https://") || strstr(pathOrURL, "file://"))
+ return WKURLCreateWithUTF8CString(pathOrURL);
+
+ // Creating from filesytem path.
+ size_t length = strlen(pathOrURL);
+ if (!length)
+ return 0;
+
+ const char separator = '/';
+ bool isAbsolutePath = pathOrURL[0] == separator;
+ const char* filePrefix = "file://";
+ static const size_t prefixLength = strlen(filePrefix);
+
+ std::unique_ptr<char[]> buffer;
+ if (isAbsolutePath) {
+ buffer = std::make_unique<char[]>(prefixLength + length + 1);
+ strcpy(buffer.get(), filePrefix);
+ strcpy(buffer.get() + prefixLength, pathOrURL);
+ } else {
+ buffer = std::make_unique<char[]>(prefixLength + PATH_MAX + length + 2); // 1 for the separator
+ strcpy(buffer.get(), filePrefix);
+ if (!getcwd(buffer.get() + prefixLength, PATH_MAX))
+ return 0;
+ size_t numCharacters = strlen(buffer.get());
+ buffer[numCharacters] = separator;
+ strcpy(buffer.get() + numCharacters + 1, pathOrURL);
+ }
+
+ return WKURLCreateWithUTF8CString(buffer.get());
+}
+
+static bool parseBooleanTestHeaderValue(const std::string& value)
+{
+ if (value == "true")
+ return true;
+ if (value == "false")
+ return false;
+
+ LOG_ERROR("Found unexpected value '%s' for boolean option. Expected 'true' or 'false'.", value.c_str());
+ return false;
+}
+
+static void updateTestOptionsFromTestHeader(TestOptions& testOptions, const std::string& pathOrURL)
+{
+ // Gross. Need to reduce conversions between all the string types and URLs.
+ WKRetainPtr<WKURLRef> wkURL(AdoptWK, createTestURL(pathOrURL.c_str()));
+ std::string filename = testPath(wkURL.get());
+ if (filename.empty())
+ return;
+
+ std::string options;
+ std::ifstream testFile(filename.data());
+ if (!testFile.good())
+ return;
+ getline(testFile, options);
+ std::string beginString("webkit-test-runner [ ");
+ std::string endString(" ]");
+ size_t beginLocation = options.find(beginString);
+ if (beginLocation == std::string::npos)
+ return;
+ size_t endLocation = options.find(endString, beginLocation);
+ if (endLocation == std::string::npos) {
+ LOG_ERROR("Could not find end of test header in %s", filename.c_str());
+ return;
+ }
+ std::string pairString = options.substr(beginLocation + beginString.size(), endLocation - (beginLocation + beginString.size()));
+ size_t pairStart = 0;
+ while (pairStart < pairString.size()) {
+ size_t pairEnd = pairString.find(" ", pairStart);
+ if (pairEnd == std::string::npos)
+ pairEnd = pairString.size();
+ size_t equalsLocation = pairString.find("=", pairStart);
+ if (equalsLocation == std::string::npos) {
+ LOG_ERROR("Malformed option in test header (could not find '=' character) in %s", filename.c_str());
+ break;
+ }
+ auto key = pairString.substr(pairStart, equalsLocation - pairStart);
+ auto value = pairString.substr(equalsLocation + 1, pairEnd - (equalsLocation + 1));
+ if (key == "language")
+ String(value.c_str()).split(",", false, testOptions.overrideLanguages);
+ if (key == "useThreadedScrolling")
+ testOptions.useThreadedScrolling = parseBooleanTestHeaderValue(value);
+ if (key == "useFlexibleViewport")
+ testOptions.useFlexibleViewport = parseBooleanTestHeaderValue(value);
+ if (key == "useDataDetection")
+ testOptions.useDataDetection = parseBooleanTestHeaderValue(value);
+ pairStart = pairEnd + 1;
+ }
+}
+
+TestOptions TestController::testOptionsForTest(const std::string& pathOrURL) const
+{
+ TestOptions options(pathOrURL);
+
+ options.useRemoteLayerTree = m_shouldUseRemoteLayerTree;
+ options.shouldShowWebView = m_shouldShowWebView;
+
+ updatePlatformSpecificTestOptionsForTest(options, pathOrURL);
+ updateTestOptionsFromTestHeader(options, pathOrURL);
+
+ return options;
+}
+
+void TestController::updateWebViewSizeForTest(const TestInvocation& test)
+{
+ unsigned width = viewWidth;
+ unsigned height = viewHeight;
+ if (test.options().isSVGTest) {
+ width = w3cSVGViewWidth;
+ height = w3cSVGViewHeight;
+ }
+
+ mainWebView()->resizeTo(width, height);
+}
+
+void TestController::updateWindowScaleForTest(PlatformWebView* view, const TestInvocation& test)
+{
+ view->changeWindowScaleIfNeeded(test.options().isHiDPITest ? 2 : 1);
+}
+
+void TestController::configureViewForTest(const TestInvocation& test)
+{
+ ensureViewSupportsOptionsForTest(test);
+ updateWebViewSizeForTest(test);
+ updateWindowScaleForTest(mainWebView(), test);
+
+ platformConfigureViewForTest(test);
+}
+
struct TestCommand {
TestCommand() : shouldDumpPixels(false), timeout(0) { }
@@ -707,15 +1054,21 @@ bool TestController::runTest(const char* inputLine)
TestCommand command = parseInputLine(std::string(inputLine));
m_state = RunningTest;
+
+ TestOptions options = testOptionsForTest(command.pathOrURL);
+
+ WKRetainPtr<WKURLRef> wkURL(AdoptWK, createTestURL(command.pathOrURL.c_str()));
+ m_currentInvocation = std::make_unique<TestInvocation>(wkURL.get(), options);
- m_currentInvocation = adoptPtr(new TestInvocation(command.pathOrURL));
if (command.shouldDumpPixels || m_shouldDumpPixelsForAllTests)
m_currentInvocation->setIsPixelTest(command.expectedPixelHash);
if (command.timeout > 0)
m_currentInvocation->setCustomTimeout(command.timeout);
+ platformWillRunTest(*m_currentInvocation);
+
m_currentInvocation->invoke();
- m_currentInvocation.clear();
+ m_currentInvocation = nullptr;
return true;
}
@@ -738,11 +1091,6 @@ void TestController::runTestingServerLoop()
void TestController::run()
{
- if (!resetStateToConsistentValues()) {
- TestInvocation::dumpWebProcessUnresponsiveness("<unknown> - TestController::run - Failed to reset state to consistent values\n");
- return;
- }
-
if (m_usingServerMode)
runTestingServerLoop();
else {
@@ -753,26 +1101,10 @@ void TestController::run()
}
}
-void TestController::runUntil(bool& done, TimeoutDuration timeoutDuration)
+void TestController::runUntil(bool& done, double timeout)
{
- double timeout = m_noTimeout;
- if (!m_forceNoTimeout) {
- switch (timeoutDuration) {
- case ShortTimeout:
- timeout = m_shortTimeout;
- break;
- case LongTimeout:
- timeout = m_longTimeout;
- break;
- case CustomTimeout:
- timeout = m_timeout;
- break;
- case NoTimeout:
- default:
- timeout = m_noTimeout;
- break;
- }
- }
+ if (m_forceNoTimeout)
+ timeout = noTimeout;
platformRunUntil(done, timeout);
}
@@ -789,6 +1121,23 @@ void TestController::didReceiveSynchronousMessageFromInjectedBundle(WKContextRef
*returnData = static_cast<TestController*>(const_cast<void*>(clientInfo))->didReceiveSynchronousMessageFromInjectedBundle(messageName, messageBody).leakRef();
}
+// WKPageInjectedBundleClient
+
+void TestController::didReceivePageMessageFromInjectedBundle(WKPageRef page, WKStringRef messageName, WKTypeRef messageBody, const void* clientInfo)
+{
+ static_cast<TestController*>(const_cast<void*>(clientInfo))->didReceiveMessageFromInjectedBundle(messageName, messageBody);
+}
+
+void TestController::didReceiveSynchronousPageMessageFromInjectedBundle(WKPageRef page, WKStringRef messageName, WKTypeRef messageBody, WKTypeRef* returnData, const void* clientInfo)
+{
+ *returnData = static_cast<TestController*>(const_cast<void*>(clientInfo))->didReceiveSynchronousMessageFromInjectedBundle(messageName, messageBody).leakRef();
+}
+
+void TestController::networkProcessDidCrash(WKContextRef context, const void *clientInfo)
+{
+ static_cast<TestController*>(const_cast<void*>(clientInfo))->networkProcessDidCrash();
+}
+
void TestController::didReceiveKeyDownMessageFromInjectedBundle(WKDictionaryRef messageBodyDictionary, bool synchronous)
{
WKRetainPtr<WKStringRef> keyKey = adoptWK(WKStringCreateWithUTF8CString("Key"));
@@ -800,18 +1149,15 @@ void TestController::didReceiveKeyDownMessageFromInjectedBundle(WKDictionaryRef
WKRetainPtr<WKStringRef> locationKey = adoptWK(WKStringCreateWithUTF8CString("Location"));
unsigned location = static_cast<unsigned>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, locationKey.get()))));
- if (synchronous)
- WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
-
m_eventSenderProxy->keyDown(key, modifiers, location);
-
- if (synchronous)
- WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
}
void TestController::didReceiveMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody)
{
if (WKStringIsEqualToUTF8CString(messageName, "EventSender")) {
+ if (m_state != RunningTest)
+ return;
+
ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
@@ -826,7 +1172,6 @@ void TestController::didReceiveMessageFromInjectedBundle(WKStringRef messageName
WKEventModifiers modifiers = static_cast<WKEventModifiers>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, modifiersKey.get()))));
// Forward to WebProcess
- WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
if (WKStringIsEqualToUTF8CString(subMessageName, "MouseDown"))
m_eventSenderProxy->mouseDown(button, modifiers);
else
@@ -841,6 +1186,53 @@ void TestController::didReceiveMessageFromInjectedBundle(WKStringRef messageName
return;
}
+ if (WKStringIsEqualToUTF8CString(subMessageName, "MouseScrollBy")) {
+ WKRetainPtr<WKStringRef> xKey = adoptWK(WKStringCreateWithUTF8CString("X"));
+ double x = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, xKey.get())));
+
+ WKRetainPtr<WKStringRef> yKey = adoptWK(WKStringCreateWithUTF8CString("Y"));
+ double y = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, yKey.get())));
+
+ // Forward to WebProcess
+ m_eventSenderProxy->mouseScrollBy(x, y);
+ return;
+ }
+
+ if (WKStringIsEqualToUTF8CString(subMessageName, "MouseScrollByWithWheelAndMomentumPhases")) {
+ WKRetainPtr<WKStringRef> xKey = adoptWK(WKStringCreateWithUTF8CString("X"));
+ double x = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, xKey.get())));
+
+ WKRetainPtr<WKStringRef> yKey = adoptWK(WKStringCreateWithUTF8CString("Y"));
+ double y = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, yKey.get())));
+
+ WKRetainPtr<WKStringRef> phaseKey = adoptWK(WKStringCreateWithUTF8CString("Phase"));
+ int phase = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, phaseKey.get()))));
+ WKRetainPtr<WKStringRef> momentumKey = adoptWK(WKStringCreateWithUTF8CString("Momentum"));
+ int momentum = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, momentumKey.get()))));
+
+ // Forward to WebProcess
+ m_eventSenderProxy->mouseScrollByWithWheelAndMomentumPhases(x, y, phase, momentum);
+
+ return;
+ }
+
+ if (WKStringIsEqualToUTF8CString(subMessageName, "SwipeGestureWithWheelAndMomentumPhases")) {
+ WKRetainPtr<WKStringRef> xKey = adoptWK(WKStringCreateWithUTF8CString("X"));
+ double x = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, xKey.get())));
+
+ WKRetainPtr<WKStringRef> yKey = adoptWK(WKStringCreateWithUTF8CString("Y"));
+ double y = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, yKey.get())));
+
+ WKRetainPtr<WKStringRef> phaseKey = adoptWK(WKStringCreateWithUTF8CString("Phase"));
+ int phase = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, phaseKey.get()))));
+ WKRetainPtr<WKStringRef> momentumKey = adoptWK(WKStringCreateWithUTF8CString("Momentum"));
+ int momentum = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, momentumKey.get()))));
+
+ m_eventSenderProxy->swipeGestureWithWheelAndMomentumPhases(x, y, phase, momentum);
+
+ return;
+ }
+
ASSERT_NOT_REACHED();
}
@@ -853,6 +1245,9 @@ void TestController::didReceiveMessageFromInjectedBundle(WKStringRef messageName
WKRetainPtr<WKTypeRef> TestController::didReceiveSynchronousMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody)
{
if (WKStringIsEqualToUTF8CString(messageName, "EventSender")) {
+ if (m_state != RunningTest)
+ return nullptr;
+
ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
@@ -873,12 +1268,10 @@ WKRetainPtr<WKTypeRef> TestController::didReceiveSynchronousMessageFromInjectedB
WKEventModifiers modifiers = static_cast<WKEventModifiers>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, modifiersKey.get()))));
// Forward to WebProcess
- WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
if (WKStringIsEqualToUTF8CString(subMessageName, "MouseDown"))
m_eventSenderProxy->mouseDown(button, modifiers);
else
m_eventSenderProxy->mouseUp(button, modifiers);
- WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
return 0;
}
@@ -890,26 +1283,40 @@ WKRetainPtr<WKTypeRef> TestController::didReceiveSynchronousMessageFromInjectedB
double y = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, yKey.get())));
// Forward to WebProcess
- WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
m_eventSenderProxy->mouseMoveTo(x, y);
- WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
return 0;
}
- if (WKStringIsEqualToUTF8CString(subMessageName, "MouseScrollBy")) {
- WKRetainPtr<WKStringRef> xKey = adoptWK(WKStringCreateWithUTF8CString("X"));
- double x = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, xKey.get())));
+#if PLATFORM(MAC)
+ if (WKStringIsEqualToUTF8CString(subMessageName, "MouseForceClick")) {
+ m_eventSenderProxy->mouseForceClick();
+ return 0;
+ }
- WKRetainPtr<WKStringRef> yKey = adoptWK(WKStringCreateWithUTF8CString("Y"));
- double y = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, yKey.get())));
+ if (WKStringIsEqualToUTF8CString(subMessageName, "StartAndCancelMouseForceClick")) {
+ m_eventSenderProxy->startAndCancelMouseForceClick();
+ return 0;
+ }
- // Forward to WebProcess
- WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
- m_eventSenderProxy->mouseScrollBy(x, y);
- WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
+ if (WKStringIsEqualToUTF8CString(subMessageName, "MouseForceDown")) {
+ m_eventSenderProxy->mouseForceDown();
return 0;
}
+ if (WKStringIsEqualToUTF8CString(subMessageName, "MouseForceUp")) {
+ m_eventSenderProxy->mouseForceUp();
+ return 0;
+ }
+
+ if (WKStringIsEqualToUTF8CString(subMessageName, "MouseForceChanged")) {
+ WKRetainPtr<WKStringRef> forceKey = adoptWK(WKStringCreateWithUTF8CString("Force"));
+ double force = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, forceKey.get())));
+
+ m_eventSenderProxy->mouseForceChanged(force);
+ return 0;
+ }
+#endif // PLATFORM(MAC)
+
if (WKStringIsEqualToUTF8CString(subMessageName, "ContinuousMouseScrollBy")) {
WKRetainPtr<WKStringRef> xKey = adoptWK(WKStringCreateWithUTF8CString("X"));
double x = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, xKey.get())));
@@ -921,9 +1328,7 @@ WKRetainPtr<WKTypeRef> TestController::didReceiveSynchronousMessageFromInjectedB
bool paged = static_cast<bool>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, pagedKey.get()))));
// Forward to WebProcess
- WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
m_eventSenderProxy->continuousMouseScrollBy(x, y, paged);
- WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
return 0;
}
@@ -984,30 +1389,22 @@ WKRetainPtr<WKTypeRef> TestController::didReceiveSynchronousMessageFromInjectedB
}
if (WKStringIsEqualToUTF8CString(subMessageName, "TouchStart")) {
- WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
m_eventSenderProxy->touchStart();
- WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
return 0;
}
if (WKStringIsEqualToUTF8CString(subMessageName, "TouchMove")) {
- WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
m_eventSenderProxy->touchMove();
- WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
return 0;
}
if (WKStringIsEqualToUTF8CString(subMessageName, "TouchEnd")) {
- WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
m_eventSenderProxy->touchEnd();
- WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
return 0;
}
if (WKStringIsEqualToUTF8CString(subMessageName, "TouchCancel")) {
- WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
m_eventSenderProxy->touchCancel();
- WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
return 0;
}
@@ -1035,21 +1432,46 @@ WKRetainPtr<WKTypeRef> TestController::didReceiveSynchronousMessageFromInjectedB
return m_currentInvocation->didReceiveSynchronousMessageFromInjectedBundle(messageName, messageBody);
}
-// WKPageLoaderClient
+// WKContextClient
-void TestController::didCommitLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef, const void* clientInfo)
+void TestController::networkProcessDidCrash()
{
- static_cast<TestController*>(const_cast<void*>(clientInfo))->didCommitLoadForFrame(page, frame);
+#if PLATFORM(COCOA)
+ pid_t pid = WKContextGetNetworkProcessIdentifier(m_context.get());
+ fprintf(stderr, "#CRASHED - %s (pid %ld)\n", networkProcessName(), static_cast<long>(pid));
+#else
+ fprintf(stderr, "#CRASHED - %s\n", networkProcessName());
+#endif
+ exit(1);
+}
+
+// WKPageNavigationClient
+
+void TestController::didCommitNavigation(WKPageRef page, WKNavigationRef navigation, WKTypeRef, const void* clientInfo)
+{
+ static_cast<TestController*>(const_cast<void*>(clientInfo))->didCommitNavigation(page, navigation);
}
-void TestController::didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef, const void* clientInfo)
+void TestController::didFinishNavigation(WKPageRef page, WKNavigationRef navigation, WKTypeRef, const void* clientInfo)
{
- static_cast<TestController*>(const_cast<void*>(clientInfo))->didFinishLoadForFrame(page, frame);
+ static_cast<TestController*>(const_cast<void*>(clientInfo))->didFinishNavigation(page, navigation);
+}
+
+bool TestController::canAuthenticateAgainstProtectionSpace(WKPageRef, WKProtectionSpaceRef protectionSpace, const void*)
+{
+ WKProtectionSpaceAuthenticationScheme authenticationScheme = WKProtectionSpaceGetAuthenticationScheme(protectionSpace);
+
+ if (authenticationScheme == kWKProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested) {
+ std::string host = toSTD(adoptWK(WKProtectionSpaceCopyHost(protectionSpace)).get());
+ return host == "localhost" || host == "127.0.0.1";
+ }
+
+ return authenticationScheme <= kWKProtectionSpaceAuthenticationSchemeHTTPDigest;
}
-void TestController::didReceiveAuthenticationChallengeInFrame(WKPageRef page, WKFrameRef frame, WKAuthenticationChallengeRef authenticationChallenge, const void *clientInfo)
+void TestController::didReceiveAuthenticationChallenge(WKPageRef page, WKAuthenticationChallengeRef authenticationChallenge, const void *clientInfo)
{
- static_cast<TestController*>(const_cast<void*>(clientInfo))->didReceiveAuthenticationChallengeInFrame(page, frame, authenticationChallenge);
+ static_cast<TestController*>(const_cast<void*>(clientInfo))->didReceiveAuthenticationChallenge(page, /*frame,*/ authenticationChallenge);
}
void TestController::processDidCrash(WKPageRef page, const void* clientInfo)
@@ -1057,52 +1479,94 @@ void TestController::processDidCrash(WKPageRef page, const void* clientInfo)
static_cast<TestController*>(const_cast<void*>(clientInfo))->processDidCrash();
}
-WKPluginLoadPolicy TestController::pluginLoadPolicy(WKPageRef page, WKPluginLoadPolicy currentPluginLoadPolicy, WKDictionaryRef pluginInformation, WKStringRef* unavailabilityDescription, const void* clientInfo)
+void TestController::didBeginNavigationGesture(WKPageRef page, const void *clientInfo)
{
- return static_cast<TestController*>(const_cast<void*>(clientInfo))->pluginLoadPolicy(page, currentPluginLoadPolicy, pluginInformation, unavailabilityDescription);
+ static_cast<TestController*>(const_cast<void*>(clientInfo))->didBeginNavigationGesture(page);
}
-WKPluginLoadPolicy TestController::pluginLoadPolicy(WKPageRef, WKPluginLoadPolicy currentPluginLoadPolicy, WKDictionaryRef pluginInformation, WKStringRef* unavailabilityDescription)
+void TestController::willEndNavigationGesture(WKPageRef page, WKBackForwardListItemRef backForwardListItem, const void *clientInfo)
+{
+ static_cast<TestController*>(const_cast<void*>(clientInfo))->willEndNavigationGesture(page, backForwardListItem);
+}
+
+void TestController::didEndNavigationGesture(WKPageRef page, WKBackForwardListItemRef backForwardListItem, const void *clientInfo)
+{
+ static_cast<TestController*>(const_cast<void*>(clientInfo))->didEndNavigationGesture(page, backForwardListItem);
+}
+
+void TestController::didRemoveNavigationGestureSnapshot(WKPageRef page, const void *clientInfo)
+{
+ static_cast<TestController*>(const_cast<void*>(clientInfo))->didRemoveNavigationGestureSnapshot(page);
+}
+
+WKPluginLoadPolicy TestController::decidePolicyForPluginLoad(WKPageRef page, WKPluginLoadPolicy currentPluginLoadPolicy, WKDictionaryRef pluginInformation, WKStringRef* unavailabilityDescription, const void* clientInfo)
+{
+ return static_cast<TestController*>(const_cast<void*>(clientInfo))->decidePolicyForPluginLoad(page, currentPluginLoadPolicy, pluginInformation, unavailabilityDescription);
+}
+
+WKPluginLoadPolicy TestController::decidePolicyForPluginLoad(WKPageRef, WKPluginLoadPolicy currentPluginLoadPolicy, WKDictionaryRef pluginInformation, WKStringRef* unavailabilityDescription)
{
if (m_shouldBlockAllPlugins)
return kWKPluginLoadPolicyBlocked;
+
+#if PLATFORM(MAC)
+ WKStringRef bundleIdentifier = (WKStringRef)WKDictionaryGetItemForKey(pluginInformation, WKPluginInformationBundleIdentifierKey());
+ if (!bundleIdentifier)
+ return currentPluginLoadPolicy;
+
+ if (WKStringIsEqualToUTF8CString(bundleIdentifier, "com.apple.QuickTime Plugin.plugin"))
+ return currentPluginLoadPolicy;
+
+ if (WKStringIsEqualToUTF8CString(bundleIdentifier, "com.apple.testnetscapeplugin"))
+ return currentPluginLoadPolicy;
+
+ RELEASE_ASSERT_NOT_REACHED(); // Please don't use any other plug-ins in tests, as they will not be installed on all machines.
+#else
return currentPluginLoadPolicy;
+#endif
}
-void TestController::didCommitLoadForFrame(WKPageRef page, WKFrameRef frame)
+void TestController::didCommitNavigation(WKPageRef page, WKNavigationRef navigation)
{
- if (!WKFrameIsMainFrame(frame))
- return;
-
mainWebView()->focus();
}
-void TestController::didFinishLoadForFrame(WKPageRef page, WKFrameRef frame)
+void TestController::didFinishNavigation(WKPageRef page, WKNavigationRef navigation)
{
if (m_state != Resetting)
return;
- if (!WKFrameIsMainFrame(frame))
- return;
-
- WKRetainPtr<WKURLRef> wkURL(AdoptWK, WKFrameCopyURL(frame));
+ WKRetainPtr<WKURLRef> wkURL(AdoptWK, WKFrameCopyURL(WKPageGetMainFrame(page)));
if (!WKURLIsEqual(wkURL.get(), blankURL()))
return;
m_doneResetting = true;
- shared().notifyDone();
+ singleton().notifyDone();
}
-void TestController::didReceiveAuthenticationChallengeInFrame(WKPageRef page, WKFrameRef frame, WKAuthenticationChallengeRef authenticationChallenge)
+void TestController::didReceiveAuthenticationChallenge(WKPageRef page, WKAuthenticationChallengeRef authenticationChallenge)
{
- String message;
+ WKProtectionSpaceRef protectionSpace = WKAuthenticationChallengeGetProtectionSpace(authenticationChallenge);
+ WKAuthenticationDecisionListenerRef decisionListener = WKAuthenticationChallengeGetDecisionListener(authenticationChallenge);
+
+ if (WKProtectionSpaceGetAuthenticationScheme(protectionSpace) == kWKProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested) {
+ // Any non-empty credential signals to accept the server trust. Since the cross-platform API
+ // doesn't expose a way to create a credential from server trust, we use a password credential.
+
+ WKRetainPtr<WKCredentialRef> credential = adoptWK(WKCredentialCreate(toWK("accept server trust").get(), toWK("").get(), kWKCredentialPersistenceNone));
+ WKAuthenticationDecisionListenerUseCredential(decisionListener, credential.get());
+ return;
+ }
+
+ std::string host = toSTD(adoptWK(WKProtectionSpaceCopyHost(protectionSpace)).get());
+ int port = WKProtectionSpaceGetPort(protectionSpace);
+ String message = String::format("%s:%d - didReceiveAuthenticationChallenge - ", host.c_str(), port);
if (!m_handlesAuthenticationChallenges)
- message = "<unknown> - didReceiveAuthenticationChallenge - Simulating cancelled authentication sheet\n";
+ message.append("Simulating cancelled authentication sheet\n");
else
- message = String::format("<unknown> - didReceiveAuthenticationChallenge - Responding with %s:%s\n", m_authenticationUsername.utf8().data(), m_authenticationPassword.utf8().data());
+ message.append(String::format("Responding with %s:%s\n", m_authenticationUsername.utf8().data(), m_authenticationPassword.utf8().data()));
m_currentInvocation->outputText(message);
- WKAuthenticationDecisionListenerRef decisionListener = WKAuthenticationChallengeGetDecisionListener(authenticationChallenge);
if (!m_handlesAuthenticationChallenges) {
WKAuthenticationDecisionListenerUseCredential(decisionListener, 0);
return;
@@ -1118,11 +1582,11 @@ void TestController::processDidCrash()
// This function can be called multiple times when crash logs are being saved on Windows, so
// ensure we only print the crashed message once.
if (!m_didPrintWebProcessCrashedMessage) {
-#if PLATFORM(MAC)
+#if PLATFORM(COCOA)
pid_t pid = WKPageGetProcessIdentifier(m_mainWebView->page());
- fprintf(stderr, "#CRASHED - WebProcess (pid %ld)\n", static_cast<long>(pid));
+ fprintf(stderr, "#CRASHED - %s (pid %ld)\n", webProcessName(), static_cast<long>(pid));
#else
- fputs("#CRASHED - WebProcess\n", stderr);
+ fprintf(stderr, "#CRASHED - %s\n", webProcessName());
#endif
fflush(stderr);
m_didPrintWebProcessCrashedMessage = true;
@@ -1132,6 +1596,26 @@ void TestController::processDidCrash()
exit(1);
}
+void TestController::didBeginNavigationGesture(WKPageRef)
+{
+ m_currentInvocation->didBeginSwipe();
+}
+
+void TestController::willEndNavigationGesture(WKPageRef, WKBackForwardListItemRef)
+{
+ m_currentInvocation->willEndSwipe();
+}
+
+void TestController::didEndNavigationGesture(WKPageRef, WKBackForwardListItemRef)
+{
+ m_currentInvocation->didEndSwipe();
+}
+
+void TestController::didRemoveNavigationGestureSnapshot(WKPageRef)
+{
+ m_currentInvocation->didRemoveSwipeSnapshot();
+}
+
void TestController::simulateWebNotificationClick(uint64_t notificationID)
{
m_webNotificationProvider.simulateWebNotificationClick(notificationID);
@@ -1160,16 +1644,97 @@ void TestController::handleGeolocationPermissionRequest(WKGeolocationPermissionR
decidePolicyForGeolocationPermissionRequestIfPossible();
}
-void TestController::setCustomPolicyDelegate(bool enabled, bool permissive)
+bool TestController::isGeolocationProviderActive() const
{
- m_policyDelegateEnabled = enabled;
- m_policyDelegatePermissive = permissive;
+ return m_geolocationProvider->isActive();
+}
+
+static WKStringRef originUserVisibleName(WKSecurityOriginRef origin)
+{
+ std::string host = toSTD(adoptWK(WKSecurityOriginCopyHost(origin))).c_str();
+ std::string protocol = toSTD(adoptWK(WKSecurityOriginCopyProtocol(origin))).c_str();
+ unsigned short port = WKSecurityOriginGetPort(origin);
+
+ String userVisibleName;
+ if (port)
+ userVisibleName = String::format("%s://%s:%d", protocol.c_str(), host.c_str(), port);
+ else
+ userVisibleName = String::format("%s://%s", protocol.c_str(), host.c_str());
+
+ return WKStringCreateWithUTF8CString(userVisibleName.utf8().data());
+}
+
+void TestController::setUserMediaPermission(bool enabled)
+{
+ m_isUserMediaPermissionSet = true;
+ m_isUserMediaPermissionAllowed = enabled;
+ decidePolicyForUserMediaPermissionRequestIfPossible();
+}
+
+void TestController::setUserMediaPermissionForOrigin(bool permission, WKStringRef originString)
+{
+ if (!m_userMediaOriginPermissions)
+ m_userMediaOriginPermissions = adoptWK(WKMutableDictionaryCreate());
+ WKRetainPtr<WKBooleanRef> allowed = adoptWK(WKBooleanCreate(permission));
+ WKRetainPtr<WKSecurityOriginRef> origin = adoptWK(WKSecurityOriginCreateFromString(originString));
+ WKDictionarySetItem(m_userMediaOriginPermissions.get(), originUserVisibleName(origin.get()), allowed.get());
+}
+
+void TestController::handleCheckOfUserMediaPermissionForOrigin(WKSecurityOriginRef origin, const WKUserMediaPermissionCheckRef& checkRequest)
+{
+ bool allowed = false;
+
+ if (m_userMediaOriginPermissions) {
+ WKRetainPtr<WKStringRef> originString = originUserVisibleName(origin);
+ WKBooleanRef value = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(m_userMediaOriginPermissions.get(), originString.get()));
+ if (value && WKGetTypeID(value) == WKBooleanGetTypeID())
+ allowed = WKBooleanGetValue(value);
+ }
+
+ WKUserMediaPermissionCheckSetHasPersistentPermission(checkRequest, allowed);
+}
+
+void TestController::handleUserMediaPermissionRequest(WKSecurityOriginRef origin, WKUserMediaPermissionRequestRef request)
+{
+ m_userMediaPermissionRequests.append(std::make_pair(origin, request));
+ decidePolicyForUserMediaPermissionRequestIfPossible();
+}
+
+void TestController::decidePolicyForUserMediaPermissionRequestIfPossible()
+{
+ if (!m_isUserMediaPermissionSet)
+ return;
+
+ for (auto& pair : m_userMediaPermissionRequests) {
+ auto request = pair.second.get();
+ WKRetainPtr<WKArrayRef> audioDeviceUIDs = WKUserMediaPermissionRequestAudioDeviceUIDs(request);
+ WKRetainPtr<WKArrayRef> videoDeviceUIDs = WKUserMediaPermissionRequestVideoDeviceUIDs(request);
+
+ if (m_isUserMediaPermissionAllowed && (WKArrayGetSize(videoDeviceUIDs.get()) || WKArrayGetSize(audioDeviceUIDs.get()))) {
+ WKRetainPtr<WKStringRef> videoDeviceUID;
+ if (WKArrayGetSize(videoDeviceUIDs.get()))
+ videoDeviceUID = reinterpret_cast<WKStringRef>(WKArrayGetItemAtIndex(videoDeviceUIDs.get(), 0));
+ else
+ videoDeviceUID = WKStringCreateWithUTF8CString("");
+
+ WKRetainPtr<WKStringRef> audioDeviceUID;
+ if (WKArrayGetSize(audioDeviceUIDs.get()))
+ audioDeviceUID = reinterpret_cast<WKStringRef>(WKArrayGetItemAtIndex(audioDeviceUIDs.get(), 0));
+ else
+ audioDeviceUID = WKStringCreateWithUTF8CString("");
+
+ WKUserMediaPermissionRequestAllow(request, audioDeviceUID.get(), videoDeviceUID.get());
+
+ } else
+ WKUserMediaPermissionRequestDeny(request);
+ }
+ m_userMediaPermissionRequests.clear();
}
-void TestController::setVisibilityState(WKPageVisibilityState visibilityState, bool isInitialState)
+void TestController::setCustomPolicyDelegate(bool enabled, bool permissive)
{
- setHidden(visibilityState != kWKPageVisibilityStateVisible);
- WKPageSetVisibilityState(m_mainWebView->page(), visibilityState, isInitialState);
+ m_policyDelegateEnabled = enabled;
+ m_policyDelegatePermissive = permissive;
}
void TestController::decidePolicyForGeolocationPermissionRequestIfPossible()
@@ -1189,7 +1754,7 @@ void TestController::decidePolicyForGeolocationPermissionRequestIfPossible()
void TestController::decidePolicyForNotificationPermissionRequest(WKPageRef page, WKSecurityOriginRef origin, WKNotificationPermissionRequestRef request, const void*)
{
- TestController::shared().decidePolicyForNotificationPermissionRequest(page, origin, request);
+ TestController::singleton().decidePolicyForNotificationPermissionRequest(page, origin, request);
}
void TestController::decidePolicyForNotificationPermissionRequest(WKPageRef, WKSecurityOriginRef, WKNotificationPermissionRequestRef request)
@@ -1202,32 +1767,38 @@ void TestController::unavailablePluginButtonClicked(WKPageRef, WKPluginUnavailab
printf("MISSING PLUGIN BUTTON PRESSED\n");
}
-void TestController::decidePolicyForNavigationAction(WKPageRef, WKFrameRef, WKFrameNavigationType, WKEventModifiers, WKEventMouseButton, WKFrameRef, WKURLRequestRef, WKFramePolicyListenerRef listener, WKTypeRef, const void* clientInfo)
+void TestController::decidePolicyForNavigationAction(WKPageRef, WKNavigationActionRef navigationAction, WKFramePolicyListenerRef listener, WKTypeRef, const void* clientInfo)
{
static_cast<TestController*>(const_cast<void*>(clientInfo))->decidePolicyForNavigationAction(listener);
}
void TestController::decidePolicyForNavigationAction(WKFramePolicyListenerRef listener)
{
- if (m_policyDelegateEnabled && !m_policyDelegatePermissive) {
- WKFramePolicyListenerIgnore(listener);
- return;
- }
+ WKRetainPtr<WKFramePolicyListenerRef> retainedListener { listener };
+ const bool shouldIgnore { m_policyDelegateEnabled && !m_policyDelegatePermissive };
+ std::function<void()> decisionFunction = [shouldIgnore, retainedListener]() {
+ if (shouldIgnore)
+ WKFramePolicyListenerIgnore(retainedListener.get());
+ else
+ WKFramePolicyListenerUse(retainedListener.get());
+ };
- WKFramePolicyListenerUse(listener);
+ if (m_shouldDecideNavigationPolicyAfterDelay)
+ RunLoop::main().dispatch(decisionFunction);
+ else
+ decisionFunction();
}
-void TestController::decidePolicyForResponse(WKPageRef, WKFrameRef frame, WKURLResponseRef response, WKURLRequestRef, bool canShowMIMEType, WKFramePolicyListenerRef listener, WKTypeRef, const void* clientInfo)
+void TestController::decidePolicyForNavigationResponse(WKPageRef, WKNavigationResponseRef navigationResponse, WKFramePolicyListenerRef listener, WKTypeRef, const void* clientInfo)
{
- static_cast<TestController*>(const_cast<void*>(clientInfo))->decidePolicyForResponse(frame, response, listener);
+ static_cast<TestController*>(const_cast<void*>(clientInfo))->decidePolicyForNavigationResponse(navigationResponse, listener);
}
-void TestController::decidePolicyForResponse(WKFrameRef frame, WKURLResponseRef response, WKFramePolicyListenerRef listener)
+void TestController::decidePolicyForNavigationResponse(WKNavigationResponseRef navigationResponse, WKFramePolicyListenerRef listener)
{
// Even though Response was already checked by WKBundlePagePolicyClient, the check did not include plugins
// so we have to re-check again.
- WKRetainPtr<WKStringRef> wkMIMEType(AdoptWK, WKURLResponseCopyMIMEType(response));
- if (WKFrameCanShowMIMEType(frame, wkMIMEType.get())) {
+ if (WKNavigationResponseCanShowMIMEType(navigationResponse)) {
WKFramePolicyListenerUse(listener);
return;
}
@@ -1235,4 +1806,117 @@ void TestController::decidePolicyForResponse(WKFrameRef frame, WKURLResponseRef
WKFramePolicyListenerIgnore(listener);
}
+void TestController::didNavigateWithNavigationData(WKContextRef, WKPageRef, WKNavigationDataRef navigationData, WKFrameRef frame, const void* clientInfo)
+{
+ static_cast<TestController*>(const_cast<void*>(clientInfo))->didNavigateWithNavigationData(navigationData, frame);
+}
+
+void TestController::didNavigateWithNavigationData(WKNavigationDataRef navigationData, WKFrameRef)
+{
+ if (m_state != RunningTest)
+ return;
+
+ if (!m_shouldLogHistoryClientCallbacks)
+ return;
+
+ // URL
+ WKRetainPtr<WKURLRef> urlWK = adoptWK(WKNavigationDataCopyURL(navigationData));
+ WKRetainPtr<WKStringRef> urlStringWK = adoptWK(WKURLCopyString(urlWK.get()));
+ // Title
+ WKRetainPtr<WKStringRef> titleWK = adoptWK(WKNavigationDataCopyTitle(navigationData));
+ // HTTP method
+ WKRetainPtr<WKURLRequestRef> requestWK = adoptWK(WKNavigationDataCopyOriginalRequest(navigationData));
+ WKRetainPtr<WKStringRef> methodWK = adoptWK(WKURLRequestCopyHTTPMethod(requestWK.get()));
+
+ // FIXME: Determine whether the navigation was successful / a client redirect rather than hard-coding the message here.
+ m_currentInvocation->outputText(String::format("WebView navigated to url \"%s\" with title \"%s\" with HTTP equivalent method \"%s\". The navigation was successful and was not a client redirect.\n",
+ toSTD(urlStringWK).c_str(), toSTD(titleWK).c_str(), toSTD(methodWK).c_str()));
+}
+
+void TestController::didPerformClientRedirect(WKContextRef, WKPageRef, WKURLRef sourceURL, WKURLRef destinationURL, WKFrameRef frame, const void* clientInfo)
+{
+ static_cast<TestController*>(const_cast<void*>(clientInfo))->didPerformClientRedirect(sourceURL, destinationURL, frame);
+}
+
+void TestController::didPerformClientRedirect(WKURLRef sourceURL, WKURLRef destinationURL, WKFrameRef)
+{
+ if (m_state != RunningTest)
+ return;
+
+ if (!m_shouldLogHistoryClientCallbacks)
+ return;
+
+ WKRetainPtr<WKStringRef> sourceStringWK = adoptWK(WKURLCopyString(sourceURL));
+ WKRetainPtr<WKStringRef> destinationStringWK = adoptWK(WKURLCopyString(destinationURL));
+
+ m_currentInvocation->outputText(String::format("WebView performed a client redirect from \"%s\" to \"%s\".\n", toSTD(sourceStringWK).c_str(), toSTD(destinationStringWK).c_str()));
+}
+
+void TestController::didPerformServerRedirect(WKContextRef, WKPageRef, WKURLRef sourceURL, WKURLRef destinationURL, WKFrameRef frame, const void* clientInfo)
+{
+ static_cast<TestController*>(const_cast<void*>(clientInfo))->didPerformServerRedirect(sourceURL, destinationURL, frame);
+}
+
+void TestController::didPerformServerRedirect(WKURLRef sourceURL, WKURLRef destinationURL, WKFrameRef)
+{
+ if (m_state != RunningTest)
+ return;
+
+ if (!m_shouldLogHistoryClientCallbacks)
+ return;
+
+ WKRetainPtr<WKStringRef> sourceStringWK = adoptWK(WKURLCopyString(sourceURL));
+ WKRetainPtr<WKStringRef> destinationStringWK = adoptWK(WKURLCopyString(destinationURL));
+
+ m_currentInvocation->outputText(String::format("WebView performed a server redirect from \"%s\" to \"%s\".\n", toSTD(sourceStringWK).c_str(), toSTD(destinationStringWK).c_str()));
+}
+
+void TestController::didUpdateHistoryTitle(WKContextRef, WKPageRef, WKStringRef title, WKURLRef URL, WKFrameRef frame, const void* clientInfo)
+{
+ static_cast<TestController*>(const_cast<void*>(clientInfo))->didUpdateHistoryTitle(title, URL, frame);
+}
+
+void TestController::didUpdateHistoryTitle(WKStringRef title, WKURLRef URL, WKFrameRef)
+{
+ if (m_state != RunningTest)
+ return;
+
+ if (!m_shouldLogHistoryClientCallbacks)
+ return;
+
+ WKRetainPtr<WKStringRef> urlStringWK(AdoptWK, WKURLCopyString(URL));
+ m_currentInvocation->outputText(String::format("WebView updated the title for history URL \"%s\" to \"%s\".\n", toSTD(urlStringWK).c_str(), toSTD(title).c_str()));
+}
+
+void TestController::setNavigationGesturesEnabled(bool value)
+{
+ m_mainWebView->setNavigationGesturesEnabled(value);
+}
+
+#if !PLATFORM(COCOA)
+void TestController::platformWillRunTest(const TestInvocation&)
+{
+}
+
+void TestController::platformCreateWebView(WKPageConfigurationRef configuration, const TestOptions& options)
+{
+ m_mainWebView = std::make_unique<PlatformWebView>(configuration, options);
+}
+
+PlatformWebView* TestController::platformCreateOtherPage(PlatformWebView* parentView, WKPageConfigurationRef configuration, const TestOptions& options)
+{
+ return new PlatformWebView(configuration, options);
+}
+
+WKContextRef TestController::platformAdjustContext(WKContextRef context, WKContextConfigurationRef contextConfiguration)
+{
+ return context;
+}
+
+void TestController::platformResetStateToConsistentValues()
+{
+
+}
+#endif
+
} // namespace WTR
diff --git a/Tools/WebKitTestRunner/TestController.h b/Tools/WebKitTestRunner/TestController.h
index 10031a176..ff06cfb16 100644
--- a/Tools/WebKitTestRunner/TestController.h
+++ b/Tools/WebKitTestRunner/TestController.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010, 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
@@ -29,22 +29,25 @@
#include "GeolocationProviderMock.h"
#include "WebNotificationProvider.h"
#include "WorkQueueManager.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
#include <string>
#include <vector>
-#include <wtf/OwnPtr.h>
+#include <wtf/HashMap.h>
#include <wtf/Vector.h>
+OBJC_CLASS WKWebViewConfiguration;
+
namespace WTR {
class TestInvocation;
class PlatformWebView;
class EventSenderProxy;
+struct TestOptions;
// FIXME: Rename this TestRunner?
class TestController {
public:
- static TestController& shared();
+ static TestController& singleton();
static const unsigned viewWidth;
static const unsigned viewHeight;
@@ -52,29 +55,32 @@ public:
static const unsigned w3cSVGViewWidth;
static const unsigned w3cSVGViewHeight;
+ static const double shortTimeout;
+ static const double noTimeout;
+
TestController(int argc, const char* argv[]);
~TestController();
bool verbose() const { return m_verbose; }
- WKStringRef injectedBundlePath() { return m_injectedBundlePath.get(); }
- WKStringRef testPluginDirectory() { return m_testPluginDirectory.get(); }
+ WKStringRef injectedBundlePath() const { return m_injectedBundlePath.get(); }
+ WKStringRef testPluginDirectory() const { return m_testPluginDirectory.get(); }
PlatformWebView* mainWebView() { return m_mainWebView.get(); }
WKContextRef context() { return m_context.get(); }
EventSenderProxy* eventSenderProxy() { return m_eventSenderProxy.get(); }
- void ensureViewSupportsOptions(WKDictionaryRef options);
bool shouldUseRemoteLayerTree() const { return m_shouldUseRemoteLayerTree; }
// Runs the run loop until `done` is true or the timeout elapses.
- enum TimeoutDuration { ShortTimeout, LongTimeout, NoTimeout, CustomTimeout };
bool useWaitToDumpWatchdogTimer() { return m_useWaitToDumpWatchdogTimer; }
- void runUntil(bool& done, TimeoutDuration);
+ void runUntil(bool& done, double timeoutSeconds);
void notifyDone();
- int getCustomTimeout();
+ bool shouldShowWebView() const { return m_shouldShowWebView; }
+
+ void configureViewForTest(const TestInvocation&);
bool beforeUnloadReturnValue() const { return m_beforeUnloadReturnValue; }
void setBeforeUnloadReturnValue(bool value) { m_beforeUnloadReturnValue = value; }
@@ -86,16 +92,29 @@ public:
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);
void handleGeolocationPermissionRequest(WKGeolocationPermissionRequestRef);
+ bool isGeolocationProviderActive() const;
+
+ // MediaStream.
+ void setUserMediaPermission(bool);
+ void setUserMediaPermissionForOrigin(bool permission, WKStringRef url);
+ void handleUserMediaPermissionRequest(WKSecurityOriginRef, WKUserMediaPermissionRequestRef);
+ void handleCheckOfUserMediaPermissionForOrigin(WKSecurityOriginRef, const WKUserMediaPermissionCheckRef&);
// Policy delegate.
void setCustomPolicyDelegate(bool enabled, bool permissive);
// Page Visibility.
- void setVisibilityState(WKPageVisibilityState, bool isInitialState);
+ void setHidden(bool);
bool resetStateToConsistentValues();
void resetPreferencesToConsistentValues();
+ void terminateWebContentProcess();
+ void reattachPageToWebProcess();
+
+ static const char* webProcessName();
+ static const char* networkProcessName();
+
WorkQueueManager& workQueueManager() { return m_workQueueManager; }
void setHandlesAuthenticationChallenges(bool value) { m_handlesAuthenticationChallenges = value; }
@@ -104,9 +123,19 @@ public:
void setBlockAllPlugins(bool shouldBlock) { m_shouldBlockAllPlugins = shouldBlock; }
+ void setShouldLogHistoryClientCallbacks(bool shouldLog) { m_shouldLogHistoryClientCallbacks = shouldLog; }
+
+ bool isCurrentInvocation(TestInvocation* invocation) const { return invocation == m_currentInvocation.get(); }
+
+ void setShouldDecideNavigationPolicyAfterDelay(bool value) { m_shouldDecideNavigationPolicyAfterDelay = value; }
+
+ void setNavigationGesturesEnabled(bool value);
+
private:
+ WKRetainPtr<WKPageConfigurationRef> generatePageConfiguration(WKContextConfigurationRef);
+ WKRetainPtr<WKContextConfigurationRef> generateContextConfiguration() const;
void initialize(int argc, const char* argv[]);
- void createWebViewWithOptions(WKDictionaryRef);
+ void createWebViewWithOptions(const TestOptions&);
void run();
void runTestingServerLoop();
@@ -114,34 +143,70 @@ private:
void platformInitialize();
void platformDestroy();
+ WKContextRef platformAdjustContext(WKContextRef, WKContextConfigurationRef);
void platformInitializeContext();
+ void platformCreateWebView(WKPageConfigurationRef, const TestOptions&);
+ static PlatformWebView* platformCreateOtherPage(PlatformWebView* parentView, WKPageConfigurationRef, const TestOptions&);
+ void platformResetPreferencesToConsistentValues();
+ void platformResetStateToConsistentValues();
+#if PLATFORM(COCOA)
+ void cocoaResetStateToConsistentValues();
+#endif
+ void platformConfigureViewForTest(const TestInvocation&);
+ void platformWillRunTest(const TestInvocation&);
void platformRunUntil(bool& done, double timeout);
void platformDidCommitLoadForFrame(WKPageRef, WKFrameRef);
+ WKPreferencesRef platformPreferences();
void initializeInjectedBundlePath();
void initializeTestPluginDirectory();
+ void ensureViewSupportsOptionsForTest(const TestInvocation&);
+ TestOptions testOptionsForTest(const std::string& pathOrURL) const;
+ void updatePlatformSpecificTestOptionsForTest(TestOptions&, const std::string& pathOrURL) const;
+
+ void updateWebViewSizeForTest(const TestInvocation&);
+ void updateWindowScaleForTest(PlatformWebView*, const TestInvocation&);
+
void decidePolicyForGeolocationPermissionRequestIfPossible();
+ void decidePolicyForUserMediaPermissionRequestIfPossible();
// WKContextInjectedBundleClient
static void didReceiveMessageFromInjectedBundle(WKContextRef, WKStringRef messageName, WKTypeRef messageBody, const void*);
static void didReceiveSynchronousMessageFromInjectedBundle(WKContextRef, WKStringRef messageName, WKTypeRef messageBody, WKTypeRef* returnData, const void*);
+
+ // WKPageInjectedBundleClient
+ static void didReceivePageMessageFromInjectedBundle(WKPageRef, WKStringRef messageName, WKTypeRef messageBody, const void*);
+ static void didReceiveSynchronousPageMessageFromInjectedBundle(WKPageRef, WKStringRef messageName, WKTypeRef messageBody, WKTypeRef* returnData, const void*);
void didReceiveMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody);
WKRetainPtr<WKTypeRef> didReceiveSynchronousMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody);
void didReceiveKeyDownMessageFromInjectedBundle(WKDictionaryRef messageBodyDictionary, bool synchronous);
- // WKPageLoaderClient
- static void didCommitLoadForFrame(WKPageRef, WKFrameRef, WKTypeRef userData, const void*);
- void didCommitLoadForFrame(WKPageRef, WKFrameRef);
+ // WKContextClient
+ static void networkProcessDidCrash(WKContextRef, const void*);
+ void networkProcessDidCrash();
- static void didFinishLoadForFrame(WKPageRef, WKFrameRef, WKTypeRef userData, const void*);
- void didFinishLoadForFrame(WKPageRef, WKFrameRef);
+ // WKPageNavigationClient
+ static void didCommitNavigation(WKPageRef, WKNavigationRef, WKTypeRef userData, const void*);
+ void didCommitNavigation(WKPageRef, WKNavigationRef);
+
+ static void didFinishNavigation(WKPageRef, WKNavigationRef, WKTypeRef userData, const void*);
+ void didFinishNavigation(WKPageRef, WKNavigationRef);
static void processDidCrash(WKPageRef, const void* clientInfo);
void processDidCrash();
- static WKPluginLoadPolicy pluginLoadPolicy(WKPageRef, WKPluginLoadPolicy currentPluginLoadPolicy, WKDictionaryRef pluginInformation, WKStringRef* unavailabilityDescription, const void* clientInfo);
- WKPluginLoadPolicy pluginLoadPolicy(WKPageRef, WKPluginLoadPolicy currentPluginLoadPolicy, WKDictionaryRef pluginInformation, WKStringRef* unavailabilityDescription);
+ static void didBeginNavigationGesture(WKPageRef, const void*);
+ static void willEndNavigationGesture(WKPageRef, WKBackForwardListItemRef, const void*);
+ static void didEndNavigationGesture(WKPageRef, WKBackForwardListItemRef, const void*);
+ static void didRemoveNavigationGestureSnapshot(WKPageRef, const void*);
+ void didBeginNavigationGesture(WKPageRef);
+ void willEndNavigationGesture(WKPageRef, WKBackForwardListItemRef);
+ void didEndNavigationGesture(WKPageRef, WKBackForwardListItemRef);
+ void didRemoveNavigationGestureSnapshot(WKPageRef);
+
+ static WKPluginLoadPolicy decidePolicyForPluginLoad(WKPageRef, WKPluginLoadPolicy currentPluginLoadPolicy, WKDictionaryRef pluginInformation, WKStringRef* unavailabilityDescription, const void* clientInfo);
+ WKPluginLoadPolicy decidePolicyForPluginLoad(WKPageRef, WKPluginLoadPolicy currentPluginLoadPolicy, WKDictionaryRef pluginInformation, WKStringRef* unavailabilityDescription);
static void decidePolicyForNotificationPermissionRequest(WKPageRef, WKSecurityOriginRef, WKNotificationPermissionRequestRef, const void*);
@@ -149,27 +214,39 @@ private:
static void unavailablePluginButtonClicked(WKPageRef, WKPluginUnavailabilityReason, WKDictionaryRef, const void*);
- static void didReceiveAuthenticationChallengeInFrame(WKPageRef, WKFrameRef, WKAuthenticationChallengeRef, const void *clientInfo);
- void didReceiveAuthenticationChallengeInFrame(WKPageRef, WKFrameRef, WKAuthenticationChallengeRef);
+ static bool canAuthenticateAgainstProtectionSpace(WKPageRef, WKProtectionSpaceRef, const void *clientInfo);
+
+ static void didReceiveAuthenticationChallenge(WKPageRef, WKAuthenticationChallengeRef, const void *clientInfo);
+ void didReceiveAuthenticationChallenge(WKPageRef, WKAuthenticationChallengeRef);
- // WKPagePolicyClient
- static void decidePolicyForNavigationAction(WKPageRef, WKFrameRef, WKFrameNavigationType, WKEventModifiers, WKEventMouseButton, WKFrameRef, WKURLRequestRef, WKFramePolicyListenerRef, WKTypeRef, const void*);
+ static void decidePolicyForNavigationAction(WKPageRef, WKNavigationActionRef, WKFramePolicyListenerRef, WKTypeRef, const void*);
void decidePolicyForNavigationAction(WKFramePolicyListenerRef);
- static void decidePolicyForResponse(WKPageRef, WKFrameRef, WKURLResponseRef, WKURLRequestRef, bool canShowMIMEType, WKFramePolicyListenerRef, WKTypeRef, const void*);
- void decidePolicyForResponse(WKFrameRef, WKURLResponseRef, WKFramePolicyListenerRef);
+ static void decidePolicyForNavigationResponse(WKPageRef, WKNavigationResponseRef, WKFramePolicyListenerRef, WKTypeRef, const void*);
+ void decidePolicyForNavigationResponse(WKNavigationResponseRef, WKFramePolicyListenerRef);
+
+ // WKContextHistoryClient
+ static void didNavigateWithNavigationData(WKContextRef, WKPageRef, WKNavigationDataRef, WKFrameRef, const void*);
+ void didNavigateWithNavigationData(WKNavigationDataRef, WKFrameRef);
+
+ static void didPerformClientRedirect(WKContextRef, WKPageRef, WKURLRef sourceURL, WKURLRef destinationURL, WKFrameRef, const void*);
+ void didPerformClientRedirect(WKURLRef sourceURL, WKURLRef destinationURL, WKFrameRef);
- static WKPageRef createOtherPage(WKPageRef oldPage, WKURLRequestRef, WKDictionaryRef, WKEventModifiers, WKEventMouseButton, const void*);
+ static void didPerformServerRedirect(WKContextRef, WKPageRef, WKURLRef sourceURL, WKURLRef destinationURL, WKFrameRef, const void*);
+ void didPerformServerRedirect(WKURLRef sourceURL, WKURLRef destinationURL, WKFrameRef);
+
+ static void didUpdateHistoryTitle(WKContextRef, WKPageRef, WKStringRef title, WKURLRef, WKFrameRef, const void*);
+ void didUpdateHistoryTitle(WKStringRef title, WKURLRef, WKFrameRef);
+
+ static WKPageRef createOtherPage(WKPageRef, WKPageConfigurationRef, WKNavigationActionRef, WKWindowFeaturesRef, const void*);
static void runModal(WKPageRef, const void* clientInfo);
static void runModal(PlatformWebView*);
- void setHidden(bool);
-
static const char* libraryPathForTesting();
static const char* platformLibraryPathForTesting();
- OwnPtr<TestInvocation> m_currentInvocation;
+ std::unique_ptr<TestInvocation> m_currentInvocation;
bool m_verbose;
bool m_printSeparators;
@@ -177,12 +254,13 @@ private:
bool m_gcBetweenTests;
bool m_shouldDumpPixelsForAllTests;
std::vector<std::string> m_paths;
+ std::vector<std::string> m_allowedHosts;
WKRetainPtr<WKStringRef> m_injectedBundlePath;
WKRetainPtr<WKStringRef> m_testPluginDirectory;
WebNotificationProvider m_webNotificationProvider;
- OwnPtr<PlatformWebView> m_mainWebView;
+ std::unique_ptr<PlatformWebView> m_mainWebView;
WKRetainPtr<WKContextRef> m_context;
WKRetainPtr<WKPageGroupRef> m_pageGroup;
@@ -194,24 +272,27 @@ private:
State m_state;
bool m_doneResetting;
- double m_longTimeout;
- double m_shortTimeout;
- double m_noTimeout;
bool m_useWaitToDumpWatchdogTimer;
bool m_forceNoTimeout;
- int m_timeout;
-
bool m_didPrintWebProcessCrashedMessage;
bool m_shouldExitWhenWebProcessCrashes;
bool m_beforeUnloadReturnValue;
- OwnPtr<GeolocationProviderMock> m_geolocationProvider;
+ std::unique_ptr<GeolocationProviderMock> m_geolocationProvider;
Vector<WKRetainPtr<WKGeolocationPermissionRequestRef> > m_geolocationPermissionRequests;
bool m_isGeolocationPermissionSet;
bool m_isGeolocationPermissionAllowed;
+ WKRetainPtr<WKMutableDictionaryRef> m_userMediaOriginPermissions;
+
+ typedef Vector<std::pair<WKRetainPtr<WKSecurityOriginRef>, WKRetainPtr<WKUserMediaPermissionRequestRef>>> PermissionRequestList;
+ PermissionRequestList m_userMediaPermissionRequests;
+
+ bool m_isUserMediaPermissionSet;
+ bool m_isUserMediaPermissionAllowed;
+
bool m_policyDelegateEnabled;
bool m_policyDelegatePermissive;
@@ -225,7 +306,12 @@ private:
bool m_shouldUseAcceleratedDrawing;
bool m_shouldUseRemoteLayerTree;
- OwnPtr<EventSenderProxy> m_eventSenderProxy;
+ bool m_shouldLogHistoryClientCallbacks;
+ bool m_shouldShowWebView;
+
+ bool m_shouldDecideNavigationPolicyAfterDelay { false };
+
+ std::unique_ptr<EventSenderProxy> m_eventSenderProxy;
WorkQueueManager m_workQueueManager;
};
diff --git a/Tools/WebKitTestRunner/TestInvocation.cpp b/Tools/WebKitTestRunner/TestInvocation.cpp
index cac2ba8b8..6ab38925f 100644
--- a/Tools/WebKitTestRunner/TestInvocation.cpp
+++ b/Tools/WebKitTestRunner/TestInvocation.cpp
@@ -30,196 +30,123 @@
#include "PlatformWebView.h"
#include "StringFunctions.h"
#include "TestController.h"
+#include "UIScriptController.h"
+#include <WebKit/WKContextPrivate.h>
+#include <WebKit/WKCookieManager.h>
+#include <WebKit/WKData.h>
+#include <WebKit/WKDictionary.h>
+#include <WebKit/WKInspector.h>
+#include <WebKit/WKPagePrivate.h>
+#include <WebKit/WKRetainPtr.h>
#include <climits>
#include <cstdio>
-#include <WebKit2/WKContextPrivate.h>
-#include <WebKit2/WKData.h>
-#include <WebKit2/WKDictionary.h>
-#include <WebKit2/WKInspector.h>
-#include <WebKit2/WKRetainPtr.h>
-#include <wtf/PassOwnPtr.h>
#include <wtf/StdLibExtras.h>
#include <wtf/text/CString.h>
-#if PLATFORM(MAC)
-#if !PLATFORM(IOS)
+#if PLATFORM(MAC) && !PLATFORM(IOS)
#include <Carbon/Carbon.h>
#endif
-#include <WebKit2/WKPagePrivateMac.h>
-#endif
-#include <unistd.h> // For getcwd.
+#if PLATFORM(COCOA)
+#include <WebKit/WKPagePrivateMac.h>
+#endif
+using namespace JSC;
using namespace WebKit;
using namespace std;
namespace WTR {
-static WKURLRef createWKURL(const char* pathOrURL)
+TestInvocation::TestInvocation(WKURLRef url, const TestOptions& options)
+ : m_options(options)
+ , m_url(url)
{
- if (strstr(pathOrURL, "http://") || strstr(pathOrURL, "https://") || strstr(pathOrURL, "file://"))
- return WKURLCreateWithUTF8CString(pathOrURL);
+ WKRetainPtr<WKStringRef> urlString = adoptWK(WKURLCopyString(m_url.get()));
- // Creating from filesytem path.
- size_t length = strlen(pathOrURL);
- if (!length)
- return 0;
-
- const char separator = '/';
- bool isAbsolutePath = pathOrURL[0] == separator;
- const char* filePrefix = "file://";
- static const size_t prefixLength = strlen(filePrefix);
-
- std::unique_ptr<char[]> buffer;
- if (isAbsolutePath) {
- buffer = std::make_unique<char[]>(prefixLength + length + 1);
- strcpy(buffer.get(), filePrefix);
- strcpy(buffer.get() + prefixLength, pathOrURL);
- } else {
- buffer = std::make_unique<char[]>(prefixLength + PATH_MAX + length + 2); // 1 for the separator
- strcpy(buffer.get(), filePrefix);
- if (!getcwd(buffer.get() + prefixLength, PATH_MAX))
- return 0;
- size_t numCharacters = strlen(buffer.get());
- buffer[numCharacters] = separator;
- strcpy(buffer.get() + numCharacters + 1, pathOrURL);
- }
-
- return WKURLCreateWithUTF8CString(buffer.get());
-}
+ size_t stringLength = WKStringGetLength(urlString.get());
-TestInvocation::TestInvocation(const std::string& pathOrURL)
- : m_url(AdoptWK, createWKURL(pathOrURL.c_str()))
- , m_pathOrURL(pathOrURL)
- , m_dumpPixels(false)
- , m_timeout(0)
- , m_gotInitialResponse(false)
- , m_gotFinalMessage(false)
- , m_gotRepaint(false)
- , m_error(false)
- , m_webProcessIsUnresponsive(false)
-{
-}
+ Vector<char> urlVector;
+ urlVector.resize(stringLength + 1);
-TestInvocation::~TestInvocation()
-{
-}
+ WKStringGetUTF8CString(urlString.get(), urlVector.data(), stringLength + 1);
-void TestInvocation::setIsPixelTest(const std::string& expectedPixelHash)
-{
- m_dumpPixels = true;
- m_expectedPixelHash = expectedPixelHash;
+ m_urlString = String(urlVector.data(), stringLength);
}
-void TestInvocation::setCustomTimeout(int timeout)
+TestInvocation::~TestInvocation()
{
- m_timeout = timeout;
+ if (m_pendingUIScriptInvocationData)
+ m_pendingUIScriptInvocationData->testInvocation = nullptr;
}
-static void sizeWebViewForCurrentTest(const char* pathOrURL)
+WKURLRef TestInvocation::url() const
{
- bool isSVGW3CTest = strstr(pathOrURL, "svg/W3C-SVG-1.1") || strstr(pathOrURL, "svg\\W3C-SVG-1.1");
-
- if (isSVGW3CTest)
- TestController::shared().mainWebView()->resizeTo(TestController::w3cSVGViewWidth, TestController::w3cSVGViewHeight);
- else
- TestController::shared().mainWebView()->resizeTo(TestController::viewWidth, TestController::viewHeight);
+ return m_url.get();
}
-static bool shouldLogFrameLoadDelegates(const char* pathOrURL)
+bool TestInvocation::urlContains(const char* searchString) const
{
- return strstr(pathOrURL, "loading/");
+ return m_urlString.contains(searchString, false);
}
-#if ENABLE(INSPECTOR) && !PLATFORM(IOS)
-static bool shouldOpenWebInspector(const char* pathOrURL)
+void TestInvocation::setIsPixelTest(const std::string& expectedPixelHash)
{
- return strstr(pathOrURL, "inspector/") || strstr(pathOrURL, "inspector\\");
+ m_dumpPixels = true;
+ m_expectedPixelHash = expectedPixelHash;
}
-#endif
-#if PLATFORM(MAC)
-static bool shouldUseThreadedScrolling(const char* pathOrURL)
+bool TestInvocation::shouldLogFrameLoadDelegates() const
{
- return strstr(pathOrURL, "tiled-drawing/") || strstr(pathOrURL, "tiled-drawing\\");
+ return urlContains("loading/");
}
-#endif
-static void updateThreadedScrollingForCurrentTest(const char* pathOrURL)
+bool TestInvocation::shouldLogHistoryClientCallbacks() const
{
-#if PLATFORM(MAC)
- WKRetainPtr<WKMutableDictionaryRef> viewOptions = adoptWK(WKMutableDictionaryCreate());
- WKRetainPtr<WKStringRef> useThreadedScrollingKey = adoptWK(WKStringCreateWithUTF8CString("ThreadedScrolling"));
- WKRetainPtr<WKBooleanRef> useThreadedScrollingValue = adoptWK(WKBooleanCreate(shouldUseThreadedScrolling(pathOrURL)));
- WKDictionarySetItem(viewOptions.get(), useThreadedScrollingKey.get(), useThreadedScrollingValue.get());
-
- WKRetainPtr<WKStringRef> useRemoteLayerTreeKey = adoptWK(WKStringCreateWithUTF8CString("RemoteLayerTree"));
- WKRetainPtr<WKBooleanRef> useRemoteLayerTreeValue = adoptWK(WKBooleanCreate(TestController::shared().shouldUseRemoteLayerTree()));
- WKDictionarySetItem(viewOptions.get(), useRemoteLayerTreeKey.get(), useRemoteLayerTreeValue.get());
-
- TestController::shared().ensureViewSupportsOptions(viewOptions.get());
-#else
- UNUSED_PARAM(pathOrURL);
-#endif
+ return urlContains("globalhistory/");
}
-static bool shouldUseFixedLayout(const char* pathOrURL)
+void TestInvocation::invoke()
{
-#if ENABLE(CSS_DEVICE_ADAPTATION)
- if (strstr(pathOrURL, "device-adapt/") || strstr(pathOrURL, "device-adapt\\"))
- return true;
-#endif
-
-#if USE(TILED_BACKING_STORE) && PLATFORM(EFL)
- if (strstr(pathOrURL, "sticky/") || strstr(pathOrURL, "sticky\\"))
- return true;
-#endif
- return false;
+ TestController::singleton().configureViewForTest(*this);
- UNUSED_PARAM(pathOrURL);
-}
+ WKPageSetAddsVisitedLinks(TestController::singleton().mainWebView()->page(), false);
-static void updateLayoutType(const char* pathOrURL)
-{
- WKRetainPtr<WKMutableDictionaryRef> viewOptions = adoptWK(WKMutableDictionaryCreate());
- WKRetainPtr<WKStringRef> useFixedLayoutKey = adoptWK(WKStringCreateWithUTF8CString("UseFixedLayout"));
- WKRetainPtr<WKBooleanRef> useFixedLayoutValue = adoptWK(WKBooleanCreate(shouldUseFixedLayout(pathOrURL)));
- WKDictionarySetItem(viewOptions.get(), useFixedLayoutKey.get(), useFixedLayoutValue.get());
+ m_textOutput.clear();
- TestController::shared().ensureViewSupportsOptions(viewOptions.get());
-}
+ TestController::singleton().setShouldLogHistoryClientCallbacks(shouldLogHistoryClientCallbacks());
-void TestInvocation::invoke()
-{
- TestController::TimeoutDuration timeoutToUse = TestController::LongTimeout;
- sizeWebViewForCurrentTest(m_pathOrURL.c_str());
- updateLayoutType(m_pathOrURL.c_str());
- updateThreadedScrollingForCurrentTest(m_pathOrURL.c_str());
+ WKCookieManagerSetHTTPCookieAcceptPolicy(WKContextGetCookieManager(TestController::singleton().context()), kWKHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain);
- m_textOutput.clear();
+ // FIXME: We should clear out visited links here.
WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("BeginTest"));
WKRetainPtr<WKMutableDictionaryRef> beginTestMessageBody = adoptWK(WKMutableDictionaryCreate());
WKRetainPtr<WKStringRef> dumpFrameLoadDelegatesKey = adoptWK(WKStringCreateWithUTF8CString("DumpFrameLoadDelegates"));
- WKRetainPtr<WKBooleanRef> dumpFrameLoadDelegatesValue = adoptWK(WKBooleanCreate(shouldLogFrameLoadDelegates(m_pathOrURL.c_str())));
+ WKRetainPtr<WKBooleanRef> dumpFrameLoadDelegatesValue = adoptWK(WKBooleanCreate(shouldLogFrameLoadDelegates()));
WKDictionarySetItem(beginTestMessageBody.get(), dumpFrameLoadDelegatesKey.get(), dumpFrameLoadDelegatesValue.get());
+ WKRetainPtr<WKStringRef> useFlexibleViewportKey = adoptWK(WKStringCreateWithUTF8CString("UseFlexibleViewport"));
+ WKRetainPtr<WKBooleanRef> useFlexibleViewportValue = adoptWK(WKBooleanCreate(options().useFlexibleViewport));
+ WKDictionarySetItem(beginTestMessageBody.get(), useFlexibleViewportKey.get(), useFlexibleViewportValue.get());
+
WKRetainPtr<WKStringRef> dumpPixelsKey = adoptWK(WKStringCreateWithUTF8CString("DumpPixels"));
WKRetainPtr<WKBooleanRef> dumpPixelsValue = adoptWK(WKBooleanCreate(m_dumpPixels));
WKDictionarySetItem(beginTestMessageBody.get(), dumpPixelsKey.get(), dumpPixelsValue.get());
WKRetainPtr<WKStringRef> useWaitToDumpWatchdogTimerKey = adoptWK(WKStringCreateWithUTF8CString("UseWaitToDumpWatchdogTimer"));
- WKRetainPtr<WKBooleanRef> useWaitToDumpWatchdogTimerValue = adoptWK(WKBooleanCreate(TestController::shared().useWaitToDumpWatchdogTimer()));
+ WKRetainPtr<WKBooleanRef> useWaitToDumpWatchdogTimerValue = adoptWK(WKBooleanCreate(TestController::singleton().useWaitToDumpWatchdogTimer()));
WKDictionarySetItem(beginTestMessageBody.get(), useWaitToDumpWatchdogTimerKey.get(), useWaitToDumpWatchdogTimerValue.get());
WKRetainPtr<WKStringRef> timeoutKey = adoptWK(WKStringCreateWithUTF8CString("Timeout"));
WKRetainPtr<WKUInt64Ref> timeoutValue = adoptWK(WKUInt64Create(m_timeout));
WKDictionarySetItem(beginTestMessageBody.get(), timeoutKey.get(), timeoutValue.get());
- WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), beginTestMessageBody.get());
+ WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), beginTestMessageBody.get());
- TestController::shared().runUntil(m_gotInitialResponse, TestController::ShortTimeout);
+ bool shouldOpenExternalURLs = false;
+
+ TestController::singleton().runUntil(m_gotInitialResponse, TestController::shortTimeout);
if (!m_gotInitialResponse) {
m_errorMessage = "Timed out waiting for initial response from web process\n";
m_webProcessIsUnresponsive = true;
@@ -228,41 +155,28 @@ void TestInvocation::invoke()
if (m_error)
goto end;
-#if ENABLE(INSPECTOR) && !PLATFORM(IOS)
- if (shouldOpenWebInspector(m_pathOrURL.c_str()))
- WKInspectorShow(WKPageGetInspector(TestController::shared().mainWebView()->page()));
-#endif // ENABLE(INSPECTOR)
-
- WKPageLoadURL(TestController::shared().mainWebView()->page(), m_url.get());
+ WKPageLoadURLWithShouldOpenExternalURLsPolicy(TestController::singleton().mainWebView()->page(), m_url.get(), shouldOpenExternalURLs);
- if (TestController::shared().useWaitToDumpWatchdogTimer()) {
- if (m_timeout > 0)
- timeoutToUse = TestController::CustomTimeout;
- } else
- timeoutToUse = TestController::NoTimeout;
- TestController::shared().runUntil(m_gotFinalMessage, timeoutToUse);
-
- if (!m_gotFinalMessage) {
- m_errorMessage = "Timed out waiting for final message from web process\n";
- m_webProcessIsUnresponsive = true;
- goto end;
- }
+ TestController::singleton().runUntil(m_gotFinalMessage, TestController::noTimeout);
if (m_error)
goto end;
dumpResults();
end:
-#if ENABLE(INSPECTOR) && !PLATFORM(IOS)
+#if !PLATFORM(IOS)
if (m_gotInitialResponse)
- WKInspectorClose(WKPageGetInspector(TestController::shared().mainWebView()->page()));
-#endif // ENABLE(INSPECTOR)
+ WKInspectorClose(WKPageGetInspector(TestController::singleton().mainWebView()->page()));
+#endif // !PLATFORM(IOS)
if (m_webProcessIsUnresponsive)
dumpWebProcessUnresponsiveness();
- else if (!TestController::shared().resetStateToConsistentValues()) {
- m_errorMessage = "Timed out loading about:blank before the next test";
- dumpWebProcessUnresponsiveness();
+ else if (!TestController::singleton().resetStateToConsistentValues()) {
+ // The process froze while loading about:blank, let's start a fresh one.
+ // It would be nice to report that the previous test froze after dumping results, but we have no way to do that.
+ TestController::singleton().terminateWebContentProcess();
+ // Make sure that we have a process, as invoke() will need one to send bundle messages for the next test.
+ TestController::singleton().reattachPageToWebProcess();
}
}
@@ -273,14 +187,12 @@ void TestInvocation::dumpWebProcessUnresponsiveness()
void TestInvocation::dumpWebProcessUnresponsiveness(const char* errorMessage)
{
- const char* errorMessageToStderr = 0;
-#if PLATFORM(MAC)
- char buffer[64];
- pid_t pid = WKPageGetProcessIdentifier(TestController::shared().mainWebView()->page());
- sprintf(buffer, "#PROCESS UNRESPONSIVE - WebProcess (pid %ld)\n", static_cast<long>(pid));
- errorMessageToStderr = buffer;
+ char errorMessageToStderr[1024];
+#if PLATFORM(COCOA)
+ pid_t pid = WKPageGetProcessIdentifier(TestController::singleton().mainWebView()->page());
+ sprintf(errorMessageToStderr, "#PROCESS UNRESPONSIVE - %s (pid %ld)\n", TestController::webProcessName(), static_cast<long>(pid));
#else
- errorMessageToStderr = "#PROCESS UNRESPONSIVE - WebProcess";
+ sprintf(errorMessageToStderr, "#PROCESS UNRESPONSIVE - %s", TestController::webProcessName());
#endif
dump(errorMessage, errorMessageToStderr, true);
@@ -302,11 +214,17 @@ void TestInvocation::dump(const char* textToStdout, const char* textToStderr, bo
fflush(stderr);
}
-void TestInvocation::forceRepaintDoneCallback(WKErrorRef, void* context)
+void TestInvocation::forceRepaintDoneCallback(WKErrorRef error, void* context)
{
+ // The context may not be valid any more, e.g. if WebKit is invalidating callbacks at process exit.
+ if (error)
+ return;
+
TestInvocation* testInvocation = static_cast<TestInvocation*>(context);
+ RELEASE_ASSERT(TestController::singleton().isCurrentInvocation(testInvocation));
+
testInvocation->m_gotRepaint = true;
- TestController::shared().notifyDone();
+ TestController::singleton().notifyDone();
}
void TestInvocation::dumpResults()
@@ -316,18 +234,22 @@ void TestInvocation::dumpResults()
else
dumpAudio(m_audioResult.get());
- if (m_dumpPixels && m_pixelResult) {
- if (PlatformWebView::windowSnapshotEnabled()) {
+ if (m_dumpPixels) {
+ if (m_pixelResult)
+ dumpPixelsAndCompareWithExpected(m_pixelResult.get(), m_repaintRects.get(), TestInvocation::SnapshotResultType::WebContents);
+ else if (m_pixelResultIsPending) {
m_gotRepaint = false;
- WKPageForceRepaint(TestController::shared().mainWebView()->page(), this, TestInvocation::forceRepaintDoneCallback);
- TestController::shared().runUntil(m_gotRepaint, TestController::ShortTimeout);
+ WKPageForceRepaint(TestController::singleton().mainWebView()->page(), this, TestInvocation::forceRepaintDoneCallback);
+ TestController::singleton().runUntil(m_gotRepaint, TestController::shortTimeout);
if (!m_gotRepaint) {
m_errorMessage = "Timed out waiting for pre-pixel dump repaint\n";
m_webProcessIsUnresponsive = true;
return;
}
+ WKRetainPtr<WKImageRef> windowSnapshot = TestController::singleton().mainWebView()->windowSnapshotImage();
+ ASSERT(windowSnapshot);
+ dumpPixelsAndCompareWithExpected(windowSnapshot.get(), m_repaintRects.get(), TestInvocation::SnapshotResultType::WebView);
}
- dumpPixelsAndCompareWithExpected(m_pixelResult.get(), m_repaintRects.get());
}
fputs("#EOF\n", stdout);
@@ -374,7 +296,7 @@ void TestInvocation::didReceiveMessageFromInjectedBundle(WKStringRef messageName
m_gotFinalMessage = true;
m_error = true;
m_errorMessage = "FAIL\n";
- TestController::shared().notifyDone();
+ TestController::singleton().notifyDone();
return;
}
@@ -383,7 +305,7 @@ void TestInvocation::didReceiveMessageFromInjectedBundle(WKStringRef messageName
WKStringRef messageBodyString = static_cast<WKStringRef>(messageBody);
if (WKStringIsEqualToUTF8CString(messageBodyString, "BeginTest")) {
m_gotInitialResponse = true;
- TestController::shared().notifyDone();
+ TestController::singleton().notifyDone();
return;
}
@@ -394,9 +316,15 @@ void TestInvocation::didReceiveMessageFromInjectedBundle(WKStringRef messageName
ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
- WKRetainPtr<WKStringRef> pixelResultKey = adoptWK(WKStringCreateWithUTF8CString("PixelResult"));
- m_pixelResult = static_cast<WKImageRef>(WKDictionaryGetItemForKey(messageBodyDictionary, pixelResultKey.get()));
- ASSERT(!m_pixelResult || m_dumpPixels);
+ WKRetainPtr<WKStringRef> pixelResultIsPendingKey = adoptWK(WKStringCreateWithUTF8CString("PixelResultIsPending"));
+ WKBooleanRef pixelResultIsPending = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, pixelResultIsPendingKey.get()));
+ m_pixelResultIsPending = WKBooleanGetValue(pixelResultIsPending);
+
+ if (!m_pixelResultIsPending) {
+ WKRetainPtr<WKStringRef> pixelResultKey = adoptWK(WKStringCreateWithUTF8CString("PixelResult"));
+ m_pixelResult = static_cast<WKImageRef>(WKDictionaryGetItemForKey(messageBodyDictionary, pixelResultKey.get()));
+ ASSERT(!m_pixelResult || m_dumpPixels);
+ }
WKRetainPtr<WKStringRef> repaintRectsKey = adoptWK(WKStringCreateWithUTF8CString("RepaintRects"));
m_repaintRects = static_cast<WKArrayRef>(WKDictionaryGetItemForKey(messageBodyDictionary, repaintRectsKey.get()));
@@ -405,7 +333,7 @@ void TestInvocation::didReceiveMessageFromInjectedBundle(WKStringRef messageName
m_audioResult = static_cast<WKDataRef>(WKDictionaryGetItemForKey(messageBodyDictionary, audioResultKey.get()));
m_gotFinalMessage = true;
- TestController::shared().notifyDone();
+ TestController::singleton().notifyDone();
return;
}
@@ -419,52 +347,59 @@ void TestInvocation::didReceiveMessageFromInjectedBundle(WKStringRef messageName
if (WKStringIsEqualToUTF8CString(messageName, "BeforeUnloadReturnValue")) {
ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
WKBooleanRef beforeUnloadReturnValue = static_cast<WKBooleanRef>(messageBody);
- TestController::shared().setBeforeUnloadReturnValue(WKBooleanGetValue(beforeUnloadReturnValue));
+ TestController::singleton().setBeforeUnloadReturnValue(WKBooleanGetValue(beforeUnloadReturnValue));
return;
}
if (WKStringIsEqualToUTF8CString(messageName, "AddChromeInputField")) {
- TestController::shared().mainWebView()->addChromeInputField();
+ TestController::singleton().mainWebView()->addChromeInputField();
WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallAddChromeInputFieldCallback"));
- WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), 0);
+ WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0);
return;
}
if (WKStringIsEqualToUTF8CString(messageName, "RemoveChromeInputField")) {
- TestController::shared().mainWebView()->removeChromeInputField();
+ TestController::singleton().mainWebView()->removeChromeInputField();
WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallRemoveChromeInputFieldCallback"));
- WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), 0);
+ WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0);
return;
}
if (WKStringIsEqualToUTF8CString(messageName, "FocusWebView")) {
- TestController::shared().mainWebView()->makeWebViewFirstResponder();
+ TestController::singleton().mainWebView()->makeWebViewFirstResponder();
WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallFocusWebViewCallback"));
- WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), 0);
+ WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0);
return;
}
if (WKStringIsEqualToUTF8CString(messageName, "SetBackingScaleFactor")) {
ASSERT(WKGetTypeID(messageBody) == WKDoubleGetTypeID());
double backingScaleFactor = WKDoubleGetValue(static_cast<WKDoubleRef>(messageBody));
- WKPageSetCustomBackingScaleFactor(TestController::shared().mainWebView()->page(), backingScaleFactor);
+ WKPageSetCustomBackingScaleFactor(TestController::singleton().mainWebView()->page(), backingScaleFactor);
WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallSetBackingScaleFactorCallback"));
- WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), 0);
+ WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0);
return;
}
if (WKStringIsEqualToUTF8CString(messageName, "SimulateWebNotificationClick")) {
ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID());
uint64_t notificationID = WKUInt64GetValue(static_cast<WKUInt64Ref>(messageBody));
- TestController::shared().simulateWebNotificationClick(notificationID);
+ TestController::singleton().simulateWebNotificationClick(notificationID);
+ return;
+ }
+
+ if (WKStringIsEqualToUTF8CString(messageName, "SetAddsVisitedLinks")) {
+ ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
+ WKBooleanRef enabledWK = static_cast<WKBooleanRef>(messageBody);
+ WKPageSetAddsVisitedLinks(TestController::singleton().mainWebView()->page(), WKBooleanGetValue(enabledWK));
return;
}
if (WKStringIsEqualToUTF8CString(messageName, "SetGeolocationPermission")) {
ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
WKBooleanRef enabledWK = static_cast<WKBooleanRef>(messageBody);
- TestController::shared().setGeolocationPermission(WKBooleanGetValue(enabledWK));
+ TestController::singleton().setGeolocationPermission(WKBooleanGetValue(enabledWK));
return;
}
@@ -516,14 +451,43 @@ void TestInvocation::didReceiveMessageFromInjectedBundle(WKStringRef messageName
WKDoubleRef speedWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, speedKeyWK.get()));
double speed = WKDoubleGetValue(speedWK);
- TestController::shared().setMockGeolocationPosition(latitude, longitude, accuracy, providesAltitude, altitude, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed);
+ TestController::singleton().setMockGeolocationPosition(latitude, longitude, accuracy, providesAltitude, altitude, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed);
return;
}
if (WKStringIsEqualToUTF8CString(messageName, "SetMockGeolocationPositionUnavailableError")) {
ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
WKStringRef errorMessage = static_cast<WKStringRef>(messageBody);
- TestController::shared().setMockGeolocationPositionUnavailableError(errorMessage);
+ TestController::singleton().setMockGeolocationPositionUnavailableError(errorMessage);
+ return;
+ }
+
+ if (WKStringIsEqualToUTF8CString(messageName, "SetUserMediaPermission")) {
+ ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
+ WKBooleanRef enabledWK = static_cast<WKBooleanRef>(messageBody);
+ TestController::singleton().setUserMediaPermission(WKBooleanGetValue(enabledWK));
+ return;
+ }
+
+ if (WKStringIsEqualToUTF8CString(messageName, "SetUserMediaPermissionForOrigin")) {
+ ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
+ WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
+
+ WKRetainPtr<WKStringRef> permissionKeyWK(AdoptWK, WKStringCreateWithUTF8CString("permission"));
+ WKBooleanRef permissionWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, permissionKeyWK.get()));
+ bool permission = WKBooleanGetValue(permissionWK);
+
+ WKRetainPtr<WKStringRef> urlKey(AdoptWK, WKStringCreateWithUTF8CString("url"));
+ WKStringRef urlWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, urlKey.get()));
+
+ TestController::singleton().setUserMediaPermissionForOrigin(permission, urlWK);
+ return;
+ }
+
+ if (WKStringIsEqualToUTF8CString(messageName, "SetCacheModel")) {
+ ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID());
+ uint64_t model = WKUInt64GetValue(static_cast<WKUInt64Ref>(messageBody));
+ WKContextSetCacheModel(TestController::singleton().context(), model);
return;
}
@@ -539,30 +503,26 @@ void TestInvocation::didReceiveMessageFromInjectedBundle(WKStringRef messageName
WKBooleanRef permissiveWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, permissiveKeyWK.get()));
bool permissive = WKBooleanGetValue(permissiveWK);
- TestController::shared().setCustomPolicyDelegate(enabled, permissive);
+ TestController::singleton().setCustomPolicyDelegate(enabled, permissive);
return;
}
- if (WKStringIsEqualToUTF8CString(messageName, "SetVisibilityState")) {
+ if (WKStringIsEqualToUTF8CString(messageName, "SetHidden")) {
ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
- WKRetainPtr<WKStringRef> visibilityStateKeyWK(AdoptWK, WKStringCreateWithUTF8CString("visibilityState"));
- WKUInt64Ref visibilityStateWK = static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, visibilityStateKeyWK.get()));
- WKPageVisibilityState visibilityState = static_cast<WKPageVisibilityState>(WKUInt64GetValue(visibilityStateWK));
-
- WKRetainPtr<WKStringRef> isInitialKeyWK(AdoptWK, WKStringCreateWithUTF8CString("isInitialState"));
- WKBooleanRef isInitialWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, isInitialKeyWK.get()));
- bool isInitialState = WKBooleanGetValue(isInitialWK);
+ WKRetainPtr<WKStringRef> isInitialKeyWK(AdoptWK, WKStringCreateWithUTF8CString("hidden"));
+ WKBooleanRef hiddenWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, isInitialKeyWK.get()));
+ bool hidden = WKBooleanGetValue(hiddenWK);
- TestController::shared().setVisibilityState(visibilityState, isInitialState);
+ TestController::singleton().setHidden(hidden);
return;
}
if (WKStringIsEqualToUTF8CString(messageName, "ProcessWorkQueue")) {
- if (TestController::shared().workQueueManager().processWorkQueue()) {
+ if (TestController::singleton().workQueueManager().processWorkQueue()) {
WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("WorkQueueProcessedCallback"));
- WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), 0);
+ WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0);
}
return;
}
@@ -570,14 +530,14 @@ void TestInvocation::didReceiveMessageFromInjectedBundle(WKStringRef messageName
if (WKStringIsEqualToUTF8CString(messageName, "QueueBackNavigation")) {
ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID());
uint64_t stepCount = WKUInt64GetValue(static_cast<WKUInt64Ref>(messageBody));
- TestController::shared().workQueueManager().queueBackNavigation(stepCount);
+ TestController::singleton().workQueueManager().queueBackNavigation(stepCount);
return;
}
if (WKStringIsEqualToUTF8CString(messageName, "QueueForwardNavigation")) {
ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID());
uint64_t stepCount = WKUInt64GetValue(static_cast<WKUInt64Ref>(messageBody));
- TestController::shared().workQueueManager().queueForwardNavigation(stepCount);
+ TestController::singleton().workQueueManager().queueForwardNavigation(stepCount);
return;
}
@@ -591,7 +551,10 @@ void TestInvocation::didReceiveMessageFromInjectedBundle(WKStringRef messageName
WKRetainPtr<WKStringRef> targetKey(AdoptWK, WKStringCreateWithUTF8CString("target"));
WKStringRef targetWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(loadDataDictionary, targetKey.get()));
- TestController::shared().workQueueManager().queueLoad(toWTFString(urlWK), toWTFString(targetWK));
+ WKRetainPtr<WKStringRef> shouldOpenExternalURLsKey(AdoptWK, WKStringCreateWithUTF8CString("shouldOpenExternalURLs"));
+ WKBooleanRef shouldOpenExternalURLsValueWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(loadDataDictionary, shouldOpenExternalURLsKey.get()));
+
+ TestController::singleton().workQueueManager().queueLoad(toWTFString(urlWK), toWTFString(targetWK), WKBooleanGetValue(shouldOpenExternalURLsValueWK));
return;
}
@@ -608,54 +571,82 @@ void TestInvocation::didReceiveMessageFromInjectedBundle(WKStringRef messageName
WKRetainPtr<WKStringRef> unreachableURLKey(AdoptWK, WKStringCreateWithUTF8CString("unreachableURL"));
WKStringRef unreachableURLWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(loadDataDictionary, unreachableURLKey.get()));
- TestController::shared().workQueueManager().queueLoadHTMLString(toWTFString(contentWK), baseURLWK ? toWTFString(baseURLWK) : String(), unreachableURLWK ? toWTFString(unreachableURLWK) : String());
+ TestController::singleton().workQueueManager().queueLoadHTMLString(toWTFString(contentWK), baseURLWK ? toWTFString(baseURLWK) : String(), unreachableURLWK ? toWTFString(unreachableURLWK) : String());
return;
}
if (WKStringIsEqualToUTF8CString(messageName, "QueueReload")) {
- TestController::shared().workQueueManager().queueReload();
+ TestController::singleton().workQueueManager().queueReload();
return;
}
if (WKStringIsEqualToUTF8CString(messageName, "QueueLoadingScript")) {
ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
WKStringRef script = static_cast<WKStringRef>(messageBody);
- TestController::shared().workQueueManager().queueLoadingScript(toWTFString(script));
+ TestController::singleton().workQueueManager().queueLoadingScript(toWTFString(script));
return;
}
if (WKStringIsEqualToUTF8CString(messageName, "QueueNonLoadingScript")) {
ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
WKStringRef script = static_cast<WKStringRef>(messageBody);
- TestController::shared().workQueueManager().queueNonLoadingScript(toWTFString(script));
+ TestController::singleton().workQueueManager().queueNonLoadingScript(toWTFString(script));
return;
}
if (WKStringIsEqualToUTF8CString(messageName, "SetHandlesAuthenticationChallenge")) {
ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
WKBooleanRef value = static_cast<WKBooleanRef>(messageBody);
- TestController::shared().setHandlesAuthenticationChallenges(WKBooleanGetValue(value));
+ TestController::singleton().setHandlesAuthenticationChallenges(WKBooleanGetValue(value));
return;
}
if (WKStringIsEqualToUTF8CString(messageName, "SetAuthenticationUsername")) {
ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
WKStringRef username = static_cast<WKStringRef>(messageBody);
- TestController::shared().setAuthenticationUsername(toWTFString(username));
+ TestController::singleton().setAuthenticationUsername(toWTFString(username));
return;
}
if (WKStringIsEqualToUTF8CString(messageName, "SetAuthenticationPassword")) {
ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
WKStringRef password = static_cast<WKStringRef>(messageBody);
- TestController::shared().setAuthenticationPassword(toWTFString(password));
+ TestController::singleton().setAuthenticationPassword(toWTFString(password));
return;
}
if (WKStringIsEqualToUTF8CString(messageName, "SetBlockAllPlugins")) {
ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
WKBooleanRef shouldBlock = static_cast<WKBooleanRef>(messageBody);
- TestController::shared().setBlockAllPlugins(WKBooleanGetValue(shouldBlock));
+ TestController::singleton().setBlockAllPlugins(WKBooleanGetValue(shouldBlock));
+ return;
+ }
+
+ if (WKStringIsEqualToUTF8CString(messageName, "SetShouldDecideNavigationPolicyAfterDelay")) {
+ ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
+ WKBooleanRef value = static_cast<WKBooleanRef>(messageBody);
+ TestController::singleton().setShouldDecideNavigationPolicyAfterDelay(WKBooleanGetValue(value));
+ return;
+ }
+
+ if (WKStringIsEqualToUTF8CString(messageName, "SetNavigationGesturesEnabled")) {
+ ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
+ WKBooleanRef value = static_cast<WKBooleanRef>(messageBody);
+ TestController::singleton().setNavigationGesturesEnabled(WKBooleanGetValue(value));
+ return;
+ }
+
+ if (WKStringIsEqualToUTF8CString(messageName, "RunUIProcessScript")) {
+ WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
+ WKRetainPtr<WKStringRef> scriptKey(AdoptWK, WKStringCreateWithUTF8CString("Script"));
+ WKRetainPtr<WKStringRef> callbackIDKey(AdoptWK, WKStringCreateWithUTF8CString("CallbackID"));
+
+ UIScriptInvocationData* invocationData = new UIScriptInvocationData();
+ invocationData->testInvocation = this;
+ invocationData->callbackID = (unsigned)WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, callbackIDKey.get())));
+ invocationData->scriptString = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, scriptKey.get()));
+ m_pendingUIScriptInvocationData = invocationData;
+ WKPageCallAfterNextPresentationUpdate(TestController::singleton().mainWebView()->page(), invocationData, runUISideScriptAfterUpdateCallback);
return;
}
@@ -667,12 +658,18 @@ WKRetainPtr<WKTypeRef> TestInvocation::didReceiveSynchronousMessageFromInjectedB
if (WKStringIsEqualToUTF8CString(messageName, "SetWindowIsKey")) {
ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
WKBooleanRef isKeyValue = static_cast<WKBooleanRef>(messageBody);
- TestController::shared().mainWebView()->setWindowIsKey(WKBooleanGetValue(isKeyValue));
- return 0;
+ TestController::singleton().mainWebView()->setWindowIsKey(WKBooleanGetValue(isKeyValue));
+ return nullptr;
+ }
+
+ if (WKStringIsEqualToUTF8CString(messageName, "IsGeolocationClientActive")) {
+ bool isActive = TestController::singleton().isGeolocationProviderActive();
+ WKRetainPtr<WKTypeRef> result(AdoptWK, WKBooleanCreate(isActive));
+ return result;
}
if (WKStringIsEqualToUTF8CString(messageName, "IsWorkQueueEmpty")) {
- bool isEmpty = TestController::shared().workQueueManager().isWorkQueueEmpty();
+ bool isEmpty = TestController::singleton().workQueueManager().isWorkQueueEmpty();
WKRetainPtr<WKTypeRef> result(AdoptWK, WKBooleanCreate(isEmpty));
return result;
}
@@ -685,8 +682,52 @@ WKRetainPtr<WKTypeRef> TestInvocation::didReceiveSynchronousMessageFromInjectedB
#endif
return result;
}
+
+ if (WKStringIsEqualToUTF8CString(messageName, "SetAlwaysAcceptCookies")) {
+ WKBooleanRef accept = static_cast<WKBooleanRef>(messageBody);
+ WKHTTPCookieAcceptPolicy policy = WKBooleanGetValue(accept) ? kWKHTTPCookieAcceptPolicyAlways : kWKHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain;
+ // FIXME: This updates the policy in WebProcess and in NetworkProcess asynchronously, which might break some tests' expectations.
+ WKCookieManagerSetHTTPCookieAcceptPolicy(WKContextGetCookieManager(TestController::singleton().context()), policy);
+ return nullptr;
+ }
+
ASSERT_NOT_REACHED();
- return 0;
+ return nullptr;
+}
+
+void TestInvocation::runUISideScriptAfterUpdateCallback(WKErrorRef, void* context)
+{
+ UIScriptInvocationData* data = static_cast<UIScriptInvocationData*>(context);
+ if (TestInvocation* invocation = data->testInvocation) {
+ RELEASE_ASSERT(TestController::singleton().isCurrentInvocation(invocation));
+ invocation->runUISideScript(data->scriptString.get(), data->callbackID);
+ }
+ delete data;
+}
+
+void TestInvocation::runUISideScript(WKStringRef script, unsigned scriptCallbackID)
+{
+ m_pendingUIScriptInvocationData = nullptr;
+
+ if (!m_UIScriptContext)
+ m_UIScriptContext = std::make_unique<UIScriptContext>(*this);
+
+ m_UIScriptContext->runUIScript(script, scriptCallbackID);
+}
+
+void TestInvocation::uiScriptDidComplete(WKStringRef result, unsigned scriptCallbackID)
+{
+ WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallUISideScriptCallback"));
+
+ WKRetainPtr<WKMutableDictionaryRef> messageBody(AdoptWK, WKMutableDictionaryCreate());
+ WKRetainPtr<WKStringRef> resultKey(AdoptWK, WKStringCreateWithUTF8CString("Result"));
+ WKRetainPtr<WKStringRef> callbackIDKey(AdoptWK, WKStringCreateWithUTF8CString("CallbackID"));
+ WKRetainPtr<WKUInt64Ref> callbackIDValue = adoptWK(WKUInt64Create(scriptCallbackID));
+
+ WKDictionarySetItem(messageBody.get(), resultKey.get(), result);
+ WKDictionarySetItem(messageBody.get(), callbackIDKey.get(), callbackIDValue.get());
+
+ WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), messageBody.get());
}
void TestInvocation::outputText(const WTF::String& text)
@@ -694,4 +735,28 @@ void TestInvocation::outputText(const WTF::String& text)
m_textOutput.append(text);
}
+void TestInvocation::didBeginSwipe()
+{
+ WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallDidBeginSwipeCallback"));
+ WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0);
+}
+
+void TestInvocation::willEndSwipe()
+{
+ WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallWillEndSwipeCallback"));
+ WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0);
+}
+
+void TestInvocation::didEndSwipe()
+{
+ WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallDidEndSwipeCallback"));
+ WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0);
+}
+
+void TestInvocation::didRemoveSwipeSnapshot()
+{
+ WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallDidRemoveSwipeSnapshotCallback"));
+ WKPagePostMessageToInjectedBundle(TestController::singleton().mainWebView()->page(), messageName.get(), 0);
+}
+
} // namespace WTR
diff --git a/Tools/WebKitTestRunner/TestInvocation.h b/Tools/WebKitTestRunner/TestInvocation.h
index a32678135..ac9c8adb6 100644
--- a/Tools/WebKitTestRunner/TestInvocation.h
+++ b/Tools/WebKitTestRunner/TestInvocation.h
@@ -26,23 +26,31 @@
#ifndef TestInvocation_h
#define TestInvocation_h
+#include "JSWrappable.h"
+#include "TestOptions.h"
+#include "UIScriptContext.h"
+#include <WebKit/WKRetainPtr.h>
#include <string>
-#include <WebKit2/WKRetainPtr.h>
#include <wtf/Noncopyable.h>
-#include <wtf/OwnPtr.h>
#include <wtf/text/StringBuilder.h>
namespace WTR {
-class TestInvocation {
+class TestInvocation : public UIScriptContextDelegate {
WTF_MAKE_NONCOPYABLE(TestInvocation);
public:
- explicit TestInvocation(const std::string& pathOrURL);
+ explicit TestInvocation(WKURLRef, const TestOptions&);
~TestInvocation();
+ WKURLRef url() const;
+ bool urlContains(const char*) const;
+
+ const TestOptions& options() const { return m_options; }
+
void setIsPixelTest(const std::string& expectedPixelHash);
- void setCustomTimeout(int duration);
+ void setCustomTimeout(int duration) { m_timeout = duration; }
+ int customTimeout() const { return m_timeout; }
void invoke();
void didReceiveMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody);
@@ -51,36 +59,63 @@ public:
void dumpWebProcessUnresponsiveness();
static void dumpWebProcessUnresponsiveness(const char* errorMessage);
void outputText(const WTF::String&);
+
+ void didBeginSwipe();
+ void willEndSwipe();
+ void didEndSwipe();
+ void didRemoveSwipeSnapshot();
+
private:
void dumpResults();
static void dump(const char* textToStdout, const char* textToStderr = 0, bool seenError = false);
- void dumpPixelsAndCompareWithExpected(WKImageRef, WKArrayRef repaintRects);
+ enum class SnapshotResultType { WebView, WebContents };
+ void dumpPixelsAndCompareWithExpected(WKImageRef, WKArrayRef repaintRects, SnapshotResultType);
void dumpAudio(WKDataRef);
bool compareActualHashToExpectedAndDumpResults(const char[33]);
static void forceRepaintDoneCallback(WKErrorRef, void* context);
+
+ struct UIScriptInvocationData {
+ unsigned callbackID;
+ WebKit::WKRetainPtr<WKStringRef> scriptString;
+ TestInvocation* testInvocation;
+ };
+ static void runUISideScriptAfterUpdateCallback(WKErrorRef, void* context);
- WKRetainPtr<WKURLRef> m_url;
- std::string m_pathOrURL;
+ bool shouldLogFrameLoadDelegates() const;
+ bool shouldLogHistoryClientCallbacks() const;
+
+ void runUISideScript(WKStringRef, unsigned callbackID);
+ // UIScriptContextDelegate
+ void uiScriptDidComplete(WKStringRef result, unsigned callbackID) override;
+
+ const TestOptions m_options;
- bool m_dumpPixels;
+ WKRetainPtr<WKURLRef> m_url;
+ WTF::String m_urlString;
+
std::string m_expectedPixelHash;
- int m_timeout;
+ int m_timeout { 0 };
// Invocation state
- bool m_gotInitialResponse;
- bool m_gotFinalMessage;
- bool m_gotRepaint;
- bool m_error;
+ bool m_gotInitialResponse { false };
+ bool m_gotFinalMessage { false };
+ bool m_gotRepaint { false };
+ bool m_error { false };
+
+ bool m_dumpPixels { false };
+ bool m_pixelResultIsPending { false };
+ bool m_webProcessIsUnresponsive { false };
StringBuilder m_textOutput;
WKRetainPtr<WKDataRef> m_audioResult;
WKRetainPtr<WKImageRef> m_pixelResult;
WKRetainPtr<WKArrayRef> m_repaintRects;
std::string m_errorMessage;
- bool m_webProcessIsUnresponsive;
-
+
+ std::unique_ptr<UIScriptContext> m_UIScriptContext;
+ UIScriptInvocationData* m_pendingUIScriptInvocationData { nullptr };
};
} // namespace WTR
diff --git a/Tools/WebKitTestRunner/TestOptions.cpp b/Tools/WebKitTestRunner/TestOptions.cpp
new file mode 100644
index 000000000..453e077cf
--- /dev/null
+++ b/Tools/WebKitTestRunner/TestOptions.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "config.h"
+#include "TestOptions.h"
+
+#include <string>
+#include <wtf/text/WTFString.h>
+
+namespace WTR {
+
+static bool pathContains(const std::string& pathOrURL, const char* substring)
+{
+ String path(pathOrURL.c_str());
+ return path.contains(substring); // Case-insensitive.
+}
+
+static bool shouldMakeViewportFlexible(const std::string& pathOrURL)
+{
+ return pathContains(pathOrURL, "viewport/");
+}
+
+static bool shouldUseFixedLayout(const std::string& pathOrURL)
+{
+#if ENABLE(CSS_DEVICE_ADAPTATION)
+ if (pathContains(pathOrURL, "device-adapt/") || pathContains(pathOrURL, "device-adapt\\"))
+ return true;
+#endif
+ return false;
+}
+
+static bool isSVGTestPath(const std::string& pathOrURL)
+{
+ return pathContains(pathOrURL, "svg/W3C-SVG-1.1") || pathContains(pathOrURL, "svg\\W3C-SVG-1.1");
+}
+
+static bool isHiDPITestPath(const std::string& pathOrURL)
+{
+ return pathContains(pathOrURL, "/hidpi-");
+}
+
+TestOptions::TestOptions(const std::string& pathOrURL)
+ : useFlexibleViewport(shouldMakeViewportFlexible(pathOrURL))
+ , useFixedLayout(shouldUseFixedLayout(pathOrURL))
+ , isSVGTest(isSVGTestPath(pathOrURL))
+ , isHiDPITest(isHiDPITestPath(pathOrURL))
+{
+}
+
+}
diff --git a/Tools/WebKitTestRunner/TestOptions.h b/Tools/WebKitTestRunner/TestOptions.h
new file mode 100644
index 000000000..c26742fa3
--- /dev/null
+++ b/Tools/WebKitTestRunner/TestOptions.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef TestOptions_h
+#define TestOptions_h
+
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+namespace WTR {
+
+struct TestOptions {
+ bool useThreadedScrolling { false };
+ bool useRemoteLayerTree { false };
+ bool shouldShowWebView { false };
+ bool useFlexibleViewport { false };
+ bool useFixedLayout { false };
+ bool isSVGTest { false };
+ bool isHiDPITest { false };
+ bool useDataDetection { false };
+
+ Vector<String> overrideLanguages;
+
+ TestOptions(const std::string& pathOrURL);
+};
+
+}
+
+#endif // TestOptions_h
diff --git a/Tools/WebKitTestRunner/UIScriptContext/Bindings/UIScriptController.idl b/Tools/WebKitTestRunner/UIScriptContext/Bindings/UIScriptController.idl
new file mode 100644
index 000000000..53e9c8a5e
--- /dev/null
+++ b/Tools/WebKitTestRunner/UIScriptContext/Bindings/UIScriptController.idl
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 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 UIScriptController {
+
+ void doAsyncTask(object callback); // Used to test the harness.
+
+ void zoomToScale(double scale, object callback);
+
+ // Interaction.
+ // These functions post events asynchronously. The callback is fired when the events have been dispatched, but any
+ // resulting behavior may also be asynchronous.
+ void touchDownAtPoint(long x, long y, long touchCount, object callback);
+ void liftUpAtPoint(long x, long y, long touchCount, object callback);
+ void singleTapAtPoint(long x, long y, object callback);
+ void doubleTapAtPoint(long x, long y, object callback);
+
+ void typeCharacterUsingHardwareKeyboard(DOMString character, object callback);
+ void keyDownUsingHardwareKeyboard(DOMString character, object callback);
+ void keyUpUsingHardwareKeyboard(DOMString character, object callback);
+
+ attribute object didShowKeyboardCallback;
+ attribute object didHideKeyboardCallback;
+
+ attribute object willBeginZoomingCallback;
+ attribute object didEndZoomingCallback;
+
+ attribute object didEndScrollingCallback;
+
+ // View state
+ readonly attribute double zoomScale;
+ readonly attribute double minimumZoomScale;
+ readonly attribute double maximumZoomScale;
+
+ readonly attribute object contentVisibleRect; // Returned object has 'left', 'top', 'width', 'height' properties.
+
+ void uiScriptComplete(DOMString result);
+};
diff --git a/Tools/WebKitTestRunner/UIScriptContext/UIScriptContext.cpp b/Tools/WebKitTestRunner/UIScriptContext/UIScriptContext.cpp
new file mode 100644
index 000000000..4d8a8c0b4
--- /dev/null
+++ b/Tools/WebKitTestRunner/UIScriptContext/UIScriptContext.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "config.h"
+#include "UIScriptContext.h"
+
+#include "StringFunctions.h"
+#include "UIScriptController.h"
+#include <JavaScriptCore/JSContextRef.h>
+#include <JavaScriptCore/JSValueRef.h>
+#include <WebKit/WKRetainPtr.h>
+#include <WebKit/WKString.h>
+#include <WebKit/WKStringPrivate.h>
+
+using namespace WTR;
+
+static inline bool isPersistentCallbackID(unsigned callbackID)
+{
+ return callbackID < firstNonPersistentCallbackID;
+}
+
+UIScriptContext::UIScriptContext(UIScriptContextDelegate& delegate)
+ : m_context(Adopt, JSGlobalContextCreate(nullptr))
+ , m_delegate(delegate)
+{
+ m_controller = UIScriptController::create(*this);
+
+ JSObjectRef globalObject = JSContextGetGlobalObject(m_context.get());
+
+ JSValueRef exception = nullptr;
+ m_controller->makeWindowObject(m_context.get(), globalObject, &exception);
+}
+
+UIScriptContext::~UIScriptContext()
+{
+ m_controller->contextDestroyed();
+}
+
+void UIScriptContext::runUIScript(WKStringRef script, unsigned scriptCallbackID)
+{
+ m_currentScriptCallbackID = scriptCallbackID;
+
+ auto scriptRef = toJS(script);
+
+ JSValueRef exception = nullptr;
+ JSValueRef result = JSEvaluateScript(m_context.get(), scriptRef.get(), 0, 0, 1, &exception);
+
+ if (!hasOutstandingAsyncTasks()) {
+ JSValueRef stringifyException = nullptr;
+ requestUIScriptCompletion(JSValueToStringCopy(m_context.get(), result, &stringifyException));
+ tryToCompleteUIScriptForCurrentParentCallback();
+ }
+}
+
+unsigned UIScriptContext::nextTaskCallbackID(CallbackType type)
+{
+ if (type == CallbackTypeNonPersistent)
+ return ++m_nextTaskCallbackID + firstNonPersistentCallbackID;
+
+ return type;
+}
+
+unsigned UIScriptContext::prepareForAsyncTask(JSValueRef callback, CallbackType type)
+{
+ unsigned callbackID = nextTaskCallbackID(type);
+
+ JSValueProtect(m_context.get(), callback);
+ Task task;
+ task.parentScriptCallbackID = m_currentScriptCallbackID;
+ task.callback = callback;
+
+ ASSERT(!m_callbacks.contains(callbackID));
+ m_callbacks.add(callbackID, task);
+
+ return callbackID;
+}
+
+void UIScriptContext::asyncTaskComplete(unsigned callbackID)
+{
+ Task task = m_callbacks.take(callbackID);
+ ASSERT(task.callback);
+
+ JSValueRef exception = nullptr;
+ JSObjectRef callbackObject = JSValueToObject(m_context.get(), task.callback, &exception);
+
+ m_currentScriptCallbackID = task.parentScriptCallbackID;
+
+ exception = nullptr;
+ JSObjectCallAsFunction(m_context.get(), callbackObject, JSContextGetGlobalObject(m_context.get()), 0, nullptr, &exception);
+ JSValueUnprotect(m_context.get(), task.callback);
+
+ tryToCompleteUIScriptForCurrentParentCallback();
+ m_currentScriptCallbackID = 0;
+}
+
+unsigned UIScriptContext::registerCallback(JSValueRef taskCallback, CallbackType type)
+{
+ if (m_callbacks.contains(type))
+ unregisterCallback(type);
+
+ return prepareForAsyncTask(taskCallback, type);
+}
+
+void UIScriptContext::unregisterCallback(unsigned callbackID)
+{
+ Task task = m_callbacks.take(callbackID);
+ ASSERT(task.callback);
+ JSValueUnprotect(m_context.get(), task.callback);
+}
+
+JSValueRef UIScriptContext::callbackWithID(unsigned callbackID)
+{
+ Task task = m_callbacks.get(callbackID);
+ return task.callback;
+}
+
+void UIScriptContext::fireCallback(unsigned callbackID)
+{
+ Task task = m_callbacks.get(callbackID);
+ ASSERT(task.callback);
+
+ JSValueRef exception = nullptr;
+ JSObjectRef callbackObject = JSValueToObject(m_context.get(), task.callback, &exception);
+
+ m_currentScriptCallbackID = task.parentScriptCallbackID;
+
+ exception = nullptr;
+ JSObjectCallAsFunction(m_context.get(), callbackObject, JSContextGetGlobalObject(m_context.get()), 0, nullptr, &exception);
+
+ tryToCompleteUIScriptForCurrentParentCallback();
+ m_currentScriptCallbackID = 0;
+}
+
+void UIScriptContext::requestUIScriptCompletion(JSStringRef result)
+{
+ ASSERT(m_currentScriptCallbackID);
+ if (currentParentCallbackIsPendingCompletion())
+ return;
+
+ // This request for the UI script to complete is not fulfilled until the last non-persistent task for the parent callback is finished.
+ m_uiScriptResultsPendingCompletion.add(m_currentScriptCallbackID, result ? JSStringRetain(result) : nullptr);
+}
+
+void UIScriptContext::tryToCompleteUIScriptForCurrentParentCallback()
+{
+ if (!currentParentCallbackIsPendingCompletion() || currentParentCallbackHasOutstandingAsyncTasks())
+ return;
+
+ JSStringRef result = m_uiScriptResultsPendingCompletion.take(m_currentScriptCallbackID);
+ WKRetainPtr<WKStringRef> uiScriptResult = adoptWK(WKStringCreateWithJSString(result));
+ m_delegate.uiScriptDidComplete(uiScriptResult.get(), m_currentScriptCallbackID);
+ m_currentScriptCallbackID = 0;
+ if (result)
+ JSStringRelease(result);
+}
+
+JSObjectRef UIScriptContext::objectFromRect(const WKRect& rect) const
+{
+ JSObjectRef object = JSObjectMake(m_context.get(), nullptr, nullptr);
+
+ JSObjectSetProperty(m_context.get(), object, adopt(JSStringCreateWithUTF8CString("left")).get(), JSValueMakeNumber(m_context.get(), rect.origin.x), kJSPropertyAttributeNone, nullptr);
+ JSObjectSetProperty(m_context.get(), object, adopt(JSStringCreateWithUTF8CString("top")).get(), JSValueMakeNumber(m_context.get(), rect.origin.y), kJSPropertyAttributeNone, nullptr);
+ JSObjectSetProperty(m_context.get(), object, adopt(JSStringCreateWithUTF8CString("width")).get(), JSValueMakeNumber(m_context.get(), rect.size.width), kJSPropertyAttributeNone, nullptr);
+ JSObjectSetProperty(m_context.get(), object, adopt(JSStringCreateWithUTF8CString("height")).get(), JSValueMakeNumber(m_context.get(), rect.size.height), kJSPropertyAttributeNone, nullptr);
+
+ return object;
+}
+
+bool UIScriptContext::currentParentCallbackHasOutstandingAsyncTasks() const
+{
+ for (auto entry : m_callbacks) {
+ unsigned callbackID = entry.key;
+ Task task = entry.value;
+ if (task.parentScriptCallbackID == m_currentScriptCallbackID && !isPersistentCallbackID(callbackID))
+ return true;
+ }
+
+ return false;
+}
+
diff --git a/Tools/WebKitTestRunner/UIScriptContext/UIScriptContext.h b/Tools/WebKitTestRunner/UIScriptContext/UIScriptContext.h
new file mode 100644
index 000000000..b17c696c0
--- /dev/null
+++ b/Tools/WebKitTestRunner/UIScriptContext/UIScriptContext.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef UIScriptContext_h
+#define UIScriptContext_h
+
+#include <JavaScriptCore/JSRetainPtr.h>
+#include <wtf/HashMap.h>
+#include <wtf/RefPtr.h>
+
+namespace WTR {
+
+class UIScriptController;
+
+class UIScriptContextDelegate {
+public:
+ virtual void uiScriptDidComplete(WKStringRef result, unsigned callbackID) = 0;
+};
+
+const unsigned firstNonPersistentCallbackID = 1000;
+
+typedef enum {
+ CallbackTypeWillBeginZooming = 0,
+ CallbackTypeDidEndZooming,
+ CallbackTypeDidShowKeyboard,
+ CallbackTypeDidHideKeyboard,
+ CallbackTypeDidEndScrolling,
+ CallbackTypeNonPersistent = firstNonPersistentCallbackID
+} CallbackType;
+
+class UIScriptContext {
+ WTF_MAKE_NONCOPYABLE(UIScriptContext);
+public:
+ UIScriptContext(UIScriptContextDelegate&);
+ ~UIScriptContext();
+
+ void runUIScript(WKStringRef script, unsigned scriptCallbackID);
+ void requestUIScriptCompletion(JSStringRef);
+
+ // For one-shot tasks callbacks.
+ unsigned prepareForAsyncTask(JSValueRef taskCallback, CallbackType);
+ void asyncTaskComplete(unsigned taskCallbackID);
+
+ // For persistent callbacks.
+ unsigned registerCallback(JSValueRef taskCallback, CallbackType);
+ JSValueRef callbackWithID(unsigned callbackID);
+ void unregisterCallback(unsigned callbackID);
+ void fireCallback(unsigned callbackID);
+
+ unsigned nextTaskCallbackID(CallbackType);
+
+ JSObjectRef objectFromRect(const WKRect&) const;
+
+private:
+ JSRetainPtr<JSGlobalContextRef> m_context;
+
+ bool hasOutstandingAsyncTasks() const { return !m_callbacks.isEmpty(); }
+ bool currentParentCallbackIsPendingCompletion() const { return m_uiScriptResultsPendingCompletion.contains(m_currentScriptCallbackID); }
+ bool currentParentCallbackHasOutstandingAsyncTasks() const;
+ void tryToCompleteUIScriptForCurrentParentCallback();
+
+ struct Task {
+ unsigned parentScriptCallbackID { 0 };
+ JSValueRef callback { nullptr };
+ };
+ HashMap<unsigned, Task> m_callbacks;
+ HashMap<unsigned, JSStringRef> m_uiScriptResultsPendingCompletion;
+
+ UIScriptContextDelegate& m_delegate;
+ RefPtr<UIScriptController> m_controller;
+
+ unsigned m_currentScriptCallbackID { 0 };
+ unsigned m_nextTaskCallbackID { 0 };
+};
+
+}
+
+#endif // UIScriptContext_h
diff --git a/Tools/WebKitTestRunner/UIScriptContext/UIScriptController.cpp b/Tools/WebKitTestRunner/UIScriptContext/UIScriptController.cpp
new file mode 100644
index 000000000..658240282
--- /dev/null
+++ b/Tools/WebKitTestRunner/UIScriptContext/UIScriptController.cpp
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "config.h"
+#include "UIScriptController.h"
+
+#include "JSUIScriptController.h"
+#include "UIScriptContext.h"
+#include <JavaScriptCore/JSValueRef.h>
+
+namespace WTR {
+
+UIScriptController::UIScriptController(UIScriptContext& context)
+ : m_context(&context)
+{
+}
+
+void UIScriptController::contextDestroyed()
+{
+ m_context = nullptr;
+}
+
+void UIScriptController::makeWindowObject(JSContextRef context, JSObjectRef windowObject, JSValueRef* exception)
+{
+ setProperty(context, windowObject, "uiController", this, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, exception);
+}
+
+JSClassRef UIScriptController::wrapperClass()
+{
+ return JSUIScriptController::uIScriptControllerClass();
+}
+
+#if !PLATFORM(COCOA)
+void UIScriptController::doAsyncTask(JSValueRef)
+{
+}
+#endif
+
+void UIScriptController::setWillBeginZoomingCallback(JSValueRef callback)
+{
+ m_context->registerCallback(callback, CallbackTypeWillBeginZooming);
+ platformSetWillBeginZoomingCallback();
+}
+
+JSValueRef UIScriptController::willBeginZoomingCallback() const
+{
+ return m_context->callbackWithID(CallbackTypeWillBeginZooming);
+}
+
+void UIScriptController::setDidEndZoomingCallback(JSValueRef callback)
+{
+ m_context->registerCallback(callback, CallbackTypeDidEndZooming);
+ platformSetDidEndZoomingCallback();
+}
+
+JSValueRef UIScriptController::didEndZoomingCallback() const
+{
+ return m_context->callbackWithID(CallbackTypeDidEndZooming);
+}
+
+void UIScriptController::setDidEndScrollingCallback(JSValueRef callback)
+{
+ m_context->registerCallback(callback, CallbackTypeDidEndScrolling);
+ platformSetDidEndScrollingCallback();
+}
+
+JSValueRef UIScriptController::didEndScrollingCallback() const
+{
+ return m_context->callbackWithID(CallbackTypeDidEndScrolling);
+}
+
+void UIScriptController::setDidShowKeyboardCallback(JSValueRef callback)
+{
+ m_context->registerCallback(callback, CallbackTypeDidShowKeyboard);
+ platformSetDidShowKeyboardCallback();
+}
+
+JSValueRef UIScriptController::didShowKeyboardCallback() const
+{
+ return m_context->callbackWithID(CallbackTypeDidShowKeyboard);
+}
+
+void UIScriptController::setDidHideKeyboardCallback(JSValueRef callback)
+{
+ m_context->registerCallback(callback, CallbackTypeDidHideKeyboard);
+ platformSetDidHideKeyboardCallback();
+}
+
+JSValueRef UIScriptController::didHideKeyboardCallback() const
+{
+ return m_context->callbackWithID(CallbackTypeDidHideKeyboard);
+}
+
+#if !PLATFORM(IOS)
+void UIScriptController::zoomToScale(double, JSValueRef)
+{
+}
+
+void UIScriptController::touchDownAtPoint(long x, long y, long touchCount, JSValueRef)
+{
+}
+
+void UIScriptController::liftUpAtPoint(long x, long y, long touchCount, JSValueRef)
+{
+}
+
+void UIScriptController::singleTapAtPoint(long x, long y, JSValueRef)
+{
+}
+
+void UIScriptController::doubleTapAtPoint(long x, long y, JSValueRef)
+{
+}
+
+void UIScriptController::typeCharacterUsingHardwareKeyboard(JSStringRef, JSValueRef)
+{
+}
+
+void UIScriptController::keyUpUsingHardwareKeyboard(JSStringRef, JSValueRef)
+{
+}
+
+void UIScriptController::keyDownUsingHardwareKeyboard(JSStringRef, JSValueRef)
+{
+}
+
+double UIScriptController::zoomScale() const
+{
+ return 1;
+}
+
+double UIScriptController::minimumZoomScale() const
+{
+ return 1;
+}
+
+double UIScriptController::maximumZoomScale() const
+{
+ return 1;
+}
+
+JSObjectRef UIScriptController::contentVisibleRect() const
+{
+ return nullptr;
+}
+
+void UIScriptController::platformSetWillBeginZoomingCallback()
+{
+}
+
+void UIScriptController::platformSetDidEndZoomingCallback()
+{
+}
+
+void UIScriptController::platformSetDidEndScrollingCallback()
+{
+}
+
+void UIScriptController::platformSetDidShowKeyboardCallback()
+{
+}
+
+void UIScriptController::platformSetDidHideKeyboardCallback()
+{
+}
+
+void UIScriptController::platformClearAllCallbacks()
+{
+}
+#endif
+
+void UIScriptController::uiScriptComplete(JSStringRef result)
+{
+ m_context->requestUIScriptCompletion(result);
+ platformClearAllCallbacks();
+}
+
+}
diff --git a/Tools/WebKitTestRunner/UIScriptContext/UIScriptController.h b/Tools/WebKitTestRunner/UIScriptContext/UIScriptController.h
new file mode 100644
index 000000000..8acef607f
--- /dev/null
+++ b/Tools/WebKitTestRunner/UIScriptContext/UIScriptController.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef UIScriptController_h
+#define UIScriptController_h
+
+#include "JSWrappable.h"
+#include <wtf/Ref.h>
+
+namespace WTR {
+
+class UIScriptContext;
+
+class UIScriptController : public JSWrappable {
+public:
+ static Ref<UIScriptController> create(UIScriptContext& context)
+ {
+ return adoptRef(*new UIScriptController(context));
+ }
+
+ void contextDestroyed();
+
+ void makeWindowObject(JSContextRef, JSObjectRef windowObject, JSValueRef* exception);
+
+ void doAsyncTask(JSValueRef callback);
+ void zoomToScale(double scale, JSValueRef callback);
+
+ void touchDownAtPoint(long x, long y, long touchCount, JSValueRef callback);
+ void liftUpAtPoint(long x, long y, long touchCount, JSValueRef callback);
+ void singleTapAtPoint(long x, long y, JSValueRef callback);
+ void doubleTapAtPoint(long x, long y, JSValueRef callback);
+
+ void typeCharacterUsingHardwareKeyboard(JSStringRef character, JSValueRef callback);
+ void keyDownUsingHardwareKeyboard(JSStringRef character, JSValueRef callback);
+ void keyUpUsingHardwareKeyboard(JSStringRef character, JSValueRef callback);
+
+ void setWillBeginZoomingCallback(JSValueRef);
+ JSValueRef willBeginZoomingCallback() const;
+
+ void setDidEndZoomingCallback(JSValueRef);
+ JSValueRef didEndZoomingCallback() const;
+
+ void setDidShowKeyboardCallback(JSValueRef);
+ JSValueRef didShowKeyboardCallback() const;
+
+ void setDidHideKeyboardCallback(JSValueRef);
+ JSValueRef didHideKeyboardCallback() const;
+
+ void setDidEndScrollingCallback(JSValueRef);
+ JSValueRef didEndScrollingCallback() const;
+
+ double zoomScale() const;
+ double minimumZoomScale() const;
+ double maximumZoomScale() const;
+
+ JSObjectRef contentVisibleRect() const;
+
+ void uiScriptComplete(JSStringRef result);
+
+private:
+ UIScriptController(UIScriptContext&);
+
+ void platformSetWillBeginZoomingCallback();
+ void platformSetDidEndZoomingCallback();
+ void platformSetDidShowKeyboardCallback();
+ void platformSetDidHideKeyboardCallback();
+ void platformSetDidEndScrollingCallback();
+ void platformClearAllCallbacks();
+
+ virtual JSClassRef wrapperClass() override;
+
+ JSObjectRef objectFromRect(const WKRect&) const;
+
+ UIScriptContext* m_context;
+};
+
+}
+
+#endif // UIScriptController_h
diff --git a/Tools/WebKitTestRunner/WebKitTestRunner.sln b/Tools/WebKitTestRunner/WebKitTestRunner.sln
new file mode 100644
index 000000000..9d11a8ed9
--- /dev/null
+++ b/Tools/WebKitTestRunner/WebKitTestRunner.sln
@@ -0,0 +1,104 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WebKitTestRunner", "win\WebKitTestRunner.vcproj", "{3B99669B-1817-443B-BCBE-835580146668}"
+ ProjectSection(ProjectDependencies) = postProject
+ {CBC3391C-F060-4BF5-A66E-81404168816B} = {CBC3391C-F060-4BF5-A66E-81404168816B}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InjectedBundleGenerated", "win\InjectedBundleGenerated.vcproj", "{4343BC0B-A2E0-4B48-8277-F33CFBFA83CD}"
+ ProjectSection(ProjectDependencies) = postProject
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C} = {C0737398-3565-439E-A2B8-AB2BE4D5430C}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ImageDiff", "..\DumpRenderTree\win\ImageDiff.vcproj", "{59CC0547-70AC-499C-9B19-EC01C6F61137}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InjectedBundle", "win\InjectedBundle.vcproj", "{CBC3391C-F060-4BF5-A66E-81404168816B}"
+ ProjectSection(ProjectDependencies) = postProject
+ {4343BC0B-A2E0-4B48-8277-F33CFBFA83CD} = {4343BC0B-A2E0-4B48-8277-F33CFBFA83CD}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestNetscapePlugin", "..\DumpRenderTree\TestNetscapePlugIn\win\TestNetscapePlugin.vcproj", "{C0737398-3565-439E-A2B8-AB2BE4D5430C}"
+ ProjectSection(ProjectDependencies) = postProject
+ {DD7949B6-F2B4-47C2-9C42-E21E84CB1017} = {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WebKitTestRunnerLauncher", "win\WebKitTestRunnerLauncher.vcproj", "{C13FA6EF-B531-4BAD-9A23-18E2BEB8B040}"
+ ProjectSection(ProjectDependencies) = postProject
+ {3B99669B-1817-443B-BCBE-835580146668} = {3B99669B-1817-443B-BCBE-835580146668}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ImageDiffLauncher", "..\DumpRenderTree\win\ImageDiffLauncher.vcproj", "{DD7949B6-F2B4-47C2-9C42-E21E84CB1017}"
+ ProjectSection(ProjectDependencies) = postProject
+ {59CC0547-70AC-499C-9B19-EC01C6F61137} = {59CC0547-70AC-499C-9B19-EC01C6F61137}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug_All|Win32 = Debug_All|Win32
+ Debug|Win32 = Debug|Win32
+ Production|Win32 = Production|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {3B99669B-1817-443B-BCBE-835580146668}.Debug_All|Win32.ActiveCfg = Debug_All|Win32
+ {3B99669B-1817-443B-BCBE-835580146668}.Debug_All|Win32.Build.0 = Debug_All|Win32
+ {3B99669B-1817-443B-BCBE-835580146668}.Debug|Win32.ActiveCfg = Debug|Win32
+ {3B99669B-1817-443B-BCBE-835580146668}.Debug|Win32.Build.0 = Debug|Win32
+ {3B99669B-1817-443B-BCBE-835580146668}.Production|Win32.ActiveCfg = Production|Win32
+ {3B99669B-1817-443B-BCBE-835580146668}.Production|Win32.Build.0 = Production|Win32
+ {3B99669B-1817-443B-BCBE-835580146668}.Release|Win32.ActiveCfg = Release|Win32
+ {3B99669B-1817-443B-BCBE-835580146668}.Release|Win32.Build.0 = Release|Win32
+ {4343BC0B-A2E0-4B48-8277-F33CFBFA83CD}.Debug_All|Win32.ActiveCfg = Debug_All|Win32
+ {4343BC0B-A2E0-4B48-8277-F33CFBFA83CD}.Debug_All|Win32.Build.0 = Debug_All|Win32
+ {4343BC0B-A2E0-4B48-8277-F33CFBFA83CD}.Debug|Win32.ActiveCfg = Debug|Win32
+ {4343BC0B-A2E0-4B48-8277-F33CFBFA83CD}.Debug|Win32.Build.0 = Debug|Win32
+ {4343BC0B-A2E0-4B48-8277-F33CFBFA83CD}.Production|Win32.ActiveCfg = Production|Win32
+ {4343BC0B-A2E0-4B48-8277-F33CFBFA83CD}.Production|Win32.Build.0 = Production|Win32
+ {4343BC0B-A2E0-4B48-8277-F33CFBFA83CD}.Release|Win32.ActiveCfg = Release|Win32
+ {4343BC0B-A2E0-4B48-8277-F33CFBFA83CD}.Release|Win32.Build.0 = Release|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Debug_All|Win32.ActiveCfg = Debug_All|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Debug_All|Win32.Build.0 = Debug_All|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Debug|Win32.ActiveCfg = Debug|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Debug|Win32.Build.0 = Debug|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Production|Win32.ActiveCfg = Production|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Production|Win32.Build.0 = Production|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Release|Win32.ActiveCfg = Release|Win32
+ {59CC0547-70AC-499C-9B19-EC01C6F61137}.Release|Win32.Build.0 = Release|Win32
+ {CBC3391C-F060-4BF5-A66E-81404168816B}.Debug_All|Win32.ActiveCfg = Debug_All|Win32
+ {CBC3391C-F060-4BF5-A66E-81404168816B}.Debug_All|Win32.Build.0 = Debug_All|Win32
+ {CBC3391C-F060-4BF5-A66E-81404168816B}.Debug|Win32.ActiveCfg = Debug|Win32
+ {CBC3391C-F060-4BF5-A66E-81404168816B}.Debug|Win32.Build.0 = Debug|Win32
+ {CBC3391C-F060-4BF5-A66E-81404168816B}.Production|Win32.ActiveCfg = Production|Win32
+ {CBC3391C-F060-4BF5-A66E-81404168816B}.Production|Win32.Build.0 = Production|Win32
+ {CBC3391C-F060-4BF5-A66E-81404168816B}.Release|Win32.ActiveCfg = Release|Win32
+ {CBC3391C-F060-4BF5-A66E-81404168816B}.Release|Win32.Build.0 = Release|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Debug_All|Win32.ActiveCfg = Debug_All|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Debug_All|Win32.Build.0 = Debug_All|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Debug|Win32.ActiveCfg = Debug|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Debug|Win32.Build.0 = Debug|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Production|Win32.ActiveCfg = Production|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Production|Win32.Build.0 = Production|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Release|Win32.ActiveCfg = Release|Win32
+ {C0737398-3565-439E-A2B8-AB2BE4D5430C}.Release|Win32.Build.0 = Release|Win32
+ {C13FA6EF-B531-4BAD-9A23-18E2BEB8B040}.Debug_All|Win32.ActiveCfg = Debug_All|Win32
+ {C13FA6EF-B531-4BAD-9A23-18E2BEB8B040}.Debug_All|Win32.Build.0 = Debug_All|Win32
+ {C13FA6EF-B531-4BAD-9A23-18E2BEB8B040}.Debug|Win32.ActiveCfg = Debug|Win32
+ {C13FA6EF-B531-4BAD-9A23-18E2BEB8B040}.Debug|Win32.Build.0 = Debug|Win32
+ {C13FA6EF-B531-4BAD-9A23-18E2BEB8B040}.Production|Win32.ActiveCfg = Production|Win32
+ {C13FA6EF-B531-4BAD-9A23-18E2BEB8B040}.Production|Win32.Build.0 = Production|Win32
+ {C13FA6EF-B531-4BAD-9A23-18E2BEB8B040}.Release|Win32.ActiveCfg = Release|Win32
+ {C13FA6EF-B531-4BAD-9A23-18E2BEB8B040}.Release|Win32.Build.0 = Release|Win32
+ {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Debug_All|Win32.ActiveCfg = Debug_All|Win32
+ {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Debug_All|Win32.Build.0 = Debug_All|Win32
+ {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Debug|Win32.ActiveCfg = Debug|Win32
+ {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Debug|Win32.Build.0 = Debug|Win32
+ {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Production|Win32.ActiveCfg = Production|Win32
+ {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Production|Win32.Build.0 = Production|Win32
+ {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Release|Win32.ActiveCfg = Release|Win32
+ {DD7949B6-F2B4-47C2-9C42-E21E84CB1017}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Tools/WebKitTestRunner/WebKitTestRunnerApp/AppDelegate.h b/Tools/WebKitTestRunner/WebKitTestRunnerApp/AppDelegate.h
new file mode 100644
index 000000000..27752908b
--- /dev/null
+++ b/Tools/WebKitTestRunner/WebKitTestRunnerApp/AppDelegate.h
@@ -0,0 +1,15 @@
+//
+// AppDelegate.h
+// WebKitTestRunnerApp
+//
+// Created by David Farler on 1/22/14.
+//
+//
+
+#import <UIKit/UIKit.h>
+
+@interface AppDelegate : UIResponder <UIApplicationDelegate>
+
+@property (strong, nonatomic) UIWindow *window;
+
+@end
diff --git a/Tools/WebKitTestRunner/WebKitTestRunnerPrefix.h b/Tools/WebKitTestRunner/WebKitTestRunnerPrefix.h
index dc958c10e..5f989fc54 100644
--- a/Tools/WebKitTestRunner/WebKitTestRunnerPrefix.h
+++ b/Tools/WebKitTestRunner/WebKitTestRunnerPrefix.h
@@ -27,13 +27,8 @@
#import <Foundation/Foundation.h>
#endif
-#if defined(BUILDING_GTK__)
-#include "autotoolsconfig.h"
-#endif /* defined (BUILDING_GTK__) */
-
+#include <WebKit/WebKit2_C.h>
#include <wtf/Platform.h>
-#include <WebKit2/WebKit2_C.h>
-
/* When C++ exceptions are disabled, the C++ library defines |try| and |catch|
* to allow C++ code that expects exceptions to build. These definitions
diff --git a/Tools/WebKitTestRunner/WebNotificationProvider.cpp b/Tools/WebKitTestRunner/WebNotificationProvider.cpp
index 55064249f..de6adece0 100644
--- a/Tools/WebKitTestRunner/WebNotificationProvider.cpp
+++ b/Tools/WebKitTestRunner/WebNotificationProvider.cpp
@@ -26,10 +26,10 @@
#include "config.h"
#include "WebNotificationProvider.h"
-#include <WebKit2/WKMutableArray.h>
-#include <WebKit2/WKNotification.h>
-#include <WebKit2/WKNumber.h>
-#include <WebKit2/WKSecurityOrigin.h>
+#include <WebKit/WKMutableArray.h>
+#include <WebKit/WKNotification.h>
+#include <WebKit/WKNumber.h>
+#include <WebKit/WKSecurityOriginRef.h>
#include <wtf/Assertions.h>
namespace WTR {
@@ -65,13 +65,14 @@ WebNotificationProvider::WebNotificationProvider()
WebNotificationProvider::~WebNotificationProvider()
{
- WKNotificationManagerSetProvider(m_notificationManager.get(), 0);
+ for (auto& manager : m_ownedNotifications)
+ WKNotificationManagerSetProvider(manager.key.get(), nullptr);
}
WKNotificationProviderV0 WebNotificationProvider::provider()
{
WKNotificationProviderV0 notificationProvider = {
- { kWKNotificationProviderCurrentVersion, this },
+ { 0, this },
WTR::showWebNotification,
WTR::closeWebNotification,
0, // didDestroyNotification
@@ -83,44 +84,57 @@ WKNotificationProviderV0 WebNotificationProvider::provider()
return notificationProvider;
}
-void WebNotificationProvider::showWebNotification(WKPageRef, WKNotificationRef notification)
+void WebNotificationProvider::showWebNotification(WKPageRef page, WKNotificationRef notification)
{
- if (!m_notificationManager)
- return;
-
+ auto context = WKPageGetContext(page);
+ auto notificationManager = WKContextGetNotificationManager(context);
uint64_t id = WKNotificationGetID(notification);
- ASSERT(!m_shownNotifications.contains(id));
- m_shownNotifications.add(id);
- WKNotificationManagerProviderDidShowNotification(m_notificationManager.get(), WKNotificationGetID(notification));
+ ASSERT(m_ownedNotifications.contains(notificationManager));
+ auto addResult = m_ownedNotifications.find(notificationManager)->value.add(id);
+ ASSERT_UNUSED(addResult, addResult.isNewEntry);
+ auto addResult2 = m_owningManager.set(id, notificationManager);
+ ASSERT_UNUSED(addResult2, addResult2.isNewEntry);
+
+ WKNotificationManagerProviderDidShowNotification(notificationManager, id);
}
void WebNotificationProvider::closeWebNotification(WKNotificationRef notification)
{
- if (!m_notificationManager)
- return;
-
uint64_t id = WKNotificationGetID(notification);
+ ASSERT(m_owningManager.contains(id));
+ auto notificationManager = m_owningManager.get(id);
+
+ ASSERT(m_ownedNotifications.contains(notificationManager));
+ bool success = m_ownedNotifications.find(notificationManager)->value.remove(id);
+ ASSERT_UNUSED(success, success);
+ m_owningManager.remove(id);
+
WKRetainPtr<WKUInt64Ref> wkID = WKUInt64Create(id);
WKRetainPtr<WKMutableArrayRef> array(AdoptWK, WKMutableArrayCreate());
WKArrayAppendItem(array.get(), wkID.get());
- m_shownNotifications.remove(id);
- WKNotificationManagerProviderDidCloseNotifications(m_notificationManager.get(), array.get());
+ WKNotificationManagerProviderDidCloseNotifications(notificationManager, array.get());
}
void WebNotificationProvider::addNotificationManager(WKNotificationManagerRef manager)
{
- // We assume there is only one for testing.
- ASSERT(!m_notificationManager);
- m_notificationManager = manager;
+ m_ownedNotifications.add(manager, HashSet<uint64_t>());
}
void WebNotificationProvider::removeNotificationManager(WKNotificationManagerRef manager)
{
- // We assume there is only one for testing.
- ASSERT(m_notificationManager);
- ASSERT(m_notificationManager.get() == manager);
- m_notificationManager = 0;
+ auto iterator = m_ownedNotifications.find(manager);
+ ASSERT(iterator != m_ownedNotifications.end());
+ auto toRemove = iterator->value;
+ WKRetainPtr<WKNotificationManagerRef> guard(manager);
+ m_ownedNotifications.remove(iterator);
+ WKRetainPtr<WKMutableArrayRef> array = adoptWK(WKMutableArrayCreate());
+ for (uint64_t notificationID : toRemove) {
+ bool success = m_owningManager.remove(notificationID);
+ ASSERT_UNUSED(success, success);
+ WKArrayAppendItem(array.get(), adoptWK(WKUInt64Create(notificationID)).get());
+ }
+ WKNotificationManagerProviderDidCloseNotifications(manager, array.get());
}
WKDictionaryRef WebNotificationProvider::notificationPermissions()
@@ -131,29 +145,23 @@ WKDictionaryRef WebNotificationProvider::notificationPermissions()
void WebNotificationProvider::simulateWebNotificationClick(uint64_t notificationID)
{
- if (!m_notificationManager)
- return;
-
- ASSERT(m_shownNotifications.contains(notificationID));
- WKNotificationManagerProviderDidClickNotification(m_notificationManager.get(), notificationID);
+ ASSERT(m_owningManager.contains(notificationID));
+ WKNotificationManagerProviderDidClickNotification(m_owningManager.get(notificationID), notificationID);
}
void WebNotificationProvider::reset()
{
- if (!m_notificationManager) {
- m_shownNotifications.clear();
- return;
+ for (auto& notificationPair : m_ownedNotifications) {
+ if (notificationPair.value.isEmpty())
+ continue;
+ WKRetainPtr<WKMutableArrayRef> array = adoptWK(WKMutableArrayCreate());
+ for (uint64_t notificationID : notificationPair.value)
+ WKArrayAppendItem(array.get(), adoptWK(WKUInt64Create(notificationID)).get());
+
+ notificationPair.value.clear();
+ WKNotificationManagerProviderDidCloseNotifications(notificationPair.key.get(), array.get());
}
-
- WKRetainPtr<WKMutableArrayRef> array(AdoptWK, WKMutableArrayCreate());
- HashSet<uint64_t>::const_iterator itEnd = m_shownNotifications.end();
- for (HashSet<uint64_t>::const_iterator it = m_shownNotifications.begin(); it != itEnd; ++it) {
- WKRetainPtr<WKUInt64Ref> wkID = WKUInt64Create(*it);
- WKArrayAppendItem(array.get(), wkID.get());
- }
-
- m_shownNotifications.clear();
- WKNotificationManagerProviderDidCloseNotifications(m_notificationManager.get(), array.get());
+ m_owningManager.clear();
}
} // namespace WTR
diff --git a/Tools/WebKitTestRunner/WebNotificationProvider.h b/Tools/WebKitTestRunner/WebNotificationProvider.h
index fba2870fc..d8724a93a 100644
--- a/Tools/WebKitTestRunner/WebNotificationProvider.h
+++ b/Tools/WebKitTestRunner/WebNotificationProvider.h
@@ -26,9 +26,10 @@
#ifndef WebNotificationProvider_h
#define WebNotificationProvider_h
-#include <WebKit2/WKNotificationManager.h>
-#include <WebKit2/WKNotificationProvider.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKNotificationManager.h>
+#include <WebKit/WKNotificationProvider.h>
+#include <WebKit/WKRetainPtr.h>
+#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
namespace WTR {
@@ -49,8 +50,9 @@ public:
void reset();
private:
- WKRetainPtr<WKNotificationManagerRef> m_notificationManager;
- HashSet<uint64_t> m_shownNotifications;
+ // Inverses of each other.
+ HashMap<WKRetainPtr<WKNotificationManagerRef>, HashSet<uint64_t>> m_ownedNotifications;
+ HashMap<uint64_t, WKNotificationManagerRef> m_owningManager;
};
}
diff --git a/Tools/WebKitTestRunner/WorkQueueManager.cpp b/Tools/WebKitTestRunner/WorkQueueManager.cpp
index e74fa3464..63f491b47 100644
--- a/Tools/WebKitTestRunner/WorkQueueManager.cpp
+++ b/Tools/WebKitTestRunner/WorkQueueManager.cpp
@@ -28,17 +28,17 @@
#include "PlatformWebView.h"
#include "TestController.h"
-#include <WebKit2/WKPage.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKPage.h>
+#include <WebKit/WKPagePrivate.h>
+#include <WebKit/WKRetainPtr.h>
#include <stdio.h>
-#include <wtf/PassOwnPtr.h>
#include <wtf/text/CString.h>
namespace WTR {
static inline WKPageRef mainPage()
{
- return TestController::shared().mainWebView()->page();
+ return TestController::singleton().mainWebView()->page();
}
static inline bool goToItemAtIndex(int index)
@@ -119,20 +119,21 @@ bool WorkQueueManager::processWorkQueue()
{
m_processing = false;
while (!m_processing && !m_workQueue.isEmpty()) {
- OwnPtr<WorkQueueItem> item(m_workQueue.takeFirst());
+ std::unique_ptr<WorkQueueItem> item(m_workQueue.takeFirst());
m_processing = (item->invoke() == WorkQueueItem::Loading);
}
return !m_processing;
}
-void WorkQueueManager::queueLoad(const String& url, const String& target)
+void WorkQueueManager::queueLoad(const String& url, const String& target, bool shouldOpenExternalURLs)
{
class LoadItem : public WorkQueueItem {
public:
- LoadItem(const String& url, const String& target)
+ LoadItem(const String& url, const String& target, bool shouldOpenExternalURLs)
: m_url(AdoptWK, WKURLCreateWithUTF8CString(url.utf8().data()))
, m_target(target)
+ , m_shouldOpenExternalURLs(shouldOpenExternalURLs)
{
}
@@ -143,15 +144,16 @@ void WorkQueueManager::queueLoad(const String& url, const String& target)
fprintf(stderr, "queueLoad for a specific target is not implemented.\n");
return WorkQueueItem::NonLoading;
}
- WKPageLoadURL(mainPage(), m_url.get());
+ WKPageLoadURLWithShouldOpenExternalURLsPolicy(mainPage(), m_url.get(), m_shouldOpenExternalURLs);
return WorkQueueItem::Loading;
}
WKRetainPtr<WKURLRef> m_url;
String m_target;
+ bool m_shouldOpenExternalURLs;
};
- enqueue(new LoadItem(url, target));
+ enqueue(new LoadItem(url, target, shouldOpenExternalURLs));
}
void WorkQueueManager::queueLoadHTMLString(const String& content, const String& baseURL, const String& unreachableURL)
@@ -222,7 +224,7 @@ void WorkQueueManager::enqueue(WorkQueueItem* item)
return;
}
- m_workQueue.append(adoptPtr(item));
+ m_workQueue.append(std::unique_ptr<WorkQueueItem>(item));
}
} // namespace WTR
diff --git a/Tools/WebKitTestRunner/WorkQueueManager.h b/Tools/WebKitTestRunner/WorkQueueManager.h
index 21d5ebb88..273d51191 100644
--- a/Tools/WebKitTestRunner/WorkQueueManager.h
+++ b/Tools/WebKitTestRunner/WorkQueueManager.h
@@ -27,7 +27,6 @@
#define WorkQueueManager_h
#include <wtf/Deque.h>
-#include <wtf/OwnPtr.h>
#include <wtf/text/WTFString.h>
namespace WTR {
@@ -42,7 +41,7 @@ public:
void clearWorkQueue();
bool processWorkQueue(); // Returns 'true' if queue is processed (no new loading is started), returns 'false' otherwise.
- void queueLoad(const String& url, const String& target);
+ void queueLoad(const String& url, const String& target, bool shouldOpenExternalURLs);
void queueLoadHTMLString(const String& content, const String& baseURL, const String& unreachableURL);
void queueBackNavigation(unsigned howFarBackward);
void queueForwardNavigation(unsigned howFarForward);
@@ -51,7 +50,7 @@ public:
void queueNonLoadingScript(const String& script);
private:
- typedef Deque<OwnPtr<class WorkQueueItem> > WorkQueue;
+ typedef Deque<std::unique_ptr<class WorkQueueItem>> WorkQueue;
void enqueue(WorkQueueItem*); // Adopts pointer.
diff --git a/Tools/WebKitTestRunner/cairo/TestInvocationCairo.cpp b/Tools/WebKitTestRunner/cairo/TestInvocationCairo.cpp
index 828e65b1b..376f31986 100644
--- a/Tools/WebKitTestRunner/cairo/TestInvocationCairo.cpp
+++ b/Tools/WebKitTestRunner/cairo/TestInvocationCairo.cpp
@@ -32,7 +32,7 @@
#include "PixelDumpSupport.h"
#include "PlatformWebView.h"
#include "TestController.h"
-#include <WebKit2/WKImageCairo.h>
+#include <WebKit/WKImageCairo.h>
#include <cairo/cairo.h>
#include <cstdio>
#include <wtf/Assertions.h>
@@ -106,14 +106,9 @@ static void paintRepaintRectOverlay(cairo_surface_t* surface, WKArrayRef repaint
cairo_destroy(context);
}
-void TestInvocation::dumpPixelsAndCompareWithExpected(WKImageRef wkImage, WKArrayRef repaintRects)
+void TestInvocation::dumpPixelsAndCompareWithExpected(WKImageRef image, WKArrayRef repaintRects, SnapshotResultType)
{
-#if USE(ACCELERATED_COMPOSITING) && PLATFORM(EFL)
- UNUSED_PARAM(wkImage);
- cairo_surface_t* surface = WKImageCreateCairoSurface(TestController::shared().mainWebView()->windowSnapshotImage().get());
-#else
- cairo_surface_t* surface = WKImageCreateCairoSurface(wkImage);
-#endif
+ cairo_surface_t* surface = WKImageCreateCairoSurface(image);
if (repaintRects)
paintRepaintRectOverlay(surface, repaintRects);
diff --git a/Tools/DumpRenderTree/gtk/TextInputController.h b/Tools/WebKitTestRunner/config.h
index 53793f637..4fb2a4b5e 100644
--- a/Tools/DumpRenderTree/gtk/TextInputController.h
+++ b/Tools/WebKitTestRunner/config.h
@@ -1,37 +1,41 @@
/*
- * Copyright (C) 2011 Igalia S.L.
+ * 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.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * 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 OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * 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.
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+
+#ifndef WebKitTestRunner_config_h
+#define WebKitTestRunner_config_h
-#ifndef TextInputController_h
-#define TextInputController_h
+#if defined (BUILDING_WITH_CMAKE)
+#include "cmakeconfig.h"
+#endif
-typedef const struct OpaqueJSContext* JSContextRef;
-typedef struct OpaqueJSValue* JSObjectRef;
+#include <WebKit/WebKit2_C.h>
+#include <wtf/Platform.h>
+#include <wtf/ExportMacros.h>
+#include <runtime/JSExportMacros.h>
-JSObjectRef makeTextInputController(JSContextRef);
+// This is needed because we include WebCore's headers.
+// FIXME: We should include <WebCore/PlatformExportMacros.h> instead.
+#define WEBCORE_EXPORT
#endif
diff --git a/Tools/WebKitTestRunner/gtk/EventSenderProxyGtk.cpp b/Tools/WebKitTestRunner/gtk/EventSenderProxyGtk.cpp
index d25320125..023edc810 100644
--- a/Tools/WebKitTestRunner/gtk/EventSenderProxyGtk.cpp
+++ b/Tools/WebKitTestRunner/gtk/EventSenderProxyGtk.cpp
@@ -14,7 +14,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.
*
@@ -39,7 +39,7 @@
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
#include <wtf/StdLibExtras.h>
-#include <wtf/gobject/GUniquePtr.h>
+#include <wtf/glib/GUniquePtr.h>
#include <wtf/text/WTFString.h>
namespace WTR {
@@ -162,8 +162,17 @@ void EventSenderProxy::updateClickCountForButton(int button)
m_clickButton = button;
}
-static void dispatchEvent(GdkEvent* event)
+void EventSenderProxy::dispatchEvent(GdkEvent* event)
{
+ ASSERT(m_testController->mainWebView());
+
+ // If we are sending an escape key to the WebView, this has the side-effect of dismissing
+ // any current popups anyway. Chances are that the test is doing this to dismiss the popup
+ // anyway. Not all tests properly dismiss popup menus, so we still need to do it manually
+ // if this isn't an escape key press.
+ if (event->type != GDK_KEY_PRESS || event->key.keyval != GDK_KEY_Escape)
+ m_testController->mainWebView()->dismissAllPopupMenus();
+
gtk_main_do_event(event);
gdk_event_free(event);
}
@@ -277,6 +286,8 @@ int getGDKKeySymForKeyRef(WKStringRef keyRef, unsigned location, guint* modifier
return GDK_KEY_Tab;
if (charCode == '\x8')
return GDK_KEY_BackSpace;
+ if (charCode == 0x001B)
+ return GDK_KEY_Escape;
if (WTF::isASCIIUpper(charCode))
*modifiers |= GDK_SHIFT_MASK;
@@ -433,6 +444,18 @@ void EventSenderProxy::continuousMouseScrollBy(int horizontal, int vertical, boo
sendOrQueueEvent(event);
}
+void EventSenderProxy::mouseScrollByWithWheelAndMomentumPhases(int x, int y, int /*phase*/, int /*momentum*/)
+{
+ // Gtk+ does not have the concept of wheel gesture phases or momentum. Just relay to
+ // the mouse wheel handler.
+ mouseScrollBy(x, y);
+}
+
+void EventSenderProxy::swipeGestureWithWheelAndMomentumPhases(int, int, int, int)
+{
+ notImplemented();
+}
+
void EventSenderProxy::leapForward(int milliseconds)
{
if (m_eventQueue.isEmpty())
@@ -466,6 +489,7 @@ GUniquePtr<GdkEvent> EventSenderProxy::createTouchEvent(GdkEventType eventType,
return touchEvent;
}
+#if ENABLE(TOUCH_EVENTS)
void EventSenderProxy::addTouchPoint(int x, int y)
{
// Touch ID is array index plus one, so 0 is skipped.
@@ -556,6 +580,6 @@ void EventSenderProxy::setTouchModifier(WKEventModifiers modifier, bool enable)
m_updatedTouchEvents.add(GPOINTER_TO_INT(event->touch.sequence));
}
}
-
+#endif // ENABLE(TOUCH_EVENTS)
} // namespace WTR
diff --git a/Tools/WebKitTestRunner/gtk/PlatformWebViewGtk.cpp b/Tools/WebKitTestRunner/gtk/PlatformWebViewGtk.cpp
index fd6f8466b..becb1705d 100644
--- a/Tools/WebKitTestRunner/gtk/PlatformWebViewGtk.cpp
+++ b/Tools/WebKitTestRunner/gtk/PlatformWebViewGtk.cpp
@@ -28,13 +28,17 @@
#include "config.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKViewPrivate.h>
+#include <WebKit/WKImageCairo.h>
+#include <WebKit/WKPageConfigurationRef.h>
+#include <WebKit/WKView.h>
+#include <WebKit/WKViewPrivate.h>
#include <gtk/gtk.h>
+#include <wtf/Assertions.h>
namespace WTR {
-PlatformWebView::PlatformWebView(WKContextRef context, WKPageGroupRef pageGroup, WKPageRef /* relatedPage */, WKDictionaryRef options)
- : m_view(WKViewCreate(context, pageGroup))
+PlatformWebView::PlatformWebView(WKPageConfigurationRef configuration, const TestOptions& options)
+ : m_view(WKViewCreate(configuration))
, m_window(gtk_window_new(GTK_WINDOW_POPUP))
, m_windowIsKey(true)
, m_options(options)
@@ -42,7 +46,7 @@ PlatformWebView::PlatformWebView(WKContextRef context, WKPageGroupRef pageGroup,
gtk_container_add(GTK_CONTAINER(m_window), GTK_WIDGET(m_view));
GtkAllocation size = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(m_window, &size);
+ gtk_widget_size_allocate(GTK_WIDGET(m_view), &size);
gtk_window_resize(GTK_WINDOW(m_window), 800, 600);
gtk_widget_show_all(m_window);
@@ -55,14 +59,17 @@ PlatformWebView::~PlatformWebView()
gtk_widget_destroy(m_window);
}
-void PlatformWebView::resizeTo(unsigned width, unsigned height)
+void PlatformWebView::setWindowIsKey(bool isKey)
{
- GtkAllocation size = { 0, 0, static_cast<int>(width), static_cast<int>(height) };
- gtk_widget_size_allocate(m_window, &size);
- gtk_window_resize(GTK_WINDOW(m_window), width, height);
+ m_windowIsKey = isKey;
+}
- while (gtk_events_pending())
- gtk_main_iteration();
+void PlatformWebView::resizeTo(unsigned width, unsigned height)
+{
+ WKRect frame = windowFrame();
+ frame.size.width = width;
+ frame.size.height = height;
+ setWindowFrame(frame);
}
WKPageRef PlatformWebView::page()
@@ -79,14 +86,8 @@ void PlatformWebView::focus()
WKRect PlatformWebView::windowFrame()
{
GtkAllocation geometry;
-#ifdef GTK_API_VERSION_2
- gint depth;
- gdk_window_get_geometry(gtk_widget_get_window(GTK_WIDGET(m_window)),
- &geometry.x, &geometry.y, &geometry.width, &geometry.height, &depth);
-#else
gdk_window_get_geometry(gtk_widget_get_window(GTK_WIDGET(m_window)),
&geometry.x, &geometry.y, &geometry.width, &geometry.height);
-#endif
WKRect frame;
frame.origin.x = geometry.x;
@@ -98,8 +99,13 @@ WKRect PlatformWebView::windowFrame()
void PlatformWebView::setWindowFrame(WKRect frame)
{
- gtk_window_move(GTK_WINDOW(m_window), frame.origin.x, frame.origin.y);
- resizeTo(frame.size.width, frame.size.height);
+ gdk_window_move_resize(gtk_widget_get_window(GTK_WIDGET(m_window)),
+ frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
+ GtkAllocation size = { 0, 0, static_cast<int>(frame.size.width), static_cast<int>(frame.size.height) };
+ gtk_widget_size_allocate(GTK_WIDGET(m_view), &size);
+
+ while (gtk_events_pending())
+ gtk_main_iteration();
}
void PlatformWebView::addChromeInputField()
@@ -114,16 +120,53 @@ void PlatformWebView::makeWebViewFirstResponder()
{
}
+void PlatformWebView::changeWindowScaleIfNeeded(float)
+{
+}
+
WKRetainPtr<WKImageRef> PlatformWebView::windowSnapshotImage()
{
- // FIXME: implement to capture pixels in the UI process,
- // which may be necessary to capture things like 3D transforms.
- return 0;
+ int width = gtk_widget_get_allocated_width(GTK_WIDGET(m_view));
+ int height = gtk_widget_get_allocated_height(GTK_WIDGET(m_view));
+
+ while (gtk_events_pending())
+ gtk_main_iteration();
+
+ cairo_surface_t* imageSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
+
+ cairo_t* context = cairo_create(imageSurface);
+ gtk_widget_draw(GTK_WIDGET(m_view), context);
+ cairo_destroy(context);
+
+ WKRetainPtr<WKImageRef> wkImage = adoptWK(WKImageCreateFromCairoSurface(imageSurface, 0 /* options */));
+
+ cairo_surface_destroy(imageSurface);
+ return wkImage;
}
void PlatformWebView::didInitializeClients()
{
}
+bool PlatformWebView::viewSupportsOptions(const TestOptions&) const
+{
+ return true;
+}
+
+void PlatformWebView::dismissAllPopupMenus()
+{
+ // gtk_menu_popdown doesn't modify the GList of attached menus, so it should
+ // be safe to walk this list while calling it.
+ GList* attachedMenusList = gtk_menu_get_for_attach_widget(GTK_WIDGET(m_view));
+ g_list_foreach(attachedMenusList, [] (void* data, void*) {
+ ASSERT(data);
+ gtk_menu_popdown(GTK_MENU(data));
+ }, nullptr);
+}
+
+void PlatformWebView::setNavigationGesturesEnabled(bool)
+{
+}
+
} // namespace WTR
diff --git a/Tools/WebKitTestRunner/gtk/TestControllerGtk.cpp b/Tools/WebKitTestRunner/gtk/TestControllerGtk.cpp
index d8fb9f728..df5da65d2 100644
--- a/Tools/WebKitTestRunner/gtk/TestControllerGtk.cpp
+++ b/Tools/WebKitTestRunner/gtk/TestControllerGtk.cpp
@@ -27,52 +27,68 @@
#include "config.h"
#include "TestController.h"
+#include "PlatformWebView.h"
#include <gtk/gtk.h>
#include <wtf/Platform.h>
-#include <wtf/gobject/GUniquePtr.h>
+#include <wtf/RunLoop.h>
+#include <wtf/glib/GRefPtr.h>
+#include <wtf/glib/GUniquePtr.h>
#include <wtf/text/WTFString.h>
namespace WTR {
-static guint gTimeoutSourceId = 0;
-
-static void cancelTimeout()
+static GSource* timeoutSource()
{
- if (!gTimeoutSourceId)
- return;
- g_source_remove(gTimeoutSourceId);
- gTimeoutSourceId = 0;
+ static GRefPtr<GSource> source = nullptr;
+ if (!source) {
+ source = adoptGRef(g_timeout_source_new(0));
+ g_source_set_ready_time(source.get(), -1);
+ g_source_set_name(source.get(), "[WTR] Test timeout source");
+ g_source_set_callback(source.get(), [](gpointer userData) -> gboolean {
+ g_source_set_ready_time(static_cast<GSource*>(userData), -1);
+ fprintf(stderr, "FAIL: TestControllerRunLoop timed out.\n");
+ RunLoop::main().stop();
+ return G_SOURCE_CONTINUE;
+ }, source.get(), nullptr);
+ g_source_attach(source.get(), nullptr);
+ }
+ return source.get();
}
void TestController::notifyDone()
{
- gtk_main_quit();
- cancelTimeout();
+ g_source_set_ready_time(timeoutSource(), -1);
+ RunLoop::main().stop();
}
void TestController::platformInitialize()
{
}
-void TestController::platformDestroy()
+WKPreferencesRef TestController::platformPreferences()
{
+ return WKPageGroupGetPreferences(m_pageGroup.get());
}
-static gboolean timeoutCallback(gpointer)
+void TestController::platformDestroy()
{
- fprintf(stderr, "FAIL: TestControllerRunLoop timed out.\n");
- gtk_main_quit();
- return FALSE;
}
void TestController::platformRunUntil(bool&, double timeout)
{
- cancelTimeout();
- if (timeout != m_noTimeout) {
- gTimeoutSourceId = g_timeout_add(timeout * 1000, timeoutCallback, 0);
- g_source_set_name_by_id(gTimeoutSourceId, "[WebKit] timeoutCallback");
- }
- gtk_main();
+ if (timeout > 0) {
+ // FIXME: This conversion is now repeated in several places, it should be moved to a common place in WTF and used everywhere.
+ auto timeoutDuration = std::chrono::duration<double>(timeout);
+ auto safeDuration = std::chrono::microseconds::max();
+ if (timeoutDuration < safeDuration)
+ safeDuration = std::chrono::duration_cast<std::chrono::microseconds>(timeoutDuration);
+ gint64 currentTime = g_get_monotonic_time();
+ gint64 targetTime = currentTime + std::min<gint64>(G_MAXINT64 - currentTime, safeDuration.count());
+ ASSERT(targetTime >= currentTime);
+ g_source_set_ready_time(timeoutSource(), targetTime);
+ } else
+ g_source_set_ready_time(timeoutSource(), -1);
+ RunLoop::main().run();
}
static char* getEnvironmentVariableAsUTF8String(const char* variableName)
@@ -102,9 +118,14 @@ void TestController::platformInitializeContext()
{
}
-void TestController::setHidden(bool)
+void TestController::setHidden(bool hidden)
{
- // FIXME: Need to implement this to test visibilityState.
+ if (!m_mainWebView)
+ return;
+ if (hidden)
+ gtk_widget_unmap(GTK_WIDGET(m_mainWebView->platformView()));
+ else
+ gtk_widget_map(GTK_WIDGET(m_mainWebView->platformView()));
}
void TestController::runModal(PlatformWebView*)
@@ -117,4 +138,19 @@ const char* TestController::platformLibraryPathForTesting()
return 0;
}
+void TestController::platformConfigureViewForTest(const TestInvocation&)
+{
+}
+
+void TestController::platformResetPreferencesToConsistentValues()
+{
+ if (!m_mainWebView)
+ return;
+ m_mainWebView->dismissAllPopupMenus();
+}
+
+void TestController::updatePlatformSpecificTestOptionsForTest(TestOptions&, const std::string&) const
+{
+}
+
} // namespace WTR
diff --git a/Tools/WebKitTestRunner/gtk/fonts/AHEM____.TTF b/Tools/WebKitTestRunner/gtk/fonts/AHEM____.TTF
new file mode 100644
index 000000000..ac81cb031
--- /dev/null
+++ b/Tools/WebKitTestRunner/gtk/fonts/AHEM____.TTF
Binary files differ
diff --git a/Tools/WebKitTestRunner/gtk/fonts/FontWithNoValidEncoding.fon b/Tools/WebKitTestRunner/gtk/fonts/FontWithNoValidEncoding.fon
new file mode 100644
index 000000000..8fff7d9c1
--- /dev/null
+++ b/Tools/WebKitTestRunner/gtk/fonts/FontWithNoValidEncoding.fon
Binary files differ
diff --git a/Tools/WebKitTestRunner/gtk/fonts/fonts.conf b/Tools/WebKitTestRunner/gtk/fonts/fonts.conf
new file mode 100644
index 000000000..2387e9581
--- /dev/null
+++ b/Tools/WebKitTestRunner/gtk/fonts/fonts.conf
@@ -0,0 +1,435 @@
+<?xml version="1.0"?>
+<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
+<fontconfig>
+
+ <!-- Due to patent (http://freetype.sourceforge.net/patents.html)
+ issues hinting gives different results depending on the
+ freetype version of the linux distribution, avoiding hinting
+ gives more consistent results. When all the distributions
+ release freetype the 2.4, which enables by default the
+ hinting method that was patented, we could undo this change
+ and try the hinting again. -->
+ <match target="font">
+ <edit name="hinting" mode="assign">
+ <bool>false</bool>
+ </edit>
+ </match>
+
+ <!-- This system may have turned off selection of bitmap fonts, but
+ we must turn it on again, because we want to be able to test that
+ bitmap fonts with no valid encodings are *never* selected regardless
+ of the Fontconfig settings. So force Fontconfig to select our cruddy
+ bitmap font -->
+ <selectfont>
+ <acceptfont>
+ <pattern>
+ <patelt name="family">
+ <string>FontWithNoValidEncoding</string>
+ </patelt>
+ </pattern>
+ </acceptfont>
+ </selectfont>
+
+ <!-- The sans-serif font should be Liberation Serif -->
+ <match target="pattern">
+ <test qual="any" name="family">
+ <string>serif</string>
+ </test>
+ <edit name="family" mode="assign">
+ <string>Liberation Serif</string>
+ </edit>
+ </match>
+ <match target="pattern">
+ <test qual="any" name="family">
+ <string>Times</string>
+ </test>
+ <edit name="family" mode="assign">
+ <string>Liberation Serif</string>
+ </edit>
+ </match>
+ <match target="pattern">
+ <test qual="any" name="family">
+ <string>Times New Roman</string>
+ </test>
+ <edit name="family" mode="assign">
+ <string>Liberation Serif</string>
+ </edit>
+ </match>
+
+ <!-- Until we find good fonts to use for cursive and fantasy
+ just use our serif font. -->
+ <match target="pattern">
+ <test qual="any" name="family">
+ <string>cursive</string>
+ </test>
+ <edit name="family" mode="assign">
+ <string>Liberation Serif</string>
+ </edit>
+ </match>
+ <match target="pattern">
+ <test qual="any" name="family">
+ <string>fantasy</string>
+ </test>
+ <edit name="family" mode="assign">
+ <string>Liberation Serif</string>
+ </edit>
+ </match>
+
+ <!-- The sans-serif font should be Liberation Sans -->
+ <match target="pattern">
+ <test qual="any" name="family">
+ <string>sans serif</string>
+ </test>
+ <edit name="family" mode="assign">
+ <string>Liberation Sans</string>
+ </edit>
+ </match>
+ <match target="pattern">
+ <test qual="any" name="family">
+ <string>sans</string>
+ </test>
+ <edit name="family" mode="assign">
+ <string>Liberation Sans</string>
+ </edit>
+ </match>
+ <!-- We need to ensure that layout tests that use "Helvetica" don't
+ fall back to the default serif font -->
+ <match target="pattern">
+ <test qual="any" name="family">
+ <string>Helvetica</string>
+ </test>
+ <edit name="family" mode="assign">
+ <string>Liberation Sans</string>
+ </edit>
+ </match>
+ <match target="pattern">
+ <test qual="any" name="family">
+ <string>Arial</string>
+ </test>
+ <edit name="family" mode="assign">
+ <string>Liberation Sans</string>
+ </edit>
+ </match>
+ <match target="pattern">
+ <test qual="any" name="family">
+ <string>Lucida Grande</string>
+ </test>
+ <edit name="family" mode="assign">
+ <string>Liberation Sans</string>
+ </edit>
+ </match>
+
+ <!-- The Monospace font should be Liberation Mono -->
+ <match target="pattern">
+ <test qual="any" name="family">
+ <string>monospace</string>
+ </test>
+ <edit name="family" mode="assign">
+ <string>Liberation Mono</string>
+ </edit>
+ </match>
+ <match target="pattern">
+ <test qual="any" name="family">
+ <string>mono</string>
+ </test>
+ <edit name="family" mode="assign">
+ <string>Liberation Mono</string>
+ </edit>
+ </match>
+ <!-- We need to ensure that layout tests that use "Courier", "Courier New",
+ and "Monaco" (all monospace fonts) don't fall back to the default
+ serif font -->
+ <match target="pattern">
+ <test qual="any" name="family">
+ <string>Courier</string>
+ </test>
+ <edit name="family" mode="assign">
+ <string>Liberation Mono</string>
+ </edit>
+ </match>
+ <match target="pattern">
+ <test qual="any" name="family">
+ <string>Courier New</string>
+ </test>
+ <edit name="family" mode="assign">
+ <string>Liberation Mono</string>
+ </edit>
+ </match>
+ <match target="pattern">
+ <test qual="any" name="family">
+ <string>Monaco</string>
+ </test>
+ <edit name="family" mode="assign">
+ <string>Liberation Mono</string>
+ </edit>
+ </match>
+
+ <!-- The following hinting specializations are adapted from those in the
+ Chromium test_shell. We try to duplicate their incredibly thorough
+ testing here -->
+ <match target="pattern">
+ <test name="family" compare="eq">
+ <string>NonAntiAliasedSans</string>
+ </test>
+ <edit name="family" mode="assign">
+ <string>Liberation Sans</string>
+ </edit>
+ <edit name="antialias" mode="assign">
+ <bool>false</bool>
+ </edit>
+ </match>
+
+ <match target="pattern">
+ <test name="family" compare="eq">
+ <string>SlightHintedSerif</string>
+ </test>
+ <edit name="family" mode="assign">
+ <string>Liberation Serif</string>
+ </edit>
+ <edit name="hinting" mode="assign">
+ <bool>true</bool>
+ </edit>
+ <edit name="hintstyle" mode="assign">
+ <const>hintslight</const>
+ </edit>
+ </match>
+
+ <match target="pattern">
+ <test name="family" compare="eq">
+ <string>NonHintedSans</string>
+ </test>
+ <edit name="family" mode="assign">
+ <string>Liberation Sans</string>
+ </edit>
+ <!-- These deliberately contradict each other. The 'hinting' preference
+ should take priority -->
+ <edit name="hintstyle" mode="assign">
+ <const>hintfull</const>
+ </edit>
+ <edit name="hinting" mode="assign">
+ <bool>false</bool>
+ </edit>
+ </match>
+
+ <match target="pattern">
+ <test name="family" compare="eq">
+ <string>AutohintedSerif</string>
+ </test>
+ <edit name="family" mode="assign">
+ <string>Liberation Serif</string>
+ </edit>
+ <edit name="hinting" mode="assign">
+ <bool>true</bool>
+ </edit>
+ <edit name="autohint" mode="assign">
+ <bool>true</bool>
+ </edit>
+ <edit name="hintstyle" mode="assign">
+ <const>hintmedium</const>
+ </edit>
+ </match>
+
+ <match target="pattern">
+ <test name="family" compare="eq">
+ <string>HintedSerif</string>
+ </test>
+ <edit name="family" mode="assign">
+ <string>Liberation Serif</string>
+ </edit>
+ <edit name="hinting" mode="assign">
+ <bool>true</bool>
+ </edit>
+ <edit name="autohint" mode="assign">
+ <bool>false</bool>
+ </edit>
+ <edit name="hintstyle" mode="assign">
+ <const>hintmedium</const>
+ </edit>
+ </match>
+
+ <match target="pattern">
+ <test name="family" compare="eq">
+ <string>FullAndAutoHintedSerif</string>
+ </test>
+ <edit name="family" mode="assign">
+ <string>Liberation Serif</string>
+ </edit>
+ <edit name="hinting" mode="assign">
+ <bool>true</bool>
+ </edit>
+ <edit name="autohint" mode="assign">
+ <bool>true</bool>
+ </edit>
+ <edit name="hintstyle" mode="assign">
+ <const>hintfull</const>
+ </edit>
+ </match>
+
+ <match target="pattern">
+ <test name="family" compare="eq">
+ <string>SubpixelEnabledSans</string>
+ </test>
+ <edit name="family" mode="assign">
+ <string>Liberation Sans</string>
+ </edit>
+ <edit name="rgba" mode="assign">
+ <const>rgb</const>
+ </edit>
+ </match>
+
+ <match target="pattern">
+ <test name="family" compare="eq">
+ <string>SubpixelDisabledSans</string>
+ </test>
+ <edit name="family" mode="assign">
+ <string>Liberation Sans</string>
+ </edit>
+ <edit name="rgba" mode="assign">
+ <const>none</const>
+ </edit>
+ </match>
+
+ <!-- We need to enable simulated bold to for DejaVu Serif to ensure that we interpret
+ this property correctly in: platform/gtk/fonts/fontconfig-synthetic-bold.html -->
+ <match target="font">
+ <test qual="any" name="family">
+ <string>DejaVu Serif</string>
+ </test>
+ <test name="weight" compare="less_eq">
+ <const>medium</const>
+ </test>
+ <test target="pattern" name="weight" compare="more">
+ <const>medium</const>
+ </test>
+ <edit name="embolden" mode="assign">
+ <bool>true</bool>
+ </edit>
+ <edit name="weight" mode="assign">
+ <const>bold</const>
+ </edit>
+ </match>
+
+ <!-- We need to enable simulated oblique to for DejaVu Serif to ensure that we interpret
+ this property correctly in: platform/gtk/fonts/fontconfig-synthetic-oblique.html -->
+ <match target="font">
+ <test qual="any" name="family">
+ <string>DejaVu Serif</string>
+ </test>
+ <test name="slant">
+ <const>roman</const>
+ </test>
+ <test target="pattern" name="slant" compare="not_eq">
+ <const>roman</const>
+ </test>
+ <edit name="matrix" mode="assign">
+ <times>
+ <name>matrix</name>
+ <matrix><double>1</double><double>0.2</double>
+ <double>0</double><double>1</double>
+ </matrix>
+ </times>
+ </edit>
+ <edit name="slant" mode="assign">
+ <const>oblique</const>
+ </edit>
+ <edit name="embeddedbitmap" mode="assign">
+ <bool>false</bool>
+ </edit>
+ </match>
+
+ <!-- These fonts should be treated as identical by CSS font fallback. -->
+ <alias binding="same">
+ <family>FamilyStrongAliasedToFreeMono</family>
+ <accept>
+ <family>FreeMono</family>
+ </accept>
+ </alias>
+
+ <!-- These fonts should NOT be treated as identical by CSS font fallback. -->
+ <alias>
+ <family>FamilyWeakAliasedToFreeMono</family>
+ <accept>
+ <family>FreeMono</family>
+ </accept>
+ </alias>
+
+ <!-- If this font doesn't have a family name we are falling back. The fallback
+ font will certainly be one of the DejaVu fonts that we have in our
+ collection since they have a wide range of characters. Fontconfig might
+ choose DejaVu Sans or DejaVu Serif depending on the system, so we force
+ the use of DejaVu Sans in these situations to maintain consistency. -->
+ <match target="pattern">
+ <test qual="all" name="family" compare="eq">
+ <string></string>
+ </test>
+ <edit name="family" mode="append_last">
+ <string>DejaVu Sans</string>
+ </edit>
+ </match>
+
+ <config>
+ <!-- These are the default Unicode chars that are expected to be blank
+ in fonts. All other blank chars are assumed to be broken and won't
+ appear in the resulting charsets -->
+ <blank>
+ <int>0x0020</int> <!-- SPACE -->
+ <int>0x00A0</int> <!-- NO-BREAK SPACE -->
+ <int>0x00AD</int> <!-- SOFT HYPHEN -->
+ <int>0x034F</int> <!-- COMBINING GRAPHEME JOINER -->
+ <int>0x0600</int> <!-- ARABIC NUMBER SIGN -->
+ <int>0x0601</int> <!-- ARABIC SIGN SANAH -->
+ <int>0x0602</int> <!-- ARABIC FOOTNOTE MARKER -->
+ <int>0x0603</int> <!-- ARABIC SIGN SAFHA -->
+ <int>0x06DD</int> <!-- ARABIC END OF AYAH -->
+ <int>0x070F</int> <!-- SYRIAC ABBREVIATION MARK -->
+ <int>0x115F</int> <!-- HANGUL CHOSEONG FILLER -->
+ <int>0x1160</int> <!-- HANGUL JUNGSEONG FILLER -->
+ <int>0x1680</int> <!-- OGHAM SPACE MARK -->
+ <int>0x17B4</int> <!-- KHMER VOWEL INHERENT AQ -->
+ <int>0x17B5</int> <!-- KHMER VOWEL INHERENT AA -->
+ <int>0x180E</int> <!-- MONGOLIAN VOWEL SEPARATOR -->
+ <int>0x2000</int> <!-- EN QUAD -->
+ <int>0x2001</int> <!-- EM QUAD -->
+ <int>0x2002</int> <!-- EN SPACE -->
+ <int>0x2003</int> <!-- EM SPACE -->
+ <int>0x2004</int> <!-- THREE-PER-EM SPACE -->
+ <int>0x2005</int> <!-- FOUR-PER-EM SPACE -->
+ <int>0x2006</int> <!-- SIX-PER-EM SPACE -->
+ <int>0x2007</int> <!-- FIGURE SPACE -->
+ <int>0x2008</int> <!-- PUNCTUATION SPACE -->
+ <int>0x2009</int> <!-- THIN SPACE -->
+ <int>0x200A</int> <!-- HAIR SPACE -->
+ <int>0x200B</int> <!-- ZERO WIDTH SPACE -->
+ <int>0x200C</int> <!-- ZERO WIDTH NON-JOINER -->
+ <int>0x200D</int> <!-- ZERO WIDTH JOINER -->
+ <int>0x200E</int> <!-- LEFT-TO-RIGHT MARK -->
+ <int>0x200F</int> <!-- RIGHT-TO-LEFT MARK -->
+ <int>0x2028</int> <!-- LINE SEPARATOR -->
+ <int>0x2029</int> <!-- PARAGRAPH SEPARATOR -->
+ <int>0x202A</int> <!-- LEFT-TO-RIGHT EMBEDDING -->
+ <int>0x202B</int> <!-- RIGHT-TO-LEFT EMBEDDING -->
+ <int>0x202C</int> <!-- POP DIRECTIONAL FORMATTING -->
+ <int>0x202D</int> <!-- LEFT-TO-RIGHT override -->
+ <int>0x202E</int> <!-- RIGHT-TO-LEFT override -->
+ <int>0x202F</int> <!-- NARROW NO-BREAK SPACE -->
+ <int>0x205F</int> <!-- MEDIUM MATHEMATICAL SPACE -->
+ <int>0x2060</int> <!-- WORD JOINER -->
+ <int>0x2061</int> <!-- FUNCTION APPLICATION -->
+ <int>0x2062</int> <!-- INVISIBLE TIMES -->
+ <int>0x2063</int> <!-- INVISIBLE SEPARATOR -->
+ <int>0x206A</int> <!-- INHIBIT SYMMETRIC SWAPPING -->
+ <int>0x206B</int> <!-- ACTIVATE SYMMETRIC SWAPPING -->
+ <int>0x206C</int> <!-- INHIBIT ARABIC FORM SHAPING -->
+ <int>0x206D</int> <!-- ACTIVATE ARABIC FORM SHAPING -->
+ <int>0x206E</int> <!-- NATIONAL DIGIT SHAPES -->
+ <int>0x206F</int> <!-- NOMINAL DIGIT SHAPES -->
+ <int>0x3000</int> <!-- IDEOGRAPHIC SPACE -->
+ <int>0x3164</int> <!-- HANGUL FILLER -->
+ <int>0xFEFF</int> <!-- ZERO WIDTH NO-BREAK SPACE -->
+ <int>0xFFA0</int> <!-- HALFWIDTH HANGUL FILLER -->
+ <int>0xFFF9</int> <!-- INTERLINEAR ANNOTATION ANCHOR -->
+ <int>0xFFFA</int> <!-- INTERLINEAR ANNOTATION SEPARATOR -->
+ <int>0xFFFB</int> <!-- INTERLINEAR ANNOTATION TERMINATOR -->
+ </blank>
+ </config>
+</fontconfig>
diff --git a/Tools/WebKitTestRunner/gtk/main.cpp b/Tools/WebKitTestRunner/gtk/main.cpp
index d53c6248a..7947ce55c 100644
--- a/Tools/WebKitTestRunner/gtk/main.cpp
+++ b/Tools/WebKitTestRunner/gtk/main.cpp
@@ -26,12 +26,21 @@
#include "config.h"
#include "TestController.h"
+#include <WebKit/WKTextCheckerGtk.h>
#include <gtk/gtk.h>
+#include <wtf/glib/GRefPtr.h>
int main(int argc, char** argv)
{
gtk_init(&argc, &argv);
+
+ GRefPtr<GPtrArray> languages = adoptGRef(g_ptr_array_new());
+ g_ptr_array_add(languages.get(), const_cast<gpointer>(static_cast<const void*>("en_US")));
+ g_ptr_array_add(languages.get(), nullptr);
+ WKTextCheckerSetSpellCheckingLanguages(reinterpret_cast<const char* const*>(languages->pdata));
+
// Prefer the not installed web and plugin processes.
WTR::TestController controller(argc, const_cast<const char**>(argv));
+
return 0;
}
diff --git a/Tools/gtk/GNUmakefile.am b/Tools/gtk/GNUmakefile.am
deleted file mode 100644
index 61cff0134..000000000
--- a/Tools/gtk/GNUmakefile.am
+++ /dev/null
@@ -1,153 +0,0 @@
-EXTRA_DIST += \
- Tools/gtk/check-for-webkitdom-api-breaks \
- Tools/gtk/common.py \
- Tools/gtk/generate-feature-defines-files \
- Tools/gtk/generate-gtkdoc \
- Tools/gtk/generate-inspector-gresource-manifest.py \
- Tools/gtk/gtkdoc.py \
- Tools/gtk/webkitdom.py
-
-docs: docs-build.stamp
-.PHONY : docs
-DISTCLEANFILES += docs-build.stamp
-
-docs_build_dependencies = \
- Source/WebKit/gtk/docs/webkitenvironment.xml
-
-if ENABLE_WEBKIT1
-docs_build_dependencies += \
- libwebkitgtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \
- Source/WebKit/gtk/docs/webkitgtk-docs.sgml \
- Source/WebKit/gtk/docs/webkitgtk-sections.txt \
- gtkdoc-webkitgtk.cfg
-endif
-
-if ENABLE_WEBKIT2
-docs_build_dependencies += \
- libwebkit2gtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \
- Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml \
- Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt \
- gtkdoc-webkit2gtk.cfg
-endif
-
-docs_build_dependencies += \
- libGObjectDOMBindings.la \
- gtkdoc-webkitdom.cfg
-
-docs-build.stamp: $(docs_build_dependencies)
- CC=$(CC) $(PYTHON) $(srcdir)/Tools/gtk/generate-gtkdoc
- @touch docs-build.stamp
-
-clean-local: doc-clean-local
-doc-clean-local:
- @rm -f Documentation/webkitgtk/*~ Documentation/webkitgtk*.bak
- @rm -f Documentation/webkit2gtk/*~ Documentation/webkit2gtk*.bak
- @rm -f Documentation/webkitdomgtk/*~ Documentation/webkitdomgtk*.bak
-
-distclean-local: doc-distclean-local
-doc-distclean-local:
- @rm -rf Documentation
-maintainer-clean-local: doc-maintainer-clean-local
-doc-maintainer-clean-local: clean
- @rm -rf Documentation/webkitgtk Documentation/webkit2gtk Documentation/webkitdomgtk
- -@rmdir Documentation
-
-install-data-local:
-if ENABLE_WEBKIT1
- @installfiles=`echo ./Documentation/webkitgtk/html/*`; \
- if test "$$installfiles" = './Documentation/webkitgtk/html/*'; \
- then echo 1>&2 'No documentation to install' ; \
- else \
- DOC_MODULE_VERSION=`cat ./Documentation/webkitgtk/version.xml`; \
- if test -n "$(DOC_MODULE_VERSION)"; then \
- installdir="$(DESTDIR)$(HTML_DIR)/webkitgtk-$(DOC_MODULE_VERSION)"; \
- else \
- installdir="$(DESTDIR)$(HTML_DIR)/webkitgtk"; \
- fi; \
- $(mkinstalldirs) $${installdir} ; \
- for i in $$installfiles; do \
- echo ' $(INSTALL_DATA) '$$i ; \
- $(INSTALL_DATA) $$i $${installdir}; \
- done; \
- if test -n "$(DOC_MODULE_VERSION)"; then \
- mv -f $${installdir}/webkitgtk.devhelp2 \
- $${installdir}/webkitgtk-$(DOC_MODULE_VERSION).devhelp2; \
- fi; \
- fi
-endif
-if ENABLE_WEBKIT2
- @installfiles=`echo ./Documentation/webkit2gtk/html/*`; \
- if test "$$installfiles" = './Documentation/webkit2gtk/html/*'; \
- then echo 1>&2 'No documentation to install' ; \
- else \
- DOC_MODULE_VERSION=`cat ./Documentation/webkit2gtk/version.xml`; \
- if test -n "$(DOC_MODULE_VERSION)"; then \
- installdir="$(DESTDIR)$(HTML_DIR)/webkit2gtk-$(DOC_MODULE_VERSION)"; \
- else \
- installdir="$(DESTDIR)$(HTML_DIR)/webkit2gtk"; \
- fi; \
- $(mkinstalldirs) $${installdir} ; \
- for i in $$installfiles; do \
- echo ' $(INSTALL_DATA) '$$i ; \
- $(INSTALL_DATA) $$i $${installdir}; \
- done; \
- if test -n "$(DOC_MODULE_VERSION)"; then \
- mv -f $${installdir}/webkit2gtk.devhelp2 \
- $${installdir}/webkit2gtk-$(DOC_MODULE_VERSION).devhelp2; \
- fi; \
- fi
-endif
- @installfiles=`echo ./Documentation/webkitdomgtk/html/*`; \
- if test "$$installfiles" = './Documentation/webkitdomgtk/html/*'; \
- then echo 1>&2 'No documentation to install' ; \
- else \
- DOC_MODULE_VERSION=`cat ./Documentation/webkitdomgtk/version.xml`; \
- if test -n "$(DOC_MODULE_VERSION)"; then \
- installdir="$(DESTDIR)$(HTML_DIR)/webkitdomgtk-$(DOC_MODULE_VERSION)"; \
- else \
- installdir="$(DESTDIR)$(HTML_DIR)/webkitdomgtk"; \
- fi; \
- $(mkinstalldirs) $${installdir} ; \
- for i in $$installfiles; do \
- echo ' $(INSTALL_DATA) '$$i ; \
- $(INSTALL_DATA) $$i $${installdir}; \
- done; \
- if test -n "$(DOC_MODULE_VERSION)"; then \
- mv -f $${installdir}/webkitdomgtk.devhelp2 \
- $${installdir}/webkitdomgtk-$(DOC_MODULE_VERSION).devhelp2; \
- fi; \
- fi
-if ENABLE_GTK_DOC
- @$(AM_V_GEN) PKG_CONFIG=$(PKG_CONFIG) $(PYTHON) $(srcdir)/Tools/gtk/generate-gtkdoc --rebase --virtual-root=$${DESTDIR}
-endif
-
-uninstall-local:
-if ENABLE_WEBKIT1
- @DOC_MODULE_VERSION=`cat ./Documentation/webkitgtk/version.xml`; \
- if test -n "$(DOC_MODULE_VERSION)"; then \
- installdir="$(DESTDIR)$(HTML_DIR)/webkitgtk-$(DOC_MODULE_VERSION)"; \
- else \
- installdir="$(DESTDIR)$(HTML_DIR)/webkitgtk"; \
- fi; \
- rm -rf $${installdir}
-endif
-if ENABLE_WEBKIT2
- @DOC_MODULE_VERSION=`cat ./Documentation/webkit2gtk/version.xml`; \
- if test -n "$(DOC_MODULE_VERSION)"; then \
- installdir="$(DESTDIR)$(HTML_DIR)/webkit2gtk-$(DOC_MODULE_VERSION)"; \
- else \
- installdir="$(DESTDIR)$(HTML_DIR)/webkit2gtk"; \
- fi; \
- rm -rf $${installdir}
-endif
- @DOC_MODULE_VERSION=`cat ./Documentation/webkitdomgtk/version.xml`; \
- if test -n "$(DOC_MODULE_VERSION)"; then \
- installdir="$(DESTDIR)$(HTML_DIR)/webkitdomgtk-$(DOC_MODULE_VERSION)"; \
- else \
- installdir="$(DESTDIR)$(HTML_DIR)/webkitdomgtk"; \
- fi; \
- rm -rf $${installdir}
-if ENABLE_GTK_DOC
-noinst_DATA += docs-build.stamp
-endif
-
diff --git a/Tools/gtk/check-for-webkitdom-api-breaks b/Tools/gtk/check-for-webkitdom-api-breaks
index 2f4237b51..b2354f13b 100755
--- a/Tools/gtk/check-for-webkitdom-api-breaks
+++ b/Tools/gtk/check-for-webkitdom-api-breaks
@@ -16,7 +16,6 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-import argparse
import common
import os
import sys
@@ -33,13 +32,9 @@ def read_built_api():
def read_expected_api():
with open(EXPECTED_API_PATH) as file_handle:
- return set(file_handle.readlines())
+ return set([symbol.strip('\n').split('@', 1)[0] + '\n' for symbol in file_handle.readlines()])
-def write_expected_api(new_expected_api):
- with open(EXPECTED_API_PATH, 'w') as file_handle:
- file_handle.writelines(new_expected_api)
-
-def check_api(options, expected_api, built_api):
+def check_api(expected_api, built_api):
missing_api = expected_api.difference(built_api)
new_api = built_api.difference(expected_api)
@@ -57,22 +52,12 @@ def check_api(options, expected_api, built_api):
# DOM bindings API varies depending on the compilation options.
# So this shouldn't be made fatal until we figure out a way to handle it.
# See https://bugs.webkit.org/show_bug.cgi?id=121481
- sys.stderr.write("Re-add the missing API and rerun the %s.\n" % __file__)
return 0
if new_api:
- if options.reset_results:
- sys.stdout.write("Resetting expected API\n")
- write_expected_api(built_api)
- else:
- sys.stdout.write("API compatible changes found in GObject DOM bindings.\n")
- sys.stdout.write("To update the symbols file, run %s --reset-results.\n" % __file__)
+ sys.stdout.write("API compatible changes found in GObject DOM bindings.\n")
return 0
if __name__ == '__main__':
- parser = argparse.ArgumentParser(description='Detect API breakage in the WebKitGTK+ GObject DOM bindings.')
- parser.add_argument('--reset-results', action='store_true',
- help='When specified, rest the expected results file with the built results.')
- options = parser.parse_args()
- sys.exit(check_api(options, read_expected_api(), read_built_api()))
+ sys.exit(check_api(read_expected_api(), read_built_api()))
diff --git a/Tools/gtk/common.py b/Tools/gtk/common.py
index 02f8b6541..f53cc95aa 100644
--- a/Tools/gtk/common.py
+++ b/Tools/gtk/common.py
@@ -24,8 +24,7 @@ import sys
top_level_dir = None
build_dir = None
library_build_dir = None
-tests_library_build_dir = None
-is_cmake = None
+binary_build_dir = None
build_types = ('Release', 'Debug')
@@ -41,41 +40,18 @@ def set_build_types(new_build_types):
build_types = new_build_types
-def is_cmake_build():
- global is_cmake
- if is_cmake is None:
- is_cmake = os.path.exists(build_path('CMakeCache.txt'))
- return is_cmake
-
-
def library_build_path(*args):
global library_build_dir
if not library_build_dir:
- if is_cmake_build():
- library_build_dir = build_path('lib', *args)
- else:
- library_build_dir = build_path('.libs', *args)
+ library_build_dir = build_path('lib', *args)
return library_build_dir
-def tests_library_build_path(*args):
- if is_cmake_build():
- return library_build_path(*args)
-
- global tests_library_build_dir
- if not tests_library_build_dir:
- tests_library_build_dir = build_path('Libraries', *args)
- return tests_library_build_dir
-
-
def binary_build_path(*args):
- global library_build_dir
- if not library_build_dir:
- if is_cmake_build():
- library_build_dir = build_path('bin', *args)
- else:
- library_build_dir = build_path('Programs', *args)
- return library_build_dir
+ global binary_build_dir
+ if not binary_build_dir:
+ binary_build_dir = build_path('bin', *args)
+ return binary_build_dir
def get_build_path(fatal=True):
@@ -84,11 +60,7 @@ def get_build_path(fatal=True):
return build_dir
def is_valid_build_directory(path):
- return os.path.exists(os.path.join(path, 'GNUmakefile')) or \
- os.path.exists(os.path.join(path, 'Programs', 'GtkLauncher')) or \
- os.path.exists(os.path.join(path, 'Programs', 'MiniBrowser')) or \
- os.path.exists(os.path.join(path, 'CMakeCache.txt')) or \
- os.path.exists(os.path.join(path, 'bin/GtkLauncher')) or \
+ return os.path.exists(os.path.join(path, 'CMakeCache.txt')) or \
os.path.exists(os.path.join(path, 'bin/MiniBrowser'))
if len(sys.argv[1:]) > 1 and os.path.exists(sys.argv[-1]) and is_valid_build_directory(sys.argv[-1]):
@@ -144,16 +116,6 @@ def prefix_of_pkg_config_file(package):
return pkg_config_file_variable(package, 'prefix')
-def gtk_version_of_pkg_config_file(pkg_config_path):
- process = subprocess.Popen(['pkg-config', pkg_config_path, '--print-requires'],
- stdout=subprocess.PIPE)
- stdout = process.communicate()[0].decode("utf-8")
-
- if 'gtk+-3.0' in stdout:
- return 3
- return 2
-
-
def parse_output_lines(fd, parse_line_callback):
output = ''
read_set = [fd]
diff --git a/Tools/gtk/generate-feature-defines-files b/Tools/gtk/generate-feature-defines-files
deleted file mode 100755
index 17d52e65a..000000000
--- a/Tools/gtk/generate-feature-defines-files
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/bin/env python
-from __future__ import with_statement
-import os
-import re
-import sys
-
-def read_feature_defines_override(feature_defines):
- feature_defines_overriding_file = 'WebKitFeatureOverrides.txt'
- if not os.path.exists(feature_defines_overriding_file):
- return
-
- print("The following feature defines were overriden:")
- with open(feature_defines_overriding_file) as f:
- match_iter = re.findall(r"((?:ENABLE_)\w+)=(0|1)", f.read())
-
- for match in match_iter:
- feature = match[0]
- value = int(match[1])
-
- if feature in feature_defines and value != feature_defines[feature]:
- print("\t{0}: {1} => {2}".format(feature, feature_defines[feature], value))
- feature_defines[feature] = value
-
-def write_file_if_contents_changed(filename, contents):
- if os.path.exists(filename):
- with open(filename, 'r') as f:
- old_contents = f.read()
- if old_contents == contents:
- return
- with open(filename, 'w') as f:
- f.write(contents)
-
-def write_feature_defines_header(feature_defines):
- contents = ''
- for (feature, value) in feature_defines.items():
- contents += '#define {0} {1}\n'.format(feature, value)
- write_file_if_contents_changed("WebKitFeatures.h", contents)
-
-def write_flattened_feature_defines_file(feature_defines):
- contents = ''
- for (feature, value) in feature_defines.items():
- contents += '{0}={1}\n'.format(feature, value)
- write_file_if_contents_changed("WebKitFeatures.txt", contents)
-
-def generate_feature_defines_files(default_features):
- build_dir = os.getcwd()
- feature_defines = {}
-
- for feature_define in default_features:
- (feature, value) = feature_define.split("=")
- feature_defines[feature] = int(value)
-
- read_feature_defines_override(feature_defines)
- write_feature_defines_header(feature_defines)
- write_flattened_feature_defines_file(feature_defines)
-
-if __name__=='__main__':
- generate_feature_defines_files(sys.argv[1:])
diff --git a/Tools/gtk/generate-gtkdoc b/Tools/gtk/generate-gtkdoc
index 37eeee94c..7044d2ad8 100755
--- a/Tools/gtk/generate-gtkdoc
+++ b/Tools/gtk/generate-gtkdoc
@@ -19,6 +19,7 @@ from __future__ import print_function
from ConfigParser import SafeConfigParser
import argparse
+import codecs
import common
import glob
import gtkdoc
@@ -27,6 +28,9 @@ import os.path
import sys
import webkitdom
+sys.stdout = codecs.getwriter("utf-8")(sys.stdout)
+sys.stderr = codecs.getwriter("utf-8")(sys.stderr)
+
def configure_logging(verbose):
level = logging.DEBUG if verbose else logging.INFO
logger = logging.getLogger('gtkdoc')
@@ -39,16 +43,13 @@ def configure_logging(verbose):
else:
handler.setFormatter(logging.Formatter('%(message)s'))
-def get_gtkdoc_module_paths(gtk_version):
+def get_gtkdoc_module_paths(cross_reference_deps):
dependent_packages = {
'glib-2.0' : ['glib', 'gobject', 'gio'],
'libsoup-2.4' : ['libsoup-2.4'],
- 'gdk-pixbuf-2.0': ['gdk-pixbuf']
+ 'gdk-pixbuf-2.0': ['gdk-pixbuf'],
+ 'gtk+-3.0' : ['gtk3', 'gdk3']
}
- if gtk_version == 3:
- dependent_packages.update({'gtk+-3.0' : ['gtk3', 'gdk3']})
- else:
- dependent_packages.update({'gtk+-2.0' : ['gtk', 'gdk']})
paths = []
html_dir = os.path.join('share', 'gtk-doc', 'html')
@@ -58,9 +59,9 @@ def get_gtkdoc_module_paths(gtk_version):
continue
for module in modules:
paths.append(os.path.join(prefix, html_dir, module))
- # This technically is not needed for the GObject DOM bindings documentation itself,
- # but adding it doesn't hurt and allows us to avoid a check here.
- paths.append(common.build_path('Documentation', 'webkitdomgtk', 'html'))
+
+ for local_dep in cross_reference_deps:
+ paths.append(common.build_path('Documentation', local_dep, 'html'))
return paths
def print_missing_api(generator):
@@ -91,13 +92,13 @@ def files_to_ignore(source_dirs, headers_with_gtkdoc):
if os.path.splitext(file)[1] not in ['.h', '.c', '.cpp', '.cc']:
return False # These files are ignored anyway.
if not os.path.isfile(file):
- return False
+ return True
return os.path.abspath(file) not in implementation_files
all_files = sum([[os.path.join(dir, file) for file in os.listdir(dir)] for dir in source_dirs], [])
return filter(file_should_be_ignored, all_files)
-def get_generator_for_config(config_file, virtual_root):
+def get_generator_for_config(config_file, virtual_root, cross_reference_deps = []):
if not os.path.isfile(config_file):
return None
@@ -105,7 +106,6 @@ def get_generator_for_config(config_file, virtual_root):
config.read(config_file)
module_name = config.sections()[0]
pkgconfig_file = config.get(module_name, 'pkgconfig_file')
- gtk_version = common.gtk_version_of_pkg_config_file(pkgconfig_file)
if not os.path.isfile(pkgconfig_file):
return None
@@ -121,10 +121,11 @@ def get_generator_for_config(config_file, virtual_root):
'namespace': config.get(module_name, 'namespace'),
'doc_dir': config.get(module_name, 'doc_dir'),
'output_dir': common.build_path('Documentation', module_name),
+ 'main_sgml_file': config.get(module_name, 'main_sgml_file'),
'source_dirs': source_dirs,
'headers': headers,
'cflags': " ".join(config.get(module_name, 'cflags').split()),
- 'cross_reference_deps': get_gtkdoc_module_paths(gtk_version),
+ 'cross_reference_deps': get_gtkdoc_module_paths(cross_reference_deps),
'ignored_files': files_to_ignore(source_dirs, headers),
})
@@ -142,16 +143,12 @@ def rebase_doc(generator):
except Exception:
print("Rebase did not happen, likely no documentation is present.")
-def generate_documentation_for_config(config_file):
- generator = get_generator_for_config(config_file, arguments.virtual_root)
- if not generator:
- print("{0} does not exist! Skipping that documentation.".format(os.path.basename(config_file)))
- return
-
+def generate_documentation(generator):
if not arguments.rebase:
return generate_doc(generator, arguments.skip_html)
rebase_doc(generator)
+ return False
def prepare_environment_for_gtkdoc_generation():
# We need to add the JavaScriptCore build directory to the PKG_CONFIG_PATH
@@ -174,10 +171,6 @@ def prepare_environment_for_gtkdoc_generation():
cflags += ' -Wno-cast-align'
os.environ['CFLAGS'] = cflags
- # Clang can be noisy, throwing unnecessary warnings for unused arguments.
- if os.environ.get('CC') == "clang":
- os.environ['CFLAGS'] += ' -Qunused-arguments'
-
# Paths from the GNUmakefile generated configuration files are relative to the build directory.
os.chdir(common.build_path())
@@ -200,10 +193,19 @@ if __name__ == "__main__":
prepare_environment_for_gtkdoc_generation()
- webkitdom.write_doc_files()
- generate_documentation_for_config(common.build_path('gtkdoc-webkitdom.cfg'))
-
- saw_webkit1_warnings = generate_documentation_for_config(common.build_path('gtkdoc-webkitgtk.cfg'))
- saw_webkit2_warnings = generate_documentation_for_config(common.build_path('gtkdoc-webkit2gtk.cfg'))
-
- sys.exit(saw_webkit1_warnings or saw_webkit2_warnings)
+ webkitdom_generator = get_generator_for_config(common.build_path('gtkdoc-webkitdom.cfg'), arguments.virtual_root)
+ if not webkitdom_generator:
+ print("gtkdoc-webkitdom.cfg does not exist! Skipping that documentation")
+ sys.exit(1)
+ webkitdom.write_doc_files(webkitdom_generator.module_name)
+ saw_warnings = generate_documentation(webkitdom_generator)
+ if saw_warnings:
+ sys.exit(saw_warnings)
+
+ webkit2_generator = get_generator_for_config(common.build_path('gtkdoc-webkit2gtk.cfg'), arguments.virtual_root, [webkitdom_generator.module_name])
+ if not webkit2_generator:
+ print("gtkdoc-webkit2gtk.cfg does not exist! Skipping that documentation")
+ sys.exit(1)
+ saw_warnings = generate_documentation(webkit2_generator)
+
+ sys.exit(saw_warnings)
diff --git a/Tools/gtk/generate-inspector-gresource-manifest.py b/Tools/gtk/generate-inspector-gresource-manifest.py
index d319eba0c..03060cfa2 100755
--- a/Tools/gtk/generate-inspector-gresource-manifest.py
+++ b/Tools/gtk/generate-inspector-gresource-manifest.py
@@ -33,8 +33,8 @@ def get_filenames(args):
base_dir_index = filename.rfind(BASE_DIR)
if base_dir_index != -1:
name = filename[base_dir_index + len(BASE_DIR):]
- # The result should use forward slashes, thus make sure any os-specific
- # separator, added by the glob.glob() call, is properly replaced
+ # The result should use forward slashes, thus make sure any os-specific
+ # separator, added by the glob.glob() call, is properly replaced
if os.sep != '/':
name = name.replace(os.sep, '/')
filenames.append(name)
@@ -55,13 +55,13 @@ if __name__ == "__main__":
args = parser.parse_args(sys.argv[1:])
args.output.write(\
-"""<?xml version=1.0 encoding=UTF-8?>
-<gresources>
- <gresource prefix="/org/webkitgtk/inspector">
+ """<?xml version=1.0 encoding=UTF-8?>
+ <gresources>
+ <gresource prefix="/org/webkitgtk/inspector">
""")
for filename in get_filenames(args.filenames):
- line = ' <file'
+ line = ' <file'
if is_compressible(filename):
line += ' compressed="true"'
if 'Images/gtk/' in filename:
@@ -71,7 +71,7 @@ if __name__ == "__main__":
args.output.write(line)
args.output.write(\
-""" </gresource>
+ """ </gresource>
</gresources>
""")
diff --git a/Tools/gtk/gtkdoc.py b/Tools/gtk/gtkdoc.py
index 947c1e8c7..4c8237b0e 100644
--- a/Tools/gtk/gtkdoc.py
+++ b/Tools/gtk/gtkdoc.py
@@ -141,7 +141,6 @@ class GTKDoc(object):
self._write_version_xml()
self._run_gtkdoc_scan()
self._run_gtkdoc_scangobj()
- self._run_gtkdoc_mktmpl()
self._run_gtkdoc_mkdb()
if not html:
@@ -195,9 +194,15 @@ class GTKDoc(object):
if print_output:
if stdout:
- sys.stdout.write(stdout)
+ try:
+ sys.stdout.write(stdout.encode("utf-8"))
+ except UnicodeDecodeError:
+ sys.stdout.write(stdout)
if stderr:
- sys.stderr.write(stderr)
+ try:
+ sys.stderr.write(stderr.encode("utf-8"))
+ except UnicodeDecodeError:
+ sys.stderr.write(stderr)
if process.returncode != 0:
raise Exception('%s produced a non-zero return code %i'
@@ -307,7 +312,11 @@ class GTKDoc(object):
env = os.environ
ldflags = self.ldflags
if self.library_path:
- ldflags = ' "-L%s" ' % self.library_path + ldflags
+ additional_ldflags = ''
+ for arg in env.get('LDFLAGS', '').split(' '):
+ if arg.startswith('-L'):
+ additional_ldflags = '%s %s' % (additional_ldflags, arg)
+ ldflags = ' "-L%s" %s ' % (self.library_path, additional_ldflags) + ldflags
current_ld_library_path = env.get('LD_LIBRARY_PATH')
if current_ld_library_path:
env['RUN'] = 'LD_LIBRARY_PATH="%s:%s" ' % (self.library_path, current_ld_library_path)
@@ -328,10 +337,6 @@ class GTKDoc(object):
self._run_command(['gtkdoc-scangobj', '--module=%s' % self.module_name],
env=env, cwd=self.output_dir)
- def _run_gtkdoc_mktmpl(self):
- args = ['gtkdoc-mktmpl', '--module=%s' % self.module_name]
- self._run_command(args, cwd=self.output_dir)
-
def _run_gtkdoc_mkdb(self):
sgml_file = os.path.join(self.output_dir, self.main_sgml_file)
self._raise_exception_if_file_inaccessible(sgml_file)
diff --git a/Tools/gtk/install-dependencies b/Tools/gtk/install-dependencies
new file mode 100755
index 000000000..cb07f51b1
--- /dev/null
+++ b/Tools/gtk/install-dependencies
@@ -0,0 +1,436 @@
+#!/bin/bash
+
+# This script needs to be run with root rights.
+if [ $UID -ne 0 ]; then
+ sudo $0
+ exit 0
+fi
+
+function printNotSupportedMessageAndExit() {
+ echo
+ echo "Currently this script only works for distributions supporting apt-get and yum."
+ echo "Please add support for your distribution: http://webkit.org/b/110693"
+ echo
+ exit 1
+}
+
+function checkInstaller {
+ # apt-get - Debian based distributions
+ apt-get --version &> /dev/null
+ if [ $? -eq 0 ]; then
+ installDependenciesWithApt
+ exit 0
+ fi
+
+ # dnf - Fedora
+ dnf --version &> /dev/null
+ if [ $? -eq 0 ]; then
+ installDependenciesWithDnf
+ exit 0
+ fi
+
+ # pacman - Arch Linux
+ # pacman --version and pacman --help both return non-0
+ pacman -Ss &> /dev/null
+ if [ $? -eq 0 ]; then
+ installDependenciesWithPacman
+ exit 0
+ fi
+
+ if [ `uname` -eq "Darwin" ]; then
+ installDependenciesWithBrew
+ exit 0
+ fi
+
+ printNotSupportedMessageAndExit
+}
+
+function installDependenciesWithBrew {
+ brew &> /dev/null
+ if [ $? -gt 1 ]; then
+ echo "Please install HomeBrew. Instructions on http://brew.sh"
+ exit 1
+ fi
+
+ brew install autoconf \
+ automake \
+ bison \
+ cmake \
+ enchant \
+ flex \
+ gettext \
+ gobject-introspection \
+ icu4c \
+ intltool \
+ itstool \
+ libcroco \
+ libgcrypt \
+ libgpg-error \
+ libtiff \
+ libtool \
+ ninja \
+ pango \
+ pkg-config \
+ sqlite \
+ webp \
+ xz
+}
+
+function installDependenciesWithApt {
+ # These are dependencies necessary for building WebKitGTK+.
+ packages=" \
+ autoconf \
+ automake \
+ autopoint \
+ autotools-dev \
+ bison \
+ cmake \
+ flex \
+ gawk \
+ gnome-common \
+ gperf \
+ gtk-doc-tools \
+ intltool \
+ itstool \
+ libatk1.0-dev \
+ libedit-dev \
+ libenchant-dev \
+ libfaad-dev \
+ libgeoclue-dev \
+ libgirepository1.0-dev \
+ libgl1-mesa-dev \
+ libgl1-mesa-glx \
+ libgnutls28-dev \
+ libgtk2.0-dev \
+ libgtk-3-dev \
+ libgudev-1.0-dev \
+ libharfbuzz-dev \
+ libhyphen-dev \
+ libicu-dev \
+ libjpeg-dev \
+ libmpg123-dev \
+ libnotify-dev \
+ libopus-dev \
+ liborc-0.4-dev \
+ libpango1.0-dev \
+ libpng12-dev \
+ libpulse-dev \
+ librsvg2-dev \
+ libsecret-1-dev \
+ libsoup2.4-dev \
+ libsqlite3-dev \
+ libtheora-dev \
+ libtool \
+ libvorbis-dev \
+ libwebp-dev \
+ libxcomposite-dev \
+ libxslt1-dev \
+ libxt-dev \
+ libxtst-dev \
+ libwayland-dev \
+ ninja-build \
+ ruby \
+ xfonts-utils"
+
+ # These are dependencies necessary for running tests.
+ packages="$packages \
+ apache2 \
+ curl \
+ dbus-x11 \
+ libapache2-mod-bw \
+ libapache2-mod-php5 \
+ libgpg-error-dev \
+ pulseaudio-utils \
+ python-gi \
+ ruby \
+ ruby-json \
+ ruby-highline \
+ xvfb"
+
+ # These are dependencies necessary for building the jhbuild.
+ packages="$packages \
+ git \
+ gobject-introspection \
+ icon-naming-utils \
+ libcroco3-dev \
+ libegl1-mesa-dev \
+ libepoxy-dev \
+ libgcrypt11-dev \
+ libgpg-error-dev \
+ libjson-glib-dev \
+ liborc-0.4-dev \
+ libp11-kit-dev \
+ libpciaccess-dev \
+ libssl-dev \
+ libtiff5-dev \
+ libv4l-dev \
+ libxcb-xfixes0-dev \
+ libxfont-dev \
+ libxkbfile-dev \
+ libtool-bin \
+ llvm \
+ llvm-dev \
+ python-dev \
+ ragel \
+ x11proto-bigreqs-dev \
+ x11proto-composite-dev \
+ x11proto-gl-dev \
+ x11proto-input-dev \
+ x11proto-randr-dev \
+ x11proto-resource-dev \
+ x11proto-scrnsaver-dev \
+ x11proto-video-dev \
+ x11proto-xcmisc-dev \
+ x11proto-xf86dri-dev \
+ xfonts-utils \
+ xtrans-dev \
+ xutils-dev"
+
+ # These are dependencies necessary for using webkit-patch
+ packages="$packages \
+ git-svn \
+ subversion"
+
+ apt-get install $packages
+}
+
+function installDependenciesWithPacman {
+ # These are dependencies necessary for building WebKitGTK+.
+ packages=" \
+ autoconf \
+ automake \
+ bison \
+ cmake \
+ libedit \
+ file \
+ findutils \
+ flex \
+ gawk \
+ gcc \
+ gettext \
+ gnome-common \
+ gperf \
+ grep \
+ groff \
+ gzip \
+ hyphen \
+ libtool \
+ m4 \
+ make \
+ patch \
+ pkg-config \
+ sed \
+ texinfo \
+ util-linux \
+ which \
+ gtk-doc \
+ intltool \
+ itstool \
+ atk \
+ enchant \
+ faad2 \
+ geoclue \
+ gobject-introspection \
+ mesa \
+ mesa-libgl \
+ gnutls \
+ gtk2 \
+ gtk3 \
+ libsystemd \
+ harfbuzz \
+ harfbuzz-icu \
+ icu \
+ libjpeg-turbo \
+ mpg123 \
+ opus \
+ pango \
+ libnotify \
+ libpng \
+ libpulse \
+ librsvg \
+ libsecret \
+ libsoup \
+ sqlite \
+ libtheora \
+ libtool \
+ libvorbis \
+ libwebp \
+ libxcomposite \
+ libxslt \
+ libxt \
+ libxtst \
+ ninja \
+ ruby \
+ xorg-font-utils \
+ orc \
+ wayland"
+
+ # These are dependencies necessary for running tests.
+ # Note: apache-mod_bw is available in the AUR, but the main repos
+ # could not find ruby-json
+ packages="$packages \
+ apache \
+ curl \
+ hunspell \
+ hunspell-en \
+ php-apache \
+ libgpg-error \
+ pulseaudio \
+ python-gobject \
+ ruby \
+ ruby-highline \
+ xorg-server-xvfb"
+
+ # These are dependencies necessary for building the jhbuild.
+ # Note: Could not find libegl-mesa
+ packages="$packages \
+ git \
+ gobject-introspection \
+ icon-naming-utils \
+ libcroco \
+ libepoxy \
+ libgcrypt \
+ libgpg-error \
+ p11-kit \
+ libpciaccess \
+ libtiff \
+ libxfixes \
+ libxfont \
+ libxkbfile \
+ llvm \
+ python2 \
+ python2-lxml \
+ ragel \
+ bigreqsproto \
+ compositeproto \
+ glproto \
+ inputproto \
+ randrproto \
+ resourceproto \
+ scrnsaverproto \
+ videoproto \
+ xcmiscproto \
+ xf86driproto \
+ xorg-font-utils \
+ xorg-util-macros \
+ xtrans \
+ xorg-utils"
+
+ # These are dependencies necessary for using webkit-patch
+ packages="$packages \
+ svn"
+ pacman -S --needed $packages
+
+ echo "You will also need to follow the instructions on the Arch Wiki to make"
+ echo "'python' call python2 in the webkit folder"
+ echo "https://wiki.archlinux.org/index.php/Python#Dealing_with_version_problem_in_build_scripts"
+}
+
+function installDependenciesWithDnf {
+ # These are dependencies necessary for building WebKitGTK+.
+ packages=" \
+ atk-devel \
+ autoconf \
+ automake \
+ bison \
+ cairo-devel \
+ cmake \
+ enchant-devel \
+ flex \
+ fontconfig-devel \
+ freetype-devel \
+ gcc-c++ \
+ geoclue2-devel \
+ gettext-devel \
+ gobject-introspection-devel \
+ gperf \
+ gstreamer1-devel \
+ gstreamer1-plugins-base-devel \
+ gtk-doc \
+ gtk2-devel \
+ gtk3-devel \
+ harfbuzz-devel \
+ hyphen-devel \
+ json-glib-devel \
+ libXt-devel \
+ libXtst-devel \
+ libedit-devel \
+ libgudev1-devel \
+ libicu-devel \
+ libjpeg-turbo-devel \
+ libnotify-devel \
+ libpng-devel \
+ libsecret-devel \
+ libsoup-devel \
+ libv4l-devel \
+ libwebp-devel \
+ libwayland-client-devel \
+ libwayland-server-devel \
+ libxslt-devel \
+ llvm \
+ llvm-devel \
+ llvm-static \
+ mesa-libGL-devel \
+ ninja-build \
+ openssl-devel \
+ pcre-devel \
+ perl-Switch \
+ perl-version \
+ pulseaudio-libs-devel \
+ python-devel \
+ orc-devel \
+ ruby \
+ sqlite-devel"
+
+ # These are dependencies necessary for running tests.
+ packages="$packages \
+ curl \
+ dbus-x11 \
+ hunspell-en \
+ httpd \
+ libgpg-error-devel \
+ mod_bw \
+ mod_ssl \
+ perl-CGI \
+ php \
+ pulseaudio-utils \
+ pygobject3-base \
+ ruby \
+ rubygem-json \
+ rubygem-highline \
+ xorg-x11-server-Xvfb"
+
+ # These are dependencies necessary for building the jhbuild.
+ packages="$packages \
+ docbook-utils \
+ docbook-utils-pdf \
+ git \
+ gobject-introspection \
+ icon-naming-utils \
+ itstool \
+ libXfont-devel \
+ libcroco-devel \
+ libepoxy-devel \
+ libgcrypt-devel \
+ libgpg-error-devel \
+ libp11-devel \
+ libpciaccess-devel \
+ libtiff-devel \
+ libxkbfile-devel \
+ mesa-libEGL-devel \
+ ragel \
+ xorg-x11-font-utils \
+ xorg-x11-proto-devel \
+ xorg-x11-util-macros \
+ xorg-x11-xtrans-devel"
+
+ # These are dependencies necessary for using webkit-patch
+ packages="$packages
+ git-svn \
+ subversion"
+
+ dnf install $packages
+}
+
+checkInstaller
+
diff --git a/Tools/gtk/jhbuild-webrtc.modules b/Tools/gtk/jhbuild-webrtc.modules
new file mode 100644
index 000000000..2ca5155dd
--- /dev/null
+++ b/Tools/gtk/jhbuild-webrtc.modules
@@ -0,0 +1,132 @@
+<?xml version="1.0"?>
+<!DOCTYPE moduleset SYSTEM "moduleset.dtd">
+<?xml-stylesheet type="text/xsl" href="moduleset.xsl"?>
+<moduleset>
+
+ <repository type="git" name="github.com"
+ href="https://github.com"/>
+ <repository type="tarball" name="github-tarball"
+ href="https://github.com/"/>
+ <repository type="git" name="freedesktop-git"
+ href="http://anongit.freedesktop.org/git"/>
+
+ <autotools id="libsrtp" autogen-sh="configure">
+ <branch module="cisco/libsrtp/archive/v${version}.tar.gz" version="1.5.2"
+ checkoutdir="libsrtp-${version}"
+ repo="github-tarball"
+ hash="sha256:86e1efe353397c0751f6bdd709794143bd1b76494412860f16ff2b6d9c304eda"
+ md5sum="2309aa6027992810a4285b042c71e644">
+ </branch>
+ </autotools>
+
+ <autotools id="openh264" supports-non-srcdir-builds="no" autogen-sh="pseudo-configure">
+ <branch module="cisco/openh264/archive/v1.4.0.tar.gz" version="1.4.0"
+ checkoutdir="openh264-1.4.0"
+ repo="github-tarball">
+ <patch file="openh264-configure.patch" strip="0"/>
+ </branch>
+ </autotools>
+
+ <autotools id="gstreamer" autogenargs="--disable-gtk-doc">
+ <if condition-set="macos">
+ <autogenargs value="--disable-introspection"/>
+ <makeargs value="CFLAGS+=-Wno-error"/>
+ </if>
+
+ <dependencies>
+ <dep package="orc"/>
+ </dependencies>
+ <branch repo="freedesktop-git" module="gstreamer/gstreamer" version="1.7" checkoutdir="gstreamer" tag="61a8c946acb077959dfec78fc6393a5bea17a260"/>
+ </autotools>
+
+ <autotools id="gst-plugins-base"
+ autogen-sh="autogen.sh"
+ autogenargs="--disable-examples --disable-gtk-doc">
+ <if condition-set="macos">
+ <autogenargs value="--disable-introspection"/>
+ <makeargs value="CFLAGS+=-Wno-error"/>
+ </if>
+ <dependencies>
+ <dep package="gstreamer"/>
+ <dep package="orc"/>
+ </dependencies>
+ <branch repo="freedesktop-git" module="gstreamer/gst-plugins-base" version="1.7" checkoutdir="gst-plugins-base" tag="5f79ccb420d6b270d108892f1c7e3dedbd64b57a"/>
+ </autotools>
+
+ <autotools id="gst-plugins-good" autogenargs="--disable-examples --disable-soup --disable-gtk-doc">
+ <if condition-set="macos">
+ <autogenargs value="--disable-introspection"/>
+ <makeargs value="CFLAGS+=-Wno-error OBJCFLAGS+=-Wno-error"/>
+ </if>
+ <dependencies>
+ <dep package="gst-plugins-base"/>
+ <dep package="libvpx"/>
+ </dependencies>
+
+ <branch repo="freedesktop-git" module="gstreamer/gst-plugins-good" version="1.7" checkoutdir="gst-plugins-good" tag="0d4e3847f0c9106ed345f0316e4954f82332e250"/>
+ </autotools>
+
+ <autotools id="gst-plugins-bad" autogenargs="--disable-examples --disable-gtk-doc --enable-openh264 --enable-opus --enable-srtp -- PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$JHBUILD_PREFIX/lib/pkgconfig">
+ <makeargs value="CFLAGS+=-Wno-error CXXFLAGS+=-Wno-error OBJCFLAGS+=-Wno-error"/>
+ <if condition-set="macos">
+ <autogenargs value="--disable-introspection"/>
+ </if>
+ <dependencies>
+ <dep package="gst-plugins-base"/>
+ <dep package="libsrtp"/>
+ <dep package="openh264"/>
+ </dependencies>
+
+ <branch repo="freedesktop-git" module="gstreamer/gst-plugins-bad" version="1.7" checkoutdir="gst-plugins-bad" tag="3d5a1ccbf4e5b036164a02c6bd6b0b0ddab19880"/>
+ </autotools>
+
+ <autotools id="gst-libav" autogenargs="--with-libav-extra-configure='--disable-yasm' --disable-gtk-doc">
+ <if condition-set="macos">
+ <makeargs value="CFLAGS+=-Wno-error"/>
+ </if>
+ <dependencies>
+ <dep package="gst-plugins-base"/>
+ </dependencies>
+
+ <branch repo="freedesktop-git" module="gstreamer/gst-libav" version="1.5" checkoutdir="gst-libav" tag="1.5.2"/>
+ </autotools>
+
+ <autotools id="libusrsctp" supports-non-srcdir-builds="no" autogen-sh="./bootstrap; ./configure --disable-warnings-as-errors">
+ <branch repo="github.com" module="sctplab/usrsctp.git" checkoutdir="usrsctp" tag="c53d43ee76673ee281806497eb43750c239c145f"/>
+ </autotools>
+
+ <autotools id="gst-plugins-openwebrtc" supports-parallel-builds="no" supports-non-srcdir-builds="no" autogen-sh="./autogen.sh; ./configure">
+ <if condition-set="macos">
+ <makeargs value="CFLAGS+=-Wno-error"/>
+ </if>
+ <dependencies>
+ <dep package="gst-plugins-base"/>
+ <dep package="libusrsctp"/>
+ </dependencies>
+ <branch repo="github.com" module="EricssonResearch/openwebrtc-gst-plugins.git" checkoutdir="gst-plugins-openwebrtc" tag="5eb92d7e58a5aec82034d1a6d3f5ef66501172b7"/>
+ </autotools>
+
+ <autotools id="libnice" supports-non-srcdir-builds="no">
+ <dependencies>
+ <dep package="gstreamer"/>
+ </dependencies>
+ <branch repo="freedesktop-git" module="libnice/libnice.git" tag="0.1.13" checkoutdir="libnice"/>
+ </autotools>
+
+ <autotools id="libvpx" supports-non-srcdir-builds="no"
+ autogen-template="./configure --prefix=%(prefix)s --enable-shared --enable-pic --as=yasm --disable-unit-tests ">
+ <branch repo="github.com" module="webmproject/libvpx.git" checkoutdir="libvpx" tag="v1.4.0"/>
+ </autotools>
+
+ <autotools id="openwebrtc" autogenargs="--enable-bridge=no --enable-owr-gst=yes">
+ <if condition-set="macos">
+ <makeargs value="CFLAGS+=-Wno-error"/>
+ </if>
+ <dependencies>
+ <dep package="gst-plugins-openwebrtc"/>
+ <dep package="libnice"/>
+ </dependencies>
+ <branch repo="github.com" module="EricssonResearch/openwebrtc.git" checkoutdir="openwebrtc" tag="f511ea1fa79a33fa3d52bfd1c0969c28084aeb35"/>
+ </autotools>
+
+</moduleset>
diff --git a/Tools/gtk/jhbuild.modules b/Tools/gtk/jhbuild.modules
new file mode 100644
index 000000000..41331b0ec
--- /dev/null
+++ b/Tools/gtk/jhbuild.modules
@@ -0,0 +1,516 @@
+<?xml version="1.0"?>
+<!DOCTYPE moduleset SYSTEM "moduleset.dtd">
+<?xml-stylesheet type="text/xsl" href="moduleset.xsl"?>
+<moduleset>
+
+ <metamodule id="webkitgtk-testing-dependencies">
+ <dependencies>
+ <dep package="cairo"/>
+ <dep package="fonts"/>
+ <dep package="dicts"/>
+ <dep package="fontconfig"/>
+ <dep package="freetype6"/>
+ <dep package="harfbuzz"/>
+ <dep package="libxml2"/>
+ <dep package="gdk-pixbuf"/>
+ <dep package="gtk+"/>
+ <dep package="glib"/>
+ <dep package="glib-networking"/>
+ <dep package="gnome-icon-theme"/>
+ <dep package="gnome-icon-theme-symbolic"/>
+ <dep package="gnome-themes-standard"/>
+ <dep package="gtk-doc"/>
+ <dep package="libsoup"/>
+ <dep package="atk"/>
+ <dep package="gstreamer"/>
+ <dep package="gst-plugins-base"/>
+ <dep package="gst-plugins-good"/>
+ <dep package="gst-plugins-bad"/>
+ <dep package="gst-libav"/>
+ <dep package="openwebrtc"/>
+ <dep package="llvm"/>
+ <dep package="shared-mime-info"/>
+ <if condition-set="linux">
+ <dep package="xserver"/>
+ <dep package="mesa"/>
+ <dep package="libseccomp"/>
+ <dep package="at-spi2-core"/>
+ <dep package="at-spi2-atk"/>
+ </if>
+ <if condition-set="macos">
+ <dep package="gsettings-desktop-schemas"/>
+ </if>
+ </dependencies>
+ </metamodule>
+
+ <!-- Please use http/https to access repositories to be friendly to users stuck behind firewalls. -->
+ <repository type="git" name="github.com"
+ href="https://github.com"/>
+ <repository type="tarball" name="sourceware.org-mirror"
+ href="http://mirrors.kernel.org/sources.redhat.com/"/>
+ <repository type="tarball" name="ftp.gnome.org"
+ href="http://ftp.gnome.org"/>
+ <repository type="git" name="git.gnome.org"
+ href="https://git.gnome.org/browse/"/>
+ <repository type="tarball" name="cairographics.org"
+ href="http://cairographics.org"/>
+ <repository type="tarball" name="freedesktop.org"
+ href="http://www.freedesktop.org"/>
+ <repository type="tarball" name="xorg"
+ href="http://xorg.freedesktop.org"/>
+ <repository type="tarball" name="xmlsoft.org"
+ href="http://xmlsoft.org"/>
+ <repository type="tarball" name="gstreamer"
+ href="http://gstreamer.freedesktop.org/src/"/>
+ <repository type="tarball" name="savannah.gnu.org"
+ href="http://download.savannah.gnu.org/releases/"/>
+ <repository type="git" name="freedesktop-git"
+ href="http://anongit.freedesktop.org/git"/>
+ <repository type="tarball" name="people.freedesktop.org"
+ href="http://people.freedesktop.org"/>
+ <repository type="tarball" name="llvm.org"
+ href="http://llvm.org"/>
+
+ <autotools id="cairo">
+ <if condition-set="linux">
+ <autogenargs value="--enable-gl=yes --enable-egl=yes --enable-glx=yes"/>
+ </if>
+ <if condition-set="macos">
+ <autogenargs value="ac_cv_func_rsvg_pixbuf_from_file=no --disable-lto"/>
+ </if>
+ <dependencies>
+ <dep package="fontconfig"/>
+ <dep package="pixman"/>
+ <dep package="glib"/>
+ </dependencies>
+ <branch module="releases/cairo-1.14.2.tar.xz" version="1.14.2"
+ repo="cairographics.org"
+ hash="sha1:c8da68aa66ca0855b5d0ff552766d3e8679e1d24"/>
+ </autotools>
+
+ <!-- FIXME: Pixman 0.32.6 isn't buildable with Clang, but disable-mmx option fixes
+ the build. This workaround can be removed once the original bug is fixed.
+ Details can be found here: https://bugs.webkit.org/show_bug.cgi?id=151441 -->
+ <autotools id="pixman" autogen-sh="configure"
+ autogenargs="--enable-gtk=no --disable-mmx">
+ <branch module="releases/pixman-0.32.6.tar.gz" version="0.32.6"
+ repo="cairographics.org"
+ hash="sha256:3dfed13b8060eadabf0a4945c7045b7793cc7e3e910e748a8bb0f0dc3e794904"
+ md5sum="3a30859719a41bd0f5cccffbfefdd4c2">
+ </branch>
+ </autotools>
+
+ <autotools id="fonts" supports-non-srcdir-builds="no"
+ skip-autogen="true">
+ <branch repo="github.com" module="mrobinson/webkitgtk-test-fonts.git" checkoutdir="webkitgtk-test-fonts" tag="0.0.5"/>
+ </autotools>
+
+ <autotools id="dicts" supports-non-srcdir-builds="no"
+ skip-autogen="true">
+ <branch repo="github.com" module="mrobinson/webkitgtk-test-dicts.git" checkoutdir="webkitgtk-test-dicts" tag="0.0.1"/>
+ </autotools>
+
+ <autotools id="freetype6" autogen-sh="configure">
+ <branch module="freetype/freetype-2.4.11.tar.bz2" version="2.4.11"
+ repo="savannah.gnu.org"
+ hash="sha256:ef9d0bcb64647d9e5125dc7534d7ca371c98310fec87677c410f397f71ffbe3f"
+ md5sum="b93435488942486c8d0ca22e8f768034">
+ <patch file="freetype6-2.4.11-truetype-font-height-fix.patch" strip="1"/>
+ </branch>
+ </autotools>
+
+ <autotools id="harfbuzz" autogen-sh="configure">
+ <branch module="software/harfbuzz/release/harfbuzz-0.9.35.tar.bz2"
+ version="0.9.35"
+ checkoutdir="harfbuzz-0.9.35"
+ repo="freedesktop.org"
+ hash="sha256:0aa1a8aba6f502321cf6fef3c9d2c73dde48389c5ed1d3615a7691944c2a06ed"
+ md5sum="531ee8650626ecddcd90b2a4637e31d4">
+ </branch>
+ </autotools>
+
+ <autotools id="libffi" autogen-sh="configure">
+ <branch module="libffi/libffi-3.1.tar.gz" version="3.1"
+ repo="sourceware.org-mirror"
+ hash="sha256:97feeeadca5e21870fa4433bc953d1b3af3f698d5df8a428f68b73cd60aef6eb"
+ md5sum="f5898b29bbfd70502831a212d9249d10"/>
+ </autotools>
+
+ <autotools id="libseccomp" supports-non-srcdir-builds="no" autogen-sh="./autogen.sh; ./configure">
+ <branch repo="github.com" module="seccomp/libseccomp.git" tag="v2.2.3"/>
+ </autotools>
+
+ <autotools id="gdk-pixbuf" autogen-sh="configure"
+ autogenargs="--disable-introspection">
+ <dependencies>
+ <dep package="glib"/>
+ </dependencies>
+ <branch module="/pub/GNOME/sources/gdk-pixbuf/2.30/gdk-pixbuf-2.30.8.tar.xz" version="2.30.8"
+ repo="ftp.gnome.org"
+ hash="sha256:4853830616113db4435837992c0aebd94cbb993c44dc55063cee7f72a7bef8be"/>
+ </autotools>
+
+ <autotools id="librsvg" autogen-sh="configure"
+ autogenargs="--disable-introspection --enable-pixbuf-loader --disable-gtk-theme">
+ <if condition-set="macos">
+ <autogenargs value="--disable-Bsymbolic"/>
+ </if>
+ <dependencies>
+ <dep package="gdk-pixbuf"/>
+ <dep package="glib"/>
+ <dep package="cairo"/>
+ </dependencies>
+ <branch module="/pub/GNOME/sources/librsvg/2.36/librsvg-2.36.1.tar.xz" version="2.36.1"
+ repo="ftp.gnome.org"
+ hash="sha256:786b95e1a091375c5ef2997a21c69ff24d7077afeff18197355f54d9dcbcd8c5"
+ md5sum="89d483f30a7c77245b7ee02faaea5a5a">
+ <patch file="librsvg-2.36.1-bump-up-config.guess-to-support-aarch64.patch" strip="1"/>
+ </branch>
+ </autotools>
+
+ <autotools id="gtk+" autogen-sh="configure"
+ autogenargs="--disable-introspection">
+ <if condition-set="macos">
+ <autogenargs value="--enable-x11-backend=no --enable-quartz-backend" />
+ <makeargs value="-j1" />
+ </if>
+ <dependencies>
+ <dep package="glib"/>
+ <dep package="cairo"/>
+ <dep package="atk"/>
+ <if condition-set="linux">
+ <dep package="at-spi2-atk"/>
+ </if>
+ <dep package="gdk-pixbuf"/>
+ <dep package="pango"/>
+ </dependencies>
+ <branch module="/pub/GNOME/sources/gtk+/3.16/gtk+-3.16.4.tar.xz" version="3.16.4"
+ repo="ftp.gnome.org"
+ hash="sha256:1ee5dbd7a4cb81a91eaa1b7ae64ba5a3eab6a3c0a764155583ab96524590fc8e"/>
+ </autotools>
+
+ <autotools id="glib"
+ autogen-sh="configure"
+ autogenargs="--disable-dtrace">
+ <dependencies>
+ <dep package="libffi"/>
+ </dependencies>
+ <branch module="/pub/GNOME/sources/glib/2.44/glib-2.44.1.tar.xz" version="2.44.1"
+ repo="ftp.gnome.org"
+ hash="sha256:8811deacaf8a503d0a9b701777ea079ca6a4277be10e3d730d2112735d5eca07">
+ <patch file="glib-warning-fix.patch" strip="1"/>
+ </branch>
+ </autotools>
+
+ <autotools id="glib-networking">
+ <if condition-set="macos">
+ <autogenargs value="--with-ca-certificates='/usr/local/etc/openssl/cert.pem' --without-pkcs11"/>
+ </if>
+ <dependencies>
+ <dep package="glib"/>
+ </dependencies>
+ <branch module="/pub/GNOME/sources/glib-networking/2.41/glib-networking-2.41.4.tar.xz" version="2.41.4"
+ repo="ftp.gnome.org"
+ hash="sha256:930ad618865dcf81765d0f48cb6f13e22d76203efa59d30604aed0384ce80fd7"
+ md5sum="f88e163322c0834f9781d6224771ab2e"/>
+ </autotools>
+
+ <autotools id="libsoup"
+ autogenargs="--without-gnome --disable-introspection">
+ <if condition-set="macos">
+ <autogenargs value="--disable-tls-check"/>
+ </if>
+ <dependencies>
+ <dep package="glib-networking"/>
+ </dependencies>
+ <branch module="libsoup" version="2.49.91.1"
+ repo="git.gnome.org"
+ tag="f7292448160128b3cb4b7cd06c2447f81fd8c6c9"/>
+ </autotools>
+
+ <autotools id="fontconfig"
+ autogen-sh="configure"
+ autogenargs="--enable-libxml2">
+ <if condition-set="macos">
+ <autogenargs value="--with-add-fonts=/System/Library/Fonts,/Library/Fonts,~/Library/Fonts"/>
+ </if>
+ <dependencies>
+ <dep package="freetype6"/>
+ <dep package="libxml2"/>
+ </dependencies>
+ <branch module="software/fontconfig/release/fontconfig-2.11.1.tar.gz" version="2.11.1"
+ repo="freedesktop.org"
+ hash="sha256:b6b066c7dce3f436fdc0dfbae9d36122b38094f4f53bd8dffd45e195b0540d8d"
+ md5sum="e75e303b4f7756c2b16203a57ac87eba">
+ <patch file="fontconfig-fix-osx-cache.diff" strip="1"/>
+ </branch>
+ </autotools>
+
+ <autotools id="gnome-icon-theme" autogen-sh="configure">
+ <dependencies>
+ <dep package="gtk+"/>
+ </dependencies>
+ <branch module="pub/GNOME/sources/gnome-icon-theme/3.2/gnome-icon-theme-3.2.1.tar.xz" version="3.2.1"
+ repo="ftp.gnome.org"
+ hash="sha256:a7f0a8b17e91ac338fdbc01ac59a8738e9c1e201de492c070d43aacf291a8959"
+ md5sum="40be1e5a6eae11181311a6fc432cf892">
+ </branch>
+ </autotools>
+
+ <autotools id="gnome-icon-theme-symbolic" supports-non-srcdir-builds="no" autogen-sh="configure">
+ <dependencies>
+ <dep package="gtk+"/>
+ </dependencies>
+ <branch module="pub/GNOME/sources/gnome-icon-theme-symbolic/3.2/gnome-icon-theme-symbolic-3.2.1.tar.xz" version="3.2.1"
+ repo="ftp.gnome.org"
+ hash="sha256:a558af2f87f761f00421f49c1addd2149b70228158e09327fa861219ac1a63cb"
+ md5sum="94137d3c256f2cc80298a9bef15d68c4">
+ </branch>
+ </autotools>
+
+ <autotools id="gnome-themes-standard" autogen-sh="configure">
+ <dependencies>
+ <dep package="gtk+"/>
+ <dep package="librsvg"/>
+ </dependencies>
+ <branch module="pub/GNOME/sources/gnome-themes-standard/3.6/gnome-themes-standard-3.6.0.tar.xz" version="3.6.0"
+ repo="ftp.gnome.org"
+ hash="sha256:d832fd38f7659f470df5ddc52131a59f989c75f3a70f8b3a514f89d90d4f43ec">
+ </branch>
+ </autotools>
+
+ <autotools id="atk"
+ autogen-sh="configure"
+ autogenargs="--disable-introspection">
+ <branch module="pub/GNOME/sources/atk/2.15/atk-2.15.4.tar.xz" version="2.15.4"
+ repo="ftp.gnome.org"
+ hash="sha256:0dddfa73a02178ca21a8de172c86d699aa887b4efeec736b4c8721eee4ac349c"/>
+ </autotools>
+
+ <autotools id="at-spi2-core"
+ autogenargs="--disable-introspection">
+ <branch module="pub/GNOME/sources/at-spi2-core/2.15/at-spi2-core-2.15.4.tar.xz" version="2.15.4"
+ repo="ftp.gnome.org"
+ hash="sha256:0e3b01af6ba06d98faf7b85891ece394897fe145b0760b7846e810b57f1b809f">
+ </branch>
+ <dependencies>
+ <dep package="glib"/>
+ </dependencies>
+ </autotools>
+
+ <autotools id="at-spi2-atk">
+ <branch module="pub/GNOME/sources/at-spi2-atk/2.15/at-spi2-atk-2.15.4.tar.xz" version="2.15.4"
+ repo="ftp.gnome.org"
+ hash="sha256:3283aa5207b81e4c77d24c4e8b1c0abe6c850b11a2e62cd873cc07af0b403501">
+ </branch>
+ <dependencies>
+ <dep package="glib"/>
+ <dep package="atk"/>
+ <dep package="at-spi2-core"/>
+ </dependencies>
+ </autotools>
+
+ <autotools id="libxml2" supports-non-srcdir-builds="no"
+ autogen-sh="./autogen.sh; ./configure --with-python=no">
+ <branch module="/sources/libxml2-2.9.1.tar.gz" version="2.9.1"
+ repo="xmlsoft.org"
+ hash="sha256:fd3c64cb66f2c4ea27e934d275904d92cec494a8e8405613780cbc8a71680fdb"
+ md5sum="9c0cfef285d5c4a5c80d00904ddab380"/>
+ </autotools>
+
+ <autotools id="orc" autogenargs="--disable-gtk-doc" autogen-sh="configure">
+ <branch module="orc/orc-0.4.17.tar.gz" version="0.4.17"
+ repo="gstreamer"
+ hash="sha256:4fc7cca48c59fff23afee78fb642cdbde001f56401c8f47b95a16578d1d5d7e8"
+ md5sum="af1bf3dab9e69f3c36f389285e2a12a1"/>
+ </autotools>
+
+ <autotools id="gstreamer" autogenargs="--disable-gtk-doc">
+ <if condition-set="macos">
+ <autogenargs value="--disable-introspection"/>
+ <makeargs value="CFLAGS+=-Wno-error"/>
+ </if>
+ <dependencies>
+ <dep package="orc"/>
+ </dependencies>
+ <branch module="gstreamer/gstreamer-${version}.tar.xz" version="1.6.3"
+ repo="gstreamer"
+ hash="sha256:22f9568d67b87cf700a111f381144bd37cb93790a77e4e331db01fe854a37f24"
+ md5sum="b4cdeb2b9cb20dd6ac022a4f417eae0d"/>
+ </autotools>
+
+ <autotools id="gst-plugins-base"
+ autogen-sh="autogen.sh"
+ autogenargs="--disable-examples --disable-gtk-doc">
+ <if condition-set="macos">
+ <autogenargs value="--disable-introspection"/>
+ <makeargs value="CFLAGS+=-Wno-error"/>
+ </if>
+ <dependencies>
+ <dep package="gstreamer"/>
+ </dependencies>
+ <branch module="gst-plugins-base/gst-plugins-base-${version}.tar.xz" version="1.6.3"
+ repo="gstreamer"
+ hash="sha256:b6154f8fdba4877e95efd94610ef0ada4f0171cd12eb829a3c3c97345d9c7a75"
+ md5sum="3ddde0ad598ef69f58d6a2e87f8b460f"/>
+ </autotools>
+
+ <autotools id="gst-plugins-good" autogenargs="--disable-examples --disable-soup --disable-gtk-doc">
+ <if condition-set="macos">
+ <autogenargs value="--disable-introspection"/>
+ <makeargs value="CFLAGS+=-Wno-error OBJCFLAGS+=-Wno-error"/>
+ </if>
+ <dependencies>
+ <dep package="gst-plugins-base"/>
+ </dependencies>
+
+ <branch module="gst-plugins-good/gst-plugins-good-${version}.tar.xz" version="1.6.3"
+ repo="gstreamer"
+ hash="sha256:24b19db70b2a83461ebddfe20033db432dadfdb5d4b54ffb1dfa0d830134a177"
+ md5sum="a1958df7aa498b42793e2f2048673815"/>
+ </autotools>
+
+ <autotools id="gst-plugins-bad" autogenargs="--disable-examples --disable-gtk-doc">
+ <if condition-set="macos">
+ <autogenargs value="--disable-introspection"/>
+ <makeargs value="CFLAGS+=-Wno-error CXXFLAGS+=-Wno-error OBJCFLAGS+=-Wno-error"/>
+ </if>
+ <dependencies>
+ <dep package="gst-plugins-base"/>
+ </dependencies>
+ <branch module="gst-plugins-bad/gst-plugins-bad-${version}.tar.xz" version="1.6.3"
+ repo="gstreamer"
+ hash="sha256:971b29101d6a9c5e3fe94d99d977a227f58f0b2d29b6ca2c7f292052542b3a61"
+ md5sum="4857adcafe41e4b9b8805cf88303bd55"/>
+ </autotools>
+
+ <autotools id="gst-libav" autogenargs="--with-libav-extra-configure='--disable-yasm' --disable-gtk-doc">
+ <if condition-set="macos">
+ <makeargs value="CFLAGS+=-Wno-error"/>
+ </if>
+ <dependencies>
+ <dep package="gst-plugins-base"/>
+ </dependencies>
+ <branch module="gst-libav/gst-libav-${version}.tar.xz" version="1.6.3"
+ repo="gstreamer"
+ hash="sha256:857b9c060a0337de38c6d26238c47352433c02eabf26c2f860c854dbc35bd4ab"
+ md5sum="cfe9a06913d4fd4067e9e47f6e05fac2"/>
+ </autotools>
+
+ <autotools id="xserver" autogenargs="--disable-xinerama --enable-glx --enable-composite --disable-xorg --disable-dmx --disable-xnest --disable-xquartz --disable-xwin --disable-xephyr --disable-xfake --disable-xfbdev --disable-install-setuid --disable-unit-tests --disable-present --enable-unix-transport --enable-tcp-transport --disable-local-transport --with-xkb-path=/usr/share/X11/xkb --with-xkb-output=/var/lib/xkb --with-xkb-bin-directory=/usr/bin --without-dtrace">
+ <dependencies>
+ <dep package="pixman"/>
+ </dependencies>
+ <branch module="/releases/individual/xserver/xorg-server-1.16.4.tar.bz2" version="1.16.4"
+ repo="xorg"
+ hash="sha256:abb6e1cc9213a9915a121f48576ff6739a0b8cdb3d32796f9a7743c9a6efc871"
+ md5sum="80d140f631d862b76dc67ae983151c77">
+ <patch file="xserver-remove-bogus-dependencies.patch" strip="1"/>
+ </branch>
+ </autotools>
+
+ <autotools id="gtk-doc" autogen-sh="configure">
+ <if condition-set="macos">
+ <autogenargs value="--with-xml-catalog=/usr/local/etc/xml/catalog"/>
+ </if>
+ <dependencies>
+ <dep package="glib"/>
+ </dependencies>
+ <branch module="/pub/GNOME/sources/gtk-doc/1.20/gtk-doc-1.20.tar.xz" version="1.20"
+ repo="ftp.gnome.org"
+ hash="sha256:3e6ecf134dbf92a74c24d79848fea3a48e59ab95408a38c6405905d95a293011"/>
+ </autotools>
+
+ <autotools id="mesa" autogenargs="--enable-xlib-glx --disable-dri --disable-egl --with-gallium-drivers=swrast" skip-install="true">
+ <!--- WARNING: At jhbuildrc, when we define the path to the Gallium llvmpipe software rasterizer (needed by XvfbDriver),
+ we assume that the directory is named "Mesa". So, don't change the checkoutdir name even if you update the version. -->
+ <branch module="/~brianp/mesa/11.0.6/mesa-11.0.6.tar.xz" version="11.0.6"
+ checkoutdir="Mesa"
+ repo="people.freedesktop.org"
+ hash="sha256:8340e64cdc91999840404c211496f3de38e7b4cb38db34e2f72f1642c5134760">
+ </branch>
+ <dependencies>
+ <dep package="llvm"/>
+ </dependencies>
+ </autotools>
+
+ <autotools id="libusrsctp" supports-non-srcdir-builds="no" autogen-sh="./bootstrap; ./configure --disable-warnings-as-errors">
+ <branch repo="github.com" module="sctplab/usrsctp.git" checkoutdir="usrsctp" tag="078ff3252f73327e0ac11d6fd5eff62011f6646e"/>
+ </autotools>
+
+ <autotools id="gst-plugins-openwebrtc" supports-parallel-builds="no" supports-non-srcdir-builds="no" autogen-sh="./autogen.sh; ./configure">
+ <if condition-set="macos">
+ <makeargs value="CFLAGS+=-Wno-error"/>
+ </if>
+ <dependencies>
+ <dep package="gst-plugins-base"/>
+ <dep package="libusrsctp"/>
+ </dependencies>
+ <branch repo="github.com" module="EricssonResearch/openwebrtc-gst-plugins.git" checkoutdir="gst-plugins-openwebrtc" tag="e359b67484af90f416ea35e301205d2b53c77a14"/>
+ </autotools>
+
+ <autotools id="libnice" supports-non-srcdir-builds="no">
+ <dependencies>
+ <dep package="gstreamer"/>
+ </dependencies>
+ <branch repo="freedesktop-git" module="libnice/libnice.git" tag="0.1.10" checkoutdir="libnice"/>
+ </autotools>
+
+ <autotools id="openwebrtc" autogenargs="--enable-bridge=no --enable-owr-gst=yes">
+ <if condition-set="macos">
+ <makeargs value="CFLAGS+=-Wno-error"/>
+ </if>
+ <dependencies>
+ <dep package="gst-plugins-openwebrtc"/>
+ <dep package="libnice"/>
+ </dependencies>
+ <branch repo="github.com" module="EricssonResearch/openwebrtc.git" checkoutdir="openwebrtc" tag="13516c7f79a0c48bb411464f7613d4b426c70f5b"/>
+ </autotools>
+
+ <autotools id="llvm"
+ autogenargs="--enable-optimized --disable-terminfo --disable-zlib --enable-targets=host --disable-backtraces --disable-crash-overrides --disable-expensive-checks --disable-debug-runtime --disable-assertions --enable-shared">
+ <branch repo="llvm.org"
+ module="/releases/3.7.0/llvm-3.7.0.src.tar.xz" version="3.7.0" checkoutdir="llvm-3.7.0"
+ hash="sha256:ab45895f9dcdad1e140a3a79fd709f64b05ad7364e308c0e582c5b02e9cc3153"/>
+ </autotools>
+
+ <autotools id="gsettings-desktop-schemas" autogen-sh="configure">
+ <dependencies>
+ <dep package="glib"/>
+ </dependencies>
+ <branch module="/pub/GNOME/sources/gsettings-desktop-schemas/3.16/gsettings-desktop-schemas-3.16.1.tar.xz" version="3.16.1"
+ repo="ftp.gnome.org"
+ hash="sha256:74fe9fdad510c8a6666febeceb7ebafc581ef990b3afcc8c1e8b5d90b24b3461">
+ </branch>
+ </autotools>
+
+ <autotools id="shared-mime-info"
+ autogenargs="--disable-default-make-check">
+ <dependencies>
+ <dep package="libxml2"/>
+ <dep package="glib"/>
+ </dependencies>
+ <branch module="/~hadess/shared-mime-info-${version}.tar.xz" version="1.5"
+ repo="freedesktop.org"
+ hash="sha256:d6412840eb265bf36e61fd7b6fc6bea21b0f58cb22bed16f2ccccdd54bea4180">
+ <patch file="shared-mime-info-xht-glob.patch" strip="1"/>
+ <patch file="shared-mime-info-xhtml-magic.patch" strip="1"/>
+ </branch>
+ </autotools>
+
+ <!-- Dependencies listed below this point are not thought to affect test results, and are only
+ included because they themselves depend on other dependencies built by jhbuild. -->
+
+ <autotools id="pango" autogen-sh="configure"
+ autogenargs="--enable-cairo">
+ <dependencies>
+ <dep package="cairo"/>
+ <dep package="fontconfig"/>
+ </dependencies>
+ <branch module="/pub/GNOME/sources/pango/1.36/pango-1.36.8.tar.xz" version="1.36.8"
+ repo="ftp.gnome.org"
+ hash="sha256:18dbb51b8ae12bae0ab7a958e7cf3317c9acfc8a1e1103ec2f147164a0fc2d07">
+ </branch>
+ </autotools>
+
+</moduleset>
diff --git a/Tools/gtk/jhbuildrc b/Tools/gtk/jhbuildrc
new file mode 100644
index 000000000..9ca28f4bd
--- /dev/null
+++ b/Tools/gtk/jhbuildrc
@@ -0,0 +1,37 @@
+#!/usr/bin/env python
+# Copyright (C) 2011-2014 Igalia S.L.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+import sys
+import os
+
+sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../jhbuild") )
+import jhbuildrc_common
+jhbuildrc_common.init(globals(), "gtk")
+
+__gtk_tools_directory = os.path.abspath(os.path.dirname(__file__))
+sys.path = [__gtk_tools_directory] + sys.path
+import common
+
+# We always enable introspection so that we can sniff out problems with our
+# annotations sooner rather than later.
+autogenargs='--enable-introspection'
+
+# LLVM requires that builddir != srcdir, and it's not possible to do that in jhbuild only
+# for a module, so we do it here globally since it's a good idea for all other modules as well.
+buildroot = os.path.join(os.path.dirname(checkoutroot), "Build")
+
+os.environ['LLVMPIPE_LIBGL_PATH'] = os.path.abspath(os.path.join(buildroot, 'Mesa', 'lib', 'gallium'))
diff --git a/Tools/gtk/make-dist.py b/Tools/gtk/make-dist.py
new file mode 100755
index 000000000..a989b8b38
--- /dev/null
+++ b/Tools/gtk/make-dist.py
@@ -0,0 +1,327 @@
+#!/usr/bin/env python
+# Copyright (C) 2014 Igalia S.L.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+from __future__ import print_function
+from contextlib import closing
+
+import argparse
+import errno
+import multiprocessing
+import os
+import re
+import shutil
+import subprocess
+import tarfile
+
+
+def enum(**enums):
+ return type('Enum', (), enums)
+
+
+class Rule(object):
+ Result = enum(INCLUDE=1, EXCLUDE=2, NO_MATCH=3)
+
+ def __init__(self, type, pattern):
+ self.type = type
+ self.original_pattern = pattern
+ self.pattern = re.compile(pattern)
+
+ def test(self, file):
+ if not(self.pattern.search(file)):
+ return Rule.Result.NO_MATCH
+ return self.type
+
+
+class Ruleset(object):
+ _global_rules = None
+
+ def __init__(self):
+ # By default, accept all files.
+ self.rules = [Rule(Rule.Result.INCLUDE, '.*')]
+
+ @classmethod
+ def global_rules(cls):
+ if not cls._global_rules:
+ cls._global_rules = Ruleset()
+ return cls._global_rules
+
+ @classmethod
+ def add_global_rule(cls, rule):
+ cls.global_rules().add_rule(rule)
+
+ def add_rule(self, rule):
+ self.rules.append(rule)
+
+ def passes(self, file):
+ allowed = False
+ for rule in self.rules:
+ result = rule.test(file)
+ if result == Rule.Result.NO_MATCH:
+ continue
+ allowed = Rule.Result.INCLUDE == result
+ return allowed
+
+
+class File(object):
+ def __init__(self, source_root, tarball_root):
+ self.source_root = source_root
+ self.tarball_root = tarball_root
+
+ def should_skip_file(self, path):
+ # Do not skip files explicitly added from the manifest.
+ return False
+
+ def get_files(self):
+ yield (self.source_root, self.tarball_root)
+
+
+class Directory(object):
+ def __init__(self, source_root, tarball_root):
+ self.source_root = source_root
+ self.tarball_root = tarball_root
+ self.rules = Ruleset()
+
+ self.files_in_version_control = self.list_files_in_version_control()
+
+ def add_rule(self, rule):
+ self.rules.add_rule(rule)
+
+ def get_tarball_path(self, filename):
+ return filename.replace(self.source_root, self.tarball_root, 1)
+
+ def list_files_in_version_control(self):
+ # FIXME: Only git is supported for now.
+ p = subprocess.Popen(['git', 'ls-tree', '-r', '--name-only', 'HEAD', self.source_root], stdout=subprocess.PIPE)
+ out = p.communicate()[0]
+ if not out:
+ return []
+ return out.rstrip('\n').split('\n')
+
+ def should_skip_file(self, path):
+ return path not in self.files_in_version_control
+
+ def get_files(self):
+ for root, dirs, files in os.walk(self.source_root):
+
+ def passes_all_rules(entry):
+ return Ruleset.global_rules().passes(entry) and self.rules.passes(entry)
+
+ to_keep = filter(passes_all_rules, dirs)
+ del dirs[:]
+ dirs.extend(to_keep)
+
+ for file in files:
+ file = os.path.join(root, file)
+ if not passes_all_rules(file):
+ continue
+ yield (file, self.get_tarball_path(file))
+
+
+class Manifest(object):
+ def __init__(self, manifest_filename, source_root, build_root, tarball_root='/'):
+ self.current_directory = None
+ self.directories = []
+ self.tarball_root = tarball_root
+ self.source_root = source_root
+ self.build_root = build_root
+
+ # Normalize the tarball root so that it starts and ends with a slash.
+ if not self.tarball_root.endswith('/'):
+ self.tarball_root = self.tarball_root + '/'
+ if not self.tarball_root.startswith('/'):
+ self.tarball_root = '/' + self.tarball_root
+
+ with open(manifest_filename, 'r') as file:
+ for line in file.readlines():
+ self.process_line(line)
+
+ def add_rule(self, rule):
+ if self.current_directory is not None:
+ self.current_directory.add_rule(rule)
+ else:
+ Ruleset.add_global_rule(rule)
+
+ def add_directory(self, directory):
+ self.current_directory = directory
+ self.directories.append(directory)
+
+ def get_full_source_path(self, source_path):
+ if not os.path.exists(source_path):
+ source_path = os.path.join(self.source_root, source_path)
+ if not os.path.exists(source_path):
+ raise Exception('Could not find directory %s' % source_path)
+ return source_path
+
+ def get_full_tarball_path(self, path):
+ return self.tarball_root + path
+
+ def get_source_and_tarball_paths_from_parts(self, parts):
+ full_source_path = self.get_full_source_path(parts[1])
+ if len(parts) > 2:
+ full_tarball_path = self.get_full_tarball_path(parts[2])
+ else:
+ full_tarball_path = self.get_full_tarball_path(parts[1])
+ return (full_source_path, full_tarball_path)
+
+ def process_line(self, line):
+ parts = line.split()
+ if not parts:
+ return
+ if parts[0].startswith("#"):
+ return
+
+ if parts[0] == "directory" and len(parts) > 1:
+ self.add_directory(Directory(*self.get_source_and_tarball_paths_from_parts(parts)))
+ elif parts[0] == "file" and len(parts) > 1:
+ self.add_directory(File(*self.get_source_and_tarball_paths_from_parts(parts)))
+ elif parts[0] == "exclude" and len(parts) > 1:
+ self.add_rule(Rule(Rule.Result.EXCLUDE, parts[1]))
+ elif parts[0] == "include" and len(parts) > 1:
+ self.add_rule(Rule(Rule.Result.INCLUDE, parts[1]))
+
+ def should_skip_file(self, directory, filename):
+ # Only allow files that are not in version control when they are explicitly included in the manifest from the build dir.
+ if filename.startswith(self.build_root):
+ return False
+
+ return directory.should_skip_file(filename)
+
+ def get_files(self):
+ for directory in self.directories:
+ for file_tuple in directory.get_files():
+ if self.should_skip_file(directory, file_tuple[0]):
+ continue
+ yield file_tuple
+
+ def create_tarfile(self, output):
+ count = 0
+ for file_tuple in self.get_files():
+ count = count + 1
+
+ with closing(tarfile.open(output, 'w')) as tarball:
+ for i, (file_path, tarball_path) in enumerate(self.get_files(), start=1):
+ print('Tarring file {0} of {1}'.format(i, count).ljust(40), end='\r')
+ tarball.add(file_path, tarball_path)
+ print("Wrote {0}".format(output).ljust(40))
+
+
+class Distcheck(object):
+ BUILD_DIRECTORY_NAME = "_build"
+ INSTALL_DIRECTORY_NAME = "_install"
+
+ def __init__(self, source_root, build_root):
+ self.source_root = source_root
+ self.build_root = build_root
+
+ def extract_tarball(self, tarball_path):
+ with closing(tarfile.open(tarball_path, 'r')) as tarball:
+ tarball.extractall(self.build_root)
+
+ def configure(self, dist_dir, build_dir, install_dir):
+ def create_dir(directory, directory_type):
+ try:
+ os.mkdir(directory)
+ except OSError, e:
+ if e.errno != errno.EEXIST or not os.path.isdir(directory):
+ raise Exception("Could not create %s dir at %s: %s" % (directory_type, directory, str(e)))
+
+ create_dir(build_dir, "build")
+ create_dir(install_dir, "install")
+
+ command = ['cmake', '-DPORT=GTK', '-DCMAKE_INSTALL_PREFIX=%s' % install_dir, '-DCMAKE_BUILD_TYPE=Release', dist_dir]
+ subprocess.check_call(command, cwd=build_dir)
+
+ def build(self, build_dir):
+ command = ['make']
+ make_args = os.getenv('MAKE_ARGS')
+ if make_args:
+ command.extend(make_args.split(' '))
+ else:
+ command.append('-j%d' % multiprocessing.cpu_count())
+ subprocess.check_call(command, cwd=build_dir)
+
+ def install(self, build_dir):
+ subprocess.check_call(['make', 'install'], cwd=build_dir)
+
+ def clean(self, dist_dir):
+ shutil.rmtree(dist_dir)
+
+ def check(self, tarball):
+ tarball_name, ext = os.path.splitext(os.path.basename(tarball))
+ dist_dir = os.path.join(self.build_root, tarball_name)
+ build_dir = os.path.join(dist_dir, self.BUILD_DIRECTORY_NAME)
+ install_dir = os.path.join(dist_dir, self.INSTALL_DIRECTORY_NAME)
+
+ self.extract_tarball(tarball)
+ self.configure(dist_dir, build_dir, install_dir)
+ self.build(build_dir)
+ self.install(build_dir)
+ self.clean(dist_dir)
+
+if __name__ == "__main__":
+ class FilePathAction(argparse.Action):
+ def __call__(self, parser, namespace, values, option_string=None):
+ setattr(namespace, self.dest, os.path.abspath(values))
+
+ def ensure_version_if_possible(arguments):
+ if arguments.version is not None:
+ return
+
+ pkgconfig_file = os.path.join(arguments.build_dir, "Source/WebKit2/webkit2gtk-4.0.pc")
+ if os.path.isfile(pkgconfig_file):
+ p = subprocess.Popen(['pkg-config', '--modversion', pkgconfig_file], stdout=subprocess.PIPE)
+ version = p.communicate()[0]
+ if version:
+ arguments.version = version.rstrip('\n')
+
+
+ def get_tarball_root_and_output_filename_from_arguments(arguments):
+ tarball_root = "webkitgtk"
+ if arguments.version is not None:
+ tarball_root += '-' + arguments.version
+
+ output_filename = os.path.join(arguments.build_dir, tarball_root + ".tar")
+ return tarball_root, output_filename
+
+ parser = argparse.ArgumentParser(description='Build a distribution bundle.')
+ parser.add_argument('-c', '--check', action='store_true',
+ help='Check the tarball')
+ parser.add_argument('-s', '--source-dir', type=str, action=FilePathAction, default=os.getcwd(),
+ help='The top-level directory of the source distribution. ' + \
+ 'Directory for relative paths. Defaults to current directory.')
+ parser.add_argument('--version', type=str, default=None,
+ help='The version of the tarball to generate')
+ parser.add_argument('-b', '--build-dir', type=str, action=FilePathAction, default=os.getcwd(),
+ help='The top-level path of directory of the build root. ' + \
+ 'By default is the current directory.')
+ parser.add_argument('manifest_filename', metavar="manifest", type=str, action=FilePathAction, help='The path to the manifest file.')
+
+ arguments = parser.parse_args()
+
+ # Paths in the manifest are relative to the source directory, and this script assumes that
+ # current working directory is the source directory, so change the current working directory
+ # to be the source directory.
+ os.chdir(arguments.source_dir)
+
+ ensure_version_if_possible(arguments)
+ tarball_root, output_filename = get_tarball_root_and_output_filename_from_arguments(arguments)
+
+ manifest = Manifest(arguments.manifest_filename, arguments.source_dir, arguments.build_dir, tarball_root)
+ manifest.create_tarfile(output_filename)
+
+ if arguments.check:
+ Distcheck(arguments.source_dir, arguments.build_dir).check(output_filename)
diff --git a/Tools/gtk/manifest.txt.in b/Tools/gtk/manifest.txt.in
new file mode 100644
index 000000000..84b39ef0a
--- /dev/null
+++ b/Tools/gtk/manifest.txt.in
@@ -0,0 +1,106 @@
+# Global rules
+exclude #$
+exclude ChangeLog
+exclude Makefile
+exclude PlatformEfl.cmake
+exclude PlatformWin.cmake
+exclude tags$
+exclude ~$
+exclude \.#$
+exclude \.bak$
+exclude \.cproject$
+exclude \.git$
+exclude \.gitattributes$
+exclude \.gitignore$
+exclude \.gyp$
+exclude \.icns$
+exclude \.lproj$
+exclude \.m$
+exclude \.mm$
+exclude \.nib$
+exclude \.o$
+exclude \.order$
+exclude \.orig$
+exclude \.pdf$
+exclude \.plist$
+exclude \.pro\.user$
+exclude \.project$
+exclude \.props$
+exclude \.pyc$
+exclude \.pyo$
+exclude \.rej$
+exclude \.rtf$
+exclude \.sb$
+exclude \.sb\.in$
+exclude \.settings$
+exclude \.svn$
+exclude \.sw[a-p]$
+exclude \.vcxproj$
+exclude \.xib$
+exclude \.xcconfig$
+exclude \.xcodeproj$
+
+# Exclude directories from other ports
+exclude .*\/(mac|ios|cf|cg|cocoa|Cocoa|objc|avfoundation|ca|curl|efl|win)\/.*$
+
+directory Source
+exclude Source/JavaScriptCore/tests
+exclude Source/WebCore/platform/audio/resources
+exclude Source/WebCore/bindings/scripts/test
+exclude Source/WebCore/platform/efl/DefaultTheme
+exclude Source/WebCore/Resources
+exclude Source/cmake/EFLHelpers.cmake$
+exclude Source/cmake/OptionsWinCairo.cmake$
+exclude Source/cmake/OptionsWindows.cmake$
+exclude Source/cmake/OptionsAppleWin.cmake$
+exclude Source/cmake/OptionsEfl.cmake$
+exclude Source/cmake/eflsymbols.filter$
+exclude Source/WebInspectorUI/Tools
+exclude Source/WebInspectorUI/UserInterface/Images
+
+directory Source/WebInspectorUI/UserInterface/Images/gtk
+
+# Most of the files in Source/WebKit are not necessary to build GTK+ and
+# the directory includes lots of images, so we're a bit more picky here.
+exclude Source/WebKit/.*
+exclude Source/WebKit2/Configurations
+exclude Source/WebKit2/Resources
+exclude Source/WebKit2/gtk/NEWS$
+
+# We do want to include the NEWS, but we want it to be in the root of the archive.
+file Source/WebKit2/gtk/NEWS NEWS
+
+file Source/WebCore/English.lproj/mediaControlsLocalizedStrings.js Source/WebCore/English.lproj/mediaControlsLocalizedStrings.js
+file Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js
+
+# Include only the resources we actually build
+file Source/WebCore/Resources/missingImage.png
+file Source/WebCore/Resources/missingImage@2x.png
+file Source/WebCore/Resources/panIcon.png
+file Source/WebCore/Resources/plugIns.js
+file Source/WebCore/Resources/textAreaResizeCorner.png
+file Source/WebCore/Resources/textAreaResizeCorner@2x.png
+file Source/WebCore/Resources/urlIcon.png
+file Source/WebCore/platform/audio/resources/Composite.wav
+
+directory Tools/gtk
+directory Tools/ImageDiff
+directory Tools/MiniBrowser
+directory Tools/TestWebKitAPI
+
+directory Tools/DumpRenderTree
+exclude Tools/DumpRenderTree/fonts
+
+directory Tools/WebKitTestRunner
+exclude Tools/WebKitTestRunner/fonts/
+
+file CMakeLists.txt
+file Tools/CMakeLists.txt
+file Tools/Scripts/VCSUtils.pm
+file Tools/Scripts/run-gtk-tests
+file Tools/Scripts/webkit-build-directory
+file Tools/Scripts/webkitdirs.pm
+file Tools/jhbuild/jhbuildutils.py
+
+directory ${CMAKE_BINARY_DIR}/Documentation/webkit2gtk-${WEBKITGTK_API_VERSION}/html Documentation/webkit2gtk-${WEBKITGTK_API_VERSION}/html
+directory ${CMAKE_BINARY_DIR}/Documentation/webkitdomgtk-${WEBKITGTK_API_VERSION}/html Documentation/webkitdomgtk-${WEBKITGTK_API_VERSION}/html
diff --git a/Tools/gtk/patches/fontconfig-C-11-requires-a-space-between-literal-and-identifier.patch b/Tools/gtk/patches/fontconfig-C-11-requires-a-space-between-literal-and-identifier.patch
new file mode 100644
index 000000000..b4e0a541d
--- /dev/null
+++ b/Tools/gtk/patches/fontconfig-C-11-requires-a-space-between-literal-and-identifier.patch
@@ -0,0 +1,30 @@
+From 7069d717e982adcf8e1d300cbd10eec6322a65c9 Mon Sep 17 00:00:00 2001
+From: Akira TAGOH <akira@tagoh.org>
+Date: Sun, 22 Apr 2012 21:40:44 +0900
+Subject: [PATCH] C++11 requires a space between literal and identifier
+
+Reported by Buganini
+---
+ fontconfig/fontconfig.h | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h
+index 0e2ca50..b27ccb5 100644
+--- a/fontconfig/fontconfig.h
++++ b/fontconfig/fontconfig.h
+@@ -112,9 +112,9 @@ typedef int FcBool;
+ #define FC_DECORATIVE "decorative" /* Bool - true if style is a decorative variant */
+ #define FC_LCD_FILTER "lcdfilter" /* Int */
+
+-#define FC_CACHE_SUFFIX ".cache-"FC_CACHE_VERSION
+-#define FC_DIR_CACHE_FILE "fonts.cache-"FC_CACHE_VERSION
+-#define FC_USER_CACHE_FILE ".fonts.cache-"FC_CACHE_VERSION
++#define FC_CACHE_SUFFIX ".cache-" FC_CACHE_VERSION
++#define FC_DIR_CACHE_FILE "fonts.cache-" FC_CACHE_VERSION
++#define FC_USER_CACHE_FILE ".fonts.cache-" FC_CACHE_VERSION
+
+ /* Adjust outline rasterizer */
+ #define FC_CHAR_WIDTH "charwidth" /* Int */
+--
+1.8.3.2
+
diff --git a/Tools/gtk/patches/fontconfig-fix-osx-cache.diff b/Tools/gtk/patches/fontconfig-fix-osx-cache.diff
new file mode 100644
index 000000000..2c71bc83a
--- /dev/null
+++ b/Tools/gtk/patches/fontconfig-fix-osx-cache.diff
@@ -0,0 +1,207 @@
+diff --git a/fc-cache/fc-cache.c b/fc-cache/fc-cache.c
+index 99e0e9f..bf3b6b4 100644
+--- a/fc-cache/fc-cache.c
++++ b/fc-cache/fc-cache.c
+@@ -187,13 +187,8 @@ scanDirs (FcStrList *list, FcConfig *config, FcBool force, FcBool really_force,
+
+ if (!cache)
+ {
+- if (!recursive)
+- cache = FcDirCacheRescan (dir, config);
+- else
+- {
+- (*changed)++;
+- cache = FcDirCacheRead (dir, FcTrue, config);
+- }
++ (*changed)++;
++ cache = FcDirCacheRead (dir, FcTrue, config);
+ if (!cache)
+ {
+ fprintf (stderr, "%s: error scanning\n", dir);
+@@ -391,7 +386,6 @@ main (int argc, char **argv)
+ ret += scanDirs (list, config, FcTrue, really_force, verbose, FcFalse, &changed, NULL);
+ FcStrListDone (list);
+ }
+- FcStrSetDestroy (updateDirs);
+
+ /*
+ * Try to create CACHEDIR.TAG anyway.
+diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h
+index 2258251..d0b4e9e 100644
+--- a/fontconfig/fontconfig.h
++++ b/fontconfig/fontconfig.h
+@@ -541,9 +541,6 @@ FcDirSave (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir);
+
+ FcPublic FcCache *
+ FcDirCacheLoad (const FcChar8 *dir, FcConfig *config, FcChar8 **cache_file);
+-
+-FcPublic FcCache *
+-FcDirCacheRescan (const FcChar8 *dir, FcConfig *config);
+
+ FcPublic FcCache *
+ FcDirCacheRead (const FcChar8 *dir, FcBool force, FcConfig *config);
+diff --git a/src/fccache.c b/src/fccache.c
+index 5173e0b..10eacff 100644
+--- a/src/fccache.c
++++ b/src/fccache.c
+@@ -828,19 +828,6 @@ bail1:
+ return NULL;
+ }
+
+-FcCache *
+-FcDirCacheRebuild (FcCache *cache, struct stat *dir_stat, FcStrSet *dirs)
+-{
+- FcCache *new;
+- FcFontSet *set = FcFontSetDeserialize (FcCacheSet (cache));
+- const FcChar8 *dir = FcCacheDir (cache);
+-
+- new = FcDirCacheBuild (set, dir, dir_stat, dirs);
+- FcFontSetDestroy (set);
+-
+- return new;
+-}
+-
+ /* write serialized state to the cache file */
+ FcBool
+ FcDirCacheWrite (FcCache *cache, FcConfig *config)
+diff --git a/src/fcdir.c b/src/fcdir.c
+index 3bcd0b8..b040a28 100644
+--- a/src/fcdir.c
++++ b/src/fcdir.c
+@@ -130,12 +130,7 @@ FcFileScanConfig (FcFontSet *set,
+ if (FcFileIsDir (file))
+ return FcStrSetAdd (dirs, file);
+ else
+- {
+- if (set)
+- return FcFileScanFontConfig (set, blanks, file, config);
+- else
+- return FcTrue;
+- }
++ return FcFileScanFontConfig (set, blanks, file, config);
+ }
+
+ FcBool
+@@ -311,45 +306,6 @@ FcDirCacheScan (const FcChar8 *dir, FcConfig *config)
+ return cache;
+ }
+
+-FcCache *
+-FcDirCacheRescan (const FcChar8 *dir, FcConfig *config)
+-{
+- FcCache *cache = FcDirCacheLoad (dir, config, NULL);
+- FcCache *new = NULL;
+- struct stat dir_stat;
+- FcStrSet *dirs;
+-
+- if (!cache)
+- return NULL;
+- if (FcStatChecksum (dir, &dir_stat) < 0)
+- goto bail;
+- dirs = FcStrSetCreate ();
+- if (!dirs)
+- goto bail;
+-
+- /*
+- * Scan the dir
+- */
+- if (!FcDirScanConfig (NULL, dirs, NULL, dir, FcTrue, config))
+- goto bail1;
+- /*
+- * Rebuild the cache object
+- */
+- new = FcDirCacheRebuild (cache, &dir_stat, dirs);
+- if (!new)
+- goto bail1;
+- FcDirCacheUnload (cache);
+- /*
+- * Write out the cache file, ignoring any troubles
+- */
+- FcDirCacheWrite (new, config);
+-
+-bail1:
+- FcStrSetDestroy (dirs);
+-bail:
+- return new;
+-}
+-
+ /*
+ * Read (or construct) the cache for a directory
+ */
+diff --git a/src/fcfs.c b/src/fcfs.c
+index 21c6c7c..941abba 100644
+--- a/src/fcfs.c
++++ b/src/fcfs.c
+@@ -122,28 +122,6 @@ FcFontSetSerialize (FcSerialize *serialize, const FcFontSet * s)
+
+ return s_serialize;
+ }
+-
+-FcFontSet *
+-FcFontSetDeserialize (const FcFontSet *set)
+-{
+- int i;
+- FcFontSet *new = FcFontSetCreate ();
+-
+- if (!new)
+- return NULL;
+- for (i = 0; i < set->nfont; i++)
+- {
+- if (!FcFontSetAdd (new, FcPatternDuplicate (FcFontSetFont (set, i))))
+- goto bail;
+- }
+-
+- return new;
+-bail:
+- FcFontSetDestroy (new);
+-
+- return NULL;
+-}
+-
+ #define __fcfs__
+ #include "fcaliastail.h"
+ #undef __fcfs__
+diff --git a/src/fcint.h b/src/fcint.h
+index cdf2dab..362ea6f 100644
+--- a/src/fcint.h
++++ b/src/fcint.h
+@@ -567,9 +567,6 @@ FcDirCacheScan (const FcChar8 *dir, FcConfig *config);
+ FcPrivate FcCache *
+ FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, struct stat *dir_stat, FcStrSet *dirs);
+
+-FcPrivate FcCache *
+-FcDirCacheRebuild (FcCache *cache, struct stat *dir_stat, FcStrSet *dirs);
+-
+ FcPrivate FcBool
+ FcDirCacheWrite (FcCache *cache, FcConfig *config);
+
+@@ -841,9 +838,6 @@ FcFontSetSerializeAlloc (FcSerialize *serialize, const FcFontSet *s);
+ FcPrivate FcFontSet *
+ FcFontSetSerialize (FcSerialize *serialize, const FcFontSet * s);
+
+-FcPrivate FcFontSet *
+-FcFontSetDeserialize (const FcFontSet *set);
+-
+ /* fchash.c */
+ FcPrivate FcChar8 *
+ FcHashGetSHA256Digest (const FcChar8 *input_strings,
+diff --git a/src/fcpat.c b/src/fcpat.c
+index 986cca3..0614ac2 100644
+--- a/src/fcpat.c
++++ b/src/fcpat.c
+@@ -33,7 +33,6 @@ FcPatternCreate (void)
+ p = (FcPattern *) malloc (sizeof (FcPattern));
+ if (!p)
+ return 0;
+- memset (p, 0, sizeof (FcPattern));
+ p->num = 0;
+ p->size = 0;
+ p->elts_offset = FcPtrToOffset (p, NULL);
+@@ -1311,7 +1310,6 @@ FcValueListSerialize (FcSerialize *serialize, const FcValueList *vl)
+ }
+ return head_serialized;
+ }
+-
+ #define __fcpat__
+ #include "fcaliastail.h"
+ #include "fcftaliastail.h" \ No newline at end of file
diff --git a/Tools/gtk/patches/freetype6-2.4.11-truetype-font-height-fix.patch b/Tools/gtk/patches/freetype6-2.4.11-truetype-font-height-fix.patch
new file mode 100644
index 000000000..0ffe76b4e
--- /dev/null
+++ b/Tools/gtk/patches/freetype6-2.4.11-truetype-font-height-fix.patch
@@ -0,0 +1,39 @@
+From e0469372be3870a5ad60b2c4586e9c281357bd28 Mon Sep 17 00:00:00 2001
+From: Werner Lemberg <wl@gnu.org>
+Date: Tue, 22 Jan 2013 10:07:07 +0000
+Subject: [truetype] Fix font height.
+
+* src/truetype/ttobjs.c (tt_size_reset): The Windows rendering
+engine uses rounded values of the ascender and descender to compute
+the TrueType font height.
+---
+diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c
+index c61b218..590b66c 100644
+--- a/src/truetype/ttobjs.c
++++ b/src/truetype/ttobjs.c
+@@ -4,7 +4,7 @@
+ /* */
+ /* Objects manager (body). */
+ /* */
+-/* Copyright 1996-2012 */
++/* Copyright 1996-2013 */
+ /* David Turner, Robert Wilhelm, and Werner Lemberg. */
+ /* */
+ /* This file is part of the FreeType project, and may only be used, */
+@@ -1177,11 +1177,12 @@
+ FT_PIX_ROUND( FT_MulFix( face->root.ascender, metrics->y_scale ) );
+ metrics->descender =
+ FT_PIX_ROUND( FT_MulFix( face->root.descender, metrics->y_scale ) );
+- metrics->height =
+- FT_PIX_ROUND( FT_MulFix( face->root.height, metrics->y_scale ) );
+ metrics->max_advance =
+ FT_PIX_ROUND( FT_MulFix( face->root.max_advance_width,
+ metrics->x_scale ) );
++
++ /* the height is derived from rounded values */
++ metrics->height = metrics->ascender - metrics->descender;
+ }
+
+ /* compute new transformation */
+--
+cgit v0.9.0.2
diff --git a/Tools/gtk/patches/glib-warning-fix.patch b/Tools/gtk/patches/glib-warning-fix.patch
new file mode 100644
index 000000000..8faf4d11f
--- /dev/null
+++ b/Tools/gtk/patches/glib-warning-fix.patch
@@ -0,0 +1,34 @@
+From 9f90ee5eeccd47f39c7a03dcd786b125a19c195d Mon Sep 17 00:00:00 2001
+From: Michael Catanzaro <mcatanzaro@gnome.org>
+Date: Sat, 13 Jun 2015 22:52:33 -0500
+Subject: [PATCH] genmarshal: silence register storage class warnings
+
+Using the register keyword triggers warnings on noteworthy compilers
+(clang), since it's deprecated in C++ and at danger of being removed
+from the language. There is no reason to use it since it isn't 1980
+anymore.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=750918
+---
+ gobject/glib-genmarshal.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/gobject/glib-genmarshal.c b/gobject/glib-genmarshal.c
+index be4151a..ca78a6f 100644
+--- a/gobject/glib-genmarshal.c
++++ b/gobject/glib-genmarshal.c
+@@ -412,9 +412,9 @@ generate_marshal (const gchar *signame,
+ g_fprintf (fout, "%s%s data2);\n", indent (ind), pad ("gpointer"));
+
+ /* cfile marshal variables */
+- g_fprintf (fout, " register GMarshalFunc_%s callback;\n", signame);
+- g_fprintf (fout, " register GCClosure *cc = (GCClosure*) closure;\n");
+- g_fprintf (fout, " register gpointer data1, data2;\n");
++ g_fprintf (fout, " GMarshalFunc_%s callback;\n", signame);
++ g_fprintf (fout, " GCClosure *cc = (GCClosure*) closure;\n");
++ g_fprintf (fout, " gpointer data1, data2;\n");
+ if (sig->rarg->setter)
+ g_fprintf (fout, " %s v_return;\n", sig->rarg->ctype);
+
+--
+2.4.2 \ No newline at end of file
diff --git a/Tools/gtk/patches/librsvg-2.36.1-bump-up-config.guess-to-support-aarch64.patch b/Tools/gtk/patches/librsvg-2.36.1-bump-up-config.guess-to-support-aarch64.patch
new file mode 100644
index 000000000..a20af4ce1
--- /dev/null
+++ b/Tools/gtk/patches/librsvg-2.36.1-bump-up-config.guess-to-support-aarch64.patch
@@ -0,0 +1,1581 @@
+diff -ur librsvg-2.36.1-orig/config.guess librsvg-2.36.1/config.guess
+--- librsvg-2.36.1-orig/config.guess 2012-02-03 13:14:58.000000000 +0100
++++ librsvg-2.36.1/config.guess 2014-09-25 18:36:54.000000000 +0200
+@@ -1,14 +1,12 @@
+ #! /bin/sh
+ # Attempt to guess a canonical system name.
+-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+-# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+-# Free Software Foundation, Inc.
++# Copyright 1992-2014 Free Software Foundation, Inc.
+
+-timestamp='2009-11-20'
++timestamp='2014-03-23'
+
+ # This file is free software; you can redistribute it and/or modify it
+ # under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2 of the License, or
++# the Free Software Foundation; either version 3 of the License, or
+ # (at your option) any later version.
+ #
+ # This program is distributed in the hope that it will be useful, but
+@@ -17,26 +15,22 @@
+ # General Public License for more details.
+ #
+ # You should have received a copy of the GNU General Public License
+-# along with this program; if not, write to the Free Software
+-# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+-# 02110-1301, USA.
++# along with this program; if not, see <http://www.gnu.org/licenses/>.
+ #
+ # As a special exception to the GNU General Public License, if you
+ # distribute this file as part of a program that contains a
+ # configuration script generated by Autoconf, you may include it under
+-# the same distribution terms that you use for the rest of that program.
+-
+-
+-# Originally written by Per Bothner. Please send patches (context
+-# diff format) to <config-patches@gnu.org> and include a ChangeLog
+-# entry.
++# the same distribution terms that you use for the rest of that
++# program. This Exception is an additional permission under section 7
++# of the GNU General Public License, version 3 ("GPLv3").
+ #
+-# This script attempts to guess a canonical system name similar to
+-# config.sub. If it succeeds, it prints the system name on stdout, and
+-# exits with 0. Otherwise, it exits with 1.
++# Originally written by Per Bothner.
+ #
+ # You can get the latest version of this script from:
+ # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
++#
++# Please send patches with a ChangeLog entry to config-patches@gnu.org.
++
+
+ me=`echo "$0" | sed -e 's,.*/,,'`
+
+@@ -56,8 +50,7 @@
+ GNU config.guess ($timestamp)
+
+ Originally written by Per Bothner.
+-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+-2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
++Copyright 1992-2014 Free Software Foundation, Inc.
+
+ This is free software; see the source for copying conditions. There is NO
+ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+@@ -139,12 +132,33 @@
+ UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+ UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
++case "${UNAME_SYSTEM}" in
++Linux|GNU|GNU/*)
++ # If the system lacks a compiler, then just pick glibc.
++ # We could probably try harder.
++ LIBC=gnu
++
++ eval $set_cc_for_build
++ cat <<-EOF > $dummy.c
++ #include <features.h>
++ #if defined(__UCLIBC__)
++ LIBC=uclibc
++ #elif defined(__dietlibc__)
++ LIBC=dietlibc
++ #else
++ LIBC=gnu
++ #endif
++ EOF
++ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
++ ;;
++esac
++
+ # Note: order is significant - the case branches are not exclusive.
+
+ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+- # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
++ # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+@@ -180,7 +194,7 @@
+ fi
+ ;;
+ *)
+- os=netbsd
++ os=netbsd
+ ;;
+ esac
+ # The OS release
+@@ -201,6 +215,10 @@
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit ;;
++ *:Bitrig:*:*)
++ UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
++ echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
++ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+@@ -223,7 +241,7 @@
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+- UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
++ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+@@ -269,7 +287,10 @@
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+- exit ;;
++ # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
++ exitcode=$?
++ trap '' 0
++ exit $exitcode ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+@@ -295,12 +316,12 @@
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+- echo powerpc-ibm-os400
++ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit ;;
+- arm:riscos:*:*|arm:RISCOS:*:*)
++ arm*:riscos:*:*|arm*:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+@@ -394,23 +415,23 @@
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+- echo m68k-atari-mint${UNAME_RELEASE}
++ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+- exit ;;
++ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+- echo m68k-atari-mint${UNAME_RELEASE}
++ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+- echo m68k-milan-mint${UNAME_RELEASE}
+- exit ;;
++ echo m68k-milan-mint${UNAME_RELEASE}
++ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+- echo m68k-hades-mint${UNAME_RELEASE}
+- exit ;;
++ echo m68k-hades-mint${UNAME_RELEASE}
++ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+- echo m68k-unknown-mint${UNAME_RELEASE}
+- exit ;;
++ echo m68k-unknown-mint${UNAME_RELEASE}
++ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
+@@ -480,8 +501,8 @@
+ echo m88k-motorola-sysv3
+ exit ;;
+ AViiON:dgux:*:*)
+- # DG/UX returns AViiON for all architectures
+- UNAME_PROCESSOR=`/usr/bin/uname -p`
++ # DG/UX returns AViiON for all architectures
++ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+@@ -494,7 +515,7 @@
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+- exit ;;
++ exit ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+@@ -551,7 +572,7 @@
+ echo rs6000-ibm-aix3.2
+ fi
+ exit ;;
+- *:AIX:*:[456])
++ *:AIX:*:[4567])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+@@ -594,52 +615,52 @@
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+- sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+- case "${sc_cpu_version}" in
+- 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+- 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+- 532) # CPU_PA_RISC2_0
+- case "${sc_kernel_bits}" in
+- 32) HP_ARCH="hppa2.0n" ;;
+- 64) HP_ARCH="hppa2.0w" ;;
++ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
++ case "${sc_cpu_version}" in
++ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
++ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
++ 532) # CPU_PA_RISC2_0
++ case "${sc_kernel_bits}" in
++ 32) HP_ARCH="hppa2.0n" ;;
++ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+- esac ;;
+- esac
++ esac ;;
++ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+- sed 's/^ //' << EOF >$dummy.c
++ sed 's/^ //' << EOF >$dummy.c
++
++ #define _HPUX_SOURCE
++ #include <stdlib.h>
++ #include <unistd.h>
++
++ int main ()
++ {
++ #if defined(_SC_KERNEL_BITS)
++ long bits = sysconf(_SC_KERNEL_BITS);
++ #endif
++ long cpu = sysconf (_SC_CPU_VERSION);
+
+- #define _HPUX_SOURCE
+- #include <stdlib.h>
+- #include <unistd.h>
+-
+- int main ()
+- {
+- #if defined(_SC_KERNEL_BITS)
+- long bits = sysconf(_SC_KERNEL_BITS);
+- #endif
+- long cpu = sysconf (_SC_CPU_VERSION);
+-
+- switch (cpu)
+- {
+- case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+- case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+- case CPU_PA_RISC2_0:
+- #if defined(_SC_KERNEL_BITS)
+- switch (bits)
+- {
+- case 64: puts ("hppa2.0w"); break;
+- case 32: puts ("hppa2.0n"); break;
+- default: puts ("hppa2.0"); break;
+- } break;
+- #else /* !defined(_SC_KERNEL_BITS) */
+- puts ("hppa2.0"); break;
+- #endif
+- default: puts ("hppa1.0"); break;
+- }
+- exit (0);
+- }
++ switch (cpu)
++ {
++ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
++ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
++ case CPU_PA_RISC2_0:
++ #if defined(_SC_KERNEL_BITS)
++ switch (bits)
++ {
++ case 64: puts ("hppa2.0w"); break;
++ case 32: puts ("hppa2.0n"); break;
++ default: puts ("hppa2.0"); break;
++ } break;
++ #else /* !defined(_SC_KERNEL_BITS) */
++ puts ("hppa2.0"); break;
++ #endif
++ default: puts ("hppa1.0"); break;
++ }
++ exit (0);
++ }
+ EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+@@ -730,22 +751,22 @@
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+- exit ;;
++ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+- exit ;;
++ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+- exit ;;
++ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+- exit ;;
++ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+- exit ;;
++ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+@@ -769,14 +790,14 @@
+ exit ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+- FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+- echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+- exit ;;
++ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
++ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
++ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
++ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+- FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+- echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
++ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
++ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
++ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+@@ -788,30 +809,35 @@
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:FreeBSD:*:*)
+- case ${UNAME_MACHINE} in
+- pc98)
+- echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
++ UNAME_PROCESSOR=`/usr/bin/uname -p`
++ case ${UNAME_PROCESSOR} in
+ amd64)
+ echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ *)
+- echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
++ echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ esac
+ exit ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit ;;
++ *:MINGW64*:*)
++ echo ${UNAME_MACHINE}-pc-mingw64
++ exit ;;
+ *:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
++ *:MSYS*:*)
++ echo ${UNAME_MACHINE}-pc-msys
++ exit ;;
+ i*:windows32*:*)
+- # uname -m includes "-pc" on this system.
+- echo ${UNAME_MACHINE}-mingw32
++ # uname -m includes "-pc" on this system.
++ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ *:Interix*:*)
+- case ${UNAME_MACHINE} in
++ case ${UNAME_MACHINE} in
+ x86)
+ echo i586-pc-interix${UNAME_RELEASE}
+ exit ;;
+@@ -848,15 +874,22 @@
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+- echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
++ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+- echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
++ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit ;;
++ aarch64:Linux:*:*)
++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
++ exit ;;
++ aarch64_be:Linux:*:*)
++ UNAME_MACHINE=aarch64_be
++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
++ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+@@ -866,52 +899,56 @@
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+- esac
++ esac
+ objdump --private-headers /bin/sh | grep -q ld.so.1
+- if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+- echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
++ if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
++ exit ;;
++ arc:Linux:*:* | arceb:Linux:*:*)
++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ arm*:Linux:*:*)
+ eval $set_cc_for_build
+ if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_EABI__
+ then
+- echo ${UNAME_MACHINE}-unknown-linux-gnu
++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ else
+- echo ${UNAME_MACHINE}-unknown-linux-gnueabi
++ if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
++ | grep -q __ARM_PCS_VFP
++ then
++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
++ else
++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
++ fi
+ fi
+ exit ;;
+ avr32*:Linux:*:*)
+- echo ${UNAME_MACHINE}-unknown-linux-gnu
++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ cris:Linux:*:*)
+- echo cris-axis-linux-gnu
++ echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+ exit ;;
+ crisv32:Linux:*:*)
+- echo crisv32-axis-linux-gnu
++ echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+ exit ;;
+ frv:Linux:*:*)
+- echo frv-unknown-linux-gnu
++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
++ exit ;;
++ hexagon:Linux:*:*)
++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ i*86:Linux:*:*)
+- LIBC=gnu
+- eval $set_cc_for_build
+- sed 's/^ //' << EOF >$dummy.c
+- #ifdef __dietlibc__
+- LIBC=dietlibc
+- #endif
+-EOF
+- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
+- echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
++ echo ${UNAME_MACHINE}-pc-linux-${LIBC}
+ exit ;;
+ ia64:Linux:*:*)
+- echo ${UNAME_MACHINE}-unknown-linux-gnu
++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ m32r*:Linux:*:*)
+- echo ${UNAME_MACHINE}-unknown-linux-gnu
++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ m68*:Linux:*:*)
+- echo ${UNAME_MACHINE}-unknown-linux-gnu
++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ mips:Linux:*:* | mips64:Linux:*:*)
+ eval $set_cc_for_build
+@@ -930,51 +967,63 @@
+ #endif
+ EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
+- test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
++ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
+ ;;
+- or32:Linux:*:*)
+- echo or32-unknown-linux-gnu
++ openrisc*:Linux:*:*)
++ echo or1k-unknown-linux-${LIBC}
++ exit ;;
++ or32:Linux:*:* | or1k*:Linux:*:*)
++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ padre:Linux:*:*)
+- echo sparc-unknown-linux-gnu
++ echo sparc-unknown-linux-${LIBC}
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+- echo hppa64-unknown-linux-gnu
++ echo hppa64-unknown-linux-${LIBC}
+ exit ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+- PA7*) echo hppa1.1-unknown-linux-gnu ;;
+- PA8*) echo hppa2.0-unknown-linux-gnu ;;
+- *) echo hppa-unknown-linux-gnu ;;
++ PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
++ PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
++ *) echo hppa-unknown-linux-${LIBC} ;;
+ esac
+ exit ;;
+ ppc64:Linux:*:*)
+- echo powerpc64-unknown-linux-gnu
++ echo powerpc64-unknown-linux-${LIBC}
+ exit ;;
+ ppc:Linux:*:*)
+- echo powerpc-unknown-linux-gnu
++ echo powerpc-unknown-linux-${LIBC}
++ exit ;;
++ ppc64le:Linux:*:*)
++ echo powerpc64le-unknown-linux-${LIBC}
++ exit ;;
++ ppcle:Linux:*:*)
++ echo powerpcle-unknown-linux-${LIBC}
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+- echo ${UNAME_MACHINE}-ibm-linux
++ echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
+ exit ;;
+ sh64*:Linux:*:*)
+- echo ${UNAME_MACHINE}-unknown-linux-gnu
++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ sh*:Linux:*:*)
+- echo ${UNAME_MACHINE}-unknown-linux-gnu
++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+- echo ${UNAME_MACHINE}-unknown-linux-gnu
++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
++ exit ;;
++ tile*:Linux:*:*)
++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ vax:Linux:*:*)
+- echo ${UNAME_MACHINE}-dec-linux-gnu
++ echo ${UNAME_MACHINE}-dec-linux-${LIBC}
+ exit ;;
+ x86_64:Linux:*:*)
+- echo x86_64-unknown-linux-gnu
++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ xtensa*:Linux:*:*)
+- echo ${UNAME_MACHINE}-unknown-linux-gnu
++ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+@@ -983,11 +1032,11 @@
+ echo i386-sequent-sysv4
+ exit ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+- # Unixware is an offshoot of SVR4, but it has its own version
+- # number series starting with 2...
+- # I am not positive that other SVR4 systems won't match this,
++ # Unixware is an offshoot of SVR4, but it has its own version
++ # number series starting with 2...
++ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+- # Use sysv4.2uw... so that sysv4* matches it.
++ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit ;;
+ i*86:OS/2:*:*)
+@@ -1019,7 +1068,7 @@
+ fi
+ exit ;;
+ i*86:*:5:[678]*)
+- # UnixWare 7.x, OpenUNIX and OpenServer 6.
++ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+@@ -1047,13 +1096,13 @@
+ exit ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+- # uname -m prints for DJGPP always 'pc', but it prints nothing about
+- # the processor, so we play safe by assuming i586.
++ # uname -m prints for DJGPP always 'pc', but it prints nothing about
++ # the processor, so we play safe by assuming i586.
+ # Note: whatever this is, it MUST be the same as what config.sub
+ # prints for the "djgpp" host, or else GDB configury will decide that
+ # this is a cross-build.
+ echo i586-pc-msdosdjgpp
+- exit ;;
++ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+@@ -1088,8 +1137,8 @@
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+- /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+- && { echo i486-ncr-sysv4; exit; } ;;
++ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
++ && { echo i486-ncr-sysv4; exit; } ;;
+ NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+ OS_REL='.3'
+ test -r /etc/.relid \
+@@ -1132,10 +1181,10 @@
+ echo ns32k-sni-sysv
+ fi
+ exit ;;
+- PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+- # says <Richard.M.Bartel@ccMail.Census.GOV>
+- echo i586-unisys-sysv4
+- exit ;;
++ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
++ # says <Richard.M.Bartel@ccMail.Census.GOV>
++ echo i586-unisys-sysv4
++ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+@@ -1161,11 +1210,11 @@
+ exit ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+- echo mips-nec-sysv${UNAME_RELEASE}
++ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+- echo mips-unknown-sysv${UNAME_RELEASE}
++ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+- exit ;;
++ exit ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+@@ -1178,6 +1227,9 @@
+ BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
+ echo i586-pc-haiku
+ exit ;;
++ x86_64:Haiku:*:*)
++ echo x86_64-unknown-haiku
++ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit ;;
+@@ -1204,19 +1256,31 @@
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+- case $UNAME_PROCESSOR in
+- i386)
+- eval $set_cc_for_build
+- if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+- if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+- (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+- grep IS_64BIT_ARCH >/dev/null
+- then
+- UNAME_PROCESSOR="x86_64"
+- fi
+- fi ;;
+- unknown) UNAME_PROCESSOR=powerpc ;;
+- esac
++ eval $set_cc_for_build
++ if test "$UNAME_PROCESSOR" = unknown ; then
++ UNAME_PROCESSOR=powerpc
++ fi
++ if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
++ if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
++ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
++ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
++ grep IS_64BIT_ARCH >/dev/null
++ then
++ case $UNAME_PROCESSOR in
++ i386) UNAME_PROCESSOR=x86_64 ;;
++ powerpc) UNAME_PROCESSOR=powerpc64 ;;
++ esac
++ fi
++ fi
++ elif test "$UNAME_PROCESSOR" = i386 ; then
++ # Avoid executing cc on OS X 10.9, as it ships with a stub
++ # that puts up a graphical alert prompting to install
++ # developer tools. Any system running Mac OS X 10.7 or
++ # later (Darwin 11 and later) is required to have a 64-bit
++ # processor. This is not true of the ARM version of Darwin
++ # that Apple uses in portable devices.
++ UNAME_PROCESSOR=x86_64
++ fi
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+@@ -1230,7 +1294,10 @@
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+- NSE-?:NONSTOP_KERNEL:*:*)
++ NEO-?:NONSTOP_KERNEL:*:*)
++ echo neo-tandem-nsk${UNAME_RELEASE}
++ exit ;;
++ NSE-*:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+@@ -1275,13 +1342,13 @@
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+- echo mips-sei-seiux${UNAME_RELEASE}
++ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+- UNAME_MACHINE=`(uname -p) 2>/dev/null`
++ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+@@ -1299,158 +1366,10 @@
+ i*86:AROS:*:*)
+ echo ${UNAME_MACHINE}-pc-aros
+ exit ;;
+-esac
+-
+-#echo '(No uname command or uname output not recognized.)' 1>&2
+-#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+-
+-eval $set_cc_for_build
+-cat >$dummy.c <<EOF
+-#ifdef _SEQUENT_
+-# include <sys/types.h>
+-# include <sys/utsname.h>
+-#endif
+-main ()
+-{
+-#if defined (sony)
+-#if defined (MIPSEB)
+- /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+- I don't know.... */
+- printf ("mips-sony-bsd\n"); exit (0);
+-#else
+-#include <sys/param.h>
+- printf ("m68k-sony-newsos%s\n",
+-#ifdef NEWSOS4
+- "4"
+-#else
+- ""
+-#endif
+- ); exit (0);
+-#endif
+-#endif
+-
+-#if defined (__arm) && defined (__acorn) && defined (__unix)
+- printf ("arm-acorn-riscix\n"); exit (0);
+-#endif
+-
+-#if defined (hp300) && !defined (hpux)
+- printf ("m68k-hp-bsd\n"); exit (0);
+-#endif
+-
+-#if defined (NeXT)
+-#if !defined (__ARCHITECTURE__)
+-#define __ARCHITECTURE__ "m68k"
+-#endif
+- int version;
+- version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+- if (version < 4)
+- printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+- else
+- printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+- exit (0);
+-#endif
+-
+-#if defined (MULTIMAX) || defined (n16)
+-#if defined (UMAXV)
+- printf ("ns32k-encore-sysv\n"); exit (0);
+-#else
+-#if defined (CMU)
+- printf ("ns32k-encore-mach\n"); exit (0);
+-#else
+- printf ("ns32k-encore-bsd\n"); exit (0);
+-#endif
+-#endif
+-#endif
+-
+-#if defined (__386BSD__)
+- printf ("i386-pc-bsd\n"); exit (0);
+-#endif
+-
+-#if defined (sequent)
+-#if defined (i386)
+- printf ("i386-sequent-dynix\n"); exit (0);
+-#endif
+-#if defined (ns32000)
+- printf ("ns32k-sequent-dynix\n"); exit (0);
+-#endif
+-#endif
+-
+-#if defined (_SEQUENT_)
+- struct utsname un;
+-
+- uname(&un);
+-
+- if (strncmp(un.version, "V2", 2) == 0) {
+- printf ("i386-sequent-ptx2\n"); exit (0);
+- }
+- if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+- printf ("i386-sequent-ptx1\n"); exit (0);
+- }
+- printf ("i386-sequent-ptx\n"); exit (0);
+-
+-#endif
+-
+-#if defined (vax)
+-# if !defined (ultrix)
+-# include <sys/param.h>
+-# if defined (BSD)
+-# if BSD == 43
+- printf ("vax-dec-bsd4.3\n"); exit (0);
+-# else
+-# if BSD == 199006
+- printf ("vax-dec-bsd4.3reno\n"); exit (0);
+-# else
+- printf ("vax-dec-bsd\n"); exit (0);
+-# endif
+-# endif
+-# else
+- printf ("vax-dec-bsd\n"); exit (0);
+-# endif
+-# else
+- printf ("vax-dec-ultrix\n"); exit (0);
+-# endif
+-#endif
+-
+-#if defined (alliant) && defined (i860)
+- printf ("i860-alliant-bsd\n"); exit (0);
+-#endif
+-
+- exit (1);
+-}
+-EOF
+-
+-$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+- { echo "$SYSTEM_NAME"; exit; }
+-
+-# Apollos put the system type in the environment.
+-
+-test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+-
+-# Convex versions that predate uname can use getsysinfo(1)
+-
+-if [ -x /usr/convex/getsysinfo ]
+-then
+- case `getsysinfo -f cpu_type` in
+- c1*)
+- echo c1-convex-bsd
+- exit ;;
+- c2*)
+- if getsysinfo -f scalar_acc
+- then echo c32-convex-bsd
+- else echo c2-convex-bsd
+- fi
++ x86_64:VMkernel:*:*)
++ echo ${UNAME_MACHINE}-unknown-esx
+ exit ;;
+- c34*)
+- echo c34-convex-bsd
+- exit ;;
+- c38*)
+- echo c38-convex-bsd
+- exit ;;
+- c4*)
+- echo c4-convex-bsd
+- exit ;;
+- esac
+-fi
++esac
+
+ cat >&2 <<EOF
+ $0: unable to guess system type
+diff -ur librsvg-2.36.1-orig/config.sub librsvg-2.36.1/config.sub
+--- librsvg-2.36.1-orig/config.sub 2012-02-03 13:14:58.000000000 +0100
++++ librsvg-2.36.1/config.sub 2014-09-25 18:37:12.000000000 +0200
+@@ -1,38 +1,31 @@
+ #! /bin/sh
+ # Configuration validation subroutine script.
+-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+-# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+-# Free Software Foundation, Inc.
+-
+-timestamp='2009-11-20'
+-
+-# This file is (in principle) common to ALL GNU software.
+-# The presence of a machine in this file suggests that SOME GNU software
+-# can handle that machine. It does not imply ALL GNU software can.
+-#
+-# This file is free software; you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation; either version 2 of the License, or
++# Copyright 1992-2014 Free Software Foundation, Inc.
++
++timestamp='2014-09-11'
++
++# This file is free software; you can redistribute it and/or modify it
++# under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 3 of the License, or
+ # (at your option) any later version.
+ #
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU General Public License for more details.
++# This program is distributed in the hope that it will be useful, but
++# WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++# General Public License for more details.
+ #
+ # You should have received a copy of the GNU General Public License
+-# along with this program; if not, write to the Free Software
+-# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+-# 02110-1301, USA.
++# along with this program; if not, see <http://www.gnu.org/licenses/>.
+ #
+ # As a special exception to the GNU General Public License, if you
+ # distribute this file as part of a program that contains a
+ # configuration script generated by Autoconf, you may include it under
+-# the same distribution terms that you use for the rest of that program.
++# the same distribution terms that you use for the rest of that
++# program. This Exception is an additional permission under section 7
++# of the GNU General Public License, version 3 ("GPLv3").
+
+
+-# Please send patches to <config-patches@gnu.org>. Submit a context
+-# diff and a properly formatted GNU ChangeLog entry.
++# Please send patches with a ChangeLog entry to config-patches@gnu.org.
+ #
+ # Configuration subroutine to validate and canonicalize a configuration type.
+ # Supply the specified configuration type as an argument.
+@@ -75,8 +68,7 @@
+ version="\
+ GNU config.sub ($timestamp)
+
+-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+-2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
++Copyright 1992-2014 Free Software Foundation, Inc.
+
+ This is free software; see the source for copying conditions. There is NO
+ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+@@ -123,13 +115,18 @@
+ # Here we must recognize all the valid KERNEL-OS combinations.
+ maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+ case $maybe_os in
+- nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+- uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
++ nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
++ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
++ knetbsd*-gnu* | netbsd*-gnu* | \
+ kopensolaris*-gnu* | \
+ storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
++ android-linux)
++ os=-linux-android
++ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
++ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+@@ -152,12 +149,12 @@
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+- -apple | -axis | -knuth | -cray | -microblaze)
++ -apple | -axis | -knuth | -cray | -microblaze*)
+ os=
+ basic_machine=$1
+ ;;
+- -bluegene*)
+- os=-cnk
++ -bluegene*)
++ os=-cnk
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+@@ -173,10 +170,10 @@
+ os=-chorusos
+ basic_machine=$1
+ ;;
+- -chorusrdb)
+- os=-chorusrdb
++ -chorusrdb)
++ os=-chorusrdb
+ basic_machine=$1
+- ;;
++ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+@@ -221,6 +218,12 @@
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
++ -lynx*178)
++ os=-lynxos178
++ ;;
++ -lynx*5)
++ os=-lynxos5
++ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+@@ -245,20 +248,28 @@
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
++ | aarch64 | aarch64_be \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+- | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
++ | arc | arceb \
++ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
++ | avr | avr32 \
++ | be32 | be64 \
+ | bfin \
+- | c4x | clipper \
++ | c4x | c8051 | clipper \
+ | d10v | d30v | dlx | dsp16xx \
++ | epiphany \
+ | fido | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
++ | hexagon \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
++ | k1om \
++ | le32 | le64 \
+ | lm32 \
+ | m32c | m32r | m32rle | m68000 | m68k | m88k \
+- | maxq | mb | microblaze | mcore | mep | metag \
++ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+@@ -272,38 +283,51 @@
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
++ | mipsisa32r6 | mipsisa32r6el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
++ | mipsisa64r6 | mipsisa64r6el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
++ | mipsr5900 | mipsr5900el \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | moxie \
+ | mt \
+ | msp430 \
+- | nios | nios2 \
++ | nds32 | nds32le | nds32be \
++ | nios | nios2 | nios2eb | nios2el \
+ | ns16k | ns32k \
+- | or32 \
++ | open8 | or1k | or1knd | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+- | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
++ | powerpc | powerpc64 | powerpc64le | powerpcle \
+ | pyramid \
+- | rx \
++ | riscv32 | riscv64 \
++ | rl78 | rx \
+ | score \
+ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+- | spu | strongarm \
+- | tahoe | thumb | tic4x | tic80 | tron \
++ | spu \
++ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+ | ubicom32 \
+- | v850 | v850e \
++ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+ | we32k \
+- | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
++ | x86 | xc16x | xstormy16 | xtensa \
+ | z8k | z80)
+ basic_machine=$basic_machine-unknown
+ ;;
+- m6811 | m68hc11 | m6812 | m68hc12 | picochip)
+- # Motorola 68HC11/12.
++ c54x)
++ basic_machine=tic54x-unknown
++ ;;
++ c55x)
++ basic_machine=tic55x-unknown
++ ;;
++ c6x)
++ basic_machine=tic6x-unknown
++ ;;
++ m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+@@ -313,6 +337,21 @@
+ basic_machine=mt-unknown
+ ;;
+
++ strongarm | thumb | xscale)
++ basic_machine=arm-unknown
++ ;;
++ xgate)
++ basic_machine=$basic_machine-unknown
++ os=-none
++ ;;
++ xscaleeb)
++ basic_machine=armeb-unknown
++ ;;
++
++ xscaleel)
++ basic_machine=armel-unknown
++ ;;
++
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+@@ -327,25 +366,31 @@
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
++ | aarch64-* | aarch64_be-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+- | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
++ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* | avr32-* \
++ | be32-* | be64-* \
+ | bfin-* | bs2000-* \
+- | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+- | clipper-* | craynv-* | cydra-* \
++ | c[123]* | c30-* | [cjt]90-* | c4x-* \
++ | c8051-* | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
++ | hexagon-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
++ | k1om-* \
++ | le32-* | le64-* \
+ | lm32-* \
+ | m32c-* | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+- | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
++ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
++ | microblaze-* | microblazeel-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+@@ -359,33 +404,41 @@
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
++ | mipsisa32r6-* | mipsisa32r6el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
++ | mipsisa64r6-* | mipsisa64r6el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
++ | mipsr5900-* | mipsr5900el-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | mt-* \
+ | msp430-* \
+- | nios-* | nios2-* \
++ | nds32-* | nds32le-* | nds32be-* \
++ | nios-* | nios2-* | nios2eb-* | nios2el-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
++ | open8-* \
++ | or1k*-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+- | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
++ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+ | pyramid-* \
+- | romp-* | rs6000-* | rx-* \
++ | rl78-* | romp-* | rs6000-* | rx-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+- | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
+- | tahoe-* | thumb-* \
+- | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \
++ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
++ | tahoe-* \
++ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
++ | tile*-* \
+ | tron-* \
+ | ubicom32-* \
+- | v850-* | v850e-* | vax-* \
++ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
++ | vax-* \
+ | we32k-* \
+- | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
++ | x86-* | x86_64-* | xc16x-* | xps100-* \
+ | xstormy16-* | xtensa*-* \
+ | ymp-* \
+ | z8k-* | z80-*)
+@@ -410,7 +463,7 @@
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+- abacus)
++ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+@@ -480,11 +533,20 @@
+ basic_machine=powerpc-ibm
+ os=-cnk
+ ;;
++ c54x-*)
++ basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
++ ;;
++ c55x-*)
++ basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
++ ;;
++ c6x-*)
++ basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
++ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+- cegcc)
++ cegcc)
+ basic_machine=arm-unknown
+ os=-cegcc
+ ;;
+@@ -516,7 +578,7 @@
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+- cr16)
++ cr16 | cr16-*)
+ basic_machine=cr16-unknown
+ os=-elf
+ ;;
+@@ -674,7 +736,6 @@
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+-# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+@@ -732,11 +793,15 @@
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+- microblaze)
++ microblaze*)
+ basic_machine=microblaze-xilinx
+ ;;
++ mingw64)
++ basic_machine=x86_64-pc
++ os=-mingw64
++ ;;
+ mingw32)
+- basic_machine=i386-pc
++ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ mingw32ce)
+@@ -764,6 +829,10 @@
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
++ moxiebox)
++ basic_machine=moxie-unknown
++ os=-moxiebox
++ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+@@ -771,10 +840,18 @@
+ ms1-*)
+ basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+ ;;
++ msys)
++ basic_machine=i686-pc
++ os=-msys
++ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
++ nacl)
++ basic_machine=le32-unknown
++ os=-nacl
++ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+@@ -839,6 +916,12 @@
+ np1)
+ basic_machine=np1-gould
+ ;;
++ neo-tandem)
++ basic_machine=neo-tandem
++ ;;
++ nse-tandem)
++ basic_machine=nse-tandem
++ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+@@ -921,9 +1004,10 @@
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+- ppc) basic_machine=powerpc-unknown
++ ppc | ppcbe) basic_machine=powerpc-unknown
+ ;;
+- ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
++ ppc-* | ppcbe-*)
++ basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+@@ -948,7 +1032,11 @@
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+- rdos)
++ rdos | rdos64)
++ basic_machine=x86_64-pc
++ os=-rdos
++ ;;
++ rdos32)
+ basic_machine=i386-pc
+ os=-rdos
+ ;;
+@@ -1017,6 +1105,9 @@
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
++ strongarm-* | thumb-*)
++ basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
++ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+@@ -1073,20 +1164,8 @@
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+- tic54x | c54x*)
+- basic_machine=tic54x-unknown
+- os=-coff
+- ;;
+- tic55x | c55x*)
+- basic_machine=tic55x-unknown
+- os=-coff
+- ;;
+- tic6x | c6x*)
+- basic_machine=tic6x-unknown
+- os=-coff
+- ;;
+ tile*)
+- basic_machine=tile-unknown
++ basic_machine=$basic_machine-unknown
+ os=-linux-gnu
+ ;;
+ tx39)
+@@ -1156,6 +1235,9 @@
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
++ xscale-* | xscalee[bl]-*)
++ basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
++ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+@@ -1253,11 +1335,11 @@
+ if [ x"$os" != x"" ]
+ then
+ case $os in
+- # First match some system type aliases
+- # that might get confused with valid system types.
++ # First match some system type aliases
++ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+- -auroraux)
+- os=-auroraux
++ -auroraux)
++ os=-auroraux
+ ;;
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+@@ -1281,28 +1363,29 @@
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+- | -sym* | -kopensolaris* \
++ | -sym* | -kopensolaris* | -plan9* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* | -aros* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+- | -openbsd* | -solidbsd* \
++ | -bitrig* | -openbsd* | -solidbsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* | -cegcc* \
+- | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+- | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+- | -uxpv* | -beos* | -mpeix* | -udk* \
++ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
++ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
++ | -linux-newlib* | -linux-musl* | -linux-uclibc* \
++ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+- | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
++ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+@@ -1341,7 +1424,7 @@
+ -opened*)
+ os=-openedition
+ ;;
+- -os400*)
++ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+@@ -1390,7 +1473,7 @@
+ -sinix*)
+ os=-sysv4
+ ;;
+- -tpf*)
++ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+@@ -1426,15 +1509,14 @@
+ -aros*)
+ os=-aros
+ ;;
+- -kaos*)
+- os=-kaos
+- ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -dicos*)
+ os=-dicos
+ ;;
++ -nacl*)
++ ;;
+ -none)
+ ;;
+ *)
+@@ -1457,10 +1539,10 @@
+ # system, and we'll never get to this point.
+
+ case $basic_machine in
+- score-*)
++ score-*)
+ os=-elf
+ ;;
+- spu-*)
++ spu-*)
+ os=-elf
+ ;;
+ *-acorn)
+@@ -1472,8 +1554,23 @@
+ arm*-semi)
+ os=-aout
+ ;;
+- c4x-* | tic4x-*)
+- os=-coff
++ c4x-* | tic4x-*)
++ os=-coff
++ ;;
++ c8051-*)
++ os=-elf
++ ;;
++ hexagon-*)
++ os=-elf
++ ;;
++ tic54x-*)
++ os=-coff
++ ;;
++ tic55x-*)
++ os=-coff
++ ;;
++ tic6x-*)
++ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+@@ -1493,14 +1590,11 @@
+ ;;
+ m68000-sun)
+ os=-sunos3
+- # This also exists in the configure program, but was not the
+- # default.
+- # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+- mep-*)
++ mep-*)
+ os=-elf
+ ;;
+ mips*-cisco)
+@@ -1527,7 +1621,7 @@
+ *-ibm)
+ os=-aix
+ ;;
+- *-knuth)
++ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
diff --git a/Tools/gtk/patches/mesa-gallivm-Fix-build-after-LLVM-commit-211259.patch b/Tools/gtk/patches/mesa-gallivm-Fix-build-after-LLVM-commit-211259.patch
new file mode 100644
index 000000000..75f38e552
--- /dev/null
+++ b/Tools/gtk/patches/mesa-gallivm-Fix-build-after-LLVM-commit-211259.patch
@@ -0,0 +1,29 @@
+From 564821c917f4a9d5a0de2ee77b90b0cd85e3d3a6 Mon Sep 17 00:00:00 2001
+From: Aaron Watry <awatry@gmail.com>
+Date: Fri, 20 Jun 2014 19:13:30 -0500
+Subject: [PATCH] gallivm: Fix build after LLVM commit 211259
+
+Signed-off-by: Aaron Watry <awatry@gmail.com>
+Reviewed-by: Tom Stellard <thomas.stellard@amd.com>
+---
+ src/gallium/auxiliary/gallivm/lp_bld_debug.cpp | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/gallium/auxiliary/gallivm/lp_bld_debug.cpp b/src/gallium/auxiliary/gallivm/lp_bld_debug.cpp
+index df26883..413a0c2 100644
+--- a/src/gallium/auxiliary/gallivm/lp_bld_debug.cpp
++++ b/src/gallium/auxiliary/gallivm/lp_bld_debug.cpp
+@@ -51,7 +51,9 @@
+ #include <llvm/MC/MCInstPrinter.h>
+ #include <llvm/MC/MCRegisterInfo.h>
+
+-#if HAVE_LLVM >= 0x0303
++#if HAVE_LLVM >= 0x0305
++#define OwningPtr std::unique_ptr
++#elif HAVE_LLVM >= 0x0303
+ #include <llvm/ADT/OwningPtr.h>
+ #endif
+
+--
+2.1.0
+
diff --git a/Tools/gtk/patches/rtspsrc-timeout-on-udpsrc-is-in-nanoseconds.patch b/Tools/gtk/patches/rtspsrc-timeout-on-udpsrc-is-in-nanoseconds.patch
new file mode 100644
index 000000000..87ed49087
--- /dev/null
+++ b/Tools/gtk/patches/rtspsrc-timeout-on-udpsrc-is-in-nanoseconds.patch
@@ -0,0 +1,27 @@
+From e0bb1fe30985aa0784825388500cc4fa92c1ff9c Mon Sep 17 00:00:00 2001
+From: Wim Taymans <wim.taymans@collabora.co.uk>
+Date: Wed, 12 Dec 2012 11:09:42 +0100
+Subject: [PATCH 2/2] rtspsrc: timeout on udpsrc is in nanoseconds
+
+---
+ gst/rtsp/gstrtspsrc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/gst/rtsp/gstrtspsrc.c b/gst/rtsp/gstrtspsrc.c
+index 98577b8..902d8ff 100644
+--- a/gst/rtsp/gstrtspsrc.c
++++ b/gst/rtsp/gstrtspsrc.c
+@@ -2812,8 +2812,8 @@ gst_rtspsrc_stream_configure_udp (GstRTSPSrc * src, GstRTSPStream * stream,
+ /* configure a timeout on the UDP port. When the timeout message is
+ * posted, we assume UDP transport is not possible. We reconnect using TCP
+ * if we can. */
+- g_object_set (G_OBJECT (stream->udpsrc[0]), "timeout", src->udp_timeout,
+- NULL);
++ g_object_set (G_OBJECT (stream->udpsrc[0]), "timeout",
++ src->udp_timeout * 1000, NULL);
+
+ /* get output pad of the UDP source. */
+ *outpad = gst_element_get_static_pad (stream->udpsrc[0], "src");
+--
+1.8.1.2
+
diff --git a/Tools/gtk/patches/shared-mime-info-xht-glob.patch b/Tools/gtk/patches/shared-mime-info-xht-glob.patch
new file mode 100644
index 000000000..667ae4991
--- /dev/null
+++ b/Tools/gtk/patches/shared-mime-info-xht-glob.patch
@@ -0,0 +1,21 @@
+From 6e5818deb54fdfa70f5798fc1df1d5c3eaba42df Mon Sep 17 00:00:00 2001
+From: Bastien Nocera <hadess@hadess.net>
+Date: Thu, 7 Jan 2016 15:48:47 +0100
+Subject: Add *.xht as a glob for XHTML files
+
+
+diff --git a/freedesktop.org.xml.in b/freedesktop.org.xml.in
+index dc12655..48696d9 100644
+--- a/freedesktop.org.xml.in
++++ b/freedesktop.org.xml.in
+@@ -3669,6 +3669,7 @@ command to generate the output files.
+ <sub-class-of type="application/xml"/>
+ <generic-icon name="text-html"/>
+ <glob pattern="*.xhtml"/>
++ <glob pattern="*.xht"/>
+ <root-XML namespaceURI='http://www.w3.org/1999/xhtml' localName='html'/>
+ </mime-type>
+ <mime-type type="application/zip">
+--
+cgit v0.10.2
+
diff --git a/Tools/gtk/patches/shared-mime-info-xhtml-magic.patch b/Tools/gtk/patches/shared-mime-info-xhtml-magic.patch
new file mode 100644
index 000000000..4d0e81615
--- /dev/null
+++ b/Tools/gtk/patches/shared-mime-info-xhtml-magic.patch
@@ -0,0 +1,26 @@
+From 4961dc3e48d13c0c675ad7c135419b864813ca55 Mon Sep 17 00:00:00 2001
+From: Bastien Nocera <hadess@hadess.net>
+Date: Thu, 7 Jan 2016 15:49:16 +0100
+Subject: Add magic for XHTML files
+
+
+diff --git a/freedesktop.org.xml.in b/freedesktop.org.xml.in
+index 48696d9..9ea2f95 100644
+--- a/freedesktop.org.xml.in
++++ b/freedesktop.org.xml.in
+@@ -3670,6 +3670,12 @@ command to generate the output files.
+ <generic-icon name="text-html"/>
+ <glob pattern="*.xhtml"/>
+ <glob pattern="*.xht"/>
++ <magic priority="60">
++ <match type="string" value="//W3C//DTD XHTML " offset="0:256"/>
++ <match type="string" value="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" offset="0:256"/>
++ <match type="string" value="&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml" offset="0:256"/>
++ <match type="string" value="&lt;HTML xmlns=&quot;http://www.w3.org/1999/xhtml" offset="0:256"/>
++ </magic>
+ <root-XML namespaceURI='http://www.w3.org/1999/xhtml' localName='html'/>
+ </mime-type>
+ <mime-type type="application/zip">
+--
+cgit v0.10.2
+
diff --git a/Tools/gtk/patches/udpsrc-improve-timeouts.patch b/Tools/gtk/patches/udpsrc-improve-timeouts.patch
new file mode 100644
index 000000000..d26e346a8
--- /dev/null
+++ b/Tools/gtk/patches/udpsrc-improve-timeouts.patch
@@ -0,0 +1,53 @@
+From dbbdf54778771535dfea5ddbdeeaba89d9bc7be6 Mon Sep 17 00:00:00 2001
+From: Wim Taymans <wim.taymans@collabora.co.uk>
+Date: Wed, 12 Dec 2012 11:08:13 +0100
+Subject: [PATCH 1/2] udpsrc: improve timeouts
+
+Make it possible to set the timeout after we went to the READY state by using
+the timeout when checking the condition. This also makes it possible to set the
+timeout with a higher granularity than seconds.
+---
+ gst/udp/gstudpsrc.c | 16 ++++++++++------
+ 1 file changed, 10 insertions(+), 6 deletions(-)
+
+diff --git a/gst/udp/gstudpsrc.c b/gst/udp/gstudpsrc.c
+index bdad5b3..5b54021 100644
+--- a/gst/udp/gstudpsrc.c
++++ b/gst/udp/gstudpsrc.c
+@@ -397,13 +397,20 @@ retry:
+ goto no_select;
+
+ do {
++ gint64 timeout;
++
+ try_again = FALSE;
+
++ if (udpsrc->timeout)
++ timeout = udpsrc->timeout / 1000;
++ else
++ timeout = -1;
++
+ GST_LOG_OBJECT (udpsrc, "doing select, timeout %" G_GUINT64_FORMAT,
+- udpsrc->timeout);
++ timeout);
+
+- if (!g_socket_condition_wait (udpsrc->used_socket, G_IO_IN | G_IO_PRI,
+- udpsrc->cancellable, &err)) {
++ if (!g_socket_condition_timed_wait (udpsrc->used_socket, G_IO_IN | G_IO_PRI,
++ timeout, udpsrc->cancellable, &err)) {
+ if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_BUSY)
+ || g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ goto stopped;
+@@ -823,9 +830,6 @@ gst_udpsrc_start (GstBaseSrc * bsrc)
+ goto getsockname_error;
+ }
+
+- if (src->timeout)
+- g_socket_set_timeout (src->used_socket, src->timeout / GST_SECOND);
+-
+ #if GLIB_CHECK_VERSION (2, 35, 7)
+ {
+ gint val = 0;
+--
+1.8.1.2
+
diff --git a/Tools/gtk/patches/xserver-remove-bogus-dependencies.patch b/Tools/gtk/patches/xserver-remove-bogus-dependencies.patch
new file mode 100644
index 000000000..e17753e37
--- /dev/null
+++ b/Tools/gtk/patches/xserver-remove-bogus-dependencies.patch
@@ -0,0 +1,43 @@
+From 879f42531ff04be578c39f9d44548aeb3ded67fd Mon Sep 17 00:00:00 2001
+From: Gustavo Noronha Silva <gustavo.noronha@collabora.com>
+Date: Wed, 8 May 2013 19:44:15 -0300
+Subject: [PATCH 2/2] Filter out -l parameters when setting dependencies
+
+Newer make (Fedora 19) gets confused when it finds a -l parameter in a
+dependency, and tries to make it as a target, causing the build to fail.
+
+Signed-off-by: Gustavo Noronha Silva <gustavo.noronha@collabora.com>
+---
+ hw/vfb/Makefile.am | 2 +-
+ test/Makefile.am | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/hw/vfb/Makefile.am b/hw/vfb/Makefile.am
+index 9f4992c..06830ae 100644
+--- a/hw/vfb/Makefile.am
++++ b/hw/vfb/Makefile.am
+@@ -20,7 +20,7 @@ XVFB_LIBS = \
+ $(top_builddir)/Xi/libXistubs.la
+
+ Xvfb_LDADD = $(XVFB_LIBS) $(XVFB_SYS_LIBS) $(XSERVER_SYS_LIBS)
+-Xvfb_DEPENDENCIES = $(XVFB_LIBS)
++Xvfb_DEPENDENCIES = $(filter-out -l%,$(XVFB_LIBS))
+ Xvfb_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG)
+
+ relink:
+diff --git a/test/Makefile.am b/test/Makefile.am
+index 34f53fc..3509306 100644
+--- a/test/Makefile.am
++++ b/test/Makefile.am
+@@ -131,7 +131,7 @@ libxservertest_la_LIBADD += \
+ endif
+ endif
+
+-libxservertest_la_DEPENDENCIES = $(libxservertest_la_LIBADD)
++libxservertest_la_DEPENDENCIES = $(filter-out -l%,$(libxservertest_la_LIBADD))
+ endif
+
+ EXTRA_DIST = ddxstubs.c
+--
+1.8.2.1
+
diff --git a/Tools/gtk/webkitdom.py b/Tools/gtk/webkitdom.py
index 221defba6..14fd9b10f 100755
--- a/Tools/gtk/webkitdom.py
+++ b/Tools/gtk/webkitdom.py
@@ -17,6 +17,7 @@
# 02110-1301 USA
import common
+import errno
import os
import re
import sys
@@ -26,12 +27,7 @@ from ConfigParser import SafeConfigParser
class WebKitDOMDocGenerator(object):
- DELETED_CLASSES = [
- "WebKitDOMBarInfo",
- "WebKitDOMHTMLPropertiesCollection",
- "WebKitDOMMemoryInfo",
- "WebKitDOMMicroDataItemValue",
- "WebKitDOMPropertyNodeList"]
+ DELETED_CLASSES = ["WebKitDOMEntityReference", "WebKitDOMHTMLBaseFontElement"]
def __init__(self, symbol_files, file_handle):
self._symbol_files = symbol_files
@@ -116,12 +112,12 @@ class WebKitDOMDocGeneratorSections(WebKitDOMDocGenerator):
self._second_decamelize_re = re.compile('([a-z0-9])([A-Z])')
self._dom_class_re = re.compile('(^WebKitDOM)(.+)$')
self._function_re = re.compile('^.+ (.+)\((.+)\)$')
+ self._constant_re = re.compile('^[A-Z_]+$')
- self.deprecated_symbosl = {}
+ self.deprecated_symbols = {}
for symbol_file in symbol_files:
if WebKitDOMDocGenerator.is_deprecated_symbol_file(symbol_file):
self._deprecated_symbols = self._find_deprecated_symbols(symbol_file)
- break
def _dom_class(self, class_name):
return self._dom_class_re.sub(r'\2', class_name)
@@ -134,6 +130,12 @@ class WebKitDOMDocGeneratorSections(WebKitDOMDocGenerator):
retval = retval.replace('Web_Kit', 'WebKit')
retval = retval.replace('X_Path', 'XPath')
retval = retval.replace('HTMLI_Frame', 'HTML_IFrame')
+ retval = retval.replace('HTMLBR', 'HTML_BR')
+ retval = retval.replace('HTMLHR', 'HTML_HR')
+ retval = retval.replace('HTMLLI', 'HTML_LI')
+ retval = retval.replace('HTMLD', 'HTML_D')
+ retval = retval.replace('HTMLO', 'HTML_O')
+ retval = retval.replace('HTMLU', 'HTML_U')
return retval
@@ -155,10 +157,8 @@ class WebKitDOMDocGeneratorSections(WebKitDOMDocGenerator):
function = match.group(1)
args = match.group(2).split(', ')
class_name = args[0].strip('*')
- if class_name == 'void':
- class_name = self._deleted_class(function)
-
retval.setdefault(class_name, []).append(function)
+ f.close()
return retval
@@ -166,6 +166,11 @@ class WebKitDOMDocGeneratorSections(WebKitDOMDocGenerator):
retval = []
f = open(symbol_file, 'r')
for line in f.readlines():
+ match = self._constant_re.match(line)
+ if match:
+ retval.append(line.strip('\n'))
+ continue
+
match = self._function_re.match(line)
if not match or match.group(1).endswith('get_type'):
continue
@@ -176,7 +181,7 @@ class WebKitDOMDocGeneratorSections(WebKitDOMDocGenerator):
def write_section(self, symbol_file):
class_name = os.path.basename(symbol_file).replace(".symbols", "")
is_custom = class_name == 'WebKitDOMCustom'
- is_interface = class_name == 'WebKitDOMEventTarget'
+ is_interface = class_name in ['WebKitDOMEventTarget', 'WebKitDOMNodeFilter', 'WebKitDOMXPathNSResolver']
is_object = class_name == 'WebKitDOMObject'
self.write('<SECTION>\n')
self.write('<FILE>%s</FILE>\n<TITLE>%s</TITLE>\n' % (class_name, class_name))
@@ -191,22 +196,19 @@ class WebKitDOMDocGeneratorSections(WebKitDOMDocGenerator):
pass
if not is_custom:
self.write('\n<SUBSECTION Standard>\n')
- self.write('%sClass\n' % class_name)
+ if is_interface:
+ self.write('%sIface\n' % class_name)
+ else:
+ self.write('%sClass\n' % class_name)
dom_class = self._dom_class_decamelize(class_name).upper()
- self.write('WEBKIT_TYPE_DOM_%s\n' % dom_class)
+ self.write('WEBKIT_DOM_TYPE_%s\n' % dom_class)
self.write('WEBKIT_DOM_%s\n' % dom_class)
- if is_object:
- self.write('WEBKIT_IS_DOM_%s\n' % dom_class)
- else:
- self.write('WEBKIT_DOM_IS_%s\n' % dom_class)
+ self.write('WEBKIT_DOM_IS_%s\n' % dom_class)
self.write('WEBKIT_DOM_%s_CLASS\n' % dom_class)
if is_interface:
self.write('WEBKIT_DOM_%s_GET_IFACE\n' % dom_class)
else:
- if is_object:
- self.write('WEBKIT_IS_DOM_%s_CLASS\n' % dom_class)
- else:
- self.write('WEBKIT_DOM_IS_%s_CLASS\n' % dom_class)
+ self.write('WEBKIT_DOM_IS_%s_CLASS\n' % dom_class)
self.write('WEBKIT_DOM_%s_GET_CLASS\n' % dom_class)
self.write('\n<SUBSECTION Private>\n')
if is_object:
@@ -218,7 +220,19 @@ class WebKitDOMDocGeneratorSections(WebKitDOMDocGenerator):
for class_name in self.DELETED_CLASSES:
self.write('<SECTION>\n')
self.write('<FILE>%s</FILE>\n<TITLE>%s</TITLE>\n' % (class_name, class_name))
- self.write('\n'.join([name for name in self._deprecated_symbols[class_name] if not name.endswith('get_type')]) + '\n')
+ try:
+ self.write('\n'.join([name for name in self._deprecated_symbols[class_name] if not name.endswith('get_type')]) + '\n')
+ except KeyError:
+ # A deleted class with no public methods doesn't have deprecated symbols.
+ pass
+ self.write('\n<SUBSECTION Standard>\n')
+ dom_class = self._dom_class_decamelize(class_name).upper()
+ self.write('WEBKIT_DOM_TYPE_%s\n' % dom_class)
+ self.write('WEBKIT_DOM_%s\n' % dom_class)
+ self.write('WEBKIT_DOM_IS_%s\n' % dom_class)
+ self.write('WEBKIT_DOM_%s_CLASS\n' % dom_class)
+ self.write('WEBKIT_DOM_IS_%s_CLASS\n' % dom_class)
+ self.write('WEBKIT_DOM_%s_GET_CLASS\n' % dom_class)
self.write('\n<SUBSECTION Private>\n')
self.write('webkit_dom_%s_get_type\n' % self._dom_class_decamelize(class_name).lower())
self.write('</SECTION>\n\n')
@@ -231,15 +245,17 @@ class WebKitDOMDocGeneratorSections(WebKitDOMDocGenerator):
self.write('</SECTION>\n\n')
-def write_doc_files():
+def write_doc_files(module_name):
doc_dir = common.build_path('DerivedSources', 'webkitdom', 'docs')
try:
os.mkdir(doc_dir)
- except:
- pass # Commonly happens if the directory already exists.
+ except OSError, e:
+ if e.errno != errno.EEXIST or not os.path.isdir(doc_dir):
+ sys.stderr.write("Could not create doc dir at %s: %s\n" % (doc_dir, str(e)))
+ sys.exit(1)
- with open(os.path.join(doc_dir, 'webkitdomgtk-sections.txt'), 'w') as sections_file:
+ with open(os.path.join(doc_dir, '%s-sections.txt' % module_name), 'w') as sections_file:
generator = WebKitDOMDocGeneratorSections(get_all_webkitdom_symbol_files(), sections_file)
generator.generate()
with open(os.path.join(doc_dir, 'webkitdomgtk-docs.sgml'), 'w') as sgml_file:
@@ -279,7 +295,5 @@ def get_all_webkitdom_symbol_files():
if os.path.exists(path):
symbol_files.append(path)
continue
- sys.stderr.write("Could not find symbol file for header: %s\n" % header_name)
- sys.exit(1)
return symbol_files
diff --git a/Tools/gtk/ycm_extra_conf.py b/Tools/gtk/ycm_extra_conf.py
new file mode 100644
index 000000000..eb35c945d
--- /dev/null
+++ b/Tools/gtk/ycm_extra_conf.py
@@ -0,0 +1,133 @@
+#!/usr/bin/env python
+# Copyright (C) 2013 Danilo Cesar Lemes de Paula <danilo.eu@gmail.com>
+# Copyright (C) 2014 ChangSeok Oh <shivamidow@gmail.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+import os
+import sys
+import ycm_core
+
+# It's very likely that this script is a symlink somewhere in the WebKit directory,
+# so we try to find the actual script location so that we can locate the tools
+# directory.
+original_file = __file__[:-1] if __file__.endswith(".pyc") else __file__
+if os.path.islink(original_file):
+ parent_folder = os.path.abspath(os.path.dirname(original_file))
+ link_file = os.path.join(parent_folder, os.readlink(original_file))
+ __tools_directory = os.path.dirname(link_file)
+else:
+ __tools_directory = os.path.dirname(original_file)
+
+sys.path.insert(0, os.path.abspath(__tools_directory))
+import common
+
+
+FLAGS_PRECEDING_PATHS = ['-isystem', '-I', '-iquote', '--sysroot=']
+def transform_relative_paths_to_absolute_paths(arguments, build_path):
+ result = []
+ make_next_absolute = False
+ for argument in arguments:
+ if make_next_absolute:
+ make_next_absolute = False
+ if not argument.startswith('/'):
+ argument = os.path.join(build_path, argument)
+ elif argument in FLAGS_PRECEDING_PATHS:
+ # Some flags precede the path in the list. For those we make the
+ # next argument absolute.
+ if argument == flag:
+ make_next_absolute = True
+ else:
+ # Some argument contain the flag and the path together. For these
+ # we parse the argument out of the path.
+ for flag in FLAGS_PRECEDING_PATHS:
+ if argument.startswith(flag):
+ argument = flag + os.path.join(build_path, argument[len(flag):])
+ break
+
+ result.append(argument)
+ return result
+
+
+def get_build_path():
+ webkitbuild_path = os.path.join(common.get_build_path(fatal=False), '..')
+ if not os.path.exists(webkitbuild_path):
+ return None
+
+ release_build_path = os.path.join(webkitbuild_path, 'Release')
+ debug_build_path = os.path.join(webkitbuild_path, 'Debug')
+
+ try:
+ release_mtime = os.path.getmtime(os.path.join(release_build_path, 'compile_commands.json'))
+ except os.error:
+ release_mtime = 0
+ try:
+ debug_mtime = os.path.getmtime(os.path.join(debug_build_path, 'compile_commands.json'))
+ except os.error:
+ debug_mtime = 0
+
+ return release_build_path if release_mtime >= debug_mtime else debug_build_path
+
+
+def FlagsForFile(filename, **kwargs):
+ """This is the main entry point for YCM. Its interface is fixed.
+
+ Args:
+ filename: (String) Path to source file being edited.
+
+ Returns:
+ (Dictionary)
+ 'flags': (List of Strings) Command line flags.
+ 'do_cache': (Boolean) True if the result should be cached.
+ """
+
+ result = {'flags': ['-std=c++11', '-x', 'c++'], 'do_cache': True}
+
+ # Headers can't be built, so we get the source file flags instead.
+ if filename.endswith('.h'):
+ alternative_extensions = ['.cpp', '.c']
+ for alternative_extension in alternative_extensions:
+ alternative_filename = filename[:-2] + alternative_extension
+ if os.path.exists(alternative_filename):
+ filename = alternative_filename
+ break
+ else:
+ return result
+ # Force config.h file inclusion, for GLib macros.
+ result['flags'].append("-includeconfig.h")
+
+ build_path = os.path.normpath(get_build_path())
+ if not build_path:
+ print "Could not find WebKit build path."
+ return result
+
+ database = ycm_core.CompilationDatabase(build_path)
+ if not database:
+ print "Could not find compile_commands.json in %s, You might forget to add CMAKE_EXPORT_COMPILE_COMMANDS=ON to cmakeargs" % build_path
+ return result
+
+ compilation_info = database.GetCompilationInfoForFile(filename)
+ if not compilation_info:
+ print "No compilation info."
+ return result
+
+ result['flags'] = transform_relative_paths_to_absolute_paths(list(compilation_info.compiler_flags_), compilation_info.compiler_working_dir_)
+ return result
+
+
+if __name__ == "__main__":
+ import sys
+ if len(sys.argv) >= 2:
+ print FlagsForFile(sys.argv[1])
diff --git a/Tools/jhbuild/jhbuildutils.py b/Tools/jhbuild/jhbuildutils.py
new file mode 100644
index 000000000..c00160e7e
--- /dev/null
+++ b/Tools/jhbuild/jhbuildutils.py
@@ -0,0 +1,56 @@
+import glob
+import os.path
+import sys
+import __builtin__
+
+top_level_dir = None
+
+
+def top_level_path(*args):
+ global top_level_dir
+ if not top_level_dir:
+ top_level_dir = os.path.join(os.path.dirname(__file__), '..', '..')
+ return os.path.join(*(top_level_dir,) + args)
+
+
+def get_dependencies_path(platform):
+ dependencies_dir = "%s%s" % ('Dependencies', platform.upper())
+ if 'WEBKIT_OUTPUTDIR' in os.environ:
+ return os.path.abspath(os.path.join(os.environ['WEBKIT_OUTPUTDIR'], dependencies_dir))
+ else:
+ return os.path.abspath(top_level_path('WebKitBuild', dependencies_dir))
+
+
+def get_config_file_for_platform(platform):
+ return top_level_path('Tools', platform, 'jhbuildrc')
+
+
+def enter_jhbuild_environment_if_available(platform):
+ if not os.path.exists(get_dependencies_path(platform)):
+ return False
+
+ # Sometimes jhbuild chooses to install in a way that reads the library from the source directory, so fall
+ # back to that method.
+ source_path = os.path.join(get_dependencies_path(platform), "Source", "jhbuild")
+ sys.path.insert(0, source_path)
+
+ # When loading jhbuild from the source checkout it fails if the SRCDIR, PKGDATADIR or DATADIR aren't present.
+ __builtin__.__dict__['SRCDIR'] = source_path
+ __builtin__.__dict__['PKGDATADIR'] = None
+ __builtin__.__dict__['DATADIR'] = None
+
+ # We don't know the Python version, so we just assume that we can safely take the first one in the list.
+ site_packages_path = glob.glob(os.path.join(get_dependencies_path(platform), "Root", "lib", "*", "site-packages"))
+ if len(site_packages_path):
+ site_packages_path = site_packages_path[0]
+ sys.path.insert(0, site_packages_path)
+
+ try:
+ import jhbuild.config
+ from jhbuild.errors import FatalError
+ config = jhbuild.config.Config(get_config_file_for_platform(platform), [])
+ except FatalError, exception:
+ sys.stderr.write('Could not load jhbuild config file: %s\n' % exception.args[0])
+ return False
+
+ return True