diff --git a/browser_patches/checkout_build_archive_upload.sh b/browser_patches/checkout_build_archive_upload.sh index c1c9894bce506..05ed2fc6dbdab 100755 --- a/browser_patches/checkout_build_archive_upload.sh +++ b/browser_patches/checkout_build_archive_upload.sh @@ -201,11 +201,6 @@ elif [[ "$BUILD_FLAVOR" == "webkit-win64" ]]; then BROWSER_NAME="webkit" EXPECTED_HOST_OS="MINGW" BUILD_BLOB_NAME="webkit-win64.zip" -elif [[ "$BUILD_FLAVOR" == "webkit-mac-10.14" ]]; then - BROWSER_NAME="webkit" - EXPECTED_HOST_OS="Darwin" - EXPECTED_HOST_OS_VERSION="10.14" - BUILD_BLOB_NAME="webkit-mac-10.14.zip" elif [[ "$BUILD_FLAVOR" == "webkit-mac-10.15" ]]; then BROWSER_NAME="webkit" EXPECTED_HOST_OS="Darwin" @@ -222,6 +217,16 @@ elif [[ "$BUILD_FLAVOR" == "webkit-mac-11.0-arm64" ]]; then EXPECTED_HOST_OS_VERSION="11.0" EXPECTED_ARCH="arm64" BUILD_BLOB_NAME="webkit-mac-11.0-arm64.zip" + + +# =================================== +# DEPRECATED WEBKIT COMPILATION +# =================================== +elif [[ "$BUILD_FLAVOR" == "deprecated-webkit-mac-10.14" ]]; then + BROWSER_NAME="deprecated-webkit-mac-10.14" + EXPECTED_HOST_OS="Darwin" + EXPECTED_HOST_OS_VERSION="10.14" + BUILD_BLOB_NAME="deprecated-webkit-mac-10.14.zip" else echo ERROR: unknown build flavor - "$BUILD_FLAVOR" exit 1 diff --git a/browser_patches/deprecated-webkit-mac-10.14/.gitignore b/browser_patches/deprecated-webkit-mac-10.14/.gitignore new file mode 100644 index 0000000000000..5e660dc18ee09 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/.gitignore @@ -0,0 +1 @@ +/checkout diff --git a/browser_patches/deprecated-webkit-mac-10.14/BUILD_NUMBER b/browser_patches/deprecated-webkit-mac-10.14/BUILD_NUMBER new file mode 100644 index 0000000000000..b0fa2aefcf3a8 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/BUILD_NUMBER @@ -0,0 +1,2 @@ +1443 +Changed: yurys@chromium.org Mon 01 Mar 2021 09:57:46 AM PST diff --git a/browser_patches/deprecated-webkit-mac-10.14/UPSTREAM_CONFIG.sh b/browser_patches/deprecated-webkit-mac-10.14/UPSTREAM_CONFIG.sh new file mode 100644 index 0000000000000..05e5bdd1dcae7 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/UPSTREAM_CONFIG.sh @@ -0,0 +1,3 @@ +REMOTE_URL="https://git.webkit.org/git/WebKit.git" +BASE_BRANCH="master" +BASE_REVISION="b3de1a5d49442523744d6326dbc852cea829a145" diff --git a/browser_patches/deprecated-webkit-mac-10.14/archive.sh b/browser_patches/deprecated-webkit-mac-10.14/archive.sh new file mode 100755 index 0000000000000..adec84818e61f --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/archive.sh @@ -0,0 +1,146 @@ +#!/bin/bash +set -e +set +x + +if [[ ("$1" == "-h") || ("$1" == "--help") ]]; then + echo "usage: $(basename $0) [output-absolute-path]" + echo + echo "Generate distributable .zip archive from ./checkout folder that was previously built." + echo + exit 0 +fi + +ZIP_PATH=$1 +if [[ $ZIP_PATH != /* ]]; then + echo "ERROR: path $ZIP_PATH is not absolute" + exit 1 +fi +if [[ $ZIP_PATH != *.zip ]]; then + echo "ERROR: path $ZIP_PATH must have .zip extension" + exit 1 +fi +if [[ -f $ZIP_PATH ]]; then + echo "ERROR: path $ZIP_PATH exists; can't do anything." + exit 1 +fi +if ! [[ -d $(dirname $ZIP_PATH) ]]; then + echo "ERROR: folder for path $($ZIP_PATH) does not exist." + exit 1 +fi + +main() { + if [[ ! -z "${WK_CHECKOUT_PATH}" ]]; then + cd "${WK_CHECKOUT_PATH}" + echo "WARNING: checkout path from WK_CHECKOUT_PATH env: ${WK_CHECKOUT_PATH}" + else + cd "checkout" + fi + + set -x + if [[ "$(uname)" == "Darwin" ]]; then + createZipForMac + elif [[ "$(uname)" == "Linux" ]]; then + createZipForLinux + elif [[ "$(uname)" == MINGW* ]]; then + createZipForWindows + else + echo "ERROR: cannot upload on this platform!" 1>&2 + exit 1; + fi +} + + +createZipForLinux() { + # create a TMP directory to copy all necessary files + local tmpdir=$(mktemp -d -t webkit-deploy-XXXXXXXXXX) + mkdir -p $tmpdir + + # copy runner + cp -t $tmpdir $SCRIPTS_DIR/pw_run.sh + # copy protocol + node $SCRIPTS_DIR/concat_protocol.js > $tmpdir/protocol.json + + # Generate and unpack MiniBrowser bundles for each port + for port in gtk wpe; do + WEBKIT_OUTPUTDIR=$(pwd)/WebKitBuild/${port^^} Tools/Scripts/generate-bundle \ + --bundle=MiniBrowser --release \ + --platform=${port} --destination=${tmpdir} + unzip ${tmpdir}/MiniBrowser_${port}_release.zip -d ${tmpdir}/minibrowser-${port} + rm -f ${tmpdir}/MiniBrowser_${port}_release.zip + done + + # tar resulting directory and cleanup TMP. + cd $tmpdir + zip --symlinks -r $ZIP_PATH ./ + cd - + rm -rf $tmpdir +} + +# see https://docs.microsoft.com/en-us/visualstudio/install/tools-for-managing-visual-studio-instances?view=vs-2019 +printMSVCRedistDir() { + local dll_file=$("C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -find '**\Redist\MSVC\*\x64\**\vcruntime140.dll') + local redist_dir=$(dirname "$dll_file") + if ! [[ -d $redist_dir ]]; then + echo "ERROR: cannot find MS VS C++ redistributable $redist_dir" + exit 1; + fi + echo "$redist_dir" +} + +createZipForWindows() { + # create a TMP directory to copy all necessary files + local tmpdir="/tmp/webkit-deploy-$(date +%s)" + mkdir -p $tmpdir + + cp -t $tmpdir ./WebKitLibraries/win/bin64/*.dll + cd WebKitBuild/Release/bin64 + cp -r -t $tmpdir WebKit.resources + cp -t $tmpdir JavaScriptCore.dll PlaywrightLib.dll WTF.dll WebKit2.dll libEGL.dll libGLESv2.dll + cp -t $tmpdir Playwright.exe WebKitNetworkProcess.exe WebKitWebProcess.exe + cd - + cd "$(printMSVCRedistDir)" + cp -t $tmpdir msvcp140.dll vcruntime140.dll vcruntime140_1.dll msvcp140_2.dll + cd - + + # copy protocol + node $SCRIPTS_DIR/concat_protocol.js > $tmpdir/protocol.json + # tar resulting directory and cleanup TMP. + cd $tmpdir + zip -r $ZIP_PATH ./ + cd - + rm -rf $tmpdir +} + +createZipForMac() { + # create a TMP directory to copy all necessary files + local tmpdir=$(mktemp -d) + + # copy all relevant files + ditto {./WebKitBuild/Release,$tmpdir}/com.apple.WebKit.Networking.xpc + ditto {./WebKitBuild/Release,$tmpdir}/com.apple.WebKit.Plugin.64.xpc + ditto {./WebKitBuild/Release,$tmpdir}/com.apple.WebKit.WebContent.xpc + ditto {./WebKitBuild/Release,$tmpdir}/JavaScriptCore.framework + ditto {./WebKitBuild/Release,$tmpdir}/libwebrtc.dylib + ditto {./WebKitBuild/Release,$tmpdir}/Playwright.app + ditto {./WebKitBuild/Release,$tmpdir}/PluginProcessShim.dylib + ditto {./WebKitBuild/Release,$tmpdir}/WebCore.framework + ditto {./WebKitBuild/Release,$tmpdir}/WebInspectorUI.framework + ditto {./WebKitBuild/Release,$tmpdir}/WebKit.framework + ditto {./WebKitBuild/Release,$tmpdir}/WebKitLegacy.framework + ditto {$SCRIPTS_DIR,$tmpdir}/pw_run.sh + # copy protocol + node $SCRIPTS_DIR/concat_protocol.js > $tmpdir/protocol.json + + # Remove all broken symlinks. @see https://github.com/microsoft/playwright/issues/5472 + find "${tmpdir}" -type l ! -exec test -e {} \; -print | xargs rm + + # zip resulting directory and cleanup TMP. + ditto -c -k $tmpdir $ZIP_PATH + rm -rf $tmpdir +} + +trap "cd $(pwd -P)" EXIT +cd "$(dirname "$0")" +SCRIPTS_DIR="$(pwd -P)" + +main "$@" diff --git a/browser_patches/deprecated-webkit-mac-10.14/build.sh b/browser_patches/deprecated-webkit-mac-10.14/build.sh new file mode 100755 index 0000000000000..e5a0144c70c6e --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/build.sh @@ -0,0 +1,77 @@ +#!/bin/bash +set -e +set +x + +trap "cd $(pwd -P)" EXIT +cd "$(dirname $0)" +SCRIPT_FOLDER="$(pwd -P)" + +build_gtk() { + if ! [[ -d ./WebKitBuild/GTK/DependenciesGTK ]]; then + yes | WEBKIT_JHBUILD=1 WEBKIT_JHBUILD_MODULESET=minimal WEBKIT_OUTPUTDIR=$(pwd)/WebKitBuild/GTK DEBIAN_FRONTEND=noninteractive ./Tools/Scripts/update-webkitgtk-libs + fi + local CMAKE_ARGS="" + if [[ -n "${EXPORT_COMPILE_COMMANDS}" ]]; then + CMAKE_ARGS="--cmakeargs=\"-DCMAKE_EXPORT_COMPILE_COMMANDS=1\"" + fi + WEBKIT_JHBUILD=1 WEBKIT_JHBUILD_MODULESET=minimal WEBKIT_OUTPUTDIR=$(pwd)/WebKitBuild/GTK ./Tools/Scripts/build-webkit --gtk --release "${CMAKE_ARGS}" --touch-events --orientation-events --no-bubblewrap-sandbox --no-webxr MiniBrowser +} + +build_wpe() { + if ! [[ -d ./WebKitBuild/WPE/DependenciesWPE ]]; then + yes | WEBKIT_JHBUILD=1 WEBKIT_JHBUILD_MODULESET=minimal WEBKIT_OUTPUTDIR=$(pwd)/WebKitBuild/WPE DEBIAN_FRONTEND=noninteractive ./Tools/Scripts/update-webkitwpe-libs + fi + local CMAKE_ARGS="" + if [[ -n "${EXPORT_COMPILE_COMMANDS}" ]]; then + CMAKE_ARGS="--cmakeargs=\"-DCMAKE_EXPORT_COMPILE_COMMANDS=1\"" + fi + WEBKIT_JHBUILD=1 WEBKIT_JHBUILD_MODULESET=minimal WEBKIT_OUTPUTDIR=$(pwd)/WebKitBuild/WPE ./Tools/Scripts/build-webkit --wpe --release "${CMAKE_ARGS}" --touch-events --orientation-events --no-bubblewrap-sandbox --no-webxr MiniBrowser +} + +ensure_linux_deps() { + yes | DEBIAN_FRONTEND=noninteractive ./Tools/gtk/install-dependencies + yes | DEBIAN_FRONTEND=noninteractive ./Tools/wpe/install-dependencies + yes | DEBIAN_FRONTEND=noninteractive WEBKIT_JHBUILD=1 WEBKIT_JHBUILD_MODULESET=minimal WEBKIT_OUTPUTDIR=$(pwd)/WebKitBuild/WPE ./Tools/Scripts/update-webkitwpe-libs + yes | DEBIAN_FRONTEND=noninteractive WEBKIT_JHBUILD=1 WEBKIT_JHBUILD_MODULESET=minimal WEBKIT_OUTPUTDIR=$(pwd)/WebKitBuild/GTK ./Tools/Scripts/update-webkitgtk-libs +} + +if [[ ! -z "${WK_CHECKOUT_PATH}" ]]; then + cd "${WK_CHECKOUT_PATH}" + echo "WARNING: checkout path from WK_CHECKOUT_PATH env: ${WK_CHECKOUT_PATH}" +else + cd "checkout" +fi + +if [[ "$(uname)" == "Darwin" ]]; then + ./Tools/Scripts/build-webkit --release --touch-events --orientation-events +elif [[ "$(uname)" == "Linux" ]]; then + if [[ $# == 0 || (-z "$1") ]]; then + echo + echo BUILDING: GTK and WPE + echo + build_wpe + build_gtk + elif [[ "$1" == "--full" ]]; then + echo + echo BUILDING: GTK and WPE + echo + ensure_linux_deps + build_wpe + build_gtk + elif [[ "$1" == "--gtk" ]]; then + echo + echo BUILDING: GTK + echo + build_gtk + elif [[ "$1" == "--wpe" ]]; then + echo + echo BUILDING: WPE + echo + build_wpe + fi +elif [[ "$(uname)" == MINGW* ]]; then + /c/Windows/System32/cmd.exe "/c $(cygpath -w ${SCRIPT_FOLDER}/buildwin.bat)" +else + echo "ERROR: cannot upload on this platform!" 1>&2 + exit 1; +fi diff --git a/browser_patches/deprecated-webkit-mac-10.14/buildwin.bat b/browser_patches/deprecated-webkit-mac-10.14/buildwin.bat new file mode 100644 index 0000000000000..d3e8dec042e85 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/buildwin.bat @@ -0,0 +1,5 @@ +set PATH=%WEBKIT_BUILD_PATH% +set WEBKIT_LIBRARIES=%CD%\WebKitLibraries\win +set WEBKIT_OUTPUTDIR=%CD%\WebKitBuild +perl %CD%\Tools\Scripts\build-webkit --wincairo --release --no-ninja --touch-events --orientation-events --dark-mode-css --generate-project-only --cmakeargs="-DLIBVPX_PACKAGE_PATH=C:\vcpkg\packages\libvpx_x64-windows" +%DEVENV% %CD%\WebKitBuild\Release\WebKit.sln /build "Release|x64" diff --git a/browser_patches/deprecated-webkit-mac-10.14/clean.sh b/browser_patches/deprecated-webkit-mac-10.14/clean.sh new file mode 100755 index 0000000000000..4230691a0f23a --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/clean.sh @@ -0,0 +1,23 @@ +#!/bin/bash +set -e +set +x + +trap "cd $(pwd -P)" EXIT +cd "$(dirname $0)" + +if [[ ! -z "${WK_CHECKOUT_PATH}" ]]; then + cd "${WK_CHECKOUT_PATH}" + echo "WARNING: checkout path from WK_CHECKOUT_PATH env: ${WK_CHECKOUT_PATH}" +else + cd "checkout" +fi + +if [[ -d ./WebKitBuild ]]; then + rm -rf ./WebKitBuild/Release +fi +if [[ -d ./WebKitBuild/GTK ]]; then + rm -rf ./WebKitBuild/GTK/Release +fi +if [[ -d ./WebKitBuild/WPE ]]; then + rm -rf ./WebKitBuild/WPE/Release +fi diff --git a/browser_patches/deprecated-webkit-mac-10.14/concat_protocol.js b/browser_patches/deprecated-webkit-mac-10.14/concat_protocol.js new file mode 100644 index 0000000000000..9d2d405d477c7 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/concat_protocol.js @@ -0,0 +1,7 @@ +const fs = require('fs'); +const path = require('path'); +const checkoutPath = process.env.WK_CHECKOUT_PATH || path.join(__dirname, 'checkout'); +const protocolDir = path.join(checkoutPath, './Source/JavaScriptCore/inspector/protocol'); +const files = fs.readdirSync(protocolDir).filter(f => f.endsWith('.json')).map(f => path.join(protocolDir, f)); +const json = files.map(file => JSON.parse(fs.readFileSync(file))); +console.log(JSON.stringify(json)); diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/Configurations/Base.xcconfig b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/Configurations/Base.xcconfig new file mode 100644 index 0000000000000..fc61d5227c860 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/Configurations/Base.xcconfig @@ -0,0 +1,87 @@ +// Copyright (C) 2010-2017 Apple Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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? "../../../../Internal/Configurations/HaveInternalSDK.xcconfig" +#include "SDKVariant.xcconfig" + +USE_INTERNAL_SDK = $(USE_INTERNAL_SDK_$(CONFIGURATION)); +USE_INTERNAL_SDK_Production = YES; +USE_INTERNAL_SDK_Debug = $(HAVE_INTERNAL_SDK); +USE_INTERNAL_SDK_Release = $(HAVE_INTERNAL_SDK); + +GCC_PREPROCESSOR_DEFINITIONS = DISABLE_LEGACY_WEBKIT_DEPRECATIONS $(inherited); + +CLANG_CXX_LANGUAGE_STANDARD = gnu++1z; +CLANG_CXX_LIBRARY = libc++; +CLANG_ENABLE_OBJC_WEAK = YES; +DEBUG_INFORMATION_FORMAT = dwarf-with-dsym; +PREBINDING = NO +GCC_C_LANGUAGE_STANDARD = gnu99 +GCC_ENABLE_CPP_EXCEPTIONS = NO; +GCC_PRECOMPILE_PREFIX_HEADER = YES +ENABLE_STRICT_OBJC_MSGSEND = YES; +GCC_TREAT_WARNINGS_AS_ERRORS = YES +CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; +CLANG_WARN_BOOL_CONVERSION = YES; +CLANG_WARN_COMMA = YES; +CLANG_WARN_CONSTANT_CONVERSION = YES; +CLANG_WARN_EMPTY_BODY = YES; +CLANG_WARN_ENUM_CONVERSION = YES; +CLANG_WARN_INFINITE_RECURSION = YES; +CLANG_WARN_INT_CONVERSION = YES; +CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; +CLANG_WARN_STRICT_PROTOTYPES = YES; +CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; +CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; +CLANG_WARN_SUSPICIOUS_MOVE = YES; +CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; +CLANG_WARN_UNREACHABLE_CODE = YES; +GCC_WARN_64_TO_32_BIT_CONVERSION = YES; +GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; +GCC_WARN_ABOUT_RETURN_TYPE = YES; +GCC_WARN_UNINITIALIZED_AUTOS = YES; +GCC_WARN_UNUSED_FUNCTION = YES +GCC_WARN_UNUSED_VARIABLE = YES +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; +GCC_WARN_UNDECLARED_SELECTOR = YES; +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; +CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; +GCC_VERSION = com.apple.compilers.llvm.clang.1_0; +WARNING_CFLAGS = -Wall -W -Wno-unused-parameter +GCC_NO_COMMON_BLOCKS = YES; + +SUPPORTED_PLATFORMS = iphoneos iphonesimulator macosx tvos tvsimulator watchos watchsimulator; + +TARGET_MAC_OS_X_VERSION_MAJOR = $(TARGET_MAC_OS_X_VERSION_MAJOR$(MACOSX_DEPLOYMENT_TARGET:suffix:identifier)); +TARGET_MAC_OS_X_VERSION_MAJOR_13 = 101300; +TARGET_MAC_OS_X_VERSION_MAJOR_14 = 101400; +TARGET_MAC_OS_X_VERSION_MAJOR_15 = 101500; +TARGET_MAC_OS_X_VERSION_MAJOR_16 = 101600; + +SDKROOT = macosx.internal; + +OTHER_CFLAGS = $(ASAN_OTHER_CFLAGS); +OTHER_CPLUSPLUSFLAGS = $(ASAN_OTHER_CPLUSPLUSFLAGS); +OTHER_LDFLAGS = $(ASAN_OTHER_LDFLAGS); + +CODE_SIGN_IDENTITY = -; diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/Configurations/DebugRelease.xcconfig b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/Configurations/DebugRelease.xcconfig new file mode 100644 index 0000000000000..44dc1139c298b --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/Configurations/DebugRelease.xcconfig @@ -0,0 +1,45 @@ +// Copyright (C) 2010, 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. ``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 "Base.xcconfig" + +ARCHS = $(ARCHS_STANDARD_32_64_BIT); + +ONLY_ACTIVE_ARCH = YES; + +TARGET_MAC_OS_X_VERSION_MAJOR = $(MAC_OS_X_VERSION_MAJOR); + +MACOSX_DEPLOYMENT_TARGET = $(MACOSX_DEPLOYMENT_TARGET_$(TARGET_MAC_OS_X_VERSION_MAJOR)) +MACOSX_DEPLOYMENT_TARGET_101300 = 10.13; +MACOSX_DEPLOYMENT_TARGET_101400 = 10.14; +MACOSX_DEPLOYMENT_TARGET_101500 = 10.15; +MACOSX_DEPLOYMENT_TARGET_101600 = 10.16; + +GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; + +SDKROOT = $(SDKROOT_$(USE_INTERNAL_SDK)); +SDKROOT_ = macosx; +SDKROOT_YES = macosx.internal; + +WK_CCACHE_DIR = $(SRCROOT)/../ccache; +#include "../../ccache/ccache.xcconfig" diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/Configurations/Playwright.xcconfig b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/Configurations/Playwright.xcconfig new file mode 100644 index 0000000000000..d05c841a5b0f5 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/Configurations/Playwright.xcconfig @@ -0,0 +1,30 @@ +// 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. ``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. + +PRODUCT_NAME = Playwright +PRODUCT_BUNDLE_IDENTIFIER = org.webkit.$(PRODUCT_NAME:rfc1034identifier) +GCC_PREFIX_HEADER = mac/Playwright_Prefix.pch +INFOPLIST_FILE = mac/Info.plist +EXCLUDED_SOURCE_FILE_NAMES[sdk=iphone*] = * +OTHER_LDFLAGS[sdk=macosx*] = $(inherited) -framework Cocoa -framework WebKit +STRIP_STYLE = debugging; diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/Configurations/SDKVariant.xcconfig b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/Configurations/SDKVariant.xcconfig new file mode 100644 index 0000000000000..fcdf7e65a67c6 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/Configurations/SDKVariant.xcconfig @@ -0,0 +1,45 @@ +// Copyright (C) 2019 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. + +WK_EMPTY_ = YES; +WK_NOT_ = YES; +WK_NOT_YES = NO; + +WK_ALTERNATE_FRAMEWORKS_DIR = $(WK_ALTERNATE_FRAMEWORKS_DIR_$(SDK_VARIANT)); +WK_ALTERNATE_FRAMEWORKS_DIR_iosmac = /System/iOSSupport; +WK_USE_ALTERNATE_FRAMEWORKS_DIR = $(WK_NOT_$(WK_EMPTY_$(WK_ALTERNATE_FRAMEWORKS_DIR))); + +WK_ALTERNATE_PLATFORM_NAME = $(WK_ALTERNATE_PLATFORM_NAME_$(SDK_VARIANT)); +WK_ALTERNATE_PLATFORM_NAME_iosmac = maccatalyst; +WK_USE_ALTERNATE_PLATFORM_NAME = $(WK_NOT_$(WK_EMPTY_$(WK_ALTERNATE_PLATFORM_NAME))); + +WK_ALTERNATE_WEBKIT_SDK_PATH = $(WK_ALTERNATE_WEBKIT_SDK_PATH_$(WK_USE_ALTERNATE_FRAMEWORKS_DIR)); +WK_ALTERNATE_WEBKIT_SDK_PATH_YES = $(WK_ALTERNATE_FRAMEWORKS_DIR)/; + +WK_PLATFORM_NAME = $(WK_PLATFORM_NAME_ALTERNATE_$(WK_USE_ALTERNATE_PLATFORM_NAME)); +WK_PLATFORM_NAME_ALTERNATE_YES = $(WK_ALTERNATE_PLATFORM_NAME); +WK_PLATFORM_NAME_ALTERNATE_NO = $(PLATFORM_NAME); + +EFFECTIVE_PLATFORM_NAME = $(EFFECTIVE_PLATFORM_NAME_ALTERNATE_$(WK_USE_ALTERNATE_PLATFORM_NAME)); +EFFECTIVE_PLATFORM_NAME_ALTERNATE_YES = -$(WK_ALTERNATE_PLATFORM_NAME); +EFFECTIVE_PLATFORM_NAME_ALTERNATE_NO = $(EFFECTIVE_PLATFORM_NAME); diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/MBToolbarItem.h b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/MBToolbarItem.h new file mode 100644 index 0000000000000..9971d4c1023a9 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/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/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/MBToolbarItem.m b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/MBToolbarItem.m new file mode 100644 index 0000000000000..56f777891519e --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/MBToolbarItem.m @@ -0,0 +1,35 @@ +/* + * 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. + */ + +#import "MBToolbarItem.h" + +@implementation MBToolbarItem + +- (void)validate +{ + [self setEnabled:[[self target] validateUserInterfaceItem:self]]; +} + +@end diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/Makefile b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/Makefile new file mode 100644 index 0000000000000..58e52428388d9 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/Makefile @@ -0,0 +1,21 @@ +# Build Playwright only on SnowLeopard and later. + +OSX_VERSION ?= $(shell sw_vers -productVersion | cut -d. -f 2) +BUILD_PLAYWRIGHT = $(shell (( $(OSX_VERSION) >= 6 )) && echo "YES" ) + +ifeq "$(BUILD_PLAYWRIGHT)" "YES" + +SCRIPTS_PATH = ../Scripts +include ../../Makefile.shared + +else + +all: ; + +debug d development dev develop: ; + +release r deployment dep deploy: ; + +clean: ; + +endif diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/Playwright.xcodeproj/project.pbxproj b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/Playwright.xcodeproj/project.pbxproj new file mode 100644 index 0000000000000..75a945e72d9fc --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/Playwright.xcodeproj/project.pbxproj @@ -0,0 +1,264 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 256AC3DA0F4B6AC300CF336A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 256AC3D90F4B6AC300CF336A /* AppDelegate.m */; }; + 51E244FA11EFCE07008228D2 /* MBToolbarItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 51E244F911EFCE07008228D2 /* MBToolbarItem.m */; }; + BC329487116A92E2008635D1 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = BC329486116A92E2008635D1 /* main.m */; }; + BC329498116A941B008635D1 /* BrowserWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = BC329497116A941B008635D1 /* BrowserWindowController.m */; }; + BC72B89511E57E07001EB4EB /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1DDD58150DA1D0A300B3202A /* MainMenu.xib */; }; + BC72B89611E57E0F001EB4EB /* BrowserWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC3294A2116A9852008635D1 /* BrowserWindow.xib */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 1AFFEF761860EE6800DA465F /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + 1AFFEF781860EE6800DA465F /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; + 1DDD58150DA1D0A300B3202A /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = MainMenu.xib; path = mac/MainMenu.xib; sourceTree = ""; }; + 256AC3D80F4B6AC300CF336A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = mac/AppDelegate.h; sourceTree = ""; }; + 256AC3D90F4B6AC300CF336A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = mac/AppDelegate.m; sourceTree = ""; }; + 256AC3F00F4B6AF500CF336A /* Playwright_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Playwright_Prefix.pch; path = mac/Playwright_Prefix.pch; sourceTree = ""; }; + 29B97324FDCFA39411CA2CEB /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; + 29B97325FDCFA39411CA2CEB /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; + 37BAF90620218053000EA87A /* Playwright.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Playwright.entitlements; sourceTree = ""; }; + 51E244F811EFCE07008228D2 /* MBToolbarItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MBToolbarItem.h; sourceTree = ""; }; + 51E244F911EFCE07008228D2 /* MBToolbarItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MBToolbarItem.m; sourceTree = ""; }; + 8D1107320486CEB800E47091 /* Playwright.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Playwright.app; sourceTree = BUILT_PRODUCTS_DIR; }; + A1B89B95221E027A00EB4CEB /* SDKVariant.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = SDKVariant.xcconfig; sourceTree = ""; }; + BC329486116A92E2008635D1 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = mac/main.m; sourceTree = ""; }; + BC329496116A941B008635D1 /* BrowserWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BrowserWindowController.h; path = mac/BrowserWindowController.h; sourceTree = ""; }; + BC329497116A941B008635D1 /* BrowserWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BrowserWindowController.m; path = mac/BrowserWindowController.m; sourceTree = ""; }; + BC3294A2116A9852008635D1 /* BrowserWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = BrowserWindow.xib; path = mac/BrowserWindow.xib; sourceTree = ""; }; + BC72B89A11E57E8A001EB4EB /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = mac/Info.plist; sourceTree = ""; }; + BCA8CBDD11E578A000812FB8 /* Base.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Base.xcconfig; sourceTree = ""; }; + BCA8CBDE11E578A000812FB8 /* DebugRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = DebugRelease.xcconfig; sourceTree = ""; }; + BCA8CBDF11E578A000812FB8 /* Playwright.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Playwright.xcconfig; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8D11072E0486CEB800E47091 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 080E96DDFE201D6D7F000002 /* Playwright */ = { + isa = PBXGroup; + children = ( + 256AC3D80F4B6AC300CF336A /* AppDelegate.h */, + 256AC3D90F4B6AC300CF336A /* AppDelegate.m */, + BC72B89A11E57E8A001EB4EB /* Info.plist */, + BC329486116A92E2008635D1 /* main.m */, + 51E244F811EFCE07008228D2 /* MBToolbarItem.h */, + 51E244F911EFCE07008228D2 /* MBToolbarItem.m */, + 37BAF90620218053000EA87A /* Playwright.entitlements */, + BC329496116A941B008635D1 /* BrowserWindowController.h */, + BC329497116A941B008635D1 /* BrowserWindowController.m */, + ); + name = Playwright; + sourceTree = ""; + }; + 1058C7A2FEA54F0111CA2CBC /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 29B97324FDCFA39411CA2CEB /* AppKit.framework */, + 1AFFEF781860EE6800DA465F /* CoreData.framework */, + 29B97325FDCFA39411CA2CEB /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + 19C28FACFE9D520D11CA2CBC /* Products */ = { + isa = PBXGroup; + children = ( + 8D1107320486CEB800E47091 /* Playwright.app */, + ); + name = Products; + sourceTree = ""; + }; + 29B97314FDCFA39411CA2CEB /* Playwright */ = { + isa = PBXGroup; + children = ( + 256AC3F00F4B6AF500CF336A /* Playwright_Prefix.pch */, + 080E96DDFE201D6D7F000002 /* Playwright */, + 29B97317FDCFA39411CA2CEB /* Resources */, + BCA8CBDA11E5787800812FB8 /* Configurations */, + 29B97323FDCFA39411CA2CEB /* Frameworks */, + 19C28FACFE9D520D11CA2CBC /* Products */, + ); + name = Playwright; + sourceTree = ""; + }; + 29B97317FDCFA39411CA2CEB /* Resources */ = { + isa = PBXGroup; + children = ( + BC3294A2116A9852008635D1 /* BrowserWindow.xib */, + 1DDD58150DA1D0A300B3202A /* MainMenu.xib */, + ); + name = Resources; + sourceTree = ""; + }; + 29B97323FDCFA39411CA2CEB /* Frameworks */ = { + isa = PBXGroup; + children = ( + 1058C7A2FEA54F0111CA2CBC /* Other Frameworks */, + 1AFFEF761860EE6800DA465F /* Cocoa.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + BCA8CBDA11E5787800812FB8 /* Configurations */ = { + isa = PBXGroup; + children = ( + BCA8CBDD11E578A000812FB8 /* Base.xcconfig */, + BCA8CBDE11E578A000812FB8 /* DebugRelease.xcconfig */, + BCA8CBDF11E578A000812FB8 /* Playwright.xcconfig */, + A1B89B95221E027A00EB4CEB /* SDKVariant.xcconfig */, + ); + path = Configurations; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8D1107260486CEB800E47091 /* Playwright */ = { + isa = PBXNativeTarget; + buildConfigurationList = C01FCF4A08A954540054247C /* Build configuration list for PBXNativeTarget "Playwright" */; + buildPhases = ( + 8D1107290486CEB800E47091 /* Resources */, + 8D11072C0486CEB800E47091 /* Sources */, + 8D11072E0486CEB800E47091 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Playwright; + productInstallPath = "$(HOME)/Applications"; + productName = Playwright; + productReference = 8D1107320486CEB800E47091 /* Playwright.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 29B97313FDCFA39411CA2CEC /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0700; + LastUpgradeCheck = 1000; + TargetAttributes = { + 8D1107260486CEB800E47091 = { + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + }; + }; + buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Playwright" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 1; + knownRegions = ( + en, + ); + mainGroup = 29B97314FDCFA39411CA2CEB /* Playwright */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8D1107260486CEB800E47091 /* Playwright */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 8D1107290486CEB800E47091 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BC72B89611E57E0F001EB4EB /* BrowserWindow.xib in Resources */, + BC72B89511E57E07001EB4EB /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 8D11072C0486CEB800E47091 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 256AC3DA0F4B6AC300CF336A /* AppDelegate.m in Sources */, + BC329487116A92E2008635D1 /* main.m in Sources */, + 51E244FA11EFCE07008228D2 /* MBToolbarItem.m in Sources */, + BC329498116A941B008635D1 /* BrowserWindowController.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + C01FCF4B08A954540054247C /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BCA8CBDF11E578A000812FB8 /* Playwright.xcconfig */; + buildSettings = { + }; + name = Debug; + }; + C01FCF4C08A954540054247B /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BCA8CBDF11E578A000812FB8 /* Playwright.xcconfig */; + buildSettings = { + }; + name = Release; + }; + C01FCF4F08A954540054247C /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BCA8CBDE11E578A000812FB8 /* DebugRelease.xcconfig */; + buildSettings = { + GCC_OPTIMIZATION_LEVEL = 0; + }; + name = Debug; + }; + C01FCF5008A954540054247C /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BCA8CBDE11E578A000812FB8 /* DebugRelease.xcconfig */; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C01FCF4A08A954540054247C /* Build configuration list for PBXNativeTarget "Playwright" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C01FCF4B08A954540054247C /* Debug */, + C01FCF4C08A954540054247B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Playwright" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C01FCF4F08A954540054247C /* Debug */, + C01FCF5008A954540054247C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 29B97313FDCFA39411CA2CEC /* Project object */; +} diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/Playwright.xcodeproj/xcshareddata/xcschemes/Playwright.xcscheme b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/Playwright.xcodeproj/xcshareddata/xcschemes/Playwright.xcscheme new file mode 100644 index 0000000000000..00fb6b0006c74 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/Playwright.xcodeproj/xcshareddata/xcschemes/Playwright.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/AppDelegate.h b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/AppDelegate.h new file mode 100644 index 0000000000000..4fb6229fa3c32 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/AppDelegate.h @@ -0,0 +1,53 @@ +/* + * 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. + */ + +#import +#import + +@interface WebViewDialog : NSObject +@property (nonatomic, strong) WKWebView *webView; +@property (nonatomic, copy) void (^completionHandler)(BOOL accept, NSString* value); +@end + +@interface BrowserAppDelegate : NSObject { + NSMutableSet *_headlessWindows; + NSMutableSet *_browserContexts; + bool _headless; + bool _noStartupWindow; + NSMutableSet *_dialogs; + NSString* _initialURL; + NSString* _userDataDir; + NSString* _proxyServer; + NSString* _proxyBypassList; + IBOutlet NSMenuItem *_newWebKit2WindowItem; +} + +@end + +@interface NSApplication (PlaywrightApplicationExtensions) + +- (BrowserAppDelegate *)browserAppDelegate; + +@end diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/AppDelegate.m b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/AppDelegate.m new file mode 100644 index 0000000000000..8f20d371771e3 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/AppDelegate.m @@ -0,0 +1,494 @@ +/* + * 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. + */ + +#import "AppDelegate.h" + +#import "BrowserWindowController.h" +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +@implementation NSApplication (PlaywrightApplicationExtensions) + +- (BrowserAppDelegate *)browserAppDelegate +{ + return (BrowserAppDelegate *)[self delegate]; +} + +@end + +@interface NSApplication (TouchBar) +@property (getter=isAutomaticCustomizeTouchBarMenuItemEnabled) BOOL automaticCustomizeTouchBarMenuItemEnabled; + +@property (readonly, nonatomic) WKWebViewConfiguration *defaultConfiguration; + +@end + +@implementation WebViewDialog +- (void)dealloc +{ + [_webView release]; + _webView = nil; + [super dealloc]; +} +@end + +enum { + _NSBackingStoreUnbuffered = 3 +}; + +NSString* const ActivityReason = @"Batch headless process"; +const NSActivityOptions ActivityOptions = + (NSActivityUserInitiatedAllowingIdleSystemSleep | + NSActivityLatencyCritical) & + ~(NSActivitySuddenTerminationDisabled | + NSActivityAutomaticTerminationDisabled); + +@implementation BrowserAppDelegate + +- (id)init +{ + self = [super init]; + + if (!self) + return nil; + + _initialURL = nil; + _userDataDir = nil; + _proxyServer = nil; + _proxyBypassList = nil; + NSArray *arguments = [[NSProcessInfo processInfo] arguments]; + NSRange subargs = NSMakeRange(1, [arguments count] - 1); + NSArray *subArray = [arguments subarrayWithRange:subargs]; + + for (NSString *argument in subArray) { + if (![argument hasPrefix:@"--"]) + _initialURL = argument; + if ([argument hasPrefix:@"--user-data-dir="]) { + NSRange range = NSMakeRange(16, [argument length] - 16); + _userDataDir = [[argument substringWithRange:range] copy]; + } + if ([argument hasPrefix:@"--proxy="]) { + NSRange range = NSMakeRange(8, [argument length] - 8); + _proxyServer = [[argument substringWithRange:range] copy]; + } + if ([argument hasPrefix:@"--proxy-bypass-list="]) { + NSRange range = NSMakeRange(20, [argument length] - 20); + _proxyBypassList = [[argument substringWithRange:range] copy]; + } + } + + _headless = [arguments containsObject: @"--headless"]; + _noStartupWindow = [arguments containsObject: @"--no-startup-window"]; + _browserContexts = [[NSMutableSet alloc] init]; + + if (_headless) { + _headlessWindows = [[NSMutableSet alloc] init]; + [NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory]; + [[NSProcessInfo processInfo] beginActivityWithOptions:ActivityOptions + reason:ActivityReason]; + _dialogs = [[NSMutableSet alloc] init]; + } else { + [NSApp activateIgnoringOtherApps:YES]; + } + if ([arguments containsObject: @"--inspector-pipe"]) + [_WKBrowserInspector initializeRemoteInspectorPipe:self headless:_headless]; + return self; +} + +- (void)awakeFromNib +{ + if ([NSApp respondsToSelector:@selector(setAutomaticCustomizeTouchBarMenuItemEnabled:)]) + [NSApp setAutomaticCustomizeTouchBarMenuItemEnabled:YES]; +} + + +- (NSDictionary *)proxyConfiguration:(NSString *)proxyServer WithBypassList:(NSString *)proxyBypassList +{ + if (!proxyServer || ![proxyServer length]) + return nil; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + + NSMutableDictionary *dictionary = [[[NSMutableDictionary alloc] init] autorelease]; + NSURL *proxyURL = [NSURL URLWithString:proxyServer]; + NSString *host = [proxyURL host]; + NSNumber *port = [proxyURL port]; + if ([proxyServer hasPrefix:@"socks5://"]) { + [dictionary setObject:host forKey:(NSString *)kCFStreamPropertySOCKSProxyHost]; + if (port) + [dictionary setObject:port forKey:(NSString *)kCFStreamPropertySOCKSProxyPort]; + } else { + [dictionary setObject:host forKey:(NSString *)kCFStreamPropertyHTTPSProxyHost]; + [dictionary setObject:host forKey:(NSString *)kCFStreamPropertyHTTPProxyHost]; + if (port) { + [dictionary setObject:port forKey:(NSString *)kCFStreamPropertyHTTPSProxyPort]; + [dictionary setObject:port forKey:(NSString *)kCFStreamPropertyHTTPProxyPort]; + } + } + + if (proxyBypassList && [proxyBypassList length]) { + NSArray* bypassList = [proxyBypassList componentsSeparatedByString:@","]; + [dictionary setObject:bypassList forKey:@"ExceptionsList"]; + } + +#pragma clang diagnostic pop + + return dictionary; +} + +- (WKWebsiteDataStore *)persistentDataStore +{ + static WKWebsiteDataStore *dataStore; + + if (!dataStore) { + _WKWebsiteDataStoreConfiguration *configuration = [[[_WKWebsiteDataStoreConfiguration alloc] init] autorelease]; + if (_userDataDir) { + NSURL *cookieFile = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/cookie.db", _userDataDir]]; + [configuration _setCookieStorageFile:cookieFile]; + + NSURL *applicationCacheDirectory = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/ApplicationCache", _userDataDir]]; + [configuration setApplicationCacheDirectory:applicationCacheDirectory]; + + NSURL *cacheStorageDirectory = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/CacheStorage", _userDataDir]]; + [configuration _setCacheStorageDirectory:cacheStorageDirectory]; + + NSURL *indexedDBDirectory = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/IndexedDB", _userDataDir]]; + [configuration _setIndexedDBDatabaseDirectory:indexedDBDirectory]; + + NSURL *localStorageDirectory = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/LocalStorage", _userDataDir]]; + [configuration _setWebStorageDirectory:localStorageDirectory]; + + NSURL *mediaCacheDirectory = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/MediaCache", _userDataDir]]; + [configuration setMediaCacheDirectory:mediaCacheDirectory]; + + NSURL *mediaKeysDirectory = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/MediaKeys", _userDataDir]]; + [configuration setMediaKeysStorageDirectory:mediaKeysDirectory]; + + NSURL *networkCacheDirectory = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/NetworkCache", _userDataDir]]; + [configuration setNetworkCacheDirectory:networkCacheDirectory]; + + NSURL *loadStatsDirectory = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/ResourceLoadStatistics", _userDataDir]]; + [configuration _setResourceLoadStatisticsDirectory:loadStatsDirectory]; + + NSURL *serviceWorkersDirectory = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/ServiceWorkers", _userDataDir]]; + [configuration _setServiceWorkerRegistrationDirectory:serviceWorkersDirectory]; + + NSURL *webSqlDirectory = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/WebSQL", _userDataDir]]; + [configuration _setWebSQLDatabaseDirectory:webSqlDirectory]; + } + [configuration setProxyConfiguration:[self proxyConfiguration:_proxyServer WithBypassList:_proxyBypassList]]; + dataStore = [[WKWebsiteDataStore alloc] _initWithConfiguration:configuration]; + } + + return dataStore; +} + +- (WKWebViewConfiguration *)defaultConfiguration +{ + static WKWebViewConfiguration *configuration; + + if (!configuration) { + configuration = [[WKWebViewConfiguration alloc] init]; + configuration.websiteDataStore = [self persistentDataStore]; + configuration.preferences._fullScreenEnabled = YES; + configuration.preferences._developerExtrasEnabled = YES; + configuration.preferences._mediaDevicesEnabled = YES; + configuration.preferences._mockCaptureDevicesEnabled = YES; + configuration.preferences._hiddenPageDOMTimerThrottlingEnabled = NO; + configuration.preferences._hiddenPageDOMTimerThrottlingAutoIncreases = NO; + configuration.preferences._pageVisibilityBasedProcessSuppressionEnabled = NO; + configuration.preferences._domTimersThrottlingEnabled = NO; + configuration.preferences._requestAnimationFrameEnabled = YES; + _WKProcessPoolConfiguration *processConfiguration = [[[_WKProcessPoolConfiguration alloc] init] autorelease]; + processConfiguration.forceOverlayScrollbars = YES; + configuration.processPool = [[[WKProcessPool alloc] _initWithConfiguration:processConfiguration] autorelease]; + } + return configuration; +} + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification +{ + if (!_headless) + [self _updateNewWindowKeyEquivalents]; + + if (_noStartupWindow) + return; + + // Force creation of the default browser context. + [self defaultConfiguration]; + // Creating the first NSWindow immediately makes it invisible in headless mode, + // so we postpone it for 50ms. Experiments show that 10ms is not enough, and 20ms is enough. + // We give it 50ms just in case. + [NSTimer scheduledTimerWithTimeInterval: 0.05 + repeats: NO + block:(void *)^(NSTimer* timer) + { + [self createNewPage:0 withURL:_initialURL ? _initialURL : @"about:blank"]; + _initialURL = nil; + }]; +} + +- (void)_updateNewWindowKeyEquivalents +{ + NSString *normalWindowEquivalent = @"n"; + _newWebKit2WindowItem.keyEquivalentModifierMask = NSEventModifierFlagCommand; + _newWebKit2WindowItem.keyEquivalent = normalWindowEquivalent; +} + +#pragma mark WKBrowserInspectorDelegate + +- (WKWebViewConfiguration *) sessionConfiguration:(uint64_t)sessionID +{ + for (_WKBrowserContext *browserContext in _browserContexts) { + if ([[browserContext dataStore] sessionID] != sessionID) + continue; + WKWebViewConfiguration *configuration = [[[self defaultConfiguration] copy] autorelease]; + configuration.websiteDataStore = [browserContext dataStore]; + configuration.processPool = [browserContext processPool]; + return configuration; + } + return [self defaultConfiguration]; +} + +- (WKWebView *)createNewPage:(uint64_t)sessionID +{ + return [self createNewPage:sessionID withURL:@"about:blank"]; +} + +- (WKWebView *)createNewPage:(uint64_t)sessionID withURL:(NSString*)urlString +{ + WKWebViewConfiguration *configuration = [self sessionConfiguration:sessionID]; + if (_headless) + return [self createHeadlessPage:configuration withURL:urlString]; + return [self createHeadfulPage:configuration withURL:urlString]; +} + +- (WKWebView *)createHeadfulPage:(WKWebViewConfiguration *)configuration withURL:(NSString*)urlString +{ + // WebView lifecycle will control the BrowserWindowController life times. + BrowserWindowController *controller = [[BrowserWindowController alloc] initWithConfiguration:configuration]; + if (!controller) + return nil; + [controller loadURLString:urlString]; + NSWindow *window = controller.window; + [window setIsVisible:YES]; + return [controller webView]; +} + +- (WKWebView *)createHeadlessPage:(WKWebViewConfiguration *)configuration withURL:(NSString*)urlString +{ + NSRect rect = NSMakeRect(0, 0, 1280, 720); + NSScreen *firstScreen = [[NSScreen screens] objectAtIndex:0]; + NSRect windowRect = NSOffsetRect(rect, -10000, [firstScreen frame].size.height - rect.size.height + 10000); + NSWindow* window = [[NSWindow alloc] initWithContentRect:windowRect styleMask:NSWindowStyleMaskBorderless backing:(NSBackingStoreType)_NSBackingStoreUnbuffered defer:YES]; + + WKWebView* webView = [[WKWebView alloc] initWithFrame:[window.contentView bounds] configuration:configuration]; + webView._windowOcclusionDetectionEnabled = NO; + if (!webView) + return nil; + + webView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; + [window.contentView addSubview:webView]; + [window setIsVisible:YES]; + if (urlString) { + NSURL *url = [NSURL _webkit_URLWithUserTypedString:urlString]; + [webView loadRequest:[NSURLRequest requestWithURL:url]]; + } + [_headlessWindows addObject:window]; + webView.navigationDelegate = self; + webView.UIDelegate = self; + return [webView autorelease]; +} + +- (_WKBrowserContext *)createBrowserContext:(NSString *)proxyServer WithBypassList:(NSString *) proxyBypassList +{ + _WKBrowserContext *browserContext = [[_WKBrowserContext alloc] init]; + _WKProcessPoolConfiguration *processConfiguration = [[[_WKProcessPoolConfiguration alloc] init] autorelease]; + processConfiguration.forceOverlayScrollbars = YES; + _WKWebsiteDataStoreConfiguration *dataStoreConfiguration = [[[_WKWebsiteDataStoreConfiguration alloc] initNonPersistentConfiguration] autorelease]; + if (!proxyServer || ![proxyServer length]) + proxyServer = _proxyServer; + if (!proxyBypassList || ![proxyBypassList length]) + proxyBypassList = _proxyBypassList; + [dataStoreConfiguration setProxyConfiguration:[self proxyConfiguration:proxyServer WithBypassList:proxyBypassList]]; + browserContext.dataStore = [[[WKWebsiteDataStore alloc] _initWithConfiguration:dataStoreConfiguration] autorelease]; + browserContext.processPool = [[[WKProcessPool alloc] _initWithConfiguration:processConfiguration] autorelease]; + [_browserContexts addObject:browserContext]; + return browserContext; +} + +- (void)deleteBrowserContext:(uint64_t)sessionID +{ + for (_WKBrowserContext *browserContext in _browserContexts) { + if ([[browserContext dataStore] sessionID] != sessionID) + continue; + [_browserContexts removeObject:browserContext]; + return; + } +} + +- (void)quit +{ + [NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0]; +} + +#pragma mark WKUIDelegate + +- (void)webViewDidClose:(WKWebView *)webView { + [self webView:webView handleJavaScriptDialog:false value:nil]; + for (NSWindow *window in _headlessWindows) { + if (webView.window != window) + continue; + [webView removeFromSuperview]; + [window close]; + [_headlessWindows removeObject:window]; + break; + } +} + +- (void)_webView:(WKWebView *)webView getWindowFrameWithCompletionHandler:(void (^)(CGRect))completionHandler +{ + completionHandler([webView.window frame]); +} + +- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler +{ + WebViewDialog* dialog = [[WebViewDialog alloc] autorelease]; + dialog.webView = webView; + dialog.completionHandler = ^void (BOOL accept, NSString* value) { + completionHandler(); + }; + [_dialogs addObject:dialog]; +} + +- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler +{ + WebViewDialog* dialog = [[WebViewDialog alloc] autorelease]; + dialog.webView = webView; + dialog.completionHandler = ^void (BOOL accept, NSString* value) { + completionHandler(accept); + }; + [_dialogs addObject:dialog]; +} + +- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString *result))completionHandler +{ + WebViewDialog* dialog = [[WebViewDialog alloc] autorelease]; + dialog.webView = webView; + dialog.completionHandler = ^void (BOOL accept, NSString* value) { + completionHandler(accept && value ? value : nil); + }; + [_dialogs addObject:dialog]; +} + +- (void)_webView:(WKWebView *)webView runBeforeUnloadConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler +{ + WebViewDialog* dialog = [[WebViewDialog alloc] autorelease]; + dialog.webView = webView; + dialog.completionHandler = ^void (BOOL accept, NSString* value) { + completionHandler(accept); + }; + [_dialogs addObject:dialog]; +} + +- (void)webView:(WKWebView *)webView handleJavaScriptDialog:(BOOL)accept value:(NSString *)value +{ + for (WebViewDialog *dialog in _dialogs) { + if (dialog.webView != webView) + continue; + dialog.completionHandler(accept, value); + [_dialogs removeObject:dialog]; + break; + } +} + +- (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures +{ + return [self createHeadlessPage:configuration withURL:nil]; +} + +- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler +{ + LOG(@"decidePolicyForNavigationAction"); + + if (navigationAction.shouldPerformDownload) { + decisionHandler(WKNavigationActionPolicyDownload); + return; + } + if (navigationAction._canHandleRequest) { + decisionHandler(WKNavigationActionPolicyAllow); + return; + } + decisionHandler(WKNavigationActionPolicyCancel); +} + +- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler +{ + if (![navigationResponse.response isKindOfClass:[NSHTTPURLResponse class]]) { + decisionHandler(WKNavigationResponsePolicyAllow); + return; + } + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)navigationResponse.response; + + NSString *disposition = [[httpResponse allHeaderFields] objectForKey:@"Content-Disposition"]; + if (disposition && [disposition hasPrefix:@"attachment"]) { + decisionHandler(WKNavigationResponsePolicyDownload); + return; + } + decisionHandler(WKNavigationResponsePolicyAllow); +} + +- (void)webView:(WKWebView *)webView navigationAction:(WKNavigationAction *)navigationAction didBecomeDownload:(WKDownload *)download +{ + download.delegate = self; +} + +- (void)webView:(WKWebView *)webView navigationResponse:(WKNavigationResponse *)navigationResponse didBecomeDownload:(WKDownload *)download +{ + download.delegate = self; +} + +#pragma mark WKDownloadDelegate + +- (void)download:(WKDownload *)download decideDestinationUsingResponse:(NSURLResponse *)response suggestedFilename:(NSString *)suggestedFilename completionHandler:(void (^)(NSURL * _Nullable destination))completionHandler +{ + completionHandler(nil); +} + +@end diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/BrowserWindow.xib b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/BrowserWindow.xib new file mode 100644 index 0000000000000..f6f3d8e3a0f16 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/BrowserWindow.xib @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/BrowserWindowController.h b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/BrowserWindowController.h new file mode 100644 index 0000000000000..4dbf13c8fb31a --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/BrowserWindowController.h @@ -0,0 +1,46 @@ +/* + * 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. + */ + +@class WKWebView; + +@interface BrowserWindowController : NSWindowController + +- (IBAction)goBack:(id)sender; +- (IBAction)goForward:(id)sender; +- (IBAction)reload:(id)sender; +- (IBAction)saveAsPDF:(id)sender; +- (IBAction)saveAsWebArchive:(id)sender; +- (IBAction)zoomIn:(id)sender; +- (IBAction)zoomOut:(id)sender; +- (IBAction)resetZoom:(id)sender; +- (IBAction)showHideWebInspector:(id)sender; + +- (IBAction)setPageScale:(id)sender; +- (IBAction)setViewScale:(id)sender; +- (instancetype)initWithConfiguration:(WKWebViewConfiguration *)configuration; +- (void)loadURLString:(NSString *)urlString; +- (WKWebView *)webView; + +@end diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/BrowserWindowController.m b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/BrowserWindowController.m new file mode 100644 index 0000000000000..f5ef03729eed0 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/BrowserWindowController.m @@ -0,0 +1,877 @@ +/* + * 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. + */ + +#import "BrowserWindowController.h" + +#import "AppDelegate.h" +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +static void* keyValueObservingContext = &keyValueObservingContext; + +@interface PlaywrightNSTextFinder : NSTextFinder + +@property (nonatomic, copy) dispatch_block_t hideInterfaceCallback; + +@end + +@implementation PlaywrightNSTextFinder + +- (void)performAction:(NSTextFinderAction)op +{ + [super performAction:op]; + + if (op == NSTextFinderActionHideFindInterface && _hideInterfaceCallback) + _hideInterfaceCallback(); +} + +@end + +@interface BrowserWindowController () +@end + +@implementation BrowserWindowController { + IBOutlet NSProgressIndicator *progressIndicator; + IBOutlet NSButton *reloadButton; + IBOutlet NSButton *backButton; + IBOutlet NSButton *forwardButton; + IBOutlet NSButton *share; + IBOutlet NSToolbar *toolbar; + IBOutlet NSTextField *urlText; + IBOutlet NSView *containerView; + IBOutlet NSButton *toggleUseShrinkToFitButton; + + WKWebViewConfiguration *_configuration; + WKWebView *_webView; + BOOL _zoomTextOnly; + BOOL _isPrivateBrowsingWindow; + NSAlert* _alert; + + BOOL _useShrinkToFit; + + PlaywrightNSTextFinder *_textFinder; + NSView *_textFindBarView; + BOOL _findBarVisible; +} + +- (id)initWithWindow:(NSWindow *)window +{ + self = [super initWithWindow:window]; + return self; +} + +- (void)windowDidLoad +{ + [share sendActionOn:NSEventMaskLeftMouseDown]; + [super windowDidLoad]; +} + +- (IBAction)openLocation:(id)sender +{ + [[self window] makeFirstResponder:urlText]; +} + +- (NSString *)addProtocolIfNecessary:(NSString *)address +{ + if ([address rangeOfString:@"://"].length > 0) + return address; + + if ([address hasPrefix:@"data:"]) + return address; + + if ([address hasPrefix:@"about:"]) + return address; + + return [@"http://" stringByAppendingString:address]; +} + +- (IBAction)share:(id)sender +{ + NSSharingServicePicker *picker = [[NSSharingServicePicker alloc] initWithItems:@[ self.currentURL ]]; + picker.delegate = self; + [picker showRelativeToRect:NSZeroRect ofView:sender preferredEdge:NSRectEdgeMinY]; +} + +- (IBAction)showHideWebView:(id)sender +{ + self.mainContentView.hidden = !self.mainContentView.isHidden; +} + +- (CGFloat)pageScaleForMenuItemTag:(NSInteger)tag +{ + if (tag == 1) + return 1; + if (tag == 2) + return 1.25; + if (tag == 3) + return 1.5; + if (tag == 4) + return 2.0; + + return 1; +} + +- (void)awakeFromNib +{ + _webView = [[WKWebView alloc] initWithFrame:[containerView bounds] configuration:_configuration]; + _webView._windowOcclusionDetectionEnabled = NO; + + _webView.allowsMagnification = YES; + _webView.allowsBackForwardNavigationGestures = YES; + + [_webView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)]; + [containerView addSubview:_webView]; + + [progressIndicator bind:NSHiddenBinding toObject:_webView withKeyPath:@"loading" options:@{ NSValueTransformerNameBindingOption : NSNegateBooleanTransformerName }]; + [progressIndicator bind:NSValueBinding toObject:_webView withKeyPath:@"estimatedProgress" options:nil]; + + [_webView addObserver:self forKeyPath:@"title" options:0 context:keyValueObservingContext]; + [_webView addObserver:self forKeyPath:@"URL" options:0 context:keyValueObservingContext]; + + _webView.navigationDelegate = self; + _webView.UIDelegate = self; + + _webView._observedRenderingProgressEvents = _WKRenderingProgressEventFirstLayout + | _WKRenderingProgressEventFirstVisuallyNonEmptyLayout + | _WKRenderingProgressEventFirstPaintWithSignificantArea + | _WKRenderingProgressEventFirstLayoutAfterSuppressedIncrementalRendering + | _WKRenderingProgressEventFirstPaintAfterSuppressedIncrementalRendering; + + _webView.customUserAgent = @"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.4 Safari/605.1.15"; + + _webView._usePlatformFindUI = NO; + + _textFinder = [[PlaywrightNSTextFinder alloc] init]; + _textFinder.incrementalSearchingEnabled = YES; + _textFinder.incrementalSearchingShouldDimContentView = NO; + _textFinder.client = _webView; + _textFinder.findBarContainer = self; + _textFinder.hideInterfaceCallback = ^{ + [_webView _hideFindUI]; + }; + + _zoomTextOnly = NO; +} + +- (instancetype)initWithConfiguration:(WKWebViewConfiguration *)configuration +{ + if (!(self = [super initWithWindowNibName:@"BrowserWindow"])) + return nil; + _configuration = [configuration copy]; + _isPrivateBrowsingWindow = !_configuration.websiteDataStore.isPersistent; + self.window.styleMask &= ~NSWindowStyleMaskFullSizeContentView; + [self.window makeKeyAndOrderFront:nil]; + return self; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + [progressIndicator unbind:NSHiddenBinding]; + [progressIndicator unbind:NSValueBinding]; + + [_textFinder release]; + [_webView release]; + [_configuration release]; + + [super dealloc]; +} + +- (IBAction)fetch:(id)sender +{ + [urlText setStringValue:[self addProtocolIfNecessary:urlText.stringValue]]; + NSURL *url = [NSURL _webkit_URLWithUserTypedString:urlText.stringValue]; + [_webView loadRequest:[NSURLRequest requestWithURL:url]]; +} + +- (IBAction)setPageScale:(id)sender +{ + CGFloat scale = [self pageScaleForMenuItemTag:[sender tag]]; + [_webView _setPageScale:scale withOrigin:CGPointZero]; +} + +- (CGFloat)viewScaleForMenuItemTag:(NSInteger)tag +{ + if (tag == 1) + return 1; + if (tag == 2) + return 0.75; + if (tag == 3) + return 0.5; + if (tag == 4) + return 0.25; + + return 1; +} + +- (IBAction)setViewScale:(id)sender +{ + CGFloat scale = [self viewScaleForMenuItemTag:[sender tag]]; + CGFloat oldScale = [_webView _viewScale]; + + if (scale == oldScale) + return; + + [_webView _setLayoutMode:_WKLayoutModeDynamicSizeComputedFromViewScale]; + + NSRect oldFrame = self.window.frame; + NSSize newFrameSize = NSMakeSize(oldFrame.size.width * (scale / oldScale), oldFrame.size.height * (scale / oldScale)); + [self.window setFrame:NSMakeRect(oldFrame.origin.x, oldFrame.origin.y - (newFrameSize.height - oldFrame.size.height), newFrameSize.width, newFrameSize.height) display:NO animate:NO]; + + [_webView _setViewScale:scale]; +} + +static BOOL areEssentiallyEqual(double a, double b) +{ + double tolerance = 0.001; + return (fabs(a - b) <= tolerance); +} + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-implementations" +- (BOOL)validateMenuItem:(NSMenuItem *)menuItem +#pragma GCC diagnostic pop +{ + SEL action = menuItem.action; + + if (action == @selector(saveAsPDF:)) + return YES; + if (action == @selector(saveAsWebArchive:)) + return YES; + + if (action == @selector(zoomIn:)) + return [self canZoomIn]; + if (action == @selector(zoomOut:)) + return [self canZoomOut]; + if (action == @selector(resetZoom:)) + return [self canResetZoom]; + + if (action == @selector(toggleZoomMode:)) + [menuItem setState:_zoomTextOnly ? NSControlStateValueOn : NSControlStateValueOff]; + else if (action == @selector(showHideWebInspector:)) + [menuItem setTitle:_webView._inspector.isVisible ? @"Close Web Inspector" : @"Show Web Inspector"]; + + if (action == @selector(setPageScale:)) + [menuItem setState:areEssentiallyEqual([_webView _pageScale], [self pageScaleForMenuItemTag:[menuItem tag]])]; + + if (action == @selector(setViewScale:)) + [menuItem setState:areEssentiallyEqual([_webView _viewScale], [self viewScaleForMenuItemTag:[menuItem tag]])]; + + return YES; +} + +- (IBAction)reload:(id)sender +{ + [_webView reload]; +} + +- (IBAction)goBack:(id)sender +{ + [_webView goBack]; +} + +- (IBAction)goForward:(id)sender +{ + [_webView goForward]; +} + +- (IBAction)toggleZoomMode:(id)sender +{ + if (_zoomTextOnly) { + _zoomTextOnly = NO; + double currentTextZoom = _webView._textZoomFactor; + _webView._textZoomFactor = 1; + _webView.pageZoom = currentTextZoom; + } else { + _zoomTextOnly = YES; + double currentPageZoom = _webView._pageZoomFactor; + _webView._textZoomFactor = currentPageZoom; + _webView.pageZoom = 1; + } +} + +- (IBAction)resetZoom:(id)sender +{ + if (![self canResetZoom]) + return; + + if (_zoomTextOnly) + _webView._textZoomFactor = 1; + else + _webView.pageZoom = 1; +} + +- (BOOL)canResetZoom +{ + return _zoomTextOnly ? (_webView._textZoomFactor != 1) : (_webView.pageZoom != 1); +} + +- (IBAction)showHideWebInspector:(id)sender +{ + _WKInspector *inspector = _webView._inspector; + if (inspector.isVisible) + [inspector hide]; + else + [inspector show]; +} + +- (NSURL *)currentURL +{ + return _webView.URL; +} + +- (NSView *)mainContentView +{ + return _webView; +} + +- (BOOL)validateUserInterfaceItem:(id )item +{ + SEL action = item.action; + + if (action == @selector(goBack:) || action == @selector(goForward:)) + return [_webView validateUserInterfaceItem:item]; + + return YES; +} + +- (void)validateToolbar +{ + [toolbar validateVisibleItems]; +} + +- (BOOL)windowShouldClose:(id)sender +{ + return YES; +} + +- (void)windowWillClose:(NSNotification *)notification +{ + [_webView removeObserver:self forKeyPath:@"title"]; + [_webView removeObserver:self forKeyPath:@"URL"]; + [_webView removeFromSuperview]; + _textFinder.hideInterfaceCallback = nil; + [self release]; + + // Post two events (don't ask me why!) to spin event loop and drain + // automatically created autorelease pools that will release our window. + // See https://www.mikeash.com/pyblog/more-fun-with-autorelease.html + // for some discussion. + NSEvent* event1 = [NSEvent + otherEventWithType:NSEventTypeApplicationDefined + location:NSMakePoint(0, 0) + modifierFlags:0 + timestamp:[[NSDate date] timeIntervalSince1970] + windowNumber:0 + context:nil + subtype:0 + data1:0 + data2:0]; + [NSApp postEvent:event1 atStart:YES]; + NSEvent* event2 = [NSEvent + otherEventWithType:NSEventTypeApplicationDefined + location:NSMakePoint(0, 0) + modifierFlags:0 + timestamp:[[NSDate date] timeIntervalSince1970] + windowNumber:0 + context:nil + subtype:0 + data1:0 + data2:0]; + [NSApp postEvent:event2 atStart:NO]; +} + +- (void)webViewDidClose:(WKWebView *)webView { + [self webView:webView handleJavaScriptDialog:false value:nil]; + [self.window close]; +} + +- (void)_webView:(WKWebView *)webView getWindowFrameWithCompletionHandler:(void (^)(CGRect))completionHandler +{ + completionHandler([self.window frame]); +} + +#define DefaultMinimumZoomFactor (.5) +#define DefaultMaximumZoomFactor (3.0) +#define DefaultZoomFactorRatio (1.2) + +- (CGFloat)currentZoomFactor +{ + return _zoomTextOnly ? _webView._textZoomFactor : _webView.pageZoom; +} + +- (void)setCurrentZoomFactor:(CGFloat)factor +{ + if (_zoomTextOnly) + _webView._textZoomFactor = factor; + else + _webView.pageZoom = factor; +} + +- (BOOL)canZoomIn +{ + return self.currentZoomFactor * DefaultZoomFactorRatio < DefaultMaximumZoomFactor; +} + +- (void)zoomIn:(id)sender +{ + if (!self.canZoomIn) + return; + + self.currentZoomFactor *= DefaultZoomFactorRatio; +} + +- (BOOL)canZoomOut +{ + return self.currentZoomFactor / DefaultZoomFactorRatio > DefaultMinimumZoomFactor; +} + +- (void)zoomOut:(id)sender +{ + if (!self.canZoomIn) + return; + + self.currentZoomFactor /= DefaultZoomFactorRatio; +} + +- (void)updateTitle:(NSString *)title +{ + if (!title) { + NSURL *url = _webView.URL; + title = url.lastPathComponent ?: url._web_userVisibleString; + } + + self.window.title = title; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context +{ + if (context != keyValueObservingContext || object != _webView) + return; + + if ([keyPath isEqualToString:@"title"]) + [self updateTitle:_webView.title]; + else if ([keyPath isEqualToString:@"URL"]) + [self updateTextFieldFromURL:_webView.URL]; +} + +- (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures +{ + // WebView lifecycle will control the BrowserWindowController life times. + BrowserWindowController *controller = [[BrowserWindowController alloc] initWithConfiguration:configuration]; + return controller->_webView; +} + +- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler +{ + NSAlert* alert = [[NSAlert alloc] init]; + + [alert setMessageText:[NSString stringWithFormat:@"JavaScript alert dialog from %@.", [frame.request.URL absoluteString]]]; + [alert setInformativeText:message]; + [alert addButtonWithTitle:@"OK"]; + + _alert = alert; + [alert beginSheetModalForWindow:self.window completionHandler:^void (NSModalResponse response) { + completionHandler(); + [alert release]; + _alert = nil; + }]; +} + +- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler +{ + NSAlert* alert = [[NSAlert alloc] init]; + + [alert setMessageText:[NSString stringWithFormat:@"JavaScript confirm dialog from %@.", [frame.request.URL absoluteString]]]; + [alert setInformativeText:message]; + + [alert addButtonWithTitle:@"OK"]; + [alert addButtonWithTitle:@"Cancel"]; + + _alert = alert; + [alert beginSheetModalForWindow:self.window completionHandler:^void (NSModalResponse response) { + completionHandler(response == NSAlertFirstButtonReturn); + [alert release]; + _alert = nil; + }]; +} + +- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString *result))completionHandler +{ + NSAlert* alert = [[NSAlert alloc] init]; + + [alert setMessageText:[NSString stringWithFormat:@"JavaScript prompt dialog from %@.", [frame.request.URL absoluteString]]]; + [alert setInformativeText:prompt]; + + [alert addButtonWithTitle:@"OK"]; + [alert addButtonWithTitle:@"Cancel"]; + + NSTextField* input = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 200, 24)]; + [input setStringValue:defaultText]; + [alert setAccessoryView:input]; + + _alert = alert; + [alert beginSheetModalForWindow:self.window completionHandler:^void (NSModalResponse response) { + [input validateEditing]; + completionHandler(response == NSAlertFirstButtonReturn ? [input stringValue] : nil); + [alert release]; + _alert = nil; + }]; +} + +- (void)webView:(WKWebView *)webView handleJavaScriptDialog:(BOOL)accept value:(NSString *)value +{ + if (!_alert) + return; + NSTextField* input = (NSTextField*)_alert.accessoryView; + if (accept && input && value) + [input setStringValue:value]; + [self.window endSheet:_alert.window returnCode: accept ? NSAlertFirstButtonReturn : NSModalResponseCancel]; +} + +#if __has_feature(objc_generics) +- (void)webView:(WKWebView *)webView runOpenPanelWithParameters:(WKOpenPanelParameters *)parameters initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSArray * URLs))completionHandler +#else +- (void)webView:(WKWebView *)webView runOpenPanelWithParameters:(WKOpenPanelParameters *)parameters initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSArray *URLs))completionHandler +#endif +{ + NSOpenPanel *openPanel = [NSOpenPanel openPanel]; + + openPanel.allowsMultipleSelection = parameters.allowsMultipleSelection; + + [openPanel beginSheetModalForWindow:webView.window completionHandler:^(NSInteger result) { + if (result == NSModalResponseOK) + completionHandler(openPanel.URLs); + else + completionHandler(nil); + }]; +} + +- (void)_webView:(WebView *)sender runBeforeUnloadConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler +{ + NSAlert *alert = [[NSAlert alloc] init]; + + alert.messageText = [NSString stringWithFormat:@"JavaScript before unload dialog from %@.", [frame.request.URL absoluteString]]; + alert.informativeText = message; + + [alert addButtonWithTitle:@"Leave Page"]; + [alert addButtonWithTitle:@"Stay On Page"]; + + _alert = alert; + [alert beginSheetModalForWindow:self.window completionHandler:^void (NSModalResponse response) { + completionHandler(response == NSAlertFirstButtonReturn); + [alert release]; + _alert = nil; + }]; +} + +- (WKDragDestinationAction)_webView:(WKWebView *)webView dragDestinationActionMaskForDraggingInfo:(id)draggingInfo +{ + return WKDragDestinationActionAny; +} + +- (void)updateTextFieldFromURL:(NSURL *)URL +{ + if (!URL) + return; + + if (!URL.absoluteString.length) + return; + + urlText.stringValue = [URL _web_userVisibleString]; +} + +- (void)loadURLString:(NSString *)urlString +{ + // FIXME: We shouldn't have to set the url text here. + [urlText setStringValue:urlString]; + [self fetch:nil]; +} + +- (void)loadHTMLString:(NSString *)HTMLString +{ + [_webView loadHTMLString:HTMLString baseURL:nil]; +} + +static NSSet *dataTypes() +{ + return [WKWebsiteDataStore allWebsiteDataTypes]; +} + +- (IBAction)fetchWebsiteData:(id)sender +{ + [_configuration.websiteDataStore _fetchDataRecordsOfTypes:dataTypes() withOptions:_WKWebsiteDataStoreFetchOptionComputeSizes completionHandler:^(NSArray *websiteDataRecords) { + NSLog(@"did fetch website data %@.", websiteDataRecords); + }]; +} + +- (IBAction)fetchAndClearWebsiteData:(id)sender +{ + [_configuration.websiteDataStore fetchDataRecordsOfTypes:dataTypes() completionHandler:^(NSArray *websiteDataRecords) { + [_configuration.websiteDataStore removeDataOfTypes:dataTypes() forDataRecords:websiteDataRecords completionHandler:^{ + [_configuration.websiteDataStore fetchDataRecordsOfTypes:dataTypes() completionHandler:^(NSArray *websiteDataRecords) { + NSLog(@"did clear website data, after clearing data is %@.", websiteDataRecords); + }]; + }]; + }]; +} + +- (IBAction)clearWebsiteData:(id)sender +{ + [_configuration.websiteDataStore removeDataOfTypes:dataTypes() modifiedSince:[NSDate distantPast] completionHandler:^{ + NSLog(@"Did clear website data."); + }]; +} + +- (IBAction)printWebView:(id)sender +{ + [[_webView printOperationWithPrintInfo:[NSPrintInfo sharedPrintInfo]] runOperationModalForWindow:self.window delegate:nil didRunSelector:nil contextInfo:nil]; +} + +#pragma mark WKNavigationDelegate + +- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler +{ + LOG(@"decidePolicyForNavigationAction"); + + if (navigationAction.shouldPerformDownload) { + decisionHandler(WKNavigationActionPolicyDownload); + return; + } + + if (navigationAction._canHandleRequest) { + decisionHandler(WKNavigationActionPolicyAllow); + return; + } + decisionHandler(WKNavigationActionPolicyCancel); +} + +- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler +{ + if (![navigationResponse.response isKindOfClass:[NSHTTPURLResponse class]]) { + decisionHandler(WKNavigationResponsePolicyAllow); + return; + } + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)navigationResponse.response; + + NSString *disposition = [[httpResponse allHeaderFields] objectForKey:@"Content-Disposition"]; + if (disposition && [disposition hasPrefix:@"attachment"]) { + decisionHandler(WKNavigationResponsePolicyDownload); + return; + } + decisionHandler(WKNavigationResponsePolicyAllow); +} + +- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation +{ + LOG(@"didStartProvisionalNavigation: %@", navigation); +} + +- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation +{ + LOG(@"didReceiveServerRedirectForProvisionalNavigation: %@", navigation); +} + +- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error +{ + LOG(@"didFailProvisionalNavigation: %@navigation, error: %@", navigation, error); +} + +- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation +{ + LOG(@"didCommitNavigation: %@", navigation); + [self updateTitle:nil]; +} + +- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation +{ + LOG(@"didFinishNavigation: %@", navigation); +} + +- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *__nullable credential))completionHandler +{ + LOG(@"didReceiveAuthenticationChallenge: %@", challenge); + if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic]) { + NSAlert *alert = [[NSAlert alloc] init]; + NSView *container = [[[NSView alloc] initWithFrame:NSMakeRect(0, 0, 200, 48)] autorelease]; + NSTextField *userInput = [[[NSTextField alloc] initWithFrame:NSMakeRect(0, 24, 200, 24)] autorelease]; + NSTextField *passwordInput = [[[NSSecureTextField alloc] initWithFrame:NSMakeRect(0, 0, 200, 24)] autorelease]; + + [alert setMessageText:[NSString stringWithFormat:@"Log in to %@:%lu.", challenge.protectionSpace.host, challenge.protectionSpace.port]]; + [alert addButtonWithTitle:@"Log in"]; + [alert addButtonWithTitle:@"Cancel"]; + [container addSubview:userInput]; + [container addSubview:passwordInput]; + [alert setAccessoryView:container]; + [userInput setNextKeyView:passwordInput]; + [alert.window setInitialFirstResponder:userInput]; + + [alert beginSheetModalForWindow:self.window completionHandler:^(NSModalResponse response) { + [userInput validateEditing]; + if (response == NSAlertFirstButtonReturn) + completionHandler(NSURLSessionAuthChallengeUseCredential, [[[NSURLCredential alloc] initWithUser:[userInput stringValue] password:[passwordInput stringValue] persistence:NSURLCredentialPersistenceForSession] autorelease]); + else + completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, nil); + [alert release]; + }]; + return; + } + completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, nil); +} + +- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error +{ + LOG(@"didFailNavigation: %@, error %@", navigation, error); +} + +- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView +{ + NSLog(@"WebContent process crashed; reloading"); + [self reload:nil]; +} + +- (void)_webView:(WKWebView *)webView renderingProgressDidChange:(_WKRenderingProgressEvents)progressEvents +{ + if (progressEvents & _WKRenderingProgressEventFirstLayout) + LOG(@"renderingProgressDidChange: %@", @"first layout"); + + if (progressEvents & _WKRenderingProgressEventFirstVisuallyNonEmptyLayout) + LOG(@"renderingProgressDidChange: %@", @"first visually non-empty layout"); + + if (progressEvents & _WKRenderingProgressEventFirstPaintWithSignificantArea) + LOG(@"renderingProgressDidChange: %@", @"first paint with significant area"); + + if (progressEvents & _WKRenderingProgressEventFirstLayoutAfterSuppressedIncrementalRendering) + LOG(@"renderingProgressDidChange: %@", @"first layout after suppressed incremental rendering"); + + if (progressEvents & _WKRenderingProgressEventFirstPaintAfterSuppressedIncrementalRendering) + LOG(@"renderingProgressDidChange: %@", @"first paint after suppressed incremental rendering"); +} + +- (void)webView:(WKWebView *)webView shouldLoadIconWithParameters:(_WKLinkIconParameters *)parameters completionHandler:(void (^)(void (^)(NSData*)))completionHandler +{ + completionHandler(^void (NSData *data) { + LOG(@"Icon URL %@ received icon data of length %u", parameters.url, (unsigned)data.length); + }); +} + +#pragma mark Find in Page + +- (IBAction)performTextFinderAction:(id)sender +{ + [_textFinder performAction:[sender tag]]; +} + +- (NSView *)findBarView +{ + return _textFindBarView; +} + +- (void)setFindBarView:(NSView *)findBarView +{ + _textFindBarView = findBarView; + _findBarVisible = YES; + [_textFindBarView setFrame:NSMakeRect(0, 0, containerView.bounds.size.width, _textFindBarView.frame.size.height)]; +} + +- (BOOL)isFindBarVisible +{ + return _findBarVisible; +} + +- (void)setFindBarVisible:(BOOL)findBarVisible +{ + _findBarVisible = findBarVisible; + if (findBarVisible) + [containerView addSubview:_textFindBarView]; + else + [_textFindBarView removeFromSuperview]; +} + +- (NSView *)contentView +{ + return _webView; +} + +- (void)findBarViewDidChangeHeight +{ +} + +- (void)_webView:(WKWebView *)webView requestMediaCaptureAuthorization: (_WKCaptureDevices)devices decisionHandler:(void (^)(BOOL authorized))decisionHandler +{ + decisionHandler(true); +} + +- (void)_webView:(WKWebView *)webView includeSensitiveMediaDeviceDetails:(void (^)(BOOL includeSensitiveDetails))decisionHandler +{ + decisionHandler(false); +} + +- (IBAction)saveAsPDF:(id)sender +{ + NSSavePanel *panel = [NSSavePanel savePanel]; + panel.allowedFileTypes = @[ @"pdf" ]; + [panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) { + if (result == NSModalResponseOK) { + [_webView createPDFWithConfiguration:nil completionHandler:^(NSData *pdfSnapshotData, NSError *error) { + [pdfSnapshotData writeToURL:[panel URL] options:0 error:nil]; + }]; + } + }]; +} + +- (IBAction)saveAsWebArchive:(id)sender +{ + NSSavePanel *panel = [NSSavePanel savePanel]; + panel.allowedFileTypes = @[ @"webarchive" ]; + [panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) { + if (result == NSModalResponseOK) { + [_webView createWebArchiveDataWithCompletionHandler:^(NSData *archiveData, NSError *error) { + [archiveData writeToURL:[panel URL] options:0 error:nil]; + }]; + } + }]; +} + +- (WKWebView *)webView +{ + return _webView; +} + +@end diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/CMakeLists.txt b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/CMakeLists.txt new file mode 100644 index 0000000000000..410d47425b793 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/CMakeLists.txt @@ -0,0 +1,43 @@ +set(PLAYWRIGHT_DIR "${TOOLS_DIR}/Playwright/mac") + +#FIXME: This should not need WEBCORE_EXPORT defined. This means we are including WebCore headers, and we should not. +add_definitions("-include Playwright_Prefix.pch -DWEBCORE_EXPORT=") + +set(Playwright_SOURCES + ${PLAYWRIGHT_DIR}/AppDelegate.m + ${PLAYWRIGHT_DIR}/BrowserWindowController.m + ${PLAYWRIGHT_DIR}/main.m + ${TOOLS_DIR}/Playwright/MBToolbarItem.m +) + +set(Playwright_INCLUDE_DIRECTORIES + ${CMAKE_SOURCE_DIR}/Source + ${FORWARDING_HEADERS_DIR} + ${PLAYWRIGHT_DIR} +) + +set(Playwright_LIBRARIES + WebKit +) + +set(CMAKE_EXE_LINKER_FLAGS "-framework Cocoa") + +set(EXECUTABLE_NAME Playwright) +set(PRODUCT_NAME Playwright) + +set(Playwright_Contents_Directory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Playwright.app/Contents) +make_directory(${Playwright_Contents_Directory}/Resources) +add_custom_command(OUTPUT ${Playwright_Contents_Directory}/Resources/BrowserWindow.nib + COMMAND ibtool --compile ${Playwright_Contents_Directory}/Resources/BrowserWindow.nib ${PLAYWRIGHT_DIR}/BrowserWindow.xib VERBATIM) +add_custom_command(OUTPUT ${Playwright_Contents_Directory}/Resources/MainMenu.nib + COMMAND ibtool --compile ${Playwright_Contents_Directory}/Resources/MainMenu.nib ${PLAYWRIGHT_DIR}/MainMenu.xib VERBATIM) +add_custom_target(PlaywrightNibs ALL DEPENDS + ${Playwright_Contents_Directory}/Resources/BrowserWindow.nib + ${Playwright_Contents_Directory}/Resources/MainMenu.nib +) + +include_directories(${Playwright_INCLUDE_DIRECTORIES}) +add_executable(Playwright MACOSX_BUNDLE ${Playwright_SOURCES}) +set_target_properties(Playwright PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${PLAYWRIGHT_DIR}/Info.plist) +target_link_libraries(Playwright ${Playwright_LIBRARIES}) +add_dependencies(Playwright PlaywrightNibs) diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/Info.plist b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/Info.plist new file mode 100644 index 0000000000000..4ed50c40f2f0d --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/Info.plist @@ -0,0 +1,56 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + WebKit Browser + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleShortVersionString + 1.0 + LSMinimumSystemVersion + ${MACOSX_DEPLOYMENT_TARGET} + CFBundleVersion + 1 + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + NSSupportsAutomaticGraphicsSwitching + + CFBundleDocumentTypes + + + CFBundleTypeExtensions + + html + + CFBundleTypeMIMETypes + + text/html + + CFBundleTypeName + HTML + CFBundleTypeRole + Editor + + + + diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/MainMenu.xib b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/MainMenu.xib new file mode 100644 index 0000000000000..b16d639a1ad18 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/MainMenu.xib @@ -0,0 +1,333 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/Playwright_Prefix.pch b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/Playwright_Prefix.pch new file mode 100644 index 0000000000000..ab6e9bce9a412 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/Playwright_Prefix.pch @@ -0,0 +1,37 @@ +/* + * 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. + */ + +#ifdef __OBJC__ +#import +#import +#endif + +#define ENABLE_LOGGING 0 + +#if ENABLE_LOGGING +#define LOG NSLog +#else +#define LOG(...) ((void)0) +#endif diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/main.m b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/main.m new file mode 100644 index 0000000000000..ba2ca12482c0a --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/mac/main.m @@ -0,0 +1,33 @@ +/* + * 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. + */ + +#import + +int main(int argc, char *argv[]) +{ + [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"WebKitLinkedOnOrAfterEverything"]; + + return NSApplicationMain(argc, (const char **) argv); +} diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/CMakeLists.txt b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/CMakeLists.txt new file mode 100644 index 0000000000000..e2ee2cd772c6b --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/CMakeLists.txt @@ -0,0 +1,41 @@ +set(Playwright_PRIVATE_INCLUDE_DIRECTORIES + ${CMAKE_BINARY_DIR} + ${WebCore_PRIVATE_FRAMEWORK_HEADERS_DIR} +) + +set(Playwright_SOURCES + Common.cpp + MainWindow.cpp + PlaywrightLib.rc + WebKitBrowserWindow.cpp + WinMain.cpp + stdafx.cpp +) + +set(Playwright_PRIVATE_DEFINITIONS _UNICODE) +set(Playwright_PRIVATE_LIBRARIES + WebKit::WTF + comctl32 + shlwapi + user32 +) + +list(APPEND Playwright_PRIVATE_DEFINITIONS ENABLE_WEBKIT) +list(APPEND Playwright_SOURCES + WebKitBrowserWindow.cpp +) +list(APPEND Playwright_PRIVATE_LIBRARIES + WebKit::WebKit +) + +WEBKIT_EXECUTABLE_DECLARE(Playwright) +WEBKIT_WRAP_EXECUTABLE(Playwright + SOURCES ${TOOLS_DIR}/win/DLLLauncher/DLLLauncherMain.cpp Playwright.rc + LIBRARIES shlwapi +) +WEBKIT_EXECUTABLE(Playwright) + +set_target_properties(Playwright PROPERTIES WIN32_EXECUTABLE ON) +if (${WTF_PLATFORM_WIN_CAIRO}) + target_compile_definitions(Playwright PRIVATE WIN_CAIRO) +endif () diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/Common.cpp b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/Common.cpp new file mode 100644 index 0000000000000..accbfdb33f232 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/Common.cpp @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2006, 2008, 2013-2015 Apple Inc. All rights reserved. + * Copyright (C) 2009, 2011 Brent Fulgham. All rights reserved. + * Copyright (C) 2009, 2010, 2011 Appcelerator, Inc. All rights reserved. + * Copyright (C) 2013 Alex Christensen. 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 "stdafx.h" +#include "Common.h" + +#include "DialogHelper.h" +#include "PlaywrightLibResource.h" +#include "PlaywrightReplace.h" +#include +#include +#include +#include +#include + +// Global Variables: +HINSTANCE hInst; + +// Support moving the transparent window +POINT s_windowPosition = { 100, 100 }; +SIZE s_windowSize = { 500, 200 }; + +namespace WebCore { +float deviceScaleFactorForWindow(HWND); +} + +void computeFullDesktopFrame() +{ + RECT desktop; + if (!::SystemParametersInfo(SPI_GETWORKAREA, 0, static_cast(&desktop), 0)) + return; + + float scaleFactor = WebCore::deviceScaleFactorForWindow(nullptr); + + s_windowPosition.x = 0; + s_windowPosition.y = 0; + s_windowSize.cx = scaleFactor * (desktop.right - desktop.left); + s_windowSize.cy = scaleFactor * (desktop.bottom - desktop.top); +} + +BOOL WINAPI DllMain(HINSTANCE dllInstance, DWORD reason, LPVOID) +{ + if (reason == DLL_PROCESS_ATTACH) + hInst = dllInstance; + + return TRUE; +} + +bool getAppDataFolder(_bstr_t& directory) +{ + wchar_t appDataDirectory[MAX_PATH]; + if (FAILED(SHGetFolderPathW(0, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, appDataDirectory))) + return false; + + wchar_t executablePath[MAX_PATH]; + if (!::GetModuleFileNameW(0, executablePath, MAX_PATH)) + return false; + + ::PathRemoveExtensionW(executablePath); + + directory = _bstr_t(appDataDirectory) + L"\\" + ::PathFindFileNameW(executablePath); + + return true; +} + +void createCrashReport(EXCEPTION_POINTERS* exceptionPointers) +{ + _bstr_t directory; + + if (!getAppDataFolder(directory)) + return; + + if (::SHCreateDirectoryEx(0, directory, 0) != ERROR_SUCCESS + && ::GetLastError() != ERROR_FILE_EXISTS + && ::GetLastError() != ERROR_ALREADY_EXISTS) + return; + + std::wstring fileName = std::wstring(static_cast(directory)) + L"\\CrashReport.dmp"; + HANDLE miniDumpFile = ::CreateFile(fileName.c_str(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + + if (miniDumpFile && miniDumpFile != INVALID_HANDLE_VALUE) { + + MINIDUMP_EXCEPTION_INFORMATION mdei; + mdei.ThreadId = ::GetCurrentThreadId(); + mdei.ExceptionPointers = exceptionPointers; + mdei.ClientPointers = 0; + +#ifdef _DEBUG + MINIDUMP_TYPE dumpType = MiniDumpWithFullMemory; +#else + MINIDUMP_TYPE dumpType = MiniDumpNormal; +#endif + + ::MiniDumpWriteDump(::GetCurrentProcess(), ::GetCurrentProcessId(), miniDumpFile, dumpType, &mdei, 0, 0); + ::CloseHandle(miniDumpFile); + processCrashReport(fileName.c_str()); + } +} + +Optional askCredential(HWND hwnd, const std::wstring& realm) +{ + struct AuthDialog : public Dialog { + std::wstring realm; + Credential credential; + + protected: + void setup() + { + setText(IDC_REALM_TEXT, realm); + } + + void ok() final + { + credential.username = getText(IDC_AUTH_USER); + credential.password = getText(IDC_AUTH_PASSWORD); + } + }; + + AuthDialog dialog; + dialog.realm = realm; + + if (dialog.run(hInst, hwnd, IDD_AUTH)) + return dialog.credential; + return WTF::nullopt; +} + +bool askServerTrustEvaluation(HWND hwnd, const std::wstring& text) +{ + class ServerTrustEvaluationDialog : public Dialog { + public: + ServerTrustEvaluationDialog(const std::wstring& text) + : m_text { text } + { + SendMessage(GetDlgItem(this->hDlg(), IDC_SERVER_TRUST_TEXT), WM_SETFONT, (WPARAM)GetStockObject(ANSI_FIXED_FONT), TRUE); + } + + protected: + std::wstring m_text; + + void setup() + { + setText(IDC_SERVER_TRUST_TEXT, m_text); + } + + void ok() final + { + + } + }; + + ServerTrustEvaluationDialog dialog { text }; + return dialog.run(hInst, hwnd, IDD_SERVER_TRUST); +} + +CommandLineOptions parseCommandLine() +{ + CommandLineOptions options; + + int argc = 0; + WCHAR** argv = CommandLineToArgvW(GetCommandLineW(), &argc); + for (int i = 1; i < argc; ++i) { + if (!wcsicmp(argv[i], L"--desktop")) + options.useFullDesktop = true; + else if (!wcsicmp(argv[i], L"--inspector-pipe")) + options.inspectorPipe = true; + else if (!wcsncmp(argv[i], L"--user-data-dir=", 16)) + options.userDataDir = argv[i] + 16; + else if (!wcsncmp(argv[i], L"--curl-proxy=", 13)) + options.curloptProxy = argv[i] + 13; + else if (!wcsncmp(argv[i], L"--curl-noproxy=", 15)) + options.curloptNoproxy = argv[i] + 15; + else if (!wcsicmp(argv[i], L"--headless")) + options.headless = true; + else if (!wcsicmp(argv[i], L"--no-startup-window")) + options.noStartupWindow = true; + else if (!options.requestedURL) + options.requestedURL = argv[i]; + } + + return options; +} + +std::wstring replaceString(std::wstring src, const std::wstring& oldValue, const std::wstring& newValue) +{ + if (src.empty() || oldValue.empty()) + return src; + + size_t pos = 0; + while ((pos = src.find(oldValue, pos)) != src.npos) { + src.replace(pos, oldValue.length(), newValue); + pos += newValue.length(); + } + + return src; +} + +std::wstring createString(WKStringRef wkString) +{ + size_t maxSize = WKStringGetLength(wkString); + + std::vector wkCharBuffer(maxSize); + size_t actualLength = WKStringGetCharacters(wkString, wkCharBuffer.data(), maxSize); + return std::wstring(wkCharBuffer.data(), actualLength); +} + +std::wstring createString(WKURLRef wkURL) +{ + if (!wkURL) + return { }; + WKRetainPtr url = adoptWK(WKURLCopyString(wkURL)); + return createString(url.get()); +} + +std::string createUTF8String(const wchar_t* src, size_t srcLength) +{ + int length = WideCharToMultiByte(CP_UTF8, 0, src, srcLength, 0, 0, nullptr, nullptr); + std::vector buffer(length); + size_t actualLength = WideCharToMultiByte(CP_UTF8, 0, src, srcLength, buffer.data(), length, nullptr, nullptr); + return { buffer.data(), actualLength }; +} + +WKRetainPtr createWKString(_bstr_t str) +{ + auto utf8 = createUTF8String(str, str.length()); + return adoptWK(WKStringCreateWithUTF8CString(utf8.data())); +} + +WKRetainPtr createWKString(const std::wstring& str) +{ + auto utf8 = createUTF8String(str.c_str(), str.length()); + return adoptWK(WKStringCreateWithUTF8CString(utf8.data())); +} + +WKRetainPtr createWKURL(_bstr_t str) +{ + auto utf8 = createUTF8String(str, str.length()); + return adoptWK(WKURLCreateWithUTF8CString(utf8.data())); +} + +WKRetainPtr createWKURL(const std::wstring& str) +{ + auto utf8 = createUTF8String(str.c_str(), str.length()); + return adoptWK(WKURLCreateWithUTF8CString(utf8.data())); +} diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/Common.h b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/Common.h new file mode 100644 index 0000000000000..6d7d2e5c98843 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/Common.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2018 Sony Interactive Entertainment Inc. + * + * 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. + */ + +#pragma once + +#include "stdafx.h" +#include +#include +#include +#include + +struct CommandLineOptions { + bool useFullDesktop { }; + bool inspectorPipe { }; + bool headless { }; + bool noStartupWindow { }; + _bstr_t requestedURL; + _bstr_t userDataDir; + _bstr_t curloptProxy; + _bstr_t curloptNoproxy; + + CommandLineOptions() + { + } +}; + +struct Credential { + std::wstring username; + std::wstring password; +}; + +void computeFullDesktopFrame(); +bool getAppDataFolder(_bstr_t& directory); +CommandLineOptions parseCommandLine(); +void createCrashReport(EXCEPTION_POINTERS*); +Optional askCredential(HWND, const std::wstring& realm); + +bool askServerTrustEvaluation(HWND, const std::wstring& text); +std::wstring replaceString(std::wstring src, const std::wstring& oldValue, const std::wstring& newValue); + +extern HINSTANCE hInst; +extern POINT s_windowPosition; +extern SIZE s_windowSize; + +std::wstring createString(WKStringRef wkString); +std::wstring createString(WKURLRef wkURL); +std::string createUTF8String(const wchar_t* src, size_t srcLength); +WKRetainPtr createWKString(_bstr_t str); +WKRetainPtr createWKString(const std::wstring& str); +WKRetainPtr createWKURL(_bstr_t str); +WKRetainPtr createWKURL(const std::wstring& str); diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/DialogHelper.h b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/DialogHelper.h new file mode 100644 index 0000000000000..6590fe0025584 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/DialogHelper.h @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2018 Sony Interactive Entertainment Inc. + * + * 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. + */ + +#pragma once + +#include "stdafx.h" +#include +#include + +class Dialog { +public: + bool run(HINSTANCE hInst, HWND hwnd, int dialogId) + { + auto result = DialogBoxParam(hInst, MAKEINTRESOURCE(dialogId), hwnd, doalogProc, reinterpret_cast(this)); + return (result > 0); + } + + static INT_PTR CALLBACK doalogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) + { + if (message == WM_INITDIALOG) + SetWindowLongPtr(hDlg, DWLP_USER, lParam); + else + lParam = GetWindowLongPtr(hDlg, DWLP_USER); + + auto* dialog = reinterpret_cast(lParam); + return dialog->handle(hDlg, message, wParam); + } + +protected: + INT_PTR handle(HWND hDlg, UINT message, WPARAM wParam) + { + switch (message) { + case WM_INITDIALOG: { + m_hDlg = hDlg; + setup(); + update(); + return TRUE; + } + case WM_COMMAND: + int wmId = LOWORD(wParam); + switch (wmId) { + case IDOK: + ok(); + close(true); + return TRUE; + case IDCANCEL: + cancel(); + close(false); + return TRUE; + default: + auto handled = command(wmId); + update(); + return handled; + } + } + return FALSE; + } + + virtual void setup() { } + virtual void update() { updateOkButton(validate()); } + virtual bool validate() { return true; } + virtual void updateOkButton(bool isValid) { setEnabled(IDOK, isValid); } + virtual bool command(int wmId) { return false; } + virtual void ok() { } + virtual void cancel() { } + + void close(bool success) { EndDialog(m_hDlg, success); } + + HWND hDlg() { return m_hDlg; } + + HWND item(int itemId) { return GetDlgItem(m_hDlg, itemId); } + + void setEnabled(int itemId, bool enabled) + { + EnableWindow(item(itemId), enabled); + } + + void setText(int itemId, const std::wstring& str) + { + SetDlgItemText(m_hDlg, itemId, _bstr_t(str.c_str())); + } + + std::wstring getText(int itemId) + { + auto length = getTextLength(itemId); + std::vector buffer(length + 1, 0); + GetWindowText(item(itemId), buffer.data(), length + 1); + return std::wstring { buffer.data() }; + } + + int getTextLength(int itemId) + { + return GetWindowTextLength(item(itemId)); + } + + class RadioGroup { + public: + RadioGroup(Dialog& dialog, int first, int last) + : m_dialog(dialog) + , m_first(first) + , m_last(last) + { + } + + void set(int item) + { + CheckRadioButton(m_dialog.hDlg(), m_first, m_last, item); + } + + int get() + { + for (int id = m_first; id <= m_last; id++) { + if (IsDlgButtonChecked(m_dialog.hDlg(), id) == BST_CHECKED) + return id; + } + return 0; + } + + private: + Dialog& m_dialog; + int m_first; + int m_last; + }; + + RadioGroup radioGroup(int first, int last) + { + return RadioGroup(*this, first, last); + } + + HWND m_hDlg { }; +}; diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/MainWindow.cpp b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/MainWindow.cpp new file mode 100644 index 0000000000000..a4c75c62b8a37 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/MainWindow.cpp @@ -0,0 +1,459 @@ +/* + * Copyright (C) 2018 Sony Interactive Entertainment Inc. + * + * 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 "stdafx.h" +#include "Common.h" +#include "MainWindow.h" +#include "PlaywrightLibResource.h" +#include "WebKitBrowserWindow.h" +#include + +namespace WebCore { +float deviceScaleFactorForWindow(HWND); +} + +static const wchar_t* kPlaywrightRegistryKey = L"Software\\WebKit\\Playwright"; + +static constexpr int kToolbarImageSize = 24; +static constexpr int kToolbarURLBarIndex = 3; + +static WNDPROC DefEditProc = nullptr; + +static LRESULT CALLBACK EditProc(HWND, UINT, WPARAM, LPARAM); +static INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); + +std::wstring MainWindow::s_windowClass; +size_t MainWindow::s_numInstances; + +bool MainWindow::s_headless = false; +bool MainWindow::s_noStartupWindow = false; + +void MainWindow::configure(bool headless, bool noStartupWindow) { + s_headless = headless; + s_noStartupWindow = noStartupWindow; +} + +static std::wstring loadString(int id) +{ + constexpr size_t length = 100; + wchar_t buff[length]; + LoadString(hInst, id, buff, length); + return buff; +} + +void MainWindow::registerClass(HINSTANCE hInstance) +{ + static bool initialized = false; + if (initialized) + return; + initialized = true; + + s_windowClass = loadString(IDC_PLAYWRIGHT); + + WNDCLASSEX wcex; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = WndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = hInstance; + wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PLAYWRIGHT)); + wcex.hCursor = LoadCursor(0, IDC_ARROW); + wcex.hbrBackground = 0; + wcex.lpszMenuName = MAKEINTRESOURCE(IDC_PLAYWRIGHT); + wcex.lpszClassName = s_windowClass.c_str(); + wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_PLAYWRIGHT)); + + RegisterClassEx(&wcex); +} + +bool MainWindow::isInstance(HWND hwnd) +{ + wchar_t buff[64]; + if (!GetClassName(hwnd, buff, _countof(buff))) + return false; + return s_windowClass == buff; +} + +MainWindow::MainWindow() +{ + s_numInstances++; +} + +MainWindow::~MainWindow() +{ + s_numInstances--; +} + +void MainWindow::createToolbar(HINSTANCE hInstance) +{ + m_hToolbarWnd = CreateWindowEx(0, TOOLBARCLASSNAME, nullptr, + WS_CHILD | WS_BORDER | TBSTYLE_FLAT | TBSTYLE_LIST | TBSTYLE_TOOLTIPS, 0, 0, 0, 0, + m_hMainWnd, nullptr, hInstance, nullptr); + + if (!m_hToolbarWnd) + return; + + const int ImageListID = 0; + + HIMAGELIST hImageList; + hImageList = ImageList_LoadImage(hInstance, MAKEINTRESOURCE(IDB_TOOLBAR), kToolbarImageSize, 0, CLR_DEFAULT, IMAGE_BITMAP, 0); + + SendMessage(m_hToolbarWnd, TB_SETIMAGELIST, ImageListID, reinterpret_cast(hImageList)); + SendMessage(m_hToolbarWnd, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_MIXEDBUTTONS); + + const DWORD buttonStyles = BTNS_AUTOSIZE; + + TBBUTTON tbButtons[] = { + { MAKELONG(0, ImageListID), IDM_HISTORY_BACKWARD, TBSTATE_ENABLED, buttonStyles, { }, 0, (INT_PTR)L"Back" }, + { MAKELONG(1, ImageListID), IDM_HISTORY_FORWARD, TBSTATE_ENABLED, buttonStyles, { }, 0, (INT_PTR)L"Forward"}, + { MAKELONG(2, ImageListID), IDM_RELOAD, TBSTATE_ENABLED, buttonStyles, { }, 0, (INT_PTR)L"Reload"}, + { 0, 0, TBSTATE_ENABLED, BTNS_SEP, { }, 0, 0}, // URL bar + }; + + SendMessage(m_hToolbarWnd, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0); + SendMessage(m_hToolbarWnd, TB_ADDBUTTONS, _countof(tbButtons), reinterpret_cast(&tbButtons)); + ShowWindow(m_hToolbarWnd, true); + + m_hURLBarWnd = CreateWindow(L"EDIT", 0, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_AUTOVSCROLL, 0, 0, 0, 0, m_hToolbarWnd, 0, hInstance, 0); + + DefEditProc = reinterpret_cast(GetWindowLongPtr(m_hURLBarWnd, GWLP_WNDPROC)); + SetWindowLongPtr(m_hURLBarWnd, GWLP_WNDPROC, reinterpret_cast(EditProc)); +} + +void MainWindow::resizeToolbar(int parentWidth) +{ + TBBUTTONINFO info { sizeof(TBBUTTONINFO), TBIF_BYINDEX | TBIF_SIZE }; + info.cx = parentWidth - m_toolbarItemsWidth; + SendMessage(m_hToolbarWnd, TB_SETBUTTONINFO, kToolbarURLBarIndex, reinterpret_cast(&info)); + SendMessage(m_hToolbarWnd, TB_AUTOSIZE, 0, 0); + + RECT rect; + SendMessage(m_hToolbarWnd, TB_GETITEMRECT, kToolbarURLBarIndex, reinterpret_cast(&rect)); + MoveWindow(m_hURLBarWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, true); +} + +void MainWindow::rescaleToolbar() +{ + const float scaleFactor = WebCore::deviceScaleFactorForWindow(m_hMainWnd); + const int scaledImageSize = kToolbarImageSize * scaleFactor; + + TBBUTTONINFO info { sizeof(TBBUTTONINFO), TBIF_BYINDEX | TBIF_SIZE }; + + info.cx = 0; + SendMessage(m_hToolbarWnd, TB_SETBUTTONINFO, kToolbarURLBarIndex, reinterpret_cast(&info)); + SendMessage(m_hToolbarWnd, TB_AUTOSIZE, 0, 0); + + int numItems = SendMessage(m_hToolbarWnd, TB_BUTTONCOUNT, 0, 0); + + RECT rect; + SendMessage(m_hToolbarWnd, TB_GETITEMRECT, numItems-1, reinterpret_cast(&rect)); + m_toolbarItemsWidth = rect.right; +} + +bool MainWindow::init(HINSTANCE hInstance, WKPageConfigurationRef conf) +{ + auto prefs = adoptWK(WKPreferencesCreate()); + + WKPageConfigurationSetPreferences(conf, prefs.get()); + WKPreferencesSetMediaCapabilitiesEnabled(prefs.get(), false); + WKPreferencesSetDeveloperExtrasEnabled(prefs.get(), true); + + m_configuration = conf; + + registerClass(hInstance); + + auto title = loadString(IDS_APP_TITLE); + + m_hMainWnd = CreateWindowExW(s_headless ? WS_EX_NOACTIVATE : 0, s_windowClass.c_str(), title.c_str(), + WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0, 0, hInstance, this); + + if (!m_hMainWnd) + return false; + + if (!s_headless) { + createToolbar(hInstance); + if (!m_hToolbarWnd) + return false; + } + + m_browserWindow.reset(new WebKitBrowserWindow(*this, m_hMainWnd, conf)); + + updateDeviceScaleFactor(); + resizeSubViews(); + + if (s_headless) { + SetMenu(m_hMainWnd, NULL); + } else { + SetFocus(m_hURLBarWnd); + ShowWindow(m_hMainWnd, SW_SHOW); + } + return true; +} + +void MainWindow::resizeSubViews() +{ + RECT rcClient; + GetClientRect(m_hMainWnd, &rcClient); + if (s_headless) { + MoveWindow(m_browserWindow->hwnd(), 0, 0, rcClient.right, rcClient.bottom, true); + return; + } + + resizeToolbar(rcClient.right); + + RECT rect; + GetWindowRect(m_hToolbarWnd, &rect); + POINT toolbarBottom = { 0, rect.bottom }; + ScreenToClient(m_hMainWnd, &toolbarBottom); + auto height = toolbarBottom.y; + MoveWindow(m_browserWindow->hwnd(), 0, height, rcClient.right, rcClient.bottom - height, true); +} + +LRESULT CALLBACK MainWindow::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + LRESULT result = 0; + MainWindow* thisWindow = reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); + if (!thisWindow && message != WM_CREATE) + return DefWindowProc(hWnd, message, wParam, lParam); + + switch (message) { + case WM_ACTIVATE: + switch (LOWORD(wParam)) { + case WA_ACTIVE: + case WA_CLICKACTIVE: + SetFocus(thisWindow->browserWindow()->hwnd()); + } + break; + case WM_CREATE: + SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast(reinterpret_cast(lParam)->lpCreateParams)); + break; + case WM_APPCOMMAND: { + auto cmd = GET_APPCOMMAND_LPARAM(lParam); + switch (cmd) { + case APPCOMMAND_BROWSER_BACKWARD: + thisWindow->browserWindow()->navigateForwardOrBackward(false); + result = 1; + break; + case APPCOMMAND_BROWSER_FORWARD: + thisWindow->browserWindow()->navigateForwardOrBackward(true); + result = 1; + break; + case APPCOMMAND_BROWSER_REFRESH: + thisWindow->browserWindow()->reload(); + result = 1; + break; + case APPCOMMAND_BROWSER_STOP: + break; + } + break; + } + case WM_COMMAND: { + int wmId = LOWORD(wParam); + int wmEvent = HIWORD(wParam); + switch (wmEvent) { + case 0: // Menu or BN_CLICKED + case 1: // Accelerator + break; + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + // Parse the menu selections: + switch (wmId) { + case IDC_URL_BAR: + thisWindow->onURLBarEnter(); + break; + case IDM_NEW_WINDOW: { + auto* newWindow = new MainWindow(); + newWindow->init(hInst, thisWindow->m_configuration.get()); + break; + } + case IDM_CLOSE_WINDOW: + PostMessage(hWnd, WM_CLOSE, 0, 0); + break; + case IDM_ABOUT: + DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); + break; + case IDM_WEB_INSPECTOR: + thisWindow->browserWindow()->launchInspector(); + break; + case IDM_HISTORY_BACKWARD: + case IDM_HISTORY_FORWARD: + thisWindow->browserWindow()->navigateForwardOrBackward(wmId == IDM_HISTORY_FORWARD); + break; + case IDM_ACTUAL_SIZE: + thisWindow->browserWindow()->resetZoom(); + break; + case IDM_RELOAD: + thisWindow->browserWindow()->reload(); + break; + case IDM_ZOOM_IN: + thisWindow->browserWindow()->zoomIn(); + break; + case IDM_ZOOM_OUT: + thisWindow->browserWindow()->zoomOut(); + break; + default: + if (!thisWindow->toggleMenuItem(wmId)) + return DefWindowProc(hWnd, message, wParam, lParam); + } + } + break; + case WM_NCDESTROY: + SetWindowLongPtr(hWnd, GWLP_USERDATA, 0); + delete thisWindow; + if (s_noStartupWindow || s_numInstances > 0) + return 0; + PostQuitMessage(0); + break; + case WM_SIZE: + thisWindow->resizeSubViews(); + break; + case WM_DPICHANGED: { + thisWindow->updateDeviceScaleFactor(); + auto& rect = *reinterpret_cast(lParam); + SetWindowPos(hWnd, nullptr, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOACTIVATE); + break; + } + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + + return result; +} + +static bool menuItemIsChecked(const MENUITEMINFO& info) +{ + return info.fState & MFS_CHECKED; +} + +bool MainWindow::toggleMenuItem(UINT menuID) +{ + if (s_headless) + return (INT_PTR)FALSE; + + HMENU menu = ::GetMenu(hwnd()); + + MENUITEMINFO info = { }; + info.cbSize = sizeof(info); + info.fMask = MIIM_STATE; + + if (!::GetMenuItemInfo(menu, menuID, FALSE, &info)) + return false; + + BOOL newState = !menuItemIsChecked(info); + info.fState = (newState) ? MFS_CHECKED : MFS_UNCHECKED; + ::SetMenuItemInfo(menu, menuID, FALSE, &info); + + return true; +} + +LRESULT CALLBACK EditProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) { + case WM_SETFOCUS: + PostMessage(hWnd, EM_SETSEL, 0, -1); + break; + case WM_CHAR: + if (wParam == 13) { + // Enter Key + ::PostMessage(GetParent(hWnd), static_cast(WM_COMMAND), MAKELPARAM(IDC_URL_BAR, 0), 0); + return 0; + } + break; + } + return CallWindowProc(DefEditProc, hWnd, message, wParam, lParam); +} + +// Message handler for about box. +INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + UNREFERENCED_PARAMETER(lParam); + switch (message) { + case WM_INITDIALOG: + return (INT_PTR)TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, LOWORD(wParam)); + return (INT_PTR)TRUE; + } + break; + } + return (INT_PTR)FALSE; +} + +void MainWindow::loadURL(std::wstring url) +{ + if (::PathFileExists(url.c_str()) || ::PathIsUNC(url.c_str())) { + wchar_t fileURL[INTERNET_MAX_URL_LENGTH]; + DWORD fileURLLength = _countof(fileURL); + + if (SUCCEEDED(::UrlCreateFromPath(url.c_str(), fileURL, &fileURLLength, 0))) + url = fileURL; + } + if (url.find(L"://") == url.npos && url.find(L"about:blank") == url.npos) + url = L"http://" + url; + + if (FAILED(m_browserWindow->loadURL(_bstr_t(url.c_str())))) + return; + + if (!s_headless) + SetFocus(m_browserWindow->hwnd()); +} + +void MainWindow::onURLBarEnter() +{ + if (s_headless) + return; + wchar_t url[INTERNET_MAX_URL_LENGTH]; + GetWindowText(m_hURLBarWnd, url, INTERNET_MAX_URL_LENGTH); + loadURL(url); +} + +void MainWindow::updateDeviceScaleFactor() +{ + if (s_headless) + return; + if (m_hURLBarFont) + ::DeleteObject(m_hURLBarFont); + + rescaleToolbar(); + + RECT rect; + GetClientRect(m_hToolbarWnd, &rect); + int fontHeight = 20; + + m_hURLBarFont = ::CreateFont(fontHeight, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, + OUT_TT_ONLY_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, FF_DONTCARE, L"Tahoma"); + ::SendMessage(m_hURLBarWnd, static_cast(WM_SETFONT), reinterpret_cast(m_hURLBarFont), TRUE); +} + +void MainWindow::activeURLChanged(std::wstring url) +{ + if (s_headless) + return; + SetWindowText(m_hURLBarWnd, url.c_str()); +} diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/MainWindow.h b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/MainWindow.h new file mode 100644 index 0000000000000..95730f46be5c9 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/MainWindow.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2018 Sony Interactive Entertainment Inc. + * + * 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. + */ + +#pragma once + +#include "WebKitBrowserWindow.h" + +#include +#include +#include +#include +#include + +class MainWindow : public BrowserWindowClient { +public: + static void configure(bool headless, bool noStartupWindow); + + MainWindow(); + + ~MainWindow(); + bool init(HINSTANCE hInstance, WKPageConfigurationRef); + + void resizeSubViews(); + HWND hwnd() const { return m_hMainWnd; } + WebKitBrowserWindow* browserWindow() const { return m_browserWindow.get(); } + + void loadURL(std::wstring); + + static bool isInstance(HWND); + +private: + static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); + static void registerClass(HINSTANCE hInstance); + static std::wstring s_windowClass; + static size_t s_numInstances; + static bool s_headless; + static bool s_noStartupWindow; + + bool toggleMenuItem(UINT menuID); + void onURLBarEnter(); + void updateDeviceScaleFactor(); + + void createToolbar(HINSTANCE); + void resizeToolbar(int); + void rescaleToolbar(); + + // BrowserWindowClient + void activeURLChanged(std::wstring) final; + + HWND m_hMainWnd { nullptr }; + HWND m_hToolbarWnd { nullptr }; + HWND m_hURLBarWnd { nullptr }; + HWND m_hProgressIndicator { nullptr }; + HWND m_hCacheWnd { nullptr }; + HGDIOBJ m_hURLBarFont { nullptr }; + // WKPageConfigurationRef retains page and WebKitBrowserWindow retains page via view + // make sure view is deleted after the page. + std::unique_ptr m_browserWindow; + WKRetainPtr m_configuration; + int m_toolbarItemsWidth { }; +}; diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/Playwright.ico b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/Playwright.ico new file mode 100644 index 0000000000000..0137fe83a54dd Binary files /dev/null and b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/Playwright.ico differ diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/Playwright.rc b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/Playwright.rc new file mode 100644 index 0000000000000..4430f19062cc9 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/Playwright.rc @@ -0,0 +1,76 @@ +// Microsoft Visual C++ generated resource script. +// +#include "PlaywrightResource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_PLAYWRIGHT ICON "Playwright.ico" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "PlaywrightResource.\0" +END + +2 TEXTINCLUDE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/PlaywrightLib.rc b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/PlaywrightLib.rc new file mode 100644 index 0000000000000..83039d330fa60 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/PlaywrightLib.rc @@ -0,0 +1,354 @@ +// Microsoft Visual C++ generated resource script. +// +#include "PlaywrightLibResource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_PLAYWRIGHT ICON "Playwright.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDC_PLAYWRIGHT MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "New Window\tCtrl-N" IDM_NEW_WINDOW + MENUITEM "Close\tCtrl-W", IDM_CLOSE_WINDOW + END + POPUP "&View" + BEGIN + MENUITEM "Actual Size\tCtrl+0", IDM_ACTUAL_SIZE + MENUITEM "Zoom In\tCtrl++", IDM_ZOOM_IN + MENUITEM "Zoom Out\tCtrl+-", IDM_ZOOM_OUT + MENUITEM "Invert Colors", IDM_INVERT_COLORS + END + POPUP "&History" + BEGIN + MENUITEM "Reload\tCtrl-R", IDM_RELOAD + MENUITEM "Back", IDM_HISTORY_BACKWARD + MENUITEM "Forward", IDM_HISTORY_FORWARD + END + POPUP "D&evelop" + BEGIN + MENUITEM "Show Web Inspector", IDM_WEB_INSPECTOR + END + POPUP "&Help" + BEGIN + MENUITEM "&About ...", IDM_ABOUT + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDC_PLAYWRIGHT ACCELERATORS +BEGIN + "/", IDM_ABOUT, ASCII, ALT, NOINVERT + "0", IDM_ACTUAL_SIZE, VIRTKEY, CONTROL, NOINVERT + "?", IDM_ABOUT, ASCII, ALT, NOINVERT + "R", IDM_RELOAD, VIRTKEY, CONTROL, NOINVERT + "N", IDM_NEW_WINDOW, VIRTKEY, CONTROL, NOINVERT + VK_ADD, IDM_ZOOM_IN, VIRTKEY, CONTROL, NOINVERT + VK_OEM_MINUS, IDM_ZOOM_OUT, VIRTKEY, CONTROL, NOINVERT + VK_OEM_PLUS, IDM_ZOOM_IN, VIRTKEY, CONTROL, NOINVERT + VK_SUBTRACT, IDM_ZOOM_OUT, VIRTKEY, CONTROL, NOINVERT +END + +IDR_ACCELERATORS_PRE ACCELERATORS +BEGIN + "W", IDM_CLOSE_WINDOW, VIRTKEY, CONTROL, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOGEX 22, 17, 230, 41 +STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "About" +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + ICON IDI_PLAYWRIGHT,IDC_MYICON,14,9,20,20 + LTEXT "Playwright Version 1.1",IDC_STATIC,49,10,119,8 + LTEXT "Copyright (C) 2015-2019",IDC_STATIC,49,20,119,8 + DEFPUSHBUTTON "OK",IDOK,186,10,30,11,WS_GROUP +END + +IDD_CACHES DIALOGEX 0, 0, 401, 456 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,287,435,50,14 + PUSHBUTTON "Cancel",IDCANCEL,344,435,50,14 + GROUPBOX "FastMalloc",IDC_STATIC,208,14,186,67 + GROUPBOX "WebCore Cache",IDC_STATIC,17,83,376,105 + GROUPBOX "JavaScript Heap",IDC_STATIC,18,193,376,168 + GROUPBOX "Site Icon Database",IDC_STATIC,18,366,142,65 + GROUPBOX "Font and Glyph Caches",IDC_STATIC,168,366,226,66 + GROUPBOX "CFURLCache",IDC_STATIC,7,14,197,67 + PUSHBUTTON "Empty URLCache",IDC_EMPTY_URL_CACHE,131,63,69,14,WS_DISABLED + PUSHBUTTON "Return Free Memory",IDC_RETURN_FREE_MEMORY,308,63,76,14,WS_DISABLED + PUSHBUTTON "Empty WebCore Cache",IDC_EMPTY_WEBCORE_CACHE,21,170,83,14,WS_DISABLED + CONTROL "Disable WebCore Cache",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,119,172,93,10 + PUSHBUTTON "Garbage Collect JavaScript Objects",IDC_GC_JSC,253,343,135,14,WS_DISABLED + RTEXT "Reserved VM",IDC_STATIC,212,26,67,9 + RTEXT "0",IDC_RESERVED_VM,290,26,94,8 + RTEXT "Committed VM",IDC_STATIC,211,39,67,8 + RTEXT "0",IDC_COMMITTED_VM,290,39,94,8 + RTEXT "Free List Bytes",IDC_STATIC,211,52,67,8 + RTEXT "0",IDC_FREE_LIST_BYTES,290,52,94,8 + RTEXT "Images",IDC_STATIC,37,106,24,8 + RTEXT "CSS",IDC_STATIC,47,116,14,8 + RTEXT "XSL",IDC_STATIC,49,126,12,8 + RTEXT "JavaScript",IDC_STATIC,27,135,34,8 + RTEXT "Total",IDC_STATIC,43,146,17,8 + LTEXT "Objects",IDC_STATIC,111,96,26,8 + LTEXT "Bytes",IDC_STATIC,175,96,19,8 + LTEXT "Live",IDC_STATIC,232,96,14,8 + LTEXT "Decoded",IDC_STATIC,284,96,29,8 + LTEXT "Purgeable",IDC_STATIC,351,96,33,8 + RTEXT "0",IDC_IMAGES_OBJECT_COUNT,100,106,32,8 + RTEXT "0",IDC_CSS_OBJECT_COUNT,100,116,32,8 + RTEXT "0",IDC_XSL_OBJECT_COUNT,100,126,32,8 + RTEXT "0",IDC_JSC_OBJECT_COUNT,100,135,32,8 + RTEXT "0",IDC_TOTAL_OBJECT_COUNT,100,146,32,8 + RTEXT "0",IDC_IMAGES_BYTES,162,106,32,8 + RTEXT "0",IDC_CSS_BYTES,162,116,32,8 + RTEXT "0",IDC_XSL_BYTES,162,126,32,8 + RTEXT "0",IDC_JSC_BYTES,162,135,32,8 + RTEXT "0",IDC_TOTAL_BYTES,162,146,32,8 + RTEXT "0",IDC_IMAGES_LIVE_COUNT,221,106,32,8 + RTEXT "0",IDC_CSS_LIVE_COUNT,221,116,32,8 + RTEXT "0",IDC_XSL_LIVE_COUNT,221,126,32,8 + RTEXT "0",IDC_JSC_LIVE_COUNT,221,135,32,8 + RTEXT "0",IDC_TOTAL_LIVE_COUNT,221,146,32,8 + RTEXT "0",IDC_IMAGES_DECODED_COUNT,284,106,32,8 + RTEXT "0",IDC_CSS_DECODED_COUNT,284,116,32,8 + RTEXT "0",IDC_XSL_DECODED_COUNT,284,126,32,8 + RTEXT "0",IDC_JSC_DECODED_COUNT,284,135,32,8 + RTEXT "0",IDC_TOTAL_DECODED,284,146,32,8 + RTEXT "0",IDC_IMAGES_PURGEABLE_COUNT,354,106,32,8 + RTEXT "0",IDC_CSS_PURGEABLE_COUNT,354,116,32,8 + RTEXT "0",IDC_XSL_PURGEABLE_COUNT,354,126,32,8 + RTEXT "0",IDC_JSC_PURGEABLE_COUNT,354,135,32,8 + RTEXT "0",IDC_TOTAL_PURGEABLE,354,146,32,8 + RTEXT "Total Objects",IDC_STATIC,63,207,44,8 + RTEXT "Global Objects",IDC_STATIC,56,217,51,8 + RTEXT "Protected Objects",IDC_STATIC,48,227,59,8 + RTEXT "0",IDC_TOTAL_JSC_HEAP_OBJECTS,127,207,56,8 + RTEXT "0",IDC_GLOBAL_JSC_HEAP_OBJECTS,127,217,56,8 + RTEXT "0",IDC_PROTECTED_JSC_HEAP_OBJECTS,127,227,56,8 + RTEXT "Size",IDC_STATIC56,223,207,14,8 + RTEXT "Free",IDC_STATIC57,222,217,16,8 + RTEXT "0",IDC_JSC_HEAP_SIZE,270,207,56,8 + RTEXT "0",IDC_JSC_HEAP_FREE,270,217,56,8 + PUSHBUTTON "Purge Inactive Font Data",IDC_BUTTON5,293,415,95,14,WS_DISABLED + LTEXT "Total Font Data Objects",IDC_STATIC,208,379,78,8 + LTEXT "Inactive Font Data Objects",IDC_STATIC,198,390,88,8 + LTEXT "Glyph Pages",IDC_STATIC,246,402,40,8 + RTEXT "0",IDC_TOTAL_FONT_OBJECTS,329,379,56,8 + RTEXT "0",IDC_INACTIVE_FONT_OBJECTS,329,390,56,8 + RTEXT "0",IDC_GLYPH_PAGES,329,402,56,8 + LTEXT "Page URL Mappings",IDC_STATIC,33,380,64,8 + LTEXT "Retained Page URLs",IDC_STATIC,31,390,66,8 + LTEXT "Site Icon Records",IDC_STATIC,40,400,57,8 + LTEXT "Site Icons with Data",IDC_STATIC,32,410,65,8 + RTEXT "0",IDC_PAGE_URL_MAPPINGS,101,380,52,8 + RTEXT "0",IDC_RETAINED_PAGE_URLS,101,390,52,8 + RTEXT "0",IDC_SITE_ICON_RECORDS,101,400,52,8 + RTEXT "0",IDC_SITE_ICONS_WITH_DATA,101,410,52,8 +END + +IDD_AUTH DIALOGEX 0, 0, 231, 119 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Authentication Required" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "Sign In",IDOK,116,98,50,14 + PUSHBUTTON "Cancel",IDCANCEL,174,98,50,14 + LTEXT "Realm",IDC_REALM_TEXT,67,21,157,8 + RTEXT "User Name:",IDC_STATIC,7,41,57,8 + EDITTEXT IDC_AUTH_USER,67,39,157,14,ES_AUTOHSCROLL + RTEXT "Password:",IDC_STATIC,7,66,57,8 + EDITTEXT IDC_AUTH_PASSWORD,67,64,157,14,ES_PASSWORD | ES_AUTOHSCROLL +END + +IDD_PROXY DIALOGEX 0, 0, 310, 176 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Proxy Configuration" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,199,155,50,14 + PUSHBUTTON "Cancel",IDCANCEL,253,155,50,14 + CONTROL "Use system default proxy configuration.",IDC_PROXY_DEFAULT, + "Button",BS_AUTORADIOBUTTON | WS_GROUP,22,15,226,10 + CONTROL "Use custom proxy configuration:",IDC_PROXY_CUSTOM, + "Button",BS_AUTORADIOBUTTON,22,33,226,10 + CONTROL "Don't use proxy.",IDC_PROXY_DISABLE,"Button",BS_AUTORADIOBUTTON,22,117,226,10 + EDITTEXT IDC_PROXY_URL,76,52,193,14,ES_AUTOHSCROLL + EDITTEXT IDC_PROXY_EXCLUDE,76,85,193,14,ES_AUTOHSCROLL + LTEXT "URL:",IDC_STATIC,30,55,43,8,0,WS_EX_RIGHT + LTEXT "Excude list:",IDC_STATIC,30,88,43,8,0,WS_EX_RIGHT + LTEXT "Example: http://192.168.0.2:8000",IDC_STATIC,80,68,194,8 + LTEXT "Comma separated hostnames.",IDC_STATIC,80,101,194,8 +END + +IDD_SERVER_TRUST DIALOGEX 0, 0, 319, 184 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Server Trust Evaluation Request" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "Yes",IDOK,197,163,50,14 + PUSHBUTTON "No",IDCANCEL,262,163,50,14 + LTEXT "Certificate information",IDC_STATIC,7,7,294,17 + EDITTEXT IDC_SERVER_TRUST_TEXT,7,24,305,130,ES_MULTILINE | ES_READONLY | WS_VSCROLL | WS_HSCROLL | NOT WS_TABSTOP +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "PlaywrightLibResource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_ABOUTBOX, DIALOG + BEGIN + END + + IDD_CACHES, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 394 + TOPMARGIN, 7 + BOTTOMMARGIN, 449 + END + + IDD_AUTH, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 224 + VERTGUIDE, 64 + VERTGUIDE, 67 + TOPMARGIN, 7 + BOTTOMMARGIN, 92 + HORZGUIDE, 25 + HORZGUIDE, 50 + END + + IDD_PROXY, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 303 + VERTGUIDE, 22 + TOPMARGIN, 7 + BOTTOMMARGIN, 169 + END + + IDD_SERVER_TRUST, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 312 + TOPMARGIN, 7 + BOTTOMMARGIN, 177 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_TOOLBAR BITMAP "toolbar.bmp" + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_APP_TITLE "Playwright" + IDC_PLAYWRIGHT "Playwright" +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/PlaywrightLibResource.h b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/PlaywrightLibResource.h new file mode 100644 index 0000000000000..360c0a9cec399 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/PlaywrightLibResource.h @@ -0,0 +1,115 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by PlaywrightLib.rc +// +#define IDC_MYICON 2 +#define IDD_PLAYWRIGHT_DIALOG 102 +#define IDS_APP_TITLE 103 +#define IDD_ABOUTBOX 103 +#define IDM_ABOUT 104 +#define IDI_PLAYWRIGHT 107 +#define IDC_PLAYWRIGHT 109 +#define IDM_WEB_INSPECTOR 120 +#define IDM_INVERT_COLORS 125 +#define IDR_MAINFRAME 128 +#define IDD_CACHES 129 +#define IDM_HISTORY_BACKWARD 130 +#define IDD_USER_AGENT 130 +#define IDM_HISTORY_FORWARD 131 +#define IDM_HISTORY_LINK0 150 +#define IDM_HISTORY_LINK1 151 +#define IDM_HISTORY_LINK2 152 +#define IDM_HISTORY_LINK3 153 +#define IDM_HISTORY_LINK4 154 +#define IDM_HISTORY_LINK5 155 +#define IDM_HISTORY_LINK6 156 +#define IDM_HISTORY_LINK7 157 +#define IDM_HISTORY_LINK8 158 +#define IDM_HISTORY_LINK9 159 +#define IDT_UPDATE_STATS 160 +#define IDM_ACTUAL_SIZE 172 +#define IDM_ZOOM_IN 173 +#define IDM_ZOOM_OUT 174 +#define IDD_AUTH 176 +#define IDD_PROXY 178 +#define IDD_SERVER_TRUST 179 +#define IDR_ACCELERATORS_PRE 180 +#define IDB_TOOLBAR 181 +#define IDC_EMPTY_URL_CACHE 1000 +#define IDC_RETURN_FREE_MEMORY 1001 +#define IDC_EMPTY_WEBCORE_CACHE 1002 +#define IDC_CHECK1 1003 +#define IDC_HEAP_OBJECTS 1005 +#define IDC_GC_JSC 1006 +#define IDC_RESERVED_VM 1007 +#define IDC_COMMITTED_VM 1008 +#define IDC_FREE_LIST_BYTES 1009 +#define IDC_IMAGES_OBJECT_COUNT 1011 +#define IDC_CSS_OBJECT_COUNT 1012 +#define IDC_XSL_OBJECT_COUNT 1013 +#define IDC_JSC_OBJECT_COUNT 1014 +#define IDC_TOTAL_OBJECT_COUNT 1015 +#define IDC_IMAGES_BYTES 1016 +#define IDC_CSS_BYTES 1017 +#define IDC_XSL_BYTES 1018 +#define IDC_JSC_BYTES 1019 +#define IDC_TOTAL_BYTES 1020 +#define IDC_IMAGES_LIVE_COUNT 1021 +#define IDC_CSS_LIVE_COUNT 1022 +#define IDC_XSL_LIVE_COUNT 1023 +#define IDC_JSC_LIVE_COUNT 1024 +#define IDC_TOTAL_LIVE_COUNT 1025 +#define IDC_IMAGES_DECODED_COUNT 1026 +#define IDC_CSS_DECODED_COUNT 1027 +#define IDC_XSL_DECODED_COUNT 1028 +#define IDC_JSC_DECODED_COUNT 1029 +#define IDC_TOTAL_DECODED 1030 +#define IDC_IMAGES_PURGEABLE_COUNT 1031 +#define IDC_CSS_PURGEABLE_COUNT 1032 +#define IDC_XSL_PURGEABLE_COUNT 1033 +#define IDC_JSC_PURGEABLE_COUNT 1034 +#define IDC_TOTAL_PURGEABLE 1035 +#define IDC_TOTAL_JSC_HEAP_OBJECTS 1036 +#define IDC_GLOBAL_JSC_HEAP_OBJECTS 1037 +#define IDC_PROTECTED_JSC_HEAP_OBJECTS 1038 +#define IDC_STATIC56 1039 +#define IDC_STATIC57 1040 +#define IDC_JSC_HEAP_SIZE 1041 +#define IDC_JSC_HEAP_FREE 1042 +#define IDC_BUTTON5 1043 +#define IDC_TOTAL_FONT_OBJECTS 1044 +#define IDC_Message 1044 +#define IDC_INACTIVE_FONT_OBJECTS 1045 +#define IDC_GLYPH_PAGES 1046 +#define IDC_PAGE_URL_MAPPINGS 1047 +#define IDC_RETAINED_PAGE_URLS 1048 +#define IDC_SITE_ICON_RECORDS 1049 +#define IDC_TOTAL_FONT_OBJECTS5 1050 +#define IDC_SITE_ICONS_WITH_DATA 1051 +#define IDC_USER_AGENT_INPUT 1052 +#define IDC_AUTH_USER 1053 +#define IDC_AUTH_PASSWORD 1054 +#define IDC_URL_BAR 1055 +#define IDC_REALM_TEXT 1056 +#define IDC_PROXY_URL 1057 +#define IDC_PROXY_DEFAULT 1058 +#define IDC_PROXY_CUSTOM 1059 +#define IDC_PROXY_EXCLUDE 1060 +#define IDC_PROXY_DISABLE 1061 +#define IDC_SERVER_TRUST_TEXT 1062 +#define IDM_NEW_WINDOW 32776 +#define IDM_RELOAD 32779 +#define IDM_CLOSE_WINDOW 32780 +#define IDC_STATIC -1 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 182 +#define _APS_NEXT_COMMAND_VALUE 32783 +#define _APS_NEXT_CONTROL_VALUE 1063 +#define _APS_NEXT_SYMED_VALUE 110 +#endif +#endif diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/PlaywrightReplace.h b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/PlaywrightReplace.h new file mode 100644 index 0000000000000..dd134b879ea6a --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/PlaywrightReplace.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2013 Alex Christensen. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +// This file is to make it easier for users to manage changes to the internals of Playwright + +static void processCrashReport(const wchar_t* fileName) { ::MessageBox(0, fileName, L"Crash Report", MB_OK); } diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/PlaywrightResource.h b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/PlaywrightResource.h new file mode 100644 index 0000000000000..c60d7b73f18d0 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/PlaywrightResource.h @@ -0,0 +1,20 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by PlaywrightLauncher.rc +// +#define IDD_PLAYWRIGHT_DIALOG 102 +#define IDI_PLAYWRIGHT 107 +#define IDR_MAINFRAME 128 +#define IDC_STATIC -1 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 110 +#endif +#endif diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/WebKitBrowserWindow.cpp b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/WebKitBrowserWindow.cpp new file mode 100644 index 0000000000000..23d99e5b1385c --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/WebKitBrowserWindow.cpp @@ -0,0 +1,393 @@ +/* + * Copyright (C) 2018 Sony Interactive Entertainment Inc. + * + * 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 "stdafx.h" +#include "Common.h" +#include "MainWindow.h" +#include "PlaywrightLibResource.h" +#include "WebKitBrowserWindow.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +std::wstring createPEMString(WKCertificateInfoRef certificateInfo) +{ + auto chainSize = WKCertificateInfoGetCertificateChainSize(certificateInfo); + + std::wstring pems; + + for (auto i = 0; i < chainSize; i++) { + auto certificate = adoptWK(WKCertificateInfoCopyCertificateAtIndex(certificateInfo, i)); + auto size = WKDataGetSize(certificate.get()); + auto data = WKDataGetBytes(certificate.get()); + + for (size_t i = 0; i < size; i++) + pems.push_back(data[i]); + } + + return replaceString(pems, L"\n", L"\r\n"); +} + +WebKitBrowserWindow::WebKitBrowserWindow(BrowserWindowClient& client, HWND mainWnd, WKPageConfigurationRef conf) + : m_client(client) + , m_hMainWnd(mainWnd) +{ + RECT rect = { }; + m_view = adoptWK(WKViewCreate(rect, conf, mainWnd)); + WKViewSetIsInWindow(m_view.get(), true); + + auto page = WKViewGetPage(m_view.get()); + + WKPageNavigationClientV0 navigationClient = { }; + navigationClient.base.version = 0; + navigationClient.base.clientInfo = this; + navigationClient.didReceiveAuthenticationChallenge = didReceiveAuthenticationChallenge; + WKPageSetPageNavigationClient(page, &navigationClient.base); + + WKPageUIClientV14 uiClient = { }; + uiClient.base.version = 14; + uiClient.base.clientInfo = this; + uiClient.createNewPage = createNewPage; + uiClient.didNotHandleKeyEvent = didNotHandleKeyEvent; + uiClient.close = closeWindow; + uiClient.runJavaScriptAlert = runJavaScriptAlert; + uiClient.runJavaScriptConfirm = runJavaScriptConfirm; + uiClient.runJavaScriptPrompt = runJavaScriptPrompt; + uiClient.runBeforeUnloadConfirmPanel = runBeforeUnloadConfirmPanel; + uiClient.handleJavaScriptDialog = handleJavaScriptDialog; + uiClient.getWindowFrame = getWindowFrame; + WKPageSetPageUIClient(page, &uiClient.base); + + WKPageStateClientV0 stateClient = { }; + stateClient.base.version = 0; + stateClient.base.clientInfo = this; + stateClient.didChangeTitle = didChangeTitle; + stateClient.didChangeIsLoading = didChangeIsLoading; + stateClient.didChangeActiveURL = didChangeActiveURL; + WKPageSetPageStateClient(page, &stateClient.base); + + WKPagePolicyClientV1 policyClient = { }; + policyClient.base.version = 1; + policyClient.base.clientInfo = this; + policyClient.decidePolicyForResponse_deprecatedForUseWithV0 = decidePolicyForResponse; + WKPageSetPagePolicyClient(page, &policyClient.base); + resetZoom(); +} + +WebKitBrowserWindow::~WebKitBrowserWindow() +{ + if (m_alertDialog) { + WKRelease(m_alertDialog); + m_alertDialog = NULL; + } + + if (m_confirmDialog) { + WKRelease(m_confirmDialog); + m_confirmDialog = NULL; + } + + if (m_promptDialog) { + WKRelease(m_promptDialog); + m_promptDialog = NULL; + } + + if (m_beforeUnloadDialog) { + WKRelease(m_beforeUnloadDialog); + m_beforeUnloadDialog = NULL; + } +} + +HWND WebKitBrowserWindow::hwnd() +{ + return WKViewGetWindow(m_view.get()); +} + +HRESULT WebKitBrowserWindow::loadURL(const BSTR& url) +{ + auto page = WKViewGetPage(m_view.get()); + WKPageLoadURL(page, createWKURL(_bstr_t(url)).get()); + return true; +} + +void WebKitBrowserWindow::reload() +{ + auto page = WKViewGetPage(m_view.get()); + WKPageReload(page); +} + +void WebKitBrowserWindow::navigateForwardOrBackward(bool forward) +{ + auto page = WKViewGetPage(m_view.get()); + if (forward) + WKPageGoForward(page); + else + WKPageGoBack(page); +} + +void WebKitBrowserWindow::launchInspector() +{ + auto page = WKViewGetPage(m_view.get()); + auto inspector = WKPageGetInspector(page); + WKInspectorShow(inspector); +} + +void WebKitBrowserWindow::setUserAgent(_bstr_t& customUAString) +{ + auto page = WKViewGetPage(m_view.get()); + auto ua = createWKString(customUAString); + WKPageSetCustomUserAgent(page, ua.get()); +} + +_bstr_t WebKitBrowserWindow::userAgent() +{ + auto page = WKViewGetPage(m_view.get()); + auto ua = adoptWK(WKPageCopyUserAgent(page)); + return createString(ua.get()).c_str(); +} + +void WebKitBrowserWindow::resetZoom() +{ + auto page = WKViewGetPage(m_view.get()); + WKPageSetPageZoomFactor(page, WebCore::deviceScaleFactorForWindow(hwnd())); +} + +void WebKitBrowserWindow::zoomIn() +{ + auto page = WKViewGetPage(m_view.get()); + double s = WKPageGetPageZoomFactor(page); + WKPageSetPageZoomFactor(page, s * 1.25); +} + +void WebKitBrowserWindow::zoomOut() +{ + auto page = WKViewGetPage(m_view.get()); + double s = WKPageGetPageZoomFactor(page); + WKPageSetPageZoomFactor(page, s * 0.8); +} + +static WebKitBrowserWindow& toWebKitBrowserWindow(const void *clientInfo) +{ + return *const_cast(static_cast(clientInfo)); +} + +void WebKitBrowserWindow::didChangeTitle(const void* clientInfo) +{ + auto& thisWindow = toWebKitBrowserWindow(clientInfo); + auto page = WKViewGetPage(thisWindow.m_view.get()); + WKRetainPtr title = adoptWK(WKPageCopyTitle(page)); + std::wstring titleString = createString(title.get()) + L" [WebKit]"; + SetWindowText(thisWindow.m_hMainWnd, titleString.c_str()); +} + +void WebKitBrowserWindow::didChangeIsLoading(const void* clientInfo) +{ + auto& thisWindow = toWebKitBrowserWindow(clientInfo); +} + +void WebKitBrowserWindow::didChangeActiveURL(const void* clientInfo) +{ + auto& thisWindow = toWebKitBrowserWindow(clientInfo); + auto page = WKViewGetPage(thisWindow.m_view.get()); + WKRetainPtr url = adoptWK(WKPageCopyActiveURL(page)); + thisWindow.m_client.activeURLChanged(createString(url.get())); +} + +void WebKitBrowserWindow::didReceiveAuthenticationChallenge(WKPageRef page, WKAuthenticationChallengeRef challenge, const void* clientInfo) +{ + auto& thisWindow = toWebKitBrowserWindow(clientInfo); + auto protectionSpace = WKAuthenticationChallengeGetProtectionSpace(challenge); + auto decisionListener = WKAuthenticationChallengeGetDecisionListener(challenge); + auto authenticationScheme = WKProtectionSpaceGetAuthenticationScheme(protectionSpace); + + if (authenticationScheme == kWKProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested) { + if (thisWindow.canTrustServerCertificate(protectionSpace)) { + WKRetainPtr username = createWKString("accept server trust"); + WKRetainPtr password = createWKString(""); + WKRetainPtr wkCredential = adoptWK(WKCredentialCreate(username.get(), password.get(), kWKCredentialPersistenceForSession)); + WKAuthenticationDecisionListenerUseCredential(decisionListener, wkCredential.get()); + return; + } + } else { + WKRetainPtr realm(WKProtectionSpaceCopyRealm(protectionSpace)); + + if (auto credential = askCredential(thisWindow.hwnd(), createString(realm.get()))) { + WKRetainPtr username = createWKString(credential->username); + WKRetainPtr password = createWKString(credential->password); + WKRetainPtr wkCredential = adoptWK(WKCredentialCreate(username.get(), password.get(), kWKCredentialPersistenceForSession)); + WKAuthenticationDecisionListenerUseCredential(decisionListener, wkCredential.get()); + return; + } + } + + WKAuthenticationDecisionListenerUseCredential(decisionListener, nullptr); +} + +bool WebKitBrowserWindow::canTrustServerCertificate(WKProtectionSpaceRef protectionSpace) +{ + auto host = createString(adoptWK(WKProtectionSpaceCopyHost(protectionSpace)).get()); + auto certificateInfo = adoptWK(WKProtectionSpaceCopyCertificateInfo(protectionSpace)); + auto verificationError = WKCertificateInfoGetVerificationError(certificateInfo.get()); + auto description = createString(adoptWK(WKCertificateInfoCopyVerificationErrorDescription(certificateInfo.get())).get()); + auto pem = createPEMString(certificateInfo.get()); + + auto it = m_acceptedServerTrustCerts.find(host); + if (it != m_acceptedServerTrustCerts.end() && it->second == pem) + return true; + + std::wstring textString = L"[HOST] " + host + L"\r\n"; + textString.append(L"[ERROR] " + std::to_wstring(verificationError) + L"\r\n"); + textString.append(L"[DESCRIPTION] " + description + L"\r\n"); + textString.append(pem); + + if (askServerTrustEvaluation(hwnd(), textString)) { + m_acceptedServerTrustCerts.emplace(host, pem); + return true; + } + + return false; +} + +void WebKitBrowserWindow::closeWindow(WKPageRef page, const void* clientInfo) +{ + auto& thisWindow = toWebKitBrowserWindow(clientInfo); + PostMessage(thisWindow.m_hMainWnd, WM_CLOSE, 0, 0); +} + +void WebKitBrowserWindow::runJavaScriptAlert(WKPageRef page, WKStringRef alertText, WKFrameRef frame, WKSecurityOriginRef securityOrigin, WKPageRunJavaScriptAlertResultListenerRef listener, const void *clientInfo) +{ + auto& thisWindow = toWebKitBrowserWindow(clientInfo); + WKRetain(listener); + thisWindow.m_alertDialog = listener; +} + +void WebKitBrowserWindow::runJavaScriptConfirm(WKPageRef page, WKStringRef message, WKFrameRef frame, WKSecurityOriginRef securityOrigin, WKPageRunJavaScriptConfirmResultListenerRef listener, const void *clientInfo) +{ + auto& thisWindow = toWebKitBrowserWindow(clientInfo); + WKRetain(listener); + thisWindow.m_confirmDialog = listener; +} + +void WebKitBrowserWindow::runJavaScriptPrompt(WKPageRef page, WKStringRef message, WKStringRef defaultValue, WKFrameRef frame, WKSecurityOriginRef securityOrigin, WKPageRunJavaScriptPromptResultListenerRef listener, const void *clientInfo) +{ + auto& thisWindow = toWebKitBrowserWindow(clientInfo); + WKRetain(listener); + thisWindow.m_promptDialog = listener; +} + +void WebKitBrowserWindow::runBeforeUnloadConfirmPanel(WKPageRef page, WKStringRef message, WKFrameRef frame, WKPageRunBeforeUnloadConfirmPanelResultListenerRef listener, const void *clientInfo) +{ + auto& thisWindow = toWebKitBrowserWindow(clientInfo); + WKRetain(listener); + thisWindow.m_beforeUnloadDialog = listener; +} + +void WebKitBrowserWindow::handleJavaScriptDialog(WKPageRef page, bool accept, WKStringRef value, const void *clientInfo) +{ + auto& thisWindow = toWebKitBrowserWindow(clientInfo); + if (thisWindow.m_alertDialog) { + WKPageRunJavaScriptAlertResultListenerCall(thisWindow.m_alertDialog); + WKRelease(thisWindow.m_alertDialog); + thisWindow.m_alertDialog = NULL; + } + + if (thisWindow.m_confirmDialog) { + WKPageRunJavaScriptConfirmResultListenerCall(thisWindow.m_confirmDialog, accept); + WKRelease(thisWindow.m_confirmDialog); + thisWindow.m_confirmDialog = NULL; + } + + if (thisWindow.m_promptDialog) { + WKPageRunJavaScriptPromptResultListenerCall(thisWindow.m_promptDialog, accept ? value : NULL); + WKRelease(thisWindow.m_promptDialog); + thisWindow.m_promptDialog = NULL; + } + + if (thisWindow.m_beforeUnloadDialog) { + WKPageRunBeforeUnloadConfirmPanelResultListenerCall(thisWindow.m_beforeUnloadDialog, accept); + WKRelease(thisWindow.m_beforeUnloadDialog); + thisWindow.m_beforeUnloadDialog = NULL; + } +} + +WKRect WebKitBrowserWindow::getWindowFrame(WKPageRef page, const void *clientInfo) { + auto& thisWindow = toWebKitBrowserWindow(clientInfo); + WKRect wkFrame { }; + RECT r; + if (::GetWindowRect(thisWindow.m_hMainWnd, &r)) { + wkFrame.origin.x = r.left; + wkFrame.origin.y = r.top; + wkFrame.size.width = r.right - r.left; + wkFrame.size.height = r.bottom - r.top; + } + return wkFrame; +} + +WKPageRef WebKitBrowserWindow::createPageCallback(WKPageConfigurationRef configuration) +{ + // This comes from the Playwright agent, configuration is a pool+data pair. + return WebKitBrowserWindow::createViewCallback(configuration, true); +} + +WKPageRef WebKitBrowserWindow::createViewCallback(WKPageConfigurationRef configuration, bool navigate) +{ + auto* newWindow = new MainWindow(); + bool ok = newWindow->init(hInst, configuration); + if (navigate) + newWindow->browserWindow()->loadURL(_bstr_t("about:blank").GetBSTR()); + + auto* newBrowserWindow = newWindow->browserWindow(); + return WKViewGetPage(newBrowserWindow->m_view.get()); +} + + +WKPageRef WebKitBrowserWindow::createNewPage(WKPageRef, WKPageConfigurationRef configuration, WKNavigationActionRef, WKWindowFeaturesRef, const void*) +{ + // This comes from the client for popups, configuration is inherited from main page. + // Retain popups as per API contract. + WKRetainPtr newPage = createViewCallback(configuration, false); + return newPage.leakRef(); +} + +void WebKitBrowserWindow::didNotHandleKeyEvent(WKPageRef, WKNativeEventPtr event, const void* clientInfo) +{ + auto& thisWindow = toWebKitBrowserWindow(clientInfo); + PostMessage(thisWindow.m_hMainWnd, event->message, event->wParam, event->lParam); +} + +void WebKitBrowserWindow::decidePolicyForResponse(WKPageRef page, WKFrameRef frame, WKURLResponseRef response, WKURLRequestRef request, WKFramePolicyListenerRef listener, WKTypeRef userData, const void* clientInfo) +{ + if (WKURLResponseIsAttachment(response)) + WKFramePolicyListenerDownload(listener); + else + WKFramePolicyListenerUse(listener); +} diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/WebKitBrowserWindow.h b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/WebKitBrowserWindow.h new file mode 100644 index 0000000000000..ce9270608a774 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/WebKitBrowserWindow.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2018 Sony Interactive Entertainment Inc. + * + * 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. + */ +#pragma once + +#include "Common.h" +#include +#include +#include + +class BrowserWindowClient { +public: + virtual void activeURLChanged(std::wstring) = 0; +}; + +class WebKitBrowserWindow { +public: + static WKPageRef createPageCallback(WKPageConfigurationRef); + WebKitBrowserWindow(BrowserWindowClient&, HWND mainWnd, WKPageConfigurationRef); + ~WebKitBrowserWindow(); + + HRESULT loadURL(const BSTR& url); + void reload(); + void navigateForwardOrBackward(bool forward); + void launchInspector(); + + _bstr_t userAgent(); + void setUserAgent(_bstr_t&); + + void resetZoom(); + void zoomIn(); + void zoomOut(); + + bool canTrustServerCertificate(WKProtectionSpaceRef); + HWND hwnd(); + +private: + static WKPageRef createViewCallback(WKPageConfigurationRef, bool navigate); + + static void didChangeTitle(const void*); + static void didChangeIsLoading(const void*); + static void didChangeEstimatedProgress(const void*); + static void didChangeActiveURL(const void*); + static void didReceiveAuthenticationChallenge(WKPageRef, WKAuthenticationChallengeRef, const void*); + static WKPageRef createNewPage(WKPageRef, WKPageConfigurationRef, WKNavigationActionRef, WKWindowFeaturesRef, const void *); + static void closeWindow(WKPageRef, const void*); + static void runJavaScriptAlert(WKPageRef page, WKStringRef alertText, WKFrameRef frame, WKSecurityOriginRef securityOrigin, WKPageRunJavaScriptAlertResultListenerRef listener, const void *clientInfo); + static void runJavaScriptConfirm(WKPageRef page, WKStringRef message, WKFrameRef frame, WKSecurityOriginRef securityOrigin, WKPageRunJavaScriptConfirmResultListenerRef listener, const void *clientInfo); + static void runJavaScriptPrompt(WKPageRef page, WKStringRef message, WKStringRef defaultValue, WKFrameRef frame, WKSecurityOriginRef securityOrigin, WKPageRunJavaScriptPromptResultListenerRef listener, const void *clientInfo); + static void runBeforeUnloadConfirmPanel(WKPageRef page, WKStringRef message, WKFrameRef frame, WKPageRunBeforeUnloadConfirmPanelResultListenerRef listener, const void *clientInfo); + static void handleJavaScriptDialog(WKPageRef page, bool accept, WKStringRef value, const void *clientInfo); + static WKRect getWindowFrame(WKPageRef page, const void *clientInfo); + static void didNotHandleKeyEvent(WKPageRef, WKNativeEventPtr, const void*); + static void decidePolicyForResponse(WKPageRef, WKFrameRef, WKURLResponseRef, WKURLRequestRef, WKFramePolicyListenerRef, WKTypeRef, const void*); + + BrowserWindowClient& m_client; + WKRetainPtr m_view; + HWND m_hMainWnd { nullptr }; + std::unordered_map m_acceptedServerTrustCerts; + WKPageRunJavaScriptAlertResultListenerRef m_alertDialog = { }; + WKPageRunJavaScriptConfirmResultListenerRef m_confirmDialog = { }; + WKPageRunJavaScriptPromptResultListenerRef m_promptDialog = { }; + WKPageRunBeforeUnloadConfirmPanelResultListenerRef m_beforeUnloadDialog = { }; +}; diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/WinMain.cpp b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/WinMain.cpp new file mode 100644 index 0000000000000..1187993d5371f --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/WinMain.cpp @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2006, 2008, 2013-2015 Apple Inc. All rights reserved. + * Copyright (C) 2009, 2011 Brent Fulgham. All rights reserved. + * Copyright (C) 2009, 2010, 2011 Appcelerator, Inc. All rights reserved. + * Copyright (C) 2013 Alex Christensen. 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. + */ + +#pragma warning(disable: 4091) + +#include "stdafx.h" +#include "Common.h" +#include "MainWindow.h" +#include "PlaywrightLibResource.h" +#include "PlaywrightReplace.h" +#include +#include +#include +#include +#include +#include "WebKitBrowserWindow.h" +#include +#include + +SOFT_LINK_LIBRARY(user32); +SOFT_LINK_OPTIONAL(user32, SetProcessDpiAwarenessContext, BOOL, STDAPICALLTYPE, (DPI_AWARENESS_CONTEXT)); + +CommandLineOptions g_options; + +static WKRetainPtr toWK(const std::string& string) +{ + return adoptWK(WKStringCreateWithUTF8CString(string.c_str())); +} + +static std::string toUTF8String(const wchar_t* src, size_t srcLength) +{ + int length = WideCharToMultiByte(CP_UTF8, 0, src, srcLength, 0, 0, nullptr, nullptr); + std::vector buffer(length); + size_t actualLength = WideCharToMultiByte(CP_UTF8, 0, src, srcLength, buffer.data(), length, nullptr, nullptr); + return { buffer.data(), actualLength }; +} + +static void configureDataStore(WKWebsiteDataStoreRef dataStore) { + if (g_options.curloptProxy.length()) { + auto curloptProxy = createWKURL(g_options.curloptProxy); + auto curloptNoproxy = createWKString(g_options.curloptNoproxy); + WKWebsiteDataStoreEnableCustomNetworkProxySettings(dataStore, curloptProxy.get(), curloptNoproxy.get()); + } +} + +int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpstrCmdLine, _In_ int nCmdShow) +{ +#ifdef _CRTDBG_MAP_ALLOC + _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); +#endif + + MSG msg { }; + HACCEL hAccelTable, hPreAccelTable; + + INITCOMMONCONTROLSEX InitCtrlEx; + + InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX); + InitCtrlEx.dwICC = 0x00004000; // ICC_STANDARD_CLASSES; + InitCommonControlsEx(&InitCtrlEx); + + g_options = parseCommandLine(); + if (g_options.inspectorPipe) { + WKInspectorInitializeRemoteInspectorPipe( + configureDataStore, + WebKitBrowserWindow::createPageCallback, + []() { PostQuitMessage(0); }); + } + + if (g_options.useFullDesktop) + computeFullDesktopFrame(); + + // Init COM + OleInitialize(nullptr); + + if (SetProcessDpiAwarenessContextPtr()) + SetProcessDpiAwarenessContextPtr()(DPI_AWARENESS_CONTEXT_UNAWARE); + + MainWindow::configure(g_options.headless, g_options.noStartupWindow); + + if (!g_options.noStartupWindow) { + auto configuration = adoptWK(WKWebsiteDataStoreConfigurationCreate()); + if (g_options.userDataDir.length()) { + std::string profileFolder = toUTF8String(g_options.userDataDir, g_options.userDataDir.length()); + WKWebsiteDataStoreConfigurationSetApplicationCacheDirectory(configuration.get(), toWK(profileFolder + "\\ApplicationCache").get()); + WKWebsiteDataStoreConfigurationSetNetworkCacheDirectory(configuration.get(), toWK(profileFolder + "\\Cache").get()); + WKWebsiteDataStoreConfigurationSetCacheStorageDirectory(configuration.get(), toWK(profileFolder + "\\CacheStorage").get()); + WKWebsiteDataStoreConfigurationSetIndexedDBDatabaseDirectory(configuration.get(), toWK(profileFolder + "\\Databases" + "\\IndexedDB").get()); + WKWebsiteDataStoreConfigurationSetLocalStorageDirectory(configuration.get(), toWK(profileFolder + "\\LocalStorage").get()); + WKWebsiteDataStoreConfigurationSetWebSQLDatabaseDirectory(configuration.get(), toWK(profileFolder + "\\Databases" + "\\WebSQL").get()); + WKWebsiteDataStoreConfigurationSetMediaKeysStorageDirectory(configuration.get(), toWK(profileFolder + "\\MediaKeys").get()); + WKWebsiteDataStoreConfigurationSetResourceLoadStatisticsDirectory(configuration.get(), toWK(profileFolder + "\\ResourceLoadStatistics").get()); + WKWebsiteDataStoreConfigurationSetServiceWorkerRegistrationDirectory(configuration.get(), toWK(profileFolder + "\\ServiceWorkers").get()); + } + auto context = adoptWK(WKContextCreateWithConfiguration(nullptr)); + auto dataStore = adoptWK(WKWebsiteDataStoreCreateWithConfiguration(configuration.get())); + configureDataStore(dataStore.get()); + + auto* mainWindow = new MainWindow(); + auto conf = adoptWK(WKPageConfigurationCreate()); + WKPageConfigurationSetContext(conf.get(), context.get()); + WKPageConfigurationSetWebsiteDataStore(conf.get(), dataStore.get()); + HRESULT hr = mainWindow->init(hInst, conf.get()); + if (FAILED(hr)) + goto exit; + + if (g_options.requestedURL.length()) + mainWindow->loadURL(g_options.requestedURL.GetBSTR()); + else + mainWindow->loadURL(L"about:blank"); + } + + hAccelTable = LoadAccelerators(hInst, MAKEINTRESOURCE(IDC_PLAYWRIGHT)); + hPreAccelTable = LoadAccelerators(hInst, MAKEINTRESOURCE(IDR_ACCELERATORS_PRE)); + +#pragma warning(disable:4509) + + // Main message loop: + __try { + while (GetMessage(&msg, nullptr, 0, 0)) { + if (TranslateAccelerator(msg.hwnd, hPreAccelTable, &msg)) + continue; + bool processed = false; + if (MainWindow::isInstance(msg.hwnd)) + processed = TranslateAccelerator(msg.hwnd, hAccelTable, &msg); + if (!processed) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + } __except(createCrashReport(GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER) { } + +exit: +#ifdef _CRTDBG_MAP_ALLOC + _CrtDumpMemoryLeaks(); +#endif + + // Shut down COM. + OleUninitialize(); + + return static_cast(msg.wParam); +} + +extern "C" __declspec(dllexport) int WINAPI dllLauncherEntryPoint(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpstrCmdLine, int nCmdShow) +{ + return wWinMain(hInstance, hPrevInstance, lpstrCmdLine, nCmdShow); +} diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/resource.h b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/resource.h new file mode 100644 index 0000000000000..5a19599daedb9 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/resource.h @@ -0,0 +1,25 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by WinLauncher.rc +// +#define IDC_MYICON 2 +#define IDD_WINLAUNCHER_DIALOG 102 +#define IDS_APP_TITLE 103 +#define IDD_ABOUTBOX 103 +#define IDM_ABOUT 104 +#define IDI_WINLAUNCHER 107 +#define IDC_WINLAUNCHER 109 +#define IDR_MAINFRAME 128 +#define IDC_STATIC -1 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 110 +#endif +#endif diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/stdafx.cpp b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/stdafx.cpp new file mode 100644 index 0000000000000..3c4e5e52a16a3 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/stdafx.cpp @@ -0,0 +1,33 @@ +/* + * 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 + * 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. + */ + +// stdafx.cpp : source file that includes just the standard includes +// Spinneret.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/stdafx.h b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/stdafx.h new file mode 100644 index 0000000000000..8436fba636da1 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/stdafx.h @@ -0,0 +1,73 @@ +/* + * 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 + * 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. + */ + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H && defined(BUILDING_WITH_CMAKE) +#include "cmakeconfig.h" +#endif + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +// Needed for limit defines, like INTMAX_MAX, which is used by the std C++ library +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#if 0 +// Visual Studio Leak Detection +// +#if defined(_MSC_VER) && defined(_DEBUG) +#define _CRTDBG_MAP_ALLOC +#include +#include +#endif +#endif diff --git a/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/toolbar.bmp b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/toolbar.bmp new file mode 100644 index 0000000000000..07eea0dbb576d Binary files /dev/null and b/browser_patches/deprecated-webkit-mac-10.14/embedder/Playwright/win/toolbar.bmp differ diff --git a/browser_patches/deprecated-webkit-mac-10.14/patches/bootstrap.diff b/browser_patches/deprecated-webkit-mac-10.14/patches/bootstrap.diff new file mode 100644 index 0000000000000..d5e234f6dd32d --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/patches/bootstrap.diff @@ -0,0 +1,19870 @@ +diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt +index b9f813cb2dbfb35d08cda041b5aa29e6e702e830..a6a44df5170bcd1c04cfb97ca0a5e3d97b46f1a7 100644 +--- a/Source/JavaScriptCore/CMakeLists.txt ++++ b/Source/JavaScriptCore/CMakeLists.txt +@@ -1224,22 +1224,27 @@ set(JavaScriptCore_INSPECTOR_DOMAINS + ${JAVASCRIPTCORE_DIR}/inspector/protocol/CSS.json + ${JAVASCRIPTCORE_DIR}/inspector/protocol/Canvas.json + ${JAVASCRIPTCORE_DIR}/inspector/protocol/Console.json ++ ${JAVASCRIPTCORE_DIR}/inspector/protocol/Dialog.json + ${JAVASCRIPTCORE_DIR}/inspector/protocol/DOM.json + ${JAVASCRIPTCORE_DIR}/inspector/protocol/DOMDebugger.json + ${JAVASCRIPTCORE_DIR}/inspector/protocol/DOMStorage.json + ${JAVASCRIPTCORE_DIR}/inspector/protocol/Database.json + ${JAVASCRIPTCORE_DIR}/inspector/protocol/Debugger.json ++ ${JAVASCRIPTCORE_DIR}/inspector/protocol/Emulation.json + ${JAVASCRIPTCORE_DIR}/inspector/protocol/GenericTypes.json + ${JAVASCRIPTCORE_DIR}/inspector/protocol/Heap.json + ${JAVASCRIPTCORE_DIR}/inspector/protocol/IndexedDB.json ++ ${JAVASCRIPTCORE_DIR}/inspector/protocol/Input.json + ${JAVASCRIPTCORE_DIR}/inspector/protocol/Inspector.json + ${JAVASCRIPTCORE_DIR}/inspector/protocol/LayerTree.json + ${JAVASCRIPTCORE_DIR}/inspector/protocol/Memory.json + ${JAVASCRIPTCORE_DIR}/inspector/protocol/Network.json + ${JAVASCRIPTCORE_DIR}/inspector/protocol/Page.json ++ ${JAVASCRIPTCORE_DIR}/inspector/protocol/Playwright.json + ${JAVASCRIPTCORE_DIR}/inspector/protocol/Recording.json + ${JAVASCRIPTCORE_DIR}/inspector/protocol/Runtime.json + ${JAVASCRIPTCORE_DIR}/inspector/protocol/ScriptProfiler.json ++ ${JAVASCRIPTCORE_DIR}/inspector/protocol/Screencast.json + ${JAVASCRIPTCORE_DIR}/inspector/protocol/Security.json + ${JAVASCRIPTCORE_DIR}/inspector/protocol/ServiceWorker.json + ${JAVASCRIPTCORE_DIR}/inspector/protocol/Target.json +diff --git a/Source/JavaScriptCore/DerivedSources.make b/Source/JavaScriptCore/DerivedSources.make +index 9df8b244d4c456901bddb412189963d065126327..2ea6388f09af272fa838ba257ee385cee7539aca 100644 +--- a/Source/JavaScriptCore/DerivedSources.make ++++ b/Source/JavaScriptCore/DerivedSources.make +@@ -265,22 +265,27 @@ INSPECTOR_DOMAINS := \ + $(JavaScriptCore)/inspector/protocol/CSS.json \ + $(JavaScriptCore)/inspector/protocol/Canvas.json \ + $(JavaScriptCore)/inspector/protocol/Console.json \ ++ $(JavaScriptCore)/inspector/protocol/Dialog.json \ + $(JavaScriptCore)/inspector/protocol/DOM.json \ + $(JavaScriptCore)/inspector/protocol/DOMDebugger.json \ + $(JavaScriptCore)/inspector/protocol/DOMStorage.json \ + $(JavaScriptCore)/inspector/protocol/Database.json \ + $(JavaScriptCore)/inspector/protocol/Debugger.json \ ++ $(JavaScriptCore)/inspector/protocol/Emulation.json \ + $(JavaScriptCore)/inspector/protocol/GenericTypes.json \ + $(JavaScriptCore)/inspector/protocol/Heap.json \ + $(JavaScriptCore)/inspector/protocol/IndexedDB.json \ ++ $(JavaScriptCore)/inspector/protocol/Input.json \ + $(JavaScriptCore)/inspector/protocol/Inspector.json \ + $(JavaScriptCore)/inspector/protocol/LayerTree.json \ + $(JavaScriptCore)/inspector/protocol/Memory.json \ + $(JavaScriptCore)/inspector/protocol/Network.json \ + $(JavaScriptCore)/inspector/protocol/Page.json \ ++ $(JavaScriptCore)/inspector/protocol/Playwright.json \ + $(JavaScriptCore)/inspector/protocol/Recording.json \ + $(JavaScriptCore)/inspector/protocol/Runtime.json \ + $(JavaScriptCore)/inspector/protocol/ScriptProfiler.json \ ++ $(JavaScriptCore)/inspector/protocol/Screencast.json \ + $(JavaScriptCore)/inspector/protocol/Security.json \ + $(JavaScriptCore)/inspector/protocol/ServiceWorker.json \ + $(JavaScriptCore)/inspector/protocol/Target.json \ +diff --git a/Source/JavaScriptCore/bindings/ScriptValue.cpp b/Source/JavaScriptCore/bindings/ScriptValue.cpp +index 52d955b1e4929f6d0dede53097d275559b29b91d..71c538e57acf3912f9a777f7bc7eba6efb8877eb 100644 +--- a/Source/JavaScriptCore/bindings/ScriptValue.cpp ++++ b/Source/JavaScriptCore/bindings/ScriptValue.cpp +@@ -79,7 +79,10 @@ static RefPtr jsToInspectorValue(JSGlobalObject* globalObject, JSVa + PropertyNameArray propertyNames(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude); + object.methodTable(vm)->getOwnPropertyNames(&object, globalObject, propertyNames, DontEnumPropertiesMode::Exclude); + for (auto& name : propertyNames) { +- auto inspectorValue = jsToInspectorValue(globalObject, object.get(globalObject, name), maxDepth); ++ JSValue childValue = object.get(globalObject, name); ++ if (childValue.isUndefined()) ++ continue; ++ auto inspectorValue = jsToInspectorValue(globalObject, childValue, maxDepth); + if (!inspectorValue) + return nullptr; + inspectorObject->setValue(name.string(), inspectorValue.releaseNonNull()); +diff --git a/Source/JavaScriptCore/inspector/IdentifiersFactory.cpp b/Source/JavaScriptCore/inspector/IdentifiersFactory.cpp +index 95cd87b01b15cb8667e57bc5bb51a71f06bc3760..0481fa93227f297be9d9cf000c5a72235956a390 100644 +--- a/Source/JavaScriptCore/inspector/IdentifiersFactory.cpp ++++ b/Source/JavaScriptCore/inspector/IdentifiersFactory.cpp +@@ -30,14 +30,21 @@ + namespace Inspector { + + namespace { ++static uint64_t s_processID = 0; + static long s_lastUsedIdentifier = 0; + } + + static String addPrefixToIdentifier(const String& identifier) + { +- return makeString("0.", identifier); ++ return makeString(s_processID, ".", identifier); + } + ++void IdentifiersFactory::initializeWithProcessID(uint64_t processID) { ++ ASSERT(!s_processID); ++ s_processID = processID; ++} ++ ++ + String IdentifiersFactory::createIdentifier() + { + return addPrefixToIdentifier(String::number(++s_lastUsedIdentifier)); +diff --git a/Source/JavaScriptCore/inspector/IdentifiersFactory.h b/Source/JavaScriptCore/inspector/IdentifiersFactory.h +index eb25aedee4cd9ebe007e06c2515b37ee095b06f4..badf6559595c8377db1089ca3c25008e1be2c8f1 100644 +--- a/Source/JavaScriptCore/inspector/IdentifiersFactory.h ++++ b/Source/JavaScriptCore/inspector/IdentifiersFactory.h +@@ -31,6 +31,7 @@ namespace Inspector { + + class JS_EXPORT_PRIVATE IdentifiersFactory { + public: ++ static void initializeWithProcessID(uint64_t); + static String createIdentifier(); + static String requestId(unsigned long identifier); + }; +diff --git a/Source/JavaScriptCore/inspector/InjectedScript.cpp b/Source/JavaScriptCore/inspector/InjectedScript.cpp +index 65f8d6bf17af27b559d5bef3089757ffa85c54de..d624b031ac0564a2525b923acfb69cee9afbcbfb 100644 +--- a/Source/JavaScriptCore/inspector/InjectedScript.cpp ++++ b/Source/JavaScriptCore/inspector/InjectedScript.cpp +@@ -289,6 +289,10 @@ RefPtr InjectedScript::wrapObject(JSC::JSValue + auto callResult = callFunctionWithEvalEnabled(wrapFunction); + if (!callResult) + return nullptr; ++ auto callResultValue = callResult.value(); ++ // callResultValue could be missing if the execution was terminated ++ if (!callResultValue) ++ return nullptr; + + auto resultValue = toInspectorValue(globalObject(), callResult.value()); + if (!resultValue) +diff --git a/Source/JavaScriptCore/inspector/InjectedScriptSource.js b/Source/JavaScriptCore/inspector/InjectedScriptSource.js +index 48baed6a1b7ffad453379a2f1eb71b8c4925f6c4..aadd4ae30513a87f36355fa4ffcb6ba7b15dd4fc 100644 +--- a/Source/JavaScriptCore/inspector/InjectedScriptSource.js ++++ b/Source/JavaScriptCore/inspector/InjectedScriptSource.js +@@ -136,7 +136,7 @@ let InjectedScript = class InjectedScript + return; + } + +- if (!(promiseObject instanceof Promise)) { ++ if (InjectedScriptHost.internalConstructorName(promiseObject) !== 'Promise') { + callback("Object with given id is not a Promise"); + return; + } +diff --git a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp +index 033a1b4713352777ee0de5ed53e64f8391f9d74f..fc356dec4b1518547a4217def6a7b5f1d97330fb 100644 +--- a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp ++++ b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp +@@ -101,7 +101,7 @@ void BackendDispatcher::registerDispatcherForDomain(const String& domain, Supple + m_dispatchers.set(domain, dispatcher); + } + +-void BackendDispatcher::dispatch(const String& message) ++void BackendDispatcher::dispatch(const String& message, Interceptor&& interceptor) + { + Ref protect(*this); + +@@ -146,6 +146,9 @@ void BackendDispatcher::dispatch(const String& message) + requestId = *requestIdInt; + } + ++ if (interceptor && interceptor(messageObject) == InterceptionResult::Intercepted) ++ return; ++ + { + // We could be called re-entrantly from a nested run loop, so restore the previous id. + SetForScope> scopedRequestId(m_currentRequestId, requestId); +diff --git a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h +index 8a5efb316e9d09337ada2323dc6f926056a9c2f9..f3dcc8fcc087f474abc88cea837d11ff3e5faeff 100644 +--- a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h ++++ b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h +@@ -84,7 +84,10 @@ public: + }; + + void registerDispatcherForDomain(const String& domain, SupplementalBackendDispatcher*); +- void dispatch(const String& message); ++ ++ enum class InterceptionResult { Intercepted, Continue }; ++ using Interceptor = WTF::Function&)>; ++ void dispatch(const String& message, Interceptor&& interceptor = Interceptor()); + + // Note that 'unused' is a workaround so the compiler can pick the right sendResponse based on arity. + // When is fixed or this class is renamed for the JSON::Object case, +diff --git a/Source/JavaScriptCore/inspector/InspectorFrontendRouter.cpp b/Source/JavaScriptCore/inspector/InspectorFrontendRouter.cpp +index d408d364f1986983161f9d44efbc8bc6f6898676..1375ce9990f0c63d7e6f33ee62930051d6cd44cb 100644 +--- a/Source/JavaScriptCore/inspector/InspectorFrontendRouter.cpp ++++ b/Source/JavaScriptCore/inspector/InspectorFrontendRouter.cpp +@@ -49,7 +49,7 @@ void FrontendRouter::connectFrontend(FrontendChannel& connection) + void FrontendRouter::disconnectFrontend(FrontendChannel& connection) + { + if (!m_connections.contains(&connection)) { +- ASSERT_NOT_REACHED(); ++ ASSERT(m_connections.isEmpty()); + return; + } + +diff --git a/Source/JavaScriptCore/inspector/InspectorTarget.cpp b/Source/JavaScriptCore/inspector/InspectorTarget.cpp +index 0cc2127c9c12c2d82dea9550bad73f4ffb99ba24..8ca65cc042d435cbc0e05dcc5c5dfc958eb24f5a 100644 +--- a/Source/JavaScriptCore/inspector/InspectorTarget.cpp ++++ b/Source/JavaScriptCore/inspector/InspectorTarget.cpp +@@ -44,6 +44,8 @@ void InspectorTarget::resume() + ASSERT(m_isPaused); + m_isPaused = false; + ++ willResume(); ++ + if (m_resumeCallback) { + m_resumeCallback(); + m_resumeCallback = nullptr; +@@ -52,7 +54,6 @@ void InspectorTarget::resume() + + void InspectorTarget::setResumeCallback(WTF::Function&& callback) + { +- ASSERT(!m_resumeCallback); + m_resumeCallback = WTFMove(callback); + } + +diff --git a/Source/JavaScriptCore/inspector/InspectorTarget.h b/Source/JavaScriptCore/inspector/InspectorTarget.h +index 4b95964db4d902b4b7f4b0b4c40afea51654ff2f..966a5927702b65edb343369decafda7fc83eaec7 100644 +--- a/Source/JavaScriptCore/inspector/InspectorTarget.h ++++ b/Source/JavaScriptCore/inspector/InspectorTarget.h +@@ -56,8 +56,12 @@ public: + virtual void connect(FrontendChannel::ConnectionType) = 0; + virtual void disconnect() = 0; + virtual void sendMessageToTargetBackend(const String&) = 0; ++ virtual void activate(String& error) { error = "Target cannot be activated"; } ++ virtual void close(String& error, bool /* runBeforeUnload */) { error = "Target cannot be closed"; } + + private: ++ virtual void willResume() { } ++ + WTF::Function m_resumeCallback; + bool m_isPaused { false }; + }; +diff --git a/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp b/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp +index 508eb02ec95c52408384a1e2b77648afd426dd9d..05f483dced4b62ffdd60b0a0447504802e1f5711 100644 +--- a/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp ++++ b/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp +@@ -87,6 +87,34 @@ Protocol::ErrorStringOr InspectorTargetAgent::sendMessageToTarget(const St + return { }; + } + ++Protocol::ErrorStringOr InspectorTargetAgent::activate(const String& targetId) ++{ ++ InspectorTarget* target = m_targets.get(targetId); ++ if (!target) ++ return makeUnexpected("Missing target for given targetId"_s); ++ ++ String errorString; ++ target->activate(errorString); ++ if (!errorString.isEmpty()) ++ return makeUnexpected(errorString); ++ ++ return { }; ++} ++ ++Protocol::ErrorStringOr InspectorTargetAgent::close(const String& targetId, Optional&& runBeforeUnload) ++{ ++ InspectorTarget* target = m_targets.get(targetId); ++ if (!target) ++ return makeUnexpected("Missing target for given targetId"_s); ++ ++ String errorString; ++ target->close(errorString, runBeforeUnload && *runBeforeUnload); ++ if (!errorString.isEmpty()) ++ return makeUnexpected(errorString); ++ ++ return { }; ++} ++ + void InspectorTargetAgent::sendMessageFromTargetToFrontend(const String& targetId, const String& message) + { + ASSERT_WITH_MESSAGE(m_targets.get(targetId), "Sending a message from an untracked target to the frontend."); +@@ -144,7 +172,17 @@ void InspectorTargetAgent::targetDestroyed(InspectorTarget& target) + if (!m_isConnected) + return; + +- m_frontendDispatcher->targetDestroyed(target.identifier()); ++ m_frontendDispatcher->targetDestroyed(target.identifier(), false); ++} ++ ++void InspectorTargetAgent::targetCrashed(InspectorTarget& target) ++{ ++ m_targets.remove(target.identifier()); ++ ++ if (!m_isConnected) ++ return; ++ ++ m_frontendDispatcher->targetDestroyed(target.identifier(), true); + } + + void InspectorTargetAgent::didCommitProvisionalTarget(const String& oldTargetID, const String& committedTargetID) +@@ -159,6 +197,18 @@ void InspectorTargetAgent::didCommitProvisionalTarget(const String& oldTargetID, + m_frontendDispatcher->didCommitProvisionalTarget(oldTargetID, committedTargetID); + } + ++void InspectorTargetAgent::ensureConnected(const String& targetID) ++{ ++ if (!m_isConnected) ++ return; ++ ++ auto* target = m_targets.get(targetID); ++ if (!target) ++ return; ++ ++ target->connect(connectionType()); ++} ++ + FrontendChannel::ConnectionType InspectorTargetAgent::connectionType() const + { + return m_router.hasLocalFrontend() ? Inspector::FrontendChannel::ConnectionType::Local : Inspector::FrontendChannel::ConnectionType::Remote; +diff --git a/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h b/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h +index e81573fd0fffaaf6fd2af36635c78fcdf8608c69..3d7b412e8cf1e4c32d23091514795a39927012fd 100644 +--- a/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h ++++ b/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h +@@ -50,15 +50,21 @@ public: + Protocol::ErrorStringOr setPauseOnStart(bool) final; + Protocol::ErrorStringOr resume(const String& targetId) final; + Protocol::ErrorStringOr sendMessageToTarget(const String& targetId, const String& message) final; ++ Protocol::ErrorStringOr activate(const String& targetId) override; ++ Protocol::ErrorStringOr close(const String& targetId, Optional&& runBeforeUnload) override; + + // Target lifecycle. + void targetCreated(InspectorTarget&); + void targetDestroyed(InspectorTarget&); ++ void targetCrashed(InspectorTarget&); + void didCommitProvisionalTarget(const String& oldTargetID, const String& committedTargetID); ++ void ensureConnected(const String& targetID); + + // Target messages. + void sendMessageFromTargetToFrontend(const String& targetId, const String& message); + ++ bool isConnected() { return m_isConnected; } ++ + private: + // FrontendChannel + FrontendChannel::ConnectionType connectionType() const; +diff --git a/Source/JavaScriptCore/inspector/protocol/DOM.json b/Source/JavaScriptCore/inspector/protocol/DOM.json +index 1620c003f076eee31ddc8be69a84e4995299892a..424b110d0e82e8ddbc4c7f44dfe87ba6c8f84a4f 100644 +--- a/Source/JavaScriptCore/inspector/protocol/DOM.json ++++ b/Source/JavaScriptCore/inspector/protocol/DOM.json +@@ -80,6 +80,16 @@ + { "name": "value", "type": "string", "description": "The value that is resolved to with this data binding relationship." } + ] + }, ++ { ++ "id": "Rect", ++ "type": "object", ++ "properties": [ ++ { "name": "x", "type": "integer", "description": "X coordinate" }, ++ { "name": "y", "type": "integer", "description": "Y coordinate" }, ++ { "name": "width", "type": "integer", "description": "Rectangle width" }, ++ { "name": "height", "type": "integer", "description": "Rectangle height" } ++ ] ++ }, + { + "id": "EventListener", + "type": "object", +@@ -168,6 +178,16 @@ + { "name": "borderColor", "$ref": "RGBAColor", "optional": true, "description": "The border highlight fill color (default: transparent)." }, + { "name": "marginColor", "$ref": "RGBAColor", "optional": true, "description": "The margin highlight fill color (default: transparent)." } + ] ++ }, ++ { ++ "id": "FilePayload", ++ "type": "object", ++ "description": "Data to construct File object.", ++ "properties": [ ++ { "name": "name", "type": "string", "description": "File name." }, ++ { "name": "type", "type": "string", "description": "File type." }, ++ { "name": "data", "type": "string", "description": "Base64-encoded file data." } ++ ] + } + ], + "commands": [ +@@ -532,7 +552,9 @@ + "description": "Resolves JavaScript node object for given node id.", + "targetTypes": ["page"], + "parameters": [ +- { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to resolve." }, ++ { "name": "nodeId", "$ref": "NodeId", "optional": true, "description": "Id of the node to resolve." }, ++ { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "optional": true, "description": "Source element handle." }, ++ { "name": "executionContextId", "$ref": "Runtime.ExecutionContextId", "optional": true, "description": "Specifies in which execution context to adopt to." }, + { "name": "objectGroup", "type": "string", "optional": true, "description": "Symbolic group name that can be used to release multiple objects." } + ], + "returns": [ +@@ -599,6 +621,45 @@ + "parameters": [ + { "name": "allow", "type": "boolean" } + ] ++ }, ++ { ++ "name": "describeNode", ++ "description": "Returns node description.", ++ "parameters": [ ++ { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "JavaScript object id of the node wrapper." } ++ ], ++ "returns": [ ++ { "name": "contentFrameId", "$ref": "Network.FrameId", "optional": true, "description": "Frame ID for frame owner elements." }, ++ { "name": "ownerFrameId", "$ref": "Network.FrameId", "optional": true, "description": "ID of the owning frame element." } ++ ] ++ }, ++ { ++ "name": "scrollIntoViewIfNeeded", ++ "description": "Scrolls the given rect into view if not already in the viewport.", ++ "parameters": [ ++ { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "JavaScript object id of the node wrapper." }, ++ { "name": "rect", "$ref": "Rect", "optional": true, "description": "Rect relative to the node's border box, in CSS pixels." } ++ ] ++ }, ++ { ++ "name": "getContentQuads", ++ "description": "Returns quads that describe node position on the page. This method\nmight return multiple quads for inline nodes.", ++ "parameters": [ ++ { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "JavaScript object id of the node wrapper." } ++ ], ++ "returns": [ ++ { ++ "name": "quads", "type": "array", "items": { "$ref": "Quad" }, "description": "Quads that describe node layout relative to viewport." ++ } ++ ] ++ }, ++ { ++ "name": "setInputFiles", ++ "description": "Sets input files for given ", ++ "parameters": [ ++ { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "Input element handle." }, ++ { "name": "files", "type": "array", "items": { "$ref": "FilePayload" }, "description": "Files to set" } ++ ] + } + ], + "events": [ +diff --git a/Source/JavaScriptCore/inspector/protocol/Dialog.json b/Source/JavaScriptCore/inspector/protocol/Dialog.json +new file mode 100644 +index 0000000000000000000000000000000000000000..79edea03fed4e9be5da96e1275e182a479cb7a0a +--- /dev/null ++++ b/Source/JavaScriptCore/inspector/protocol/Dialog.json +@@ -0,0 +1,36 @@ ++{ ++ "domain": "Dialog", ++ "description": "Actions and events related to alert boxes.", ++ "availability": ["web"], ++ "types": [ ++ ], ++ "commands": [ ++ { ++ "name": "enable", ++ "description": "Enables dialog domain notifications." ++ }, ++ { ++ "name": "disable", ++ "description": "Disables dialog domain notifications." ++ }, ++ { ++ "name": "handleJavaScriptDialog", ++ "description": "Accepts or dismisses a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload).", ++ "parameters": [ ++ { "name": "accept", "type": "boolean", "description": "Whether to accept or dismiss the dialog."}, ++ { "name": "promptText", "optional": true, "type": "string", "description": "The text to enter into the dialog prompt before accepting. Used only if this is a prompt dialog."} ++ ] ++ } ++ ], ++ "events": [ ++ { ++ "name": "javascriptDialogOpening", ++ "description": "Fired when a JavaScript initiated dialog (alert, confirm, prompt, or onbeforeunload) is about to open.", ++ "parameters": [ ++ { "name": "type", "type": "string", "description": "Dialog type."}, ++ { "name": "message", "type": "string", "description": "Message that will be displayed by the dialog."}, ++ { "name": "defaultPrompt", "optional": true, "type": "string", "description": "Default dialog prompt."} ++ ] ++ } ++ ] ++} +diff --git a/Source/JavaScriptCore/inspector/protocol/Emulation.json b/Source/JavaScriptCore/inspector/protocol/Emulation.json +new file mode 100644 +index 0000000000000000000000000000000000000000..3f28f8e41b39c517369c8ca69415486a75657489 +--- /dev/null ++++ b/Source/JavaScriptCore/inspector/protocol/Emulation.json +@@ -0,0 +1,51 @@ ++{ ++ "domain": "Emulation", ++ "availability": ["web"], ++ "commands": [ ++ { ++ "name": "setDeviceMetricsOverride", ++ "description": "Overrides device metrics with provided values.", ++ "async": true, ++ "parameters": [ ++ { "name": "width", "type": "integer" }, ++ { "name": "height", "type": "integer" }, ++ { "name": "deviceScaleFactor", "type": "number" }, ++ { "name": "fixedLayout", "type": "boolean" } ++ ] ++ }, ++ { ++ "name": "setJavaScriptEnabled", ++ "description": "Allows to disable script execution for the page.", ++ "parameters": [ ++ { "name": "enabled", "type": "boolean" } ++ ] ++ }, ++ { ++ "name": "setAuthCredentials", ++ "description": "Credentials to use during HTTP authentication.", ++ "parameters": [ ++ { "name": "username", "type": "string", "optional": true }, ++ { "name": "password", "type": "string", "optional": true } ++ ] ++ }, ++ { ++ "name": "setActiveAndFocused", ++ "description": "Makes page focused for test.", ++ "parameters": [ ++ { "name": "active", "type": "boolean", "optional": true } ++ ] ++ }, ++ { ++ "name": "grantPermissions", ++ "parameters": [ ++ { "name": "origin", "type": "string" }, ++ { "name": "permissions", "type": "array", "items": { "type": "string" } } ++ ], ++ "description": "Overrides the permissions." ++ }, ++ { ++ "name": "resetPermissions", ++ "description": "Clears permission overrides." ++ } ++ ] ++} +diff --git a/Source/JavaScriptCore/inspector/protocol/Input.json b/Source/JavaScriptCore/inspector/protocol/Input.json +new file mode 100644 +index 0000000000000000000000000000000000000000..587287d52fde2735cbae34a27a0f673b7e38e1a7 +--- /dev/null ++++ b/Source/JavaScriptCore/inspector/protocol/Input.json +@@ -0,0 +1,188 @@ ++{ ++ "domain": "Input", ++ "availability": ["web"], ++ "types": [ ++ { ++ "id": "TimeSinceEpoch", ++ "description": "UTC time in seconds, counted from January 1, 1970.", ++ "type": "number" ++ } ++ ], ++ "commands": [ ++ { ++ "name": "dispatchKeyEvent", ++ "description": "Dispatches a key event to the page.", ++ "async": true, ++ "parameters": [ ++ { ++ "name": "type", ++ "description": "Type of the key event.", ++ "type": "string", ++ "enum": [ ++ "keyDown", ++ "keyUp" ++ ] ++ }, ++ { ++ "name": "modifiers", ++ "description": "Bit field representing pressed modifier keys. (default: 0).", ++ "optional": true, ++ "type": "integer" ++ }, ++ { ++ "name": "text", ++ "description": "Text as generated by processing a virtual key code with a keyboard layout. Not needed for\nfor `keyUp` and `rawKeyDown` events (default: \"\")", ++ "optional": true, ++ "type": "string" ++ }, ++ { ++ "name": "unmodifiedText", ++ "description": "Text that would have been generated by the keyboard if no modifiers were pressed (except for\nshift). Useful for shortcut (accelerator) key handling (default: \"\").", ++ "optional": true, ++ "type": "string" ++ }, ++ { ++ "name": "code", ++ "description": "Unique DOM defined string value for each physical key (e.g., 'KeyA') (default: \"\").", ++ "optional": true, ++ "type": "string" ++ }, ++ { ++ "name": "key", ++ "description": "Unique DOM defined string value describing the meaning of the key in the context of active\nmodifiers, keyboard layout, etc (e.g., 'AltGr') (default: \"\").", ++ "optional": true, ++ "type": "string" ++ }, ++ { ++ "name": "windowsVirtualKeyCode", ++ "description": "Windows virtual key code (default: 0).", ++ "optional": true, ++ "type": "integer" ++ }, ++ { ++ "name": "nativeVirtualKeyCode", ++ "description": "Native virtual key code (default: 0).", ++ "optional": true, ++ "type": "integer" ++ }, ++ { ++ "name": "autoRepeat", ++ "description": "Whether the event was generated from auto repeat (default: false).", ++ "optional": true, ++ "type": "boolean" ++ }, ++ { ++ "name": "isKeypad", ++ "description": "Whether the event was generated from the keypad (default: false).", ++ "optional": true, ++ "type": "boolean" ++ }, ++ { ++ "name": "isSystemKey", ++ "description": "Whether the event was a system key event (default: false).", ++ "optional": true, ++ "type": "boolean" ++ }, ++ { ++ "name": "macCommands", ++ "description": "Mac editing commands associated with this key", ++ "type": "array", ++ "optional": true, ++ "items": { ++ "type": "string" ++ } ++ } ++ ] ++ }, ++ { ++ "name": "dispatchMouseEvent", ++ "description": "Dispatches a mouse event to the page.", ++ "async": true, ++ "parameters": [ ++ { ++ "name": "type", ++ "description": "Type of the mouse event.", ++ "type": "string", ++ "enum": [ "move", "down", "up", "wheel"] ++ }, ++ { ++ "name": "x", ++ "description": "X coordinate of the event relative to the main frame's viewport in CSS pixels.", ++ "type": "integer" ++ }, ++ { ++ "name": "y", ++ "description": "Y coordinate of the event relative to the main frame's viewport in CSS pixels. 0 refers to\nthe top of the viewport and Y increases as it proceeds towards the bottom of the viewport.", ++ "type": "integer" ++ }, ++ { ++ "name": "modifiers", ++ "description": "Bit field representing pressed modifier keys. Alt=1, Ctrl=2, Meta/Command=4, Shift=8\n(default: 0).", ++ "optional": true, ++ "type": "integer" ++ }, ++ { ++ "name": "button", ++ "description": "Mouse button (default: \"none\").", ++ "optional": true, ++ "type": "string", ++ "enum": [ ++ "none", ++ "left", ++ "middle", ++ "right", ++ "back", ++ "forward" ++ ] ++ }, ++ { ++ "name": "buttons", ++ "description": "A number indicating which buttons are pressed on the mouse when a mouse event is triggered.\nLeft=1, Right=2, Middle=4, Back=8, Forward=16, None=0.", ++ "optional": true, ++ "type": "integer" ++ }, ++ { ++ "name": "clickCount", ++ "description": "Number of times the mouse button was clicked (default: 0).", ++ "optional": true, ++ "type": "integer" ++ }, ++ { ++ "name": "deltaX", ++ "description": "X delta in CSS pixels for mouse wheel event (default: 0).", ++ "optional": true, ++ "type": "integer" ++ }, ++ { ++ "name": "deltaY", ++ "description": "Y delta in CSS pixels for mouse wheel event (default: 0).", ++ "optional": true, ++ "type": "integer" ++ } ++ ] ++ }, ++ { ++ "name": "dispatchTapEvent", ++ "description": "Dispatches a tap event to the page.", ++ "async": true, ++ "parameters": [ ++ { ++ "name": "x", ++ "description": "X coordinate of the event relative to the main frame's viewport in CSS pixels.", ++ "type": "integer" ++ }, ++ { ++ "name": "y", ++ "description": "Y coordinate of the event relative to the main frame's viewport in CSS pixels. 0 refers to\nthe top of the viewport and Y increases as it proceeds towards the bottom of the viewport.", ++ "type": "integer" ++ }, ++ { ++ "name": "modifiers", ++ "description": "Bit field representing pressed modifier keys. Alt=1, Ctrl=2, Meta/Command=4, Shift=8\n(default: 0).", ++ "optional": true, ++ "type": "integer" ++ } ++ ] ++ } ++ ] ++} +diff --git a/Source/JavaScriptCore/inspector/protocol/Network.json b/Source/JavaScriptCore/inspector/protocol/Network.json +index 65ab2092b0ffd0ead3da1ddccd398d4f4179f51a..2d9ef40a20df819193c9a5867fbf6f8f8bf46b48 100644 +--- a/Source/JavaScriptCore/inspector/protocol/Network.json ++++ b/Source/JavaScriptCore/inspector/protocol/Network.json +@@ -321,6 +321,13 @@ + { "name": "requestId", "$ref": "RequestId", "description": "Identifier for the intercepted Network request to fail." }, + { "name": "errorType", "$ref": "ResourceErrorType", "description": "Deliver error reason for the request failure." } + ] ++ }, ++ { ++ "name": "setEmulateOfflineState", ++ "description": "Emulate offline state overriding the actual state.", ++ "parameters": [ ++ { "name": "offline", "type": "boolean", "description": "True to emulate offline." } ++ ] + } + ], + "events": [ +diff --git a/Source/JavaScriptCore/inspector/protocol/Page.json b/Source/JavaScriptCore/inspector/protocol/Page.json +index db52479a72d459be23d4d8d080c0ed15ea9fc4c0..b77bec0ab30e8562ef16fa0b01a68ef7501a62eb 100644 +--- a/Source/JavaScriptCore/inspector/protocol/Page.json ++++ b/Source/JavaScriptCore/inspector/protocol/Page.json +@@ -27,7 +27,7 @@ + { + "id": "ResourceType", + "type": "string", +- "enum": ["Document", "StyleSheet", "Image", "Font", "Script", "XHR", "Fetch", "Ping", "Beacon", "WebSocket", "Other"], ++ "enum": ["Document", "StyleSheet", "Image", "Font", "Script", "XHR", "Fetch", "Ping", "Beacon", "WebSocket", "EventSource", "Other"], + "description": "Resource type as it was perceived by the rendering engine." + }, + { +@@ -112,6 +112,41 @@ + { "name": "secure", "type": "boolean", "description": "True if cookie is secure." }, + { "name": "sameSite", "$ref": "CookieSameSitePolicy", "description": "Cookie Same-Site policy." } + ] ++ }, ++ { ++ "id": "AXNode", ++ "type": "object", ++ "description": "Accessibility Node", ++ "properties": [ ++ { "name": "role", "type": "string", "description": "The role."}, ++ { "name": "name", "type": "string","optional": true, "description": "A human readable name for the node."}, ++ { "name": "value", "type": "any", "optional": true, "description": "The current value of the node."}, ++ { "name": "description", "type": "string", "optional": true, "description": "An additional human readable description of the node."}, ++ { "name": "keyshortcuts", "type": "string", "optional": true, "description": "Keyboard shortcuts associated with this node."}, ++ { "name": "roledescription", "type": "string", "optional": true, "description": "A human readable alternative to the role."}, ++ { "name": "valuetext", "type": "string", "optional": true, "description": "A description of the current value."}, ++ { "name": "disabled", "type": "boolean", "optional": true, "description": "Whether the node is disabled."}, ++ { "name": "expanded", "type": "boolean", "optional": true, "description": "Whether the node is expanded or collapsed."}, ++ { "name": "focused", "type": "boolean", "optional": true, "description": "Whether the node is focused."}, ++ { "name": "modal", "type": "boolean", "optional": true, "description": "Whether the node is modal."}, ++ { "name": "multiline", "type": "boolean", "optional": true, "description": "Whether the node text input supports multiline."}, ++ { "name": "multiselectable", "type": "boolean", "optional": true, "description": "Whether more than one child can be selected."}, ++ { "name": "readonly", "type": "boolean", "optional": true, "description": "Whether the node is read only."}, ++ { "name": "required", "type": "boolean", "optional": true, "description": "Whether the node is required."}, ++ { "name": "selected", "type": "boolean", "optional": true, "description": "Whether the node is selected in its parent node."}, ++ { "name": "checked", "type": "string", "optional": true, "enum": ["true", "false", "mixed"], "description": "Whether the checkbox is checked, or \"mixed\"."}, ++ { "name": "pressed", "type": "string", "optional": true, "enum": ["true", "false", "mixed"], "description": "Whether the toggle button is checked, or \"mixed\"."}, ++ { "name": "level", "type": "integer", "optional": true, "description": "The level of a heading."}, ++ { "name": "valuemin", "type": "number", "optional": true, "description": "The minimum value in a node."}, ++ { "name": "valuemax", "type": "number", "optional": true, "description": "The maximum value in a node."}, ++ { "name": "autocomplete", "type": "string", "optional": true, "description": "What kind of autocomplete is supported by a control."}, ++ { "name": "haspopup", "type": "string", "optional": true, "description": "What kind of popup is currently being shown for a node."}, ++ { "name": "invalid", "type": "string", "optional": true, "enum": ["true", "false", "grammar", "spelling"], "description": "Whether and in what way this node's value is invalid."}, ++ { "name": "orientation", "type": "string", "optional": true, "description": "Whether the node is oriented horizontally or vertically."}, ++ { "name": "focusable", "type": "boolean", "optional": true, "description": "Whether the node is focusable."}, ++ { "name": "children", "type": "array", "optional": true, "items": { "$ref": "AXNode"}, "description": "Child AXNodes of this node, if any."}, ++ { "name": "found", "type": "boolean", "optional": true, "description": "True if this AXNode corresponds with the ObjectId passed into acessibilitySnapshot."} ++ ] + } + ], + "commands": [ +@@ -131,6 +166,14 @@ + { "name": "revalidateAllResources", "type": "boolean", "optional": true, "description": "If true, all cached subresources will be revalidated when the main resource loads. Otherwise, only expired cached subresources will be revalidated (the default behavior for most WebKit clients)." } + ] + }, ++ { ++ "name": "goBack", ++ "description": "Goes back in the history." ++ }, ++ { ++ "name": "goForward", ++ "description": "Goes forward in the history." ++ }, + { + "name": "navigate", + "description": "Navigates current page to the given URL.", +@@ -270,6 +313,20 @@ + { "name": "appearance", "$ref": "Appearance", "optional": true } + ] + }, ++ { ++ "name": "setTimeZone", ++ "description": "Enables time zone emulation.", ++ "parameters": [ ++ { "name": "timeZone", "type": "string", "optional": true } ++ ] ++ }, ++ { ++ "name": "setTouchEmulationEnabled", ++ "description": "Enables touch events on platforms that lack them.", ++ "parameters": [ ++ {"name": "enabled", "type": "boolean", "description": "Whether touch should be enabled."} ++ ] ++ }, + { + "name": "snapshotNode", + "description": "Capture a snapshot of the specified node that does not include unrelated layers.", +@@ -308,12 +365,67 @@ + { + "name": "setScreenSizeOverride", + "description": "Overrides screen size exposed to DOM and used in media queries for testing with provided values.", +- "condition": "!(defined(WTF_PLATFORM_COCOA) && WTF_PLATFORM_COCOA)", + "targetTypes": ["page"], + "parameters": [ + { "name": "width", "type": "integer", "description": "Screen width", "optional": true }, + { "name": "height", "type": "integer", "description": "Screen height", "optional": true } + ] ++ }, ++ { ++ "name": "insertText", ++ "description": "Insert text into the current selection of the page.", ++ "parameters": [ ++ { "name": "text", "type": "string", "description": "Text to insert." } ++ ] ++ }, ++ { ++ "name": "accessibilitySnapshot", ++ "description": "Serializes and returns all of the accessibility nodes of the page.", ++ "parameters": [ ++ { "name": "objectId", "type": "string", "optional": true, "description": "Object Id of a node to find in the accessibility tree."} ++ ], ++ "returns": [ ++ { "name": "axNode", "$ref": "AXNode", "description": "The root AXNode."} ++ ] ++ }, ++ { ++ "name": "setInterceptFileChooserDialog", ++ "description": "Intercepts file chooser dialog", ++ "parameters": [ ++ { "name": "enabled", "type": "boolean", "description": "True to enable." } ++ ] ++ }, ++ { ++ "name": "setDefaultBackgroundColorOverride", ++ "description": "Sets or clears an override of the default background color of the frame. This override is used if the content does not specify one.", ++ "parameters": [ ++ { "name": "color", "$ref": "DOM.RGBAColor", "optional": true, "description": "RGBA of the default background color. If not specified, any existing override will be cleared." } ++ ] ++ }, ++ { ++ "name": "createUserWorld", ++ "description": "Creates an user world for every loaded frame.", ++ "parameters": [ ++ { "name": "name", "type": "string", "description": "Isolated world name, will be used as an execution context name." } ++ ] ++ }, ++ { ++ "name": "setBypassCSP", ++ "description": "Enable page Content Security Policy by-passing.", ++ "parameters": [ ++ { "name": "enabled", "type": "boolean", "description": "Whether to bypass page CSP." } ++ ] ++ }, ++ { ++ "name": "crash", ++ "description": "Crashes the page process" ++ }, ++ { ++ "name": "setOrientationOverride", ++ "description": "Overrides window.orientation with provided value.", ++ "parameters": [ ++ { "name": "angle", "type": "integer", "optional": true } ++ ] + } + ], + "events": [ +@@ -321,14 +433,16 @@ + "name": "domContentEventFired", + "targetTypes": ["page"], + "parameters": [ +- { "name": "timestamp", "type": "number" } ++ { "name": "timestamp", "type": "number" }, ++ { "name": "frameId", "$ref": "Network.FrameId", "description": "Id of the frame that has fired DOMContentLoaded event." } + ] + }, + { + "name": "loadEventFired", + "targetTypes": ["page"], + "parameters": [ +- { "name": "timestamp", "type": "number" } ++ { "name": "timestamp", "type": "number" }, ++ { "name": "frameId", "$ref": "Network.FrameId", "description": "Id of the frame that has fired load event." } + ] + }, + { +@@ -338,6 +452,14 @@ + { "name": "frame", "$ref": "Frame", "description": "Frame object." } + ] + }, ++ { ++ "name": "frameAttached", ++ "description": "Fired when frame has been attached to its parent.", ++ "parameters": [ ++ { "name": "frameId", "$ref": "Network.FrameId", "description": "Id of the frame that has been detached." }, ++ { "name": "parentFrameId", "$ref": "Network.FrameId", "optional": true, "description": "Parent frame id if non-root." } ++ ] ++ }, + { + "name": "frameDetached", + "description": "Fired when frame has been detached from its parent.", +@@ -377,6 +499,22 @@ + { "name": "frameId", "$ref": "Network.FrameId", "description": "Id of the frame that has cleared its scheduled navigation." } + ] + }, ++ { ++ "name": "navigatedWithinDocument", ++ "description": "Fired when same-document navigation happens, e.g. due to history API usage or anchor navigation.", ++ "parameters": [ ++ { ++ "name": "frameId", ++ "description": "Id of the frame.", ++ "$ref": "Network.FrameId" ++ }, ++ { ++ "name": "url", ++ "description": "Frame's new url.", ++ "type": "string" ++ } ++ ] ++ }, + { + "name": "defaultAppearanceDidChange", + "description": "Fired when page's default appearance changes, even if there is a forced appearance.", +@@ -385,6 +523,28 @@ + "parameters": [ + { "name": "appearance", "$ref": "Appearance", "description": "Name of the appearance that is active (not considering any forced appearance.)" } + ] ++ }, ++ { ++ "name": "willRequestOpenWindow", ++ "description": "Fired when page tries to open a new window.", ++ "parameters": [ ++ { "name": "url", "type": "string" } ++ ] ++ }, ++ { ++ "name": "didRequestOpenWindow", ++ "description": "Fired after page did try to open a new window.", ++ "parameters": [ ++ { "name": "opened", "type": "boolean" } ++ ] ++ }, ++ { ++ "name": "fileChooserOpened", ++ "description": "Fired when the page shows file chooser for it's .", ++ "parameters": [ ++ { "name": "frameId", "$ref": "Network.FrameId", "description": "Frame where file chooser is opened." }, ++ { "name": "element", "$ref": "Runtime.RemoteObject", "description": "Input element." } ++ ] + } + ] + } +diff --git a/Source/JavaScriptCore/inspector/protocol/Playwright.json b/Source/JavaScriptCore/inspector/protocol/Playwright.json +new file mode 100644 +index 0000000000000000000000000000000000000000..ce69bc6a10b49460c73110e54b2936afe5dd4ebf +--- /dev/null ++++ b/Source/JavaScriptCore/inspector/protocol/Playwright.json +@@ -0,0 +1,244 @@ ++{ ++ "domain": "Playwright", ++ "availability": ["web"], ++ "types": [ ++ { ++ "id": "ContextID", ++ "type": "string", ++ "description": "Id of Browser context." ++ }, ++ { ++ "id": "PageProxyID", ++ "type": "string", ++ "description": "Id of WebPageProxy." ++ }, ++ { ++ "id": "CookieSameSitePolicy", ++ "type": "string", ++ "enum": ["None", "Lax", "Strict"], ++ "description": "Same-Site policy of a cookie." ++ }, ++ { ++ "id": "Cookie", ++ "type": "object", ++ "description": "Cookie object", ++ "properties": [ ++ { "name": "name", "type": "string", "description": "Cookie name." }, ++ { "name": "value", "type": "string", "description": "Cookie value." }, ++ { "name": "domain", "type": "string", "description": "Cookie domain." }, ++ { "name": "path", "type": "string", "description": "Cookie path." }, ++ { "name": "expires", "type": "number", "description": "Cookie expires." }, ++ { "name": "httpOnly", "type": "boolean", "description": "True if cookie is http-only." }, ++ { "name": "secure", "type": "boolean", "description": "True if cookie is secure." }, ++ { "name": "session", "type": "boolean", "description": "True if cookie is session cookie." }, ++ { "name": "sameSite", "$ref": "CookieSameSitePolicy", "description": "Cookie Same-Site policy." } ++ ] ++ }, ++ { ++ "id": "SetCookieParam", ++ "type": "object", ++ "description": "Cookie object", ++ "properties": [ ++ { "name": "name", "type": "string", "description": "Cookie name." }, ++ { "name": "value", "type": "string", "description": "Cookie value." }, ++ { "name": "domain", "type": "string", "description": "Cookie domain." }, ++ { "name": "path", "type": "string", "description": "Cookie path." }, ++ { "name": "expires", "type": "number", "optional": true, "description": "Cookie expires." }, ++ { "name": "httpOnly", "type": "boolean", "optional": true, "description": "True if cookie is http-only." }, ++ { "name": "secure", "type": "boolean", "optional": true, "description": "True if cookie is secure." }, ++ { "name": "session", "type": "boolean", "optional": true, "description": "True if cookie is session cookie." }, ++ { "name": "sameSite", "$ref": "CookieSameSitePolicy", "optional": true, "description": "Cookie Same-Site policy." } ++ ] ++ }, ++ { ++ "id": "Geolocation", ++ "type": "object", ++ "description": "Geolocation", ++ "properties": [ ++ { "name": "timestamp", "type": "number", "description": "Mock latitude" }, ++ { "name": "latitude", "type": "number", "description": "Mock latitude" }, ++ { "name": "longitude", "type": "number", "description": "Mock longitude" }, ++ { "name": "accuracy", "type": "number", "description": "Mock accuracy" } ++ ] ++ } ++ ], ++ "commands": [ ++ { ++ "name": "enable" ++ }, ++ { ++ "name": "disable" ++ }, ++ { ++ "name": "close", ++ "async": true, ++ "description": "Close browser." ++ }, ++ { ++ "name": "createContext", ++ "description": "Creates new ephemeral browser context.", ++ "parameters": [ ++ { "name": "proxyServer", "type": "string", "optional": true, "description": "Proxy server, similar to the one passed to --proxy-server" }, ++ { "name": "proxyBypassList", "type": "string", "optional": true, "description": "Proxy bypass list, similar to the one passed to --proxy-bypass-list" } ++ ], ++ "returns": [ ++ { "name": "browserContextId", "$ref": "ContextID", "description": "Unique identifier of the context." } ++ ] ++ }, ++ { ++ "name": "deleteContext", ++ "async": true, ++ "description": "Deletes browser context previously created with createContect. The command will automatically close all pages that use the context.", ++ "parameters": [ ++ { "name": "browserContextId", "$ref": "ContextID", "description": "Identifier of the context to delete." } ++ ] ++ }, ++ { ++ "name": "createPage", ++ "parameters": [ ++ { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "JSON Inspector Protocol message (command) to be dispatched on the backend." } ++ ], ++ "returns": [ ++ { "name": "pageProxyId", "$ref": "PageProxyID", "description": "Unique identifier of the page proxy." } ++ ] ++ }, ++ { ++ "name": "navigate", ++ "async": true, ++ "description": "Navigates current page to the given URL.", ++ "parameters": [ ++ { "name": "url", "type": "string", "description": "URL to navigate the page to." }, ++ { "name": "pageProxyId", "$ref": "PageProxyID", "description": "Unique identifier of the page proxy." }, ++ { "name": "frameId", "$ref": "Network.FrameId", "optional": true, "description": "Id of the frame to navigate."}, ++ { "name": "referrer", "type": "string", "optional": true, "description": "Referrer URL." } ++ ], ++ "returns": [ ++ { "name": "loaderId", "$ref": "Network.LoaderId", "optional": true, "description": "Identifier of the loader associated with the navigation." } ++ ] ++ }, ++ { ++ "name": "setIgnoreCertificateErrors", ++ "description": "Change whether all certificate errors should be ignored.", ++ "parameters": [ ++ { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." }, ++ { "name": "ignore", "type": "boolean" } ++ ] ++ }, ++ { ++ "name": "getAllCookies", ++ "description": "Returns all cookies in the given browser context.", ++ "async": true, ++ "parameters": [ ++ { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." } ++ ], ++ "returns": [ ++ { "name": "cookies", "type": "array", "items": { "$ref": "Cookie" }, "description": "Cookies." } ++ ] ++ }, ++ { ++ "name": "setCookies", ++ "description": "Sets cookies in the given browser context.", ++ "async": true, ++ "parameters": [ ++ { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." }, ++ { "name": "cookies", "type": "array", "items": { "$ref": "SetCookieParam" }, "description": "Cookies." } ++ ] ++ }, ++ { ++ "name": "deleteAllCookies", ++ "description": "Deletes cookies in the given browser context.", ++ "async": true, ++ "parameters": [ ++ { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." } ++ ] ++ }, ++ { ++ "name": "setGeolocationOverride", ++ "parameters": [ ++ { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." }, ++ { "name": "geolocation", "$ref": "Geolocation", "optional": true, "description": "Geolocation to set, if missing emulates position unavailable." } ++ ], ++ "description": "Overrides the geolocation position or error." ++ }, ++ { ++ "name": "setLanguages", ++ "description": "Allows to set locale language for context.", ++ "parameters": [ ++ { "name": "languages", "type": "array", "items": { "type": "string" } }, ++ { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." } ++ ] ++ }, ++ { ++ "name": "setDownloadBehavior", ++ "description": "Allows to override download behavior.", ++ "parameters": [ ++ { "name": "behavior", "optional": true, "type": "string", "enum": ["allow", "deny"] }, ++ { "name": "downloadPath", "optional": true, "type": "string" }, ++ { "name": "browserContextId", "$ref": "ContextID", "optional": true, "description": "Browser context id." } ++ ] ++ } ++ ], ++ "events": [ ++ { ++ "name": "pageProxyCreated", ++ "parameters": [ ++ { "name": "browserContextId", "$ref": "ContextID", "description": "Unique identifier of the context." }, ++ { "name": "pageProxyId", "$ref": "PageProxyID" }, ++ { "name": "openerId", "$ref": "PageProxyID", "optional": true, "description": "Unique identifier of the opening page. Only set for pages created by window.open()." } ++ ] ++ }, ++ { ++ "name": "pageProxyDestroyed", ++ "parameters": [ ++ { "name": "pageProxyId", "$ref": "PageProxyID" } ++ ] ++ }, ++ { ++ "name": "provisionalLoadFailed", ++ "description": "Fired when provisional load fails.", ++ "parameters": [ ++ { "name": "pageProxyId", "$ref": "PageProxyID", "description": "Unique identifier of the page proxy." }, ++ { "name": "loaderId", "$ref": "Network.LoaderId", "description": "Identifier of the loader associated with the navigation." }, ++ { "name": "error", "type": "string", "description": "Localized error string." } ++ ] ++ }, ++ { ++ "name": "windowOpen", ++ "description": "Fired when page opens a new window.", ++ "parameters": [ ++ { "name": "pageProxyId", "$ref": "PageProxyID", "description": "Unique identifier of the page proxy." }, ++ { "name": "url", "type": "string" }, ++ { "name": "windowFeatures", "type": "array", "items": { "type": "string" } } ++ ] ++ }, ++ { ++ "name": "downloadCreated", ++ "parameters": [ ++ { "name": "pageProxyId", "$ref": "PageProxyID", "description": "Unique identifier of the page proxy." }, ++ { "name": "frameId", "$ref": "Network.FrameId", "description": "Unique identifier of the originating frame." }, ++ { "name": "uuid", "type": "string" }, ++ { "name": "url", "type": "string" } ++ ] ++ }, ++ { ++ "name": "downloadFilenameSuggested", ++ "parameters": [ ++ { "name": "uuid", "type": "string" }, ++ { "name": "suggestedFilename", "type": "string" } ++ ] ++ }, ++ { ++ "name": "downloadFinished", ++ "parameters": [ ++ { "name": "uuid", "type": "string" }, ++ { "name": "error", "type": "string" } ++ ] ++ }, ++ { ++ "name": "screencastFinished", ++ "parameters": [ ++ { "name": "screencastId", "$ref": "Screencast.ScreencastId", "description": "Unique identifier of the screencast." } ++ ] ++ } ++ ] ++} +diff --git a/Source/JavaScriptCore/inspector/protocol/Screencast.json b/Source/JavaScriptCore/inspector/protocol/Screencast.json +new file mode 100644 +index 0000000000000000000000000000000000000000..a51b42b2a2b575927509e11dc7241ab6f203c104 +--- /dev/null ++++ b/Source/JavaScriptCore/inspector/protocol/Screencast.json +@@ -0,0 +1,31 @@ ++{ ++ "domain": "Screencast", ++ "availability": ["web"], ++ "types": [ ++ { ++ "id": "ScreencastId", ++ "type": "string", ++ "description": "Unique identifier of the screencast." ++ } ++ ], ++ "commands": [ ++ { ++ "name": "start", ++ "description": "Starts recoring video to speified file.", ++ "parameters": [ ++ { "name": "file", "type": "string", "description": "Output file location." }, ++ { "name": "width", "type": "integer" }, ++ { "name": "height", "type": "integer" }, ++ { "name": "scale", "type": "number", "optional": true } ++ ], ++ "returns": [ ++ { "name": "screencastId", "$ref": "ScreencastId", "description": "Unique identifier of the screencast." } ++ ] ++ }, ++ { ++ "name": "stop", ++ "async": true, ++ "description": "Stops recoding video. Returns after the file has been closed." ++ } ++ ] ++} +diff --git a/Source/JavaScriptCore/inspector/protocol/Target.json b/Source/JavaScriptCore/inspector/protocol/Target.json +index 52920cded24a9c6b0ef6fb4e518664955db4f9fa..bbbabc4e7259088b9404e8cc07eecd6f45077da0 100644 +--- a/Source/JavaScriptCore/inspector/protocol/Target.json ++++ b/Source/JavaScriptCore/inspector/protocol/Target.json +@@ -10,7 +10,7 @@ + "properties": [ + { "name": "targetId", "type": "string", "description": "Unique identifier for the target." }, + { "name": "type", "type": "string", "enum": ["page", "service-worker", "worker"] }, +- { "name": "isProvisional", "type": "boolean", "optional": true, "description": "Whether this is a provisional page target." }, ++ { "name": "isProvisional", "type": "boolean", "optional": true, "description": "True value indicates that this is a provisional page target i.e. Such target may be created when current page starts cross-origin navigation. Eventually each provisional target is either committed and swaps with the current target or gets destroyed, e.g. in case of load request failure." }, + { "name": "isPaused", "type": "boolean", "optional": true, "description": "Whether the target is paused on start and has to be explicitely resumed by inspector." } + ] + } +@@ -37,6 +37,21 @@ + { "name": "targetId", "type": "string" }, + { "name": "message", "type": "string", "description": "JSON Inspector Protocol message (command) to be dispatched on the backend." } + ] ++ }, ++ { ++ "name": "activate", ++ "description": "Reveals the target on screen.", ++ "parameters": [ ++ { "name": "targetId", "type": "string" } ++ ] ++ }, ++ { ++ "name": "close", ++ "description": "Closes the target.", ++ "parameters": [ ++ { "name": "targetId", "type": "string" }, ++ { "name": "runBeforeUnload", "type": "boolean", "optional": true } ++ ] + } + ], + "events": [ +@@ -49,7 +64,8 @@ + { + "name": "targetDestroyed", + "parameters": [ +- { "name": "targetId", "type": "string" } ++ { "name": "targetId", "type": "string" }, ++ { "name": "crashed", "type": "boolean" } + ] + }, + { +diff --git a/Source/JavaScriptCore/inspector/protocol/Worker.json b/Source/JavaScriptCore/inspector/protocol/Worker.json +index 638612413466efc87b737e8a81042ed07ca12703..6f9e518ff0bfa2a6228675d25b6b785f1ed3022a 100644 +--- a/Source/JavaScriptCore/inspector/protocol/Worker.json ++++ b/Source/JavaScriptCore/inspector/protocol/Worker.json +@@ -16,7 +16,7 @@ + "description": "Sent after the frontend has sent all initialization messages and can resume this worker. This command is required to allow execution in the worker.", + "parameters": [ + { "name": "workerId", "type": "string" } +- ] ++ ] + }, + { + "name": "sendMessageToWorker", +@@ -33,7 +33,8 @@ + "parameters": [ + { "name": "workerId", "type": "string" }, + { "name": "url", "type": "string" }, +- { "name": "name", "type": "string" } ++ { "name": "name", "type": "string" }, ++ { "name": "frameId", "$ref": "Network.FrameId", "description": "Id of the frame this worker belongs to." } + ] + }, + { +diff --git a/Source/JavaScriptCore/runtime/DateConversion.cpp b/Source/JavaScriptCore/runtime/DateConversion.cpp +index 955756ba405f400970610f9a68c7ed42a67cb015..1520c0a1475a90de2795e4ccd8919c1bb1384066 100644 +--- a/Source/JavaScriptCore/runtime/DateConversion.cpp ++++ b/Source/JavaScriptCore/runtime/DateConversion.cpp +@@ -100,17 +100,23 @@ String formatDateTime(const GregorianDateTime& t, DateTimeFormat format, bool as + appendNumber<2>(builder, offset / 60); + appendNumber<2>(builder, offset % 60); + +-#if OS(WINDOWS) +- TIME_ZONE_INFORMATION timeZoneInformation; +- GetTimeZoneInformation(&timeZoneInformation); +- const WCHAR* winTimeZoneName = t.isDST() ? timeZoneInformation.DaylightName : timeZoneInformation.StandardName; +- String timeZoneName(winTimeZoneName); ++ String timeZoneName; ++ if (!WTF::timeZoneDisplayNameForAutomation().isEmpty()) { ++ timeZoneName = WTF::timeZoneDisplayNameForAutomation(); ++ } else { ++ #if OS(WINDOWS) ++ TIME_ZONE_INFORMATION timeZoneInformation; ++ GetTimeZoneInformation(&timeZoneInformation); ++ const WCHAR* winTimeZoneName = t.isDST() ? timeZoneInformation.DaylightName : timeZoneInformation.StandardName; ++ timeZoneName = String(winTimeZoneName); + #else +- struct tm gtm = t; +- char timeZoneName[70]; +- strftime(timeZoneName, sizeof(timeZoneName), "%Z", >m); ++ struct tm gtm = t; ++ char tzName[70]; ++ strftime(tzName, sizeof(tzName), "%Z", >m); ++ timeZoneName = String(tzName); + #endif +- if (timeZoneName[0]) { ++ } ++ if (!timeZoneName.isEmpty()) { + builder.appendLiteral(" ("); + builder.append(timeZoneName); + builder.append(')'); +diff --git a/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp b/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp +index a17a9c204925b077c2c3f8ef973a996bcae2719b..bd48bd57ab21ee53136111e83614f35cb854ef4c 100644 +--- a/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp ++++ b/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp +@@ -35,6 +35,7 @@ + #include + #include + #include ++#include + #include + #include + +diff --git a/Source/JavaScriptCore/runtime/JSDateMath.cpp b/Source/JavaScriptCore/runtime/JSDateMath.cpp +index 0df4ba0b078a122e33b8bff707ae808e55284584..7f9ceb68cfbff4dc5ab7fecb644ada5fb12b7dca 100644 +--- a/Source/JavaScriptCore/runtime/JSDateMath.cpp ++++ b/Source/JavaScriptCore/runtime/JSDateMath.cpp +@@ -75,6 +75,7 @@ + #include "ExceptionHelpers.h" + #include "VM.h" + #include ++#include + + // icu::TimeZone and icu::BasicTimeZone features are only available in ICU C++ APIs. + // We use these C++ APIs as an exception. +@@ -284,6 +285,10 @@ double DateCache::parseDate(JSGlobalObject* globalObject, VM& vm, const String& + // https://tc39.es/ecma402/#sec-defaulttimezone + String DateCache::defaultTimeZone() + { ++ String tz = WTF::timeZoneForAutomation(); ++ if (!tz.isEmpty()) ++ return tz; ++ + icu::UnicodeString timeZoneID; + icu::UnicodeString canonicalTimeZoneID; + auto& timeZone = *bitwise_cast(timeZoneCache()); +@@ -315,7 +320,9 @@ void DateCache::timeZoneCacheSlow() + { + // Do not use icu::TimeZone::createDefault. ICU internally has a cache for timezone and createDefault returns this cached value. + ASSERT(!m_timeZoneCache); +- m_timeZoneCache = std::unique_ptr(bitwise_cast(icu::TimeZone::detectHostTimeZone())); ++ String override = WTF::timeZoneForAutomation(); ++ auto* timezone = override.isEmpty() ? icu::TimeZone::detectHostTimeZone() : icu::TimeZone::createTimeZone(override.utf8().data()); ++ m_timeZoneCache = std::unique_ptr(bitwise_cast(timezone)); + } + + void DateCache::reset() +diff --git a/Source/ThirdParty/libwebrtc/CMakeLists.txt b/Source/ThirdParty/libwebrtc/CMakeLists.txt +index cc007616a999989c8e1c4134bd3888678c0abf03..660501e258342331395c8d861dbb636265770f51 100644 +--- a/Source/ThirdParty/libwebrtc/CMakeLists.txt ++++ b/Source/ThirdParty/libwebrtc/CMakeLists.txt +@@ -291,6 +291,11 @@ set(webrtc_SOURCES + Source/third_party/jsoncpp/source/src/lib_json/json_reader.cpp + Source/third_party/jsoncpp/source/src/lib_json/json_value.cpp + Source/third_party/jsoncpp/source/src/lib_json/json_writer.cpp ++# Playwright begin ++ Source/third_party/libwebm/mkvmuxer/mkvmuxer.cc ++ Source/third_party/libwebm/mkvmuxer/mkvmuxerutil.cc ++ Source/third_party/libwebm/mkvmuxer/mkvwriter.cc ++# Playwright end + Source/third_party/libyuv/source/compare.cc + Source/third_party/libyuv/source/compare_common.cc + Source/third_party/libyuv/source/compare_gcc.cc +@@ -1494,6 +1499,9 @@ target_include_directories(webrtc PRIVATE + Source/third_party/libsrtp/config + Source/third_party/libsrtp/crypto/include + Source/third_party/libsrtp/include ++# Playwright begin ++ Source/third_party/libwebm ++# Playwright end + Source/third_party/libyuv/include + Source/third_party/opus/src/celt + Source/third_party/opus/src/include +diff --git a/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.mac.exp b/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.mac.exp +index f5937960adc8d175179b1cdaf7e24c0c2e11e4e6..0387a2b16a821b0934bddc6324986475b212b209 100644 +--- a/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.mac.exp ++++ b/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.mac.exp +@@ -317,3 +317,23 @@ __ZN6webrtc23RtpTransceiverInterface29SetOfferedRtpHeaderExtensionsEN3rtc9ArrayV + __ZN6webrtc23RtpTransceiverInterface4StopEv + __ZNK6webrtc23RtpTransceiverInterface23HeaderExtensionsToOfferEv + __ZNK6webrtc23RtpTransceiverInterface8stoppingEv ++__ZN8mkvmuxer11SegmentInfo15set_writing_appEPKc ++__ZN8mkvmuxer11SegmentInfo4InitEv ++__ZN8mkvmuxer7Segment10OutputCuesEb ++__ZN8mkvmuxer7Segment13AddVideoTrackEiii ++__ZN8mkvmuxer7Segment4InitEPNS_10IMkvWriterE ++__ZN8mkvmuxer7Segment8AddFrameEPKhyyyb ++__ZN8mkvmuxer7Segment8FinalizeEv ++__ZN8mkvmuxer7SegmentC1Ev ++__ZN8mkvmuxer7SegmentD1Ev ++__ZN8mkvmuxer9MkvWriterC1EP7__sFILE ++_ARGBToI420 ++_vpx_codec_enc_config_default ++_vpx_codec_enc_init_ver ++_vpx_codec_encode ++_vpx_codec_err_to_string ++_vpx_codec_error ++_vpx_codec_get_cx_data ++_vpx_codec_iface_name ++_vpx_codec_version_str ++_vpx_codec_vp8_cx +diff --git a/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.xcconfig b/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.xcconfig +index 41d5e34701fe5b24f10089440576e8e8d14003ef..ace72d31f4761b5f6da9aac6571b0186d7517fac 100644 +--- a/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.xcconfig ++++ b/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.xcconfig +@@ -41,7 +41,7 @@ DYLIB_INSTALL_NAME_BASE_WK_RELOCATABLE_FRAMEWORKS_ = $(DYLIB_INSTALL_NAME_BASE); + DYLIB_INSTALL_NAME_BASE_WK_RELOCATABLE_FRAMEWORKS_YES = @loader_path/../../../; + + GCC_WARN_64_TO_32_BIT_CONVERSION = NO; +-HEADER_SEARCH_PATHS = Source Source/third_party/jsoncpp/source/include Source/third_party/libsrtp/crypto/include Source/third_party/libsrtp/include Source/third_party/boringssl/src/include Source/third_party/libyuv/include Source/third_party/usrsctp Source/third_party/usrsctp/usrsctplib Source/third_party/usrsctp/usrsctplib/usrsctplib Source/webrtc/sdk/objc/Framework/Headers Source/webrtc/common_audio/signal_processing/include Source/webrtc/modules/audio_coding/codecs/isac/main/include Source/third_party/opus/src/celt Source/third_party/opus/src/include Source/third_party/opus/src/src Source/webrtc/modules/audio_device/mac Source/third_party/usrsctp/usrsctplib/usrsctplib/netinet Source/webrtc/modules/audio_device/ios Source/webrtc Source/webrtc/sdk/objc Source/webrtc/sdk/objc/base Source/webrtc/sdk/objc/Framework/Classes Source/third_party/libsrtp/config Source/webrtc/sdk/objc/Framework/Classes/Common Source/webrtc/sdk/objc/Framework/Classes/Video Source/webrtc/sdk/objc/Framework/Classes/PeerConnection Source/third_party/abseil-cpp Source/third_party/libvpx/source/libvpx Source/third_party/libwebm/webm_parser/include; ++HEADER_SEARCH_PATHS = Source Source/third_party/jsoncpp/source/include Source/third_party/libsrtp/crypto/include Source/third_party/libsrtp/include Source/third_party/boringssl/src/include Source/third_party/libyuv/include Source/third_party/usrsctp Source/third_party/usrsctp/usrsctplib Source/third_party/usrsctp/usrsctplib/usrsctplib Source/webrtc/sdk/objc/Framework/Headers Source/webrtc/common_audio/signal_processing/include Source/webrtc/modules/audio_coding/codecs/isac/main/include Source/third_party/opus/src/celt Source/third_party/opus/src/include Source/third_party/opus/src/src Source/webrtc/modules/audio_device/mac Source/third_party/usrsctp/usrsctplib/usrsctplib/netinet Source/webrtc/modules/audio_device/ios Source/webrtc Source/webrtc/sdk/objc Source/webrtc/sdk/objc/base Source/webrtc/sdk/objc/Framework/Classes Source/third_party/libsrtp/config Source/webrtc/sdk/objc/Framework/Classes/Common Source/webrtc/sdk/objc/Framework/Classes/Video Source/webrtc/sdk/objc/Framework/Classes/PeerConnection Source/third_party/abseil-cpp Source/third_party/libvpx/source/libvpx Source/third_party/libwebm/webm_parser/include Source/third_party/libvpx/source/libvpx/third_party/libwebm; + + PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/libwebrtc; + USE_HEADERMAP = NO; +diff --git a/Source/ThirdParty/libwebrtc/libwebrtc.xcodeproj/project.pbxproj b/Source/ThirdParty/libwebrtc/libwebrtc.xcodeproj/project.pbxproj +index d855b14cbc6717e9759e201642ea6ca2d1c2d094..1f946b94bd26d99711a2a1d213d437669931257b 100644 +--- a/Source/ThirdParty/libwebrtc/libwebrtc.xcodeproj/project.pbxproj ++++ b/Source/ThirdParty/libwebrtc/libwebrtc.xcodeproj/project.pbxproj +@@ -3803,6 +3803,9 @@ + CDFD2FCC24C4DAF70048DAC3 /* reader.h in Copy webm headers */ = {isa = PBXBuildFile; fileRef = CDEBB40524C0191A00ADBD44 /* reader.h */; }; + CDFD2FCD24C4DAF70048DAC3 /* status.h in Copy webm headers */ = {isa = PBXBuildFile; fileRef = CDEBB40624C0191A00ADBD44 /* status.h */; }; + CDFD2FCE24C4DAF70048DAC3 /* webm_parser.h in Copy webm headers */ = {isa = PBXBuildFile; fileRef = CDEBB40824C0191A00ADBD44 /* webm_parser.h */; }; ++ F3B7819924C7CC5200FCB122 /* mkvmuxerutil.cc in Sources */ = {isa = PBXBuildFile; fileRef = F3B7819624C7CC5100FCB122 /* mkvmuxerutil.cc */; }; ++ F3B7819A24C7CC5200FCB122 /* mkvmuxer.cc in Sources */ = {isa = PBXBuildFile; fileRef = F3B7819724C7CC5200FCB122 /* mkvmuxer.cc */; }; ++ F3B7819B24C7CC5200FCB122 /* mkvwriter.cc in Sources */ = {isa = PBXBuildFile; fileRef = F3B7819824C7CC5200FCB122 /* mkvwriter.cc */; }; + /* End PBXBuildFile section */ + + /* Begin PBXBuildRule section */ +@@ -8246,6 +8249,9 @@ + CDEBB49D24C0191A00ADBD44 /* master_parser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = master_parser.h; sourceTree = ""; }; + CDFD2F9624C4B2F90048DAC3 /* vp9_header_parser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = vp9_header_parser.h; sourceTree = ""; }; + CDFD2F9A24C4B2F90048DAC3 /* vp9_header_parser.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = vp9_header_parser.cc; sourceTree = ""; }; ++ F3B7819624C7CC5100FCB122 /* mkvmuxerutil.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = mkvmuxerutil.cc; path = mkvmuxer/mkvmuxerutil.cc; sourceTree = ""; }; ++ F3B7819724C7CC5200FCB122 /* mkvmuxer.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = mkvmuxer.cc; path = mkvmuxer/mkvmuxer.cc; sourceTree = ""; }; ++ F3B7819824C7CC5200FCB122 /* mkvwriter.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = mkvwriter.cc; path = mkvmuxer/mkvwriter.cc; sourceTree = ""; }; + FB39D0D11200F0E300088E69 /* libwebrtc.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libwebrtc.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; + /* End PBXFileReference section */ + +@@ -15116,6 +15122,7 @@ + isa = PBXGroup; + children = ( + CDFD2F9224C4B2F90048DAC3 /* common */, ++ F3B7819524C7CC1300FCB122 /* mkvmuxer */, + CDEBB19224C0191800ADBD44 /* webm_parser */, + ); + path = libwebm; +@@ -15250,6 +15257,16 @@ + path = common; + sourceTree = ""; + }; ++ F3B7819524C7CC1300FCB122 /* mkvmuxer */ = { ++ isa = PBXGroup; ++ children = ( ++ F3B7819724C7CC5200FCB122 /* mkvmuxer.cc */, ++ F3B7819624C7CC5100FCB122 /* mkvmuxerutil.cc */, ++ F3B7819824C7CC5200FCB122 /* mkvwriter.cc */, ++ ); ++ name = mkvmuxer; ++ sourceTree = ""; ++ }; + FB39D06E1200ED9200088E69 = { + isa = PBXGroup; + children = ( +@@ -17320,7 +17337,7 @@ + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; +- shellScript = "PRIVATE_HEADERS_FOLDER_PATH=usr/local/include\n\nif [[ \"${DEPLOYMENT_LOCATION}\" == \"NO\" ]]; then\n PRIVATE_HEADERS_PATH=\"${TARGET_BUILD_DIR%/}/${PRIVATE_HEADERS_FOLDER_PATH}\"\nelse\n PRIVATE_HEADERS_PATH=\"${DSTROOT}${INSTALL_PATH_PREFIX%/}/${PRIVATE_HEADERS_FOLDER_PATH}\"\nfi;\n\nmkdir -p \"${PRIVATE_HEADERS_PATH}\"\n\nrsync -av --no-owner --no-group --prune-empty-dirs --exclude \".svn\" --exclude \"usr\" --include \"*/\" --include \"*.h\" --exclude \"*\" \"${SRCROOT}/Source/webrtc\" \"${PRIVATE_HEADERS_PATH}\"\n\nrsync -av --no-owner --no-group --prune-empty-dirs --exclude \".svn\" --exclude \"usr\" --include \"*/\" --include \"*.h\" --exclude \"*\" \"${SRCROOT}/Source/third_party/abseil-cpp/absl\" \"${PRIVATE_HEADERS_PATH}\"\n"; ++ shellScript = "PRIVATE_HEADERS_FOLDER_PATH=usr/local/include\n\nif [[ \"${DEPLOYMENT_LOCATION}\" == \"NO\" ]]; then\n PRIVATE_HEADERS_PATH=\"${TARGET_BUILD_DIR%/}/${PRIVATE_HEADERS_FOLDER_PATH}\"\nelse\n PRIVATE_HEADERS_PATH=\"${DSTROOT}${INSTALL_PATH_PREFIX%/}/${PRIVATE_HEADERS_FOLDER_PATH}\"\nfi;\n\nmkdir -p \"${PRIVATE_HEADERS_PATH}\"\n\nrsync -av --no-owner --no-group --prune-empty-dirs --exclude \".svn\" --exclude \"usr\" --include \"*/\" --include \"*.h\" --exclude \"*\" \"${SRCROOT}/Source/webrtc\" \"${PRIVATE_HEADERS_PATH}\"\n\nrsync -av --no-owner --no-group --prune-empty-dirs --exclude \".svn\" --exclude \"usr\" --include \"*/\" --include \"*.h\" --exclude \"*\" \"${SRCROOT}/Source/third_party/abseil-cpp/absl\" \"${PRIVATE_HEADERS_PATH}\"\n\nrsync -av --no-owner --no-group --prune-empty-dirs --exclude \".svn\" --exclude \"usr\" --include \"*/\" --include \"*.h\" --exclude \"*\" \"${SRCROOT}/Source/third_party/libyuv/include/\" \"${PRIVATE_HEADERS_PATH}\"\n\nrsync -av --no-owner --no-group --prune-empty-dirs --exclude \".svn\" --exclude \"usr\" --exclude \"src\" --exclude \"internal\" --include \"*/\" --include \"*.h\" --exclude \"*\" \"${SRCROOT}/Source/third_party/libvpx/source/libvpx/vpx\" \"${PRIVATE_HEADERS_PATH}\"\n\nrsync -av --no-owner --no-group --prune-empty-dirs --exclude \".svn\" --exclude \"usr\" --include \"*/\" --include \"*.h\" --exclude \"*\" \"${SRCROOT}/Source/third_party/libwebm/\" \"${PRIVATE_HEADERS_PATH}\"\n"; + }; + 5CD286461E6E154E0094FDC8 /* Check for Weak VTables and Externals */ = { + isa = PBXShellScriptBuildPhase; +@@ -18464,6 +18481,7 @@ + 419C82F51FE20EB50040C30F /* audio_encoder_opus.cc in Sources */, + 419C82F31FE20EB50040C30F /* audio_encoder_opus_config.cc in Sources */, + 4140B8201E4E3383007409E6 /* audio_encoder_pcm.cc in Sources */, ++ F3B7819A24C7CC5200FCB122 /* mkvmuxer.cc in Sources */, + 5CDD8FFE1E43CE3A00621E92 /* audio_encoder_pcm16b.cc in Sources */, + 5CD285461E6A61D20094FDC8 /* audio_format.cc in Sources */, + 41DDB26F212679D200296D47 /* audio_format_to_string.cc in Sources */, +@@ -18882,6 +18900,7 @@ + 417953DB216983910028266B /* metrics.cc in Sources */, + 5CDD865E1E43B8B500621E92 /* min_max_operations.c in Sources */, + 4189395B242A71F5007FDC41 /* min_video_bitrate_experiment.cc in Sources */, ++ F3B7819B24C7CC5200FCB122 /* mkvwriter.cc in Sources */, + 4131C387234B957D0028A615 /* moving_average.cc in Sources */, + 41FCBB1521B1F7AA00A5DF27 /* moving_average.cc in Sources */, + 5CD286101E6A64C90094FDC8 /* moving_max.cc in Sources */, +@@ -19107,6 +19126,7 @@ + 4131C53B234C8B190028A615 /* rtc_event_rtp_packet_outgoing.cc in Sources */, + 4131C552234C8B190028A615 /* rtc_event_video_receive_stream_config.cc in Sources */, + 4131C554234C8B190028A615 /* rtc_event_video_send_stream_config.cc in Sources */, ++ F3B7819924C7CC5200FCB122 /* mkvmuxerutil.cc in Sources */, + 4131C3CF234B98420028A615 /* rtc_stats.cc in Sources */, + 4131BF2D234B88200028A615 /* rtc_stats_collector.cc in Sources */, + 4131C3CE234B98420028A615 /* rtc_stats_report.cc in Sources */, +diff --git a/Source/WTF/Scripts/Preferences/WebPreferences.yaml b/Source/WTF/Scripts/Preferences/WebPreferences.yaml +index 1a964d163ffcc0f4c438d4c3b9679690f3157ea0..46fcceff6d2382d53e47d3867438e9d407a44fa6 100644 +--- a/Source/WTF/Scripts/Preferences/WebPreferences.yaml ++++ b/Source/WTF/Scripts/Preferences/WebPreferences.yaml +@@ -1010,7 +1010,7 @@ InspectorStartsAttached: + exposed: [ WebKit ] + defaultValue: + WebKit: +- default: true ++ default: false + + InspectorWindowFrame: + type: String +diff --git a/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml b/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml +index 7c74d8b376a1c8045c99b7647b67f97825b6b257..9bfe02b682845bd1bfa0565e08d86cdd0a56295c 100644 +--- a/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml ++++ b/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml +@@ -568,7 +568,7 @@ MaskWebGLStringsEnabled: + WebKitLegacy: + default: true + WebKit: +- default: true ++ default: false + + # FIXME: This is on by default in WebKit2. Perhaps we should consider turning it on for WebKitLegacy as well. + MediaCapabilitiesExtensionsEnabled: +diff --git a/Source/WTF/wtf/DateMath.cpp b/Source/WTF/wtf/DateMath.cpp +index 1e128fb9f20b50b6874a88656907bb4c059bc229..d2bae0c62da3b9ae22222241dce9d7121a0295df 100644 +--- a/Source/WTF/wtf/DateMath.cpp ++++ b/Source/WTF/wtf/DateMath.cpp +@@ -76,9 +76,14 @@ + #include + #include + #include ++#include + #include + #include ++#include ++#include ++#include + #include ++#include + + #if OS(WINDOWS) + #include +@@ -92,6 +97,18 @@ template inline bool startsWithLettersIgnoringASCIICase(const c + return equalLettersIgnoringASCIICase(string, lowercaseLetters, length - 1); + } + ++struct TimeZoneForAutomation { ++ UCalendar* cal; ++ String id; ++ String displayName; ++}; ++ ++static TimeZoneForAutomation& innerTimeZoneForAutomation() ++{ ++ static NeverDestroyed> timeZoneForAutomation; ++ return *timeZoneForAutomation.get(); ++} ++ + /* Constants */ + + const char* const weekdayName[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" }; +@@ -318,6 +335,14 @@ static double calculateDSTOffset(time_t localTime, double utcOffset) + // Returns combined offset in millisecond (UTC + DST). + LocalTimeOffset calculateLocalTimeOffset(double ms, TimeType inputTimeType) + { ++ TimeZoneForAutomation& tz = innerTimeZoneForAutomation(); ++ if (tz.cal) { ++ UErrorCode status = U_ZERO_ERROR; ++ ucal_setMillis(tz.cal, ms, &status); ++ int32_t offset = ucal_get(tz.cal, UCAL_ZONE_OFFSET, &status); ++ int32_t dstOffset = ucal_get(tz.cal, UCAL_DST_OFFSET, &status); ++ return LocalTimeOffset(dstOffset, offset + dstOffset); ++ } + #if HAVE(TM_GMTOFF) + double localToUTCTimeOffset = inputTimeType == LocalTime ? calculateUTCOffset() : 0; + #else +@@ -1016,4 +1041,65 @@ String makeRFC2822DateString(unsigned dayOfWeek, unsigned day, unsigned month, u + return stringBuilder.toString(); + } + ++bool setTimeZoneForAutomation(const String& timeZone) ++{ ++ innerTimeZoneForAutomation().displayName = String(); ++ if (innerTimeZoneForAutomation().cal) { ++ ucal_close(innerTimeZoneForAutomation().cal); ++ innerTimeZoneForAutomation().cal = nullptr; ++ } ++ if (timeZone.isEmpty()) { ++ innerTimeZoneForAutomation().id = String(); ++ return true; ++ } ++ ++ // Timezone is ascii. ++ Vector buffer(timeZone.length()); ++ UChar* bufferStart = buffer.data(); ++ CString ctz = timeZone.utf8(); ++ if (!Unicode::convertUTF8ToUTF16(ctz.data(), ctz.data() + ctz.length(), &bufferStart, bufferStart + timeZone.length())) ++ return false; ++ ++ Vector canonicalBuffer(32); ++ UErrorCode status = U_ZERO_ERROR; ++ auto canonicalLength = ucal_getCanonicalTimeZoneID(buffer.data(), buffer.size(), canonicalBuffer.data(), canonicalBuffer.size(), nullptr, &status); ++ if (status == U_BUFFER_OVERFLOW_ERROR) { ++ status = U_ZERO_ERROR; ++ canonicalBuffer.grow(canonicalLength); ++ ucal_getCanonicalTimeZoneID(buffer.data(), buffer.size(), canonicalBuffer.data(), canonicalLength, nullptr, &status); ++ } ++ if (!U_SUCCESS(status)) ++ return false; ++ ++ UCalendar* cal = ucal_open(canonicalBuffer.data(), canonicalLength, nullptr, UCAL_TRADITIONAL, &status); ++ if (!U_SUCCESS(status)) ++ return false; ++ ++ Vector displayNameBuffer(32); ++ auto displayNameLength = ucal_getTimeZoneDisplayName(cal, UCAL_STANDARD, defaultLanguage().utf8().data(), displayNameBuffer.data(), displayNameBuffer.size(), &status); ++ if (status == U_BUFFER_OVERFLOW_ERROR) { ++ status = U_ZERO_ERROR; ++ displayNameBuffer.grow(displayNameLength); ++ ucal_getTimeZoneDisplayName(cal, UCAL_STANDARD, defaultLanguage().utf8().data(), displayNameBuffer.data(), displayNameLength, &status); ++ } ++ if (!U_SUCCESS(status)) ++ return false; ++ ++ TimeZoneForAutomation& tzfa = innerTimeZoneForAutomation(); ++ tzfa.cal = cal; ++ tzfa.id = String(canonicalBuffer.data(), canonicalLength); ++ tzfa.displayName = String(displayNameBuffer.data(), displayNameLength); ++ return true; ++} ++ ++String timeZoneForAutomation() ++{ ++ return innerTimeZoneForAutomation().id; ++} ++ ++String timeZoneDisplayNameForAutomation() ++{ ++ return innerTimeZoneForAutomation().displayName; ++} ++ + } // namespace WTF +diff --git a/Source/WTF/wtf/DateMath.h b/Source/WTF/wtf/DateMath.h +index 1ac29617a0111e37c0239524ad8860734dd391fc..5eb36b02da455e55018f0b9d236858640be8e282 100644 +--- a/Source/WTF/wtf/DateMath.h ++++ b/Source/WTF/wtf/DateMath.h +@@ -384,6 +384,10 @@ inline int dayInMonthFromDayInYear(int dayInYear, bool leapYear) + return d - step; + } + ++WTF_EXPORT_PRIVATE bool setTimeZoneForAutomation(const String& timeZone); ++WTF_EXPORT_PRIVATE String timeZoneForAutomation(); ++WTF_EXPORT_PRIVATE String timeZoneDisplayNameForAutomation(); ++ + // Returns combined offset in millisecond (UTC + DST). + WTF_EXPORT_PRIVATE LocalTimeOffset calculateLocalTimeOffset(double utcInMilliseconds, TimeType = UTCTime); + +diff --git a/Source/WTF/wtf/PlatformEnable.h b/Source/WTF/wtf/PlatformEnable.h +index 19a8e4763c2a40bf2fb3c834aaa37012985152fe..3643f87014b1282259871db51cbdcd0e51361aa9 100644 +--- a/Source/WTF/wtf/PlatformEnable.h ++++ b/Source/WTF/wtf/PlatformEnable.h +@@ -409,7 +409,7 @@ + #endif + + #if !defined(ENABLE_ORIENTATION_EVENTS) +-#define ENABLE_ORIENTATION_EVENTS 0 ++#define ENABLE_ORIENTATION_EVENTS 1 + #endif + + #if OS(WINDOWS) +@@ -474,7 +474,7 @@ + #endif + + #if !defined(ENABLE_TOUCH_EVENTS) +-#define ENABLE_TOUCH_EVENTS 0 ++#define ENABLE_TOUCH_EVENTS 1 + #endif + + #if !defined(ENABLE_TOUCH_ACTION_REGIONS) +diff --git a/Source/WTF/wtf/PlatformHave.h b/Source/WTF/wtf/PlatformHave.h +index 41afbb4ee164125b51a39a1fcbcc7dae16ba4799..f02c4cd2fbff98a315ed956c3845b2ae771ad5cc 100644 +--- a/Source/WTF/wtf/PlatformHave.h ++++ b/Source/WTF/wtf/PlatformHave.h +@@ -353,7 +353,7 @@ + #define HAVE_NSHTTPCOOKIESTORAGE__INITWITHIDENTIFIER_WITH_INACCURATE_NULLABILITY 1 + #endif + +-#if PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(MACCATALYST) ++#if PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(MACCATALYST) || PLATFORM(GTK) || PLATFORM(WPE) || PLATFORM(WIN) + #define HAVE_OS_DARK_MODE_SUPPORT 1 + #endif + +diff --git a/Source/WebCore/DerivedSources.make b/Source/WebCore/DerivedSources.make +index 03fa2c626a15d69fa0dc671563dfdf70033a4476..b5201ee15508ec2c73328a01f7c0c8c076063318 100644 +--- a/Source/WebCore/DerivedSources.make ++++ b/Source/WebCore/DerivedSources.make +@@ -774,6 +774,10 @@ JS_BINDING_IDLS := \ + $(WebCore)/dom/Slotable.idl \ + $(WebCore)/dom/StaticRange.idl \ + $(WebCore)/dom/StringCallback.idl \ ++ $(WebCore)/dom/Document+Touch.idl \ ++ $(WebCore)/dom/Touch.idl \ ++ $(WebCore)/dom/TouchEvent.idl \ ++ $(WebCore)/dom/TouchList.idl \ + $(WebCore)/dom/Text.idl \ + $(WebCore)/dom/TextDecoder.idl \ + $(WebCore)/dom/TextDecoderStream.idl \ +@@ -1298,9 +1302,6 @@ JS_BINDING_IDLS := \ + ADDITIONAL_BINDING_IDLS = \ + DocumentTouch.idl \ + GestureEvent.idl \ +- Touch.idl \ +- TouchEvent.idl \ +- TouchList.idl \ + # + + vpath %.in $(WEBKITADDITIONS_HEADER_SEARCH_PATHS) +diff --git a/Source/WebCore/Modules/geolocation/Geolocation.cpp b/Source/WebCore/Modules/geolocation/Geolocation.cpp +index 6d5be9a591a272cd67d6e9d097b30505bdf8ae5e..8f67ba28c380e844c8e4191ee704466559d88f97 100644 +--- a/Source/WebCore/Modules/geolocation/Geolocation.cpp ++++ b/Source/WebCore/Modules/geolocation/Geolocation.cpp +@@ -356,8 +356,9 @@ bool Geolocation::shouldBlockGeolocationRequests() + bool isSecure = SecurityOrigin::isSecure(document()->url()); + bool hasMixedContent = !document()->foundMixedContent().isEmpty(); + bool isLocalOrigin = securityOrigin()->isLocal(); ++ bool isPotentiallyTrustworthy = securityOrigin()->isPotentiallyTrustworthy(); + if (securityOrigin()->canRequestGeolocation()) { +- if (isLocalOrigin || (isSecure && !hasMixedContent) || isRequestFromIBooks()) ++ if (isLocalOrigin || isPotentiallyTrustworthy || (isSecure && !hasMixedContent) || isRequestFromIBooks()) + return false; + } + +diff --git a/Source/WebCore/Modules/speech/cocoa/WebSpeechRecognizerTask.mm b/Source/WebCore/Modules/speech/cocoa/WebSpeechRecognizerTask.mm +index f1b96958057d2fe6044d2c7b259db6c5ceb44efe..29e51dad380285fb16bd32ef04efde2ac4ed6479 100644 +--- a/Source/WebCore/Modules/speech/cocoa/WebSpeechRecognizerTask.mm ++++ b/Source/WebCore/Modules/speech/cocoa/WebSpeechRecognizerTask.mm +@@ -202,6 +202,7 @@ NS_ASSUME_NONNULL_BEGIN + + - (void)speechRecognizer:(SFSpeechRecognizer *)speechRecognizer availabilityDidChange:(BOOL)available + { ++ UNUSED_PARAM(speechRecognizer); + ASSERT(isMainThread()); + + if (available || !_task) +@@ -215,6 +216,7 @@ NS_ASSUME_NONNULL_BEGIN + + - (void)speechRecognitionTask:(SFSpeechRecognitionTask *)task didHypothesizeTranscription:(SFTranscription *)transcription + { ++ UNUSED_PARAM(task); + ASSERT(isMainThread()); + + [self sendSpeechStartIfNeeded]; +@@ -223,6 +225,7 @@ NS_ASSUME_NONNULL_BEGIN + + - (void)speechRecognitionTask:(SFSpeechRecognitionTask *)task didFinishRecognition:(SFSpeechRecognitionResult *)recognitionResult + { ++ UNUSED_PARAM(task); + ASSERT(isMainThread()); + [self callbackWithTranscriptions:recognitionResult.transcriptions isFinal:YES]; + +@@ -234,6 +237,7 @@ NS_ASSUME_NONNULL_BEGIN + + - (void)speechRecognitionTaskWasCancelled:(SFSpeechRecognitionTask *)task + { ++ UNUSED_PARAM(task); + ASSERT(isMainThread()); + + [self sendSpeechEndIfNeeded]; +diff --git a/Source/WebCore/Modules/speech/cocoa/WebSpeechRecognizerTaskMock.mm b/Source/WebCore/Modules/speech/cocoa/WebSpeechRecognizerTaskMock.mm +index 66cec91542b74765a9c1ffbc2f28e1a5085c55e0..9a2a89a09279b3b7102282de6bfc4cc7e2b5925f 100644 +--- a/Source/WebCore/Modules/speech/cocoa/WebSpeechRecognizerTaskMock.mm ++++ b/Source/WebCore/Modules/speech/cocoa/WebSpeechRecognizerTaskMock.mm +@@ -36,6 +36,9 @@ NS_ASSUME_NONNULL_BEGIN + + - (instancetype)initWithIdentifier:(SpeechRecognitionConnectionClientIdentifier)identifier locale:(NSString*)localeIdentifier doMultipleRecognitions:(BOOL)continuous reportInterimResults:(BOOL)interimResults maxAlternatives:(unsigned long)alternatives delegateCallback:(void(^)(const SpeechRecognitionUpdate&))callback + { ++ UNUSED_PARAM(localeIdentifier); ++ UNUSED_PARAM(interimResults); ++ UNUSED_PARAM(alternatives); + if (!(self = [super init])) + return nil; + +@@ -51,6 +54,7 @@ NS_ASSUME_NONNULL_BEGIN + + - (void)audioSamplesAvailable:(CMSampleBufferRef)sampleBuffer + { ++ UNUSED_PARAM(sampleBuffer); + if (!_hasSentSpeechStart) { + _hasSentSpeechStart = true; + _delegateCallback(SpeechRecognitionUpdate::create(_identifier, SpeechRecognitionUpdateType::SpeechStart)); +diff --git a/Source/WebCore/PlatformWPE.cmake b/Source/WebCore/PlatformWPE.cmake +index 1d56fe2397aa683922f9e65e3ccd74707e73744e..129d21a0c83a7fdc576291f2955121acaab81d30 100644 +--- a/Source/WebCore/PlatformWPE.cmake ++++ b/Source/WebCore/PlatformWPE.cmake +@@ -38,6 +38,7 @@ list(APPEND WebCore_PRIVATE_INCLUDE_DIRECTORIES + list(APPEND WebCore_PRIVATE_FRAMEWORK_HEADERS + platform/graphics/wayland/PlatformDisplayWayland.h + platform/graphics/wayland/WlUniquePtr.h ++ platform/wpe/SelectionData.h + ) + + list(APPEND WebCore_USER_AGENT_STYLE_SHEETS +diff --git a/Source/WebCore/SourcesCocoa.txt b/Source/WebCore/SourcesCocoa.txt +index 5ee539fedb49535a3e2bd71d7bf951adfa9db55c..cecc3074e855b006e2b1dc5481e9b9578e4e5510 100644 +--- a/Source/WebCore/SourcesCocoa.txt ++++ b/Source/WebCore/SourcesCocoa.txt +@@ -614,3 +614,9 @@ platform/graphics/angle/TemporaryANGLESetting.cpp @no-unify + // Derived Sources + + WHLSLStandardLibraryFunctionMap.cpp ++ ++// Playwright begin ++JSTouch.cpp ++JSTouchEvent.cpp ++JSTouchList.cpp ++// Playwright end +diff --git a/Source/WebCore/SourcesWPE.txt b/Source/WebCore/SourcesWPE.txt +index 0d5eeec271334322b56087fe6a6e24ed85a60e21..e26d57d7708fef88c945721ba5a85788c7d5b53b 100644 +--- a/Source/WebCore/SourcesWPE.txt ++++ b/Source/WebCore/SourcesWPE.txt +@@ -44,6 +44,8 @@ editing/libwpe/EditorLibWPE.cpp + + loader/soup/ResourceLoaderSoup.cpp + ++page/wpe/DragControllerWPE.cpp ++ + page/linux/ResourceUsageOverlayLinux.cpp + page/linux/ResourceUsageThreadLinux.cpp + +@@ -84,8 +86,12 @@ platform/text/LocaleICU.cpp + + platform/unix/LoggingUnix.cpp + ++platform/wpe/DragDataWPE.cpp ++platform/wpe/DragImageWPE.cpp + platform/wpe/PlatformScreenWPE.cpp + + platform/xdg/MIMETypeRegistryXdg.cpp + + rendering/RenderThemeAdwaita.cpp ++ ++platform/wpe/SelectionData.cpp +diff --git a/Source/WebCore/WebCore.order b/Source/WebCore/WebCore.order +index ef168b76819216d984b7a2d0f760005fb9d24de8..2d6cf51f3b45191ad84106429d4f108f85679123 100644 +--- a/Source/WebCore/WebCore.order ++++ b/Source/WebCore/WebCore.order +@@ -3093,7 +3093,6 @@ __ZN7WebCore14DocumentLoader23stopLoadingSubresourcesEv + __ZN7WebCore14DocumentLoader18stopLoadingPlugInsEv + __ZN7WebCore14DocumentLoader15detachFromFrameEv + __ZN7WebCore20ApplicationCacheHost22setDOMApplicationCacheEPNS_19DOMApplicationCacheE +-__ZN7WebCore24InspectorInstrumentation27loaderDetachedFromFrameImplEPNS_19InstrumentingAgentsEPNS_14DocumentLoaderE + __ZN7WebCore14DocumentLoaderD0Ev + __ZN7WebCore14DocumentLoaderD2Ev + __ZN7WebCore14DocumentLoader17clearMainResourceEv +diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj +index 5b64ba66a8e9e1cca962b9ae13af1a496711d8dc..09b1d917ab7955b1d62627438b7e9ff7c1352376 100644 +--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj ++++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj +@@ -5268,6 +5268,14 @@ + EDE3A5000C7A430600956A37 /* ColorMac.h in Headers */ = {isa = PBXBuildFile; fileRef = EDE3A4FF0C7A430600956A37 /* ColorMac.h */; settings = {ATTRIBUTES = (Private, ); }; }; + EDEC98030AED7E170059137F /* WebCorePrefix.h in Headers */ = {isa = PBXBuildFile; fileRef = EDEC98020AED7E170059137F /* WebCorePrefix.h */; }; + EFCC6C8F20FE914400A2321B /* CanvasActivityRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = EFCC6C8D20FE914000A2321B /* CanvasActivityRecord.h */; settings = {ATTRIBUTES = (Private, ); }; }; ++ F050E16823AC9C080011CE47 /* PlatformTouchEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = F050E16623AC9C070011CE47 /* PlatformTouchEvent.h */; settings = {ATTRIBUTES = (Private, ); }; }; ++ F050E16A23AD660C0011CE47 /* Touch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F050E16923AD660C0011CE47 /* Touch.cpp */; }; ++ F050E16D23AD66630011CE47 /* TouchList.h in Headers */ = {isa = PBXBuildFile; fileRef = F050E16B23AD66620011CE47 /* TouchList.h */; settings = {ATTRIBUTES = (Private, ); }; }; ++ F050E16E23AD66630011CE47 /* TouchList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F050E16C23AD66630011CE47 /* TouchList.cpp */; }; ++ F050E17123AD669F0011CE47 /* TouchEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F050E16F23AD669E0011CE47 /* TouchEvent.cpp */; }; ++ F050E17223AD669F0011CE47 /* TouchEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = F050E17023AD669F0011CE47 /* TouchEvent.h */; settings = {ATTRIBUTES = (Private, ); }; }; ++ F050E17423AD6A800011CE47 /* DocumentTouch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F050E17323AD6A800011CE47 /* DocumentTouch.cpp */; }; ++ F050E17823AD70C50011CE47 /* PlatformTouchPoint.h in Headers */ = {isa = PBXBuildFile; fileRef = F050E17623AD70C40011CE47 /* PlatformTouchPoint.h */; settings = {ATTRIBUTES = (Private, ); }; }; + F12171F616A8CF0B000053CA /* WebVTTElement.h in Headers */ = {isa = PBXBuildFile; fileRef = F12171F416A8BC63000053CA /* WebVTTElement.h */; }; + F32BDCD92363AACA0073B6AE /* UserGestureEmulationScope.h in Headers */ = {isa = PBXBuildFile; fileRef = F32BDCD72363AACA0073B6AE /* UserGestureEmulationScope.h */; }; + F344C7141125B82C00F26EEE /* InspectorFrontendClient.h in Headers */ = {isa = PBXBuildFile; fileRef = F344C7121125B82C00F26EEE /* InspectorFrontendClient.h */; settings = {ATTRIBUTES = (Private, ); }; }; +@@ -16617,6 +16625,14 @@ + EDEC98020AED7E170059137F /* WebCorePrefix.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = WebCorePrefix.h; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; + EFB7287B2124C73D005C2558 /* CanvasActivityRecord.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CanvasActivityRecord.cpp; sourceTree = ""; }; + EFCC6C8D20FE914000A2321B /* CanvasActivityRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CanvasActivityRecord.h; sourceTree = ""; }; ++ F050E16623AC9C070011CE47 /* PlatformTouchEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformTouchEvent.h; sourceTree = ""; }; ++ F050E16923AD660C0011CE47 /* Touch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Touch.cpp; path = dom/Touch.cpp; sourceTree = SOURCE_ROOT; }; ++ F050E16B23AD66620011CE47 /* TouchList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TouchList.h; path = dom/TouchList.h; sourceTree = SOURCE_ROOT; }; ++ F050E16C23AD66630011CE47 /* TouchList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TouchList.cpp; path = dom/TouchList.cpp; sourceTree = SOURCE_ROOT; }; ++ F050E16F23AD669E0011CE47 /* TouchEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TouchEvent.cpp; path = dom/TouchEvent.cpp; sourceTree = SOURCE_ROOT; }; ++ F050E17023AD669F0011CE47 /* TouchEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TouchEvent.h; path = dom/TouchEvent.h; sourceTree = SOURCE_ROOT; }; ++ F050E17323AD6A800011CE47 /* DocumentTouch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocumentTouch.cpp; sourceTree = ""; }; ++ F050E17623AD70C40011CE47 /* PlatformTouchPoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformTouchPoint.h; sourceTree = ""; }; + F12171F316A8BC63000053CA /* WebVTTElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebVTTElement.cpp; sourceTree = ""; }; + F12171F416A8BC63000053CA /* WebVTTElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebVTTElement.h; sourceTree = ""; }; + F32BDCD52363AAC90073B6AE /* UserGestureEmulationScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UserGestureEmulationScope.cpp; sourceTree = ""; }; +@@ -22162,7 +22178,12 @@ + 93D6B7A62551D3ED0058DD3A /* DummySpeechRecognitionProvider.h */, + 1AF326770D78B9440068F0C4 /* EditorClient.h */, + 93C09A800B064F00005ABD4D /* EventHandler.cpp */, ++ F050E16F23AD669E0011CE47 /* TouchEvent.cpp */, ++ F050E17023AD669F0011CE47 /* TouchEvent.h */, + 93C09A520B064DB3005ABD4D /* EventHandler.h */, ++ F050E16923AD660C0011CE47 /* Touch.cpp */, ++ F050E16C23AD66630011CE47 /* TouchList.cpp */, ++ F050E16B23AD66620011CE47 /* TouchList.h */, + E0FEF371B27C53EAC1C1FBEE /* EventSource.cpp */, + E0FEF371B17C53EAC1C1FBEE /* EventSource.h */, + E0FEF371B07C53EAC1C1FBEE /* EventSource.idl */, +@@ -27626,7 +27647,9 @@ + B2C3D9EC0D006C1D00EF6F26 /* text */, + E1EE8B6B2412B2A700E794D6 /* xr */, + DFDB912CF8E88A6DA1AD264F /* AbortableTaskQueue.h */, ++ F050E16623AC9C070011CE47 /* PlatformTouchEvent.h */, + 49AE2D94134EE5F90072920A /* CalculationValue.cpp */, ++ F050E17623AD70C40011CE47 /* PlatformTouchPoint.h */, + 49AE2D95134EE5F90072920A /* CalculationValue.h */, + C330A22113EC196B0000B45B /* ColorChooser.h */, + C37CDEBC149EF2030042090D /* ColorChooserClient.h */, +@@ -30167,6 +30190,7 @@ + BCCFBAE70B5152ED0001F1D7 /* DocumentParser.h */, + AD6E71AA1668899D00320C13 /* DocumentSharedObjectPool.cpp */, + AD6E71AB1668899D00320C13 /* DocumentSharedObjectPool.h */, ++ F050E17323AD6A800011CE47 /* DocumentTouch.cpp */, + 6BDB5DC1227BD3B800919770 /* DocumentStorageAccess.cpp */, + 6BDB5DC0227BD3B800919770 /* DocumentStorageAccess.h */, + 86D982F6125C154000AD9E3D /* DocumentTiming.h */, +@@ -31194,6 +31218,7 @@ + 93C4F6EB1108F9A50099D0DB /* AccessibilityScrollbar.h in Headers */, + 29489FC712C00F0300D83F0F /* AccessibilityScrollView.h in Headers */, + 0709FC4E1025DEE30059CDBA /* AccessibilitySlider.h in Headers */, ++ F050E16D23AD66630011CE47 /* TouchList.h in Headers */, + 29D7BCFA1444AF7D0070619C /* AccessibilitySpinButton.h in Headers */, + 69A6CBAD1C6BE42C00B836E9 /* AccessibilitySVGElement.h in Headers */, + AAC08CF315F941FD00F1E188 /* AccessibilitySVGRoot.h in Headers */, +@@ -33181,6 +33206,7 @@ + 6E4ABCD5138EA0B70071D291 /* JSHTMLUnknownElement.h in Headers */, + E44614170CD6826900FADA75 /* JSHTMLVideoElement.h in Headers */, + 81BE20D311F4BC3200915DFA /* JSIDBCursor.h in Headers */, ++ F050E17823AD70C50011CE47 /* PlatformTouchPoint.h in Headers */, + 7C3D8EF01E0B21430023B084 /* JSIDBCursorDirection.h in Headers */, + C585A68311D4FB08004C3E4B /* JSIDBDatabase.h in Headers */, + C585A69711D4FB13004C3E4B /* JSIDBFactory.h in Headers */, +@@ -35203,9 +35229,11 @@ + B2C3DA3A0D006C1D00EF6F26 /* TextCodec.h in Headers */, + 26E98A10130A9FCA008EB7B2 /* TextCodecASCIIFastPath.h in Headers */, + DF95B14A24FDAFD300B1F4D7 /* TextCodecCJK.h in Headers */, ++ F050E16823AC9C080011CE47 /* PlatformTouchEvent.h in Headers */, + B2C3DA3C0D006C1D00EF6F26 /* TextCodecICU.h in Headers */, + B2C3DA3E0D006C1D00EF6F26 /* TextCodecLatin1.h in Headers */, + 57EF5E601D20C83900171E60 /* TextCodecReplacement.h in Headers */, ++ F050E17223AD669F0011CE47 /* TouchEvent.h in Headers */, + B2C3DA400D006C1D00EF6F26 /* TextCodecUserDefined.h in Headers */, + B2C3DA420D006C1D00EF6F26 /* TextCodecUTF16.h in Headers */, + 9343CB8212F25E510033C5EE /* TextCodecUTF8.h in Headers */, +@@ -36176,6 +36204,7 @@ + 2D22830323A8470700364B7E /* CursorMac.mm in Sources */, + 5CBD59592280E926002B22AA /* CustomHeaderFields.cpp in Sources */, + 4463CF682212FA68001A8577 /* DataDetectorsCoreSoftLink.mm in Sources */, ++ F050E17423AD6A800011CE47 /* DocumentTouch.cpp in Sources */, + 6E72F54C229DCD0C00B3E151 /* ExtensionsGLANGLE.cpp in Sources */, + 7CE6CBFD187F394900D46BF5 /* FormatConverter.cpp in Sources */, + 5130F2F624AEA60A00E1D0A0 /* GameControllerSoftLink.mm in Sources */, +@@ -36262,6 +36291,7 @@ + 6E72F54F229DCD1300B3E151 /* TemporaryANGLESetting.cpp in Sources */, + CE88EE262414467B007F29C2 /* TextAlternativeWithRange.mm in Sources */, + 51DF6D800B92A18E00C2DC85 /* ThreadCheck.mm in Sources */, ++ F050E17123AD669F0011CE47 /* TouchEvent.cpp in Sources */, + 538EC8031F96AF81004D22A8 /* UnifiedSource1-mm.mm in Sources */, + 538EC8021F96AF81004D22A8 /* UnifiedSource1.cpp in Sources */, + 538EC8051F96AF81004D22A8 /* UnifiedSource2-mm.mm in Sources */, +@@ -36310,6 +36340,7 @@ + 538EC8881F993F9C004D22A8 /* UnifiedSource23.cpp in Sources */, + DE5F85801FA1ABF4006DB63A /* UnifiedSource24-mm.mm in Sources */, + 538EC8891F993F9D004D22A8 /* UnifiedSource24.cpp in Sources */, ++ F050E16E23AD66630011CE47 /* TouchList.cpp in Sources */, + DE5F85811FA1ABF4006DB63A /* UnifiedSource25-mm.mm in Sources */, + 538EC88A1F993F9D004D22A8 /* UnifiedSource25.cpp in Sources */, + DE5F85821FA1ABF4006DB63A /* UnifiedSource26-mm.mm in Sources */, +@@ -36842,6 +36873,7 @@ + 2D8B92F1203D13E1009C868F /* UnifiedSource516.cpp in Sources */, + 2D8B92F2203D13E1009C868F /* UnifiedSource517.cpp in Sources */, + 2D8B92F3203D13E1009C868F /* UnifiedSource518.cpp in Sources */, ++ F050E16A23AD660C0011CE47 /* Touch.cpp in Sources */, + 2D8B92F4203D13E1009C868F /* UnifiedSource519.cpp in Sources */, + 2D8B92F5203D13E1009C868F /* UnifiedSource520.cpp in Sources */, + 2D8B92F6203D13E1009C868F /* UnifiedSource521.cpp in Sources */, +diff --git a/Source/WebCore/accessibility/AccessibilityObject.cpp b/Source/WebCore/accessibility/AccessibilityObject.cpp +index 904354d628ab54f77bac8e1f0665efce7ad55848..625515148ac7e73a06a3341c59b871588318364f 100644 +--- a/Source/WebCore/accessibility/AccessibilityObject.cpp ++++ b/Source/WebCore/accessibility/AccessibilityObject.cpp +@@ -59,6 +59,7 @@ + #include "HTMLParserIdioms.h" + #include "HTMLTextAreaElement.h" + #include "HitTestResult.h" ++#include "InspectorInstrumentation.h" + #include "LocalizedStrings.h" + #include "MathMLNames.h" + #include "NodeList.h" +@@ -3265,10 +3266,15 @@ AccessibilityObjectInclusion AccessibilityObject::defaultObjectInclusion() const + + if (useParentData ? m_isIgnoredFromParentData.isPresentationalChildOfAriaRole : isPresentationalChildOfAriaRole()) + return AccessibilityObjectInclusion::IgnoreObject; +- +- return accessibilityPlatformIncludesObject(); ++ ++ AccessibilityObjectInclusion platformBehavior = accessibilityPlatformIncludesObject(); ++ if (platformBehavior != AccessibilityObjectInclusion::DefaultBehavior) { ++ if (auto* page = this->page()) ++ InspectorInstrumentation::maybeOverrideDefaultObjectInclusion(*page, platformBehavior); ++ } ++ return platformBehavior; + } +- ++ + bool AccessibilityObject::accessibilityIsIgnored() const + { + AXComputedObjectAttributeCache* attributeCache = nullptr; +diff --git a/Source/WebCore/dom/DataTransfer.cpp b/Source/WebCore/dom/DataTransfer.cpp +index 1deac4f41cf49f1f882dccefd48cf6a9732f3ed9..c691eeccd75fc76f5df367b9fb5b95435e92ab79 100644 +--- a/Source/WebCore/dom/DataTransfer.cpp ++++ b/Source/WebCore/dom/DataTransfer.cpp +@@ -494,6 +494,14 @@ Ref DataTransfer::createForDrag(const Document& document) + return adoptRef(*new DataTransfer(StoreMode::ReadWrite, Pasteboard::createForDragAndDrop(PagePasteboardContext::create(document.pageID())), Type::DragAndDropData)); + } + ++#if PLATFORM(MAC) ++Ref DataTransfer::createForDrag(const Document& document, const String& pasteboardName) ++{ ++ return adoptRef(*new DataTransfer(StoreMode::ReadWrite, makeUnique(PagePasteboardContext::create(document.pageID()), pasteboardName), Type::DragAndDropData)); ++} ++#endif ++ ++ + Ref DataTransfer::createForDragStartEvent(const Document& document) + { + auto dataTransfer = adoptRef(*new DataTransfer(StoreMode::ReadWrite, makeUnique(), Type::DragAndDropData)); +diff --git a/Source/WebCore/dom/DataTransfer.h b/Source/WebCore/dom/DataTransfer.h +index b084ee416512652220e43a6d4bcccaff7c666d5a..b250f3d0161817efef7e2634a16713b0a0f1fa71 100644 +--- a/Source/WebCore/dom/DataTransfer.h ++++ b/Source/WebCore/dom/DataTransfer.h +@@ -90,6 +90,9 @@ public: + + #if ENABLE(DRAG_SUPPORT) + static Ref createForDrag(const Document&); ++#if PLATFORM(MAC) ++ static Ref createForDrag(const Document&, const String& pasteboardName); ++#endif + static Ref createForDragStartEvent(const Document&); + static Ref createForDrop(const Document&, std::unique_ptr&&, OptionSet, bool draggingFiles); + static Ref createForUpdatingDropTarget(const Document&, std::unique_ptr&&, OptionSet, bool draggingFiles); +diff --git a/Source/WebCore/dom/PointerEvent.cpp b/Source/WebCore/dom/PointerEvent.cpp +index f21879fdfbc64e7d2f11ab084d46794a9e601110..151c9b72f0f552c2ff741305c4c0a8c7f51a92e3 100644 +--- a/Source/WebCore/dom/PointerEvent.cpp ++++ b/Source/WebCore/dom/PointerEvent.cpp +@@ -114,4 +114,61 @@ EventInterface PointerEvent::eventInterface() const + return PointerEventInterfaceType; + } + ++#if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS_FAMILY) ++ ++static const AtomString& pointerEventType(PlatformTouchPoint::State state) ++{ ++ switch (state) { ++ case PlatformTouchPoint::State::TouchPressed: ++ return eventNames().pointerdownEvent; ++ case PlatformTouchPoint::State::TouchMoved: ++ return eventNames().pointermoveEvent; ++ case PlatformTouchPoint::State::TouchStationary: ++ return eventNames().pointermoveEvent; ++ case PlatformTouchPoint::State::TouchReleased: ++ return eventNames().pointerupEvent; ++ case PlatformTouchPoint::State::TouchCancelled: ++ return eventNames().pointercancelEvent; ++ case PlatformTouchPoint::State::TouchStateEnd: ++ break; ++ } ++ ASSERT_NOT_REACHED(); ++ return nullAtom(); ++} ++ ++static short buttonForType(const AtomString& type) ++{ ++ return type == eventNames().pointermoveEvent ? -1 : 0; ++} ++ ++static unsigned short buttonsForType(const AtomString& type) ++{ ++ // We have contact with the touch surface for most events except when we've released the touch or canceled it. ++ return (type == eventNames().pointerupEvent || type == eventNames().pointeroutEvent || type == eventNames().pointerleaveEvent || type == eventNames().pointercancelEvent) ? 0 : 1; ++} ++ ++Ref PointerEvent::create(const PlatformTouchEvent& event, unsigned index, bool isPrimary, Ref&& view) ++{ ++ const auto& type = pointerEventType(event.touchPoints().at(index).state()); ++ return adoptRef(*new PointerEvent(type, event, typeIsCancelable(type), index, isPrimary, WTFMove(view))); ++} ++ ++Ref PointerEvent::create(const String& type, const PlatformTouchEvent& event, unsigned index, bool isPrimary, Ref&& view) ++{ ++ return adoptRef(*new PointerEvent(type, event, typeIsCancelable(type), index, isPrimary, WTFMove(view))); ++} ++ ++PointerEvent::PointerEvent(const AtomString& type, const PlatformTouchEvent& event, IsCancelable isCancelable, unsigned index, bool isPrimary, Ref&& view) ++ : MouseEvent(type, typeCanBubble(type), isCancelable, typeIsComposed(type), event.timestamp().approximateMonotonicTime(), WTFMove(view), 0, event.touchPoints().at(index).pos(), event.touchPoints().at(index).pos(), { }, event.modifiers(), buttonForType(type), buttonsForType(type), nullptr, 0, 0, IsSimulated::No, IsTrusted::Yes) ++ , m_pointerId(2) ++ , m_width(2 * event.touchPoints().at(index).radiusX()) ++ , m_height(2 * event.touchPoints().at(index).radiusY()) ++ , m_pressure(event.touchPoints().at(index).force()) ++ , m_pointerType(touchPointerEventType()) ++ , m_isPrimary(isPrimary) ++{ ++} ++ ++#endif // ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS_FAMILY) ++ + } // namespace WebCore +diff --git a/Source/WebCore/dom/PointerEvent.h b/Source/WebCore/dom/PointerEvent.h +index 9d60b85152f378566118574663701c25b001df3d..9811ce9aa6f066c57acf65f629d2ab8155c090e1 100644 +--- a/Source/WebCore/dom/PointerEvent.h ++++ b/Source/WebCore/dom/PointerEvent.h +@@ -33,6 +33,8 @@ + + #if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY) + #include "PlatformTouchEventIOS.h" ++#else ++#include "PlatformTouchEvent.h" + #endif + + namespace WebCore { +@@ -81,7 +83,7 @@ public: + static Ref create(const String& type, short button, const MouseEvent&, PointerID, const String& pointerType); + static Ref create(const String& type, PointerID, const String& pointerType, IsPrimary = IsPrimary::No); + +-#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY) ++#if ENABLE(TOUCH_EVENTS) + static Ref create(const PlatformTouchEvent&, unsigned touchIndex, bool isPrimary, Ref&&); + static Ref create(const String& type, const PlatformTouchEvent&, unsigned touchIndex, bool isPrimary, Ref&&); + #endif +@@ -121,7 +123,7 @@ private: + PointerEvent(const AtomString&, Init&&); + PointerEvent(const AtomString& type, short button, const MouseEvent&, PointerID, const String& pointerType); + PointerEvent(const AtomString& type, PointerID, const String& pointerType, IsPrimary); +-#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY) ++#if ENABLE(TOUCH_EVENTS) + PointerEvent(const AtomString& type, const PlatformTouchEvent&, IsCancelable isCancelable, unsigned touchIndex, bool isPrimary, Ref&&); + #endif + +diff --git a/Source/WebCore/editing/libwpe/EditorLibWPE.cpp b/Source/WebCore/editing/libwpe/EditorLibWPE.cpp +index 9dd41d6366512fd385937a7608bd3fc9b5b90f60..d6bb529fb891a65c8f6dcc6cff1e718c7a40b8dd 100644 +--- a/Source/WebCore/editing/libwpe/EditorLibWPE.cpp ++++ b/Source/WebCore/editing/libwpe/EditorLibWPE.cpp +@@ -33,6 +33,7 @@ + #include "NotImplemented.h" + #include "Pasteboard.h" + #include "Settings.h" ++#include "WebContentReader.h" + #include "markup.h" + + namespace WebCore { +@@ -91,6 +92,14 @@ void Editor::pasteWithPasteboard(Pasteboard* pasteboard, OptionSet + pasteAsFragment(*fragment, canSmartReplaceWithPasteboard(*pasteboard), chosePlainText, options.contains(PasteOption::IgnoreMailBlockquote) ? MailBlockquoteHandling::IgnoreBlockquote : MailBlockquoteHandling::RespectBlockquote); + } + ++RefPtr Editor::webContentFromPasteboard(Pasteboard& pasteboard, const SimpleRange& context, bool allowPlainText, bool& chosePlainText) ++{ ++ WebContentReader reader(*m_document.frame(), context, allowPlainText); ++ pasteboard.read(reader); ++ chosePlainText = reader.madeFragmentFromPlainText; ++ return WTFMove(reader.fragment); ++} ++ + } // namespace WebCore + + #endif // USE(LIBWPE) +diff --git a/Source/WebCore/html/FileInputType.cpp b/Source/WebCore/html/FileInputType.cpp +index 06c84321bb291fb178625f3d783438ee88846f93..1c8a87decc58045ed353b66240a9f2ad322e49e0 100644 +--- a/Source/WebCore/html/FileInputType.cpp ++++ b/Source/WebCore/html/FileInputType.cpp +@@ -36,6 +36,7 @@ + #include "HTMLNames.h" + #include "Icon.h" + #include "InputTypeNames.h" ++#include "InspectorInstrumentation.h" + #include "LocalizedStrings.h" + #include "MIMETypeRegistry.h" + #include "RenderFileUploadControl.h" +@@ -211,6 +212,11 @@ void FileInputType::handleDOMActivateEvent(Event& event) + if (input.isDisabledFormControl()) + return; + ++ bool intercept = false; ++ InspectorInstrumentation::runOpenPanel(input.document().frame(), element(), &intercept); ++ if (intercept) ++ return; ++ + if (!UserGestureIndicator::processingUserGesture()) + return; + +diff --git a/Source/WebCore/inspector/InspectorController.cpp b/Source/WebCore/inspector/InspectorController.cpp +index 8728fb72fa042796dc8bdf5c91e8242bd0755f61..2978f9df308f67a3c858f8dd8970a203c790b11d 100644 +--- a/Source/WebCore/inspector/InspectorController.cpp ++++ b/Source/WebCore/inspector/InspectorController.cpp +@@ -376,8 +376,8 @@ void InspectorController::inspect(Node* node) + if (!enabled()) + return; + +- if (!hasRemoteFrontend()) +- show(); ++ // HACK: Always attempt to show inspector even if there is a remote connection. ++ show(); + + ensureDOMAgent().inspect(node); + } +@@ -518,4 +518,24 @@ void InspectorController::didComposite(Frame& frame) + InspectorInstrumentation::didComposite(frame); + } + ++void InspectorController::pauseWhenShown() ++{ ++ m_pauseWhenShown = true; ++} ++ ++void InspectorController::resumeIfPausedInNewWindow() ++{ ++ m_pauseWhenShown = false; ++} ++ ++void InspectorController::didShowNewWindow() ++{ ++ if (!m_pauseWhenShown) ++ return; ++ while (m_pauseWhenShown) { ++ if (RunLoop::cycle() == RunLoop::CycleResult::Stop) ++ break; ++ } ++} ++ + } // namespace WebCore +diff --git a/Source/WebCore/inspector/InspectorController.h b/Source/WebCore/inspector/InspectorController.h +index 784bf482fd68da68e1f38fd5cd6bcedc8971dfda..6cdf012453ff31120adbe5946ce23f075761ebef 100644 +--- a/Source/WebCore/inspector/InspectorController.h ++++ b/Source/WebCore/inspector/InspectorController.h +@@ -101,6 +101,10 @@ public: + WEBCORE_EXPORT void willComposite(Frame&); + WEBCORE_EXPORT void didComposite(Frame&); + ++ WEBCORE_EXPORT void pauseWhenShown(); ++ WEBCORE_EXPORT void resumeIfPausedInNewWindow(); ++ WEBCORE_EXPORT void didShowNewWindow(); ++ + // Testing support. + bool isUnderTest() const { return m_isUnderTest; } + void setIsUnderTest(bool isUnderTest) { m_isUnderTest = isUnderTest; } +@@ -152,6 +156,7 @@ private: + bool m_isAutomaticInspection { false }; + bool m_pauseAfterInitialization = { false }; + bool m_didCreateLazyAgents { false }; ++ bool m_pauseWhenShown { false }; + }; + + } // namespace WebCore +diff --git a/Source/WebCore/inspector/InspectorInstrumentation.cpp b/Source/WebCore/inspector/InspectorInstrumentation.cpp +index ce09e57f0114419a6704dee6a34776520cadf59c..cdc7bb32ebe4132ed75a47d41b769e4e9785e169 100644 +--- a/Source/WebCore/inspector/InspectorInstrumentation.cpp ++++ b/Source/WebCore/inspector/InspectorInstrumentation.cpp +@@ -633,6 +633,12 @@ void InspectorInstrumentation::didFailLoadingImpl(InstrumentingAgents& instrumen + consoleAgent->didFailLoading(identifier, error); // This should come AFTER resource notification, front-end relies on this. + } + ++void InspectorInstrumentation::didReceiveMainResourceErrorImpl(InstrumentingAgents& instrumentingAgents, Frame& frame, const ResourceError&) ++{ ++ if (auto* pageRuntimeAgent = instrumentingAgents.enabledPageRuntimeAgent()) ++ pageRuntimeAgent->didReceiveMainResourceError(frame); ++} ++ + void InspectorInstrumentation::willLoadXHRSynchronouslyImpl(InstrumentingAgents& instrumentingAgents) + { + if (auto* networkAgent = instrumentingAgents.enabledNetworkAgent()) +@@ -665,20 +671,17 @@ void InspectorInstrumentation::didReceiveScriptResponseImpl(InstrumentingAgents& + + void InspectorInstrumentation::domContentLoadedEventFiredImpl(InstrumentingAgents& instrumentingAgents, Frame& frame) + { +- if (!frame.isMainFrame()) +- return; +- + if (auto* pageAgent = instrumentingAgents.enabledPageAgent()) +- pageAgent->domContentEventFired(); ++ pageAgent->domContentEventFired(frame); + } + + void InspectorInstrumentation::loadEventFiredImpl(InstrumentingAgents& instrumentingAgents, Frame* frame) + { +- if (!frame || !frame->isMainFrame()) ++ if (!frame) + return; + + if (auto* pageAgent = instrumentingAgents.enabledPageAgent()) +- pageAgent->loadEventFired(); ++ pageAgent->loadEventFired(*frame); + } + + void InspectorInstrumentation::frameDetachedFromParentImpl(InstrumentingAgents& instrumentingAgents, Frame& frame) +@@ -759,12 +762,6 @@ void InspectorInstrumentation::frameDocumentUpdatedImpl(InstrumentingAgents& ins + pageDOMDebuggerAgent->frameDocumentUpdated(frame); + } + +-void InspectorInstrumentation::loaderDetachedFromFrameImpl(InstrumentingAgents& instrumentingAgents, DocumentLoader& loader) +-{ +- if (auto* inspectorPageAgent = instrumentingAgents.enabledPageAgent()) +- inspectorPageAgent->loaderDetachedFromFrame(loader); +-} +- + void InspectorInstrumentation::frameStartedLoadingImpl(InstrumentingAgents& instrumentingAgents, Frame& frame) + { + if (frame.isMainFrame()) { +@@ -801,6 +798,12 @@ void InspectorInstrumentation::frameClearedScheduledNavigationImpl(Instrumenting + inspectorPageAgent->frameClearedScheduledNavigation(frame); + } + ++void InspectorInstrumentation::didNavigateWithinPageImpl(InstrumentingAgents& instrumentingAgents, Frame& frame) ++{ ++ if (InspectorPageAgent* inspectorPageAgent = instrumentingAgents.enabledPageAgent()) ++ inspectorPageAgent->didNavigateWithinPage(frame); ++} ++ + #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT) + void InspectorInstrumentation::defaultAppearanceDidChangeImpl(InstrumentingAgents& instrumentingAgents, bool useDarkAppearance) + { +@@ -1326,6 +1329,36 @@ void InspectorInstrumentation::renderLayerDestroyedImpl(InstrumentingAgents& ins + layerTreeAgent->renderLayerDestroyed(renderLayer); + } + ++void InspectorInstrumentation::runOpenPanelImpl(InstrumentingAgents& instrumentingAgents, HTMLInputElement* element, bool* intercept) ++{ ++ if (InspectorPageAgent* pageAgent = instrumentingAgents.enabledPageAgent()) ++ pageAgent->runOpenPanel(element, intercept); ++} ++ ++void InspectorInstrumentation::frameAttachedImpl(InstrumentingAgents& instrumentingAgents, Frame& frame) { ++ if (InspectorPageAgent* pageAgent = instrumentingAgents.enabledPageAgent()) ++ pageAgent->frameAttached(frame); ++} ++ ++bool InspectorInstrumentation::shouldBypassCSPImpl(InstrumentingAgents& instrumentingAgents) ++{ ++ if (InspectorPageAgent* pageAgent = instrumentingAgents.enabledPageAgent()) ++ return pageAgent->shouldBypassCSP(); ++ return false; ++} ++ ++void InspectorInstrumentation::willCheckNewWindowPolicyImpl(InstrumentingAgents& instrumentingAgents, const URL& url) ++{ ++ if (InspectorPageAgent* pageAgent = instrumentingAgents.enabledPageAgent()) ++ pageAgent->willCheckNewWindowPolicy(url); ++} ++ ++void InspectorInstrumentation::didCheckNewWindowPolicyImpl(InstrumentingAgents& instrumentingAgents, bool allowed) ++{ ++ if (InspectorPageAgent* pageAgent = instrumentingAgents.enabledPageAgent()) ++ pageAgent->didCheckNewWindowPolicy(allowed); ++} ++ + InstrumentingAgents& InspectorInstrumentation::instrumentingAgents(WorkerOrWorkletGlobalScope& globalScope) + { + return globalScope.inspectorController().m_instrumentingAgents; +@@ -1337,6 +1370,13 @@ InstrumentingAgents& InspectorInstrumentation::instrumentingAgents(Page& page) + return page.inspectorController().m_instrumentingAgents.get(); + } + ++void InspectorInstrumentation::maybeOverrideDefaultObjectInclusion(Page& page, AccessibilityObjectInclusion& inclusion) { ++ if (InspectorPageAgent* pageAgent = instrumentingAgents(page).enabledPageAgent()) { ++ if (pageAgent->doingAccessibilitySnapshot()) ++ inclusion = AccessibilityObjectInclusion::DefaultBehavior; ++ } ++} ++ + InstrumentingAgents* InspectorInstrumentation::instrumentingAgents(ScriptExecutionContext& context) + { + if (is(context)) +diff --git a/Source/WebCore/inspector/InspectorInstrumentation.h b/Source/WebCore/inspector/InspectorInstrumentation.h +index 597938385139a199d20e841ac80576193a19ed53..277c369a20574a816e0ce1f68e9a8e7bb12366a9 100644 +--- a/Source/WebCore/inspector/InspectorInstrumentation.h ++++ b/Source/WebCore/inspector/InspectorInstrumentation.h +@@ -31,6 +31,7 @@ + + #pragma once + ++#include "AccessibilityObjectInterface.h" + #include "CSSSelector.h" + #include "CallTracerTypes.h" + #include "CanvasBase.h" +@@ -80,6 +81,7 @@ class DOMWrapperWorld; + class Document; + class DocumentLoader; + class EventListener; ++class HTMLInputElement; + class HTTPHeaderMap; + class InspectorTimelineAgent; + class InstrumentingAgents; +@@ -201,6 +203,7 @@ public: + static void didReceiveData(Frame*, unsigned long identifier, const char* data, int dataLength, int encodedDataLength); + static void didFinishLoading(Frame*, DocumentLoader*, unsigned long identifier, const NetworkLoadMetrics&, ResourceLoader*); + static void didFailLoading(Frame*, DocumentLoader*, unsigned long identifier, const ResourceError&); ++ static void didReceiveMainResourceError(Frame&, const ResourceError&); + + static void willSendRequest(WorkerOrWorkletGlobalScope&, unsigned long identifier, ResourceRequest&); + static void didReceiveResourceResponse(WorkerOrWorkletGlobalScope&, unsigned long identifier, const ResourceResponse&); +@@ -227,11 +230,11 @@ public: + static void frameDetachedFromParent(Frame&); + static void didCommitLoad(Frame&, DocumentLoader*); + static void frameDocumentUpdated(Frame&); +- static void loaderDetachedFromFrame(Frame&, DocumentLoader&); + static void frameStartedLoading(Frame&); + static void frameStoppedLoading(Frame&); + static void frameScheduledNavigation(Frame&, Seconds delay); + static void frameClearedScheduledNavigation(Frame&); ++ static void didNavigateWithinPage(Frame&); + #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT) + static void defaultAppearanceDidChange(Page&, bool useDarkAppearance); + #endif +@@ -326,6 +329,12 @@ public: + static void layerTreeDidChange(Page*); + static void renderLayerDestroyed(Page*, const RenderLayer&); + ++ static void runOpenPanel(Frame*, HTMLInputElement*, bool*); ++ static void frameAttached(Frame*); ++ static bool shouldBypassCSP(ScriptExecutionContext*); ++ static void willCheckNewWindowPolicy(Frame&, const URL&); ++ static void didCheckNewWindowPolicy(Frame&, bool allowed); ++ + static void frontendCreated(); + static void frontendDeleted(); + static bool hasFrontends() { return InspectorInstrumentationPublic::hasFrontends(); } +@@ -341,6 +350,8 @@ public: + static void registerInstrumentingAgents(InstrumentingAgents&); + static void unregisterInstrumentingAgents(InstrumentingAgents&); + ++ static void maybeOverrideDefaultObjectInclusion(Page&, AccessibilityObjectInclusion&); ++ + private: + static void didClearWindowObjectInWorldImpl(InstrumentingAgents&, Frame&, DOMWrapperWorld&); + static bool isDebuggerPausedImpl(InstrumentingAgents&); +@@ -428,6 +439,7 @@ private: + static void didReceiveDataImpl(InstrumentingAgents&, unsigned long identifier, const char* data, int dataLength, int encodedDataLength); + static void didFinishLoadingImpl(InstrumentingAgents&, unsigned long identifier, DocumentLoader*, const NetworkLoadMetrics&, ResourceLoader*); + static void didFailLoadingImpl(InstrumentingAgents&, unsigned long identifier, DocumentLoader*, const ResourceError&); ++ static void didReceiveMainResourceErrorImpl(InstrumentingAgents&, Frame&, const ResourceError&); + static void willLoadXHRSynchronouslyImpl(InstrumentingAgents&); + static void didLoadXHRSynchronouslyImpl(InstrumentingAgents&); + static void scriptImportedImpl(InstrumentingAgents&, unsigned long identifier, const String& sourceString); +@@ -438,11 +450,11 @@ private: + static void frameDetachedFromParentImpl(InstrumentingAgents&, Frame&); + static void didCommitLoadImpl(InstrumentingAgents&, Frame&, DocumentLoader*); + static void frameDocumentUpdatedImpl(InstrumentingAgents&, Frame&); +- static void loaderDetachedFromFrameImpl(InstrumentingAgents&, DocumentLoader&); + static void frameStartedLoadingImpl(InstrumentingAgents&, Frame&); + static void frameStoppedLoadingImpl(InstrumentingAgents&, Frame&); + static void frameScheduledNavigationImpl(InstrumentingAgents&, Frame&, Seconds delay); + static void frameClearedScheduledNavigationImpl(InstrumentingAgents&, Frame&); ++ static void didNavigateWithinPageImpl(InstrumentingAgents&, Frame&); + #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT) + static void defaultAppearanceDidChangeImpl(InstrumentingAgents&, bool useDarkAppearance); + #endif +@@ -533,6 +545,12 @@ private: + static void layerTreeDidChangeImpl(InstrumentingAgents&); + static void renderLayerDestroyedImpl(InstrumentingAgents&, const RenderLayer&); + ++ static void runOpenPanelImpl(InstrumentingAgents&, HTMLInputElement*, bool*); ++ static void frameAttachedImpl(InstrumentingAgents&, Frame&); ++ static bool shouldBypassCSPImpl(InstrumentingAgents&); ++ static void willCheckNewWindowPolicyImpl(InstrumentingAgents&, const URL&); ++ static void didCheckNewWindowPolicyImpl(InstrumentingAgents&, bool allowed); ++ + static InstrumentingAgents& instrumentingAgents(Page&); + static InstrumentingAgents& instrumentingAgents(WorkerOrWorkletGlobalScope&); + +@@ -1128,6 +1146,13 @@ inline void InspectorInstrumentation::didFailLoading(Frame* frame, DocumentLoade + didFailLoadingImpl(*agents, identifier, loader, error); + } + ++inline void InspectorInstrumentation::didReceiveMainResourceError(Frame& frame, const ResourceError& error) ++{ ++ FAST_RETURN_IF_NO_FRONTENDS(void()); ++ if (auto* agents = instrumentingAgents(frame)) ++ didReceiveMainResourceErrorImpl(*agents, frame, error); ++} ++ + inline void InspectorInstrumentation::didFailLoading(WorkerOrWorkletGlobalScope& globalScope, unsigned long identifier, const ResourceError& error) + { + didFailLoadingImpl(instrumentingAgents(globalScope), identifier, nullptr, error); +@@ -1223,13 +1248,6 @@ inline void InspectorInstrumentation::frameDocumentUpdated(Frame& frame) + frameDocumentUpdatedImpl(*agents, frame); + } + +-inline void InspectorInstrumentation::loaderDetachedFromFrame(Frame& frame, DocumentLoader& loader) +-{ +- FAST_RETURN_IF_NO_FRONTENDS(void()); +- if (auto* agents = instrumentingAgents(frame)) +- loaderDetachedFromFrameImpl(*agents, loader); +-} +- + inline void InspectorInstrumentation::frameStartedLoading(Frame& frame) + { + FAST_RETURN_IF_NO_FRONTENDS(void()); +@@ -1258,6 +1276,13 @@ inline void InspectorInstrumentation::frameClearedScheduledNavigation(Frame& fra + frameClearedScheduledNavigationImpl(*agents, frame); + } + ++inline void InspectorInstrumentation::didNavigateWithinPage(Frame& frame) ++{ ++ FAST_RETURN_IF_NO_FRONTENDS(void()); ++ if (auto* agents = instrumentingAgents(frame)) ++ didNavigateWithinPageImpl(*agents, frame); ++} ++ + #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT) + inline void InspectorInstrumentation::defaultAppearanceDidChange(Page& page, bool useDarkAppearance) + { +@@ -1732,6 +1757,42 @@ inline void InspectorInstrumentation::renderLayerDestroyed(Page* page, const Ren + renderLayerDestroyedImpl(*agents, renderLayer); + } + ++inline void InspectorInstrumentation::runOpenPanel(Frame* frame, HTMLInputElement* element, bool* intercept) ++{ ++ FAST_RETURN_IF_NO_FRONTENDS(void()); ++ if (auto* agents = instrumentingAgents(*frame)) ++ runOpenPanelImpl(*agents, element, intercept); ++} ++ ++inline void InspectorInstrumentation::frameAttached(Frame* frame) ++{ ++ FAST_RETURN_IF_NO_FRONTENDS(void()); ++ if (auto* agents = instrumentingAgents(frame)) ++ frameAttachedImpl(*agents, *frame); ++} ++ ++inline bool InspectorInstrumentation::shouldBypassCSP(ScriptExecutionContext* context) ++{ ++ FAST_RETURN_IF_NO_FRONTENDS(false); ++ if (auto* agents = instrumentingAgents(context)) ++ return shouldBypassCSPImpl(*agents); ++ return false; ++} ++ ++inline void InspectorInstrumentation::willCheckNewWindowPolicy(Frame& frame, const URL& url) ++{ ++ FAST_RETURN_IF_NO_FRONTENDS(void()); ++ if (auto* agents = instrumentingAgents(frame)) ++ willCheckNewWindowPolicyImpl(*agents, url); ++} ++ ++inline void InspectorInstrumentation::didCheckNewWindowPolicy(Frame& frame, bool allowed) ++{ ++ FAST_RETURN_IF_NO_FRONTENDS(void()); ++ if (auto* agents = instrumentingAgents(frame)) ++ didCheckNewWindowPolicyImpl(*agents, allowed); ++} ++ + inline InstrumentingAgents* InspectorInstrumentation::instrumentingAgents(ScriptExecutionContext* context) + { + return context ? instrumentingAgents(*context) : nullptr; +diff --git a/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp b/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp +index 5e343a54ba721729b81292c60639925dc1d0dea1..371229ab6bd7562bb903ba030b9fea650afed3d8 100644 +--- a/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp ++++ b/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp +@@ -62,12 +62,16 @@ + #include "Event.h" + #include "EventListener.h" + #include "EventNames.h" ++#include "File.h" ++#include "FileList.h" + #include "Frame.h" + #include "FrameTree.h" + #include "FrameView.h" + #include "FullscreenManager.h" ++#include "FloatQuad.h" + #include "HTMLElement.h" + #include "HTMLFrameOwnerElement.h" ++#include "HTMLInputElement.h" + #include "HTMLMediaElement.h" + #include "HTMLNames.h" + #include "HTMLParserIdioms.h" +@@ -94,11 +98,14 @@ + #include "Pasteboard.h" + #include "PseudoElement.h" + #include "RenderGrid.h" ++#include "RenderLayer.h" ++#include "RenderObject.h" + #include "RenderStyle.h" + #include "RenderStyleConstants.h" + #include "ScriptState.h" + #include "SelectorChecker.h" + #include "ShadowRoot.h" ++#include "SharedBuffer.h" + #include "StaticNodeList.h" + #include "StyleProperties.h" + #include "StyleResolver.h" +@@ -131,7 +138,8 @@ using namespace HTMLNames; + static const size_t maxTextSize = 10000; + static const UChar ellipsisUChar[] = { 0x2026, 0 }; + +-static Optional parseColor(RefPtr&& colorObject) ++// static ++Optional InspectorDOMAgent::parseColor(RefPtr&& colorObject) + { + if (!colorObject) + return WTF::nullopt; +@@ -150,7 +158,7 @@ static Optional parseColor(RefPtr&& colorObject) + + static Color parseConfigColor(const String& fieldName, JSON::Object& configObject) + { +- return parseColor(configObject.getObject(fieldName)).valueOr(Color::transparentBlack); ++ return InspectorDOMAgent::parseColor(configObject.getObject(fieldName)).valueOr(Color::transparentBlack); + } + + static bool parseQuad(Ref&& quadArray, FloatQuad* quad) +@@ -435,6 +443,20 @@ Node* InspectorDOMAgent::assertNode(Protocol::ErrorString& errorString, Protocol + return node; + } + ++Node* InspectorDOMAgent::assertNode(Protocol::ErrorString& errorString, Optional&& nodeId, const String& objectId) ++{ ++ Node* node = nullptr; ++ if (nodeId) { ++ node = assertNode(errorString, *nodeId); ++ } else if (!!objectId) { ++ node = nodeForObjectId(objectId); ++ if (!node) ++ errorString = "Missing node for given objectId"_s; ++ } else ++ errorString = "Either nodeId or objectId must be specified"_s; ++ return node; ++} ++ + Document* InspectorDOMAgent::assertDocument(Protocol::ErrorString& errorString, Protocol::DOM::NodeId nodeId) + { + Node* node = assertNode(errorString, nodeId); +@@ -1394,16 +1416,7 @@ Protocol::ErrorStringOr InspectorDOMAgent::highlightSelector(Ref InspectorDOMAgent::highlightNode(Ref&& highlightInspectorObject, Optional&& nodeId, const Protocol::Runtime::RemoteObjectId& objectId) + { + Protocol::ErrorString errorString; +- +- Node* node = nullptr; +- if (nodeId) +- node = assertNode(errorString, *nodeId); +- else if (!!objectId) { +- node = nodeForObjectId(objectId); +- errorString = "Missing node for given objectId"_s; +- } else +- errorString = "Either nodeId or objectId must be specified"_s; +- ++ Node* node = assertNode(errorString, WTFMove(nodeId), objectId); + if (!node) + return makeUnexpected(errorString); + +@@ -1605,15 +1618,136 @@ Protocol::ErrorStringOr InspectorDOMAgent::setInspectedNode(Protocol::DOM: + return { }; + } + +-Protocol::ErrorStringOr> InspectorDOMAgent::resolveNode(Protocol::DOM::NodeId nodeId, const String& objectGroup) ++static FloatPoint contentsToRootView(FrameView& containingView, const FloatPoint& point) + { +- Protocol::ErrorString errorString; ++ return containingView.convertToRootView(point - toFloatSize(containingView.documentScrollPositionRelativeToViewOrigin())); ++} + +- Node* node = assertNode(errorString, nodeId); ++static void frameQuadToViewport(FrameView& containingView, FloatQuad& quad, float pageScaleFactor) ++{ ++ // Return css (not dip) coordinates by scaling back. ++ quad.setP1(contentsToRootView(containingView, quad.p1()).scaled(1 / pageScaleFactor)); ++ quad.setP2(contentsToRootView(containingView, quad.p2()).scaled(1 / pageScaleFactor)); ++ quad.setP3(contentsToRootView(containingView, quad.p3()).scaled(1 / pageScaleFactor)); ++ quad.setP4(contentsToRootView(containingView, quad.p4()).scaled(1 / pageScaleFactor)); ++} ++ ++static Ref buildObjectForQuad(const FloatQuad& quad) ++{ ++ auto result = Inspector::Protocol::DOM::Quad::create(); ++ result->addItem(quad.p1().x()); ++ result->addItem(quad.p1().y()); ++ result->addItem(quad.p2().x()); ++ result->addItem(quad.p2().y()); ++ result->addItem(quad.p3().x()); ++ result->addItem(quad.p3().y()); ++ result->addItem(quad.p4().x()); ++ result->addItem(quad.p4().y()); ++ return result; ++} ++ ++static Ref> buildArrayOfQuads(const Vector& quads) ++{ ++ auto result = JSON::ArrayOf::create(); ++ for (const auto& quad : quads) ++ result->addItem(buildObjectForQuad(quad)); ++ return result; ++} ++ ++Inspector::Protocol::ErrorStringOr> InspectorDOMAgent::describeNode(const String& objectId) ++{ ++ Node* node = nodeForObjectId(objectId); ++ if (!node) ++ return makeUnexpected("Node not found"_s); ++ ++ auto* pageAgent = m_instrumentingAgents.enabledPageAgent(); ++ if (!pageAgent) ++ return makeUnexpected("Page agent must be enabled"_s); ++ ++ String ownerFrameId; ++ String frameId = pageAgent->frameId(node->document().frame()); ++ if (!frameId.isEmpty()) ++ ownerFrameId = frameId; ++ ++ String contentFrameId; ++ if (is(*node)) { ++ const auto& frameOwner = downcast(*node); ++ String frameId = pageAgent->frameId(frameOwner.contentFrame()); ++ if (!frameId.isEmpty()) ++ contentFrameId = frameId; ++ } ++ ++ return { { contentFrameId, ownerFrameId } }; ++} ++ ++Protocol::ErrorStringOr InspectorDOMAgent::scrollIntoViewIfNeeded(const String& objectId, RefPtr&& rect) ++{ ++ Node* node = nodeForObjectId(objectId); ++ if (!node) ++ return makeUnexpected("Node not found"_s); ++ ++ m_inspectedPage.isolatedUpdateRendering(); ++ if (!node->isConnected()) ++ return makeUnexpected("Node is detached from document"_s); ++ ++ RenderObject* renderer = node->renderer(); ++ if (!renderer) ++ return makeUnexpected("Node does not have a layout object"_s); ++ ++ bool insideFixed; ++ LayoutRect absoluteBounds = renderer->absoluteBoundingBoxRect(true, &insideFixed); ++ if (rect) { ++ Optional x = rect->getDouble("x"); ++ Optional y = rect->getDouble("y"); ++ Optional width = rect->getDouble("width"); ++ Optional height = rect->getDouble("height"); ++ if (!x || !y || !width || !height) ++ return makeUnexpected("Malformed rect"_s); ++ ++ absoluteBounds.setX(absoluteBounds.x() + LayoutUnit(*x)); ++ absoluteBounds.setY(absoluteBounds.y() + LayoutUnit(*y)); ++ absoluteBounds.setWidth(LayoutUnit(std::max(*width, 1.0))); ++ absoluteBounds.setHeight(LayoutUnit(std::max(*height, 1.0))); ++ } ++ ScrollAlignment alignment = ScrollAlignment::alignCenterIfNeeded; ++ alignment.m_disableMinThreshold = true; // Disable RenderLayer minium horizontal scroll threshold. ++ renderer->scrollRectToVisible(absoluteBounds, insideFixed, { SelectionRevealMode::Reveal, alignment, alignment, ShouldAllowCrossOriginScrolling::Yes }); ++ return { }; ++} ++ ++Protocol::ErrorStringOr>> InspectorDOMAgent::getContentQuads(const String& objectId) ++{ ++ Node* node = nodeForObjectId(objectId); ++ if (!node) ++ return makeUnexpected("Node not found"_s); ++ ++ RenderObject* renderer = node->renderer(); ++ if (!renderer) ++ return makeUnexpected("Node doesn't have renderer"_s); ++ ++ // Ensure quads are up to date. ++ m_inspectedPage.isolatedUpdateRendering(); ++ ++ Frame* containingFrame = renderer->document().frame(); ++ FrameView* containingView = containingFrame ? containingFrame->view() : nullptr; ++ if (!containingView) ++ return makeUnexpected("Internal error: no containing view"_s); ++ ++ Vector quads; ++ renderer->absoluteQuads(quads); ++ for (auto& quad : quads) ++ frameQuadToViewport(*containingView, quad, m_inspectedPage.pageScaleFactor()); ++ return buildArrayOfQuads(quads); ++} ++ ++Protocol::ErrorStringOr> InspectorDOMAgent::resolveNode(Optional&& nodeId, const String& objectId, Optional&& contextId, const String& objectGroup) ++{ ++ Protocol::ErrorString errorString; ++ Node* node = assertNode(errorString, WTFMove(nodeId), objectId); + if (!node) + return makeUnexpected(errorString); + +- auto object = resolveNode(node, objectGroup); ++ auto object = resolveNode(node, objectGroup, WTFMove(contextId)); + if (!object) + return makeUnexpected("Missing injected script for given nodeId"_s); + +@@ -2807,7 +2941,7 @@ Protocol::ErrorStringOr InspectorDOMAgent::pushNodeByPath + return makeUnexpected("Missing node for given path"_s); + } + +-RefPtr InspectorDOMAgent::resolveNode(Node* node, const String& objectGroup) ++RefPtr InspectorDOMAgent::resolveNode(Node* node, const String& objectGroup, Optional&& contextId) + { + Document* document = &node->document(); + if (auto* templateHost = document->templateDocumentHost()) +@@ -2816,12 +2950,16 @@ RefPtr InspectorDOMAgent::resolveNode(Node* nod + if (!frame) + return nullptr; + +- auto& state = *mainWorldExecState(frame); +- auto injectedScript = m_injectedScriptManager.injectedScriptFor(&state); ++ InjectedScript injectedScript; ++ if (contextId) { ++ injectedScript = m_injectedScriptManager.injectedScriptForId(*contextId); ++ } else { ++ injectedScript = m_injectedScriptManager.injectedScriptFor(mainWorldExecState(frame)); ++ } + if (injectedScript.hasNoValue()) + return nullptr; + +- return injectedScript.wrapObject(nodeAsScriptValue(state, node), objectGroup); ++ return injectedScript.wrapObject(nodeAsScriptValue(*injectedScript.globalObject(), node), objectGroup); + } + + Node* InspectorDOMAgent::scriptValueAsNode(JSC::JSValue value) +@@ -2844,4 +2982,42 @@ Protocol::ErrorStringOr InspectorDOMAgent::setAllowEditingUserAgentShadowT + return { }; + } + ++Protocol::ErrorStringOr InspectorDOMAgent::setInputFiles(const String& objectId, Ref&& files) { ++ InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId); ++ if (injectedScript.hasNoValue()) ++ return makeUnexpected("Can not find element's context for given id"_s); ++ ++ Node* node = scriptValueAsNode(injectedScript.findObjectById(objectId)); ++ if (!node) ++ return makeUnexpected("Can not find element for given id"_s); ++ ++ if (node->nodeType() != Node::ELEMENT_NODE || node->nodeName() != "INPUT") ++ return makeUnexpected("Not an input node"_s); ++ ++ HTMLInputElement* element = static_cast(node); ++ Vector> fileObjects; ++ for (unsigned i = 0; i < files->length(); ++i) { ++ RefPtr item = files->get(i); ++ RefPtr obj = item->asObject(); ++ if (!obj) ++ return makeUnexpected("Invalid file payload format"_s); ++ ++ String name; ++ String type; ++ String data; ++ if (!obj->getString("name", name) || !obj->getString("type", type) || !obj->getString("data", data)) ++ return makeUnexpected("Invalid file payload format"_s); ++ ++ Vector buffer; ++ if (!base64Decode(data, buffer)) ++ return makeUnexpected("Unable to decode given content"_s); ++ ++ ScriptExecutionContext* context = element->scriptExecutionContext(); ++ fileObjects.append(File::create(context, Blob::create(context, SharedBuffer::create(WTFMove(buffer)), type), name)); ++ } ++ RefPtr fileList = FileList::create(WTFMove(fileObjects)); ++ element->setFiles(WTFMove(fileList)); ++ return { }; ++} ++ + } // namespace WebCore +diff --git a/Source/WebCore/inspector/agents/InspectorDOMAgent.h b/Source/WebCore/inspector/agents/InspectorDOMAgent.h +index fd4ea25d520f411c8a80ddc391fc1a3acf259c7e..333ad9fbdf2132454452306460867c1e1054801b 100644 +--- a/Source/WebCore/inspector/agents/InspectorDOMAgent.h ++++ b/Source/WebCore/inspector/agents/InspectorDOMAgent.h +@@ -56,6 +56,7 @@ namespace WebCore { + + class AXCoreObject; + class CharacterData; ++class Color; + class DOMEditor; + class Document; + class Element; +@@ -85,6 +86,7 @@ public: + static String toErrorString(Exception&&); + + static String documentURLString(Document*); ++ static Optional parseColor(RefPtr&&); + + // We represent embedded doms as a part of the same hierarchy. Hence we treat children of frame owners differently. + // We also skip whitespace text nodes conditionally. Following methods encapsulate these specifics. +@@ -128,7 +130,7 @@ public: + Inspector::Protocol::ErrorStringOr> performSearch(const String& query, RefPtr&& nodeIds, Optional&& caseSensitive); + Inspector::Protocol::ErrorStringOr>> getSearchResults(const String& searchId, int fromIndex, int toIndex); + Inspector::Protocol::ErrorStringOr discardSearchResults(const String& searchId); +- Inspector::Protocol::ErrorStringOr> resolveNode(Inspector::Protocol::DOM::NodeId, const String& objectGroup); ++ Inspector::Protocol::ErrorStringOr> resolveNode(Optional&& nodeId, const String& objectId, Optional&& contextId, const String& objectGroup); + Inspector::Protocol::ErrorStringOr>> getAttributes(Inspector::Protocol::DOM::NodeId); + #if PLATFORM(IOS_FAMILY) + Inspector::Protocol::ErrorStringOr setInspectModeEnabled(bool, RefPtr&& highlightConfig); +@@ -153,6 +155,10 @@ public: + Inspector::Protocol::ErrorStringOr focus(Inspector::Protocol::DOM::NodeId); + Inspector::Protocol::ErrorStringOr setInspectedNode(Inspector::Protocol::DOM::NodeId); + Inspector::Protocol::ErrorStringOr setAllowEditingUserAgentShadowTrees(bool); ++ Inspector::Protocol::ErrorStringOr> describeNode(const String& objectId); ++ Inspector::Protocol::ErrorStringOr scrollIntoViewIfNeeded(const String& objectId, RefPtr&& rect); ++ Inspector::Protocol::ErrorStringOr>> getContentQuads(const String& objectId); ++ Inspector::Protocol::ErrorStringOr setInputFiles(const String& objectId, Ref&& files); + + // InspectorInstrumentation + Inspector::Protocol::DOM::NodeId identifierForNode(Node&); +@@ -190,7 +196,7 @@ public: + Node* nodeForId(Inspector::Protocol::DOM::NodeId); + Inspector::Protocol::DOM::NodeId boundNodeId(const Node*); + +- RefPtr resolveNode(Node*, const String& objectGroup); ++ RefPtr resolveNode(Node*, const String& objectGroup, Optional&& contextId); + bool handleMousePress(); + void mouseDidMoveOverElement(const HitTestResult&, unsigned modifierFlags); + void inspect(Node*); +@@ -201,12 +207,15 @@ public: + void reset(); + + Node* assertNode(Inspector::Protocol::ErrorString&, Inspector::Protocol::DOM::NodeId); ++ Node* assertNode(Inspector::Protocol::ErrorString&, Optional&& nodeId, const String& objectId); + Element* assertElement(Inspector::Protocol::ErrorString&, Inspector::Protocol::DOM::NodeId); + Document* assertDocument(Inspector::Protocol::ErrorString&, Inspector::Protocol::DOM::NodeId); + + RefPtr breakpointForEventListener(EventTarget&, const AtomString& eventType, EventListener&, bool capture); + Inspector::Protocol::DOM::EventListenerId idForEventListener(EventTarget&, const AtomString& eventType, EventListener&, bool capture); + ++ Node* nodeForObjectId(const Inspector::Protocol::Runtime::RemoteObjectId&); ++ + private: + #if ENABLE(VIDEO) + void mediaMetricsTimerFired(); +@@ -236,7 +245,6 @@ private: + void processAccessibilityChildren(AXCoreObject&, JSON::ArrayOf&); + + Node* nodeForPath(const String& path); +- Node* nodeForObjectId(const Inspector::Protocol::Runtime::RemoteObjectId&); + + void discardBindings(); + +diff --git a/Source/WebCore/inspector/agents/InspectorDOMStorageAgent.h b/Source/WebCore/inspector/agents/InspectorDOMStorageAgent.h +index 3386cb879f1178c1b9635775c9a0e864f5b94c52..d2350182f5f061855e8ca172779ad60ee73b39fb 100644 +--- a/Source/WebCore/inspector/agents/InspectorDOMStorageAgent.h ++++ b/Source/WebCore/inspector/agents/InspectorDOMStorageAgent.h +@@ -40,6 +40,7 @@ class DOMStorageFrontendDispatcher; + + namespace WebCore { + ++class Color; + class Frame; + class Page; + class SecurityOrigin; +diff --git a/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp b/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp +index 292d2c2940da6a410ec68fb665e3e9d70df71b4a..54cf2a65c57b99c449e4c22e9c4a824bbf2c395b 100644 +--- a/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp ++++ b/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp +@@ -45,6 +45,7 @@ + #include "DocumentThreadableLoader.h" + #include "FormData.h" + #include "Frame.h" ++#include "FormData.h" + #include "FrameLoader.h" + #include "HTTPHeaderMap.h" + #include "HTTPHeaderNames.h" +@@ -57,6 +58,7 @@ + #include "MIMETypeRegistry.h" + #include "MemoryCache.h" + #include "NetworkResourcesData.h" ++#include "NetworkStateNotifier.h" + #include "Page.h" + #include "PlatformStrategies.h" + #include "ProgressTracker.h" +@@ -309,8 +311,8 @@ static Ref buildObjectForResourceRequest(const Resou + .setHeaders(buildObjectForHeaders(request.httpHeaderFields())) + .release(); + if (request.httpBody() && !request.httpBody()->isEmpty()) { +- auto bytes = request.httpBody()->flatten(); +- requestObject->setPostData(String::fromUTF8WithLatin1Fallback(bytes.data(), bytes.size())); ++ Vector bytes = request.httpBody()->flatten(); ++ requestObject->setPostData(base64Encode(bytes)); + } + return requestObject; + } +@@ -355,6 +357,8 @@ RefPtr InspectorNetworkAgent::buildObjectForResourc + .setSource(responseSource(response.source())) + .release(); + ++ responseObject->setRequestHeaders(buildObjectForHeaders(response.m_httpRequestHeaderFields)); ++ + if (resourceLoader) + responseObject->setTiming(buildObjectForTiming(response.deprecatedNetworkLoadMetricsOrNull(), *resourceLoader)); + +@@ -490,8 +494,14 @@ static InspectorPageAgent::ResourceType resourceTypeForLoadType(InspectorInstrum + + void InspectorNetworkAgent::willSendRequest(unsigned long identifier, DocumentLoader* loader, ResourceRequest& request, const ResourceResponse& redirectResponse) + { +- auto* cachedResource = loader ? InspectorPageAgent::cachedResource(loader->frame(), request.url()) : nullptr; +- willSendRequest(identifier, loader, request, redirectResponse, resourceTypeForCachedResource(cachedResource)); ++ InspectorPageAgent::ResourceType resourceType; ++ if (request.initiatorIdentifier() == initiatorIdentifierForEventSource()) { ++ resourceType = InspectorPageAgent::EventSource; ++ } else { ++ auto* cachedResource = loader ? InspectorPageAgent::cachedResource(loader->frame(), request.url()) : nullptr; ++ resourceType = resourceTypeForCachedResource(cachedResource); ++ } ++ willSendRequest(identifier, loader, request, redirectResponse, resourceType); + } + + void InspectorNetworkAgent::willSendRequestOfType(unsigned long identifier, DocumentLoader* loader, ResourceRequest& request, InspectorInstrumentation::LoadType loadType) +@@ -1105,8 +1115,7 @@ bool InspectorNetworkAgent::willIntercept(const ResourceRequest& request) + if (!m_interceptionEnabled) + return false; + +- return shouldIntercept(request.url(), Protocol::Network::NetworkStage::Request) +- || shouldIntercept(request.url(), Protocol::Network::NetworkStage::Response); ++ return shouldIntercept(request.url(), Protocol::Network::NetworkStage::Response); + } + + bool InspectorNetworkAgent::shouldInterceptRequest(const ResourceRequest& request) +@@ -1189,6 +1198,9 @@ Protocol::ErrorStringOr InspectorNetworkAgent::interceptWithRequest(const + return makeUnexpected("Missing pending intercept request for given requestId"_s); + + auto& loader = *pendingRequest->m_loader; ++ if (loader.reachedTerminalState()) ++ return makeUnexpected("Unable to intercept request, it has already been processed"_s); ++ + ResourceRequest request = loader.request(); + if (!!url) + request.setURL(URL({ }, url)); +@@ -1284,14 +1296,24 @@ Protocol::ErrorStringOr InspectorNetworkAgent::interceptRequestWithRespons + response.setHTTPStatusCode(status); + response.setHTTPStatusText(statusText); + HTTPHeaderMap explicitHeaders; ++ String setCookieValue; + for (auto& header : headers.get()) { + auto headerValue = header.value->asString(); + if (!!headerValue) + explicitHeaders.add(header.key, headerValue); ++ if (equalIgnoringASCIICase(header.key, "Set-Cookie")) ++ setCookieValue = headerValue; + } + response.setHTTPHeaderFields(WTFMove(explicitHeaders)); + response.setHTTPHeaderField(HTTPHeaderName::ContentType, response.mimeType()); ++ ++ auto* frame = loader->frame(); ++ if (!setCookieValue.isEmpty() && frame && frame->page()) ++ frame->page()->cookieJar().setCookieFromResponse(*loader.get(), setCookieValue); ++ + loader->didReceiveResponse(response, [loader, buffer = data.releaseNonNull()]() mutable { ++ if (loader->reachedTerminalState()) ++ return; + if (buffer->size()) + loader->didReceiveBuffer(WTFMove(buffer), buffer->size(), DataPayloadWholeResource); + loader->didFinishLoading(NetworkLoadMetrics()); +@@ -1332,6 +1354,12 @@ Protocol::ErrorStringOr InspectorNetworkAgent::interceptRequestWithError(c + return { }; + } + ++Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::setEmulateOfflineState(bool offline) ++{ ++ platformStrategies()->loaderStrategy()->setEmulateOfflineState(offline); ++ return { }; ++} ++ + bool InspectorNetworkAgent::shouldTreatAsText(const String& mimeType) + { + return startsWithLettersIgnoringASCIICase(mimeType, "text/") +@@ -1373,6 +1401,12 @@ Optional InspectorNetworkAgent::textContentForCachedResource(CachedResou + return WTF::nullopt; + } + ++// static ++String InspectorNetworkAgent::initiatorIdentifierForEventSource() ++{ ++ return "InspectorNetworkAgent: eventSource"_s; ++} ++ + bool InspectorNetworkAgent::cachedResourceContent(CachedResource& resource, String* result, bool* base64Encoded) + { + ASSERT(result); +diff --git a/Source/WebCore/inspector/agents/InspectorNetworkAgent.h b/Source/WebCore/inspector/agents/InspectorNetworkAgent.h +index 933601761667417ebe5de301586869ccc64fc3da..f63a95c3c45980d5606971b83881e8245df11403 100644 +--- a/Source/WebCore/inspector/agents/InspectorNetworkAgent.h ++++ b/Source/WebCore/inspector/agents/InspectorNetworkAgent.h +@@ -71,6 +71,7 @@ public: + static Ref createTextDecoder(const String& mimeType, const String& textEncodingName); + static Optional textContentForCachedResource(CachedResource&); + static bool cachedResourceContent(CachedResource&, String* result, bool* base64Encoded); ++ static String initiatorIdentifierForEventSource(); + + // InspectorAgentBase + void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) final; +@@ -93,6 +94,7 @@ public: + Inspector::Protocol::ErrorStringOr interceptWithResponse(const Inspector::Protocol::Network::RequestId&, const String& content, bool base64Encoded, const String& mimeType, Optional&& status, const String& statusText, RefPtr&& headers) final; + Inspector::Protocol::ErrorStringOr interceptRequestWithResponse(const Inspector::Protocol::Network::RequestId&, const String& content, bool base64Encoded, const String& mimeType, int status, const String& statusText, Ref&& headers) final; + Inspector::Protocol::ErrorStringOr interceptRequestWithError(const Inspector::Protocol::Network::RequestId&, Inspector::Protocol::Network::ResourceErrorType) final; ++ Inspector::Protocol::ErrorStringOr setEmulateOfflineState(bool offline) final; + + // InspectorInstrumentation + void willRecalculateStyle(); +diff --git a/Source/WebCore/inspector/agents/InspectorPageAgent.cpp b/Source/WebCore/inspector/agents/InspectorPageAgent.cpp +index af0a051bdae52b2daf70b1fee76eee0866b7b046..b8a55168af379e51a62ffd8181b70f1ddeec40bc 100644 +--- a/Source/WebCore/inspector/agents/InspectorPageAgent.cpp ++++ b/Source/WebCore/inspector/agents/InspectorPageAgent.cpp +@@ -32,19 +32,25 @@ + #include "config.h" + #include "InspectorPageAgent.h" + ++#include "AXObjectCache.h" ++#include "BackForwardController.h" + #include "CachedResource.h" + #include "CachedResourceLoader.h" + #include "Cookie.h" + #include "CookieJar.h" ++#include "CustomHeaderFields.h" + #include "DOMWrapperWorld.h" + #include "Document.h" + #include "DocumentLoader.h" ++#include "FocusController.h" + #include "Frame.h" + #include "FrameLoadRequest.h" + #include "FrameLoader.h" ++#include "FrameLoaderClient.h" + #include "FrameSnapshotting.h" + #include "FrameView.h" + #include "HTMLFrameOwnerElement.h" ++#include "HTMLInputElement.h" + #include "HTMLNames.h" + #include "ImageBuffer.h" + #include "InspectorClient.h" +@@ -55,19 +61,28 @@ + #include "MIMETypeRegistry.h" + #include "MemoryCache.h" + #include "Page.h" ++#include "PageRuntimeAgent.h" + #include "RenderObject.h" + #include "RenderTheme.h" ++#include "RuntimeEnabledFeatures.h" + #include "ScriptController.h" + #include "ScriptSourceCode.h" ++#include "ScriptState.h" + #include "SecurityOrigin.h" + #include "Settings.h" + #include "StyleScope.h" + #include "TextEncoding.h" ++#include "TypingCommand.h" + #include "UserGestureIndicator.h" + #include + #include ++#include + #include ++#include + #include ++#include ++#include ++#include + #include + #include + #include +@@ -80,11 +95,15 @@ + #include "LegacyWebArchive.h" + #endif + +- + namespace WebCore { + + using namespace Inspector; + ++static HashMap>& createdUserWorlds() { ++ static NeverDestroyed>> nameToWorld; ++ return nameToWorld; ++} ++ + static bool decodeBuffer(const char* buffer, unsigned size, const String& textEncodingName, String* result) + { + if (buffer) { +@@ -234,6 +253,8 @@ Protocol::Page::ResourceType InspectorPageAgent::resourceTypeJSON(InspectorPageA + return Protocol::Page::ResourceType::Beacon; + case WebSocketResource: + return Protocol::Page::ResourceType::WebSocket; ++ case EventSource: ++ return Protocol::Page::ResourceType::EventSource; + case OtherResource: + return Protocol::Page::ResourceType::Other; + #if ENABLE(APPLICATION_MANIFEST) +@@ -321,6 +342,7 @@ InspectorPageAgent::InspectorPageAgent(PageAgentContext& context, InspectorClien + , m_frontendDispatcher(makeUnique(context.frontendRouter)) + , m_backendDispatcher(Inspector::PageBackendDispatcher::create(context.backendDispatcher, this)) + , m_inspectedPage(context.inspectedPage) ++ , m_injectedScriptManager(context.injectedScriptManager) + , m_client(client) + , m_overlay(overlay) + { +@@ -352,12 +374,20 @@ Protocol::ErrorStringOr InspectorPageAgent::enable() + defaultAppearanceDidChange(m_inspectedPage.defaultUseDarkAppearance()); + #endif + ++ if (!createdUserWorlds().isEmpty()) { ++ Vector worlds; ++ for (const auto& world : createdUserWorlds().values()) ++ worlds.append(world.ptr()); ++ ensureUserWorldsExistInAllFrames(worlds); ++ } + return { }; + } + + Protocol::ErrorStringOr InspectorPageAgent::disable() + { + m_instrumentingAgents.setEnabledPageAgent(nullptr); ++ m_interceptFileChooserDialog = false; ++ m_bypassCSP = false; + + setShowPaintRects(false); + #if !PLATFORM(IOS_FAMILY) +@@ -406,6 +436,22 @@ Protocol::ErrorStringOr InspectorPageAgent::reload(Optional&& ignore + return { }; + } + ++Protocol::ErrorStringOr InspectorPageAgent::goBack() ++{ ++ if (!m_inspectedPage.backForward().goBack()) ++ return makeUnexpected("Failed to go back"_s); ++ ++ return { }; ++} ++ ++Protocol::ErrorStringOr InspectorPageAgent::goForward() ++{ ++ if (!m_inspectedPage.backForward().goForward()) ++ return makeUnexpected("Failed to go forward"_s); ++ ++ return { }; ++} ++ + Protocol::ErrorStringOr InspectorPageAgent::navigate(const String& url) + { + UserGestureIndicator indicator { ProcessingUserGesture }; +@@ -801,15 +847,16 @@ Protocol::ErrorStringOr InspectorPageAgent::setShowPaintRects(bool show) + return { }; + } + +-void InspectorPageAgent::domContentEventFired() ++void InspectorPageAgent::domContentEventFired(Frame& frame) + { +- m_isFirstLayoutAfterOnLoad = true; +- m_frontendDispatcher->domContentEventFired(timestamp()); ++ if (frame.isMainFrame()) ++ m_isFirstLayoutAfterOnLoad = true; ++ m_frontendDispatcher->domContentEventFired(timestamp(), frameId(&frame)); + } + +-void InspectorPageAgent::loadEventFired() ++void InspectorPageAgent::loadEventFired(Frame& frame) + { +- m_frontendDispatcher->loadEventFired(timestamp()); ++ m_frontendDispatcher->loadEventFired(timestamp(), frameId(&frame)); + } + + void InspectorPageAgent::frameNavigated(Frame& frame) +@@ -817,13 +864,23 @@ void InspectorPageAgent::frameNavigated(Frame& frame) + m_frontendDispatcher->frameNavigated(buildObjectForFrame(&frame)); + } + ++String InspectorPageAgent::makeFrameID(ProcessIdentifier processID, FrameIdentifier frameID) ++{ ++ return makeString(processID.toUInt64(), ".", frameID.toUInt64()); ++} ++ ++static String globalIDForFrame(Frame& frame) ++{ ++ return InspectorPageAgent::makeFrameID(Process::identifier(), *frame.loader().client().frameID()); ++} ++ + void InspectorPageAgent::frameDetached(Frame& frame) + { +- auto identifier = m_frameToIdentifier.take(&frame); +- if (identifier.isNull()) ++ String identifier = globalIDForFrame(frame); ++ if (!m_identifierToFrame.take(identifier)) + return; ++ + m_frontendDispatcher->frameDetached(identifier); +- m_identifierToFrame.remove(identifier); + } + + Frame* InspectorPageAgent::frameForId(const Protocol::Network::FrameId& frameId) +@@ -835,20 +892,18 @@ String InspectorPageAgent::frameId(Frame* frame) + { + if (!frame) + return emptyString(); +- return m_frameToIdentifier.ensure(frame, [this, frame] { +- auto identifier = IdentifiersFactory::createIdentifier(); +- m_identifierToFrame.set(identifier, makeWeakPtr(frame)); +- return identifier; +- }).iterator->value; ++ ++ String identifier = globalIDForFrame(*frame); ++ m_identifierToFrame.set(identifier, makeWeakPtr(frame)); ++ return identifier; + } + + String InspectorPageAgent::loaderId(DocumentLoader* loader) + { + if (!loader) + return emptyString(); +- return m_loaderToIdentifier.ensure(loader, [] { +- return IdentifiersFactory::createIdentifier(); +- }).iterator->value; ++ ++ return String::number(loader->loaderIDForInspector()); + } + + Frame* InspectorPageAgent::assertFrame(Protocol::ErrorString& errorString, const Protocol::Network::FrameId& frameId) +@@ -859,11 +914,6 @@ Frame* InspectorPageAgent::assertFrame(Protocol::ErrorString& errorString, const + return frame; + } + +-void InspectorPageAgent::loaderDetachedFromFrame(DocumentLoader& loader) +-{ +- m_loaderToIdentifier.remove(&loader); +-} +- + void InspectorPageAgent::frameStartedLoading(Frame& frame) + { + m_frontendDispatcher->frameStartedLoading(frameId(&frame)); +@@ -884,6 +934,12 @@ void InspectorPageAgent::frameClearedScheduledNavigation(Frame& frame) + m_frontendDispatcher->frameClearedScheduledNavigation(frameId(&frame)); + } + ++void InspectorPageAgent::didNavigateWithinPage(Frame& frame) ++{ ++ String url = frame.document()->url().string(); ++ m_frontendDispatcher->navigatedWithinDocument(frameId(&frame), url); ++} ++ + #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT) + void InspectorPageAgent::defaultAppearanceDidChange(bool useDarkAppearance) + { +@@ -943,6 +999,52 @@ void InspectorPageAgent::didRecalculateStyle() + m_overlay->update(); + } + ++void InspectorPageAgent::runOpenPanel(HTMLInputElement* element, bool* intercept) ++{ ++ if (m_interceptFileChooserDialog) { ++ *intercept = true; ++ } else { ++ return; ++ } ++ Document& document = element->document(); ++ auto* frame = document.frame(); ++ if (!frame) ++ return; ++ ++ auto& state = *mainWorldExecState(frame); ++ auto injectedScript = m_injectedScriptManager.injectedScriptFor(&state); ++ if (injectedScript.hasNoValue()) ++ return; ++ ++ auto object = injectedScript.wrapObject(InspectorDOMAgent::nodeAsScriptValue(state, element), WTF::String()); ++ if (!object) ++ return; ++ ++ m_frontendDispatcher->fileChooserOpened(frameId(frame), object.releaseNonNull()); ++} ++ ++void InspectorPageAgent::frameAttached(Frame& frame) ++{ ++ Frame* parent = frame.tree().parent(); ++ String parentFrameId = frameId(parent); ++ m_frontendDispatcher->frameAttached(frameId(&frame), parentFrameId); ++} ++ ++bool InspectorPageAgent::shouldBypassCSP() ++{ ++ return m_bypassCSP; ++} ++ ++void InspectorPageAgent::willCheckNewWindowPolicy(const URL& url) ++{ ++ m_frontendDispatcher->willRequestOpenWindow(url.string()); ++} ++ ++void InspectorPageAgent::didCheckNewWindowPolicy(bool allowed) ++{ ++ m_frontendDispatcher->didRequestOpenWindow(allowed); ++} ++ + Ref InspectorPageAgent::buildObjectForFrame(Frame* frame) + { + ASSERT_ARG(frame, frame); +@@ -1094,6 +1196,27 @@ Protocol::ErrorStringOr InspectorPageAgent::snapshotRect(int x, int y, i + return snapshot->toDataURL("image/png"_s, WTF::nullopt, PreserveResolution::Yes); + } + ++Protocol::ErrorStringOr InspectorPageAgent::setTimeZone(const String& timeZone) ++{ ++ bool success = WTF::setTimeZoneForAutomation(timeZone); ++ if (!success) ++ return makeUnexpected("Invalid time zone " + timeZone); ++ ++ return { }; ++} ++ ++Protocol::ErrorStringOr InspectorPageAgent::setTouchEmulationEnabled(bool enabled) ++{ ++#if ENABLE(TOUCH_EVENTS) ++ RuntimeEnabledFeatures::sharedFeatures().setTouchEventsEnabled(enabled); ++ return { }; ++#else ++ UNUSED_PARAM(enabled); ++ return makeUnexpected("Not supported"_s); ++#endif ++} ++ ++ + #if ENABLE(WEB_ARCHIVE) && USE(CF) + Protocol::ErrorStringOr InspectorPageAgent::archive() + { +@@ -1106,7 +1229,6 @@ Protocol::ErrorStringOr InspectorPageAgent::archive() + } + #endif + +-#if !PLATFORM(COCOA) + Protocol::ErrorStringOr InspectorPageAgent::setScreenSizeOverride(Optional&& width, Optional&& height) + { + if (width.hasValue() != height.hasValue()) +@@ -1121,6 +1243,533 @@ Protocol::ErrorStringOr InspectorPageAgent::setScreenSizeOverride(Optional + m_inspectedPage.mainFrame().setOverrideScreenSize(FloatSize(width.valueOr(0), height.valueOr(0))); + return { }; + } ++ ++Protocol::ErrorStringOr InspectorPageAgent::insertText(const String& text) ++{ ++ UserGestureIndicator indicator { ProcessingUserGesture }; ++ Document* focusedDocument = m_inspectedPage.focusController().focusedOrMainFrame().document(); ++ TypingCommand::insertText(*focusedDocument, text, 0); ++ return { }; ++} ++ ++static String roleFromObject(RefPtr axObject) ++{ ++ String computedRoleString = axObject->computedRoleString(); ++ if (!computedRoleString.isEmpty()) ++ return computedRoleString; ++ AccessibilityRole role = axObject->roleValue(); ++ switch(role) { ++ case AccessibilityRole::Annotation: ++ return "Annotation"; ++ case AccessibilityRole::Application: ++ return "Application"; ++ case AccessibilityRole::ApplicationAlert: ++ return "ApplicationAlert"; ++ case AccessibilityRole::ApplicationAlertDialog: ++ return "ApplicationAlertDialog"; ++ case AccessibilityRole::ApplicationDialog: ++ return "ApplicationDialog"; ++ case AccessibilityRole::ApplicationGroup: ++ return "ApplicationGroup"; ++ case AccessibilityRole::ApplicationLog: ++ return "ApplicationLog"; ++ case AccessibilityRole::ApplicationMarquee: ++ return "ApplicationMarquee"; ++ case AccessibilityRole::ApplicationStatus: ++ return "ApplicationStatus"; ++ case AccessibilityRole::ApplicationTextGroup: ++ return "ApplicationTextGroup"; ++ case AccessibilityRole::ApplicationTimer: ++ return "ApplicationTimer"; ++ case AccessibilityRole::Audio: ++ return "Audio"; ++ case AccessibilityRole::Blockquote: ++ return "Blockquote"; ++ case AccessibilityRole::Browser: ++ return "Browser"; ++ case AccessibilityRole::BusyIndicator: ++ return "BusyIndicator"; ++ case AccessibilityRole::Button: ++ return "Button"; ++ case AccessibilityRole::Canvas: ++ return "Canvas"; ++ case AccessibilityRole::Caption: ++ return "Caption"; ++ case AccessibilityRole::Cell: ++ return "Cell"; ++ case AccessibilityRole::CheckBox: ++ return "CheckBox"; ++ case AccessibilityRole::ColorWell: ++ return "ColorWell"; ++ case AccessibilityRole::Column: ++ return "Column"; ++ case AccessibilityRole::ColumnHeader: ++ return "ColumnHeader"; ++ case AccessibilityRole::ComboBox: ++ return "ComboBox"; ++ case AccessibilityRole::Definition: ++ return "Definition"; ++ case AccessibilityRole::Deletion: ++ return "Deletion"; ++ case AccessibilityRole::DescriptionList: ++ return "DescriptionList"; ++ case AccessibilityRole::DescriptionListTerm: ++ return "DescriptionListTerm"; ++ case AccessibilityRole::DescriptionListDetail: ++ return "DescriptionListDetail"; ++ case AccessibilityRole::Details: ++ return "Details"; ++ case AccessibilityRole::Directory: ++ return "Directory"; ++ case AccessibilityRole::DisclosureTriangle: ++ return "DisclosureTriangle"; ++ case AccessibilityRole::Div: ++ return "Div"; ++ case AccessibilityRole::Document: ++ return "Document"; ++ case AccessibilityRole::DocumentArticle: ++ return "DocumentArticle"; ++ case AccessibilityRole::DocumentMath: ++ return "DocumentMath"; ++ case AccessibilityRole::DocumentNote: ++ return "DocumentNote"; ++ case AccessibilityRole::Drawer: ++ return "Drawer"; ++ case AccessibilityRole::EditableText: ++ return "EditableText"; ++ case AccessibilityRole::Feed: ++ return "Feed"; ++ case AccessibilityRole::Figure: ++ return "Figure"; ++ case AccessibilityRole::Footer: ++ return "Footer"; ++ case AccessibilityRole::Footnote: ++ return "Footnote"; ++ case AccessibilityRole::Form: ++ return "Form"; ++ case AccessibilityRole::GraphicsDocument: ++ return "GraphicsDocument"; ++ case AccessibilityRole::GraphicsObject: ++ return "GraphicsObject"; ++ case AccessibilityRole::GraphicsSymbol: ++ return "GraphicsSymbol"; ++ case AccessibilityRole::Grid: ++ return "Grid"; ++ case AccessibilityRole::GridCell: ++ return "GridCell"; ++ case AccessibilityRole::Group: ++ return "Group"; ++ case AccessibilityRole::GrowArea: ++ return "GrowArea"; ++ case AccessibilityRole::Heading: ++ return "Heading"; ++ case AccessibilityRole::HelpTag: ++ return "HelpTag"; ++ case AccessibilityRole::HorizontalRule: ++ return "HorizontalRule"; ++ case AccessibilityRole::Ignored: ++ return "Ignored"; ++ case AccessibilityRole::Inline: ++ return "Inline"; ++ case AccessibilityRole::Image: ++ return "Image"; ++ case AccessibilityRole::ImageMap: ++ return "ImageMap"; ++ case AccessibilityRole::ImageMapLink: ++ return "ImageMapLink"; ++ case AccessibilityRole::Incrementor: ++ return "Incrementor"; ++ case AccessibilityRole::Insertion: ++ return "Insertion"; ++ case AccessibilityRole::Label: ++ return "Label"; ++ case AccessibilityRole::LandmarkBanner: ++ return "LandmarkBanner"; ++ case AccessibilityRole::LandmarkComplementary: ++ return "LandmarkComplementary"; ++ case AccessibilityRole::LandmarkContentInfo: ++ return "LandmarkContentInfo"; ++ case AccessibilityRole::LandmarkDocRegion: ++ return "LandmarkDocRegion"; ++ case AccessibilityRole::LandmarkMain: ++ return "LandmarkMain"; ++ case AccessibilityRole::LandmarkNavigation: ++ return "LandmarkNavigation"; ++ case AccessibilityRole::LandmarkRegion: ++ return "LandmarkRegion"; ++ case AccessibilityRole::LandmarkSearch: ++ return "LandmarkSearch"; ++ case AccessibilityRole::Legend: ++ return "Legend"; ++ case AccessibilityRole::Link: ++ return "Link"; ++ case AccessibilityRole::List: ++ return "List"; ++ case AccessibilityRole::ListBox: ++ return "ListBox"; ++ case AccessibilityRole::ListBoxOption: ++ return "ListBoxOption"; ++ case AccessibilityRole::ListItem: ++ return "ListItem"; ++ case AccessibilityRole::ListMarker: ++ return "ListMarker"; ++ case AccessibilityRole::Mark: ++ return "Mark"; ++ case AccessibilityRole::MathElement: ++ return "MathElement"; ++ case AccessibilityRole::Matte: ++ return "Matte"; ++ case AccessibilityRole::Menu: ++ return "Menu"; ++ case AccessibilityRole::MenuBar: ++ return "MenuBar"; ++ case AccessibilityRole::MenuButton: ++ return "MenuButton"; ++ case AccessibilityRole::MenuItem: ++ return "MenuItem"; ++ case AccessibilityRole::MenuItemCheckbox: ++ return "MenuItemCheckbox"; ++ case AccessibilityRole::MenuItemRadio: ++ return "MenuItemRadio"; ++ case AccessibilityRole::MenuListPopup: ++ return "MenuListPopup"; ++ case AccessibilityRole::MenuListOption: ++ return "MenuListOption"; ++ case AccessibilityRole::Meter: ++ return "Meter"; ++ case AccessibilityRole::Outline: ++ return "Outline"; ++ case AccessibilityRole::Paragraph: ++ return "Paragraph"; ++ case AccessibilityRole::PopUpButton: ++ return "PopUpButton"; ++ case AccessibilityRole::Pre: ++ return "Pre"; ++ case AccessibilityRole::Presentational: ++ return "Presentational"; ++ case AccessibilityRole::ProgressIndicator: ++ return "ProgressIndicator"; ++ case AccessibilityRole::RadioButton: ++ return "RadioButton"; ++ case AccessibilityRole::RadioGroup: ++ return "RadioGroup"; ++ case AccessibilityRole::RowHeader: ++ return "RowHeader"; ++ case AccessibilityRole::Row: ++ return "Row"; ++ case AccessibilityRole::RowGroup: ++ return "RowGroup"; ++ case AccessibilityRole::RubyBase: ++ return "RubyBase"; ++ case AccessibilityRole::RubyBlock: ++ return "RubyBlock"; ++ case AccessibilityRole::RubyInline: ++ return "RubyInline"; ++ case AccessibilityRole::RubyRun: ++ return "RubyRun"; ++ case AccessibilityRole::RubyText: ++ return "RubyText"; ++ case AccessibilityRole::Ruler: ++ return "Ruler"; ++ case AccessibilityRole::RulerMarker: ++ return "RulerMarker"; ++ case AccessibilityRole::ScrollArea: ++ return "ScrollArea"; ++ case AccessibilityRole::ScrollBar: ++ return "ScrollBar"; ++ case AccessibilityRole::SearchField: ++ return "SearchField"; ++ case AccessibilityRole::Sheet: ++ return "Sheet"; ++ case AccessibilityRole::Slider: ++ return "Slider"; ++ case AccessibilityRole::SliderThumb: ++ return "SliderThumb"; ++ case AccessibilityRole::SpinButton: ++ return "SpinButton"; ++ case AccessibilityRole::SpinButtonPart: ++ return "SpinButtonPart"; ++ case AccessibilityRole::SplitGroup: ++ return "SplitGroup"; ++ case AccessibilityRole::Splitter: ++ return "Splitter"; ++ case AccessibilityRole::StaticText: ++ return "StaticText"; ++ case AccessibilityRole::Subscript: ++ return "Subscript"; ++ case AccessibilityRole::Summary: ++ return "Summary"; ++ case AccessibilityRole::Superscript: ++ return "Superscript"; ++ case AccessibilityRole::Switch: ++ return "Switch"; ++ case AccessibilityRole::SystemWide: ++ return "SystemWide"; ++ case AccessibilityRole::SVGRoot: ++ return "SVGRoot"; ++ case AccessibilityRole::SVGText: ++ return "SVGText"; ++ case AccessibilityRole::SVGTSpan: ++ return "SVGTSpan"; ++ case AccessibilityRole::SVGTextPath: ++ return "SVGTextPath"; ++ case AccessibilityRole::TabGroup: ++ return "TabGroup"; ++ case AccessibilityRole::TabList: ++ return "TabList"; ++ case AccessibilityRole::TabPanel: ++ return "TabPanel"; ++ case AccessibilityRole::Tab: ++ return "Tab"; ++ case AccessibilityRole::Table: ++ return "Table"; ++ case AccessibilityRole::TableHeaderContainer: ++ return "TableHeaderContainer"; ++ case AccessibilityRole::TextArea: ++ return "TextArea"; ++ case AccessibilityRole::TextGroup: ++ return "TextGroup"; ++ case AccessibilityRole::Term: ++ return "Term"; ++ case AccessibilityRole::Time: ++ return "Time"; ++ case AccessibilityRole::Tree: ++ return "Tree"; ++ case AccessibilityRole::TreeGrid: ++ return "TreeGrid"; ++ case AccessibilityRole::TreeItem: ++ return "TreeItem"; ++ case AccessibilityRole::TextField: ++ return "TextField"; ++ case AccessibilityRole::ToggleButton: ++ return "ToggleButton"; ++ case AccessibilityRole::Toolbar: ++ return "Toolbar"; ++ case AccessibilityRole::Unknown: ++ return "Unknown"; ++ case AccessibilityRole::UserInterfaceTooltip: ++ return "UserInterfaceTooltip"; ++ case AccessibilityRole::ValueIndicator: ++ return "ValueIndicator"; ++ case AccessibilityRole::Video: ++ return "Video"; ++ case AccessibilityRole::WebApplication: ++ return "WebApplication"; ++ case AccessibilityRole::WebArea: ++ return "WebArea"; ++ case AccessibilityRole::WebCoreLink: ++ return "WebCoreLink"; ++ case AccessibilityRole::Window: ++ return "Window"; ++ }; ++ return "Unknown"; ++} ++ ++static Ref snapshotForAXObject(RefPtr axObject, Node* nodeToFind) ++{ ++ auto axNode = Inspector::Protocol::Page::AXNode::create() ++ .setRole(roleFromObject(axObject)) ++ .release(); ++ ++ if (!axObject->computedLabel().isEmpty()) ++ axNode->setName(axObject->computedLabel()); ++ if (!axObject->stringValue().isEmpty()) ++ axNode->setValue(JSON::Value::create(axObject->stringValue())); ++ if (!axObject->accessibilityDescription().isEmpty()) ++ axNode->setDescription(axObject->accessibilityDescription()); ++ if (!axObject->keyShortcutsValue().isEmpty()) ++ axNode->setKeyshortcuts(axObject->keyShortcutsValue()); ++ if (!axObject->valueDescription().isEmpty()) ++ axNode->setValuetext(axObject->valueDescription()); ++ if (!axObject->roleDescription().isEmpty()) ++ axNode->setRoledescription(axObject->roleDescription()); ++ if (!axObject->isEnabled()) ++ axNode->setDisabled(!axObject->isEnabled()); ++ if (axObject->supportsExpanded()) ++ axNode->setExpanded(axObject->isExpanded()); ++ if (axObject->isFocused()) ++ axNode->setFocused(axObject->isFocused()); ++ if (axObject->isModalNode()) ++ axNode->setModal(axObject->isModalNode()); ++ bool multiline = axObject->ariaIsMultiline() || axObject->roleValue() == AccessibilityRole::TextArea; ++ if (multiline) ++ axNode->setMultiline(multiline); ++ if (axObject->isMultiSelectable()) ++ axNode->setMultiselectable(axObject->isMultiSelectable()); ++ if (axObject->supportsReadOnly() && !axObject->canSetValueAttribute() && axObject->isEnabled()) ++ axNode->setReadonly(true); ++ if (axObject->supportsRequiredAttribute()) ++ axNode->setRequired(axObject->isRequired()); ++ if (axObject->isSelected()) ++ axNode->setSelected(axObject->isSelected()); ++ if (axObject->supportsChecked()) { ++ AccessibilityButtonState checkedState = axObject->checkboxOrRadioValue(); ++ switch (checkedState) { ++ case AccessibilityButtonState::On: ++ axNode->setChecked(Inspector::Protocol::Page::AXNode::Checked::True); ++ break; ++ case AccessibilityButtonState::Off: ++ axNode->setChecked(Inspector::Protocol::Page::AXNode::Checked::False); ++ break; ++ case AccessibilityButtonState::Mixed: ++ axNode->setChecked(Inspector::Protocol::Page::AXNode::Checked::Mixed); ++ break; ++ } ++ } ++ if (axObject->supportsPressed()) { ++ AccessibilityButtonState checkedState = axObject->checkboxOrRadioValue(); ++ switch (checkedState) { ++ case AccessibilityButtonState::On: ++ axNode->setPressed(Inspector::Protocol::Page::AXNode::Pressed::True); ++ break; ++ case AccessibilityButtonState::Off: ++ axNode->setPressed(Inspector::Protocol::Page::AXNode::Pressed::False); ++ break; ++ case AccessibilityButtonState::Mixed: ++ axNode->setPressed(Inspector::Protocol::Page::AXNode::Pressed::Mixed); ++ break; ++ } ++ } ++ unsigned level = axObject->hierarchicalLevel() ? axObject->hierarchicalLevel() : axObject->headingLevel(); ++ if (level) ++ axNode->setLevel(level); ++ if (axObject->minValueForRange() != 0) ++ axNode->setValuemin(axObject->minValueForRange()); ++ if (axObject->maxValueForRange() != 0) ++ axNode->setValuemax(axObject->maxValueForRange()); ++ if (axObject->supportsAutoComplete()) ++ axNode->setAutocomplete(axObject->autoCompleteValue()); ++ if (axObject->hasPopup()) ++ axNode->setHaspopup(axObject->popupValue()); ++ ++ String invalidValue = axObject->invalidStatus(); ++ if (invalidValue != "false") { ++ if (invalidValue == "grammar") ++ axNode->setInvalid(Inspector::Protocol::Page::AXNode::Invalid::Grammar); ++ else if (invalidValue == "spelling") ++ axNode->setInvalid(Inspector::Protocol::Page::AXNode::Invalid::Spelling); ++ else // Future versions of ARIA may allow additional truthy values. Ex. format, order, or size. ++ axNode->setInvalid(Inspector::Protocol::Page::AXNode::Invalid::True); ++ } ++ switch (axObject->orientation()) { ++ case AccessibilityOrientation::Undefined: ++ break; ++ case AccessibilityOrientation::Vertical: ++ axNode->setOrientation("vertical"_s); ++ break; ++ case AccessibilityOrientation::Horizontal: ++ axNode->setOrientation("horizontal"_s); ++ break; ++ } ++ ++ if (axObject->isKeyboardFocusable()) ++ axNode->setFocusable(axObject->isKeyboardFocusable()); ++ ++ if (nodeToFind && axObject->node() == nodeToFind) ++ axNode->setFound(true); ++ ++ if (axObject->hasChildren()) { ++ Ref> children = JSON::ArrayOf::create(); ++ for (auto& childObject : axObject->children()) ++ children->addItem(snapshotForAXObject(childObject, nodeToFind)); ++ axNode->setChildren(WTFMove(children)); ++ } ++ return axNode; ++} ++ ++ ++Protocol::ErrorStringOr> InspectorPageAgent::accessibilitySnapshot(const String& objectId) ++{ ++ if (!WebCore::AXObjectCache::accessibilityEnabled()) ++ WebCore::AXObjectCache::enableAccessibility(); ++ auto document = makeRefPtr(m_inspectedPage.mainFrame().document()); ++ if (!document) ++ return makeUnexpected("No document for main frame"_s); ++ ++ AXObjectCache* axObjectCache = document->axObjectCache(); ++ if (!axObjectCache) ++ return makeUnexpected("No AXObjectCache for main document"_s); ++ ++ AXCoreObject* axObject = axObjectCache->rootObject(); ++ if (!axObject) ++ return makeUnexpected("No AXObject for main document"_s); ++ ++ Node* node = nullptr; ++ if (!objectId.isEmpty()) { ++ InspectorDOMAgent* domAgent = m_instrumentingAgents.persistentDOMAgent(); ++ ASSERT(domAgent); ++ node = domAgent->nodeForObjectId(objectId); ++ if (!node) ++ return makeUnexpected("No Node for objectId"_s); ++ } ++ ++ m_doingAccessibilitySnapshot = true; ++ Ref axNode = snapshotForAXObject(makeRefPtr(axObject), node); ++ m_doingAccessibilitySnapshot = false; ++ return axNode; ++} ++ ++Protocol::ErrorStringOr InspectorPageAgent::setInterceptFileChooserDialog(bool enabled) ++{ ++ m_interceptFileChooserDialog = enabled; ++ return { }; ++} ++ ++Protocol::ErrorStringOr InspectorPageAgent::setDefaultBackgroundColorOverride(RefPtr&& color) ++{ ++ FrameView* view = m_inspectedPage.mainFrame().view(); ++ if (!view) ++ return makeUnexpected("Internal error: No frame view to set color two"_s); ++ ++ if (!color) { ++ view->updateBackgroundRecursively(Optional()); ++ return { }; ++ } ++ ++ view->updateBackgroundRecursively(InspectorDOMAgent::parseColor(WTFMove(color))); ++ return { }; ++} ++ ++Protocol::ErrorStringOr InspectorPageAgent::createUserWorld(const String& name) ++{ ++ if (createdUserWorlds().contains(name)) ++ return makeUnexpected("World with the given name already exists"_s); ++ ++ Ref world = ScriptController::createWorld(name, ScriptController::WorldType::User); ++ ensureUserWorldsExistInAllFrames({world.ptr()}); ++ createdUserWorlds().set(name, WTFMove(world)); ++ return { }; ++} ++ ++void InspectorPageAgent::ensureUserWorldsExistInAllFrames(const Vector& worlds) ++{ ++ for (Frame* frame = &m_inspectedPage.mainFrame(); frame; frame = frame->tree().traverseNext()) { ++ for (auto* world : worlds) ++ frame->windowProxy().jsWindowProxy(*world)->window(); ++ } ++} ++ ++Protocol::ErrorStringOr InspectorPageAgent::setBypassCSP(bool enabled) ++{ ++ m_bypassCSP = enabled; ++ return { }; ++} ++ ++Protocol::ErrorStringOr InspectorPageAgent::crash() ++{ ++ CRASH(); ++ return { }; ++} ++ ++Protocol::ErrorStringOr InspectorPageAgent::setOrientationOverride(Optional&& angle) ++{ ++#if ENABLE(ORIENTATION_EVENTS) ++ m_inspectedPage.setOverrideOrientation(WTFMove(angle)); ++ return { }; ++#else ++ UNUSED_PARAM(angle); ++ return makeUnexpected("Orientation events are disabled in this build"); + #endif ++} + + } // namespace WebCore +diff --git a/Source/WebCore/inspector/agents/InspectorPageAgent.h b/Source/WebCore/inspector/agents/InspectorPageAgent.h +index 78a98224ab5450e0729751571fe1bb957d303301..a4f46cc377bde6a787f3e67ca4869bfc25461127 100644 +--- a/Source/WebCore/inspector/agents/InspectorPageAgent.h ++++ b/Source/WebCore/inspector/agents/InspectorPageAgent.h +@@ -34,17 +34,23 @@ + #include "CachedResource.h" + #include "InspectorWebAgentBase.h" + #include "LayoutRect.h" ++#include "ProcessIdentifier.h" + #include + #include + #include + #include + #include + ++namespace Inspector { ++class InjectedScriptManager; ++} ++ + namespace WebCore { + + class DOMWrapperWorld; + class DocumentLoader; + class Frame; ++class HTMLInputElement; + class InspectorClient; + class InspectorOverlay; + class Page; +@@ -69,12 +75,14 @@ public: + PingResource, + BeaconResource, + WebSocketResource, ++ EventSource, + #if ENABLE(APPLICATION_MANIFEST) + ApplicationManifestResource, + #endif + OtherResource, + }; + ++ WEBCORE_EXPORT static String makeFrameID(ProcessIdentifier processID, FrameIdentifier frameID); + static bool sharedBufferContent(RefPtr&&, const String& textEncodingName, bool withBase64Encode, String* result); + static Vector cachedResourcesForFrame(Frame*); + static void resourceContent(Inspector::Protocol::ErrorString&, Frame*, const URL&, String* result, bool* base64Encoded); +@@ -95,6 +103,8 @@ public: + Inspector::Protocol::ErrorStringOr enable(); + Inspector::Protocol::ErrorStringOr disable(); + Inspector::Protocol::ErrorStringOr reload(Optional&& ignoreCache, Optional&& revalidateAllResources); ++ Inspector::Protocol::ErrorStringOr goBack(); ++ Inspector::Protocol::ErrorStringOr goForward(); + Inspector::Protocol::ErrorStringOr navigate(const String& url); + Inspector::Protocol::ErrorStringOr overrideUserAgent(const String&); + Inspector::Protocol::ErrorStringOr overrideSetting(Inspector::Protocol::Page::Setting, Optional&& value); +@@ -114,25 +124,35 @@ public: + #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT) + Inspector::Protocol::ErrorStringOr setForcedAppearance(Optional&&); + #endif ++ Inspector::Protocol::ErrorStringOr setTimeZone(const String&); ++ Inspector::Protocol::ErrorStringOr setTouchEmulationEnabled(bool); + Inspector::Protocol::ErrorStringOr snapshotNode(Inspector::Protocol::DOM::NodeId); + Inspector::Protocol::ErrorStringOr snapshotRect(int x, int y, int width, int height, Inspector::Protocol::Page::CoordinateSystem); + #if ENABLE(WEB_ARCHIVE) && USE(CF) + Inspector::Protocol::ErrorStringOr archive(); + #endif +-#if !PLATFORM(COCOA) + Inspector::Protocol::ErrorStringOr setScreenSizeOverride(Optional&& width, Optional&& height); +-#endif ++ ++ Inspector::Protocol::ErrorStringOr insertText(const String& text); ++ Inspector::Protocol::ErrorStringOr> accessibilitySnapshot(const String& objectId); ++ Inspector::Protocol::ErrorStringOr setInterceptFileChooserDialog(bool enabled); ++ Inspector::Protocol::ErrorStringOr setDefaultBackgroundColorOverride(RefPtr&&); ++ Inspector::Protocol::ErrorStringOr createUserWorld(const String&); ++ Inspector::Protocol::ErrorStringOr setBypassCSP(bool); ++ Inspector::Protocol::ErrorStringOr crash(); ++ Inspector::Protocol::ErrorStringOr setScreenSizeOverride(int width, int height); ++ Inspector::Protocol::ErrorStringOr setOrientationOverride(Optional&& angle); + + // InspectorInstrumentation +- void domContentEventFired(); +- void loadEventFired(); ++ void domContentEventFired(Frame&); ++ void loadEventFired(Frame&); + void frameNavigated(Frame&); + void frameDetached(Frame&); +- void loaderDetachedFromFrame(DocumentLoader&); + void frameStartedLoading(Frame&); + void frameStoppedLoading(Frame&); + void frameScheduledNavigation(Frame&, Seconds delay); + void frameClearedScheduledNavigation(Frame&); ++ void didNavigateWithinPage(Frame&); + #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT) + void defaultAppearanceDidChange(bool useDarkAppearance); + #endif +@@ -143,6 +163,12 @@ public: + void didLayout(); + void didScroll(); + void didRecalculateStyle(); ++ void runOpenPanel(HTMLInputElement* element, bool* intercept); ++ void frameAttached(Frame&); ++ bool shouldBypassCSP(); ++ void willCheckNewWindowPolicy(const URL&); ++ void didCheckNewWindowPolicy(bool allowed); ++ bool doingAccessibilitySnapshot() const { return m_doingAccessibilitySnapshot; }; + + Frame* frameForId(const Inspector::Protocol::Network::FrameId&); + WEBCORE_EXPORT String frameId(Frame*); +@@ -151,6 +177,7 @@ public: + + private: + double timestamp(); ++ void ensureUserWorldsExistInAllFrames(const Vector&); + + static bool mainResourceContent(Frame*, bool withBase64Encode, String* result); + static bool dataContent(const char* data, unsigned size, const String& textEncodingName, bool withBase64Encode, String* result); +@@ -162,18 +189,19 @@ private: + RefPtr m_backendDispatcher; + + Page& m_inspectedPage; ++ Inspector::InjectedScriptManager& m_injectedScriptManager; + InspectorClient* m_client { nullptr }; + InspectorOverlay* m_overlay { nullptr }; + +- // FIXME: Make a WeakHashMap and use it for m_frameToIdentifier and m_loaderToIdentifier. +- HashMap m_frameToIdentifier; + HashMap> m_identifierToFrame; +- HashMap m_loaderToIdentifier; + String m_userAgentOverride; + String m_emulatedMedia; + String m_bootstrapScript; + bool m_isFirstLayoutAfterOnLoad { false }; + bool m_showPaintRects { false }; ++ bool m_interceptFileChooserDialog { false }; ++ bool m_bypassCSP { false }; ++ bool m_doingAccessibilitySnapshot { false }; + }; + + } // namespace WebCore +diff --git a/Source/WebCore/inspector/agents/InspectorWorkerAgent.cpp b/Source/WebCore/inspector/agents/InspectorWorkerAgent.cpp +index 33caa0aa2079ad4081cc29605a53537c24d66bef..4b74d397d4de9a7eba3d5530538443d8907726aa 100644 +--- a/Source/WebCore/inspector/agents/InspectorWorkerAgent.cpp ++++ b/Source/WebCore/inspector/agents/InspectorWorkerAgent.cpp +@@ -161,7 +161,11 @@ void InspectorWorkerAgent::connectToWorkerInspectorProxy(WorkerInspectorProxy& p + + m_connectedProxies.set(proxy.identifier(), &proxy); + +- m_frontendDispatcher->workerCreated(proxy.identifier(), proxy.url().string(), proxy.name()); ++ ASSERT(is(proxy.scriptExecutionContext())); ++ Document& document = downcast(*proxy.scriptExecutionContext()); ++ auto* pageAgent = m_instrumentingAgents.enabledPageAgent(); ++ m_frontendDispatcher->workerCreated(proxy.identifier(), proxy.url().string(), proxy.name(), ++ pageAgent ? pageAgent->frameId(document.frame()) : emptyString()); + } + + void InspectorWorkerAgent::disconnectFromWorkerInspectorProxy(WorkerInspectorProxy& proxy) +diff --git a/Source/WebCore/inspector/agents/page/PageDebuggerAgent.cpp b/Source/WebCore/inspector/agents/page/PageDebuggerAgent.cpp +index 746da1a4d3e03a871b7880a3e52856b0ed2835cd..6d06ed07527541b8339236eefa51f15ecaebc93e 100644 +--- a/Source/WebCore/inspector/agents/page/PageDebuggerAgent.cpp ++++ b/Source/WebCore/inspector/agents/page/PageDebuggerAgent.cpp +@@ -38,6 +38,7 @@ + #include "Frame.h" + #include "InspectorPageAgent.h" + #include "InstrumentingAgents.h" ++#include "JSDOMWindowBase.h" + #include "Page.h" + #include "PageConsoleClient.h" + #include "PageDebugger.h" +@@ -70,7 +71,11 @@ bool PageDebuggerAgent::enabled() const + + Protocol::ErrorStringOr, Optional /* wasThrown */, Optional /* savedResultIndex */>> PageDebuggerAgent::evaluateOnCallFrame(const Protocol::Debugger::CallFrameId& callFrameId, const String& expression, const String& objectGroup, Optional&& includeCommandLineAPI, Optional&& doNotPauseOnExceptionsAndMuteConsole, Optional&& returnByValue, Optional&& generatePreview, Optional&& saveResult, Optional&& emulateUserGesture) + { +- UserGestureEmulationScope userGestureScope(m_inspectedPage, emulateUserGesture && *emulateUserGesture); ++ InjectedScript injectedScript = injectedScriptManager().injectedScriptForObjectId(callFrameId); ++ JSC::JSGlobalObject* globalObject = injectedScript.globalObject(); ++ Document* document = globalObject ? activeDOMWindow(*globalObject).document() : nullptr; ++ auto shouldEmulateUserGesture = emulateUserGesture && *emulateUserGesture; ++ UserGestureEmulationScope userGestureScope(m_inspectedPage, shouldEmulateUserGesture, document); + + return WebDebuggerAgent::evaluateOnCallFrame(callFrameId, expression, objectGroup, WTFMove(includeCommandLineAPI), WTFMove(doNotPauseOnExceptionsAndMuteConsole), WTFMove(returnByValue), WTFMove(generatePreview), WTFMove(saveResult), WTFMove(emulateUserGesture)); + } +@@ -122,8 +127,9 @@ void PageDebuggerAgent::unmuteConsole() + + void PageDebuggerAgent::debuggerWillEvaluate(JSC::Debugger&, const JSC::Breakpoint::Action& action) + { ++ // FIXME(playwright): we should pass proper Documnt instead of nullptr here. + if (action.emulateUserGesture) +- m_breakpointActionUserGestureEmulationScopeStack.append(makeUniqueRef(m_inspectedPage, true)); ++ m_breakpointActionUserGestureEmulationScopeStack.append(makeUniqueRef(m_inspectedPage, true, nullptr)); + } + + void PageDebuggerAgent::debuggerDidEvaluate(JSC::Debugger&, const JSC::Breakpoint::Action& action) +diff --git a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp +index 00e69f1aa2e3f8ea2f445e8dd446dd16ea6363df..92d45059ca6d87ddf7b6cc12033267a4c108a73c 100644 +--- a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp ++++ b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp +@@ -35,12 +35,14 @@ + #include "DOMWrapperWorld.h" + #include "Document.h" + #include "Frame.h" ++#include "FrameLoader.h" + #include "InspectorPageAgent.h" + #include "InstrumentingAgents.h" + #include "JSDOMWindowBase.h" + #include "Page.h" + #include "PageConsoleClient.h" + #include "ScriptController.h" ++#include "ScriptSourceCode.h" + #include "ScriptState.h" + #include "SecurityOrigin.h" + #include "UserGestureEmulationScope.h" +@@ -103,6 +105,15 @@ void PageRuntimeAgent::didClearWindowObjectInWorld(Frame& frame, DOMWrapperWorld + notifyContextCreated(pageAgent->frameId(&frame), frame.script().globalObject(world), world); + } + ++void PageRuntimeAgent::didReceiveMainResourceError(Frame& frame) ++{ ++ if (frame.loader().stateMachine().isDisplayingInitialEmptyDocument()) { ++ // Ensure execution context is created for the empty docment to make ++ // it usable in case loading failed. ++ mainWorldExecState(&frame); ++ } ++} ++ + InjectedScript PageRuntimeAgent::injectedScriptForEval(Protocol::ErrorString& errorString, Optional&& executionContextId) + { + if (!executionContextId) { +@@ -191,13 +202,23 @@ void PageRuntimeAgent::notifyContextCreated(const Protocol::Network::FrameId& fr + + Protocol::ErrorStringOr, Optional /* wasThrown */, Optional /* savedResultIndex */>> PageRuntimeAgent::evaluate(const String& expression, const String& objectGroup, Optional&& includeCommandLineAPI, Optional&& doNotPauseOnExceptionsAndMuteConsole, Optional&& executionContextId, Optional&& returnByValue, Optional&& generatePreview, Optional&& saveResult, Optional&& emulateUserGesture) + { +- UserGestureEmulationScope userGestureScope(m_inspectedPage, emulateUserGesture && *emulateUserGesture); ++ String errorString; ++ InjectedScript injectedScript = injectedScriptForEval(errorString, Optional(executionContextId)); ++ if (!errorString.isEmpty()) ++ return makeUnexpected(errorString); ++ ++ JSC::JSGlobalObject* globalObject = injectedScript.globalObject(); ++ Document* document = globalObject ? activeDOMWindow(*globalObject).document() : nullptr; ++ UserGestureEmulationScope userGestureScope(m_inspectedPage, emulateUserGesture && *emulateUserGesture, document); + return InspectorRuntimeAgent::evaluate(expression, objectGroup, WTFMove(includeCommandLineAPI), WTFMove(doNotPauseOnExceptionsAndMuteConsole), WTFMove(executionContextId), WTFMove(returnByValue), WTFMove(generatePreview), WTFMove(saveResult), WTFMove(emulateUserGesture)); + } + + Protocol::ErrorStringOr, Optional /* wasThrown */>> PageRuntimeAgent::callFunctionOn(const Protocol::Runtime::RemoteObjectId& objectId, const String& expression, RefPtr&& optionalArguments, Optional&& doNotPauseOnExceptionsAndMuteConsole, Optional&& returnByValue, Optional&& generatePreview, Optional&& emulateUserGesture) + { +- UserGestureEmulationScope userGestureScope(m_inspectedPage, emulateUserGesture && *emulateUserGesture); ++ InjectedScript injectedScript = injectedScriptManager().injectedScriptForObjectId(objectId); ++ JSC::JSGlobalObject* globalObject = injectedScript.globalObject(); ++ Document* document = globalObject ? activeDOMWindow(*globalObject).document() : nullptr; ++ UserGestureEmulationScope userGestureScope(m_inspectedPage, emulateUserGesture && *emulateUserGesture, document); + return InspectorRuntimeAgent::callFunctionOn(objectId, expression, WTFMove(optionalArguments), WTFMove(doNotPauseOnExceptionsAndMuteConsole), WTFMove(returnByValue), WTFMove(generatePreview), WTFMove(emulateUserGesture)); + } + +diff --git a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h +index 298465c52b42464c2733659e07f3f760174a95eb..3b7ac5a5e6fba11bfbc3d641e5a312db5f1391a8 100644 +--- a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h ++++ b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h +@@ -62,6 +62,7 @@ public: + // InspectorInstrumentation + void frameNavigated(Frame&); + void didClearWindowObjectInWorld(Frame&, DOMWrapperWorld&); ++ void didReceiveMainResourceError(Frame&); + + private: + Inspector::InjectedScript injectedScriptForEval(Inspector::Protocol::ErrorString&, Optional&&); +@@ -72,7 +73,6 @@ private: + + std::unique_ptr m_frontendDispatcher; + RefPtr m_backendDispatcher; +- + InstrumentingAgents& m_instrumentingAgents; + + Page& m_inspectedPage; +diff --git a/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.cpp b/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.cpp +index 633bce6e8f3c0785632eb7f26d172f6016b3efd9..14f531504bb2b96646d1a48092a0b132b0510f55 100644 +--- a/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.cpp ++++ b/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.cpp +@@ -39,9 +39,9 @@ + + namespace WebCore { + +-UserGestureEmulationScope::UserGestureEmulationScope(Page& inspectedPage, bool emulateUserGesture) ++UserGestureEmulationScope::UserGestureEmulationScope(Page& inspectedPage, bool emulateUserGesture, Document* document) + : m_pageChromeClient(inspectedPage.chrome().client()) +- , m_gestureIndicator(emulateUserGesture ? Optional(ProcessingUserGesture) : WTF::nullopt) ++ , m_gestureIndicator(emulateUserGesture ? Optional(ProcessingUserGesture) : WTF::nullopt, document) + , m_emulateUserGesture(emulateUserGesture) + , m_userWasInteracting(false) + { +diff --git a/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.h b/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.h +index 16edb3bc689b8e2dde17597b642b706c1343e1f5..f363b2ca2410f22cff8d6ad908a88527970ab1d8 100644 +--- a/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.h ++++ b/Source/WebCore/inspector/agents/page/UserGestureEmulationScope.h +@@ -38,12 +38,13 @@ namespace WebCore { + + class ChromeClient; + class Page; ++class Document; + + class UserGestureEmulationScope { + WTF_MAKE_NONCOPYABLE(UserGestureEmulationScope); + WTF_MAKE_FAST_ALLOCATED; + public: +- UserGestureEmulationScope(Page& inspectedPage, bool emulateUserGesture); ++ UserGestureEmulationScope(Page& inspectedPage, bool emulateUserGesture, Document* document); + ~UserGestureEmulationScope(); + + private: +diff --git a/Source/WebCore/loader/CookieJar.h b/Source/WebCore/loader/CookieJar.h +index ca42c37f15d240a0e6692e66ee83210352023547..1c82f768aecff9fcce098840fb0093bf2fb9bf72 100644 +--- a/Source/WebCore/loader/CookieJar.h ++++ b/Source/WebCore/loader/CookieJar.h +@@ -42,6 +42,7 @@ struct CookieRequestHeaderFieldProxy; + class NetworkStorageSession; + class StorageSessionProvider; + struct SameSiteInfo; ++class ResourceLoader; + + class WEBCORE_EXPORT CookieJar : public RefCounted { + public: +@@ -65,6 +66,9 @@ public: + virtual void clearCache() { } + virtual void clearCacheForHost(const String&) { } + ++ // Playwright. ++ virtual void setCookieFromResponse(ResourceLoader&, const String&) { } ++ + virtual ~CookieJar(); + protected: + static SameSiteInfo sameSiteInfo(const Document&); +diff --git a/Source/WebCore/loader/DocumentLoader.cpp b/Source/WebCore/loader/DocumentLoader.cpp +index dccf553864490d7e8758a49073014745ee7e5e8f..2bdba8d36d90ac70059a02110d39bfadca667c5c 100644 +--- a/Source/WebCore/loader/DocumentLoader.cpp ++++ b/Source/WebCore/loader/DocumentLoader.cpp +@@ -1380,8 +1380,6 @@ void DocumentLoader::detachFromFrame() + if (!m_frame) + return; + +- InspectorInstrumentation::loaderDetachedFromFrame(*m_frame, *this); +- + observeFrame(nullptr); + } + +diff --git a/Source/WebCore/loader/DocumentLoader.h b/Source/WebCore/loader/DocumentLoader.h +index eab710a27defd8dd5e3eab2272e88a1f336cda2a..3316c44d39225c58afa54f13d4d65fd35337e5da 100644 +--- a/Source/WebCore/loader/DocumentLoader.h ++++ b/Source/WebCore/loader/DocumentLoader.h +@@ -166,9 +166,13 @@ public: + + WEBCORE_EXPORT virtual void detachFromFrame(); + ++ virtual void replacedByFragmentNavigation(Frame&) { } ++ + WEBCORE_EXPORT FrameLoader* frameLoader() const; + WEBCORE_EXPORT SubresourceLoader* mainResourceLoader() const; + WEBCORE_EXPORT RefPtr mainResourceData() const; ++ ++ virtual uint64_t loaderIDForInspector() { return 0; } + + DocumentWriter& writer() const { return m_writer; } + +diff --git a/Source/WebCore/loader/FrameLoader.cpp b/Source/WebCore/loader/FrameLoader.cpp +index 10952e4c5f636f8269b25e7b4ce18187f11b1eb7..f72b78926c93d629b86d1e85cf9009767e9adb4b 100644 +--- a/Source/WebCore/loader/FrameLoader.cpp ++++ b/Source/WebCore/loader/FrameLoader.cpp +@@ -1152,6 +1152,7 @@ void FrameLoader::loadInSameDocument(const URL& url, SerializedScriptValue* stat + } + + m_client->dispatchDidNavigateWithinPage(); ++ InspectorInstrumentation::didNavigateWithinPage(m_frame); + + m_frame.document()->statePopped(stateObject ? Ref { *stateObject } : SerializedScriptValue::nullValue()); + m_client->dispatchDidPopStateWithinPage(); +@@ -1463,6 +1464,7 @@ void FrameLoader::load(FrameLoadRequest&& request) + + void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, NavigationAction&& action, FrameLoadType type, RefPtr&& formState, AllowNavigationToInvalidURL allowNavigationToInvalidURL, CompletionHandler&& completionHandler) + { ++ InspectorInstrumentation::frameScheduledNavigation(m_frame, Seconds(0)); + FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "loadWithNavigationAction: frame load started"); + + Ref loader = m_client->createDocumentLoader(request, defaultSubstituteDataForURL(request.url())); +@@ -1566,6 +1568,8 @@ void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType t + const String& httpMethod = loader->request().httpMethod(); + + if (shouldPerformFragmentNavigation(isFormSubmission, httpMethod, policyChecker().loadType(), newURL)) { ++ loader->replacedByFragmentNavigation(m_frame); ++ + RefPtr oldDocumentLoader = m_documentLoader; + NavigationAction action { *m_frame.document(), loader->request(), InitiatedByMainFrame::Unknown, policyChecker().loadType(), isFormSubmission }; + +@@ -3149,6 +3153,8 @@ void FrameLoader::receivedMainResourceError(const ResourceError& error) + checkCompleted(); + if (m_frame.page()) + checkLoadComplete(); ++ ++ InspectorInstrumentation::didReceiveMainResourceError(m_frame, error); + } + + void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, bool shouldContinue) +@@ -3911,9 +3917,6 @@ String FrameLoader::referrer() const + + void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds() + { +- if (!m_frame.script().canExecuteScripts(NotAboutToExecuteScript)) +- return; +- + Vector> worlds; + ScriptController::getAllWorlds(worlds); + for (auto& world : worlds) +@@ -3922,13 +3925,13 @@ void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds() + + void FrameLoader::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld& world) + { +- if (!m_frame.script().canExecuteScripts(NotAboutToExecuteScript) || !m_frame.windowProxy().existingJSWindowProxy(world)) +- return; +- +- m_client->dispatchDidClearWindowObjectInWorld(world); ++ if (m_frame.windowProxy().existingJSWindowProxy(world)) { ++ if (m_frame.script().canExecuteScripts(NotAboutToExecuteScript)) ++ m_client->dispatchDidClearWindowObjectInWorld(world); + +- if (Page* page = m_frame.page()) +- page->inspectorController().didClearWindowObjectInWorld(m_frame, world); ++ if (Page* page = m_frame.page()) ++ page->inspectorController().didClearWindowObjectInWorld(m_frame, world); ++ } + + InspectorInstrumentation::didClearWindowObjectInWorld(m_frame, world); + } +diff --git a/Source/WebCore/loader/LoaderStrategy.h b/Source/WebCore/loader/LoaderStrategy.h +index 1a422d75ef5071450145933553e2b7a7cddb2c9c..413e06e6ed569932807b064a43f557023c1004bf 100644 +--- a/Source/WebCore/loader/LoaderStrategy.h ++++ b/Source/WebCore/loader/LoaderStrategy.h +@@ -84,6 +84,7 @@ public: + + virtual bool isOnLine() const = 0; + virtual void addOnlineStateChangeListener(WTF::Function&&) = 0; ++ virtual void setEmulateOfflineState(bool) {}; + + virtual bool shouldPerformSecurityChecks() const { return false; } + virtual bool havePerformedSecurityChecks(const ResourceResponse&) const { return false; } +diff --git a/Source/WebCore/loader/PolicyChecker.cpp b/Source/WebCore/loader/PolicyChecker.cpp +index 22b0588a61a84d73cd20bea2764cfcae4737ba1a..5f0c1d79ae2b5e878b28f1504120d406e1ae35db 100644 +--- a/Source/WebCore/loader/PolicyChecker.cpp ++++ b/Source/WebCore/loader/PolicyChecker.cpp +@@ -46,6 +46,7 @@ + #include "HTMLFormElement.h" + #include "HTMLFrameOwnerElement.h" + #include "HTMLPlugInElement.h" ++#include "InspectorInstrumentation.h" + #include "Logging.h" + #include + +@@ -260,26 +261,32 @@ void FrameLoader::PolicyChecker::checkNewWindowPolicy(NavigationAction&& navigat + + auto blobURLLifetimeExtension = extendBlobURLLifetimeIfNecessary(request, nullptr); + ++ InspectorInstrumentation::willCheckNewWindowPolicy(m_frame, request.url()); + auto requestIdentifier = PolicyCheckIdentifier::create(); + m_frame.loader().client().dispatchDecidePolicyForNewWindowAction(navigationAction, request, formState.get(), frameName, requestIdentifier, [frame = makeRef(m_frame), request, + formState = WTFMove(formState), frameName, navigationAction, function = WTFMove(function), blobURLLifetimeExtension = WTFMove(blobURLLifetimeExtension), + requestIdentifier] (PolicyAction policyAction, PolicyCheckIdentifier responseIdentifier) mutable { + +- if (!responseIdentifier.isValidFor(requestIdentifier)) ++ if (!responseIdentifier.isValidFor(requestIdentifier)) { ++ InspectorInstrumentation::didCheckNewWindowPolicy(frame.get(), false); + return function({ }, nullptr, { }, { }, ShouldContinuePolicyCheck::No); ++ } + + switch (policyAction) { + case PolicyAction::Download: + frame->loader().client().startDownload(request); + FALLTHROUGH; + case PolicyAction::Ignore: ++ InspectorInstrumentation::didCheckNewWindowPolicy(frame.get(), false); + function({ }, nullptr, { }, { }, ShouldContinuePolicyCheck::No); + return; + case PolicyAction::StopAllLoads: + ASSERT_NOT_REACHED(); ++ InspectorInstrumentation::didCheckNewWindowPolicy(frame.get(), false); + function({ }, nullptr, { }, { }, ShouldContinuePolicyCheck::No); + return; + case PolicyAction::Use: ++ InspectorInstrumentation::didCheckNewWindowPolicy(frame.get(), true); + function(request, makeWeakPtr(formState.get()), frameName, navigationAction, ShouldContinuePolicyCheck::Yes); + return; + } +diff --git a/Source/WebCore/loader/ProgressTracker.cpp b/Source/WebCore/loader/ProgressTracker.cpp +index e24fded2225f1c1918f454017566717e20484eab..30e4b7a986418c4b4f6c799b858b608206e22bb5 100644 +--- a/Source/WebCore/loader/ProgressTracker.cpp ++++ b/Source/WebCore/loader/ProgressTracker.cpp +@@ -154,6 +154,8 @@ void ProgressTracker::progressCompleted(Frame& frame) + if (!m_numProgressTrackedFrames || m_originatingProgressFrame == &frame) + finalProgressComplete(); + ++ InspectorInstrumentation::frameStoppedLoading(frame); ++ + m_client->didChangeEstimatedProgress(); + } + +@@ -179,8 +181,6 @@ void ProgressTracker::finalProgressComplete() + frame->loader().client().setMainFrameDocumentReady(true); + m_client->progressFinished(*frame); + frame->loader().loadProgressingStatusChanged(); +- +- InspectorInstrumentation::frameStoppedLoading(*frame); + } + + void ProgressTracker::incrementProgress(unsigned long identifier, const ResourceResponse& response) +diff --git a/Source/WebCore/page/ChromeClient.h b/Source/WebCore/page/ChromeClient.h +index a9a3b07edb08e9e5bed95ce4ede97981d70594a4..a0d4d1698a0a0167ca6a77416ea73291c4ee9ca5 100644 +--- a/Source/WebCore/page/ChromeClient.h ++++ b/Source/WebCore/page/ChromeClient.h +@@ -288,7 +288,7 @@ public: + #endif + + #if ENABLE(ORIENTATION_EVENTS) +- virtual int deviceOrientation() const = 0; ++ virtual int deviceOrientation() const { return 0; } + #endif + + #if ENABLE(INPUT_TYPE_COLOR) +diff --git a/Source/WebCore/page/EventHandler.cpp b/Source/WebCore/page/EventHandler.cpp +index aeed5c2b380796e15617404946ebfda1c5b46629..751a26fc4df017adb6bc1cf9ffae13dfb1c7dcce 100644 +--- a/Source/WebCore/page/EventHandler.cpp ++++ b/Source/WebCore/page/EventHandler.cpp +@@ -122,6 +122,7 @@ + + #if ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS) + #include "PlatformTouchEvent.h" ++#include "PointerCaptureController.h" + #endif + + #if ENABLE(MAC_GESTURE_EVENTS) +@@ -777,9 +778,7 @@ bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve + m_mousePressNode = event.targetNode(); + m_frame.document()->setFocusNavigationStartingNode(event.targetNode()); + +-#if ENABLE(DRAG_SUPPORT) + m_dragStartPosition = event.event().position(); +-#endif + + m_mousePressed = true; + m_selectionInitiationState = HaveNotStartedSelection; +@@ -818,8 +817,6 @@ VisiblePosition EventHandler::selectionExtentRespectingEditingBoundary(const Vis + return targetNode->renderer()->positionForPoint(LayoutPoint(selectionEndPoint), nullptr); + } + +-#if ENABLE(DRAG_SUPPORT) +- + #if !PLATFORM(IOS_FAMILY) + + bool EventHandler::supportsSelectionUpdatesOnMouseDrag() const +@@ -841,8 +838,10 @@ bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e + + Ref protectedFrame(m_frame); + ++#if ENABLE(DRAG_SUPPORT) + if (handleDrag(event, checkDragHysteresis)) + return true; ++#endif + + Node* targetNode = event.targetNode(); + if (event.event().button() != LeftButton || !targetNode) +@@ -863,7 +862,9 @@ bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e + ASSERT(mouseDownMayStartSelect() || m_mouseDownMayStartAutoscroll); + #endif + ++#if ENABLE(DRAG_SUPPORT) + m_mouseDownMayStartDrag = false; ++#endif + + if (m_mouseDownMayStartAutoscroll && !panScrollInProgress()) { + m_autoscrollController->startAutoscrollForSelection(renderer); +@@ -880,6 +881,8 @@ bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e + return true; + } + ++#if ENABLE(DRAG_SUPPORT) ++ + bool EventHandler::eventMayStartDrag(const PlatformMouseEvent& event) const + { + // This is a pre-flight check of whether the event might lead to a drag being started. Be careful +@@ -911,6 +914,8 @@ bool EventHandler::eventMayStartDrag(const PlatformMouseEvent& event) const + return targetElement && page->dragController().draggableElement(&m_frame, targetElement, result.roundedPointInInnerNodeFrame(), state); + } + ++#endif // ENABLE(DRAG_SUPPORT) ++ + void EventHandler::updateSelectionForMouseDrag() + { + if (!supportsSelectionUpdatesOnMouseDrag()) +@@ -1001,7 +1006,6 @@ void EventHandler::updateSelectionForMouseDrag(const HitTestResult& hitTestResul + m_frame.selection().setSelectionByMouseIfDifferent(newSelection, m_frame.selection().granularity(), + FrameSelection::EndPointsAdjustmentMode::AdjustAtBidiBoundary); + } +-#endif // ENABLE(DRAG_SUPPORT) + + void EventHandler::lostMouseCapture() + { +@@ -1049,9 +1053,7 @@ bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& e + // on the selection, the selection goes away. However, if we are + // editing, place the caret. + if (m_mouseDownWasSingleClickInSelection && m_selectionInitiationState != ExtendedSelection +-#if ENABLE(DRAG_SUPPORT) + && m_dragStartPosition == event.event().position() +-#endif + && m_frame.selection().isRange() + && event.event().button() != RightButton) { + VisibleSelection newSelection; +@@ -2016,10 +2018,8 @@ bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& platformMouseE + + swallowEvent = !dispatchMouseEvent(eventNames().mousemoveEvent, mouseEvent.targetNode(), 0, platformMouseEvent, FireMouseOverOut::Yes); + +-#if ENABLE(DRAG_SUPPORT) + if (!swallowEvent) + swallowEvent = handleMouseDraggedEvent(mouseEvent); +-#endif + + return swallowEvent; + } +@@ -3992,7 +3992,14 @@ bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event, CheckDr + if (!m_frame.document()) + return false; + +- dragState().dataTransfer = DataTransfer::createForDrag(*m_frame.document()); ++#if PLATFORM(MAC) ++ auto* page = m_frame.page(); ++ if (page && !page->overrideDragPasteboardName().isEmpty()) ++ dragState().dataTransfer = DataTransfer::createForDrag(*m_frame.document(), page->overrideDragPasteboardName()); ++ else ++#endif ++ dragState().dataTransfer = DataTransfer::createForDrag(*m_frame.document()); ++ + auto hasNonDefaultPasteboardData = HasNonDefaultPasteboardData::No; + + if (dragState().shouldDispatchEvents) { +@@ -4348,7 +4355,8 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) + allTouchReleased = false; + } + +- for (auto& point : points) { ++ for (unsigned index = 0; index < points.size(); index++) { ++ auto& point = points[index]; + PlatformTouchPoint::State pointState = point.state(); + LayoutPoint pagePoint = documentPointForWindowPoint(m_frame, point.pos()); + +@@ -4474,6 +4482,9 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) + changedTouches[pointState].m_touches->append(WTFMove(touch)); + changedTouches[pointState].m_targets.add(touchTarget); + } ++ document.page()->pointerCaptureController().dispatchEventForTouchAtIndex( ++ *touchTarget, event, index, index == 0, *document.windowProxy()); ++ + } + m_touchPressed = touches->length() > 0; + if (allTouchReleased) +diff --git a/Source/WebCore/page/EventHandler.h b/Source/WebCore/page/EventHandler.h +index 5d042038bf34bf89ffe3db994763737889452879..d2b698bc61590e09abd2770cda46b408edc4ae47 100644 +--- a/Source/WebCore/page/EventHandler.h ++++ b/Source/WebCore/page/EventHandler.h +@@ -135,9 +135,7 @@ public: + + WEBCORE_EXPORT VisiblePosition selectionExtentRespectingEditingBoundary(const VisibleSelection&, const LayoutPoint&, Node*); + +-#if ENABLE(DRAG_SUPPORT) + void updateSelectionForMouseDrag(); +-#endif + + #if ENABLE(PAN_SCROLLING) + void didPanScrollStart(); +@@ -374,10 +372,8 @@ private: + bool handleMousePressEventDoubleClick(const MouseEventWithHitTestResults&); + bool handleMousePressEventTripleClick(const MouseEventWithHitTestResults&); + +-#if ENABLE(DRAG_SUPPORT) + bool handleMouseDraggedEvent(const MouseEventWithHitTestResults&, CheckDragHysteresis = ShouldCheckDragHysteresis); + bool shouldAllowMouseDownToStartDrag() const; +-#endif + + WEBCORE_EXPORT bool handleMouseReleaseEvent(const MouseEventWithHitTestResults&); + +@@ -482,10 +478,8 @@ private: + void defaultTabEventHandler(KeyboardEvent&); + void defaultArrowEventHandler(FocusDirection, KeyboardEvent&); + +-#if ENABLE(DRAG_SUPPORT) + OptionSet updateDragSourceActionsAllowed() const; + bool supportsSelectionUpdatesOnMouseDrag() const; +-#endif + + // The following are called at the beginning of handleMouseUp and handleDrag. + // If they return true it indicates that they have consumed the event. +@@ -493,9 +487,10 @@ private: + + #if ENABLE(DRAG_SUPPORT) + bool eventLoopHandleMouseDragged(const MouseEventWithHitTestResults&); +- void updateSelectionForMouseDrag(const HitTestResult&); + #endif + ++ void updateSelectionForMouseDrag(const HitTestResult&); ++ + enum class SetOrClearLastScrollbar { Clear, Set }; + void updateLastScrollbarUnderMouse(Scrollbar*, SetOrClearLastScrollbar); + +@@ -587,8 +582,8 @@ private: + Timer m_autoHideCursorTimer; + #endif + +-#if ENABLE(DRAG_SUPPORT) + LayoutPoint m_dragStartPosition; ++#if ENABLE(DRAG_SUPPORT) + RefPtr m_dragTarget; + bool m_mouseDownMayStartDrag { false }; + bool m_dragMayStartSelectionInstead { false }; +diff --git a/Source/WebCore/page/EventSource.cpp b/Source/WebCore/page/EventSource.cpp +index 757765c3b4872d5a6f92b34e3f2ac67eaaf2dd82..69c4ef67941cee93213ccac1aa04d2cb1db08782 100644 +--- a/Source/WebCore/page/EventSource.cpp ++++ b/Source/WebCore/page/EventSource.cpp +@@ -36,6 +36,7 @@ + #include "CachedResourceRequestInitiators.h" + #include "ContentSecurityPolicy.h" + #include "EventNames.h" ++#include "InspectorNetworkAgent.h" + #include "MessageEvent.h" + #include "ResourceError.h" + #include "ResourceRequest.h" +@@ -97,6 +98,7 @@ void EventSource::connect() + ASSERT(!m_requestInFlight); + + ResourceRequest request { m_url }; ++ request.setInitiatorIdentifier(InspectorNetworkAgent::initiatorIdentifierForEventSource()); + request.setHTTPMethod("GET"); + request.setHTTPHeaderField(HTTPHeaderName::Accept, "text/event-stream"); + request.setHTTPHeaderField(HTTPHeaderName::CacheControl, "no-cache"); +diff --git a/Source/WebCore/page/Frame.cpp b/Source/WebCore/page/Frame.cpp +index a75a3c0a16d27c7057feccc81c258fa510ba61de..cadc30cbff7d943a993204120cf09bcfd58ba5f3 100644 +--- a/Source/WebCore/page/Frame.cpp ++++ b/Source/WebCore/page/Frame.cpp +@@ -39,6 +39,7 @@ + #include "CachedResourceLoader.h" + #include "Chrome.h" + #include "ChromeClient.h" ++#include "ComposedTreeIterator.h" + #include "DOMWindow.h" + #include "DocumentTimeline.h" + #include "DocumentType.h" +@@ -71,6 +72,7 @@ + #include "NavigationScheduler.h" + #include "Navigator.h" + #include "NodeList.h" ++#include "NodeRenderStyle.h" + #include "NodeTraversal.h" + #include "Page.h" + #include "ProcessWarming.h" +@@ -179,6 +181,7 @@ Frame::Frame(Page& page, HTMLFrameOwnerElement* ownerElement, UniqueRefinit(); ++ InspectorInstrumentation::frameAttached(this); + } + + Ref Frame::create(Page* page, HTMLFrameOwnerElement* ownerElement, UniqueRef&& client) +@@ -364,7 +367,7 @@ void Frame::orientationChanged() + int Frame::orientation() const + { + if (m_page) +- return m_page->chrome().client().deviceOrientation(); ++ return m_page->orientation(); + return 0; + } + #endif // ENABLE(ORIENTATION_EVENTS) +@@ -1154,6 +1157,358 @@ bool Frame::arePluginsEnabled() + return settings().arePluginsEnabled(); + } + ++void Frame::betterApproximateNode(const IntPoint& testPoint, const NodeQualifier& nodeQualifierFunction, Node*& best, Node* failedNode, IntPoint& bestPoint, IntRect& bestRect, const IntRect& testRect) ++{ ++ IntRect candidateRect; ++ constexpr OptionSet hitType { HitTestRequest::ReadOnly, HitTestRequest::Active, HitTestRequest::DisallowUserAgentShadowContent, HitTestRequest::AllowVisibleChildFrameContentOnly }; ++ auto* candidate = nodeQualifierFunction(eventHandler().hitTestResultAtPoint(testPoint, hitType), failedNode, &candidateRect); ++ ++ // Bail if we have no candidate, or the candidate is already equal to our current best node, ++ // or our candidate is the avoidedNode and there is a current best node. ++ if (!candidate || candidate == best) ++ return; ++ ++ // The document should never be considered the best alternative. ++ if (candidate->isDocumentNode()) ++ return; ++ ++ if (best) { ++ IntRect bestIntersect = intersection(testRect, bestRect); ++ IntRect candidateIntersect = intersection(testRect, candidateRect); ++ // if the candidate intersection is smaller than the current best intersection, bail. ++ if (candidateIntersect.width() * candidateIntersect.height() <= bestIntersect.width() * bestIntersect.height()) ++ return; ++ } ++ ++ // At this point we either don't have a previous best, or our current candidate has a better intersection. ++ best = candidate; ++ bestPoint = testPoint; ++ bestRect = candidateRect; ++} ++ ++bool Frame::hitTestResultAtViewportLocation(const FloatPoint& viewportLocation, HitTestResult& hitTestResult, IntPoint& center) ++{ ++ if (!m_doc || !m_doc->renderView()) ++ return false; ++ ++ FrameView* view = m_view.get(); ++ if (!view) ++ return false; ++ ++ center = view->windowToContents(roundedIntPoint(viewportLocation)); ++ constexpr OptionSet hitType { HitTestRequest::ReadOnly, HitTestRequest::Active, HitTestRequest::DisallowUserAgentShadowContent, HitTestRequest::AllowVisibleChildFrameContentOnly }; ++ hitTestResult = eventHandler().hitTestResultAtPoint(center, hitType); ++ return true; ++} ++ ++Node* Frame::qualifyingNodeAtViewportLocation(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation, const NodeQualifier& nodeQualifierFunction, ShouldApproximate shouldApproximate, ShouldFindRootEditableElement shouldFindRootEditableElement) ++{ ++ adjustedViewportLocation = viewportLocation; ++ ++ IntPoint testCenter; ++ HitTestResult candidateInfo; ++ if (!hitTestResultAtViewportLocation(viewportLocation, candidateInfo, testCenter)) ++ return nullptr; ++ ++ IntPoint bestPoint = testCenter; ++ ++ // We have the candidate node at the location, check whether it or one of its ancestors passes ++ // the qualifier function, which typically checks if the node responds to a particular event type. ++ Node* approximateNode = nodeQualifierFunction(candidateInfo, 0, 0); ++ ++ if (shouldFindRootEditableElement == ShouldFindRootEditableElement::Yes && approximateNode && approximateNode->isContentEditable()) { ++ // If we are in editable content, we look for the root editable element. ++ approximateNode = approximateNode->rootEditableElement(); ++ // If we have a focusable node, there is no need to approximate. ++ if (approximateNode) ++ shouldApproximate = ShouldApproximate::No; ++ } ++ ++ float scale = page() ? page()->pageScaleFactor() : 1; ++#if PLATFORM(IOS_FAMILY) ++ float ppiFactor = screenPPIFactor(); ++#else ++ float ppiFactor = 326; // most popular iPhone PPI ++#endif ++ ++ static const float unscaledSearchRadius = 15; ++ int searchRadius = static_cast(unscaledSearchRadius * ppiFactor / scale); ++ ++ if (approximateNode && shouldApproximate == ShouldApproximate::Yes) { ++ const float testOffsets[] = { ++ -.3f, -.3f, ++ -.6f, -.6f, ++ +.3f, +.3f, ++ -.9f, -.9f, ++ }; ++ ++ Node* originalApproximateNode = approximateNode; ++ for (unsigned n = 0; n < WTF_ARRAY_LENGTH(testOffsets); n += 2) { ++ IntSize testOffset(testOffsets[n] * searchRadius, testOffsets[n + 1] * searchRadius); ++ IntPoint testPoint = testCenter + testOffset; ++ ++ constexpr OptionSet hitType { HitTestRequest::ReadOnly, HitTestRequest::Active, HitTestRequest::DisallowUserAgentShadowContent, HitTestRequest::AllowChildFrameContent }; ++ auto candidateInfo = eventHandler().hitTestResultAtPoint(testPoint, hitType); ++ Node* candidateNode = nodeQualifierFunction(candidateInfo, 0, 0); ++ if (candidateNode && candidateNode->isDescendantOf(originalApproximateNode)) { ++ approximateNode = candidateNode; ++ bestPoint = testPoint; ++ break; ++ } ++ } ++ } else if (!approximateNode && shouldApproximate == ShouldApproximate::Yes) { ++ // Grab the closest parent element of our failed candidate node. ++ Node* candidate = candidateInfo.innerNode(); ++ Node* failedNode = candidate; ++ ++ while (candidate && !candidate->isElementNode()) ++ candidate = candidate->parentInComposedTree(); ++ ++ if (candidate) ++ failedNode = candidate; ++ ++ // The center point was tested earlier. ++ const float testOffsets[] = { ++ -.3f, -.3f, ++ +.3f, -.3f, ++ -.3f, +.3f, ++ +.3f, +.3f, ++ -.6f, -.6f, ++ +.6f, -.6f, ++ -.6f, +.6f, ++ +.6f, +.6f, ++ -1.f, 0, ++ +1.f, 0, ++ 0, +1.f, ++ 0, -1.f, ++ }; ++ IntRect bestFrame; ++ IntRect testRect(testCenter, IntSize()); ++ testRect.inflate(searchRadius); ++ int currentTestRadius = 0; ++ for (unsigned n = 0; n < WTF_ARRAY_LENGTH(testOffsets); n += 2) { ++ IntSize testOffset(testOffsets[n] * searchRadius, testOffsets[n + 1] * searchRadius); ++ IntPoint testPoint = testCenter + testOffset; ++ int testRadius = std::max(abs(testOffset.width()), abs(testOffset.height())); ++ if (testRadius > currentTestRadius) { ++ // Bail out with the best match within a radius ++ currentTestRadius = testRadius; ++ if (approximateNode) ++ break; ++ } ++ betterApproximateNode(testPoint, nodeQualifierFunction, approximateNode, failedNode, bestPoint, bestFrame, testRect); ++ } ++ } ++ ++ if (approximateNode) { ++ IntPoint p = m_view->contentsToWindow(bestPoint); ++ adjustedViewportLocation = p; ++ if (shouldFindRootEditableElement == ShouldFindRootEditableElement::Yes && approximateNode->isContentEditable()) { ++ // When in editable content, look for the root editable node again, ++ // since this could be the node found with the approximation. ++ approximateNode = approximateNode->rootEditableElement(); ++ } ++ } ++ ++ return approximateNode; ++} ++ ++Node* Frame::deepestNodeAtLocation(const FloatPoint& viewportLocation) ++{ ++ IntPoint center; ++ HitTestResult hitTestResult; ++ if (!hitTestResultAtViewportLocation(viewportLocation, hitTestResult, center)) ++ return nullptr; ++ ++ return hitTestResult.innerNode(); ++} ++ ++static bool nodeIsMouseFocusable(Node& node) ++{ ++ if (!is(node)) ++ return false; ++ ++ auto& element = downcast(node); ++ if (element.isMouseFocusable()) ++ return true; ++ ++ if (auto shadowRoot = makeRefPtr(element.shadowRoot())) { ++ if (shadowRoot->delegatesFocus()) { ++ for (auto& node : composedTreeDescendants(element)) { ++ if (is(node) && downcast(node).isMouseFocusable()) ++ return true; ++ } ++ } ++ } ++ ++ return false; ++} ++ ++static bool nodeWillRespondToMouseEvents(Node& node) ++{ ++ return node.willRespondToMouseClickEvents() || node.willRespondToMouseMoveEvents() || nodeIsMouseFocusable(node); ++} ++ ++Node* Frame::approximateNodeAtViewportLocationLegacy(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation) ++{ ++ // This function is only used for UIWebView. ++ auto&& ancestorRespondingToClickEvents = [](const HitTestResult& hitTestResult, Node* terminationNode, IntRect* nodeBounds) -> Node* { ++ bool bodyHasBeenReached = false; ++ bool pointerCursorStillValid = true; ++ ++ if (nodeBounds) ++ *nodeBounds = IntRect(); ++ ++ auto node = hitTestResult.innerNode(); ++ if (!node) ++ return nullptr; ++ ++ Node* pointerCursorNode = nullptr; ++ for (; node && node != terminationNode; node = node->parentInComposedTree()) { ++ // We only accept pointer nodes before reaching the body tag. ++ if (node->hasTagName(HTMLNames::bodyTag)) { ++ // Make sure we cover the case of an empty editable body. ++ if (!pointerCursorNode && node->isContentEditable()) ++ pointerCursorNode = node; ++ bodyHasBeenReached = true; ++ pointerCursorStillValid = false; ++ } ++ ++ // If we already have a pointer, and we reach a table, don't accept it. ++ if (pointerCursorNode && (node->hasTagName(HTMLNames::tableTag) || node->hasTagName(HTMLNames::tbodyTag))) ++ pointerCursorStillValid = false; ++ ++ // If we haven't reached the body, and we are still paying attention to pointer cursors, and the node has a pointer cursor. ++ if (pointerCursorStillValid && node->renderStyle() && node->renderStyle()->cursor() == CursorType::Pointer) ++ pointerCursorNode = node; ++ else if (pointerCursorNode) { ++ // We want the lowest unbroken chain of pointer cursors. ++ pointerCursorStillValid = false; ++ } ++ ++ if (nodeWillRespondToMouseEvents(*node)) { ++ // If we're at the body or higher, use the pointer cursor node (which may be null). ++ if (bodyHasBeenReached) ++ node = pointerCursorNode; ++ ++ // If we are interested about the frame, use it. ++ if (nodeBounds) { ++ // This is a check to see whether this node is an area element. The only way this can happen is if this is the first check. ++ if (node == hitTestResult.innerNode() && node != hitTestResult.innerNonSharedNode() && is(*node)) ++ *nodeBounds = snappedIntRect(downcast(*node).computeRect(hitTestResult.innerNonSharedNode()->renderer())); ++ else if (node && node->renderer()) ++ *nodeBounds = node->renderer()->absoluteBoundingBoxRect(true); ++ } ++ ++ return node; ++ } ++ } ++ ++ return nullptr; ++ }; ++ ++ return qualifyingNodeAtViewportLocation(viewportLocation, adjustedViewportLocation, WTFMove(ancestorRespondingToClickEvents), ShouldApproximate::Yes); ++} ++ ++static inline NodeQualifier ancestorRespondingToClickEventsNodeQualifier(SecurityOrigin* securityOrigin = nullptr) ++{ ++ return [securityOrigin](const HitTestResult& hitTestResult, Node* terminationNode, IntRect* nodeBounds) -> Node* { ++ if (nodeBounds) ++ *nodeBounds = IntRect(); ++ ++ auto node = hitTestResult.innerNode(); ++ if (!node || (securityOrigin && !securityOrigin->isSameOriginAs(node->document().securityOrigin()))) ++ return nullptr; ++ ++ for (; node && node != terminationNode; node = node->parentInComposedTree()) { ++ if (nodeWillRespondToMouseEvents(*node)) { ++ // If we are interested about the frame, use it. ++ if (nodeBounds) { ++ // This is a check to see whether this node is an area element. The only way this can happen is if this is the first check. ++ if (node == hitTestResult.innerNode() && node != hitTestResult.innerNonSharedNode() && is(*node)) ++ *nodeBounds = snappedIntRect(downcast(*node).computeRect(hitTestResult.innerNonSharedNode()->renderer())); ++ else if (node && node->renderer()) ++ *nodeBounds = node->renderer()->absoluteBoundingBoxRect(true); ++ } ++ ++ return node; ++ } ++ } ++ ++ return nullptr; ++ }; ++} ++ ++Node* Frame::nodeRespondingToClickEvents(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation, SecurityOrigin* securityOrigin) ++{ ++ return qualifyingNodeAtViewportLocation(viewportLocation, adjustedViewportLocation, ancestorRespondingToClickEventsNodeQualifier(securityOrigin), ShouldApproximate::Yes); ++} ++ ++Node* Frame::nodeRespondingToDoubleClickEvent(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation) ++{ ++ auto&& ancestorRespondingToDoubleClickEvent = [](const HitTestResult& hitTestResult, Node* terminationNode, IntRect* nodeBounds) -> Node* { ++ if (nodeBounds) ++ *nodeBounds = IntRect(); ++ ++ auto* node = hitTestResult.innerNode(); ++ if (!node) ++ return nullptr; ++ ++ for (; node && node != terminationNode; node = node->parentInComposedTree()) { ++ if (!node->hasEventListeners(eventNames().dblclickEvent)) ++ continue; ++#if ENABLE(TOUCH_EVENTS) ++ if (!node->allowsDoubleTapGesture()) ++ continue; ++#endif ++ if (nodeBounds && node->renderer()) ++ *nodeBounds = node->renderer()->absoluteBoundingBoxRect(true); ++ return node; ++ } ++ return nullptr; ++ }; ++ ++ return qualifyingNodeAtViewportLocation(viewportLocation, adjustedViewportLocation, WTFMove(ancestorRespondingToDoubleClickEvent), ShouldApproximate::Yes); ++} ++ ++Node* Frame::nodeRespondingToInteraction(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation) ++{ ++ return qualifyingNodeAtViewportLocation(viewportLocation, adjustedViewportLocation, ancestorRespondingToClickEventsNodeQualifier(), ShouldApproximate::Yes, ShouldFindRootEditableElement::No); ++} ++ ++Node* Frame::nodeRespondingToScrollWheelEvents(const FloatPoint& viewportLocation) ++{ ++ auto&& ancestorRespondingToScrollWheelEvents = [](const HitTestResult& hitTestResult, Node* terminationNode, IntRect* nodeBounds) -> Node* { ++ if (nodeBounds) ++ *nodeBounds = IntRect(); ++ ++ Node* scrollingAncestor = nullptr; ++ for (Node* node = hitTestResult.innerNode(); node && node != terminationNode && !node->hasTagName(HTMLNames::bodyTag); node = node->parentNode()) { ++ RenderObject* renderer = node->renderer(); ++ if (!renderer) ++ continue; ++ ++ if ((renderer->isTextField() || renderer->isTextArea()) && downcast(*renderer).canScroll()) { ++ scrollingAncestor = node; ++ continue; ++ } ++ ++ auto& style = renderer->style(); ++ ++ if (renderer->hasOverflowClip() ++ && (style.overflowY() == Overflow::Auto || style.overflowY() == Overflow::Scroll ++ || style.overflowX() == Overflow::Auto || style.overflowX() == Overflow::Scroll)) { ++ scrollingAncestor = node; ++ } ++ } ++ ++ return scrollingAncestor; ++ }; ++ ++ FloatPoint adjustedViewportLocation; ++ return qualifyingNodeAtViewportLocation(viewportLocation, adjustedViewportLocation, WTFMove(ancestorRespondingToScrollWheelEvents), ShouldApproximate::No); ++} ++ + } // namespace WebCore + + #undef RELEASE_LOG_ERROR_IF_ALLOWED +diff --git a/Source/WebCore/page/Frame.h b/Source/WebCore/page/Frame.h +index 0c9a65b9cf13d733c3dc580b5f2614123cfd9810..cc524edd5668db78eb23ae28f24efa3539a09b7f 100644 +--- a/Source/WebCore/page/Frame.h ++++ b/Source/WebCore/page/Frame.h +@@ -109,8 +109,8 @@ enum { + }; + + enum OverflowScrollAction { DoNotPerformOverflowScroll, PerformOverflowScroll }; +-using NodeQualifier = Function; + #endif ++using NodeQualifier = Function; + + enum { + LayerTreeFlagsIncludeDebugInfo = 1 << 0, +@@ -229,10 +229,6 @@ public: + NSArray *dataDetectionResults() const { return m_dataDetectionResults.get(); } + #endif + +-#if PLATFORM(IOS_FAMILY) +- const ViewportArguments& viewportArguments() const; +- WEBCORE_EXPORT void setViewportArguments(const ViewportArguments&); +- + WEBCORE_EXPORT Node* deepestNodeAtLocation(const FloatPoint& viewportLocation); + WEBCORE_EXPORT Node* nodeRespondingToClickEvents(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation, SecurityOrigin* = nullptr); + WEBCORE_EXPORT Node* nodeRespondingToDoubleClickEvent(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation); +@@ -240,6 +236,10 @@ public: + WEBCORE_EXPORT Node* nodeRespondingToScrollWheelEvents(const FloatPoint& viewportLocation); + WEBCORE_EXPORT Node* approximateNodeAtViewportLocationLegacy(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation); + ++#if PLATFORM(IOS_FAMILY) ++ const ViewportArguments& viewportArguments() const; ++ WEBCORE_EXPORT void setViewportArguments(const ViewportArguments&); ++ + WEBCORE_EXPORT NSArray *wordsInCurrentParagraph() const; + WEBCORE_EXPORT CGRect renderRectForPoint(CGPoint, bool* isReplaced, float* fontSize) const; + +@@ -313,6 +313,7 @@ public: + + WEBCORE_EXPORT FloatSize screenSize() const; + void setOverrideScreenSize(FloatSize&&); ++ bool hasScreenSizeOverride() const { return !m_overrideScreenSize.isEmpty(); } + + void selfOnlyRef(); + void selfOnlyDeref(); +@@ -351,7 +352,6 @@ private: + #if ENABLE(DATA_DETECTION) + RetainPtr m_dataDetectionResults; + #endif +-#if PLATFORM(IOS_FAMILY) + void betterApproximateNode(const IntPoint& testPoint, const NodeQualifier&, Node*& best, Node* failedNode, IntPoint& bestPoint, IntRect& bestRect, const IntRect& testRect); + bool hitTestResultAtViewportLocation(const FloatPoint& viewportLocation, HitTestResult&, IntPoint& center); + +@@ -359,6 +359,7 @@ private: + enum class ShouldFindRootEditableElement : bool { No, Yes }; + Node* qualifyingNodeAtViewportLocation(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation, const NodeQualifier&, ShouldApproximate, ShouldFindRootEditableElement = ShouldFindRootEditableElement::Yes); + ++#if PLATFORM(IOS_FAMILY) + void setTimersPausedInternal(bool); + + ViewportArguments m_viewportArguments; +diff --git a/Source/WebCore/page/FrameSnapshotting.cpp b/Source/WebCore/page/FrameSnapshotting.cpp +index e2f8a37fb89b421eebfa846e54c47ee795c6a9ab..f31da2c7cb84a027601c68d26232670c1f3ab142 100644 +--- a/Source/WebCore/page/FrameSnapshotting.cpp ++++ b/Source/WebCore/page/FrameSnapshotting.cpp +@@ -114,7 +114,12 @@ RefPtr snapshotFrameRectWithClip(Frame& frame, const IntRect& image + auto buffer = ImageBuffer::create(imageRect.size(), RenderingMode::Unaccelerated, scaleFactor); + if (!buffer) + return nullptr; ++#if !PLATFORM(MAC) ++ buffer->context().scale(scaleFactor); ++#endif + buffer->context().translate(-imageRect.x(), -imageRect.y()); ++ if (coordinateSpace != FrameView::ViewCoordinates) ++ buffer->context().scale(1 / frame.page()->pageScaleFactor()); + + if (!clipRects.isEmpty()) { + Path clipPath; +@@ -123,7 +128,10 @@ RefPtr snapshotFrameRectWithClip(Frame& frame, const IntRect& image + buffer->context().clipPath(clipPath); + } + +- frame.view()->paintContentsForSnapshot(buffer->context(), imageRect, shouldIncludeSelection, coordinateSpace); ++ FloatRect fr = imageRect; ++ if (coordinateSpace != FrameView::ViewCoordinates) ++ fr.scale(frame.page()->pageScaleFactor()); ++ frame.view()->paintContentsForSnapshot(buffer->context(), enclosingIntRect(fr), shouldIncludeSelection, coordinateSpace); + return buffer; + } + +diff --git a/Source/WebCore/page/FrameView.cpp b/Source/WebCore/page/FrameView.cpp +index 69acfb0d1b6bfd48bba9c961da4453653c4453be..2a5a9fcbf2c7190df9f31a1b73e4552f513a6457 100644 +--- a/Source/WebCore/page/FrameView.cpp ++++ b/Source/WebCore/page/FrameView.cpp +@@ -3036,7 +3036,7 @@ void FrameView::setBaseBackgroundColor(const Color& backgroundColor) + + void FrameView::updateBackgroundRecursively(const Optional& backgroundColor) + { +-#if HAVE(OS_DARK_MODE_SUPPORT) ++#if HAVE(OS_DARK_MODE_SUPPORT) && (defined(WTF_PLATFORM_MAC) && WTF_PLATFORM_MAC) || (defined(WTF_PLATFORM_IOS_FAMILY) && WTF_PLATFORM_IOS_FAMILY) + Color baseBackgroundColor = backgroundColor.valueOr(RenderTheme::singleton().systemColor(CSSValueAppleSystemControlBackground, styleColorOptions())); + #else + Color baseBackgroundColor = backgroundColor.valueOr(Color::white); +diff --git a/Source/WebCore/page/History.cpp b/Source/WebCore/page/History.cpp +index 38fd7b29b53eab484e30963b51c8ae525c5d7a38..3c2f2104e3f364d3d6201e3009a448b4db317d03 100644 +--- a/Source/WebCore/page/History.cpp ++++ b/Source/WebCore/page/History.cpp +@@ -33,6 +33,7 @@ + #include "FrameLoaderClient.h" + #include "HistoryController.h" + #include "HistoryItem.h" ++#include "InspectorInstrumentation.h" + #include "Logging.h" + #include "NavigationScheduler.h" + #include "Page.h" +@@ -260,6 +261,7 @@ ExceptionOr History::stateObjectAdded(RefPtr&& data + + if (!urlString.isEmpty()) + frame->document()->updateURLForPushOrReplaceState(fullURL); ++ InspectorInstrumentation::didNavigateWithinPage(*frame); + + if (stateObjectType == StateObjectType::Push) { + frame->loader().history().pushState(WTFMove(data), title, fullURL.string()); +diff --git a/Source/WebCore/page/Page.cpp b/Source/WebCore/page/Page.cpp +index 040973abb4b3267c34a3693ed80c0e602b66a8e8..dc2c19fad82120d073e2d71d3e274cbcf6645379 100644 +--- a/Source/WebCore/page/Page.cpp ++++ b/Source/WebCore/page/Page.cpp +@@ -438,6 +438,37 @@ void Page::setOverrideViewportArguments(const Optional& viewp + document->updateViewportArguments(); + } + ++FloatSize Page::screenSize() ++{ ++ return m_overrideScreenSize.valueOr(screenRect(mainFrame().view()).size()); ++} ++ ++void Page::setOverrideScreenSize(Optional size) ++{ ++ if (size == m_overrideScreenSize) ++ return; ++ ++ m_overrideScreenSize = size; ++ if (auto* document = mainFrame().document()) ++ document->updateViewportArguments(); ++} ++ ++#if ENABLE(ORIENTATION_EVENTS) ++int Page::orientation() const ++{ ++ return m_overrideOrientation.valueOr(chrome().client().deviceOrientation()); ++} ++ ++void Page::setOverrideOrientation(Optional orientation) ++{ ++ if (orientation == m_overrideOrientation) ++ return; ++ ++ m_overrideOrientation = orientation; ++ mainFrame().orientationChanged(); ++} ++#endif ++ + ScrollingCoordinator* Page::scrollingCoordinator() + { + if (!m_scrollingCoordinator && m_settings->scrollingCoordinatorEnabled()) { +diff --git a/Source/WebCore/page/Page.h b/Source/WebCore/page/Page.h +index 152f492444e19304c826be2f31f8ad222549099d..f2e16daeb71be00c1515ff9e454787693ff3b5e5 100644 +--- a/Source/WebCore/page/Page.h ++++ b/Source/WebCore/page/Page.h +@@ -250,6 +250,9 @@ public: + const Optional& overrideViewportArguments() const { return m_overrideViewportArguments; } + WEBCORE_EXPORT void setOverrideViewportArguments(const Optional&); + ++ WEBCORE_EXPORT FloatSize screenSize(); ++ void setOverrideScreenSize(Optional size); ++ + static void refreshPlugins(bool reload); + WEBCORE_EXPORT PluginData& pluginData(); + void clearPluginData(); +@@ -296,6 +299,10 @@ public: + DragCaretController& dragCaretController() const { return *m_dragCaretController; } + #if ENABLE(DRAG_SUPPORT) + DragController& dragController() const { return *m_dragController; } ++#if PLATFORM(MAC) ++ void setDragPasteboardName(const String& pasteboardName) { m_overrideDragPasteboardName = pasteboardName; } ++ const String& overrideDragPasteboardName() { return m_overrideDragPasteboardName; } ++#endif + #endif + FocusController& focusController() const { return *m_focusController; } + #if ENABLE(CONTEXT_MENUS) +@@ -812,6 +819,11 @@ public: + + WEBCORE_EXPORT Vector> editableElementsInRect(const FloatRect&) const; + ++#if ENABLE(ORIENTATION_EVENTS) ++ int orientation() const; ++ void setOverrideOrientation(Optional); ++#endif ++ + #if ENABLE(DEVICE_ORIENTATION) && PLATFORM(IOS_FAMILY) + DeviceOrientationUpdateProvider* deviceOrientationUpdateProvider() const { return m_deviceOrientationUpdateProvider.get(); } + #endif +@@ -890,6 +902,9 @@ private: + + #if ENABLE(DRAG_SUPPORT) + const std::unique_ptr m_dragController; ++#if PLATFORM(MAC) ++ String m_overrideDragPasteboardName; ++#endif + #endif + const std::unique_ptr m_focusController; + #if ENABLE(CONTEXT_MENUS) +@@ -1130,6 +1145,11 @@ private: + #endif + + Optional m_overrideViewportArguments; ++ Optional m_overrideScreenSize; ++ ++#if ENABLE(ORIENTATION_EVENTS) ++ Optional m_overrideOrientation; ++#endif + + #if ENABLE(DEVICE_ORIENTATION) && PLATFORM(IOS_FAMILY) + RefPtr m_deviceOrientationUpdateProvider; +diff --git a/Source/WebCore/page/PointerCaptureController.cpp b/Source/WebCore/page/PointerCaptureController.cpp +index 757f54568e1d8b4d5fe40f30911073e6de2b17a1..96592389079a90136bb00e1052c50f4946a3453c 100644 +--- a/Source/WebCore/page/PointerCaptureController.cpp ++++ b/Source/WebCore/page/PointerCaptureController.cpp +@@ -202,7 +202,7 @@ bool PointerCaptureController::preventsCompatibilityMouseEventsForIdentifier(Poi + return iterator != m_activePointerIdsToCapturingData.end() && iterator->value.preventsCompatibilityMouseEvents; + } + +-#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY) ++#if ENABLE(TOUCH_EVENTS) + static bool hierarchyHasCapturingEventListeners(Element* target, const AtomString& eventName) + { + for (ContainerNode* curr = target; curr; curr = curr->parentInComposedTree()) { +@@ -490,7 +490,7 @@ void PointerCaptureController::cancelPointer(PointerID pointerId, const IntPoint + capturingData.pendingTargetOverride = nullptr; + capturingData.cancelled = true; + +-#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY) ++#if ENABLE(TOUCH_EVENTS) + capturingData.previousTarget = nullptr; + #endif + +diff --git a/Source/WebCore/page/PointerCaptureController.h b/Source/WebCore/page/PointerCaptureController.h +index 56c1a236db2522c33ad88822602f5e76466c697e..0e5c42f89367726db7dd492a308e24666d415c9f 100644 +--- a/Source/WebCore/page/PointerCaptureController.h ++++ b/Source/WebCore/page/PointerCaptureController.h +@@ -57,7 +57,7 @@ public: + + RefPtr pointerEventForMouseEvent(const MouseEvent&, PointerID, const String& pointerType); + +-#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY) ++#if ENABLE(TOUCH_EVENTS) + void dispatchEventForTouchAtIndex(EventTarget&, const PlatformTouchEvent&, unsigned, bool isPrimary, WindowProxy&); + #endif + +@@ -72,7 +72,7 @@ private: + struct CapturingData { + RefPtr pendingTargetOverride; + RefPtr targetOverride; +-#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY) ++#if ENABLE(TOUCH_EVENTS) + RefPtr previousTarget; + #endif + bool hasAnyElement() const { +diff --git a/Source/WebCore/page/RuntimeEnabledFeatures.cpp b/Source/WebCore/page/RuntimeEnabledFeatures.cpp +index e9d30c7c06618177cbab04e35b75735dc291ad1f..d0673b66d9c14e4e3f2317faa29438aa0bdc616e 100644 +--- a/Source/WebCore/page/RuntimeEnabledFeatures.cpp ++++ b/Source/WebCore/page/RuntimeEnabledFeatures.cpp +@@ -56,7 +56,11 @@ RuntimeEnabledFeatures& RuntimeEnabledFeatures::sharedFeatures() + #if ENABLE(TOUCH_EVENTS) + bool RuntimeEnabledFeatures::touchEventsEnabled() const + { +- return m_touchEventsEnabled.valueOr(screenHasTouchDevice()); ++ return m_touchEventsEnabled.valueOr(platformScreenHasTouchDevice()); ++} ++bool RuntimeEnabledFeatures::isTouchPrimaryInputDevice() const ++{ ++ return m_touchEventsEnabled.valueOr(platformScreenIsTouchPrimaryInputDevice()); + } + #endif + +diff --git a/Source/WebCore/page/RuntimeEnabledFeatures.h b/Source/WebCore/page/RuntimeEnabledFeatures.h +index f819d1c79868b0adc84c64ef1bbb9b2538c93a74..a0efb4592cd227067a304c04b9c5b0ad7bb26d99 100644 +--- a/Source/WebCore/page/RuntimeEnabledFeatures.h ++++ b/Source/WebCore/page/RuntimeEnabledFeatures.h +@@ -220,6 +220,7 @@ public: + void setMouseEventsSimulationEnabled(bool isEnabled) { m_mouseEventsSimulationEnabled = isEnabled; } + bool touchEventsEnabled() const; + void setTouchEventsEnabled(bool isEnabled) { m_touchEventsEnabled = isEnabled; } ++ bool isTouchPrimaryInputDevice() const; + #endif + + bool pageAtRuleSupportEnabled() const { return m_pageAtRuleSupportEnabled; } +diff --git a/Source/WebCore/page/Screen.cpp b/Source/WebCore/page/Screen.cpp +index 7ac11c8289347e3a2f3e7316cf9e32932b9544ed..764b2d4fe36ac2e5588bd22595424ac11d42acd0 100644 +--- a/Source/WebCore/page/Screen.cpp ++++ b/Source/WebCore/page/Screen.cpp +@@ -102,6 +102,8 @@ int Screen::availLeft() const + return 0; + if (RuntimeEnabledFeatures::sharedFeatures().webAPIStatisticsEnabled()) + ResourceLoadObserver::shared().logScreenAPIAccessed(*frame->document(), ResourceLoadStatistics::ScreenAPI::AvailLeft); ++ if (frame->hasScreenSizeOverride()) ++ return 0; + return static_cast(screenAvailableRect(frame->view()).x()); + } + +@@ -112,6 +114,8 @@ int Screen::availTop() const + return 0; + if (RuntimeEnabledFeatures::sharedFeatures().webAPIStatisticsEnabled()) + ResourceLoadObserver::shared().logScreenAPIAccessed(*frame->document(), ResourceLoadStatistics::ScreenAPI::AvailTop); ++ if (frame->hasScreenSizeOverride()) ++ return 0; + return static_cast(screenAvailableRect(frame->view()).y()); + } + +@@ -122,6 +126,8 @@ unsigned Screen::availHeight() const + return 0; + if (RuntimeEnabledFeatures::sharedFeatures().webAPIStatisticsEnabled()) + ResourceLoadObserver::shared().logScreenAPIAccessed(*frame->document(), ResourceLoadStatistics::ScreenAPI::AvailHeight); ++ if (frame->hasScreenSizeOverride()) ++ return static_cast(frame->screenSize().height()); + return static_cast(screenAvailableRect(frame->view()).height()); + } + +@@ -132,6 +138,8 @@ unsigned Screen::availWidth() const + return 0; + if (RuntimeEnabledFeatures::sharedFeatures().webAPIStatisticsEnabled()) + ResourceLoadObserver::shared().logScreenAPIAccessed(*frame->document(), ResourceLoadStatistics::ScreenAPI::AvailWidth); ++ if (frame->hasScreenSizeOverride()) ++ return static_cast(frame->screenSize().width()); + return static_cast(screenAvailableRect(frame->view()).width()); + } + +diff --git a/Source/WebCore/page/SocketProvider.cpp b/Source/WebCore/page/SocketProvider.cpp +index 3bec0aef174336939838fb1069fffbcb9f3d5604..566ef3806be3c5ccf1bb951251c2a90dba7071a3 100644 +--- a/Source/WebCore/page/SocketProvider.cpp ++++ b/Source/WebCore/page/SocketProvider.cpp +@@ -33,7 +33,7 @@ namespace WebCore { + + Ref SocketProvider::createSocketStreamHandle(const URL& url, SocketStreamHandleClient& client, WebSocketIdentifier, PAL::SessionID sessionID, const String& credentialPartition, const StorageSessionProvider* provider) + { +- return SocketStreamHandleImpl::create(url, client, sessionID, credentialPartition, { }, provider); ++ return SocketStreamHandleImpl::create(url, false, client, sessionID, credentialPartition, { }, provider); + } + + RefPtr SocketProvider::createWebSocketChannel(Document&, WebSocketChannelClient&) +diff --git a/Source/WebCore/page/csp/ContentSecurityPolicy.cpp b/Source/WebCore/page/csp/ContentSecurityPolicy.cpp +index 37d5c443785f3df52bddb775cb9c1e66e0dd97b6..f2329ad61fd4f4ad006ca89ba2bdc729278dee0d 100644 +--- a/Source/WebCore/page/csp/ContentSecurityPolicy.cpp ++++ b/Source/WebCore/page/csp/ContentSecurityPolicy.cpp +@@ -299,6 +299,8 @@ bool ContentSecurityPolicy::protocolMatchesSelf(const URL& url) const + template + typename std::enable_if::value, bool>::type ContentSecurityPolicy::allPoliciesWithDispositionAllow(Disposition disposition, Predicate&& predicate, Args&&... args) const + { ++ if (InspectorInstrumentation::shouldBypassCSP(m_scriptExecutionContext)) ++ return true; + bool isReportOnly = disposition == ContentSecurityPolicy::Disposition::ReportOnly; + for (auto& policy : m_policies) { + if (policy->isReportOnly() != isReportOnly) +@@ -312,6 +314,8 @@ typename std::enable_if + bool ContentSecurityPolicy::allPoliciesWithDispositionAllow(Disposition disposition, ViolatedDirectiveCallback&& callback, Predicate&& predicate, Args&&... args) const + { ++ if (InspectorInstrumentation::shouldBypassCSP(m_scriptExecutionContext)) ++ return true; + bool isReportOnly = disposition == ContentSecurityPolicy::Disposition::ReportOnly; + bool isAllowed = true; + for (auto& policy : m_policies) { +@@ -328,6 +332,8 @@ bool ContentSecurityPolicy::allPoliciesWithDispositionAllow(Disposition disposit + template + bool ContentSecurityPolicy::allPoliciesAllow(ViolatedDirectiveCallback&& callback, Predicate&& predicate, Args&&... args) const + { ++ if (InspectorInstrumentation::shouldBypassCSP(m_scriptExecutionContext)) ++ return true; + bool isAllowed = true; + for (auto& policy : m_policies) { + if (const ContentSecurityPolicyDirective* violatedDirective = (policy.get()->*predicate)(std::forward(args)...)) { +diff --git a/Source/WebCore/page/ios/FrameIOS.mm b/Source/WebCore/page/ios/FrameIOS.mm +index a49c131b46210e30c2a75a4b0339316f1115e13a..73054a67afe42cdb708ab0979e57a1024bb258de 100644 +--- a/Source/WebCore/page/ios/FrameIOS.mm ++++ b/Source/WebCore/page/ios/FrameIOS.mm +@@ -226,354 +226,6 @@ CGRect Frame::renderRectForPoint(CGPoint point, bool* isReplaced, float* fontSiz + return CGRectZero; + } + +-void Frame::betterApproximateNode(const IntPoint& testPoint, const NodeQualifier& nodeQualifierFunction, Node*& best, Node* failedNode, IntPoint& bestPoint, IntRect& bestRect, const IntRect& testRect) +-{ +- IntRect candidateRect; +- constexpr OptionSet hitType { HitTestRequest::ReadOnly, HitTestRequest::Active, HitTestRequest::DisallowUserAgentShadowContent, HitTestRequest::AllowVisibleChildFrameContentOnly }; +- auto* candidate = nodeQualifierFunction(eventHandler().hitTestResultAtPoint(testPoint, hitType), failedNode, &candidateRect); +- +- // Bail if we have no candidate, or the candidate is already equal to our current best node, +- // or our candidate is the avoidedNode and there is a current best node. +- if (!candidate || candidate == best) +- return; +- +- // The document should never be considered the best alternative. +- if (candidate->isDocumentNode()) +- return; +- +- if (best) { +- IntRect bestIntersect = intersection(testRect, bestRect); +- IntRect candidateIntersect = intersection(testRect, candidateRect); +- // if the candidate intersection is smaller than the current best intersection, bail. +- if (candidateIntersect.width() * candidateIntersect.height() <= bestIntersect.width() * bestIntersect.height()) +- return; +- } +- +- // At this point we either don't have a previous best, or our current candidate has a better intersection. +- best = candidate; +- bestPoint = testPoint; +- bestRect = candidateRect; +-} +- +-bool Frame::hitTestResultAtViewportLocation(const FloatPoint& viewportLocation, HitTestResult& hitTestResult, IntPoint& center) +-{ +- if (!m_doc || !m_doc->renderView()) +- return false; +- +- FrameView* view = m_view.get(); +- if (!view) +- return false; +- +- center = view->windowToContents(roundedIntPoint(viewportLocation)); +- constexpr OptionSet hitType { HitTestRequest::ReadOnly, HitTestRequest::Active, HitTestRequest::DisallowUserAgentShadowContent, HitTestRequest::AllowVisibleChildFrameContentOnly }; +- hitTestResult = eventHandler().hitTestResultAtPoint(center, hitType); +- return true; +-} +- +-Node* Frame::qualifyingNodeAtViewportLocation(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation, const NodeQualifier& nodeQualifierFunction, ShouldApproximate shouldApproximate, ShouldFindRootEditableElement shouldFindRootEditableElement) +-{ +- adjustedViewportLocation = viewportLocation; +- +- IntPoint testCenter; +- HitTestResult candidateInfo; +- if (!hitTestResultAtViewportLocation(viewportLocation, candidateInfo, testCenter)) +- return nullptr; +- +- IntPoint bestPoint = testCenter; +- +- // We have the candidate node at the location, check whether it or one of its ancestors passes +- // the qualifier function, which typically checks if the node responds to a particular event type. +- Node* approximateNode = nodeQualifierFunction(candidateInfo, 0, 0); +- +- if (shouldFindRootEditableElement == ShouldFindRootEditableElement::Yes && approximateNode && approximateNode->isContentEditable()) { +- // If we are in editable content, we look for the root editable element. +- approximateNode = approximateNode->rootEditableElement(); +- // If we have a focusable node, there is no need to approximate. +- if (approximateNode) +- shouldApproximate = ShouldApproximate::No; +- } +- +- float scale = page() ? page()->pageScaleFactor() : 1; +- float ppiFactor = screenPPIFactor(); +- +- static const float unscaledSearchRadius = 15; +- int searchRadius = static_cast(unscaledSearchRadius * ppiFactor / scale); +- +- if (approximateNode && shouldApproximate == ShouldApproximate::Yes) { +- const float testOffsets[] = { +- -.3f, -.3f, +- -.6f, -.6f, +- +.3f, +.3f, +- -.9f, -.9f, +- }; +- +- Node* originalApproximateNode = approximateNode; +- for (unsigned n = 0; n < WTF_ARRAY_LENGTH(testOffsets); n += 2) { +- IntSize testOffset(testOffsets[n] * searchRadius, testOffsets[n + 1] * searchRadius); +- IntPoint testPoint = testCenter + testOffset; +- +- constexpr OptionSet hitType { HitTestRequest::ReadOnly, HitTestRequest::Active, HitTestRequest::DisallowUserAgentShadowContent, HitTestRequest::AllowChildFrameContent }; +- auto candidateInfo = eventHandler().hitTestResultAtPoint(testPoint, hitType); +- Node* candidateNode = nodeQualifierFunction(candidateInfo, 0, 0); +- if (candidateNode && candidateNode->isDescendantOf(originalApproximateNode)) { +- approximateNode = candidateNode; +- bestPoint = testPoint; +- break; +- } +- } +- } else if (!approximateNode && shouldApproximate == ShouldApproximate::Yes) { +- // Grab the closest parent element of our failed candidate node. +- Node* candidate = candidateInfo.innerNode(); +- Node* failedNode = candidate; +- +- while (candidate && !candidate->isElementNode()) +- candidate = candidate->parentInComposedTree(); +- +- if (candidate) +- failedNode = candidate; +- +- // The center point was tested earlier. +- const float testOffsets[] = { +- -.3f, -.3f, +- +.3f, -.3f, +- -.3f, +.3f, +- +.3f, +.3f, +- -.6f, -.6f, +- +.6f, -.6f, +- -.6f, +.6f, +- +.6f, +.6f, +- -1.f, 0, +- +1.f, 0, +- 0, +1.f, +- 0, -1.f, +- }; +- IntRect bestFrame; +- IntRect testRect(testCenter, IntSize()); +- testRect.inflate(searchRadius); +- int currentTestRadius = 0; +- for (unsigned n = 0; n < WTF_ARRAY_LENGTH(testOffsets); n += 2) { +- IntSize testOffset(testOffsets[n] * searchRadius, testOffsets[n + 1] * searchRadius); +- IntPoint testPoint = testCenter + testOffset; +- int testRadius = std::max(abs(testOffset.width()), abs(testOffset.height())); +- if (testRadius > currentTestRadius) { +- // Bail out with the best match within a radius +- currentTestRadius = testRadius; +- if (approximateNode) +- break; +- } +- betterApproximateNode(testPoint, nodeQualifierFunction, approximateNode, failedNode, bestPoint, bestFrame, testRect); +- } +- } +- +- if (approximateNode) { +- IntPoint p = m_view->contentsToWindow(bestPoint); +- adjustedViewportLocation = p; +- if (shouldFindRootEditableElement == ShouldFindRootEditableElement::Yes && approximateNode->isContentEditable()) { +- // When in editable content, look for the root editable node again, +- // since this could be the node found with the approximation. +- approximateNode = approximateNode->rootEditableElement(); +- } +- } +- +- return approximateNode; +-} +- +-Node* Frame::deepestNodeAtLocation(const FloatPoint& viewportLocation) +-{ +- IntPoint center; +- HitTestResult hitTestResult; +- if (!hitTestResultAtViewportLocation(viewportLocation, hitTestResult, center)) +- return nullptr; +- +- return hitTestResult.innerNode(); +-} +- +-static bool nodeIsMouseFocusable(Node& node) +-{ +- if (!is(node)) +- return false; +- +- auto& element = downcast(node); +- if (element.isMouseFocusable()) +- return true; +- +- if (auto shadowRoot = makeRefPtr(element.shadowRoot())) { +- if (shadowRoot->delegatesFocus()) { +- for (auto& node : composedTreeDescendants(element)) { +- if (is(node) && downcast(node).isMouseFocusable()) +- return true; +- } +- } +- } +- +- return false; +-} +- +-static bool nodeWillRespondToMouseEvents(Node& node) +-{ +- return node.willRespondToMouseClickEvents() || node.willRespondToMouseMoveEvents() || nodeIsMouseFocusable(node); +-} +- +-Node* Frame::approximateNodeAtViewportLocationLegacy(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation) +-{ +- // This function is only used for UIWebView. +- auto&& ancestorRespondingToClickEvents = [](const HitTestResult& hitTestResult, Node* terminationNode, IntRect* nodeBounds) -> Node* { +- bool bodyHasBeenReached = false; +- bool pointerCursorStillValid = true; +- +- if (nodeBounds) +- *nodeBounds = IntRect(); +- +- auto node = hitTestResult.innerNode(); +- if (!node) +- return nullptr; +- +- Node* pointerCursorNode = nullptr; +- for (; node && node != terminationNode; node = node->parentInComposedTree()) { +- // We only accept pointer nodes before reaching the body tag. +- if (node->hasTagName(HTMLNames::bodyTag)) { +- // Make sure we cover the case of an empty editable body. +- if (!pointerCursorNode && node->isContentEditable()) +- pointerCursorNode = node; +- bodyHasBeenReached = true; +- pointerCursorStillValid = false; +- } +- +- // If we already have a pointer, and we reach a table, don't accept it. +- if (pointerCursorNode && (node->hasTagName(HTMLNames::tableTag) || node->hasTagName(HTMLNames::tbodyTag))) +- pointerCursorStillValid = false; +- +- // If we haven't reached the body, and we are still paying attention to pointer cursors, and the node has a pointer cursor. +- if (pointerCursorStillValid && node->renderStyle() && node->renderStyle()->cursor() == CursorType::Pointer) +- pointerCursorNode = node; +- else if (pointerCursorNode) { +- // We want the lowest unbroken chain of pointer cursors. +- pointerCursorStillValid = false; +- } +- +- if (nodeWillRespondToMouseEvents(*node)) { +- // If we're at the body or higher, use the pointer cursor node (which may be null). +- if (bodyHasBeenReached) +- node = pointerCursorNode; +- +- // If we are interested about the frame, use it. +- if (nodeBounds) { +- // This is a check to see whether this node is an area element. The only way this can happen is if this is the first check. +- if (node == hitTestResult.innerNode() && node != hitTestResult.innerNonSharedNode() && is(*node)) +- *nodeBounds = snappedIntRect(downcast(*node).computeRect(hitTestResult.innerNonSharedNode()->renderer())); +- else if (node && node->renderer()) +- *nodeBounds = node->renderer()->absoluteBoundingBoxRect(true); +- } +- +- return node; +- } +- } +- +- return nullptr; +- }; +- +- return qualifyingNodeAtViewportLocation(viewportLocation, adjustedViewportLocation, WTFMove(ancestorRespondingToClickEvents), ShouldApproximate::Yes); +-} +- +-static inline NodeQualifier ancestorRespondingToClickEventsNodeQualifier(SecurityOrigin* securityOrigin = nullptr) +-{ +- return [securityOrigin](const HitTestResult& hitTestResult, Node* terminationNode, IntRect* nodeBounds) -> Node* { +- if (nodeBounds) +- *nodeBounds = IntRect(); +- +- auto node = hitTestResult.innerNode(); +- if (!node || (securityOrigin && !securityOrigin->isSameOriginAs(node->document().securityOrigin()))) +- return nullptr; +- +- for (; node && node != terminationNode; node = node->parentInComposedTree()) { +- if (nodeWillRespondToMouseEvents(*node)) { +- // If we are interested about the frame, use it. +- if (nodeBounds) { +- // This is a check to see whether this node is an area element. The only way this can happen is if this is the first check. +- if (node == hitTestResult.innerNode() && node != hitTestResult.innerNonSharedNode() && is(*node)) +- *nodeBounds = snappedIntRect(downcast(*node).computeRect(hitTestResult.innerNonSharedNode()->renderer())); +- else if (node && node->renderer()) +- *nodeBounds = node->renderer()->absoluteBoundingBoxRect(true); +- } +- +- return node; +- } +- } +- +- return nullptr; +- }; +-} +- +-Node* Frame::nodeRespondingToClickEvents(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation, SecurityOrigin* securityOrigin) +-{ +- return qualifyingNodeAtViewportLocation(viewportLocation, adjustedViewportLocation, ancestorRespondingToClickEventsNodeQualifier(securityOrigin), ShouldApproximate::Yes); +-} +- +-Node* Frame::nodeRespondingToDoubleClickEvent(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation) +-{ +- auto&& ancestorRespondingToDoubleClickEvent = [](const HitTestResult& hitTestResult, Node* terminationNode, IntRect* nodeBounds) -> Node* { +- if (nodeBounds) +- *nodeBounds = IntRect(); +- +- auto* node = hitTestResult.innerNode(); +- if (!node) +- return nullptr; +- +- for (; node && node != terminationNode; node = node->parentInComposedTree()) { +- if (!node->hasEventListeners(eventNames().dblclickEvent)) +- continue; +-#if ENABLE(TOUCH_EVENTS) +- if (!node->allowsDoubleTapGesture()) +- continue; +-#endif +- if (nodeBounds && node->renderer()) +- *nodeBounds = node->renderer()->absoluteBoundingBoxRect(true); +- return node; +- } +- return nullptr; +- }; +- +- return qualifyingNodeAtViewportLocation(viewportLocation, adjustedViewportLocation, WTFMove(ancestorRespondingToDoubleClickEvent), ShouldApproximate::Yes); +-} +- +-Node* Frame::nodeRespondingToInteraction(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation) +-{ +- return qualifyingNodeAtViewportLocation(viewportLocation, adjustedViewportLocation, ancestorRespondingToClickEventsNodeQualifier(), ShouldApproximate::Yes, ShouldFindRootEditableElement::No); +-} +- +-Node* Frame::nodeRespondingToScrollWheelEvents(const FloatPoint& viewportLocation) +-{ +- auto&& ancestorRespondingToScrollWheelEvents = [](const HitTestResult& hitTestResult, Node* terminationNode, IntRect* nodeBounds) -> Node* { +- if (nodeBounds) +- *nodeBounds = IntRect(); +- +- Node* scrollingAncestor = nullptr; +- for (Node* node = hitTestResult.innerNode(); node && node != terminationNode && !node->hasTagName(HTMLNames::bodyTag); node = node->parentNode()) { +- RenderObject* renderer = node->renderer(); +- if (!renderer) +- continue; +- +- if ((renderer->isTextField() || renderer->isTextArea()) && downcast(*renderer).canScroll()) { +- scrollingAncestor = node; +- continue; +- } +- +- auto& style = renderer->style(); +- +- if (renderer->hasOverflowClip() +- && (style.overflowY() == Overflow::Auto || style.overflowY() == Overflow::Scroll +- || style.overflowX() == Overflow::Auto || style.overflowX() == Overflow::Scroll)) { +- scrollingAncestor = node; +- } +- } +- +- return scrollingAncestor; +- }; +- +- FloatPoint adjustedViewportLocation; +- return qualifyingNodeAtViewportLocation(viewportLocation, adjustedViewportLocation, WTFMove(ancestorRespondingToScrollWheelEvents), ShouldApproximate::No); +-} +- + int Frame::preferredHeight() const + { + Document* document = this->document(); +diff --git a/Source/WebCore/page/wpe/DragControllerWPE.cpp b/Source/WebCore/page/wpe/DragControllerWPE.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..e86e4295101a0a3e9be64681a84eb16b8bfe49d8 +--- /dev/null ++++ b/Source/WebCore/page/wpe/DragControllerWPE.cpp +@@ -0,0 +1,79 @@ ++/* ++ * Copyright (C) 2007-20 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 "DragController.h" ++ ++#include "DataTransfer.h" ++#include "Document.h" ++#include "DragData.h" ++#include "Editor.h" ++#include "Element.h" ++#include "Frame.h" ++#include "Pasteboard.h" ++#include "markup.h" ++ ++namespace WebCore { ++ ++// FIXME: These values are straight out of DragControllerMac, so probably have ++// little correlation with Gdk standards... ++const int DragController::MaxOriginalImageArea = 1500 * 1500; ++const int DragController::DragIconRightInset = 7; ++const int DragController::DragIconBottomInset = 3; ++ ++const float DragController::DragImageAlpha = 0.75f; ++ ++bool DragController::isCopyKeyDown(const DragData& dragData) ++{ ++ return dragData.flags().contains(DragApplicationFlags::IsCopyKeyDown); ++} ++ ++Optional DragController::dragOperation(const DragData& dragData) ++{ ++ // FIXME: This logic is incomplete ++ if (dragData.containsURL()) ++ return DragOperation::Copy; ++ ++ return WTF::nullopt; ++} ++ ++const IntSize& DragController::maxDragImageSize() ++{ ++ static const IntSize maxDragImageSize(200, 200); ++ return maxDragImageSize; ++} ++ ++void DragController::cleanupAfterSystemDrag() ++{ ++} ++ ++void DragController::declareAndWriteDragImage(DataTransfer& dataTransfer, Element& element, const URL& url, const String& label) ++{ ++ Frame* frame = element.document().frame(); ++ ASSERT(frame); ++ frame->editor().writeImageToPasteboard(dataTransfer.pasteboard(), element, url, label); ++} ++ ++} +diff --git a/Source/WebCore/platform/Cairo.cmake b/Source/WebCore/platform/Cairo.cmake +index c1b53605713774dc006d028eda7c6a8213d6cca1..9135e67fa835ab3462b8898a9a75c9f5359eab92 100644 +--- a/Source/WebCore/platform/Cairo.cmake ++++ b/Source/WebCore/platform/Cairo.cmake +@@ -16,6 +16,7 @@ list(APPEND WebCore_PRIVATE_FRAMEWORK_HEADERS + platform/graphics/cairo/ImageBufferCairoBackend.h + platform/graphics/cairo/ImageBufferCairoImageSurfaceBackend.h + platform/graphics/cairo/ImageBufferCairoSurfaceBackend.h ++ platform/graphics/cairo/ImageBufferUtilitiesCairo.h + platform/graphics/cairo/PlatformContextCairo.h + platform/graphics/cairo/RefPtrCairo.h + ) +diff --git a/Source/WebCore/platform/DragData.h b/Source/WebCore/platform/DragData.h +index ce0dff2cfaf3b5cf55070eb991bd5db1f2c8e1f7..cb3df549cb15f95140d46082c9e706c0158d575a 100644 +--- a/Source/WebCore/platform/DragData.h ++++ b/Source/WebCore/platform/DragData.h +@@ -48,7 +48,7 @@ typedef void* DragDataRef; + + #elif PLATFORM(WIN) + typedef struct IDataObject* DragDataRef; +-#elif PLATFORM(GTK) ++#elif PLATFORM(GTK) || PLATFORM(WPE) + namespace WebCore { + class SelectionData; + } +diff --git a/Source/WebCore/platform/DragImage.cpp b/Source/WebCore/platform/DragImage.cpp +index 1939fb90c22564d02cadf65bdaf7f65ccb7ce9a7..f6a73e6ac480ed0d9b964617d6aa62f364bc391a 100644 +--- a/Source/WebCore/platform/DragImage.cpp ++++ b/Source/WebCore/platform/DragImage.cpp +@@ -274,7 +274,7 @@ DragImage::~DragImage() + deleteDragImage(m_dragImageRef); + } + +-#if !PLATFORM(COCOA) && !PLATFORM(GTK) && !PLATFORM(WIN) ++#if !PLATFORM(COCOA) && !PLATFORM(GTK) && !PLATFORM(WIN) && !PLATFORM(WPE) + + IntSize dragImageSize(DragImageRef) + { +diff --git a/Source/WebCore/platform/Pasteboard.h b/Source/WebCore/platform/Pasteboard.h +index af54715d8ac8e6f87c41bfafe7fab2ff63648d97..819b43372068ae385381fad264bf72fa10459732 100644 +--- a/Source/WebCore/platform/Pasteboard.h ++++ b/Source/WebCore/platform/Pasteboard.h +@@ -44,7 +44,7 @@ OBJC_CLASS NSString; + OBJC_CLASS NSArray; + #endif + +-#if PLATFORM(GTK) ++#if PLATFORM(GTK) || PLATFORM(WPE) + #include "SelectionData.h" + #endif + +@@ -91,16 +91,12 @@ struct PasteboardWebContent { + Vector clientTypes; + Vector> clientData; + #endif +-#if PLATFORM(GTK) ++#if PLATFORM(GTK) || PLATFORM(WPE) + String contentOrigin; + bool canSmartCopyOrDelete; + String text; + String markup; + #endif +-#if USE(LIBWPE) +- String text; +- String markup; +-#endif + }; + + struct PasteboardURL { +@@ -109,7 +105,7 @@ struct PasteboardURL { + #if PLATFORM(MAC) + String userVisibleForm; + #endif +-#if PLATFORM(GTK) ++#if PLATFORM(GTK) || PLATFORM(WPE) + String markup; + #endif + }; +@@ -188,6 +184,11 @@ public: + #endif + #endif + ++#if PLATFORM(WPE) && ENABLE(DRAG_SUPPORT) ++ explicit Pasteboard(std::unique_ptr&&, SelectionData&); ++ explicit Pasteboard(std::unique_ptr&&, SelectionData&&); ++#endif ++ + #if PLATFORM(WIN) + explicit Pasteboard(std::unique_ptr&&, IDataObject*); + explicit Pasteboard(std::unique_ptr&&, WCDataObject*); +@@ -253,6 +254,12 @@ public: + static std::unique_ptr createForGlobalSelection(std::unique_ptr&&); + #endif + ++#if PLATFORM(WPE) ++ const SelectionData& selectionData() const { ++ return *m_selectionData; ++ } ++#endif ++ + #if PLATFORM(IOS_FAMILY) + explicit Pasteboard(std::unique_ptr&&, int64_t changeCount); + explicit Pasteboard(std::unique_ptr&&, const String& pasteboardName); +@@ -287,6 +294,7 @@ public: + COMPtr dataObject() const { return m_dataObject; } + void setExternalDataObject(IDataObject*); + const DragDataMap& dragDataMap() const { return m_dragDataMap; } ++ WEBCORE_EXPORT DragDataMap createDragDataMap(); + void writeURLToWritableDataObject(const URL&, const String&); + COMPtr writableDataObject() const { return m_writableDataObject; } + void writeImageToDataObject(Element&, const URL&); // FIXME: Layering violation. +@@ -338,6 +346,10 @@ private: + String m_name; + #endif + ++#if PLATFORM(WPE) ++ Optional m_selectionData; ++#endif ++ + #if PLATFORM(COCOA) + String m_pasteboardName; + int64_t m_changeCount; +@@ -353,6 +365,7 @@ private: + COMPtr m_dataObject; + COMPtr m_writableDataObject; + DragDataMap m_dragDataMap; ++ bool m_forDrag = false; + #endif + }; + +diff --git a/Source/WebCore/platform/PlatformKeyboardEvent.h b/Source/WebCore/platform/PlatformKeyboardEvent.h +index 1a1367f7a9df0ab1ace16d0365e55f6538d0cbd6..e24d748074295cc68f2eb89fb21adccc1acad149 100644 +--- a/Source/WebCore/platform/PlatformKeyboardEvent.h ++++ b/Source/WebCore/platform/PlatformKeyboardEvent.h +@@ -134,6 +134,7 @@ namespace WebCore { + static String keyCodeForHardwareKeyCode(unsigned); + static String keyIdentifierForGdkKeyCode(unsigned); + static int windowsKeyCodeForGdkKeyCode(unsigned); ++ static unsigned gdkKeyCodeForWindowsKeyCode(int); + static String singleCharacterString(unsigned); + static bool modifiersContainCapsLock(unsigned); + #endif +@@ -143,6 +144,7 @@ namespace WebCore { + static String keyCodeForHardwareKeyCode(unsigned); + static String keyIdentifierForWPEKeyCode(unsigned); + static int windowsKeyCodeForWPEKeyCode(unsigned); ++ static unsigned WPEKeyCodeForWindowsKeyCode(int); + static String singleCharacterString(unsigned); + #endif + +diff --git a/Source/WebCore/platform/PlatformScreen.cpp b/Source/WebCore/platform/PlatformScreen.cpp +index ba50b688ab6d0bae5d199fa0bac4b7e2004baf81..0b83a798b00835635a95a0db22173de094ba4035 100644 +--- a/Source/WebCore/platform/PlatformScreen.cpp ++++ b/Source/WebCore/platform/PlatformScreen.cpp +@@ -25,6 +25,7 @@ + + #include "config.h" + #include "PlatformScreen.h" ++#include "RuntimeEnabledFeatures.h" + + #if PLATFORM(COCOA) + +@@ -72,3 +73,16 @@ const ScreenData* screenData(PlatformDisplayID screenDisplayID) + } // namespace WebCore + + #endif // PLATFORM(COCOA) ++ ++#if ENABLE(TOUCH_EVENTS) ++namespace WebCore { ++ ++bool screenHasTouchDevice() { ++ return RuntimeEnabledFeatures::sharedFeatures().touchEventsEnabled(); ++} ++bool screenIsTouchPrimaryInputDevice() { ++ return RuntimeEnabledFeatures::sharedFeatures().isTouchPrimaryInputDevice(); ++} ++ ++} // namespace WebCore ++#endif +diff --git a/Source/WebCore/platform/PlatformScreen.h b/Source/WebCore/platform/PlatformScreen.h +index 4a4f6c72b54a2e6c5462aa4366b71b67d82e3582..9b15f8992bc32892e24e27025870c09b223ce0a1 100644 +--- a/Source/WebCore/platform/PlatformScreen.h ++++ b/Source/WebCore/platform/PlatformScreen.h +@@ -151,12 +151,14 @@ WEBCORE_EXPORT float screenScaleFactor(UIScreen * = nullptr); + #endif + + #if ENABLE(TOUCH_EVENTS) +-#if PLATFORM(GTK) || PLATFORM(WPE) + WEBCORE_EXPORT bool screenHasTouchDevice(); + WEBCORE_EXPORT bool screenIsTouchPrimaryInputDevice(); ++#if PLATFORM(GTK) || PLATFORM(WPE) ++bool platformScreenHasTouchDevice(); ++bool platformScreenIsTouchPrimaryInputDevice(); + #else +-constexpr bool screenHasTouchDevice() { return true; } +-constexpr bool screenIsTouchPrimaryInputDevice() { return true; } ++constexpr bool platformScreenHasTouchDevice() { return true; } ++constexpr bool platformScreenIsTouchPrimaryInputDevice() { return true; } + #endif + #endif + +diff --git a/Source/WebCore/platform/ScrollableArea.h b/Source/WebCore/platform/ScrollableArea.h +index 1e9a2d3797edf60debb454066363a94971863dd5..9d839e3eefca3381e0156323a289fff2c17c645b 100644 +--- a/Source/WebCore/platform/ScrollableArea.h ++++ b/Source/WebCore/platform/ScrollableArea.h +@@ -105,7 +105,7 @@ public: + void updateScrollSnapState(); + + #if ENABLE(TOUCH_EVENTS) +- virtual bool handleTouchEvent(const PlatformTouchEvent&); ++ WEBCORE_EXPORT virtual bool handleTouchEvent(const PlatformTouchEvent&); + #endif + + #if PLATFORM(IOS_FAMILY) +diff --git a/Source/WebCore/platform/graphics/FontCascade.h b/Source/WebCore/platform/graphics/FontCascade.h +index 66b6f13ad3302d62dbc95023038dbf46e28c1920..10c937dd32b01fd88e0fedf7b2b87b29d7217726 100644 +--- a/Source/WebCore/platform/graphics/FontCascade.h ++++ b/Source/WebCore/platform/graphics/FontCascade.h +@@ -284,7 +284,8 @@ private: + return true; + if (textRenderingMode == TextRenderingMode::OptimizeSpeed) + return false; +-#if PLATFORM(COCOA) || USE(FREETYPE) ++ // WIN: quick fix for https://bugs.webkit.org/show_bug.cgi?id=201213 ++#if PLATFORM(COCOA) || USE(FREETYPE) || PLATFORM(WIN) + return true; + #else + return false; +diff --git a/Source/WebCore/platform/graphics/cairo/ImageBufferUtilitiesCairo.cpp b/Source/WebCore/platform/graphics/cairo/ImageBufferUtilitiesCairo.cpp +index d79728555b7db9b59cb615c55a7a7a6851cb57c8..61d3cc4b488e35ef9e1afa1ce3ac5f5d60ebe9a7 100644 +--- a/Source/WebCore/platform/graphics/cairo/ImageBufferUtilitiesCairo.cpp ++++ b/Source/WebCore/platform/graphics/cairo/ImageBufferUtilitiesCairo.cpp +@@ -48,6 +48,13 @@ + #include + #endif + ++#if PLATFORM(WPE) || PLATFORM(WIN) ++#include // Needed by jpeglib.h for FILE. ++extern "C" { ++#include "jpeglib.h" ++} ++#endif ++ + namespace WebCore { + + #if !PLATFORM(GTK) +@@ -65,8 +72,75 @@ static bool encodeImage(cairo_surface_t* image, const String& mimeType, Vector data(cairo_surface_t* image, const String& mimeType, Optional) ++static Vector encodeJpeg(cairo_surface_t* image, int quality) ++{ ++ if (cairo_surface_get_type(image) != CAIRO_SURFACE_TYPE_IMAGE) { ++ fprintf(stderr, "Unexpected cairo surface type: %d\n", cairo_surface_get_type(image)); ++ return { }; ++ } ++ ++ if (cairo_image_surface_get_format(image) != CAIRO_FORMAT_ARGB32) { ++ fprintf(stderr, "Unexpected surface image format: %d\n", cairo_image_surface_get_format(image)); ++ return { }; ++ } ++ ++ struct jpeg_compress_struct info; ++ struct jpeg_error_mgr error; ++ info.err = jpeg_std_error(&error); ++ jpeg_create_compress(&info); ++ ++ unsigned char* bufferPtr = nullptr; ++ unsigned long bufferSize; ++ jpeg_mem_dest(&info, &bufferPtr, &bufferSize); ++ info.image_width = cairo_image_surface_get_width(image); ++ info.image_height = cairo_image_surface_get_height(image); ++ ++#ifndef LIBJPEG_TURBO_VERSION ++ COMPILE_ASSERT(false, only_libjpeg_turbo_is_supported); ++#endif ++ ++#if CPU(LITTLE_ENDIAN) ++ info.in_color_space = JCS_EXT_BGRA; ++#else ++ info.in_color_space = JCS_EXT_ARGB; ++#endif ++ // # of color components in input image ++ info.input_components = 4; ++ ++ jpeg_set_defaults(&info); ++ jpeg_set_quality(&info, quality, true); ++ ++ jpeg_start_compress(&info, true); ++ ++ while (info.next_scanline < info.image_height) ++ { ++ JSAMPROW row = cairo_image_surface_get_data(image) + (info.next_scanline * cairo_image_surface_get_stride(image)); ++ if (jpeg_write_scanlines(&info, &row, 1) != 1) { ++ fprintf(stderr, "JPEG library failed to encode line\n"); ++ break; ++ } ++ } ++ ++ jpeg_finish_compress(&info); ++ jpeg_destroy_compress(&info); ++ ++ Vector output; ++ output.append(bufferPtr, bufferSize); ++ // Cannot use unique_ptr as bufferPtr changes during compression. GUniquePtr would work ++ // but it's under GLib and won't work on Windows. ++ free(bufferPtr); ++ return output; ++} ++ ++Vector data(cairo_surface_t* image, const String& mimeType, Optional quality) + { ++ if (mimeType == "image/jpeg") { ++ int qualityPercent = 100; ++ if (quality) ++ qualityPercent = static_cast(*quality * 100.0 + 0.5); ++ return encodeJpeg(image, qualityPercent); ++ } ++ + Vector encodedImage; + if (!image || !encodeImage(image, mimeType, &encodedImage)) + return { }; +diff --git a/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h b/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h +index bc87758878d5163a938af8242c7a6800ea9bd13c..3d0751f8dfe1124bbe054daa2fa0c7552fecab32 100644 +--- a/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h ++++ b/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h +@@ -42,7 +42,7 @@ WEBCORE_EXPORT uint8_t verifyImageBufferIsBigEnough(const void* buffer, size_t b + CFStringRef jpegUTI(); + RetainPtr utiFromImageBufferMIMEType(const String&); + +-bool encodeImage(CGImageRef, CFStringRef uti, Optional quality, CFMutableDataRef); ++WEBCORE_EXPORT bool encodeImage(CGImageRef, CFStringRef uti, Optional quality, CFMutableDataRef); + + String dataURL(CFDataRef, const String& mimeType); + String dataURL(const ImageData&, const String& mimeType, Optional quality); +diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLBase.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLBase.cpp +index a562e8af27bdb6259c2efceb804efe38ff9d61f1..6ab9f3464d6af127d3727f00bd88f6fe3273719d 100644 +--- a/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLBase.cpp ++++ b/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGLBase.cpp +@@ -27,7 +27,7 @@ + #include "config.h" + #include "GraphicsContextGLOpenGL.h" + +-#if ENABLE(WEBGL) && USE(OPENGL) ++#if !PLATFORM(WIN) && ENABLE(WEBGL) && USE(OPENGL) + + #include "ExtensionsGLOpenGL.h" + #include "ImageData.h" +diff --git a/Source/WebCore/platform/graphics/win/ComplexTextControllerUniscribe.cpp b/Source/WebCore/platform/graphics/win/ComplexTextControllerUniscribe.cpp +index 774a52a28693bc51dde10a0875ea379afb06fd3c..cd714a7298fe4f5d2c9b580697a5c4cd22d25870 100644 +--- a/Source/WebCore/platform/graphics/win/ComplexTextControllerUniscribe.cpp ++++ b/Source/WebCore/platform/graphics/win/ComplexTextControllerUniscribe.cpp +@@ -172,6 +172,33 @@ static Vector stringIndicesFromClusters(const Vector& clusters, + return stringIndices; + } + ++static int compactScriptItemsIfNeeded(const UChar* cp, unsigned stringLength, Vector& items, int numItems, const Font* font) ++{ ++ // https://bugs.webkit.org/show_bug.cgi?id=201214 ++ // Uniscribe is overly aggressive in separating the runs. It'll split "3d_rotation" into "3", "d", "_" and "rotation" and we ++ // will ScriptShape them separately. As a result, a ligature for "3d_rotation" in the Material icon set ++ // (https://www.materialui.co/icon/3d-rotation) will not be used. A quick and dirty hack is to glue them back here, only making ++ // this apply to the readable characters, digits and _. ++ ++ if (!numItems) ++ return numItems; ++ ++ if (font->platformData().isSystemFont() || font->platformData().hasVariations()) ++ return numItems; ++ ++ bool allGoodCharacters = true; ++ for (unsigned i = 0; allGoodCharacters && i < stringLength; ++i) { ++ const UChar c = cp[i]; ++ allGoodCharacters = (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_'; ++ } ++ if (!allGoodCharacters) ++ return numItems; ++ ++ // Consume entire string into a single run. |items| is at least numItems + 1 long. ++ items[1] = items[numItems]; ++ return 1; ++} ++ + void ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp, unsigned stringLength, unsigned stringLocation, const Font* font) + { + if (!font) { +@@ -201,6 +228,8 @@ void ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp, + } + items.resize(numItems + 1); + ++ numItems = compactScriptItemsIfNeeded(cp, stringLength, items, numItems, font); ++ + for (int i = 0; i < numItems; i++) { + // Determine the string for this item. + const UChar* str = cp + items[i].iCharPos; +diff --git a/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp b/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp +index 0516e70973e0078de6ad0216375d34dd9ef51a8d..ffd9a02deb5518e0c8c77b156815c11eb4b16829 100644 +--- a/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp ++++ b/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp +@@ -37,8 +37,10 @@ + #include "WindowsKeyboardCodes.h" + #include + #include ++#include + #include + #include ++#include + + namespace WebCore { + +@@ -1294,6 +1296,246 @@ int PlatformKeyboardEvent::windowsKeyCodeForGdkKeyCode(unsigned keycode) + + } + ++static const HashMap& gdkToWindowsKeyCodeMap() ++{ ++ static HashMap* result; ++ static std::once_flag once; ++ std::call_once( ++ once, ++ [] { ++ const unsigned gdkKeyCodes[] = { ++ GDK_KEY_Cancel, ++ // FIXME: non-keypad keys should take precedence, so we skip GDK_KEY_KP_* ++ // GDK_KEY_KP_0, ++ // GDK_KEY_KP_1, ++ // GDK_KEY_KP_2, ++ // GDK_KEY_KP_3, ++ // GDK_KEY_KP_4, ++ // GDK_KEY_KP_5, ++ // GDK_KEY_KP_6, ++ // GDK_KEY_KP_7, ++ // GDK_KEY_KP_8, ++ // GDK_KEY_KP_9, ++ // GDK_KEY_KP_Multiply, ++ // GDK_KEY_KP_Add, ++ // GDK_KEY_KP_Subtract, ++ // GDK_KEY_KP_Decimal, ++ // GDK_KEY_KP_Divide, ++ // GDK_KEY_KP_Page_Up, ++ // GDK_KEY_KP_Page_Down, ++ // GDK_KEY_KP_End, ++ // GDK_KEY_KP_Home, ++ // GDK_KEY_KP_Left, ++ // GDK_KEY_KP_Up, ++ // GDK_KEY_KP_Right, ++ // GDK_KEY_KP_Down, ++ GDK_KEY_BackSpace, ++ // GDK_KEY_ISO_Left_Tab, ++ // GDK_KEY_3270_BackTab, ++ GDK_KEY_Tab, ++ GDK_KEY_Clear, ++ // GDK_KEY_ISO_Enter, ++ // GDK_KEY_KP_Enter, ++ GDK_KEY_Return, ++ GDK_KEY_Menu, ++ GDK_KEY_Pause, ++ GDK_KEY_AudioPause, ++ GDK_KEY_Caps_Lock, ++ GDK_KEY_Kana_Lock, ++ GDK_KEY_Kana_Shift, ++ GDK_KEY_Hangul, ++ GDK_KEY_Hangul_Hanja, ++ GDK_KEY_Kanji, ++ GDK_KEY_Escape, ++ GDK_KEY_space, ++ GDK_KEY_Page_Up, ++ GDK_KEY_Page_Down, ++ GDK_KEY_End, ++ GDK_KEY_Home, ++ GDK_KEY_Left, ++ GDK_KEY_Up, ++ GDK_KEY_Right, ++ GDK_KEY_Down, ++ GDK_KEY_Select, ++ GDK_KEY_Print, ++ GDK_KEY_Execute, ++ GDK_KEY_Insert, ++ GDK_KEY_KP_Insert, ++ GDK_KEY_Delete, ++ GDK_KEY_KP_Delete, ++ GDK_KEY_Help, ++ GDK_KEY_0, ++ GDK_KEY_parenright, ++ GDK_KEY_1, ++ GDK_KEY_exclam, ++ GDK_KEY_2, ++ GDK_KEY_at, ++ GDK_KEY_3, ++ GDK_KEY_numbersign, ++ GDK_KEY_4, ++ GDK_KEY_dollar, ++ GDK_KEY_5, ++ GDK_KEY_percent, ++ GDK_KEY_6, ++ GDK_KEY_asciicircum, ++ GDK_KEY_7, ++ GDK_KEY_ampersand, ++ GDK_KEY_8, ++ GDK_KEY_asterisk, ++ GDK_KEY_9, ++ GDK_KEY_parenleft, ++ GDK_KEY_a, ++ GDK_KEY_A, ++ GDK_KEY_b, ++ GDK_KEY_B, ++ GDK_KEY_c, ++ GDK_KEY_C, ++ GDK_KEY_d, ++ GDK_KEY_D, ++ GDK_KEY_e, ++ GDK_KEY_E, ++ GDK_KEY_f, ++ GDK_KEY_F, ++ GDK_KEY_g, ++ GDK_KEY_G, ++ GDK_KEY_h, ++ GDK_KEY_H, ++ GDK_KEY_i, ++ GDK_KEY_I, ++ GDK_KEY_j, ++ GDK_KEY_J, ++ GDK_KEY_k, ++ GDK_KEY_K, ++ GDK_KEY_l, ++ GDK_KEY_L, ++ GDK_KEY_m, ++ GDK_KEY_M, ++ GDK_KEY_n, ++ GDK_KEY_N, ++ GDK_KEY_o, ++ GDK_KEY_O, ++ GDK_KEY_p, ++ GDK_KEY_P, ++ GDK_KEY_q, ++ GDK_KEY_Q, ++ GDK_KEY_r, ++ GDK_KEY_R, ++ GDK_KEY_s, ++ GDK_KEY_S, ++ GDK_KEY_t, ++ GDK_KEY_T, ++ GDK_KEY_u, ++ GDK_KEY_U, ++ GDK_KEY_v, ++ GDK_KEY_V, ++ GDK_KEY_w, ++ GDK_KEY_W, ++ GDK_KEY_x, ++ GDK_KEY_X, ++ GDK_KEY_y, ++ GDK_KEY_Y, ++ GDK_KEY_z, ++ GDK_KEY_Z, ++ GDK_KEY_Meta_L, ++ GDK_KEY_Meta_R, ++ GDK_KEY_Sleep, ++ GDK_KEY_Num_Lock, ++ GDK_KEY_Scroll_Lock, ++ GDK_KEY_Shift_L, ++ GDK_KEY_Shift_R, ++ GDK_KEY_Control_L, ++ GDK_KEY_Control_R, ++ GDK_KEY_Alt_L, ++ GDK_KEY_Alt_R, ++ GDK_KEY_Back, ++ GDK_KEY_Forward, ++ GDK_KEY_Refresh, ++ GDK_KEY_Stop, ++ GDK_KEY_Search, ++ GDK_KEY_Favorites, ++ GDK_KEY_HomePage, ++ GDK_KEY_AudioMute, ++ GDK_KEY_AudioLowerVolume, ++ GDK_KEY_AudioRaiseVolume, ++ GDK_KEY_AudioNext, ++ GDK_KEY_AudioPrev, ++ GDK_KEY_AudioStop, ++ GDK_KEY_AudioMedia, ++ GDK_KEY_semicolon, ++ GDK_KEY_colon, ++ GDK_KEY_plus, ++ GDK_KEY_equal, ++ GDK_KEY_comma, ++ GDK_KEY_less, ++ GDK_KEY_minus, ++ GDK_KEY_underscore, ++ GDK_KEY_period, ++ GDK_KEY_greater, ++ GDK_KEY_slash, ++ GDK_KEY_question, ++ GDK_KEY_asciitilde, ++ GDK_KEY_quoteleft, ++ GDK_KEY_bracketleft, ++ GDK_KEY_braceleft, ++ GDK_KEY_backslash, ++ GDK_KEY_bar, ++ GDK_KEY_bracketright, ++ GDK_KEY_braceright, ++ GDK_KEY_quoteright, ++ GDK_KEY_quotedbl, ++ GDK_KEY_AudioRewind, ++ GDK_KEY_AudioForward, ++ GDK_KEY_AudioPlay, ++ GDK_KEY_F1, ++ GDK_KEY_F2, ++ GDK_KEY_F3, ++ GDK_KEY_F4, ++ GDK_KEY_F5, ++ GDK_KEY_F6, ++ GDK_KEY_F7, ++ GDK_KEY_F8, ++ GDK_KEY_F9, ++ GDK_KEY_F10, ++ GDK_KEY_F11, ++ GDK_KEY_F12, ++ GDK_KEY_F13, ++ GDK_KEY_F14, ++ GDK_KEY_F15, ++ GDK_KEY_F16, ++ GDK_KEY_F17, ++ GDK_KEY_F18, ++ GDK_KEY_F19, ++ GDK_KEY_F20, ++ GDK_KEY_F21, ++ GDK_KEY_F22, ++ GDK_KEY_F23, ++ GDK_KEY_F24, ++ GDK_KEY_VoidSymbol, ++ GDK_KEY_Red, ++ GDK_KEY_Green, ++ GDK_KEY_Yellow, ++ GDK_KEY_Blue, ++ GDK_KEY_PowerOff, ++ GDK_KEY_AudioRecord, ++ GDK_KEY_Display, ++ GDK_KEY_Subtitle, ++ GDK_KEY_Video ++ }; ++ result = new HashMap(); ++ for (unsigned gdkKeyCode : gdkKeyCodes) { ++ int winKeyCode = PlatformKeyboardEvent::windowsKeyCodeForGdkKeyCode(gdkKeyCode); ++ // If several gdk key codes map to the same win key code first one is used. ++ result->add(winKeyCode, gdkKeyCode); ++ } ++ }); ++ return *result; ++} ++ ++unsigned PlatformKeyboardEvent::gdkKeyCodeForWindowsKeyCode(int keycode) ++{ ++ return gdkToWindowsKeyCodeMap().get(keycode); ++} ++ + String PlatformKeyboardEvent::singleCharacterString(unsigned val) + { + switch (val) { +diff --git a/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp b/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp +index e0e8809d8f39614b2b6bb8c7cf0f02652d574fe7..5d05504ec57869c9d6c6562c4237640099c295cd 100644 +--- a/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp ++++ b/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp +@@ -218,7 +218,7 @@ bool screenSupportsExtendedColor(Widget*) + } + + #if ENABLE(TOUCH_EVENTS) +-bool screenHasTouchDevice() ++bool platformScreenHasTouchDevice() + { + auto* display = gdk_display_get_default(); + if (!display) +@@ -228,7 +228,7 @@ bool screenHasTouchDevice() + return seat ? gdk_seat_get_capabilities(seat) & GDK_SEAT_CAPABILITY_TOUCH : true; + } + +-bool screenIsTouchPrimaryInputDevice() ++bool platformScreenIsTouchPrimaryInputDevice() + { + auto* display = gdk_display_get_default(); + if (!display) +diff --git a/Source/WebCore/platform/libwpe/PasteboardLibWPE.cpp b/Source/WebCore/platform/libwpe/PasteboardLibWPE.cpp +index 59d3bc81471d3e7bca77cda22d7a05895a5a21b5..0c25426bc0a477786c367fe28ad6816a82437a33 100644 +--- a/Source/WebCore/platform/libwpe/PasteboardLibWPE.cpp ++++ b/Source/WebCore/platform/libwpe/PasteboardLibWPE.cpp +@@ -33,6 +33,10 @@ + #include "PlatformStrategies.h" + #include + ++#if ENABLE(DRAG_SUPPORT) ++#include "DragData.h" ++#endif ++ + namespace WebCore { + + std::unique_ptr Pasteboard::createForCopyAndPaste(std::unique_ptr&& context) +@@ -74,6 +78,16 @@ String Pasteboard::readOrigin() + + String Pasteboard::readString(const String& type) + { ++ if (m_selectionData) { ++ if (type == "text/plain") ++ return m_selectionData->text();; ++ if (type == "text/html") ++ return m_selectionData->markup(); ++ if (type == "Files" || type == "text/uri-list") ++ return m_selectionData->uriList(); ++ return { }; ++ } ++ + return platformStrategies()->pasteboardStrategy()->readStringFromPasteboard(0, type, name(), context()); + } + +@@ -85,6 +99,15 @@ String Pasteboard::readStringInCustomData(const String&) + + void Pasteboard::writeString(const String& type, const String& text) + { ++ if (m_selectionData) { ++ if (type == "Files" || type == "text/uri-list") ++ m_selectionData->setURIList(text); ++ else if (type == "text/html") ++ m_selectionData->setMarkup(text); ++ else if (type == "text/plain") ++ m_selectionData->setText(text); ++ return; ++ } + platformStrategies()->pasteboardStrategy()->writeToPasteboard(type, text); + } + +@@ -112,7 +135,12 @@ void Pasteboard::read(PasteboardFileReader&, Optional) + + void Pasteboard::write(const PasteboardURL& url) + { +- platformStrategies()->pasteboardStrategy()->writeToPasteboard("text/plain;charset=utf-8", url.url.string()); ++ if (m_selectionData) { ++ m_selectionData->clearAll(); ++ m_selectionData->setURL(url.url, url.title); ++ } else { ++ platformStrategies()->pasteboardStrategy()->writeToPasteboard("text/plain;charset=utf-8", url.url.string()); ++ } + } + + void Pasteboard::writeTrustworthyWebURLsPboardType(const PasteboardURL&) +@@ -120,13 +148,28 @@ void Pasteboard::writeTrustworthyWebURLsPboardType(const PasteboardURL&) + notImplemented(); + } + +-void Pasteboard::write(const PasteboardImage&) ++void Pasteboard::write(const PasteboardImage& pasteboardImage) + { ++ if (m_selectionData) { ++ m_selectionData->clearAll(); ++ if (!pasteboardImage.url.url.isEmpty()) { ++ m_selectionData->setURL(pasteboardImage.url.url, pasteboardImage.url.title); ++ m_selectionData->setMarkup(pasteboardImage.url.markup); ++ } ++ m_selectionData->setImage(pasteboardImage.image.get()); ++ } + } + + void Pasteboard::write(const PasteboardWebContent& content) + { +- platformStrategies()->pasteboardStrategy()->writeToPasteboard(content); ++ if (m_selectionData) { ++ m_selectionData->clearAll(); ++ m_selectionData->setText(content.text); ++ m_selectionData->setMarkup(content.markup); ++ m_selectionData->setCanSmartReplace(content.canSmartCopyOrDelete); ++ } else { ++ platformStrategies()->pasteboardStrategy()->writeToPasteboard(content); ++ } + } + + Pasteboard::FileContentState Pasteboard::fileContentState() +@@ -157,6 +200,35 @@ void Pasteboard::write(const Color&) + { + } + ++#if ENABLE(DRAG_SUPPORT) ++ ++Pasteboard::Pasteboard(std::unique_ptr&& context, SelectionData&& selectionData) ++ : m_context(WTFMove(context)) ++ , m_selectionData(WTFMove(selectionData)) ++{ ++} ++ ++Pasteboard::Pasteboard(std::unique_ptr&& context, SelectionData& selectionData) ++ : m_context(WTFMove(context)) ++ , m_selectionData(selectionData) ++{ ++} ++ ++std::unique_ptr Pasteboard::createForDragAndDrop(std::unique_ptr&& context) ++{ ++ return makeUnique(WTFMove(context), SelectionData()); ++} ++ ++std::unique_ptr Pasteboard::create(const DragData& dragData) ++{ ++ RELEASE_ASSERT(dragData.platformData()); ++ return makeUnique(dragData.createPasteboardContext(), *dragData.platformData()); ++} ++void Pasteboard::setDragImage(DragImage, const IntPoint&) ++{ ++} ++#endif ++ + } // namespace WebCore + + #endif // USE(LIBWPE) +diff --git a/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp b/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp +index a34dc220bbb9a92b40dfb463e8724e81ac745b2c..8ecedd5dae88469366a619b96960598c1232a32d 100644 +--- a/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp ++++ b/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp +@@ -30,8 +30,10 @@ + + #include "WindowsKeyboardCodes.h" + #include ++#include + #include + #include ++#include + + namespace WebCore { + +@@ -1291,6 +1293,246 @@ int PlatformKeyboardEvent::windowsKeyCodeForWPEKeyCode(unsigned keycode) + return 0; + } + ++static const HashMap& WPEToWindowsKeyCodeMap() ++{ ++ static HashMap* result; ++ static std::once_flag once; ++ std::call_once( ++ once, ++ [] { ++ const unsigned WPEKeyCodes[] = { ++ WPE_KEY_Cancel, ++ // FIXME: non-keypad keys should take precedence, so we skip WPE_KEY_KP_* ++ // WPE_KEY_KP_0, ++ // WPE_KEY_KP_1, ++ // WPE_KEY_KP_2, ++ // WPE_KEY_KP_3, ++ // WPE_KEY_KP_4, ++ // WPE_KEY_KP_5, ++ // WPE_KEY_KP_6, ++ // WPE_KEY_KP_7, ++ // WPE_KEY_KP_8, ++ // WPE_KEY_KP_9, ++ // WPE_KEY_KP_Multiply, ++ // WPE_KEY_KP_Add, ++ // WPE_KEY_KP_Subtract, ++ // WPE_KEY_KP_Decimal, ++ // WPE_KEY_KP_Divide, ++ // WPE_KEY_KP_Page_Up, ++ // WPE_KEY_KP_Page_Down, ++ // WPE_KEY_KP_End, ++ // WPE_KEY_KP_Home, ++ // WPE_KEY_KP_Left, ++ // WPE_KEY_KP_Up, ++ // WPE_KEY_KP_Right, ++ // WPE_KEY_KP_Down, ++ WPE_KEY_BackSpace, ++ // WPE_KEY_ISO_Left_Tab, ++ // WPE_KEY_3270_BackTab, ++ WPE_KEY_Tab, ++ WPE_KEY_Clear, ++ // WPE_KEY_ISO_Enter, ++ // WPE_KEY_KP_Enter, ++ WPE_KEY_Return, ++ WPE_KEY_Menu, ++ WPE_KEY_Pause, ++ WPE_KEY_AudioPause, ++ WPE_KEY_Caps_Lock, ++ WPE_KEY_Kana_Lock, ++ WPE_KEY_Kana_Shift, ++ WPE_KEY_Hangul, ++ WPE_KEY_Hangul_Hanja, ++ WPE_KEY_Kanji, ++ WPE_KEY_Escape, ++ WPE_KEY_space, ++ WPE_KEY_Page_Up, ++ WPE_KEY_Page_Down, ++ WPE_KEY_End, ++ WPE_KEY_Home, ++ WPE_KEY_Left, ++ WPE_KEY_Up, ++ WPE_KEY_Right, ++ WPE_KEY_Down, ++ WPE_KEY_Select, ++ WPE_KEY_Print, ++ WPE_KEY_Execute, ++ WPE_KEY_Insert, ++ WPE_KEY_KP_Insert, ++ WPE_KEY_Delete, ++ WPE_KEY_KP_Delete, ++ WPE_KEY_Help, ++ WPE_KEY_0, ++ WPE_KEY_parenright, ++ WPE_KEY_1, ++ WPE_KEY_exclam, ++ WPE_KEY_2, ++ WPE_KEY_at, ++ WPE_KEY_3, ++ WPE_KEY_numbersign, ++ WPE_KEY_4, ++ WPE_KEY_dollar, ++ WPE_KEY_5, ++ WPE_KEY_percent, ++ WPE_KEY_6, ++ WPE_KEY_asciicircum, ++ WPE_KEY_7, ++ WPE_KEY_ampersand, ++ WPE_KEY_8, ++ WPE_KEY_asterisk, ++ WPE_KEY_9, ++ WPE_KEY_parenleft, ++ WPE_KEY_a, ++ WPE_KEY_A, ++ WPE_KEY_b, ++ WPE_KEY_B, ++ WPE_KEY_c, ++ WPE_KEY_C, ++ WPE_KEY_d, ++ WPE_KEY_D, ++ WPE_KEY_e, ++ WPE_KEY_E, ++ WPE_KEY_f, ++ WPE_KEY_F, ++ WPE_KEY_g, ++ WPE_KEY_G, ++ WPE_KEY_h, ++ WPE_KEY_H, ++ WPE_KEY_i, ++ WPE_KEY_I, ++ WPE_KEY_j, ++ WPE_KEY_J, ++ WPE_KEY_k, ++ WPE_KEY_K, ++ WPE_KEY_l, ++ WPE_KEY_L, ++ WPE_KEY_m, ++ WPE_KEY_M, ++ WPE_KEY_n, ++ WPE_KEY_N, ++ WPE_KEY_o, ++ WPE_KEY_O, ++ WPE_KEY_p, ++ WPE_KEY_P, ++ WPE_KEY_q, ++ WPE_KEY_Q, ++ WPE_KEY_r, ++ WPE_KEY_R, ++ WPE_KEY_s, ++ WPE_KEY_S, ++ WPE_KEY_t, ++ WPE_KEY_T, ++ WPE_KEY_u, ++ WPE_KEY_U, ++ WPE_KEY_v, ++ WPE_KEY_V, ++ WPE_KEY_w, ++ WPE_KEY_W, ++ WPE_KEY_x, ++ WPE_KEY_X, ++ WPE_KEY_y, ++ WPE_KEY_Y, ++ WPE_KEY_z, ++ WPE_KEY_Z, ++ WPE_KEY_Meta_L, ++ WPE_KEY_Meta_R, ++ WPE_KEY_Sleep, ++ WPE_KEY_Num_Lock, ++ WPE_KEY_Scroll_Lock, ++ WPE_KEY_Shift_L, ++ WPE_KEY_Shift_R, ++ WPE_KEY_Control_L, ++ WPE_KEY_Control_R, ++ WPE_KEY_Alt_L, ++ WPE_KEY_Alt_R, ++ WPE_KEY_Back, ++ WPE_KEY_Forward, ++ WPE_KEY_Refresh, ++ WPE_KEY_Stop, ++ WPE_KEY_Search, ++ WPE_KEY_Favorites, ++ WPE_KEY_HomePage, ++ WPE_KEY_AudioMute, ++ WPE_KEY_AudioLowerVolume, ++ WPE_KEY_AudioRaiseVolume, ++ WPE_KEY_AudioNext, ++ WPE_KEY_AudioPrev, ++ WPE_KEY_AudioStop, ++ WPE_KEY_AudioMedia, ++ WPE_KEY_semicolon, ++ WPE_KEY_colon, ++ WPE_KEY_plus, ++ WPE_KEY_equal, ++ WPE_KEY_comma, ++ WPE_KEY_less, ++ WPE_KEY_minus, ++ WPE_KEY_underscore, ++ WPE_KEY_period, ++ WPE_KEY_greater, ++ WPE_KEY_slash, ++ WPE_KEY_question, ++ WPE_KEY_asciitilde, ++ WPE_KEY_quoteleft, ++ WPE_KEY_bracketleft, ++ WPE_KEY_braceleft, ++ WPE_KEY_backslash, ++ WPE_KEY_bar, ++ WPE_KEY_bracketright, ++ WPE_KEY_braceright, ++ WPE_KEY_quoteright, ++ WPE_KEY_quotedbl, ++ WPE_KEY_AudioRewind, ++ WPE_KEY_AudioForward, ++ WPE_KEY_AudioPlay, ++ WPE_KEY_F1, ++ WPE_KEY_F2, ++ WPE_KEY_F3, ++ WPE_KEY_F4, ++ WPE_KEY_F5, ++ WPE_KEY_F6, ++ WPE_KEY_F7, ++ WPE_KEY_F8, ++ WPE_KEY_F9, ++ WPE_KEY_F10, ++ WPE_KEY_F11, ++ WPE_KEY_F12, ++ WPE_KEY_F13, ++ WPE_KEY_F14, ++ WPE_KEY_F15, ++ WPE_KEY_F16, ++ WPE_KEY_F17, ++ WPE_KEY_F18, ++ WPE_KEY_F19, ++ WPE_KEY_F20, ++ WPE_KEY_F21, ++ WPE_KEY_F22, ++ WPE_KEY_F23, ++ WPE_KEY_F24, ++ WPE_KEY_VoidSymbol, ++ WPE_KEY_Red, ++ WPE_KEY_Green, ++ WPE_KEY_Yellow, ++ WPE_KEY_Blue, ++ WPE_KEY_PowerOff, ++ WPE_KEY_AudioRecord, ++ WPE_KEY_Display, ++ WPE_KEY_Subtitle, ++ WPE_KEY_Video ++ }; ++ result = new HashMap(); ++ for (unsigned WPEKeyCode : WPEKeyCodes) { ++ int winKeyCode = PlatformKeyboardEvent::windowsKeyCodeForWPEKeyCode(WPEKeyCode); ++ // If several gdk key codes map to the same win key code first one is used. ++ result->add(winKeyCode, WPEKeyCode); ++ } ++ }); ++ return *result; ++} ++ ++unsigned PlatformKeyboardEvent::WPEKeyCodeForWindowsKeyCode(int keycode) ++{ ++ return WPEToWindowsKeyCodeMap().get(keycode); ++} ++ + String PlatformKeyboardEvent::singleCharacterString(unsigned val) + { + switch (val) { +diff --git a/Source/WebCore/platform/network/HTTPHeaderMap.cpp b/Source/WebCore/platform/network/HTTPHeaderMap.cpp +index 39cb560e54bf9efd2dad6e1fb60dd0f609daf6bf..91c132460d4b466f61a8c579f70329fdde3b130f 100644 +--- a/Source/WebCore/platform/network/HTTPHeaderMap.cpp ++++ b/Source/WebCore/platform/network/HTTPHeaderMap.cpp +@@ -205,8 +205,11 @@ void HTTPHeaderMap::add(HTTPHeaderName name, const String& value) + auto index = m_commonHeaders.findMatching([&](auto& header) { + return header.key == name; + }); ++ // Align with Chromium and Firefox, but just for SetCookies where it is critical: ++ // https://bit.ly/2HCa0iq ++ String separator = name == HTTPHeaderName::SetCookie ? "\n " : ", "; + if (index != notFound) +- m_commonHeaders[index].value = makeString(m_commonHeaders[index].value, ", ", value); ++ m_commonHeaders[index].value = makeString(m_commonHeaders[index].value, separator, value); + else + m_commonHeaders.append(CommonHeader { name, value }); + } +diff --git a/Source/WebCore/platform/network/NetworkStateNotifier.h b/Source/WebCore/platform/network/NetworkStateNotifier.h +index 87930048f4fd18d6098af7de4da25be532df5931..2bb2afcf9473b0d5d97efbe18dd7b8145bc5f932 100644 +--- a/Source/WebCore/platform/network/NetworkStateNotifier.h ++++ b/Source/WebCore/platform/network/NetworkStateNotifier.h +@@ -72,6 +72,7 @@ private: + #endif + + Optional m_isOnLine; ++ Optional m_emulatedIsOnLine; + Vector> m_listeners; + Timer m_updateStateTimer; + +diff --git a/Source/WebCore/platform/network/ResourceResponseBase.h b/Source/WebCore/platform/network/ResourceResponseBase.h +index 0e97fee9c6d65a382d6bc5616ffa91de776b771b..9b337b3a2d3a641707fb9568efadb7fc5c2ef4b8 100644 +--- a/Source/WebCore/platform/network/ResourceResponseBase.h ++++ b/Source/WebCore/platform/network/ResourceResponseBase.h +@@ -217,6 +217,8 @@ public: + + WEBCORE_EXPORT static ResourceResponse dataURLResponse(const URL&, const DataURLDecoder::Result&); + ++ HTTPHeaderMap m_httpRequestHeaderFields; ++ + protected: + enum InitLevel { + Uninitialized, +@@ -299,6 +301,7 @@ void ResourceResponseBase::encode(Encoder& encoder) const + encoder << m_httpStatusText; + encoder << m_httpVersion; + encoder << m_httpHeaderFields; ++ encoder << m_httpRequestHeaderFields; + + // We don't want to put the networkLoadMetrics info + // into the disk cache, because we will never use the old info. +@@ -371,6 +374,12 @@ bool ResourceResponseBase::decode(Decoder& decoder, ResourceResponseBase& respon + return false; + response.m_httpHeaderFields = WTFMove(*httpHeaderFields); + ++ Optional httpRequestHeaderFields; ++ decoder >> httpRequestHeaderFields; ++ if (!httpRequestHeaderFields) ++ return false; ++ response.m_httpRequestHeaderFields = WTFMove(*httpRequestHeaderFields); ++ + // The networkLoadMetrics info is only send over IPC and not stored in disk cache. + if constexpr (Decoder::isIPCDecoder) { + Optional> networkLoadMetrics; +diff --git a/Source/WebCore/platform/network/cf/SocketStreamHandleImpl.h b/Source/WebCore/platform/network/cf/SocketStreamHandleImpl.h +index d677280d2b5e7b053a240c155d64bc881f1737bb..1be949e09982b34366d162e6d45ebc51a76dcfb0 100644 +--- a/Source/WebCore/platform/network/cf/SocketStreamHandleImpl.h ++++ b/Source/WebCore/platform/network/cf/SocketStreamHandleImpl.h +@@ -47,7 +47,7 @@ class SocketStreamHandleClient; + + class SocketStreamHandleImpl : public SocketStreamHandle { + public: +- static Ref create(const URL& url, SocketStreamHandleClient& client, PAL::SessionID sessionID, const String& credentialPartition, SourceApplicationAuditToken&& auditData, const StorageSessionProvider* provider) { return adoptRef(*new SocketStreamHandleImpl(url, client, sessionID, credentialPartition, WTFMove(auditData), provider)); } ++ static Ref create(const URL& url, bool ignoreCertificateErrors, SocketStreamHandleClient& client, PAL::SessionID sessionID, const String& credentialPartition, SourceApplicationAuditToken&& auditData, const StorageSessionProvider* provider) { return adoptRef(*new SocketStreamHandleImpl(url, ignoreCertificateErrors, client, sessionID, credentialPartition, WTFMove(auditData), provider)); } + + virtual ~SocketStreamHandleImpl(); + +@@ -61,7 +61,7 @@ private: + Optional platformSendInternal(const uint8_t*, size_t); + bool sendPendingData(); + +- WEBCORE_EXPORT SocketStreamHandleImpl(const URL&, SocketStreamHandleClient&, PAL::SessionID, const String& credentialPartition, SourceApplicationAuditToken&&, const StorageSessionProvider*); ++ WEBCORE_EXPORT SocketStreamHandleImpl(const URL&, bool ignoreCertificateErrors, SocketStreamHandleClient&, PAL::SessionID, const String& credentialPartition, SourceApplicationAuditToken&&, const StorageSessionProvider*); + void createStreams(); + void scheduleStreams(); + void chooseProxy(); +@@ -106,6 +106,7 @@ private: + String m_credentialPartition; + SourceApplicationAuditToken m_auditData; + RefPtr m_storageSessionProvider; ++ bool m_ignoreCertificateErrors { false }; + + StreamBuffer m_buffer; + static const unsigned maxBufferSize = 100 * 1024 * 1024; +diff --git a/Source/WebCore/platform/network/cf/SocketStreamHandleImplCFNet.cpp b/Source/WebCore/platform/network/cf/SocketStreamHandleImplCFNet.cpp +index 9915f0ceacaf946eb4af2d6b740f7226e344b78d..4382ccde112e3c21892a4dd28fba416a6db90a62 100644 +--- a/Source/WebCore/platform/network/cf/SocketStreamHandleImplCFNet.cpp ++++ b/Source/WebCore/platform/network/cf/SocketStreamHandleImplCFNet.cpp +@@ -96,7 +96,7 @@ static inline auto callbacksRunLoopMode() + #endif + } + +-SocketStreamHandleImpl::SocketStreamHandleImpl(const URL& url, SocketStreamHandleClient& client, PAL::SessionID sessionID, const String& credentialPartition, SourceApplicationAuditToken&& auditData, const StorageSessionProvider* provider) ++SocketStreamHandleImpl::SocketStreamHandleImpl(const URL& url, bool ignoreCertificateErrors, SocketStreamHandleClient& client, PAL::SessionID sessionID, const String& credentialPartition, SourceApplicationAuditToken&& auditData, const StorageSessionProvider* provider) + : SocketStreamHandle(url, client) + , m_connectingSubstate(New) + , m_connectionType(Unknown) +@@ -104,6 +104,7 @@ SocketStreamHandleImpl::SocketStreamHandleImpl(const URL& url, SocketStreamHandl + , m_credentialPartition(credentialPartition) + , m_auditData(WTFMove(auditData)) + , m_storageSessionProvider(provider) ++ , m_ignoreCertificateErrors(ignoreCertificateErrors) + { + LOG(Network, "SocketStreamHandle %p new client %p", this, &m_client); + +@@ -360,7 +361,7 @@ void SocketStreamHandleImpl::createStreams() + } + + if (shouldUseSSL()) { +- CFBooleanRef validateCertificateChain = DeprecatedGlobalSettings::allowsAnySSLCertificate() ? kCFBooleanFalse : kCFBooleanTrue; ++ CFBooleanRef validateCertificateChain = m_ignoreCertificateErrors || DeprecatedGlobalSettings::allowsAnySSLCertificate() ? kCFBooleanFalse : kCFBooleanTrue; + const void* keys[] = { + kCFStreamSSLPeerName, + kCFStreamSSLLevel, +diff --git a/Source/WebCore/platform/network/curl/CookieJarDB.h b/Source/WebCore/platform/network/curl/CookieJarDB.h +index 7c0ea47ece4ff0d472ce595c91ea1cfa90b25ca7..1c44229a18fe90f6e5e0c0056dddd09acadfe49b 100644 +--- a/Source/WebCore/platform/network/curl/CookieJarDB.h ++++ b/Source/WebCore/platform/network/curl/CookieJarDB.h +@@ -72,7 +72,7 @@ public: + WEBCORE_EXPORT ~CookieJarDB(); + + private: +- CookieAcceptPolicy m_acceptPolicy { CookieAcceptPolicy::Always }; ++ CookieAcceptPolicy m_acceptPolicy { CookieAcceptPolicy::OnlyFromMainDocumentDomain }; + String m_databasePath; + + bool m_detectedDatabaseCorruption { false }; +diff --git a/Source/WebCore/platform/network/curl/CurlStream.cpp b/Source/WebCore/platform/network/curl/CurlStream.cpp +index 1b15af01bcc0eab910fc3b9e8a8d463b7c668519..c11f0b310810fad74eacbd2c41ff16c2507111f1 100644 +--- a/Source/WebCore/platform/network/curl/CurlStream.cpp ++++ b/Source/WebCore/platform/network/curl/CurlStream.cpp +@@ -33,7 +33,7 @@ + + namespace WebCore { + +-CurlStream::CurlStream(CurlStreamScheduler& scheduler, CurlStreamID streamID, URL&& url) ++CurlStream::CurlStream(CurlStreamScheduler& scheduler, CurlStreamID streamID, bool ignoreCertificateErrors, URL&& url) + : m_scheduler(scheduler) + , m_streamID(streamID) + { +@@ -45,6 +45,9 @@ CurlStream::CurlStream(CurlStreamScheduler& scheduler, CurlStreamID streamID, UR + m_curlHandle->setUrl(WTFMove(url)); + + m_curlHandle->enableConnectionOnly(); ++ if (ignoreCertificateErrors) ++ m_curlHandle->disableServerTrustEvaluation(); ++ + + auto errorCode = m_curlHandle->perform(); + if (errorCode != CURLE_OK) { +diff --git a/Source/WebCore/platform/network/curl/CurlStream.h b/Source/WebCore/platform/network/curl/CurlStream.h +index 313b0173da5cd404a1e3fcad9573b8ff7c3abd4f..020980a0f61d47e8c7929bfaab2f8394d014766d 100644 +--- a/Source/WebCore/platform/network/curl/CurlStream.h ++++ b/Source/WebCore/platform/network/curl/CurlStream.h +@@ -50,12 +50,12 @@ public: + virtual void didFail(CurlStreamID, CURLcode) = 0; + }; + +- static std::unique_ptr create(CurlStreamScheduler& scheduler, CurlStreamID streamID, URL&& url) ++ static std::unique_ptr create(CurlStreamScheduler& scheduler, CurlStreamID streamID, bool ignoreCertificateErrors, URL&& url) + { +- return WTF::makeUnique(scheduler, streamID, WTFMove(url)); ++ return WTF::makeUnique(scheduler, streamID, ignoreCertificateErrors, WTFMove(url)); + } + +- CurlStream(CurlStreamScheduler&, CurlStreamID, URL&&); ++ CurlStream(CurlStreamScheduler&, CurlStreamID, bool ignoreCertificateErrors, URL&&); + virtual ~CurlStream(); + + void send(UniqueArray&&, size_t); +diff --git a/Source/WebCore/platform/network/curl/CurlStreamScheduler.cpp b/Source/WebCore/platform/network/curl/CurlStreamScheduler.cpp +index 3fb8759984aa31a7d44baa2f69afe2fee461ea4f..bb7ad47477d97fa1eaff5d3da6b9a3705ff1e32f 100644 +--- a/Source/WebCore/platform/network/curl/CurlStreamScheduler.cpp ++++ b/Source/WebCore/platform/network/curl/CurlStreamScheduler.cpp +@@ -40,7 +40,7 @@ CurlStreamScheduler::~CurlStreamScheduler() + ASSERT(isMainThread()); + } + +-CurlStreamID CurlStreamScheduler::createStream(const URL& url, CurlStream::Client& client) ++CurlStreamID CurlStreamScheduler::createStream(const URL& url, bool ignoreCertificateErrors, CurlStream::Client& client) + { + ASSERT(isMainThread()); + +@@ -51,8 +51,8 @@ CurlStreamID CurlStreamScheduler::createStream(const URL& url, CurlStream::Clien + auto streamID = m_currentStreamID; + m_clientList.add(streamID, &client); + +- callOnWorkerThread([this, streamID, url = url.isolatedCopy()]() mutable { +- m_streamList.add(streamID, CurlStream::create(*this, streamID, WTFMove(url))); ++ callOnWorkerThread([this, streamID, ignoreCertificateErrors, url = url.isolatedCopy()]() mutable { ++ m_streamList.add(streamID, CurlStream::create(*this, streamID, ignoreCertificateErrors, WTFMove(url))); + }); + + return streamID; +diff --git a/Source/WebCore/platform/network/curl/CurlStreamScheduler.h b/Source/WebCore/platform/network/curl/CurlStreamScheduler.h +index 7d881206c9689f433227969c9b7f9ff268bdaaed..2e8118f11f87fa5f32adcedc165aec8220b36d58 100644 +--- a/Source/WebCore/platform/network/curl/CurlStreamScheduler.h ++++ b/Source/WebCore/platform/network/curl/CurlStreamScheduler.h +@@ -38,7 +38,7 @@ public: + CurlStreamScheduler(); + virtual ~CurlStreamScheduler(); + +- CurlStreamID createStream(const URL&, CurlStream::Client&); ++ CurlStreamID createStream(const URL&, bool ignoreCertificateErrors, CurlStream::Client&); + void destroyStream(CurlStreamID); + void send(CurlStreamID, UniqueArray&&, size_t); + +diff --git a/Source/WebCore/platform/network/curl/SocketStreamHandleImpl.h b/Source/WebCore/platform/network/curl/SocketStreamHandleImpl.h +index fad4ef9198118f5e6e5ed7d3c14b99e574593451..a2d59843896f252fccdddbb94c5275eec6300f1b 100644 +--- a/Source/WebCore/platform/network/curl/SocketStreamHandleImpl.h ++++ b/Source/WebCore/platform/network/curl/SocketStreamHandleImpl.h +@@ -44,7 +44,7 @@ class StorageSessionProvider; + + class SocketStreamHandleImpl : public SocketStreamHandle, public CurlStream::Client { + public: +- static Ref create(const URL& url, SocketStreamHandleClient& client, PAL::SessionID, const String&, SourceApplicationAuditToken&&, const StorageSessionProvider* provider) { return adoptRef(*new SocketStreamHandleImpl(url, client, provider)); } ++ static Ref create(const URL& url, bool ignoreCertificateErrors, SocketStreamHandleClient& client, PAL::SessionID, const String&, SourceApplicationAuditToken&&, const StorageSessionProvider* provider) { return adoptRef(*new SocketStreamHandleImpl(url, ignoreCertificateErrors, client, provider)); } + + virtual ~SocketStreamHandleImpl(); + +@@ -53,7 +53,7 @@ public: + WEBCORE_EXPORT void platformClose() final; + + private: +- WEBCORE_EXPORT SocketStreamHandleImpl(const URL&, SocketStreamHandleClient&, const StorageSessionProvider*); ++ WEBCORE_EXPORT SocketStreamHandleImpl(const URL&, bool ignoreCertificateErrors, SocketStreamHandleClient&, const StorageSessionProvider*); + + size_t bufferedAmount() final; + Optional platformSendInternal(const uint8_t*, size_t); +diff --git a/Source/WebCore/platform/network/curl/SocketStreamHandleImplCurl.cpp b/Source/WebCore/platform/network/curl/SocketStreamHandleImplCurl.cpp +index cae8c43d60fcf6a3d69c58a7436516f923d227cb..e6b03f378929abbd4437f8507ea2f6c563edcff7 100644 +--- a/Source/WebCore/platform/network/curl/SocketStreamHandleImplCurl.cpp ++++ b/Source/WebCore/platform/network/curl/SocketStreamHandleImplCurl.cpp +@@ -43,7 +43,7 @@ + + namespace WebCore { + +-SocketStreamHandleImpl::SocketStreamHandleImpl(const URL& url, SocketStreamHandleClient& client, const StorageSessionProvider* provider) ++SocketStreamHandleImpl::SocketStreamHandleImpl(const URL& url, bool ignoreCertificateErrors, SocketStreamHandleClient& client, const StorageSessionProvider* provider) + : SocketStreamHandle(url, client) + , m_storageSessionProvider(provider) + , m_scheduler(CurlContext::singleton().streamScheduler()) +@@ -52,7 +52,7 @@ SocketStreamHandleImpl::SocketStreamHandleImpl(const URL& url, SocketStreamHandl + if (m_url.protocolIs("wss") && DeprecatedGlobalSettings::allowsAnySSLCertificate()) + CurlContext::singleton().sslHandle().setIgnoreSSLErrors(true); + +- m_streamID = m_scheduler.createStream(m_url, *this); ++ m_streamID = m_scheduler.createStream(m_url, ignoreCertificateErrors, *this); + } + + SocketStreamHandleImpl::~SocketStreamHandleImpl() +diff --git a/Source/WebCore/platform/network/soup/SocketStreamHandleImpl.h b/Source/WebCore/platform/network/soup/SocketStreamHandleImpl.h +index 3ecf866005da6da9cec7c7930e6a4f93cb39d6e0..d81dc9ac0c433e00ab4ad73e206856098ab9230e 100644 +--- a/Source/WebCore/platform/network/soup/SocketStreamHandleImpl.h ++++ b/Source/WebCore/platform/network/soup/SocketStreamHandleImpl.h +@@ -47,7 +47,7 @@ class StorageSessionProvider; + + class SocketStreamHandleImpl final : public SocketStreamHandle { + public: +- static Ref create(const URL&, SocketStreamHandleClient&, PAL::SessionID, const String&, SourceApplicationAuditToken&&, const StorageSessionProvider*) ++ static Ref create(const URL&, bool, SocketStreamHandleClient&, PAL::SessionID, const String&, SourceApplicationAuditToken&&, const StorageSessionProvider*) + { + RELEASE_ASSERT_NOT_REACHED(); + } +diff --git a/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp b/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp +index 8789f11c3643999c30dfdb1c9b939ae45bb0a51f..422961d2b43e6da9e36df4cdeb06fe91ac57a644 100644 +--- a/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp ++++ b/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include "Pasteboard.h" + + #if USE(CF) + #include +@@ -724,7 +725,10 @@ template void getStringData(IDataObject* data, FORMATETC* format, Ve + STGMEDIUM store; + if (FAILED(data->GetData(format, &store))) + return; +- dataStrings.append(String(static_cast(GlobalLock(store.hGlobal)), ::GlobalSize(store.hGlobal) / sizeof(T))); ++ // The string here should be null terminated, but it could come from another app so lets lock it ++ // to the size to prevent an overflow. ++ String rawString = String(static_cast(GlobalLock(store.hGlobal)), ::GlobalSize(store.hGlobal) / sizeof(T)); ++ dataStrings.append(String::fromUTF8(rawString.utf8().data())); + GlobalUnlock(store.hGlobal); + ReleaseStgMedium(&store); + } +diff --git a/Source/WebCore/platform/win/ClipboardUtilitiesWin.h b/Source/WebCore/platform/win/ClipboardUtilitiesWin.h +index c50799b63e05adbe32bae3535d786c7d268f980f..9cf1cc7ec4eaae22947f80ba272dfae272167bd6 100644 +--- a/Source/WebCore/platform/win/ClipboardUtilitiesWin.h ++++ b/Source/WebCore/platform/win/ClipboardUtilitiesWin.h +@@ -34,6 +34,7 @@ namespace WebCore { + + class Document; + class DocumentFragment; ++class Pasteboard; + + HGLOBAL createGlobalData(const String&); + HGLOBAL createGlobalData(const Vector&); +diff --git a/Source/WebCore/platform/win/DragDataWin.cpp b/Source/WebCore/platform/win/DragDataWin.cpp +index 9e28783e6e1ac135970b06d420f5ec64a6b99fa1..bac00b5d69ae8d462ab0204082ca51cb105fd090 100644 +--- a/Source/WebCore/platform/win/DragDataWin.cpp ++++ b/Source/WebCore/platform/win/DragDataWin.cpp +@@ -48,6 +48,7 @@ DragData::DragData(const DragDataMap& data, const IntPoint& clientPosition, cons + , m_applicationFlags(flags) + , m_pageID(pageID) + , m_dragDataMap(data) ++ , m_dragDestinationActionMask(anyDragDestinationAction()) + { + } + +diff --git a/Source/WebCore/platform/win/KeyEventWin.cpp b/Source/WebCore/platform/win/KeyEventWin.cpp +index 44737686187a06a92c408ea60b63a48ac8481334..c754a763688b52e7ddd47493296ef9b0c6adc527 100644 +--- a/Source/WebCore/platform/win/KeyEventWin.cpp ++++ b/Source/WebCore/platform/win/KeyEventWin.cpp +@@ -239,10 +239,16 @@ PlatformKeyboardEvent::PlatformKeyboardEvent(HWND, WPARAM code, LPARAM keyData, + { + } + +-void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type, bool) ++void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type type, bool backwardsCompatibility) + { +- // No KeyDown events on Windows to disambiguate. +- ASSERT_NOT_REACHED(); ++ m_type = type; ++ if (type == PlatformEvent::RawKeyDown) { ++ m_text = String(); ++ m_unmodifiedText = String(); ++ } else { ++ m_keyIdentifier = String(); ++ m_windowsVirtualKeyCode = 0; ++ } + } + + bool PlatformKeyboardEvent::currentCapsLockState() +diff --git a/Source/WebCore/platform/win/PasteboardWin.cpp b/Source/WebCore/platform/win/PasteboardWin.cpp +index cc8003f5e153205ac075ad06954215950199debc..310c0a03162b987f21ad9288bd71337abf1d3893 100644 +--- a/Source/WebCore/platform/win/PasteboardWin.cpp ++++ b/Source/WebCore/platform/win/PasteboardWin.cpp +@@ -1135,7 +1135,21 @@ void Pasteboard::writeCustomData(const Vector& data) + } + + clear(); ++ if (m_dataObject) { ++ const auto& customData = data.first(); ++ customData.forEachPlatformString([&](auto& type, auto& string) { ++ writeString(type, string); ++ }); + ++ if (customData.hasSameOriginCustomData() || !customData.origin().isEmpty()) { ++ customData.forEachCustomString([&](auto& type, auto& string) { ++ writeString(type, string); ++ }); ++ } ++ return; ++ } ++ ++ // this is the real real clipboard. Prbaobly need to be doing drag data stuff. + if (::OpenClipboard(m_owner)) { + const auto& customData = data.first(); + customData.forEachPlatformStringOrBuffer([](auto& type, auto& stringOrBuffer) { +@@ -1174,4 +1188,25 @@ void Pasteboard::write(const Color&) + { + } + ++DragDataMap Pasteboard::createDragDataMap() { ++ DragDataMap dragDataMap; ++ auto dragObject = dataObject(); ++ if (!dragObject) ++ return dragDataMap; ++ // Enumerate clipboard content and load it in the map. ++ COMPtr itr; ++ ++ if (FAILED(dragObject->EnumFormatEtc(DATADIR_GET, &itr)) || !itr) ++ return dragDataMap; ++ ++ FORMATETC dataFormat; ++ while (itr->Next(1, &dataFormat, 0) == S_OK) { ++ Vector dataStrings; ++ getClipboardData(dragObject.get(), &dataFormat, dataStrings); ++ if (!dataStrings.isEmpty()) ++ dragDataMap.set(dataFormat.cfFormat, dataStrings); ++ } ++ return dragDataMap; ++} ++ + } // namespace WebCore +diff --git a/Source/WebCore/platform/wpe/DragDataWPE.cpp b/Source/WebCore/platform/wpe/DragDataWPE.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..07fb260a5203167fdf94a552949394bb73ca8c61 +--- /dev/null ++++ b/Source/WebCore/platform/wpe/DragDataWPE.cpp +@@ -0,0 +1,87 @@ ++/* ++ * 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" ++#include "DragData.h" ++#include "SelectionData.h" ++ ++namespace WebCore { ++ ++bool DragData::canSmartReplace() const ++{ ++ return false; ++} ++ ++bool DragData::containsColor() const ++{ ++ return false; ++} ++ ++bool DragData::containsFiles() const ++{ ++ return m_platformDragData->hasFilenames(); ++} ++ ++unsigned DragData::numberOfFiles() const ++{ ++ return m_platformDragData->filenames().size(); ++} ++ ++Vector DragData::asFilenames() const ++{ ++ return m_platformDragData->filenames(); ++} ++ ++bool DragData::containsPlainText() const ++{ ++ return m_platformDragData->hasText(); ++} ++ ++String DragData::asPlainText() const ++{ ++ return m_platformDragData->text(); ++} ++ ++Color DragData::asColor() const ++{ ++ return Color(); ++} ++ ++bool DragData::containsCompatibleContent(DraggingPurpose) const ++{ ++ return containsPlainText() || containsURL() || containsColor() || containsFiles(); ++} ++ ++bool DragData::containsURL(FilenameConversionPolicy filenamePolicy) const ++{ ++ return !asURL(filenamePolicy).isEmpty(); ++} ++ ++String DragData::asURL(FilenameConversionPolicy filenamePolicy, String* title) const ++{ ++ if (!m_platformDragData->hasURL()) ++ return String(); ++ if (filenamePolicy != ConvertFilenames) { ++ if (m_platformDragData->url().isLocalFile()) ++ return { }; ++ } ++ ++ if (title) ++ *title = m_platformDragData->urlLabel(); ++ return m_platformDragData->url().string(); ++} ++ ++} +diff --git a/Source/WebCore/platform/wpe/DragImageWPE.cpp b/Source/WebCore/platform/wpe/DragImageWPE.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..0c684ea504c0c93895ab75a880b4d2febc946813 +--- /dev/null ++++ b/Source/WebCore/platform/wpe/DragImageWPE.cpp +@@ -0,0 +1,68 @@ ++/* ++ * Copyright (C) 2010,2017 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" ++#include "DragImage.h" ++#include "NotImplemented.h" ++ ++#include "Image.h" ++ ++namespace WebCore { ++ ++IntSize dragImageSize(DragImageRef) ++{ ++ notImplemented(); ++ return { 0, 0 }; ++} ++ ++void deleteDragImage(DragImageRef) ++{ ++ notImplemented(); ++} ++ ++DragImageRef scaleDragImage(DragImageRef, FloatSize) ++{ ++ notImplemented(); ++ return nullptr; ++} ++ ++DragImageRef dissolveDragImageToFraction(DragImageRef image, float) ++{ ++ notImplemented(); ++ return image; ++} ++ ++DragImageRef createDragImageFromImage(Image* image, ImageOrientation) ++{ ++ return image->nativeImageForCurrentFrame()->platformImage(); ++} ++ ++ ++DragImageRef createDragImageIconForCachedImageFilename(const String&) ++{ ++ notImplemented(); ++ return nullptr; ++} ++ ++DragImageRef createDragImageForLink(Element&, URL&, const String&, TextIndicatorData&, FontRenderingMode, float) ++{ ++ notImplemented(); ++ return nullptr; ++} ++ ++} +diff --git a/Source/WebCore/platform/wpe/PlatformScreenWPE.cpp b/Source/WebCore/platform/wpe/PlatformScreenWPE.cpp +index 6b859de7a16bf05610f70cc561c15358a0f4b6be..6e09d6979042c69729c89c509bc0d9c944efbb5a 100644 +--- a/Source/WebCore/platform/wpe/PlatformScreenWPE.cpp ++++ b/Source/WebCore/platform/wpe/PlatformScreenWPE.cpp +@@ -87,12 +87,12 @@ bool screenSupportsExtendedColor(Widget*) + } + + #if ENABLE(TOUCH_EVENTS) +-bool screenHasTouchDevice() ++bool platformScreenHasTouchDevice() + { + return true; + } + +-bool screenIsTouchPrimaryInputDevice() ++bool platformScreenIsTouchPrimaryInputDevice() + { + return true; + } +diff --git a/Source/WebCore/platform/wpe/SelectionData.cpp b/Source/WebCore/platform/wpe/SelectionData.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..9f181fdfe507ad5b7a47b5c58295cf4f2725e7d8 +--- /dev/null ++++ b/Source/WebCore/platform/wpe/SelectionData.cpp +@@ -0,0 +1,134 @@ ++/* ++ * Copyright (C) 2009, Martin Robinson ++ * ++ * 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" ++#include "SelectionData.h" ++ ++#include ++#include ++#include ++ ++namespace WebCore { ++ ++static void replaceNonBreakingSpaceWithSpace(String& str) ++{ ++ static const UChar NonBreakingSpaceCharacter = 0xA0; ++ static const UChar SpaceCharacter = ' '; ++ str.replace(NonBreakingSpaceCharacter, SpaceCharacter); ++} ++ ++void SelectionData::setText(const String& newText) ++{ ++ m_text = newText; ++ replaceNonBreakingSpaceWithSpace(m_text); ++} ++ ++void SelectionData::setURIList(const String& uriListString) ++{ ++ m_uriList = uriListString; ++ ++ // This code is originally from: platform/chromium/ChromiumDataObject.cpp. ++ // FIXME: We should make this code cross-platform eventually. ++ ++ // Line separator is \r\n per RFC 2483 - however, for compatibility ++ // reasons we also allow just \n here. ++ ++ // Process the input and copy the first valid URL into the url member. ++ // In case no URLs can be found, subsequent calls to getData("URL") ++ // will get an empty string. This is in line with the HTML5 spec (see ++ // "The DragEvent and DataTransfer interfaces"). Also extract all filenames ++ // from the URI list. ++ bool setURL = hasURL(); ++ for (auto& line : uriListString.split('\n')) { ++ line = line.stripWhiteSpace(); ++ if (line.isEmpty()) ++ continue; ++ if (line[0] == '#') ++ continue; ++ ++ URL url = URL(URL(), line); ++ if (url.isValid()) { ++ if (!setURL) { ++ m_url = url; ++ setURL = true; ++ } ++ ++ GUniqueOutPtr error; ++ GUniquePtr filename(g_filename_from_uri(line.utf8().data(), 0, &error.outPtr())); ++ if (!error && filename) ++ m_filenames.append(String::fromUTF8(filename.get())); ++ } ++ } ++} ++ ++void SelectionData::setURL(const URL& url, const String& label) ++{ ++ m_url = url; ++ if (m_uriList.isEmpty()) ++ m_uriList = url.string(); ++ ++ if (!hasText()) ++ setText(url.string()); ++ ++ if (hasMarkup()) ++ return; ++ ++ String actualLabel(label); ++ if (actualLabel.isEmpty()) ++ actualLabel = url.string(); ++ ++ StringBuilder markup; ++ markup.append(""); ++ GUniquePtr escaped(g_markup_escape_text(actualLabel.utf8().data(), -1)); ++ markup.append(String::fromUTF8(escaped.get())); ++ markup.append(""); ++ setMarkup(markup.toString()); ++} ++ ++const String& SelectionData::urlLabel() const ++{ ++ if (hasText()) ++ return text(); ++ ++ if (hasURL()) ++ return url().string(); ++ ++ return emptyString(); ++} ++ ++void SelectionData::clearAllExceptFilenames() ++{ ++ clearText(); ++ clearMarkup(); ++ clearURIList(); ++ clearURL(); ++ clearImage(); ++ clearCustomData(); ++ ++ m_canSmartReplace = false; ++} ++ ++void SelectionData::clearAll() ++{ ++ clearAllExceptFilenames(); ++ m_filenames.clear(); ++} ++ ++} // namespace WebCore +diff --git a/Source/WebCore/platform/wpe/SelectionData.h b/Source/WebCore/platform/wpe/SelectionData.h +new file mode 100644 +index 0000000000000000000000000000000000000000..cf2b51f6f02837a1106f4d999f2f130e2580986a +--- /dev/null ++++ b/Source/WebCore/platform/wpe/SelectionData.h +@@ -0,0 +1,82 @@ ++/* ++ * Copyright (C) 2009, Martin Robinson ++ * ++ * 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 ++ */ ++ ++#pragma once ++ ++#include "Image.h" ++#include "SharedBuffer.h" ++#include ++#include ++#include ++ ++namespace WebCore { ++ ++class SelectionData { ++ WTF_MAKE_FAST_ALLOCATED; ++public: ++ void setText(const String&); ++ const String& text() const { return m_text; } ++ bool hasText() const { return !m_text.isEmpty(); } ++ void clearText() { m_text = emptyString(); } ++ ++ void setMarkup(const String& newMarkup) { m_markup = newMarkup; } ++ const String& markup() const { return m_markup; } ++ bool hasMarkup() const { return !m_markup.isEmpty(); } ++ void clearMarkup() { m_markup = emptyString(); } ++ ++ void setURL(const URL&, const String&); ++ const URL& url() const { return m_url; } ++ const String& urlLabel() const; ++ bool hasURL() const { return !m_url.isEmpty() && m_url.isValid(); } ++ void clearURL() { m_url = URL(); } ++ ++ void setURIList(const String&); ++ const String& uriList() const { return m_uriList; } ++ const Vector& filenames() const { return m_filenames; } ++ bool hasURIList() const { return !m_uriList.isEmpty(); } ++ bool hasFilenames() const { return !m_filenames.isEmpty(); } ++ void clearURIList() { m_uriList = emptyString(); } ++ ++ void setImage(Image* newImage) { m_image = newImage; } ++ Image* image() const { return m_image.get(); } ++ bool hasImage() const { return m_image; } ++ void clearImage() { m_image = nullptr; } ++ ++ void setCanSmartReplace(bool canSmartReplace) { m_canSmartReplace = canSmartReplace; } ++ bool canSmartReplace() const { return m_canSmartReplace; } ++ ++ void setCustomData(Ref&& buffer) { m_customData = WTFMove(buffer); } ++ SharedBuffer* customData() const { return m_customData.get(); } ++ bool hasCustomData() const { return !!m_customData; } ++ void clearCustomData() { m_customData = nullptr; } ++ ++ void clearAll(); ++ void clearAllExceptFilenames(); ++ ++private: ++ String m_text; ++ String m_markup; ++ URL m_url; ++ String m_uriList; ++ Vector m_filenames; ++ RefPtr m_image; ++ bool m_canSmartReplace { false }; ++ RefPtr m_customData; ++}; ++ ++} // namespace WebCore +diff --git a/Source/WebCore/rendering/RenderLayer.cpp b/Source/WebCore/rendering/RenderLayer.cpp +index 28a14d76e0eb26a1cc413396a6f2cf69523f75fa..56e820a215f1cf254277a6fa997b654a8a3df1bb 100644 +--- a/Source/WebCore/rendering/RenderLayer.cpp ++++ b/Source/WebCore/rendering/RenderLayer.cpp +@@ -2540,7 +2540,7 @@ LayoutRect RenderLayer::getRectToExpose(const LayoutRect& visibleRect, const Lay + ScrollAlignment::Behavior scrollX; + LayoutRect exposeRectX(exposeRect.x(), visibleRect.y(), exposeRect.width(), visibleRect.height()); + LayoutUnit intersectWidth = intersection(visibleRect, exposeRectX).width(); +- if (intersectWidth == exposeRect.width() || intersectWidth >= MIN_INTERSECT_FOR_REVEAL) ++ if (intersectWidth == exposeRect.width() || (intersectWidth >= MIN_INTERSECT_FOR_REVEAL && !alignX.m_disableMinThreshold)) + // If the rectangle is fully visible, use the specified visible behavior. + // If the rectangle is partially visible, but over a certain threshold, + // then treat it as fully visible to avoid unnecessary horizontal scrolling +diff --git a/Source/WebCore/rendering/RenderTextControl.cpp b/Source/WebCore/rendering/RenderTextControl.cpp +index dc058d53467aa3cfabf852f331ef01f3155321f4..2ac8e9e232ee97fd8d88f6d255d3ea8604254bfa 100644 +--- a/Source/WebCore/rendering/RenderTextControl.cpp ++++ b/Source/WebCore/rendering/RenderTextControl.cpp +@@ -205,13 +205,13 @@ void RenderTextControl::layoutExcludedChildren(bool relayoutChildren) + } + } + +-#if PLATFORM(IOS_FAMILY) + bool RenderTextControl::canScroll() const + { + auto innerText = innerTextElement(); + return innerText && innerText->renderer() && innerText->renderer()->hasOverflowClip(); + } + ++#if PLATFORM(IOS_FAMILY) + int RenderTextControl::innerLineHeight() const + { + auto innerText = innerTextElement(); +diff --git a/Source/WebCore/rendering/RenderTextControl.h b/Source/WebCore/rendering/RenderTextControl.h +index 69b193b1ff28bf2d0e58be6ae3152da8d9229a90..9b8327958cbc21e46a5720f558156b00e1c289a8 100644 +--- a/Source/WebCore/rendering/RenderTextControl.h ++++ b/Source/WebCore/rendering/RenderTextControl.h +@@ -36,9 +36,9 @@ public: + + WEBCORE_EXPORT HTMLTextFormControlElement& textFormControlElement() const; + +-#if PLATFORM(IOS_FAMILY) + bool canScroll() const; + ++#if PLATFORM(IOS_FAMILY) + // Returns the line height of the inner renderer. + int innerLineHeight() const override; + #endif +diff --git a/Source/WebCore/rendering/ScrollAlignment.h b/Source/WebCore/rendering/ScrollAlignment.h +index 694008e0451edc5770142a0a6d9eed52b04ded80..ec93869f9486bdf7bd3bb56478c62469d2fa58b6 100644 +--- a/Source/WebCore/rendering/ScrollAlignment.h ++++ b/Source/WebCore/rendering/ScrollAlignment.h +@@ -78,6 +78,7 @@ struct ScrollAlignment { + Behavior m_rectVisible; + Behavior m_rectHidden; + Behavior m_rectPartial; ++ bool m_disableMinThreshold = false; + }; + + WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, ScrollAlignment::Behavior); +diff --git a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp +index 84c913ad1c0a914ff6d4a97e69b152c4ebbc6808..0263674fef79d9e97d12e87c3cfd195646c1ffea 100644 +--- a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp ++++ b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp +@@ -73,6 +73,11 @@ + #include + #include + ++#if PLATFORM(COCOA) ++#include "NetworkDataTaskCocoa.h" ++#include "NetworkSessionCocoa.h" ++#endif ++ + #if ENABLE(APPLE_PAY_REMOTE_UI) + #include "WebPaymentCoordinatorProxyMessages.h" + #endif +@@ -866,6 +871,15 @@ void NetworkConnectionToWebProcess::clearPageSpecificData(PageIdentifier pageID) + #endif + } + ++void NetworkConnectionToWebProcess::setCookieFromResponse(NetworkResourceLoadParameters&& parameters, const URL& mainDocumentURL, const String& setCookieValue) ++{ ++ if (auto* session = networkSession()) { ++#if PLATFORM(COCOA) ++ NetworkDataTaskCocoa::setCookieFromResponse(*static_cast(session), WTFMove(parameters), mainDocumentURL, setCookieValue); ++#endif ++ } ++} ++ + #if ENABLE(RESOURCE_LOAD_STATISTICS) + void NetworkConnectionToWebProcess::removeStorageAccessForFrame(FrameIdentifier frameID, PageIdentifier pageID) + { +diff --git a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h +index 5a4b2b8937d2501312e9d7e19422291ebf2180f2..6ee414bbec95611286c721d8af7f27ecc139d8fd 100644 +--- a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h ++++ b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h +@@ -271,6 +271,8 @@ private: + + void clearPageSpecificData(WebCore::PageIdentifier); + ++ void setCookieFromResponse(NetworkResourceLoadParameters&&, const URL& mainDocumentURL, const String& setCookieValue); ++ + #if ENABLE(RESOURCE_LOAD_STATISTICS) + void removeStorageAccessForFrame(WebCore::FrameIdentifier, WebCore::PageIdentifier); + +diff --git a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in +index ff8d4a179f1fafd62b5d3fa64e99c208aa8fbf9a..c779fe10243bf2e5e3bd48f9833c9e2e7ecc07ae 100644 +--- a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in ++++ b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in +@@ -64,6 +64,8 @@ messages -> NetworkConnectionToWebProcess LegacyReceiver { + + ClearPageSpecificData(WebCore::PageIdentifier pageID); + ++ SetCookieFromResponse(WebKit::NetworkResourceLoadParameters parameters, URL mainDocumentURL, String setCookieValue); ++ + #if ENABLE(RESOURCE_LOAD_STATISTICS) + RemoveStorageAccessForFrame(WebCore::FrameIdentifier frameID, WebCore::PageIdentifier pageID); + LogUserInteraction(WebCore::RegistrableDomain domain) +diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.cpp b/Source/WebKit/NetworkProcess/NetworkProcess.cpp +index 0ea5fafa67e9a4d1b1e4e562de17621e1a7023ac..0a6b9cef4fe7cd0832634288e41cf084d7a8b7d7 100644 +--- a/Source/WebKit/NetworkProcess/NetworkProcess.cpp ++++ b/Source/WebKit/NetworkProcess/NetworkProcess.cpp +@@ -26,7 +26,6 @@ + + #include "config.h" + #include "NetworkProcess.h" +- + #include "ArgumentCoders.h" + #include "Attachment.h" + #include "AuthenticationManager.h" +@@ -552,6 +551,41 @@ void NetworkProcess::destroySession(PAL::SessionID sessionID) + #endif + } + ++void NetworkProcess::getAllCookies(PAL::SessionID sessionID, CompletionHandler&&)>&& completionHandler) ++{ ++ if (auto* networkStorageSession = storageSession(sessionID)) { ++ completionHandler(networkStorageSession->getAllCookies()); ++ return; ++ } ++ completionHandler({ }); ++} ++ ++void NetworkProcess::setCookies(PAL::SessionID sessionID, Vector cookies, CompletionHandler&& completionHandler) { ++ if (auto* networkStorageSession = storageSession(sessionID)) { ++ for (auto cookie : cookies) ++ networkStorageSession->setCookie(cookie); ++ completionHandler(true); ++ return; ++ } ++ completionHandler(false); ++} ++ ++void NetworkProcess::deleteAllCookies(PAL::SessionID sessionID, CompletionHandler&& completionHandler) ++{ ++ if (auto* networkStorageSession = storageSession(sessionID)) { ++ networkStorageSession->deleteAllCookies(); ++ completionHandler(true); ++ return; ++ } ++ completionHandler(false); ++} ++ ++void NetworkProcess::setIgnoreCertificateErrors(PAL::SessionID sessionID, bool ignore) ++{ ++ if (auto* networkSession = this->networkSession(sessionID)) ++ networkSession->setIgnoreCertificateErrors(ignore); ++} ++ + #if ENABLE(RESOURCE_LOAD_STATISTICS) + void NetworkProcess::dumpResourceLoadStatistics(PAL::SessionID sessionID, CompletionHandler&& completionHandler) + { +diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.h b/Source/WebKit/NetworkProcess/NetworkProcess.h +index 08322b42720df827eb5e3a038cf13811ccb67d79..887df3618b07688fa02574d0d8afe30d3206421e 100644 +--- a/Source/WebKit/NetworkProcess/NetworkProcess.h ++++ b/Source/WebKit/NetworkProcess/NetworkProcess.h +@@ -77,6 +77,7 @@ class SessionID; + + namespace WebCore { + class CertificateInfo; ++struct Cookie; + class CurlProxySettings; + class ProtectionSpace; + class StorageQuotaManager; +@@ -205,6 +206,11 @@ public: + + void addWebsiteDataStore(WebsiteDataStoreParameters&&); + ++ void getAllCookies(PAL::SessionID, CompletionHandler&&)>&&); ++ void setCookies(PAL::SessionID, Vector, CompletionHandler&&); ++ void deleteAllCookies(PAL::SessionID, CompletionHandler&&); ++ void setIgnoreCertificateErrors(PAL::SessionID, bool); ++ + #if ENABLE(RESOURCE_LOAD_STATISTICS) + void clearPrevalentResource(PAL::SessionID, const RegistrableDomain&, CompletionHandler&&); + void clearUserInteraction(PAL::SessionID, const RegistrableDomain&, CompletionHandler&&); +diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.messages.in b/Source/WebKit/NetworkProcess/NetworkProcess.messages.in +index c340befc0f0ffc65eed8e181cc696e788ca30e92..33b9e4486d1ee4df6cf9c0f994e4f55d7d325da3 100644 +--- a/Source/WebKit/NetworkProcess/NetworkProcess.messages.in ++++ b/Source/WebKit/NetworkProcess/NetworkProcess.messages.in +@@ -79,6 +79,11 @@ messages -> NetworkProcess LegacyReceiver { + + PreconnectTo(PAL::SessionID sessionID, WebKit::WebPageProxyIdentifier webPageProxyID, WebCore::PageIdentifier webPageID, URL url, String userAgent, enum:uint8_t WebCore::StoredCredentialsPolicy storedCredentialsPolicy, enum:bool Optional isNavigatingToAppBoundDomain, enum:bool WebKit::LastNavigationWasAppBound lastNavigationWasAppBound); + ++ GetAllCookies(PAL::SessionID sessionID) -> (Vector cookies) Async ++ SetCookies(PAL::SessionID sessionID, Vector cookies) -> (bool success) Async ++ DeleteAllCookies(PAL::SessionID sessionID) -> (bool success) Async ++ SetIgnoreCertificateErrors(PAL::SessionID sessionID, bool ignoreTLSErrors) ++ + #if ENABLE(RESOURCE_LOAD_STATISTICS) + ClearPrevalentResource(PAL::SessionID sessionID, WebCore::RegistrableDomain resourceDomain) -> () Async + ClearUserInteraction(PAL::SessionID sessionID, WebCore::RegistrableDomain resourceDomain) -> () Async +diff --git a/Source/WebKit/NetworkProcess/NetworkSession.h b/Source/WebKit/NetworkProcess/NetworkSession.h +index c8147ec822f92ecd45df0b39aa27967414d8f866..8c46cb2e3562857071dbc8d88b0f4c9dea4d8912 100644 +--- a/Source/WebKit/NetworkProcess/NetworkSession.h ++++ b/Source/WebKit/NetworkProcess/NetworkSession.h +@@ -150,6 +150,9 @@ public: + + bool isStaleWhileRevalidateEnabled() const { return m_isStaleWhileRevalidateEnabled; } + ++ void setIgnoreCertificateErrors(bool ignore) { m_ignoreCertificateErrors = ignore; } ++ bool ignoreCertificateErrors() { return m_ignoreCertificateErrors; } ++ + #if ENABLE(SERVICE_WORKER) + void addSoftUpdateLoader(std::unique_ptr&& loader) { m_softUpdateLoaders.add(WTFMove(loader)); } + void removeSoftUpdateLoader(ServiceWorkerSoftUpdateLoader* loader) { m_softUpdateLoaders.remove(loader); } +@@ -189,6 +192,7 @@ protected: + #endif + bool m_isStaleWhileRevalidateEnabled { false }; + std::unique_ptr m_privateClickMeasurement; ++ bool m_ignoreCertificateErrors { false }; + + HashSet> m_keptAliveLoads; + +diff --git a/Source/WebKit/NetworkProcess/NetworkSocketStream.cpp b/Source/WebKit/NetworkProcess/NetworkSocketStream.cpp +index 48c883bfc0fc7d501c8a4a4e7684ccc33e38c14d..20dedbbaf4b1a713c8be41e21425c3074e4e22ff 100644 +--- a/Source/WebKit/NetworkProcess/NetworkSocketStream.cpp ++++ b/Source/WebKit/NetworkProcess/NetworkSocketStream.cpp +@@ -43,7 +43,7 @@ Ref NetworkSocketStream::create(NetworkProcess& networkProc + NetworkSocketStream::NetworkSocketStream(NetworkProcess& networkProcess, URL&& url, PAL::SessionID sessionID, const String& credentialPartition, WebSocketIdentifier identifier, IPC::Connection& connection, SourceApplicationAuditToken&& auditData) + : m_identifier(identifier) + , m_connection(connection) +- , m_impl(SocketStreamHandleImpl::create(url, *this, sessionID, credentialPartition, WTFMove(auditData), NetworkStorageSessionProvider::create(networkProcess, sessionID).ptr())) ++ , m_impl(SocketStreamHandleImpl::create(url, networkProcess.networkSession(sessionID)->ignoreCertificateErrors(), *this, sessionID, credentialPartition, WTFMove(auditData), NetworkStorageSessionProvider::create(networkProcess, sessionID).ptr())) + , m_delayFailTimer(*this, &NetworkSocketStream::sendDelayedFailMessage) + { + } +diff --git a/Source/WebKit/NetworkProcess/cocoa/NetworkDataTaskCocoa.h b/Source/WebKit/NetworkProcess/cocoa/NetworkDataTaskCocoa.h +index 9d0d6395089dbbf22e899c93edaf9a1fd7045507..398396996ec4c346852044749e1f87f8be798957 100644 +--- a/Source/WebKit/NetworkProcess/cocoa/NetworkDataTaskCocoa.h ++++ b/Source/WebKit/NetworkProcess/cocoa/NetworkDataTaskCocoa.h +@@ -84,6 +84,8 @@ public: + void setH2PingCallback(const URL&, CompletionHandler&&)>&&) override; + void setPriority(WebCore::ResourceLoadPriority) override; + ++ static void setCookieFromResponse(NetworkSessionCocoa& session, const NetworkLoadParameters&, const URL& mainDocumentURL, const String& setCookieValue); ++ + private: + NetworkDataTaskCocoa(NetworkSession&, NetworkDataTaskClient&, const WebCore::ResourceRequest&, WebCore::FrameIdentifier, WebCore::PageIdentifier, WebCore::StoredCredentialsPolicy, WebCore::ContentSniffingPolicy, WebCore::ContentEncodingSniffingPolicy, bool shouldClearReferrerOnHTTPSToHTTPRedirect, PreconnectOnly, bool dataTaskIsForMainFrameNavigation, bool dataTaskIsForMainResourceNavigationForAnyFrame, Optional, Optional isNavigatingToAppBoundDomain, WebCore::ShouldRelaxThirdPartyCookieBlocking, Optional); + +diff --git a/Source/WebKit/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm b/Source/WebKit/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm +index f59442397c999ea224dd70da86e19aeebc569dbb..3e2330d76439bcd8ec0b53ddde96ddc5d38ca252 100644 +--- a/Source/WebKit/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm ++++ b/Source/WebKit/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm +@@ -41,6 +41,7 @@ + #import + #import + #import ++#import + #import + #import + #import +@@ -711,4 +712,59 @@ void NetworkDataTaskCocoa::setPriority(WebCore::ResourceLoadPriority priority) + m_task.get().priority = toNSURLSessionTaskPriority(priority); + } + ++class DummyNetworkDataTaskClient: public NetworkDataTaskClient { ++public: ++ void willPerformHTTPRedirection(WebCore::ResourceResponse&&, WebCore::ResourceRequest&&, RedirectCompletionHandler&&) final {} ++ void didReceiveChallenge(WebCore::AuthenticationChallenge&&, NegotiatedLegacyTLS, ChallengeCompletionHandler&&) final {} ++ void didReceiveResponse(WebCore::ResourceResponse&&, NegotiatedLegacyTLS, ResponseCompletionHandler&&) final {} ++ void didReceiveData(Ref&&) final {} ++ void didCompleteWithError(const WebCore::ResourceError&, const WebCore::NetworkLoadMetrics&) final {} ++ void didSendData(uint64_t totalBytesSent, uint64_t totalBytesExpectedToSend) final {} ++ void wasBlocked() final {} ++ void cannotShowURL() final {} ++ void wasBlockedByRestrictions() final {} ++ ~DummyNetworkDataTaskClient() {} ++}; ++ ++// static ++void NetworkDataTaskCocoa::setCookieFromResponse(NetworkSessionCocoa& networkSession, const NetworkLoadParameters& parameters, const URL& mainDocumentURL, const String& setCookieValue) ++{ ++ const URL& url = parameters.request.url(); ++ DummyNetworkDataTaskClient client; ++ RefPtr taskGeneric = NetworkDataTask::create(networkSession, client, parameters); ++ NetworkDataTaskCocoa* task = static_cast(taskGeneric.get()); ++ // Note: we are not calling task->resume(), and miss some logic from there. ++ ++ WebCore::ResourceResponse resourceResponse; ++ resourceResponse.setURL(url); ++ task->didReceiveResponse(WTFMove(resourceResponse), NegotiatedLegacyTLS::No, [](WebCore::PolicyAction policyAction) {}); ++ ++ if (task->m_hasBeenSetToUseStatelessCookieStorage || !task->m_sessionWrapper) { ++ task->cancel(); ++ return; ++ } ++ ++ NSURLSessionConfiguration* configuration = [task->m_sessionWrapper->session configuration]; ++ if (!configuration.HTTPCookieStorage) { ++ task->cancel(); ++ return; ++ } ++ ++ NSString* cookieString = (NSString *)setCookieValue; ++ NSString* cookieKey = @"Set-Cookie"; ++ NSDictionary* headers = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObject:cookieString] forKeys:[NSArray arrayWithObject:cookieKey]]; ++ NSArray* cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:headers forURL:(NSURL *)url]; ++ ++ NSURL* siteForCookies = task->m_task.get()._siteForCookies; ++ NSURL* documentURL = task->isTopLevelNavigation() ? siteForCookies : (NSURL *)mainDocumentURL; ++ if (siteForCookies && documentURL) { ++ // Both siteForCookies and/or documentURL may be nil, for example when one of them is about:blank. ++ BEGIN_BLOCK_OBJC_EXCEPTIONS ++ [configuration.HTTPCookieStorage setCookies:cookies forURL:siteForCookies mainDocumentURL:documentURL]; ++ END_BLOCK_OBJC_EXCEPTIONS ++ } ++ ++ task->cancel(); ++} ++ + } +diff --git a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm +index 9a164c133ce7c72dac5f98e7e3aa2bdfc419c243..b5a62e3ee30ab64cc9ecd68885f9da3343b75e29 100644 +--- a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm ++++ b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm +@@ -663,7 +663,7 @@ static inline void processServerTrustEvaluation(NetworkSessionCocoa& session, Se + NegotiatedLegacyTLS negotiatedLegacyTLS = NegotiatedLegacyTLS::No; + + if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { +- if (NetworkSessionCocoa::allowsSpecificHTTPSCertificateForHost(challenge)) ++ if (sessionCocoa->ignoreCertificateErrors() || sessionCocoa->allowsSpecificHTTPSCertificateForHost(challenge)) + return completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]); + + #if HAVE(TLS_PROTOCOL_VERSION_T) +@@ -930,6 +930,13 @@ static inline void processServerTrustEvaluation(NetworkSessionCocoa& session, Se + // NetworkLoadMetrics. For example, PerformanceTiming. + resourceResponse.setDeprecatedNetworkLoadMetrics(WebCore::copyTimingData([dataTask _timingData])); + ++ __block WebCore::HTTPHeaderMap requestHeaders; ++ NSURLSessionTaskTransactionMetrics *m = dataTask._incompleteTaskMetrics.transactionMetrics.lastObject; ++ [m.request.allHTTPHeaderFields enumerateKeysAndObjectsUsingBlock:^(NSString *name, NSString *value, BOOL *) { ++ requestHeaders.set(String(name), String(value)); ++ }]; ++ resourceResponse.m_httpRequestHeaderFields = WTFMove(requestHeaders); ++ + auto completionHandlerCopy = Block_copy(completionHandler); + networkDataTask->didReceiveResponse(WTFMove(resourceResponse), negotiatedLegacyTLS, [completionHandlerCopy, taskIdentifier](WebCore::PolicyAction policyAction) { + #if !LOG_DISABLED +diff --git a/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp b/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp +index 27f8ef54e561d6c3e812f8d4dc4cc133634fb4eb..a8a0c6fecd5f4fc816b02dccf276ed92573ad7b2 100644 +--- a/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp ++++ b/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp +@@ -26,9 +26,13 @@ + #include "config.h" + #include "NetworkDataTaskCurl.h" + ++#include "APIError.h" + #include "AuthenticationChallengeDisposition.h" + #include "AuthenticationManager.h" ++#include "DataReference.h" ++#include "Download.h" + #include "NetworkSessionCurl.h" ++#include "NetworkProcess.h" + #include + #include + #include +@@ -39,6 +43,8 @@ + #include + #include + #include ++#include ++#include + + namespace WebKit { + +@@ -78,6 +84,8 @@ NetworkDataTaskCurl::NetworkDataTaskCurl(NetworkSession& session, NetworkDataTas + m_curlRequest->setUserPass(m_initialCredential.user(), m_initialCredential.password()); + m_curlRequest->setAuthenticationScheme(ProtectionSpaceAuthenticationSchemeHTTPBasic); + } ++ if (m_session->ignoreCertificateErrors()) ++ m_curlRequest->disableServerTrustEvaluation(); + m_curlRequest->setStartTime(m_startTime); + m_curlRequest->start(); + } +@@ -152,6 +160,7 @@ void NetworkDataTaskCurl::curlDidReceiveResponse(CurlRequest& request, CurlRespo + m_response = ResourceResponse(receivedResponse); + m_response.setCertificateInfo(WTFMove(receivedResponse.certificateInfo)); + m_response.setDeprecatedNetworkLoadMetrics(Box::create(WTFMove(receivedResponse.networkLoadMetrics))); ++ m_response.m_httpRequestHeaderFields = request.resourceRequest().httpHeaderFields(); + + handleCookieHeaders(request.resourceRequest(), receivedResponse); + +@@ -179,7 +188,12 @@ void NetworkDataTaskCurl::curlDidReceiveBuffer(CurlRequest&, Ref&& + auto protectedThis = makeRef(*this); + if (state() == State::Canceling || state() == State::Completed || (!m_client && !isDownload())) + return; +- ++ if (isDownload()) { ++ FileSystem::PlatformFileHandle file = FileSystem::openFile(m_pendingDownloadLocation, FileSystem::FileOpenMode::Write); ++ FileSystem::writeToFile(file, buffer->data(), buffer->size()); ++ FileSystem::closeFile(file); ++ return; ++ } + m_client->didReceiveData(WTFMove(buffer)); + } + +@@ -188,6 +202,12 @@ void NetworkDataTaskCurl::curlDidComplete(CurlRequest&, NetworkLoadMetrics&& net + if (state() == State::Canceling || state() == State::Completed || (!m_client && !isDownload())) + return; + ++ if (isDownload()) { ++ auto* download = m_session->networkProcess().downloadManager().download(m_pendingDownloadID); ++ ASSERT(download); ++ download->didFinish(); ++ return; ++ } + m_client->didCompleteWithError({ }, WTFMove(networkLoadMetrics)); + } + +@@ -201,6 +221,13 @@ void NetworkDataTaskCurl::curlDidFailWithError(CurlRequest& request, ResourceErr + return; + } + ++ if (isDownload()) { ++ auto* download = m_session->networkProcess().downloadManager().download(m_pendingDownloadID); ++ ASSERT(download); ++ download->didFail(resourceError, IPC::DataReference()); ++ return; ++ } ++ + m_client->didCompleteWithError(resourceError); + } + +@@ -238,6 +265,18 @@ void NetworkDataTaskCurl::invokeDidReceiveResponse() + case PolicyAction::Ignore: + invalidateAndCancel(); + break; ++ case PolicyAction::Download: { ++ FileSystem::deleteFile(m_pendingDownloadLocation); ++ auto& downloadManager = m_session->networkProcess().downloadManager(); ++ auto download = makeUnique(downloadManager, m_pendingDownloadID, *this, *m_session, suggestedFilename()); ++ auto* downloadPtr = download.get(); ++ downloadManager.dataTaskBecameDownloadTask(m_pendingDownloadID, WTFMove(download)); ++ downloadPtr->didCreateDestination(m_pendingDownloadLocation); ++ ++ if (m_curlRequest) ++ m_curlRequest->completeDidReceiveResponse(); ++ break; ++ } + default: + notImplemented(); + break; +@@ -320,6 +359,8 @@ void NetworkDataTaskCurl::willPerformHTTPRedirection() + m_curlRequest->setUserPass(m_initialCredential.user(), m_initialCredential.password()); + m_curlRequest->setAuthenticationScheme(ProtectionSpaceAuthenticationSchemeHTTPBasic); + } ++ if (m_session->ignoreCertificateErrors()) ++ m_curlRequest->disableServerTrustEvaluation(); + m_curlRequest->setStartTime(m_startTime); + m_curlRequest->start(); + +@@ -503,4 +544,16 @@ bool NetworkDataTaskCurl::isThirdPartyRequest(const WebCore::ResourceRequest& re + return !WebCore::areRegistrableDomainsEqual(request.url(), request.firstPartyForCookies()); + } + ++String NetworkDataTaskCurl::suggestedFilename() const ++{ ++ if (!m_suggestedFilename.isEmpty()) ++ return m_suggestedFilename; ++ ++ String suggestedFilename = m_response.suggestedFilename(); ++ if (!suggestedFilename.isEmpty()) ++ return suggestedFilename; ++ ++ return decodeURLEscapeSequences(m_response.url().lastPathComponent()); ++} ++ + } // namespace WebKit +diff --git a/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.h b/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.h +index 4c120d6830582861432e5e58fba5707206350cd0..3509c62ac2c970fdcf78db2503c0cc4259f56dbd 100644 +--- a/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.h ++++ b/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.h +@@ -85,6 +85,7 @@ private: + + void appendCookieHeader(WebCore::ResourceRequest&); + void handleCookieHeaders(const WebCore::ResourceRequest&, const WebCore::CurlResponse&); ++ String suggestedFilename() const override; + + bool isThirdPartyRequest(const WebCore::ResourceRequest&); + bool shouldBlockCookies(const WebCore::ResourceRequest&); +diff --git a/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp b/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp +index 435980eb8eff1749afd65ea09941d257a0a9cfc1..69a63ca6d28ed9c569176c2058d7a0e86ae1b3e8 100644 +--- a/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp ++++ b/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp +@@ -404,6 +404,7 @@ void NetworkDataTaskSoup::didSendRequest(GRefPtr&& inputStream) + m_inputStream = WTFMove(inputStream); + + m_networkLoadMetrics.responseStart = MonotonicTime::now() - m_startTime; ++ m_response.m_httpRequestHeaderFields = m_networkLoadMetrics.requestHeaders; + dispatchDidReceiveResponse(); + } + +@@ -490,6 +491,8 @@ bool NetworkDataTaskSoup::acceptCertificate(GTlsCertificate* certificate, GTlsCe + { + ASSERT(m_soupMessage); + URL url = soupURIToURL(soup_message_get_uri(m_soupMessage.get())); ++ if (m_session->ignoreCertificateErrors()) ++ return true; + auto error = static_cast(*m_session).soupNetworkSession().checkTLSErrors(url, certificate, tlsErrors); + if (!error) + return true; +diff --git a/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp b/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp +index 6e973f518c176c589e426bd6f466b1a7552828d4..8df1134613da2d817147bc5db3d30f5d29d994fb 100644 +--- a/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp ++++ b/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp +@@ -113,6 +113,11 @@ static gboolean webSocketAcceptCertificateCallback(GTlsConnection* connection, G + return !session->soupNetworkSession().checkTLSErrors(soupURIToURL(soup_message_get_uri(soupMessage)), certificate, errors); + } + ++static gboolean webSocketAcceptCertificateCallbackIgnoreTLSErrors(GTlsConnection* connection, GTlsCertificate* certificate, GTlsCertificateFlags errors, NetworkSessionSoup* session) ++{ ++ return TRUE; ++} ++ + static void webSocketMessageNetworkEventCallback(SoupMessage* soupMessage, GSocketClientEvent event, GIOStream* connection, NetworkSessionSoup* session) + { + if (event != G_SOCKET_CLIENT_TLS_HANDSHAKING) +@@ -123,6 +128,15 @@ static void webSocketMessageNetworkEventCallback(SoupMessage* soupMessage, GSock + } + #endif + ++static void webSocketMessageNetworkEventCallbackIgnoreTLSErrors(SoupMessage* soupMessage, GSocketClientEvent event, GIOStream* connection) ++{ ++ if (event != G_SOCKET_CLIENT_TLS_HANDSHAKING) ++ return; ++ ++ g_object_set_data(G_OBJECT(connection), "wk-soup-message", soupMessage); ++ g_signal_connect(connection, "accept-certificate", G_CALLBACK(webSocketAcceptCertificateCallbackIgnoreTLSErrors), soupMessage); ++} ++ + std::unique_ptr NetworkSessionSoup::createWebSocketTask(NetworkSocketChannel& channel, const ResourceRequest& request, const String& protocol) + { + GRefPtr soupMessage = request.createSoupMessage(blobRegistry()); +@@ -131,14 +145,21 @@ std::unique_ptr NetworkSessionSoup::createWebSocketTask(NetworkSo + + if (request.url().protocolIs("wss")) { + #if USE(SOUP2) +- g_signal_connect(soupMessage.get(), "network-event", G_CALLBACK(webSocketMessageNetworkEventCallback), this); ++ if (ignoreCertificateErrors()) ++ g_signal_connect(soupMessage.get(), "network-event", G_CALLBACK(webSocketMessageNetworkEventCallbackIgnoreTLSErrors), this); ++ else ++ g_signal_connect(soupMessage.get(), "network-event", G_CALLBACK(webSocketMessageNetworkEventCallback), this); + #else +- g_signal_connect(soupMessage.get(), "accept-certificate", G_CALLBACK(+[](SoupMessage* message, GTlsCertificate* certificate, GTlsCertificateFlags errors, NetworkSessionSoup* session) -> gboolean { +- if (DeprecatedGlobalSettings::allowsAnySSLCertificate()) +- return TRUE; +- +- return !session->soupNetworkSession().checkTLSErrors(soup_message_get_uri(message), certificate, errors); +- }), this); ++ if (ignoreCertificateErrors()) { ++ g_signal_connect(soupMessage.get(), "accept-certificate", G_CALLBACK(webSocketAcceptCertificateCallbackIgnoreTLSErrors), this); ++ } else { ++ g_signal_connect(soupMessage.get(), "accept-certificate", G_CALLBACK(+[](SoupMessage* message, GTlsCertificate* certificate, GTlsCertificateFlags errors, NetworkSessionSoup* session) -> gboolean { ++ if (DeprecatedGlobalSettings::allowsAnySSLCertificate()) ++ return TRUE; ++ ++ return !session->soupNetworkSession().checkTLSErrors(soup_message_get_uri(message), certificate, errors); ++ }), this); ++ } + #endif + } + return makeUnique(channel, request, soupSession(), soupMessage.get(), protocol); +diff --git a/Source/WebKit/PlatformGTK.cmake b/Source/WebKit/PlatformGTK.cmake +index 9a8e0fa8978f6b2ae887853634a9ccd67d751871..24a81d0d0d1a7916ea1875c5490ec68bf84ac5c8 100644 +--- a/Source/WebKit/PlatformGTK.cmake ++++ b/Source/WebKit/PlatformGTK.cmake +@@ -462,6 +462,9 @@ list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES + ${GSTREAMER_PBUTILS_INCLUDE_DIRS} + ${GTK_INCLUDE_DIRS} + ${LIBSOUP_INCLUDE_DIRS} ++# Playwright begin ++ ${LIBVPX_INCLUDE_DIRS} ++# Playwright end + ) + + if (USE_WPE_RENDERER) +@@ -515,6 +518,9 @@ if (USE_LIBWEBRTC) + list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES + "${THIRDPARTY_DIR}/libwebrtc/Source/" + "${THIRDPARTY_DIR}/libwebrtc/Source/webrtc" ++# Playwright begin ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/include" ++# Playwright end + ) + endif () + +@@ -529,6 +535,12 @@ if (ENABLE_MEDIA_STREAM) + ) + endif () + ++# Playwright begin ++list(APPEND WebKit_PRIVATE_INCLUDE_DIRECTORIES ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libwebm" ++) ++# Playwright end ++ + # To generate WebKitEnumTypes.h we want to use all installed headers, except WebKitEnumTypes.h itself. + set(WebKit2GTK_ENUM_GENERATION_HEADERS ${WebKit2GTK_INSTALLED_HEADERS}) + list(REMOVE_ITEM WebKit2GTK_ENUM_GENERATION_HEADERS ${DERIVED_SOURCES_WEBKIT2GTK_API_DIR}/WebKitEnumTypes.h) +diff --git a/Source/WebKit/PlatformWPE.cmake b/Source/WebKit/PlatformWPE.cmake +index a09a2f7b33b6a157b35eff41f5cbbc728255f4ed..614105c2c3d6463f7585c36cd53c9618d98cc9ed 100644 +--- a/Source/WebKit/PlatformWPE.cmake ++++ b/Source/WebKit/PlatformWPE.cmake +@@ -283,6 +283,7 @@ list(APPEND WebKit_INCLUDE_DIRECTORIES + "${WEBKIT_DIR}/UIProcess/API/wpe" + "${WEBKIT_DIR}/UIProcess/CoordinatedGraphics" + "${WEBKIT_DIR}/UIProcess/geoclue" ++ "${WEBKIT_DIR}/UIProcess/glib" + "${WEBKIT_DIR}/UIProcess/gstreamer" + "${WEBKIT_DIR}/UIProcess/linux" + "${WEBKIT_DIR}/UIProcess/soup" +@@ -308,8 +309,17 @@ list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES + ${GIO_UNIX_INCLUDE_DIRS} + ${GLIB_INCLUDE_DIRS} + ${LIBSOUP_INCLUDE_DIRS} ++# Playwright begin ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/include" ++# Playwright end + ) + ++# Playwright begin ++list(APPEND WebKit_PRIVATE_INCLUDE_DIRECTORIES ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libwebm" ++) ++# Playwright end ++ + list(APPEND WebKit_LIBRARIES + Cairo::Cairo + Freetype::Freetype +diff --git a/Source/WebKit/PlatformWin.cmake b/Source/WebKit/PlatformWin.cmake +index 03af565ed1ae39e77e183a4aebd1e64a2e247e0a..7bf35d77e8989d50bfb81b67909b6c828cf50dde 100644 +--- a/Source/WebKit/PlatformWin.cmake ++++ b/Source/WebKit/PlatformWin.cmake +@@ -65,8 +65,12 @@ list(APPEND WebKit_SOURCES + + UIProcess/WebsiteData/win/WebsiteDataStoreWin.cpp + ++ UIProcess/win/InspectorTargetProxyWin.cpp ++ UIProcess/win/InspectorPlaywrightAgentClientWin.cpp + UIProcess/win/PageClientImpl.cpp + UIProcess/win/WebContextMenuProxyWin.cpp ++ UIProcess/win/WebPageInspectorEmulationAgentWin.cpp ++ UIProcess/win/WebPageInspectorInputAgentWin.cpp + UIProcess/win/WebPageProxyWin.cpp + UIProcess/win/WebPopupMenuProxyWin.cpp + UIProcess/win/WebProcessPoolWin.cpp +@@ -84,6 +88,7 @@ list(APPEND WebKit_SOURCES + WebProcess/Plugins/Netscape/win/PluginProxyWin.cpp + + WebProcess/WebCoreSupport/win/WebPopupMenuWin.cpp ++ WebProcess/WebCoreSupport/win/WebDragClientWin.cpp + + WebProcess/WebPage/AcceleratedSurface.cpp + +@@ -125,6 +130,63 @@ list(APPEND WebKit_INCLUDE_DIRECTORIES + "${WEBKIT_DIR}/win" + ) + ++# Playwright begin ++list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/include" ++ "${LIBVPX_CUSTOM_INCLUDE_DIR}" ++) ++ ++list(APPEND WebKit_PRIVATE_INCLUDE_DIRECTORIES ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libwebm" ++) ++ ++list(APPEND WebKit_SOURCES ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libwebm/mkvmuxer/mkvmuxer.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libwebm/mkvmuxer/mkvmuxerutil.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libwebm/mkvmuxer/mkvwriter.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_common.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_gcc.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_win.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_argb.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_from.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_from_argb.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_jpeg.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_to_argb.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_to_i420.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/cpu_id.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/mjpeg_decoder.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/mjpeg_validate.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/planar_functions.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_neon.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_neon64.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_any.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_argb.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_common.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_gcc.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_neon.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_neon64.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_win.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_any.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_common.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_gcc.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_neon.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_neon64.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_win.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_any.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_argb.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_common.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_gcc.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_neon.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_neon64.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_win.cc" ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/video_common.cc" ++) ++# Playwright end ++ + set(WebKitCommonIncludeDirectories ${WebKit_INCLUDE_DIRECTORIES}) + set(WebKitCommonSystemIncludeDirectories ${WebKit_SYSTEM_INCLUDE_DIRECTORIES}) + +@@ -177,6 +239,7 @@ if (${WTF_PLATFORM_WIN_CAIRO}) + OpenSSL::SSL + mfuuid.lib + strmiids.lib ++ ${LIBVPX_CUSTOM_LIBRARY} + ) + endif () + +diff --git a/Source/WebKit/Shared/API/c/wpe/WebKit.h b/Source/WebKit/Shared/API/c/wpe/WebKit.h +index 898e30b370db8176e886fbbde0cd960e38a64818..74945e06fac0eb14936578de6a599a123364a63a 100644 +--- a/Source/WebKit/Shared/API/c/wpe/WebKit.h ++++ b/Source/WebKit/Shared/API/c/wpe/WebKit.h +@@ -78,6 +78,7 @@ + // From Source/WebKit/UIProcess/API/C + #include + #include ++#include + #include + #include + #include +diff --git a/Source/WebKit/Shared/NativeWebKeyboardEvent.h b/Source/WebKit/Shared/NativeWebKeyboardEvent.h +index fd2b55f40fdd3d82d6d6947dc33ad31f24f4c1c7..bb1487b1efcbab2fd7ccf79a50eae99ecf4b4cab 100644 +--- a/Source/WebKit/Shared/NativeWebKeyboardEvent.h ++++ b/Source/WebKit/Shared/NativeWebKeyboardEvent.h +@@ -33,6 +33,7 @@ + #if USE(APPKIT) + #include + OBJC_CLASS NSView; ++OBJC_CLASS NSEvent; + #endif + + #if PLATFORM(GTK) +@@ -65,19 +66,35 @@ public: + #if USE(APPKIT) + // FIXME: Share iOS's HandledByInputMethod enum here instead of passing a boolean. + NativeWebKeyboardEvent(NSEvent *, bool handledByInputMethod, bool replacesSoftSpace, const Vector&); ++ NativeWebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, WallTime timestamp, Vector&& commands) ++ : WebKeyboardEvent(type, text, unmodifiedText, key, code, keyIdentifier, windowsVirtualKeyCode, nativeVirtualKeyCode, isAutoRepeat, isKeypad, isSystemKey, modifiers, timestamp, WTFMove(commands)) ++ { ++ } + #elif PLATFORM(GTK) + NativeWebKeyboardEvent(const NativeWebKeyboardEvent&); + NativeWebKeyboardEvent(GdkEvent*, const String&, Vector&& commands); + NativeWebKeyboardEvent(const String&, Optional>&&, Optional&&); + NativeWebKeyboardEvent(Type, const String& text, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, Vector&& commands, bool isKeypad, OptionSet); ++ NativeWebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, WallTime timestamp, Vector&& commands) ++ : WebKeyboardEvent(type, text, unmodifiedText, key, code, keyIdentifier, windowsVirtualKeyCode, nativeVirtualKeyCode, isAutoRepeat, isKeypad, isSystemKey, modifiers, timestamp, WTFMove(commands)) ++ { ++ } + #elif PLATFORM(IOS_FAMILY) + enum class HandledByInputMethod : bool { No, Yes }; + NativeWebKeyboardEvent(::WebEvent *, HandledByInputMethod); + #elif USE(LIBWPE) + enum class HandledByInputMethod : bool { No, Yes }; + NativeWebKeyboardEvent(struct wpe_input_keyboard_event*, const String&, HandledByInputMethod, Optional>&&, Optional&&); ++ NativeWebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, WallTime timestamp) ++ : WebKeyboardEvent(type, text, unmodifiedText, key, code, keyIdentifier, windowsVirtualKeyCode, nativeVirtualKeyCode, isAutoRepeat, isKeypad, isSystemKey, modifiers, timestamp) ++ { ++ } + #elif PLATFORM(WIN) + NativeWebKeyboardEvent(HWND, UINT message, WPARAM, LPARAM, Vector&& pendingCharEvents); ++ NativeWebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, WallTime timestamp) ++ : WebKeyboardEvent(type, text, unmodifiedText, key, code, keyIdentifier, windowsVirtualKeyCode, nativeVirtualKeyCode, isAutoRepeat, isKeypad, isSystemKey, modifiers, timestamp) ++ { ++ } + #endif + + #if USE(APPKIT) +diff --git a/Source/WebKit/Shared/NativeWebMouseEvent.h b/Source/WebKit/Shared/NativeWebMouseEvent.h +index b838fca9702c1432602176bb13ef052db224e82e..d802e555369176e74b37495ae924b04e515b144c 100644 +--- a/Source/WebKit/Shared/NativeWebMouseEvent.h ++++ b/Source/WebKit/Shared/NativeWebMouseEvent.h +@@ -77,6 +77,11 @@ public: + NativeWebMouseEvent(HWND, UINT message, WPARAM, LPARAM, bool); + #endif + ++#if PLATFORM(GTK) || USE(LIBWPE) || PLATFORM(WIN) ++ NativeWebMouseEvent(Type type, Button button, unsigned short buttons, const WebCore::IntPoint& position, const WebCore::IntPoint& globalPosition, float deltaX, float deltaY, float deltaZ, int clickCount, OptionSet modifiers, WallTime timestamp) ++ : WebMouseEvent(type, button, buttons, position, globalPosition, deltaX, deltaY, deltaZ, clickCount, modifiers, timestamp) { } ++#endif ++ + #if USE(APPKIT) + NSEvent* nativeEvent() const { return m_nativeEvent.get(); } + #elif PLATFORM(GTK) +diff --git a/Source/WebKit/Shared/WebCoreArgumentCoders.cpp b/Source/WebKit/Shared/WebCoreArgumentCoders.cpp +index 611f4624dbb8961a9aad173e56e755aaf4390195..bd4f11d3e8097f2ee3616cf785b2fa2c6e090167 100644 +--- a/Source/WebKit/Shared/WebCoreArgumentCoders.cpp ++++ b/Source/WebKit/Shared/WebCoreArgumentCoders.cpp +@@ -113,6 +113,10 @@ + #include + #endif + ++#if PLATFORM(WPE) ++#include "ArgumentCodersWPE.h" ++#endif ++ + // FIXME: Seems like we could use std::tuple to cut down the code below a lot! + + namespace IPC { +@@ -651,7 +655,7 @@ bool ArgumentCoder::decode(Decoder& decoder, FloatBoxExtent& flo + { + return SimpleArgumentCoder::decode(decoder, floatBoxExtent); + } +- ++ + + void ArgumentCoder::encode(Encoder& encoder, const FloatSize& floatSize) + { +@@ -1366,6 +1370,9 @@ void ArgumentCoder::encode(Encoder& encoder, const WindowFeature + encoder << windowFeatures.resizable; + encoder << windowFeatures.fullscreen; + encoder << windowFeatures.dialog; ++ encoder << windowFeatures.noopener; ++ encoder << windowFeatures.noreferrer; ++ encoder << windowFeatures.additionalFeatures; + } + + bool ArgumentCoder::decode(Decoder& decoder, WindowFeatures& windowFeatures) +@@ -1394,6 +1401,12 @@ bool ArgumentCoder::decode(Decoder& decoder, WindowFeatures& win + return false; + if (!decoder.decode(windowFeatures.dialog)) + return false; ++ if (!decoder.decode(windowFeatures.noopener)) ++ return false; ++ if (!decoder.decode(windowFeatures.noreferrer)) ++ return false; ++ if (!decoder.decode(windowFeatures.additionalFeatures)) ++ return false; + return true; + } + +@@ -1407,6 +1420,11 @@ void ArgumentCoder::encode(Encoder& encoder, const DragData& dragData) + #if PLATFORM(COCOA) + encoder << dragData.pasteboardName(); + encoder << dragData.fileNames(); ++#endif ++#if PLATFORM(WIN) ++ DragData dragDataCopy = dragData; ++ HashMap> hash = dragDataCopy.dragDataMap(); ++ encoder << hash; + #endif + encoder << dragData.dragDestinationActionMask(); + encoder << dragData.pageID(); +@@ -1430,9 +1448,16 @@ bool ArgumentCoder::decode(Decoder& decoder, DragData& dragData) + if (!decoder.decode(applicationFlags)) + return false; + ++#if PLATFORM(WIN) ++ DragDataMap dragDataMap; ++ if (!decoder.decode(dragDataMap)) ++ return false; ++#else + String pasteboardName; +- Vector fileNames; ++#endif ++ + #if PLATFORM(COCOA) ++ Vector fileNames; + if (!decoder.decode(pasteboardName)) + return false; + +@@ -1448,8 +1473,14 @@ bool ArgumentCoder::decode(Decoder& decoder, DragData& dragData) + if (!decoder.decode(pageID)) + return false; + ++#if PLATFORM(WIN) ++ dragData = DragData(dragDataMap, clientPosition, globalPosition, draggingSourceOperationMask, applicationFlags, pageID); ++#else + dragData = DragData(pasteboardName, clientPosition, globalPosition, draggingSourceOperationMask, applicationFlags, dragDestinationActionMask, pageID); ++#endif ++#if PLATFORM(COCOA) + dragData.setFileNames(fileNames); ++#endif + + return true; + } +diff --git a/Source/WebKit/Shared/WebEvent.h b/Source/WebKit/Shared/WebEvent.h +index 3ae6504779d3917a79f69f32b58260afeda270b4..72d44c33953cc13bf2ed7c762b4f9a7b88571b56 100644 +--- a/Source/WebKit/Shared/WebEvent.h ++++ b/Source/WebKit/Shared/WebEvent.h +@@ -31,6 +31,7 @@ + + #include + #include ++#include + #include + #include + +diff --git a/Source/WebKit/Shared/WebKeyboardEvent.cpp b/Source/WebKit/Shared/WebKeyboardEvent.cpp +index bc4322286484e6afdd49353fae6a8fb3cd5e66f2..7af88c4e93f6a0ea61dd107699c04c0695f7842f 100644 +--- a/Source/WebKit/Shared/WebKeyboardEvent.cpp ++++ b/Source/WebKit/Shared/WebKeyboardEvent.cpp +@@ -35,6 +35,7 @@ WebKeyboardEvent::WebKeyboardEvent() + { + } + ++ + #if USE(APPKIT) + + WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool handledByInputMethod, const Vector& commands, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, WallTime timestamp) +@@ -56,6 +57,24 @@ WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& + ASSERT(isKeyboardEventType(type)); + } + ++WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, WallTime timestamp, Vector&& commands) ++ : WebEvent(type, modifiers, timestamp) ++ , m_text(text) ++ , m_unmodifiedText(text) ++ , m_key(key) ++ , m_code(code) ++ , m_keyIdentifier(keyIdentifier) ++ , m_windowsVirtualKeyCode(windowsVirtualKeyCode) ++ , m_nativeVirtualKeyCode(nativeVirtualKeyCode) ++ , m_macCharCode(0) ++ , m_commands(WTFMove(commands)) ++ , m_isAutoRepeat(isAutoRepeat) ++ , m_isKeypad(isKeypad) ++ , m_isSystemKey(isSystemKey) ++{ ++ ASSERT(isKeyboardEventType(type)); ++} ++ + #elif PLATFORM(GTK) + + WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool handledByInputMethod, Optional>&& preeditUnderlines, Optional&& preeditSelectionRange, Vector&& commands, bool isKeypad, OptionSet modifiers, WallTime timestamp) +@@ -79,6 +98,24 @@ WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& + ASSERT(isKeyboardEventType(type)); + } + ++WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, WallTime timestamp, Vector&& commands) ++ : WebEvent(type, modifiers, timestamp) ++ , m_text(text) ++ , m_unmodifiedText(text) ++ , m_key(key) ++ , m_code(code) ++ , m_keyIdentifier(keyIdentifier) ++ , m_windowsVirtualKeyCode(windowsVirtualKeyCode) ++ , m_nativeVirtualKeyCode(nativeVirtualKeyCode) ++ , m_macCharCode(0) ++ , m_commands(WTFMove(commands)) ++ , m_isAutoRepeat(isAutoRepeat) ++ , m_isKeypad(isKeypad) ++ , m_isSystemKey(isSystemKey) ++{ ++ ASSERT(isKeyboardEventType(type)); ++} ++ + #elif PLATFORM(IOS_FAMILY) + + WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool handledByInputMethod, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, WallTime timestamp) +@@ -144,6 +181,27 @@ WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& + + #endif + ++#if PLATFORM(WIN) || USE(LIBWPE) ++ ++WebKeyboardEvent::WebKeyboardEvent(Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, WallTime timestamp) ++ : WebEvent(type, modifiers, timestamp) ++ , m_text(text) ++ , m_unmodifiedText(text) ++ , m_key(key) ++ , m_code(code) ++ , m_keyIdentifier(keyIdentifier) ++ , m_windowsVirtualKeyCode(windowsVirtualKeyCode) ++ , m_nativeVirtualKeyCode(nativeVirtualKeyCode) ++ , m_macCharCode(0) ++ , m_isAutoRepeat(isAutoRepeat) ++ , m_isKeypad(isKeypad) ++ , m_isSystemKey(isSystemKey) ++{ ++ ASSERT(isKeyboardEventType(type)); ++} ++ ++#endif ++ + WebKeyboardEvent::~WebKeyboardEvent() + { + } +diff --git a/Source/WebKit/Shared/WebKeyboardEvent.h b/Source/WebKit/Shared/WebKeyboardEvent.h +index cb8029dc46dc2531f5cc23409dc6d2f11d5a3b49..a0e673b9680b0013d56920e525f358e333b06b0b 100644 +--- a/Source/WebKit/Shared/WebKeyboardEvent.h ++++ b/Source/WebKit/Shared/WebKeyboardEvent.h +@@ -43,14 +43,18 @@ public: + + #if USE(APPKIT) + WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool handledByInputMethod, const Vector&, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet, WallTime timestamp); ++ WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet, WallTime timestamp, Vector&& commands); + #elif PLATFORM(GTK) + WebKeyboardEvent(Type, const String& text, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool handledByInputMethod, Optional>&&, Optional&&, Vector&& commands, bool isKeypad, OptionSet, WallTime timestamp); ++ WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet, WallTime timestamp, Vector&& commands); + #elif PLATFORM(IOS_FAMILY) + WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool handledByInputMethod, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet, WallTime timestamp); + #elif USE(LIBWPE) + WebKeyboardEvent(Type, const String& text, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool handledByInputMethod, Optional>&&, Optional&&, bool isKeypad, OptionSet, WallTime timestamp); ++ WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet, WallTime timestamp); + #else + WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet, WallTime timestamp); ++ WebKeyboardEvent(Type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet, WallTime timestamp); + #endif + + const String& text() const { return m_text; } +diff --git a/Source/WebKit/Shared/WebPageCreationParameters.cpp b/Source/WebKit/Shared/WebPageCreationParameters.cpp +index ed4bd87a4022b15f9cf80ba69967ce52d40963d8..b615351011fa728beac4f6d097947598183c2df3 100644 +--- a/Source/WebKit/Shared/WebPageCreationParameters.cpp ++++ b/Source/WebKit/Shared/WebPageCreationParameters.cpp +@@ -156,6 +156,8 @@ void WebPageCreationParameters::encode(IPC::Encoder& encoder) const + encoder << crossOriginAccessControlCheckEnabled; + encoder << processDisplayName; + ++ encoder << shouldPauseInInspectorWhenShown; ++ + encoder << shouldCaptureAudioInUIProcess; + encoder << shouldCaptureAudioInGPUProcess; + encoder << shouldCaptureVideoInUIProcess; +@@ -529,7 +531,10 @@ Optional WebPageCreationParameters::decode(IPC::Decod + if (!processDisplayName) + return WTF::nullopt; + parameters.processDisplayName = WTFMove(*processDisplayName); +- ++ ++ if (!decoder.decode(parameters.shouldPauseInInspectorWhenShown)) ++ return WTF::nullopt; ++ + if (!decoder.decode(parameters.shouldCaptureAudioInUIProcess)) + return WTF::nullopt; + +diff --git a/Source/WebKit/Shared/WebPageCreationParameters.h b/Source/WebKit/Shared/WebPageCreationParameters.h +index 033091f6db76d63a9a47860973ee2188f382711f..8dbf026692bb597b29a5aaba7f52247dbde2aa51 100644 +--- a/Source/WebKit/Shared/WebPageCreationParameters.h ++++ b/Source/WebKit/Shared/WebPageCreationParameters.h +@@ -250,6 +250,8 @@ struct WebPageCreationParameters { + + WebCore::ShouldRelaxThirdPartyCookieBlocking shouldRelaxThirdPartyCookieBlocking { WebCore::ShouldRelaxThirdPartyCookieBlocking::No }; + ++ bool shouldPauseInInspectorWhenShown { false }; ++ + #if PLATFORM(GTK) + String themeName; + #endif +diff --git a/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp b/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp +index c76a9e1f7dae7a31c4048d8f00d849a18ebaff23..1cfd9c7acb69dea69783c42b3f427929509782a4 100644 +--- a/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp ++++ b/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp +@@ -50,7 +50,7 @@ NativeWebKeyboardEvent::NativeWebKeyboardEvent(Type type, const String& text, co + } + + NativeWebKeyboardEvent::NativeWebKeyboardEvent(const NativeWebKeyboardEvent& event) +- : WebKeyboardEvent(event.type(), event.text(), event.key(), event.code(), event.keyIdentifier(), event.windowsVirtualKeyCode(), event.nativeVirtualKeyCode(), event.handledByInputMethod(), Optional>(event.preeditUnderlines()), Optional(event.preeditSelectionRange()), Vector(event.commands()), event.isKeypad(), event.modifiers(), event.timestamp()) ++ : WebKeyboardEvent(event) + , m_nativeEvent(event.nativeEvent() ? gdk_event_copy(event.nativeEvent()) : nullptr) + { + } +diff --git a/Source/WebKit/Shared/gtk/NativeWebMouseEventGtk.cpp b/Source/WebKit/Shared/gtk/NativeWebMouseEventGtk.cpp +index 46ef3b371f52c105451d917ff8fd384db518b39f..c64066b40d09c6b0605ad1895e3af1215288b3e4 100644 +--- a/Source/WebKit/Shared/gtk/NativeWebMouseEventGtk.cpp ++++ b/Source/WebKit/Shared/gtk/NativeWebMouseEventGtk.cpp +@@ -54,7 +54,7 @@ NativeWebMouseEvent::NativeWebMouseEvent(Type type, Button button, unsigned shor + } + + NativeWebMouseEvent::NativeWebMouseEvent(const NativeWebMouseEvent& event) +- : WebMouseEvent(event.type(), event.button(), event.buttons(), event.position(), event.globalPosition(), event.deltaX(), event.deltaY(), event.deltaZ(), event.clickCount(), event.modifiers(), event.timestamp(), 0, NoTap, event.pointerId(), event.pointerType()) ++ : WebMouseEvent(event) + , m_nativeEvent(event.nativeEvent() ? gdk_event_copy(const_cast(event.nativeEvent())) : nullptr) + { + } +diff --git a/Source/WebKit/Shared/ios/WebPlatformTouchPointIOS.cpp b/Source/WebKit/Shared/ios/WebPlatformTouchPointIOS.cpp +index 2a9db4f8acafe9d64d5d4ebd9913aa161ea0f4c0..f151ef4e8e6abb5e3044771c235139d48e8aa7cf 100644 +--- a/Source/WebKit/Shared/ios/WebPlatformTouchPointIOS.cpp ++++ b/Source/WebKit/Shared/ios/WebPlatformTouchPointIOS.cpp +@@ -26,7 +26,7 @@ + #include "config.h" + #include "WebTouchEvent.h" + +-#if ENABLE(TOUCH_EVENTS) ++#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY) + + #include "WebCoreArgumentCoders.h" + +@@ -79,4 +79,4 @@ Optional WebPlatformTouchPoint::decode(IPC::Decoder& deco + + } // namespace WebKit + +-#endif // ENABLE(TOUCH_EVENTS) ++#endif // ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY) +diff --git a/Source/WebKit/Shared/ios/WebTouchEventIOS.cpp b/Source/WebKit/Shared/ios/WebTouchEventIOS.cpp +index e40a6e172bfd2b75076fd4053da643ebab9eb81f..2516655bbc9e5bc863537a554c5faac0f6fc1a09 100644 +--- a/Source/WebKit/Shared/ios/WebTouchEventIOS.cpp ++++ b/Source/WebKit/Shared/ios/WebTouchEventIOS.cpp +@@ -26,7 +26,7 @@ + #include "config.h" + #include "WebTouchEvent.h" + +-#if ENABLE(TOUCH_EVENTS) ++#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY) + + #include "ArgumentCoders.h" + #include "WebCoreArgumentCoders.h" +@@ -71,4 +71,4 @@ bool WebTouchEvent::decode(IPC::Decoder& decoder, WebTouchEvent& result) + + } // namespace WebKit + +-#endif // ENABLE(TOUCH_EVENTS) ++#endif // ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY) +diff --git a/Source/WebKit/Shared/libwpe/ArgumentCodersWPE.cpp b/Source/WebKit/Shared/libwpe/ArgumentCodersWPE.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..0aa4440ac795d2068f0ec89e6cd62205dcd3e537 +--- /dev/null ++++ b/Source/WebKit/Shared/libwpe/ArgumentCodersWPE.cpp +@@ -0,0 +1,173 @@ ++/* ++ * 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. ++ * ++ * 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 "ArgumentCodersWPE.h" ++ ++#include "DataReference.h" ++#include "ShareableBitmap.h" ++#include "WebCoreArgumentCoders.h" ++#include ++#include ++#include ++ ++namespace IPC { ++using namespace WebCore; ++using namespace WebKit; ++ ++static void encodeImage(Encoder& encoder, Image& image) ++{ ++ RefPtr bitmap = ShareableBitmap::createShareable(IntSize(image.size()), { }); ++ bitmap->createGraphicsContext()->drawImage(image, IntPoint()); ++ ++ ShareableBitmap::Handle handle; ++ bitmap->createHandle(handle); ++ ++ encoder << handle; ++} ++ ++static WARN_UNUSED_RETURN bool decodeImage(Decoder& decoder, RefPtr& image) ++{ ++ ShareableBitmap::Handle handle; ++ if (!decoder.decode(handle)) ++ return false; ++ ++ RefPtr bitmap = ShareableBitmap::create(handle); ++ if (!bitmap) ++ return false; ++ image = bitmap->createImage(); ++ if (!image) ++ return false; ++ return true; ++} ++ ++void ArgumentCoder::encode(Encoder& encoder, const SelectionData& selection) ++{ ++ bool hasText = selection.hasText(); ++ encoder << hasText; ++ if (hasText) ++ encoder << selection.text(); ++ bool hasMarkup = selection.hasMarkup(); ++ encoder << hasMarkup; ++ if (hasMarkup) ++ encoder << selection.markup(); ++ ++ bool hasURL = selection.hasURL(); ++ encoder << hasURL; ++ if (hasURL) ++ encoder << selection.url().string(); ++ ++ bool hasURIList = selection.hasURIList(); ++ encoder << hasURIList; ++ if (hasURIList) ++ encoder << selection.uriList(); ++ ++ bool hasImage = selection.hasImage(); ++ encoder << hasImage; ++ if (hasImage) ++ encodeImage(encoder, *selection.image()); ++ ++ bool hasCustomData = selection.hasCustomData(); ++ encoder << hasCustomData; ++ if (hasCustomData) ++ encoder << RefPtr(selection.customData()); ++ ++ bool canSmartReplace = selection.canSmartReplace(); ++ encoder << canSmartReplace; ++} ++ ++Optional ArgumentCoder::decode(Decoder& decoder) ++{ ++ SelectionData selection; ++ ++ bool hasText; ++ if (!decoder.decode(hasText)) ++ return WTF::nullopt; ++ if (hasText) { ++ String text; ++ if (!decoder.decode(text)) ++ return WTF::nullopt; ++ selection.setText(text); ++ } ++ ++ bool hasMarkup; ++ if (!decoder.decode(hasMarkup)) ++ return WTF::nullopt; ++ if (hasMarkup) { ++ String markup; ++ if (!decoder.decode(markup)) ++ return WTF::nullopt; ++ selection.setMarkup(markup); ++ } ++ ++ bool hasURL; ++ if (!decoder.decode(hasURL)) ++ return WTF::nullopt; ++ if (hasURL) { ++ String url; ++ if (!decoder.decode(url)) ++ return WTF::nullopt; ++ selection.setURL(URL(URL(), url), String()); ++ } ++ ++ bool hasURIList; ++ if (!decoder.decode(hasURIList)) ++ return WTF::nullopt; ++ if (hasURIList) { ++ String uriList; ++ if (!decoder.decode(uriList)) ++ return WTF::nullopt; ++ selection.setURIList(uriList); ++ } ++ ++ bool hasImage; ++ if (!decoder.decode(hasImage)) ++ return WTF::nullopt; ++ if (hasImage) { ++ RefPtr image; ++ if (!decodeImage(decoder, image)) ++ return WTF::nullopt; ++ selection.setImage(image.get()); ++ } ++ ++ bool hasCustomData; ++ if (!decoder.decode(hasCustomData)) ++ return WTF::nullopt; ++ if (hasCustomData) { ++ RefPtr buffer; ++ if (!decoder.decode(buffer)) ++ return WTF::nullopt; ++ selection.setCustomData(Ref(*buffer)); ++ } ++ ++ bool canSmartReplace; ++ if (!decoder.decode(canSmartReplace)) ++ return WTF::nullopt; ++ selection.setCanSmartReplace(canSmartReplace); ++ ++ return selection; ++} ++ ++} +diff --git a/Source/WebKit/Shared/libwpe/ArgumentCodersWPE.h b/Source/WebKit/Shared/libwpe/ArgumentCodersWPE.h +new file mode 100644 +index 0000000000000000000000000000000000000000..c5099cd4b6be31769e6344677625b0a1f7ee42a5 +--- /dev/null ++++ b/Source/WebKit/Shared/libwpe/ArgumentCodersWPE.h +@@ -0,0 +1,41 @@ ++/* ++ * 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. ++ * ++ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ++ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS ++ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF ++ * THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#pragma once ++ ++#include "ArgumentCoders.h" ++ ++namespace WebCore { ++class SelectionData; ++} ++ ++namespace IPC { ++ ++template<> struct ArgumentCoder { ++ static void encode(Encoder&, const WebCore::SelectionData&); ++ static Optional decode(Decoder&); ++}; ++ ++} // namespace IPC +diff --git a/Source/WebKit/Shared/win/WebEventFactory.cpp b/Source/WebKit/Shared/win/WebEventFactory.cpp +index 88d53d236cd6d62735f03678a04ca9c198dddacb..b8f8efc57ab00dc5725660c5a8ad56a3e6384de5 100644 +--- a/Source/WebKit/Shared/win/WebEventFactory.cpp ++++ b/Source/WebKit/Shared/win/WebEventFactory.cpp +@@ -473,7 +473,7 @@ WebKeyboardEvent WebEventFactory::createWebKeyboardEvent(HWND hwnd, UINT message + } + + #if ENABLE(TOUCH_EVENTS) +-WebTouchEvent WebEventFactory::createWebTouchEvent(const GdkEvent* event, Vector&& touchPoints) ++WebTouchEvent WebEventFactory::createWebTouchEvent() + { + return WebTouchEvent(); + } +diff --git a/Source/WebKit/Sources.txt b/Source/WebKit/Sources.txt +index 458926f25bd6d5162a759ce0c73f8ea1eb17d5ff..2f3014d402f77c7554f07dbd7ed6f89e2b190a9f 100644 +--- a/Source/WebKit/Sources.txt ++++ b/Source/WebKit/Sources.txt +@@ -287,11 +287,14 @@ Shared/WebsiteData/WebsiteData.cpp + + UIProcess/AuxiliaryProcessProxy.cpp + UIProcess/BackgroundProcessResponsivenessTimer.cpp ++UIProcess/BrowserInspectorPipe.cpp + UIProcess/DeviceIdHashSaltStorage.cpp + UIProcess/DrawingAreaProxy.cpp + UIProcess/FrameLoadState.cpp + UIProcess/GeolocationPermissionRequestManagerProxy.cpp + UIProcess/GeolocationPermissionRequestProxy.cpp ++UIProcess/InspectorDialogAgent.cpp ++UIProcess/InspectorPlaywrightAgent.cpp + UIProcess/LegacyGlobalSettings.cpp + UIProcess/MediaKeySystemPermissionRequestManagerProxy.cpp + UIProcess/MediaKeySystemPermissionRequestProxy.cpp +@@ -299,6 +302,7 @@ UIProcess/PageLoadState.cpp + UIProcess/ProcessAssertion.cpp + UIProcess/ProcessThrottler.cpp + UIProcess/ProvisionalPageProxy.cpp ++UIProcess/RemoteInspectorPipe.cpp + UIProcess/ResponsivenessTimer.cpp + UIProcess/SpeechRecognitionRemoteRealtimeMediaSource.cpp + UIProcess/SpeechRecognitionRemoteRealtimeMediaSourceManager.cpp +@@ -340,6 +344,8 @@ UIProcess/WebOpenPanelResultListenerProxy.cpp + UIProcess/WebPageDiagnosticLoggingClient.cpp + UIProcess/WebPageGroup.cpp + UIProcess/WebPageInjectedBundleClient.cpp ++UIProcess/WebPageInspectorEmulationAgent.cpp ++UIProcess/WebPageInspectorInputAgent.cpp + UIProcess/WebPageProxy.cpp + UIProcess/WebPasteboardProxy.cpp + UIProcess/WebPreferences.cpp +@@ -463,6 +469,9 @@ UIProcess/Inspector/WebPageDebuggable.cpp + UIProcess/Inspector/WebPageInspectorController.cpp + + UIProcess/Inspector/Agents/InspectorBrowserAgent.cpp ++UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp ++UIProcess/Inspector/Agents/ScreencastEncoder.cpp ++UIProcess/Inspector/Agents/WebMFileWriter.cpp + + UIProcess/Media/AudioSessionRoutingArbitratorProxy.cpp + UIProcess/Media/MediaUsageManager.cpp +diff --git a/Source/WebKit/SourcesCocoa.txt b/Source/WebKit/SourcesCocoa.txt +index 09b4dad870423c1c3a63b766f1c50a6ae9914e03..d04c79e757fd6fa8249eac0d04f98ce8d82f0638 100644 +--- a/Source/WebKit/SourcesCocoa.txt ++++ b/Source/WebKit/SourcesCocoa.txt +@@ -259,6 +259,7 @@ UIProcess/API/Cocoa/_WKApplicationManifest.mm + UIProcess/API/Cocoa/_WKAttachment.mm + UIProcess/API/Cocoa/_WKAutomationSession.mm + UIProcess/API/Cocoa/_WKAutomationSessionConfiguration.mm ++UIProcess/API/Cocoa/_WKBrowserInspector.mm + UIProcess/API/Cocoa/_WKContentRuleListAction.mm + UIProcess/API/Cocoa/_WKContextMenuElementInfo.mm + UIProcess/API/Cocoa/_WKCustomHeaderFields.mm @no-unify +@@ -428,6 +429,7 @@ UIProcess/Inspector/ios/WKInspectorHighlightView.mm + UIProcess/Inspector/ios/WKInspectorNodeSearchGestureRecognizer.mm + + UIProcess/Inspector/mac/RemoteWebInspectorProxyMac.mm ++UIProcess/Inspector/mac/ScreencastEncoderMac.mm + UIProcess/Inspector/mac/WebInspectorProxyMac.mm + UIProcess/Inspector/mac/WKInspectorViewController.mm + UIProcess/Inspector/mac/WKInspectorWKWebView.mm +diff --git a/Source/WebKit/SourcesGTK.txt b/Source/WebKit/SourcesGTK.txt +index bcd721fece7e6e683357f0993081809ac5477c20..d51550c4ca9173d3735b2f39eacb946982486d94 100644 +--- a/Source/WebKit/SourcesGTK.txt ++++ b/Source/WebKit/SourcesGTK.txt +@@ -125,6 +125,7 @@ UIProcess/API/glib/WebKitAuthenticationRequest.cpp @no-unify + UIProcess/API/glib/WebKitAutomationSession.cpp @no-unify + UIProcess/API/glib/WebKitBackForwardList.cpp @no-unify + UIProcess/API/glib/WebKitBackForwardListItem.cpp @no-unify ++UIProcess/API/glib/WebKitBrowserInspector.cpp @no-unify + UIProcess/API/glib/WebKitContextMenuClient.cpp @no-unify + UIProcess/API/glib/WebKitCookieManager.cpp @no-unify + UIProcess/API/glib/WebKitCredential.cpp @no-unify +@@ -238,6 +239,7 @@ UIProcess/WebsiteData/unix/WebsiteDataStoreUnix.cpp + + UIProcess/cairo/BackingStoreCairo.cpp @no-unify + ++UIProcess/glib/InspectorPlaywrightAgentClientGLib.cpp + UIProcess/glib/WebPageProxyGLib.cpp + UIProcess/glib/WebProcessPoolGLib.cpp + UIProcess/glib/WebProcessProxyGLib.cpp +@@ -254,6 +256,7 @@ UIProcess/gtk/ClipboardGtk3.cpp @no-unify + UIProcess/gtk/ClipboardGtk4.cpp @no-unify + UIProcess/gtk/GestureController.cpp + UIProcess/gtk/HardwareAccelerationManager.cpp ++UIProcess/gtk/InspectorTargetProxyGtk.cpp + UIProcess/gtk/KeyBindingTranslator.cpp + UIProcess/gtk/PointerLockManager.cpp @no-unify + UIProcess/gtk/PointerLockManagerWayland.cpp @no-unify +@@ -264,6 +267,8 @@ UIProcess/gtk/WaylandCompositor.cpp @no-unify + UIProcess/gtk/WebColorPickerGtk.cpp + UIProcess/gtk/WebContextMenuProxyGtk.cpp + UIProcess/gtk/WebDataListSuggestionsDropdownGtk.cpp ++UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp ++UIProcess/gtk/WebPageInspectorInputAgentGtk.cpp + UIProcess/gtk/WebPageProxyGtk.cpp @no-unify + UIProcess/gtk/WebPasteboardProxyGtk.cpp + UIProcess/gtk/WebPopupMenuProxyGtk.cpp +diff --git a/Source/WebKit/SourcesWPE.txt b/Source/WebKit/SourcesWPE.txt +index 7f9767dcf74adeb9da371da0f4fb84987783d131..355c55b8834f371a69a9d3f7164bd4c4515f3c95 100644 +--- a/Source/WebKit/SourcesWPE.txt ++++ b/Source/WebKit/SourcesWPE.txt +@@ -85,6 +85,7 @@ Shared/glib/ProcessExecutablePathGLib.cpp + Shared/glib/UserMessage.cpp + Shared/glib/WebContextMenuItemGlib.cpp + ++Shared/libwpe/ArgumentCodersWPE.cpp + Shared/libwpe/NativeWebKeyboardEventLibWPE.cpp + Shared/libwpe/NativeWebMouseEventLibWPE.cpp + Shared/libwpe/NativeWebTouchEventLibWPE.cpp +@@ -117,6 +118,7 @@ UIProcess/API/glib/WebKitAuthenticationRequest.cpp @no-unify + UIProcess/API/glib/WebKitAutomationSession.cpp @no-unify + UIProcess/API/glib/WebKitBackForwardList.cpp @no-unify + UIProcess/API/glib/WebKitBackForwardListItem.cpp @no-unify ++UIProcess/API/glib/WebKitBrowserInspector.cpp @no-unify + UIProcess/API/glib/WebKitContextMenuClient.cpp @no-unify + UIProcess/API/glib/WebKitCookieManager.cpp @no-unify + UIProcess/API/glib/WebKitCredential.cpp @no-unify +@@ -197,6 +199,7 @@ UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp + + UIProcess/geoclue/GeoclueGeolocationProvider.cpp + ++UIProcess/glib/InspectorPlaywrightAgentClientGLib.cpp + UIProcess/glib/WebPageProxyGLib.cpp + UIProcess/glib/WebProcessPoolGLib.cpp + UIProcess/glib/WebProcessProxyGLib.cpp +@@ -219,6 +222,10 @@ UIProcess/linux/MemoryPressureMonitor.cpp + UIProcess/soup/WebCookieManagerProxySoup.cpp + UIProcess/soup/WebProcessPoolSoup.cpp + ++UIProcess/wpe/InspectorTargetProxyWPE.cpp ++UIProcess/wpe/WebPageInspectorEmulationAgentWPE.cpp ++UIProcess/wpe/WebPageInspectorInputAgentWPE.cpp ++ + UIProcess/wpe/WebPageProxyWPE.cpp + + WebProcess/GPU/media/gstreamer/VideoLayerRemoteGStreamer.cpp +@@ -247,6 +254,8 @@ WebProcess/WebCoreSupport/glib/WebEditorClientGLib.cpp + + WebProcess/WebCoreSupport/soup/WebFrameNetworkingContext.cpp + ++WebProcess/WebCoreSupport/wpe/WebDragClientWPE.cpp ++ + WebProcess/WebCoreSupport/wpe/WebEditorClientWPE.cpp + + WebProcess/WebPage/AcceleratedSurface.cpp +diff --git a/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp b/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp +index 18585f61bb6ecabec39ff0c03b862c65856dca24..21bab039d1f6116ebf9c59bc42a695a45f4701e8 100644 +--- a/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp ++++ b/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp +@@ -53,6 +53,9 @@ Ref ProcessPoolConfiguration::copy() + copy->m_ignoreSynchronousMessagingTimeoutsForTesting = this->m_ignoreSynchronousMessagingTimeoutsForTesting; + copy->m_attrStyleEnabled = this->m_attrStyleEnabled; + copy->m_overrideLanguages = this->m_overrideLanguages; ++#if PLATFORM(MAC) ++ copy->m_forceOverlayScrollbars = this->m_forceOverlayScrollbars; ++#endif + copy->m_alwaysRunsAtBackgroundPriority = this->m_alwaysRunsAtBackgroundPriority; + copy->m_shouldTakeUIBackgroundAssertion = this->m_shouldTakeUIBackgroundAssertion; + copy->m_shouldCaptureDisplayInUIProcess = this->m_shouldCaptureDisplayInUIProcess; +diff --git a/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h b/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h +index 64924902f19811792537a15a32ed4d706daf9670..28906745477d89bb0e7c2b9c3f1523d2d76803d6 100644 +--- a/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h ++++ b/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h +@@ -98,6 +98,11 @@ public: + const Vector& overrideLanguages() const { return m_overrideLanguages; } + void setOverrideLanguages(Vector&& languages) { m_overrideLanguages = WTFMove(languages); } + ++#if PLATFORM(MAC) ++ bool forceOverlayScrollbars() const { return m_forceOverlayScrollbars; } ++ void setForceOverlayScrollbars(bool forceOverlayScrollbars) { m_forceOverlayScrollbars = forceOverlayScrollbars; } ++#endif ++ + bool alwaysRunsAtBackgroundPriority() const { return m_alwaysRunsAtBackgroundPriority; } + void setAlwaysRunsAtBackgroundPriority(bool alwaysRunsAtBackgroundPriority) { m_alwaysRunsAtBackgroundPriority = alwaysRunsAtBackgroundPriority; } + +@@ -157,6 +162,9 @@ private: + bool m_ignoreSynchronousMessagingTimeoutsForTesting { false }; + bool m_attrStyleEnabled { false }; + Vector m_overrideLanguages; ++#if PLATFORM(MAC) ++ bool m_forceOverlayScrollbars { false }; ++#endif + bool m_alwaysRunsAtBackgroundPriority { false }; + bool m_shouldTakeUIBackgroundAssertion { true }; + bool m_shouldCaptureDisplayInUIProcess { DEFAULT_CAPTURE_DISPLAY_IN_UI_PROCESS }; +diff --git a/Source/WebKit/UIProcess/API/APIUIClient.h b/Source/WebKit/UIProcess/API/APIUIClient.h +index 7cebe2fabad5b335eb362a327eb344ae82dbe66e..7e02d18aab14356ab7aaaee661502950a0fd12f9 100644 +--- a/Source/WebKit/UIProcess/API/APIUIClient.h ++++ b/Source/WebKit/UIProcess/API/APIUIClient.h +@@ -94,6 +94,7 @@ public: + virtual void runJavaScriptAlert(WebKit::WebPageProxy&, const WTF::String&, WebKit::WebFrameProxy*, WebKit::FrameInfoData&&, Function&& completionHandler) { completionHandler(); } + virtual void runJavaScriptConfirm(WebKit::WebPageProxy&, const WTF::String&, WebKit::WebFrameProxy*, WebKit::FrameInfoData&&, Function&& completionHandler) { completionHandler(false); } + virtual void runJavaScriptPrompt(WebKit::WebPageProxy&, const WTF::String&, const WTF::String&, WebKit::WebFrameProxy*, WebKit::FrameInfoData&&, Function&& completionHandler) { completionHandler(WTF::String()); } ++ virtual void handleJavaScriptDialog(WebKit::WebPageProxy&, bool, const WTF::String&) { } + + virtual void setStatusText(WebKit::WebPageProxy*, const WTF::String&) { } + virtual void mouseDidMoveOverElement(WebKit::WebPageProxy&, const WebKit::WebHitTestResultData&, OptionSet, Object*) { } +diff --git a/Source/WebKit/UIProcess/API/C/WKInspector.cpp b/Source/WebKit/UIProcess/API/C/WKInspector.cpp +index 39327c5c9230591e4f52e4574c416e36687788f0..450033d87fefb743ab7240ce317fae221f91dcf5 100644 +--- a/Source/WebKit/UIProcess/API/C/WKInspector.cpp ++++ b/Source/WebKit/UIProcess/API/C/WKInspector.cpp +@@ -28,6 +28,11 @@ + + #if !PLATFORM(IOS_FAMILY) + ++#if PLATFORM(WIN) ++#include "BrowserInspectorPipe.h" ++#include "InspectorPlaywrightAgentClientWin.h" ++#endif ++ + #include "WKAPICast.h" + #include "WebInspectorProxy.h" + #include "WebPageProxy.h" +@@ -130,4 +135,11 @@ void WKInspectorToggleElementSelection(WKInspectorRef inspectorRef) + toImpl(inspectorRef)->toggleElementSelection(); + } + ++void WKInspectorInitializeRemoteInspectorPipe(ConfigureDataStoreCallback configureDataStore, CreatePageCallback createPage, QuitCallback quit) ++{ ++#if PLATFORM(WIN) ++ initializeBrowserInspectorPipe(makeUnique(configureDataStore, createPage, quit)); ++#endif ++} ++ + #endif // !PLATFORM(IOS_FAMILY) +diff --git a/Source/WebKit/UIProcess/API/C/WKInspector.h b/Source/WebKit/UIProcess/API/C/WKInspector.h +index 026121d114c5fcad84c1396be8d692625beaa3bd..edd6e5cae033124c589959a42522fde07a42fdf6 100644 +--- a/Source/WebKit/UIProcess/API/C/WKInspector.h ++++ b/Source/WebKit/UIProcess/API/C/WKInspector.h +@@ -66,6 +66,10 @@ WK_EXPORT void WKInspectorTogglePageProfiling(WKInspectorRef inspector); + WK_EXPORT bool WKInspectorIsElementSelectionActive(WKInspectorRef inspector); + WK_EXPORT void WKInspectorToggleElementSelection(WKInspectorRef inspector); + ++typedef void (*ConfigureDataStoreCallback)(WKWebsiteDataStoreRef dataStore); ++typedef WKPageRef (*CreatePageCallback)(WKPageConfigurationRef configuration); ++typedef void (*QuitCallback)(); ++WK_EXPORT void WKInspectorInitializeRemoteInspectorPipe(ConfigureDataStoreCallback, CreatePageCallback, QuitCallback); + #ifdef __cplusplus + } + #endif +diff --git a/Source/WebKit/UIProcess/API/C/WKPage.cpp b/Source/WebKit/UIProcess/API/C/WKPage.cpp +index 94572f8c985ee74958fe47f248983e28cf9a5317..8ffe9fa14971a43370e0e8e00ec72b948d26d594 100644 +--- a/Source/WebKit/UIProcess/API/C/WKPage.cpp ++++ b/Source/WebKit/UIProcess/API/C/WKPage.cpp +@@ -1695,6 +1695,13 @@ void WKPageSetPageUIClient(WKPageRef pageRef, const WKPageUIClientBase* wkClient + completionHandler(String()); + } + ++ void handleJavaScriptDialog(WebPageProxy& page, bool accept, const String& value) final { ++ if (m_client.handleJavaScriptDialog) { ++ m_client.handleJavaScriptDialog(toAPI(&page), accept, toAPI(value.impl()), m_client.base.clientInfo); ++ return; ++ } ++ } ++ + void setStatusText(WebPageProxy* page, const String& text) final + { + if (!m_client.setStatusText) +@@ -1755,6 +1762,8 @@ void WKPageSetPageUIClient(WKPageRef pageRef, const WKPageUIClientBase* wkClient + { + if (!m_client.didNotHandleKeyEvent) + return; ++ if (!event.nativeEvent()) ++ return; + m_client.didNotHandleKeyEvent(toAPI(page), event.nativeEvent(), m_client.base.clientInfo); + } + +diff --git a/Source/WebKit/UIProcess/API/C/WKPageUIClient.h b/Source/WebKit/UIProcess/API/C/WKPageUIClient.h +index 3d315be61348dd7d2467baa94dea4ae711c27803..364cfc24d55d9a2db33cbf9810295bfb2e23460a 100644 +--- a/Source/WebKit/UIProcess/API/C/WKPageUIClient.h ++++ b/Source/WebKit/UIProcess/API/C/WKPageUIClient.h +@@ -90,6 +90,7 @@ typedef void (*WKPageRunBeforeUnloadConfirmPanelCallback)(WKPageRef page, WKStri + typedef void (*WKPageRunJavaScriptAlertCallback)(WKPageRef page, WKStringRef alertText, WKFrameRef frame, WKSecurityOriginRef securityOrigin, WKPageRunJavaScriptAlertResultListenerRef listener, const void *clientInfo); + typedef void (*WKPageRunJavaScriptConfirmCallback)(WKPageRef page, WKStringRef message, WKFrameRef frame, WKSecurityOriginRef securityOrigin, WKPageRunJavaScriptConfirmResultListenerRef listener, const void *clientInfo); + typedef void (*WKPageRunJavaScriptPromptCallback)(WKPageRef page, WKStringRef message, WKStringRef defaultValue, WKFrameRef frame, WKSecurityOriginRef securityOrigin, WKPageRunJavaScriptPromptResultListenerRef listener, const void *clientInfo); ++typedef void (*WKPageHandleJavaScriptDialogCallback)(WKPageRef page, bool accept, WKStringRef value, const void *clientInfo); + typedef void (*WKPageRequestStorageAccessConfirmCallback)(WKPageRef page, WKFrameRef frame, WKStringRef requestingDomain, WKStringRef currentDomain, WKPageRequestStorageAccessConfirmResultListenerRef listener, const void *clientInfo); + typedef void (*WKPageTakeFocusCallback)(WKPageRef page, WKFocusDirection direction, const void *clientInfo); + typedef void (*WKPageFocusCallback)(WKPageRef page, const void *clientInfo); +@@ -1354,6 +1355,7 @@ typedef struct WKPageUIClientV14 { + + // Version 14. + WKPageRunWebAuthenticationPanelCallback runWebAuthenticationPanel; ++ WKPageHandleJavaScriptDialogCallback handleJavaScriptDialog; + } WKPageUIClientV14; + + typedef struct WKPageUIClientV15 { +@@ -1461,6 +1463,7 @@ typedef struct WKPageUIClientV15 { + + // Version 14. + WKPageRunWebAuthenticationPanelCallback runWebAuthenticationPanel; ++ WKPageHandleJavaScriptDialogCallback handleJavaScriptDialog; + + // Version 15. + WKPageDecidePolicyForSpeechRecognitionPermissionRequestCallback decidePolicyForSpeechRecognitionPermissionRequest; +@@ -1572,6 +1575,7 @@ typedef struct WKPageUIClientV16 { + + // Version 14. + WKPageRunWebAuthenticationPanelCallback runWebAuthenticationPanel; ++ WKPageHandleJavaScriptDialogCallback handleJavaScriptDialog; + + // Version 15. + WKPageDecidePolicyForSpeechRecognitionPermissionRequestCallback decidePolicyForSpeechRecognitionPermissionRequest; +diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKDownloadInternal.h b/Source/WebKit/UIProcess/API/Cocoa/WKDownloadInternal.h +index 06c89420e6e27b143db025405cb33b7a9d7c4af9..cc0258b9dadf38dce74cabab479881b444a41167 100644 +--- a/Source/WebKit/UIProcess/API/Cocoa/WKDownloadInternal.h ++++ b/Source/WebKit/UIProcess/API/Cocoa/WKDownloadInternal.h +@@ -26,6 +26,7 @@ + #import "DownloadProxy.h" + #import "WKDownload.h" + #import "WKObject.h" ++#import + + namespace WebKit { + +diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegate.h b/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegate.h +index cad87f3ef2ab93d93a74cec0c34b47c695de6bc6..66145a384638b97ee08516e56e1e86a83713c634 100644 +--- a/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegate.h ++++ b/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegate.h +@@ -123,6 +123,13 @@ NS_ASSUME_NONNULL_BEGIN + */ + - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable result))completionHandler; + ++/*! @abstract Handle a JavaScript dialog. ++ @param webView The web view invoking the delegate method. ++ @param accept Whether to accept the dialog. ++ @param value Value to use for prompt dialog. ++ */ ++- (void)webView:(WKWebView *)webView handleJavaScriptDialog:(BOOL)accept value:(nullable NSString *)value; ++ + #if TARGET_OS_IPHONE + + /*! @abstract Allows your app to determine whether or not the given element should show a preview. +diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.h b/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.h +index 245580d7e15679b82a61c4639850da02d81a4e1e..5fd5c4afbdc167f817b4ae961f446ec44a0ae2c1 100644 +--- a/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.h ++++ b/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.h +@@ -24,7 +24,6 @@ + */ + + #import +- + #import + + NS_ASSUME_NONNULL_BEGIN +@@ -79,6 +78,8 @@ WK_CLASS_AVAILABLE(macos(10.11), ios(9.0)) + /*! @abstract Returns the cookie store representing HTTP cookies in this website data store. */ + @property (nonatomic, readonly) WKHTTPCookieStore *httpCookieStore WK_API_AVAILABLE(macos(10.13), ios(11.0)); + ++- (uint64_t)sessionID; ++ + @end + + NS_ASSUME_NONNULL_END +diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm b/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm +index 40d7f85bf9bf84265d06d4972dc4d06ee0ce9531..cc8c7c35c1e73fb85f78135ae965468d7a05896b 100644 +--- a/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm ++++ b/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm +@@ -44,6 +44,7 @@ + #import + #import + #import ++#import + #import + #import + #import +@@ -198,6 +199,11 @@ static WallTime toSystemClockTime(NSDate *date) + }); + } + ++- (uint64_t) sessionID ++{ ++ return _websiteDataStore->sessionID().toUInt64(); ++} ++ + static Vector toWebsiteDataRecords(NSArray *dataRecords) + { + Vector result; +diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.h b/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.h +new file mode 100644 +index 0000000000000000000000000000000000000000..5fabe06a3289689246c36dfd96eb9900a48b2b0f +--- /dev/null ++++ b/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.h +@@ -0,0 +1,55 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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. ++ */ ++ ++#import ++#import ++#import ++#import ++ ++NS_ASSUME_NONNULL_BEGIN ++ ++@class WKWebView; ++ ++WK_CLASS_AVAILABLE(macos(10.14.0)) ++@interface _WKBrowserContext : NSObject ++@property (nonatomic, strong) WKWebsiteDataStore *dataStore; ++@property (nonatomic, strong) WKProcessPool *processPool; ++@end ++ ++@protocol _WKBrowserInspectorDelegate ++- (WKWebView *)createNewPage:(uint64_t)sessionID; ++- (_WKBrowserContext *)createBrowserContext:(NSString *)proxyServer WithBypassList:(NSString *)proxyBypassList; ++- (void)deleteBrowserContext:(uint64_t)sessionID; ++- (void)quit; ++@end ++ ++WK_CLASS_AVAILABLE(macos(10.14.0)) ++@interface _WKBrowserInspector : NSObject +++ (void)initializeRemoteInspectorPipe:(id<_WKBrowserInspectorDelegate>)delegate headless:(BOOL)headless; ++@end ++ ++ ++NS_ASSUME_NONNULL_END ++ +diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.mm +new file mode 100644 +index 0000000000000000000000000000000000000000..e7143513ea2be8e1cdab5c86a28643fffea626dd +--- /dev/null ++++ b/Source/WebKit/UIProcess/API/Cocoa/_WKBrowserInspector.mm +@@ -0,0 +1,60 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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 "_WKBrowserInspector.h" ++ ++#include "BrowserInspectorPipe.h" ++#include "InspectorPlaywrightAgentClientMac.h" ++#include "PageClientImplMac.h" ++#include "WebKit2Initialize.h" ++ ++#import "WKWebView.h" ++ ++using namespace WebKit; ++ ++@implementation _WKBrowserInspector ++ +++ (void)initializeRemoteInspectorPipe:(id<_WKBrowserInspectorDelegate>)delegate headless:(BOOL)headless ++{ ++#if ENABLE(REMOTE_INSPECTOR) ++ InitializeWebKit2(); ++ PageClientImpl::setHeadless(headless); ++ initializeBrowserInspectorPipe(makeUnique(delegate)); ++#endif ++} ++ ++@end ++ ++@implementation _WKBrowserContext ++- (void)dealloc ++{ ++ [_dataStore release]; ++ [_processPool release]; ++ _dataStore = nil; ++ _processPool = nil; ++ [super dealloc]; ++} ++@end +diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKDownload.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKDownload.mm +index 913f53a5411894c29ebfe0d7f07fb7b60207af08..f198b4f05a5bcfe3455af157628791d549f181b0 100644 +--- a/Source/WebKit/UIProcess/API/Cocoa/_WKDownload.mm ++++ b/Source/WebKit/UIProcess/API/Cocoa/_WKDownload.mm +@@ -32,6 +32,7 @@ + #import "WKFrameInfoInternal.h" + #import "WKNSData.h" + #import "WKWebViewInternal.h" ++#import + #import + + ALLOW_DEPRECATED_DECLARATIONS_BEGIN +diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKDownloadInternal.h b/Source/WebKit/UIProcess/API/Cocoa/_WKDownloadInternal.h +index ca94c2173757a54a0c755cbf30f8e05a0b75c9cb..422c1379da9b091ae5903a42bc7625be78030016 100644 +--- a/Source/WebKit/UIProcess/API/Cocoa/_WKDownloadInternal.h ++++ b/Source/WebKit/UIProcess/API/Cocoa/_WKDownloadInternal.h +@@ -24,6 +24,7 @@ + */ + + #import "_WKDownload.h" ++#import "WKObject.h" + + #import + +diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKInspectorExtension.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKInspectorExtension.mm +index 20b40a96519e434c5c18acb2b4ea6a35f0dcf5aa..55282c441d6184fbf67a2bdc0a3d8a7cdfc97abb 100644 +--- a/Source/WebKit/UIProcess/API/Cocoa/_WKInspectorExtension.mm ++++ b/Source/WebKit/UIProcess/API/Cocoa/_WKInspectorExtension.mm +@@ -24,7 +24,10 @@ + */ + + #import "config.h" ++#import "WKError.h" + #import "_WKInspectorExtensionInternal.h" ++#import ++#import + + #if ENABLE(INSPECTOR_EXTENSIONS) + +diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h b/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h +index 5f213970acfc0396839a613bb8ee9407bfe8881e..613ae48e76f292fde0749bbbb9a47c9a9011ecd8 100644 +--- a/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h ++++ b/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h +@@ -62,6 +62,7 @@ WK_CLASS_AVAILABLE(macos(10.10), ios(8.0)) + #endif + @property (nonatomic) pid_t presentingApplicationPID WK_API_AVAILABLE(macos(10.13), ios(11.0)); + @property (nonatomic) BOOL processSwapsOnNavigation WK_API_AVAILABLE(macos(10.14), ios(12.0)); ++@property (nonatomic) BOOL forceOverlayScrollbars WK_API_AVAILABLE(macos(10.14)); + @property (nonatomic) BOOL alwaysKeepAndReuseSwappedProcesses WK_API_AVAILABLE(macos(10.14), ios(12.0)); + @property (nonatomic) BOOL processSwapsOnWindowOpenWithOpener WK_API_AVAILABLE(macos(10.14), ios(12.0)); + @property (nonatomic) BOOL prewarmsProcessesAutomatically WK_API_AVAILABLE(macos(10.14.4), ios(12.2)); +diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm +index 455d5a9234d599277c6288209eda2c76c06f177b..5788f08ef417fab32a335222fc1453d1a2c028a8 100644 +--- a/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm ++++ b/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm +@@ -231,6 +231,16 @@ + return _processPoolConfiguration->processSwapsOnNavigation(); + } + ++- (void)setForceOverlayScrollbars:(BOOL)force ++{ ++ _processPoolConfiguration->setForceOverlayScrollbars(force); ++} ++ ++- (BOOL)forceOverlayScrollbars ++{ ++ return _processPoolConfiguration->forceOverlayScrollbars(); ++} ++ + - (void)setPrewarmsProcessesAutomatically:(BOOL)prewarms + { + _processPoolConfiguration->setIsAutomaticProcessWarmingEnabled(prewarms); +diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm +index 06e2eece712b59250f5390bdc48014b5d7e50b25..58a7bb1eac1a2173ddcf92ce7a9686cafaaa9963 100644 +--- a/Source/WebKit/UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm ++++ b/Source/WebKit/UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm +@@ -24,6 +24,7 @@ + */ + + #import "config.h" ++#import "WKWebViewPrivate.h" + #import "_WKRemoteWebInspectorViewControllerInternal.h" + + #if PLATFORM(MAC) +diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.h b/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.h +index 4974e14214e2bb3e982325b885bab33e54f83998..cacdf8c71fab248d38d2faf03f7affdcfed1ef62 100644 +--- a/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.h ++++ b/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.h +@@ -31,6 +31,7 @@ NS_ASSUME_NONNULL_BEGIN + @class _WKUserContentWorld; + @class WKContentWorld; + @class WKWebView; ++@class WKContentWorld; + + typedef NS_ENUM(NSInteger, _WKUserStyleLevel) { + _WKUserStyleUserLevel, +diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.mm +index da76d3a80fc3dbe1a66a4a76a2254f5912828372..f7451072eb6c3f505d37396c4eab505198b055c7 100644 +--- a/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.mm ++++ b/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.mm +@@ -34,6 +34,7 @@ + #import "WebKit2Initialize.h" + #import "WebPageProxy.h" + #import "_WKUserContentWorldInternal.h" ++#import + #import + + @implementation _WKUserStyleSheet +diff --git a/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspector.cpp b/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspector.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..54529a23f53cebe6f8a96873ca6c2f31f0481ae0 +--- /dev/null ++++ b/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspector.cpp +@@ -0,0 +1,158 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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 "WebKitBrowserInspector.h" ++ ++#include "BrowserInspectorPipe.h" ++#include "InspectorPlaywrightAgentClientGLib.h" ++#include "WebKitBrowserInspectorPrivate.h" ++#include "WebKitWebViewPrivate.h" ++#include ++#include ++ ++/** ++ * SECTION: WebKitBrowserInspector ++ * @Short_description: Access to the WebKit browser inspector ++ * @Title: WebKitBrowserInspector ++ * ++ * The WebKit Browser Inspector is an experimental API that provides ++ * access to the inspector via the remote debugging protocol. The protocol ++ * allows to create ephemeral contexts and create pages in them and then ++ * manipulate them using the inspector commands. This may be useful for ++ * the browser automation or remote debugging. ++ * ++ * Currently the protocol can be exposed to the parent process via a unix ++ * pipe. ++ */ ++ ++enum { ++ CREATE_NEW_PAGE, ++ QUIT_APPLICATION, ++ ++ LAST_SIGNAL ++}; ++ ++struct _WebKitBrowserInspectorPrivate { ++ int unused { 0 }; ++}; ++ ++WEBKIT_DEFINE_TYPE(WebKitBrowserInspector, webkit_browser_inspector, G_TYPE_OBJECT) ++ ++static guint signals[LAST_SIGNAL] = { 0, }; ++ ++static void webkit_browser_inspector_class_init(WebKitBrowserInspectorClass* findClass) ++{ ++ GObjectClass* gObjectClass = G_OBJECT_CLASS(findClass); ++ ++ /** ++ * WebKitBrowserInspector::create-new-page: ++ * @inspector: the #WebKitBrowserInspector on which the signal is emitted ++ * ++ * Emitted when the inspector is requested to create a new page in the provided ++ * #WebKitWebContext. ++ * ++ * This signal is emitted when inspector receives 'Browser.createPage' command ++ * from its remote client. If the signal is not handled the command will fail. ++ * ++ * Returns: %WebKitWebView that contains created page. ++ */ ++ signals[CREATE_NEW_PAGE] = g_signal_new( ++ "create-new-page", ++ G_TYPE_FROM_CLASS(gObjectClass), ++ G_SIGNAL_RUN_LAST, ++ G_STRUCT_OFFSET(WebKitBrowserInspectorClass, create_new_page), ++ nullptr, nullptr, ++ g_cclosure_marshal_generic, ++#if PLATFORM(GTK) ++ GTK_TYPE_WIDGET, ++#else ++ WEBKIT_TYPE_WEB_VIEW, ++#endif ++ 1, ++ WEBKIT_TYPE_WEB_CONTEXT); ++ ++ /** ++ * WebKitBrowserInspector::quit-application: ++ * @inspector: the #WebKitBrowserInspector on which the signal is emitted ++ * ++ * Emitted when the inspector is requested to close the browser application. ++ * ++ * This signal is emitted when inspector receives 'Browser.close' command ++ * from its remote client. If the signal is not handled the command will fail. ++ */ ++ signals[QUIT_APPLICATION] = g_signal_new( ++ "quit-application", ++ G_TYPE_FROM_CLASS(gObjectClass), ++ G_SIGNAL_RUN_LAST, ++ G_STRUCT_OFFSET(WebKitBrowserInspectorClass, quit_application), ++ nullptr, nullptr, ++ g_cclosure_marshal_VOID__VOID, ++ G_TYPE_NONE, 0); ++} ++ ++WebKit::WebPageProxy* webkitBrowserInspectorCreateNewPageInContext(WebKitWebContext* context) ++{ ++ WebKitWebView* newWebView; ++ g_signal_emit(webkit_browser_inspector_get_default(), signals[CREATE_NEW_PAGE], 0, context, &newWebView); ++ if (!newWebView) ++ return nullptr; ++ return &webkitWebViewGetPage(newWebView); ++} ++ ++void webkitBrowserInspectorQuitApplication() ++{ ++ g_signal_emit(webkit_browser_inspector_get_default(), signals[QUIT_APPLICATION], 0, NULL); ++} ++ ++static gpointer createWebKitBrowserInspector(gpointer) ++{ ++ static GRefPtr browserInspector = adoptGRef(WEBKIT_BROWSER_INSPECTOR(g_object_new(WEBKIT_TYPE_BROWSER_INSPECTOR, nullptr))); ++ return browserInspector.get(); ++} ++ ++/** ++ * webkit_browser_inspector_get_default: ++ * ++ * Gets the default instance of the browser inspector. ++ * ++ * Returns: (transfer none): a #WebKitBrowserInspector ++ */ ++WebKitBrowserInspector* webkit_browser_inspector_get_default(void) ++{ ++ static GOnce onceInit = G_ONCE_INIT; ++ return WEBKIT_BROWSER_INSPECTOR(g_once(&onceInit, createWebKitBrowserInspector, 0)); ++} ++ ++/** ++ * webkit_browser_inspector_initialize_pipe: ++ * ++ * Creates browser inspector and configures pipe handler to communicate with ++ * the parent process. ++ */ ++void webkit_browser_inspector_initialize_pipe(const char* defaultProxyURI, const char* const* ignoreHosts) ++{ ++ WebKit::initializeBrowserInspectorPipe(makeUnique(defaultProxyURI, ignoreHosts)); ++} +diff --git a/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspectorPrivate.h b/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspectorPrivate.h +new file mode 100644 +index 0000000000000000000000000000000000000000..e0b1da48465c850f541532ed961d1b778bea6028 +--- /dev/null ++++ b/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspectorPrivate.h +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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. ++ */ ++ ++#pragma once ++ ++#include "WebKitBrowserInspector.h" ++#include "WebPageProxy.h" ++ ++WebKit::WebPageProxy* webkitBrowserInspectorCreateNewPageInContext(WebKitWebContext*); ++void webkitBrowserInspectorQuitApplication(); +diff --git a/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp b/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp +index 8d13ea418df483f0724525ed4d23cce5aad80207..4532cd0873a99f19ba3467c826045b8c8a7d5f47 100644 +--- a/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp ++++ b/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp +@@ -94,6 +94,10 @@ private: + { + webkitWebViewRunJavaScriptPrompt(m_webView, message.utf8(), defaultValue.utf8(), WTFMove(completionHandler)); + } ++ void handleJavaScriptDialog(WebPageProxy&, bool accept, const String& value) final ++ { ++ webkitWebViewHandleJavaScriptDialog(m_webView, accept, value); ++ } + + bool canRunBeforeUnloadConfirmPanel() const final { return true; } + +diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp b/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp +index 2bbe1a72728ce776f3a140fefdde2a53207eff25..ce3bed68577ef2e9ff8a9fa014a3c35704cf826b 100644 +--- a/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp ++++ b/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp +@@ -120,8 +120,8 @@ enum { + PROP_LOCAL_STORAGE_DIRECTORY, + #endif + PROP_WEBSITE_DATA_MANAGER, +-#if PLATFORM(GTK) + PROP_PSON_ENABLED, ++#if PLATFORM(GTK) + #if !USE(GTK4) + PROP_USE_SYSYEM_APPEARANCE_FOR_SCROLLBARS + #endif +@@ -206,8 +206,8 @@ struct _WebKitWebContextPrivate { + + RefPtr processPool; + bool clientsDetached; +-#if PLATFORM(GTK) + bool psonEnabled; ++#if PLATFORM(GTK) + #if !USE(GTK4) + bool useSystemAppearanceForScrollbars; + #endif +@@ -306,11 +306,9 @@ WEBKIT_DEFINE_TYPE(WebKitWebContext, webkit_web_context, G_TYPE_OBJECT) + + static const char* injectedBundleDirectory() + { +-#if ENABLE(DEVELOPER_MODE) + const char* bundleDirectory = g_getenv("WEBKIT_INJECTED_BUNDLE_PATH"); + if (bundleDirectory && g_file_test(bundleDirectory, G_FILE_TEST_IS_DIR)) + return bundleDirectory; +-#endif + + #if PLATFORM(GTK) + static const char* injectedBundlePath = LIBDIR G_DIR_SEPARATOR_S "webkit2gtk-" WEBKITGTK_API_VERSION_STRING +@@ -335,10 +333,10 @@ static void webkitWebContextGetProperty(GObject* object, guint propID, GValue* v + case PROP_WEBSITE_DATA_MANAGER: + g_value_set_object(value, webkit_web_context_get_website_data_manager(context)); + break; +-#if PLATFORM(GTK) + case PROP_PSON_ENABLED: + g_value_set_boolean(value, context->priv->psonEnabled); + break; ++#if PLATFORM(GTK) + #if !USE(GTK4) + case PROP_USE_SYSYEM_APPEARANCE_FOR_SCROLLBARS: + g_value_set_boolean(value, webkit_web_context_get_use_system_appearance_for_scrollbars(context)); +@@ -365,10 +363,10 @@ static void webkitWebContextSetProperty(GObject* object, guint propID, const GVa + context->priv->websiteDataManager = manager ? WEBKIT_WEBSITE_DATA_MANAGER(manager) : nullptr; + break; + } +-#if PLATFORM(GTK) + case PROP_PSON_ENABLED: + context->priv->psonEnabled = g_value_get_boolean(value); + break; ++#if PLATFORM(GTK) + #if !USE(GTK4) + case PROP_USE_SYSYEM_APPEARANCE_FOR_SCROLLBARS: + webkit_web_context_set_use_system_appearance_for_scrollbars(context, g_value_get_boolean(value)); +@@ -380,10 +378,19 @@ static void webkitWebContextSetProperty(GObject* object, guint propID, const GVa + } + } + ++static int webkitWebContext = 0; ++ ++int webkitWebContextExistingCount() ++{ ++ return webkitWebContext; ++} ++ + static void webkitWebContextConstructed(GObject* object) + { + G_OBJECT_CLASS(webkit_web_context_parent_class)->constructed(object); + ++ ++webkitWebContext; ++ + GUniquePtr bundleFilename(g_build_filename(injectedBundleDirectory(), INJECTED_BUNDLE_FILENAME, nullptr)); + + WebKitWebContext* webContext = WEBKIT_WEB_CONTEXT(object); +@@ -392,8 +399,8 @@ static void webkitWebContextConstructed(GObject* object) + API::ProcessPoolConfiguration configuration; + configuration.setInjectedBundlePath(FileSystem::stringFromFileSystemRepresentation(bundleFilename.get())); + configuration.setUsesWebProcessCache(true); +-#if PLATFORM(GTK) + configuration.setProcessSwapsOnNavigation(priv->psonEnabled); ++#if PLATFORM(GTK) + #if !USE(GTK4) + configuration.setUseSystemAppearanceForScrollbars(priv->useSystemAppearanceForScrollbars); + #endif +@@ -430,6 +437,8 @@ static void webkitWebContextConstructed(GObject* object) + + static void webkitWebContextDispose(GObject* object) + { ++ --webkitWebContext; ++ + WebKitWebContextPrivate* priv = WEBKIT_WEB_CONTEXT(object)->priv; + if (!priv->clientsDetached) { + priv->clientsDetached = true; +@@ -502,7 +511,6 @@ static void webkit_web_context_class_init(WebKitWebContextClass* webContextClass + WEBKIT_TYPE_WEBSITE_DATA_MANAGER, + static_cast(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY))); + +-#if PLATFORM(GTK) + /** + * WebKitWebContext:process-swap-on-cross-site-navigation-enabled: + * +@@ -526,6 +534,7 @@ static void webkit_web_context_class_init(WebKitWebContextClass* webContextClass + FALSE, + static_cast(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY))); + ++#if PLATFORM(GTK) + #if !USE(GTK4) + /** + * WebKitWebContext:use-system-appearance-for-scrollbars: +diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebContextPrivate.h b/Source/WebKit/UIProcess/API/glib/WebKitWebContextPrivate.h +index 78d1578f94793e9e59a3d4d2b33e79ea8530fa04..493cdadac3873508b3efa3048638e73a13f4c976 100644 +--- a/Source/WebKit/UIProcess/API/glib/WebKitWebContextPrivate.h ++++ b/Source/WebKit/UIProcess/API/glib/WebKitWebContextPrivate.h +@@ -45,3 +45,4 @@ void webkitWebContextInitializeNotificationPermissions(WebKitWebContext*); + #if ENABLE(REMOTE_INSPECTOR) + void webkitWebContextWillCloseAutomationSession(WebKitWebContext*); + #endif ++int webkitWebContextExistingCount(); +diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp b/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp +index d1a9b7bae144f9adcdb093c66f12550e8f490680..405e9c69aaa87aa92abcc6cc65ef5d9c683411b3 100644 +--- a/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp ++++ b/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp +@@ -31,6 +31,7 @@ + #include "WebCertificateInfo.h" + #include "WebContextMenuItem.h" + #include "WebContextMenuItemData.h" ++#include "WebPageInspectorController.h" + #include "WebKitAuthenticationRequestPrivate.h" + #include "WebKitBackForwardListPrivate.h" + #include "WebKitContextMenuClient.h" +@@ -132,6 +133,7 @@ enum { + CLOSE, + + SCRIPT_DIALOG, ++ SCRIPT_DIALOG_HANDLED, + + DECIDE_POLICY, + PERMISSION_REQUEST, +@@ -437,6 +439,9 @@ void WebKitWebViewClient::handleDownloadRequest(WKWPE::View&, DownloadProxy& dow + + void WebKitWebViewClient::frameDisplayed(WKWPE::View&) + { ++ if (RefPtr surface = adoptRef(webkitWebViewBackendTakeScreenshot(m_webView->priv->backend.get()))) ++ getPage(m_webView).inspectorController().didPaint(surface.get()); ++ + { + SetForScope inFrameDisplayedGuard(m_webView->priv->inFrameDisplayed, true); + for (const auto& callback : m_webView->priv->frameDisplayedCallbacks) { +@@ -467,6 +472,7 @@ void WebKitWebViewClient::didReceiveUserMessage(WKWPE::View&, UserMessage&& mess + { + webkitWebViewDidReceiveUserMessage(m_webView, WTFMove(message), WTFMove(completionHandler)); + } ++ + #endif + + static gboolean webkitWebViewLoadFail(WebKitWebView* webView, WebKitLoadEvent, const char* failingURI, GError* error) +@@ -1606,6 +1612,15 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) + G_TYPE_BOOLEAN, 1, + WEBKIT_TYPE_SCRIPT_DIALOG); + ++ signals[SCRIPT_DIALOG_HANDLED] = g_signal_new( ++ "script-dialog-handled", ++ G_TYPE_FROM_CLASS(webViewClass), ++ G_SIGNAL_RUN_LAST, ++ G_STRUCT_OFFSET(WebKitWebViewClass, script_dialog), ++ g_signal_accumulator_true_handled, nullptr, ++ g_cclosure_marshal_generic, ++ G_TYPE_BOOLEAN, 1); ++ + /** + * WebKitWebView::decide-policy: + * @web_view: the #WebKitWebView on which the signal is emitted +@@ -2499,6 +2514,23 @@ void webkitWebViewRunJavaScriptBeforeUnloadConfirm(WebKitWebView* webView, const + webkit_script_dialog_unref(webView->priv->currentScriptDialog); + } + ++void webkitWebViewHandleJavaScriptDialog(WebKitWebView* webView, bool accept, const String& value) { ++ auto* dialog = webView->priv->currentScriptDialog; ++#if PLATFORM(WPE) ++ dialog->isUserHandled = false; ++#endif ++ webkit_script_dialog_ref(dialog); ++ if (!value.isNull()) ++ webkitWebViewSetCurrentScriptDialogUserInput(webView, value); ++ if (accept) ++ webkitWebViewAcceptCurrentScriptDialog(webView); ++ else ++ webkitWebViewDismissCurrentScriptDialog(webView); ++ gboolean returnValue; ++ g_signal_emit(webView, signals[SCRIPT_DIALOG_HANDLED], 0, dialog, &returnValue); ++ webkit_script_dialog_unref(dialog); ++} ++ + bool webkitWebViewIsShowingScriptDialog(WebKitWebView* webView) + { + if (!webView->priv->currentScriptDialog) +diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h b/Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h +index b9e56fc55fd7dfa821f789264b0c15f9b4c7b412..4138d5b42077f735264ac7a168cce329ebaa89c3 100644 +--- a/Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h ++++ b/Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h +@@ -60,6 +60,7 @@ void webkitWebViewRunJavaScriptAlert(WebKitWebView*, const CString& message, Fun + void webkitWebViewRunJavaScriptConfirm(WebKitWebView*, const CString& message, Function&& completionHandler); + void webkitWebViewRunJavaScriptPrompt(WebKitWebView*, const CString& message, const CString& defaultText, Function&& completionHandler); + void webkitWebViewRunJavaScriptBeforeUnloadConfirm(WebKitWebView*, const CString& message, Function&& completionHandler); ++void webkitWebViewHandleJavaScriptDialog(WebKitWebView*, bool accept, const String& value); + bool webkitWebViewIsShowingScriptDialog(WebKitWebView*); + bool webkitWebViewIsScriptDialogRunning(WebKitWebView*, WebKitScriptDialog*); + String webkitWebViewGetCurrentScriptDialogMessage(WebKitWebView*); +diff --git a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp +index 57139e2d910cf1834d071d482b3967194dd0fda1..3b6ecd1ace15fdaded93b9207446f2810aaf7dbd 100644 +--- a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp ++++ b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp +@@ -241,6 +241,8 @@ void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool + { + if (wasEventHandled || event.type() != WebEvent::Type::KeyDown || !event.nativeEvent()) + return; ++ if (!event.nativeEvent()) ++ return; + + WebKitWebViewBase* webkitWebViewBase = WEBKIT_WEB_VIEW_BASE(m_viewWidget); + webkitWebViewBaseForwardNextKeyEvent(webkitWebViewBase); +diff --git a/Source/WebKit/UIProcess/API/gtk/WebKitBrowserInspector.h b/Source/WebKit/UIProcess/API/gtk/WebKitBrowserInspector.h +new file mode 100644 +index 0000000000000000000000000000000000000000..9f1a0173a5641d6f158d815b8f7b9ea66f65c26d +--- /dev/null ++++ b/Source/WebKit/UIProcess/API/gtk/WebKitBrowserInspector.h +@@ -0,0 +1,81 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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 !defined(__WEBKIT2_H_INSIDE__) && !defined(WEBKIT2_COMPILATION) ++#error "Only can be included directly." ++#endif ++ ++#ifndef WebKitBrowserInspector_h ++#define WebKitBrowserInspector_h ++ ++#include ++#include ++#include ++ ++G_BEGIN_DECLS ++ ++#define WEBKIT_TYPE_BROWSER_INSPECTOR (webkit_browser_inspector_get_type()) ++#define WEBKIT_BROWSER_INSPECTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_BROWSER_INSPECTOR, WebKitBrowserInspector)) ++#define WEBKIT_IS_BROWSER_INSPECTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_BROWSER_INSPECTOR)) ++#define WEBKIT_BROWSER_INSPECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_BROWSER_INSPECTOR, WebKitBrowserInspectorClass)) ++#define WEBKIT_IS_BROWSER_INSPECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_BROWSER_INSPECTOR)) ++#define WEBKIT_BROWSER_INSPECTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_BROWSER_INSPECTOR, WebKitBrowserInspectorClass)) ++ ++typedef struct _WebKitBrowserInspector WebKitBrowserInspector; ++typedef struct _WebKitBrowserInspectorClass WebKitBrowserInspectorClass; ++typedef struct _WebKitBrowserInspectorPrivate WebKitBrowserInspectorPrivate; ++ ++struct _WebKitBrowserInspector { ++ GObject parent; ++ ++ WebKitBrowserInspectorPrivate *priv; ++}; ++ ++struct _WebKitBrowserInspectorClass { ++ GObjectClass parent_class; ++ ++ WebKitWebView *(* create_new_page) (WebKitBrowserInspector *browser_inspector, ++ WebKitWebContext *context); ++ WebKitWebView *(* quit_application) (WebKitBrowserInspector *browser_inspector); ++ ++ void (*_webkit_reserved0) (void); ++ void (*_webkit_reserved1) (void); ++ void (*_webkit_reserved2) (void); ++ void (*_webkit_reserved3) (void); ++}; ++ ++WEBKIT_API GType ++webkit_browser_inspector_get_type (void); ++ ++WEBKIT_API WebKitBrowserInspector * ++webkit_browser_inspector_get_default (void); ++ ++WEBKIT_API void ++webkit_browser_inspector_initialize_pipe (const char* defaultProxyURI, ++ const char* const* ignoreHosts); ++ ++G_END_DECLS ++ ++#endif +diff --git a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp b/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp +index dd0eb6ab0895a9265cd227ea7cd8458e7dc1bdf3..ba7ae4e211eb26a7688826785c347103809677bb 100644 +--- a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp ++++ b/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp +@@ -2267,6 +2267,11 @@ void webkitWebViewBaseResetClickCounter(WebKitWebViewBase* webkitWebViewBase) + #endif + } + ++WebKit::AcceleratedBackingStore* webkitWebViewBaseGetAcceleratedBackingStore(WebKitWebViewBase* webkitWebViewBase) ++{ ++ return webkitWebViewBase->priv->acceleratedBackingStore.get(); ++} ++ + void webkitWebViewBaseEnterAcceleratedCompositingMode(WebKitWebViewBase* webkitWebViewBase, const LayerTreeContext& layerTreeContext) + { + ASSERT(webkitWebViewBase->priv->acceleratedBackingStore); +diff --git a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h b/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h +index d09aea45d94fb7367ba88fdf8326dea1209d02ce..dac8f3ec62ace87fc82c997feb950733aa59a996 100644 +--- a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h ++++ b/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h +@@ -27,6 +27,7 @@ + + #pragma once + ++#include "AcceleratedBackingStore.h" + #include "APIPageConfiguration.h" + #include "GestureController.h" + #include "InputMethodState.h" +@@ -120,3 +121,5 @@ void webkitWebViewBaseDidLosePointerLock(WebKitWebViewBase*); + void webkitWebViewBaseSetInputMethodContext(WebKitWebViewBase*, WebKitInputMethodContext*); + WebKitInputMethodContext* webkitWebViewBaseGetInputMethodContext(WebKitWebViewBase*); + void webkitWebViewBaseSynthesizeCompositionKeyPress(WebKitWebViewBase*, const String& text, Optional>&&, Optional&&); ++ ++WebKit::AcceleratedBackingStore* webkitWebViewBaseGetAcceleratedBackingStore(WebKitWebViewBase*); +diff --git a/Source/WebKit/UIProcess/API/gtk/webkit2.h b/Source/WebKit/UIProcess/API/gtk/webkit2.h +index ecbe433ed888353b1e6013943b4463835c3582d2..7385877fe664515814fc5c3380a2b7298ff90e1e 100644 +--- a/Source/WebKit/UIProcess/API/gtk/webkit2.h ++++ b/Source/WebKit/UIProcess/API/gtk/webkit2.h +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + #include + #include + #include +diff --git a/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp b/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp +index eb3be657de82181296a6afc55072548d6b2ea33e..98f5579cde832ed0946d124f1c052ec5cbe8666b 100644 +--- a/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp ++++ b/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp +@@ -194,7 +194,7 @@ WebCore::IntPoint PageClientImpl::accessibilityScreenToRootView(const WebCore::I + + WebCore::IntRect PageClientImpl::rootViewToAccessibilityScreen(const WebCore::IntRect& rect) + { +- return rootViewToScreen(rect); ++ return rootViewToScreen(rect); + } + + void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent&, bool) +diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitBrowserInspector.h b/Source/WebKit/UIProcess/API/wpe/WebKitBrowserInspector.h +new file mode 100644 +index 0000000000000000000000000000000000000000..cb1a540d341b07581ec87b922b7d007ce45ba989 +--- /dev/null ++++ b/Source/WebKit/UIProcess/API/wpe/WebKitBrowserInspector.h +@@ -0,0 +1,81 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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 !defined(__WEBKIT_H_INSIDE__) && !defined(WEBKIT2_COMPILATION) ++#error "Only can be included directly." ++#endif ++ ++#ifndef WebKitBrowserInspector_h ++#define WebKitBrowserInspector_h ++ ++#include ++#include ++#include ++ ++G_BEGIN_DECLS ++ ++#define WEBKIT_TYPE_BROWSER_INSPECTOR (webkit_browser_inspector_get_type()) ++#define WEBKIT_BROWSER_INSPECTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_BROWSER_INSPECTOR, WebKitBrowserInspector)) ++#define WEBKIT_IS_BROWSER_INSPECTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_BROWSER_INSPECTOR)) ++#define WEBKIT_BROWSER_INSPECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_BROWSER_INSPECTOR, WebKitBrowserInspectorClass)) ++#define WEBKIT_IS_BROWSER_INSPECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_BROWSER_INSPECTOR)) ++#define WEBKIT_BROWSER_INSPECTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_BROWSER_INSPECTOR, WebKitBrowserInspectorClass)) ++ ++typedef struct _WebKitBrowserInspector WebKitBrowserInspector; ++typedef struct _WebKitBrowserInspectorClass WebKitBrowserInspectorClass; ++typedef struct _WebKitBrowserInspectorPrivate WebKitBrowserInspectorPrivate; ++ ++struct _WebKitBrowserInspector { ++ GObject parent; ++ ++ WebKitBrowserInspectorPrivate *priv; ++}; ++ ++struct _WebKitBrowserInspectorClass { ++ GObjectClass parent_class; ++ ++ WebKitWebView *(* create_new_page) (WebKitBrowserInspector *browser_inspector, ++ WebKitWebContext *context); ++ WebKitWebView *(* quit_application) (WebKitBrowserInspector *browser_inspector); ++ ++ void (*_webkit_reserved0) (void); ++ void (*_webkit_reserved1) (void); ++ void (*_webkit_reserved2) (void); ++ void (*_webkit_reserved3) (void); ++}; ++ ++WEBKIT_API GType ++webkit_browser_inspector_get_type (void); ++ ++WEBKIT_API WebKitBrowserInspector * ++webkit_browser_inspector_get_default (void); ++ ++WEBKIT_API void ++webkit_browser_inspector_initialize_pipe (const char* defaultProxyURI, ++ const char* const* ignoreHosts); ++ ++G_END_DECLS ++ ++#endif +diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.cpp b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.cpp +index e0fc205b39095cf8aae201a1dcca520461c60de4..872186ad99a7b82f0c61705ff6c5ae4453e5e1d4 100644 +--- a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.cpp ++++ b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.cpp +@@ -54,6 +54,7 @@ struct _WebKitWebViewBackend { + struct wpe_view_backend* backend; + GDestroyNotify notifyCallback; + gpointer notifyCallbackData; ++ take_screenshot_callback screenshotCallback; + int referenceCount { 1 }; + }; + +@@ -116,6 +117,19 @@ struct wpe_view_backend* webkit_web_view_backend_get_wpe_backend(WebKitWebViewBa + return viewBackend->backend; + } + ++void webkit_web_view_backend_set_screenshot_callback(WebKitWebViewBackend *view_backend, take_screenshot_callback callback) ++{ ++ view_backend->screenshotCallback = callback; ++} ++ ++cairo_surface_t* webkitWebViewBackendTakeScreenshot(WebKitWebViewBackend* view_backend) ++{ ++ if (!view_backend->screenshotCallback) ++ return nullptr; ++ ++ return view_backend->screenshotCallback(view_backend->notifyCallbackData); ++} ++ + namespace WTF { + + template <> WebKitWebViewBackend* refGPtr(WebKitWebViewBackend* ptr) +diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.h b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.h +index 6663964d5abac79e123d90e0351590884c66aa72..13ba5e7c3895c6e4efda95f1f90b9baea1c1bf30 100644 +--- a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.h ++++ b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.h +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + G_BEGIN_DECLS + +@@ -44,6 +45,12 @@ webkit_web_view_backend_new (struct wpe_view_backend *backend, + WEBKIT_API struct wpe_view_backend * + webkit_web_view_backend_get_wpe_backend (WebKitWebViewBackend *view_backend); + ++typedef cairo_surface_t* (*take_screenshot_callback)(gpointer user_data); ++ ++WEBKIT_API void ++webkit_web_view_backend_set_screenshot_callback (WebKitWebViewBackend *view_backend, ++ take_screenshot_callback callback); ++ + G_END_DECLS + + #endif /* WebKitWebViewBackend_h */ +diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackendPrivate.h b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackendPrivate.h +index e4b92ace1531090ae38a7aec3d3d4febf19aee84..43690f9ef4969a39084501613bfc00a77fd5df49 100644 +--- a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackendPrivate.h ++++ b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackendPrivate.h +@@ -31,3 +31,5 @@ template <> void derefGPtr(WebKitWebViewBackend* ptr); + } + + void webkitWebViewBackendUnref(WebKitWebViewBackend*); ++ ++cairo_surface_t* webkitWebViewBackendTakeScreenshot(WebKitWebViewBackend*); +diff --git a/Source/WebKit/UIProcess/API/wpe/docs/wpe-1.0-sections.txt b/Source/WebKit/UIProcess/API/wpe/docs/wpe-1.0-sections.txt +index 825d5100b6a69acf5a7a209538376d2c852dbac8..0128d1ad0256593f3e7c0313b932a0cc655144e7 100644 +--- a/Source/WebKit/UIProcess/API/wpe/docs/wpe-1.0-sections.txt ++++ b/Source/WebKit/UIProcess/API/wpe/docs/wpe-1.0-sections.txt +@@ -317,6 +317,8 @@ WEBKIT_TYPE_WEB_VIEW_BACKEND + WebKitWebViewBackend + webkit_web_view_backend_get_wpe_backend + webkit_web_view_backend_new ++take_screenshot_callback ++webkit_web_view_backend_set_screenshot_callback + + + webkit_web_view_backend_get_type +diff --git a/Source/WebKit/UIProcess/API/wpe/webkit.h b/Source/WebKit/UIProcess/API/wpe/webkit.h +index 27c680d46428d349b0d1119f12da56ff283a60aa..1980aff7d662a1eea450d2db78b41f12a04f715e 100644 +--- a/Source/WebKit/UIProcess/API/wpe/webkit.h ++++ b/Source/WebKit/UIProcess/API/wpe/webkit.h +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + #include + #include + #include +diff --git a/Source/WebKit/UIProcess/BackingStore.h b/Source/WebKit/UIProcess/BackingStore.h +index fe3c63e61f778762dc2c2080c74ec53fdf8c2e5f..c43a8226c9be702e248f1712e465efa396ee8969 100644 +--- a/Source/WebKit/UIProcess/BackingStore.h ++++ b/Source/WebKit/UIProcess/BackingStore.h +@@ -60,6 +60,7 @@ public: + + #if USE(CAIRO) + typedef cairo_t* PlatformGraphicsContext; ++ cairo_surface_t* surface() const; + #elif USE(DIRECT2D) + struct DXConnections { + ID3D11DeviceContext1* immediateContext { nullptr }; +diff --git a/Source/WebKit/UIProcess/BrowserInspectorPipe.cpp b/Source/WebKit/UIProcess/BrowserInspectorPipe.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..dc8af6fe1c57bcd62d605fd1daa3da13361858bb +--- /dev/null ++++ b/Source/WebKit/UIProcess/BrowserInspectorPipe.cpp +@@ -0,0 +1,57 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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 "BrowserInspectorPipe.h" ++ ++#if ENABLE(REMOTE_INSPECTOR) ++ ++#include "InspectorPlaywrightAgent.h" ++#include "RemoteInspectorPipe.h" ++#include ++#include "InspectorPlaywrightAgentClient.h" ++ ++namespace WebKit { ++ ++void initializeBrowserInspectorPipe(std::unique_ptr client) ++{ ++ class BrowserInspectorPipe { ++ public: ++ BrowserInspectorPipe(std::unique_ptr client) ++ : m_playwrightAgent(std::move(client)) ++ , m_remoteInspectorPipe(m_playwrightAgent) ++ { ++ } ++ ++ InspectorPlaywrightAgent m_playwrightAgent; ++ RemoteInspectorPipe m_remoteInspectorPipe; ++ }; ++ ++ static NeverDestroyed pipe(std::move(client)); ++} ++ ++} // namespace WebKit ++ ++#endif // ENABLE(REMOTE_INSPECTOR) +diff --git a/Source/WebKit/UIProcess/BrowserInspectorPipe.h b/Source/WebKit/UIProcess/BrowserInspectorPipe.h +new file mode 100644 +index 0000000000000000000000000000000000000000..cd66887de171cda7d15a8e4dc6dbff63665dc619 +--- /dev/null ++++ b/Source/WebKit/UIProcess/BrowserInspectorPipe.h +@@ -0,0 +1,38 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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. ++ */ ++ ++#pragma once ++ ++#if ENABLE(REMOTE_INSPECTOR) ++ ++namespace WebKit { ++ ++class InspectorPlaywrightAgentClient; ++ ++void initializeBrowserInspectorPipe(std::unique_ptr client); ++ ++} // namespace WebKit ++ ++#endif // ENABLE(REMOTE_INSPECTOR) +diff --git a/Source/WebKit/UIProcess/Cocoa/AutomationClient.mm b/Source/WebKit/UIProcess/Cocoa/AutomationClient.mm +index 02dadcc4c813ad82c718f16a583616e03e35a195..5211c6b38efaf2a62eb556ec060cd9caa5e5d40e 100644 +--- a/Source/WebKit/UIProcess/Cocoa/AutomationClient.mm ++++ b/Source/WebKit/UIProcess/Cocoa/AutomationClient.mm +@@ -35,6 +35,7 @@ + #import + #import + #import ++#import + + using namespace Inspector; + +diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h +index 454c61ffdefecc476d1560c7c43f5b5d345f281d..6de7509037b7683ddd403ee247bdf2845ce4e87a 100644 +--- a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h ++++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h +@@ -27,6 +27,8 @@ + + #if HAVE(APP_SSO) + ++#include ++#include + #include "SOAuthorizationSession.h" + #include + +@@ -39,6 +41,8 @@ class NavigationAction; + + namespace WebKit { + ++class WebPageProxy; ++ + // FSM: Idle => Active => Completed + class PopUpSOAuthorizationSession final : public SOAuthorizationSession { + public: +diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.mm b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.mm +index 0f18038de989e69a8432c85b71b6c04e931302b3..82a966779403346aed174dcfcd01a79691956d7b 100644 +--- a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.mm ++++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.mm +@@ -29,6 +29,7 @@ + #if HAVE(APP_SSO) + + #import "APINavigationAction.h" ++#import "WebPageProxy.h" + #import "WKNavigationDelegatePrivate.h" + #import "WKUIDelegate.h" + #import "WKWebViewConfigurationPrivate.h" +diff --git a/Source/WebKit/UIProcess/Cocoa/UIDelegate.h b/Source/WebKit/UIProcess/Cocoa/UIDelegate.h +index 909d9200580ce551e36c71997cec72ca38446583..4ecff0e335fb15b5857b828109f6b466892d1c68 100644 +--- a/Source/WebKit/UIProcess/Cocoa/UIDelegate.h ++++ b/Source/WebKit/UIProcess/Cocoa/UIDelegate.h +@@ -92,6 +92,7 @@ private: + void runJavaScriptAlert(WebPageProxy&, const WTF::String&, WebFrameProxy*, FrameInfoData&&, Function&& completionHandler) final; + void runJavaScriptConfirm(WebPageProxy&, const WTF::String&, WebFrameProxy*, FrameInfoData&&, Function&& completionHandler) final; + void runJavaScriptPrompt(WebPageProxy&, const WTF::String&, const WTF::String&, WebFrameProxy*, FrameInfoData&&, Function&&) final; ++ void handleJavaScriptDialog(WebKit::WebPageProxy&, bool accept, const WTF::String&) final; + void presentStorageAccessConfirmDialog(const WTF::String& requestingDomain, const WTF::String& currentDomain, CompletionHandler&&); + void requestStorageAccessConfirm(WebPageProxy&, WebFrameProxy*, const WebCore::RegistrableDomain& requestingDomain, const WebCore::RegistrableDomain& currentDomain, CompletionHandler&&) final; + void decidePolicyForGeolocationPermissionRequest(WebPageProxy&, WebFrameProxy&, const FrameInfoData&, Function&) final; +@@ -178,6 +179,7 @@ private: + bool webViewRunJavaScriptAlertPanelWithMessageInitiatedByFrameCompletionHandler : 1; + bool webViewRunJavaScriptConfirmPanelWithMessageInitiatedByFrameCompletionHandler : 1; + bool webViewRunJavaScriptTextInputPanelWithPromptDefaultTextInitiatedByFrameCompletionHandler : 1; ++ bool webViewHandleJavaScriptDialogValue : 1; + bool webViewRequestStorageAccessPanelUnderFirstPartyCompletionHandler : 1; + bool webViewRunBeforeUnloadConfirmPanelWithMessageInitiatedByFrameCompletionHandler : 1; + bool webViewRequestGeolocationPermissionForFrameDecisionHandler : 1; +diff --git a/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm b/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm +index f078994c0253b92e548c283879d88e44306fff76..9d70a9295af7f5b8003788dd7635932fc2c2bcbc 100644 +--- a/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm ++++ b/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm +@@ -104,6 +104,7 @@ void UIDelegate::setDelegate(id delegate) + m_delegateMethods.webViewRunJavaScriptAlertPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:)]; + m_delegateMethods.webViewRunJavaScriptConfirmPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:completionHandler:)]; + m_delegateMethods.webViewRunJavaScriptTextInputPanelWithPromptDefaultTextInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:completionHandler:)]; ++ m_delegateMethods.webViewHandleJavaScriptDialogValue = [delegate respondsToSelector:@selector(webView:handleJavaScriptDialog:value:)]; + m_delegateMethods.webViewRequestStorageAccessPanelUnderFirstPartyCompletionHandler = [delegate respondsToSelector:@selector(_webView:requestStorageAccessPanelForDomain:underCurrentDomain:completionHandler:)]; + m_delegateMethods.webViewRunBeforeUnloadConfirmPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(_webView:runBeforeUnloadConfirmPanelWithMessage:initiatedByFrame:completionHandler:)]; + m_delegateMethods.webViewRequestGeolocationPermissionForFrameDecisionHandler = [delegate respondsToSelector:@selector(_webView:requestGeolocationPermissionForFrame:decisionHandler:)]; +@@ -363,6 +364,15 @@ void UIDelegate::UIClient::runJavaScriptPrompt(WebPageProxy& page, const WTF::St + }).get()]; + } + ++void UIDelegate::UIClient::handleJavaScriptDialog(WebKit::WebPageProxy&, bool accept, const WTF::String& value) { ++ if (!m_uiDelegate->m_delegateMethods.webViewHandleJavaScriptDialogValue) ++ return; ++ auto delegate = m_uiDelegate->m_delegate.get(); ++ if (!delegate) ++ return; ++ [delegate webView:m_uiDelegate->m_webView.get().get() handleJavaScriptDialog:accept value:value]; ++} ++ + void UIDelegate::UIClient::requestStorageAccessConfirm(WebPageProxy& webPageProxy, WebFrameProxy*, const WebCore::RegistrableDomain& requestingDomain, const WebCore::RegistrableDomain& currentDomain, CompletionHandler&& completionHandler) + { + if (!m_uiDelegate) +diff --git a/Source/WebKit/UIProcess/Cocoa/WKBlankOverlayView.mm b/Source/WebKit/UIProcess/Cocoa/WKBlankOverlayView.mm +index 77adfc78b4a1a93c112da563a70a1de1ee73b947..1754517afa1fdcb30a6b8ee7a81da2c40c36fcec 100644 +--- a/Source/WebKit/UIProcess/Cocoa/WKBlankOverlayView.mm ++++ b/Source/WebKit/UIProcess/Cocoa/WKBlankOverlayView.mm +@@ -24,7 +24,7 @@ + */ + + #import "config.h" +-#import "WKBlankOverlayView.mm" ++#import "WKBlankOverlayView.h" + + @implementation WKBlankOverlayView { + } +diff --git a/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm b/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm +index feec8fd9d67e9c0cde0d2f5509ba51b15616a9b1..0419fa930c9f5d74ea5c655a161f8582c56080ac 100644 +--- a/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm ++++ b/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm +@@ -34,6 +34,7 @@ + #import "InsertTextOptions.h" + #import "LoadParameters.h" + #import "PageClient.h" ++#import "PasteboardTypes.h" + #import "QuickLookThumbnailLoader.h" + #import "SafeBrowsingSPI.h" + #import "SafeBrowsingWarning.h" +@@ -217,9 +218,64 @@ bool WebPageProxy::scrollingUpdatesDisabledForTesting() + + void WebPageProxy::startDrag(const DragItem& dragItem, const ShareableBitmap::Handle& dragImageHandle) + { ++ if (m_interceptDrags) { ++ NSPasteboard *pasteboard = [NSPasteboard pasteboardWithName: m_overrideDragPasteboardName]; ++ ++ m_dragSelectionData = String([pasteboard name]); ++ grantAccessToCurrentPasteboardData(String([pasteboard name])); ++ m_dragSourceOperationMask = WebCore::anyDragOperation(); ++ ++ if (auto& info = dragItem.promisedAttachmentInfo) { ++ NSString *utiType = info.contentType; ++ if (auto attachment = attachmentForIdentifier(info.attachmentIdentifier)) ++ utiType = attachment->utiType(); ++ ++ if (!utiType.length) { ++ dragCancelled(); ++ return; ++ } ++ ++ ASSERT(info.additionalTypes.size() == info.additionalData.size()); ++ if (info.additionalTypes.size() == info.additionalData.size()) { ++ for (size_t index = 0; index < info.additionalTypes.size(); ++index) { ++ auto nsData = info.additionalData[index]->createNSData(); ++ [pasteboard setData:nsData.get() forType:info.additionalTypes[index]]; ++ } ++ } ++ } else { ++ [pasteboard setString:@"" forType:PasteboardTypes::WebDummyPboardType]; ++ } ++ didStartDrag(); ++ return; ++ } ++ + pageClient().startDrag(dragItem, dragImageHandle); + } + ++void WebPageProxy::releaseInspectorDragPasteboard() { ++ if (!!m_dragSelectionData) ++ m_dragSelectionData = WTF::nullopt; ++ if (!m_overrideDragPasteboardName.isEmpty()) { ++ NSPasteboard *pasteboard = [NSPasteboard pasteboardWithUniqueName]; ++ [pasteboard releaseGlobally]; ++ m_overrideDragPasteboardName = ""; ++ } ++} ++ ++ ++void WebPageProxy::setInterceptDrags(bool shouldIntercept) { ++ m_interceptDrags = shouldIntercept; ++ if (m_interceptDrags) { ++ if (m_overrideDragPasteboardName.isEmpty()) { ++ NSPasteboard *pasteboard = [NSPasteboard pasteboardWithUniqueName]; ++ m_overrideDragPasteboardName = String([pasteboard name]); ++ } ++ send(Messages::WebPage::SetDragPasteboardName(m_overrideDragPasteboardName)); ++ } else { ++ send(Messages::WebPage::SetDragPasteboardName("")); ++ } ++} ++ + // FIXME: Move these functions to WebPageProxyIOS.mm. + #if PLATFORM(IOS_FAMILY) + +diff --git a/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm b/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm +index 7e7aa05ef750677f4393685bb7628b476ea2a769..d5474964bd80387ae5acd6e6114c17acee9fc765 100644 +--- a/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm ++++ b/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm +@@ -398,7 +398,7 @@ void WebProcessPool::platformInitializeWebProcess(const WebProcessProxy& process + auto screenProperties = WebCore::collectScreenProperties(); + parameters.screenProperties = WTFMove(screenProperties); + #if PLATFORM(MAC) +- parameters.useOverlayScrollbars = ([NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay); ++ parameters.useOverlayScrollbars = m_configuration->forceOverlayScrollbars() || ([NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay); + #endif + + #if PLATFORM(IOS) +@@ -671,8 +671,8 @@ void WebProcessPool::registerNotificationObservers() + + #if ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING) + m_scrollerStyleNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSPreferredScrollerStyleDidChangeNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) { +- auto scrollbarStyle = [NSScroller preferredScrollerStyle]; +- sendToAllProcesses(Messages::WebProcess::ScrollerStylePreferenceChanged(scrollbarStyle)); ++ bool useOverlayScrollbars = m_configuration->forceOverlayScrollbars() || ([NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay); ++ sendToAllProcesses(Messages::WebProcess::ScrollerStylePreferenceChanged(useOverlayScrollbars)); + }]; + #endif + +diff --git a/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h b/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h +index 056c39e4b63fbcd8d99436a61664fe00357152f3..f7078b32991a986723069a235f4b61d026cd8134 100644 +--- a/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h ++++ b/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h +@@ -499,6 +499,9 @@ public: + void provideDataForPasteboard(NSPasteboard *, NSString *type); + NSArray *namesOfPromisedFilesDroppedAtDestination(NSURL *dropDestination); + ++// Paywright begin ++ RetainPtr takeSnapshotForAutomation(); ++// Paywright end + RefPtr takeViewSnapshot(); + void saveBackForwardSnapshotForCurrentItem(); + void saveBackForwardSnapshotForItem(WebBackForwardListItem&); +diff --git a/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm b/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm +index a5c6bbc0ccfe4fb2eb309777ce8f7e7ca6bb399c..2f098834bbb6609c99237b3a31d17bef93bae85f 100644 +--- a/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm ++++ b/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm +@@ -4520,6 +4520,18 @@ static RetainPtr takeWindowSnapshot(CGSWindowID windowID, bool captu + return adoptCF(CGWindowListCreateImage(CGRectNull, kCGWindowListOptionIncludingWindow, windowID, imageOptions)); + } + ++// Paywright begin ++RetainPtr WebViewImpl::takeSnapshotForAutomation() { ++ NSWindow *window = [m_view window]; ++ ++ CGSWindowID windowID = (CGSWindowID)window.windowNumber; ++ if (!windowID || !window.isVisible) ++ return nullptr; ++ ++ return takeWindowSnapshot(windowID, true); ++} ++// Paywright end ++ + RefPtr WebViewImpl::takeViewSnapshot() + { + NSWindow *window = [m_view window]; +diff --git a/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp b/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp +index 5a51b9ec1d68feecb5cf46a10d07c62785ad1fb0..1e165124020ac9e520123a0503d2a4ec30d7c32b 100644 +--- a/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp ++++ b/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp +@@ -32,13 +32,16 @@ + #include "DrawingAreaProxyMessages.h" + #include "LayerTreeContext.h" + #include "UpdateInfo.h" ++#include "WebPageInspectorController.h" + #include "WebPageProxy.h" + #include "WebPreferences.h" + #include "WebProcessProxy.h" + #include + #include ++#include + + #if PLATFORM(GTK) ++#include "WebKitWebViewBasePrivate.h" + #include + #endif + +@@ -51,6 +54,13 @@ + #include + #endif + ++#if PLATFORM(WIN) ++#include ++#include ++#include ++#include ++#endif ++ + namespace WebKit { + using namespace WebCore; + +@@ -119,6 +129,10 @@ void DrawingAreaProxyCoordinatedGraphics::paint(BackingStore::PlatformGraphicsCo + + void DrawingAreaProxyCoordinatedGraphics::sizeDidChange() + { ++ for (auto& value : m_callbacks) ++ value(); ++ m_callbacks.clear(); ++ + #if USE(DIRECT2D) + m_backingStore = nullptr; + #endif +@@ -133,6 +147,11 @@ void DrawingAreaProxyCoordinatedGraphics::deviceScaleFactorDidChange() + backingStoreStateDidChange(RespondImmediately); + } + ++void DrawingAreaProxyCoordinatedGraphics::waitForSizeUpdate(Function&& callback) ++{ ++ m_callbacks.append(WTFMove(callback)); ++} ++ + void DrawingAreaProxyCoordinatedGraphics::waitForBackingStoreUpdateOnNextPaint() + { + m_hasReceivedFirstUpdate = true; +@@ -238,6 +257,45 @@ void DrawingAreaProxyCoordinatedGraphics::updateAcceleratedCompositingMode(uint6 + updateAcceleratedCompositingMode(layerTreeContext); + } + ++#if PLATFORM(WIN) ++void DrawingAreaProxyCoordinatedGraphics::didChangeAcceleratedCompositingMode(bool enabled) ++{ ++ m_isInAcceleratedCompositingMode = enabled; ++} ++#endif ++ ++#if !PLATFORM(WPE) ++void DrawingAreaProxyCoordinatedGraphics::captureFrame() ++{ ++ RefPtr surface; ++#if PLATFORM(WIN) ++ HWndDC dc; ++ if (m_isInAcceleratedCompositingMode) { ++ dc.setHWnd(m_webPageProxy.viewWidget()); ++ surface = adoptRef(cairo_win32_surface_create(dc)); ++#else ++ if (isInAcceleratedCompositingMode()) { ++# if PLATFORM(GTK) ++ AcceleratedBackingStore* backingStore = webkitWebViewBaseGetAcceleratedBackingStore(WEBKIT_WEB_VIEW_BASE(m_webPageProxy.viewWidget())); ++ if (!backingStore) ++ return; ++ ++ surface = backingStore->surface(); ++# else ++ fprintf(stderr, "captureFrame() is not supported in accelerated compositing mode on this platform.\n"); ++# endif ++#endif ++ } else if (m_backingStore) { ++ surface = m_backingStore->surface(); ++ } ++ ++ if (!surface) ++ return; ++ ++ m_webPageProxy.inspectorController().didPaint(surface.get()); ++} ++#endif ++ + #if !PLATFORM(WPE) + void DrawingAreaProxyCoordinatedGraphics::incorporateUpdate(const UpdateInfo& updateInfo) + { +diff --git a/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h b/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h +index d7695088e7cfc4f638f157338754f9f157489749..f99c2b7c2a2b5fa666aa7db96a124717eee0e922 100644 +--- a/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h ++++ b/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h +@@ -30,6 +30,7 @@ + #include "BackingStore.h" + #include "DrawingAreaProxy.h" + #include "LayerTreeContext.h" ++#include + #include + + namespace WebCore { +@@ -49,6 +50,10 @@ public: + + bool isInAcceleratedCompositingMode() const { return !m_layerTreeContext.isEmpty(); } + const LayerTreeContext& layerTreeContext() const { return m_layerTreeContext; } ++ void waitForSizeUpdate(Function&&); ++#if !PLATFORM(WPE) ++ void captureFrame(); ++#endif + + private: + // DrawingAreaProxy +@@ -63,6 +68,9 @@ private: + void enterAcceleratedCompositingMode(uint64_t backingStoreStateID, const LayerTreeContext&) override; + void exitAcceleratedCompositingMode(uint64_t backingStoreStateID, const UpdateInfo&) override; + void updateAcceleratedCompositingMode(uint64_t backingStoreStateID, const LayerTreeContext&) override; ++#if PLATFORM(WIN) ++ void didChangeAcceleratedCompositingMode(bool enabled) override; ++#endif + + #if !PLATFORM(WPE) + void incorporateUpdate(const UpdateInfo&); +@@ -126,12 +134,18 @@ private: + // For a new Drawing Area don't draw anything until the WebProcess has sent over the first content. + bool m_hasReceivedFirstUpdate { false }; + ++ Vector> m_callbacks; ++ + #if !PLATFORM(WPE) + bool m_isBackingStoreDiscardable { true }; + std::unique_ptr m_backingStore; + RunLoop::Timer m_discardBackingStoreTimer; + #endif + std::unique_ptr m_drawingMonitor; ++ ++#if PLATFORM(WIN) ++ bool m_isInAcceleratedCompositingMode { false }; ++#endif + }; + + } // namespace WebKit +diff --git a/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp b/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp +index c61bb3fd2ee046f3824c40ab99181c0fcee2a197..0fee368e936443cc15f02903f97fb6ad60f6091e 100644 +--- a/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp ++++ b/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp +@@ -42,8 +42,10 @@ + #include + #include + #include ++#include + #include + #include ++#include + + namespace WebKit { + using namespace WebCore; +@@ -56,7 +58,10 @@ DownloadProxy::DownloadProxy(DownloadProxyMap& downloadProxyMap, WebsiteDataStor + , m_request(resourceRequest) + , m_originatingPage(makeWeakPtr(originatingPage)) + , m_frameInfo(API::FrameInfo::create(FrameInfoData { frameInfoData }, originatingPage)) ++ , m_uuid(createCanonicalUUIDString()) + { ++ if (auto* instrumentation = m_dataStore->downloadInstrumentation()) ++ instrumentation->downloadCreated(m_uuid, m_request, frameInfoData, originatingPage); + } + + DownloadProxy::~DownloadProxy() +@@ -79,6 +84,8 @@ void DownloadProxy::cancel(CompletionHandler&& completionHandl + m_legacyResumeData = createData(resumeData); + completionHandler(m_legacyResumeData.get()); + m_downloadProxyMap.downloadFinished(*this); ++ if (auto* instrumentation = m_dataStore->downloadInstrumentation()) ++ instrumentation->downloadFinished(m_uuid, "canceled"_s); + }); + } else + completionHandler(nullptr); +@@ -161,6 +168,20 @@ void DownloadProxy::decideDestinationWithSuggestedFilename(const WebCore::Resour + suggestedFilename = m_suggestedFilename; + suggestedFilename = MIMETypeRegistry::appendFileExtensionIfNecessary(suggestedFilename, response.mimeType()); + ++ if (auto* instrumentation = m_dataStore->downloadInstrumentation()) ++ instrumentation->downloadFilenameSuggested(m_uuid, suggestedFilename); ++ ++ if (m_dataStore->allowDownloadForAutomation()) { ++ SandboxExtension::Handle sandboxExtensionHandle; ++ String destination; ++ if (*m_dataStore->allowDownloadForAutomation()) { ++ destination = FileSystem::pathByAppendingComponent(m_dataStore->downloadPathForAutomation(), m_uuid); ++ SandboxExtension::createHandle(destination, SandboxExtension::Type::ReadWrite, sandboxExtensionHandle); ++ } ++ completionHandler(destination, WTFMove(sandboxExtensionHandle), AllowOverwrite::Yes); ++ return; ++ } ++ + m_client->decideDestinationWithSuggestedFilename(*this, response, ResourceResponseBase::sanitizeSuggestedFilename(suggestedFilename), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)] (AllowOverwrite allowOverwrite, String destination) mutable { + SandboxExtension::Handle sandboxExtensionHandle; + if (!destination.isNull()) +@@ -179,6 +200,8 @@ void DownloadProxy::didCreateDestination(const String& path) + void DownloadProxy::didFinish() + { + m_client->didFinish(*this); ++ if (auto* instrumentation = m_dataStore->downloadInstrumentation()) ++ instrumentation->downloadFinished(m_uuid, String()); + + // This can cause the DownloadProxy object to be deleted. + m_downloadProxyMap.downloadFinished(*this); +@@ -189,6 +212,8 @@ void DownloadProxy::didFail(const ResourceError& error, const IPC::DataReference + m_legacyResumeData = createData(resumeData); + + m_client->didFail(*this, error, m_legacyResumeData.get()); ++ if (auto* instrumentation = m_dataStore->downloadInstrumentation()) ++ instrumentation->downloadFinished(m_uuid, error.localizedDescription()); + + // This can cause the DownloadProxy object to be deleted. + m_downloadProxyMap.downloadFinished(*this); +diff --git a/Source/WebKit/UIProcess/Downloads/DownloadProxy.h b/Source/WebKit/UIProcess/Downloads/DownloadProxy.h +index 895208c3bc226d6fb12861da437cda381f48d637..22b77046e94ff46c74282d28545574fe013df915 100644 +--- a/Source/WebKit/UIProcess/Downloads/DownloadProxy.h ++++ b/Source/WebKit/UIProcess/Downloads/DownloadProxy.h +@@ -146,6 +146,7 @@ private: + #if PLATFORM(COCOA) + RetainPtr m_progress; + #endif ++ String m_uuid; + }; + + } // namespace WebKit +diff --git a/Source/WebKit/UIProcess/DrawingAreaProxy.h b/Source/WebKit/UIProcess/DrawingAreaProxy.h +index 59cdfdafab1d85ea3a5aecb3cd2293e6dfb1eb8d..2c9d8122919bed0b6d7e6f600e5b0c0f9732d1ff 100644 +--- a/Source/WebKit/UIProcess/DrawingAreaProxy.h ++++ b/Source/WebKit/UIProcess/DrawingAreaProxy.h +@@ -75,6 +75,7 @@ public: + + const WebCore::IntSize& size() const { return m_size; } + bool setSize(const WebCore::IntSize&, const WebCore::IntSize& scrollOffset = { }); ++ void waitForSizeUpdate(Function&&); + + #if USE(COORDINATED_GRAPHICS) || USE(TEXTURE_MAPPER) + // The timeout we use when waiting for a DidUpdateGeometry message. +@@ -160,6 +161,9 @@ private: + virtual void update(uint64_t /* backingStoreStateID */, const UpdateInfo&) { } + virtual void didUpdateBackingStoreState(uint64_t /* backingStoreStateID */, const UpdateInfo&, const LayerTreeContext&) { } + virtual void exitAcceleratedCompositingMode(uint64_t /* backingStoreStateID */, const UpdateInfo&) { } ++#endif ++#if PLATFORM(WIN) ++ virtual void didChangeAcceleratedCompositingMode(bool) { } + #endif + bool m_startedReceivingMessages { false }; + }; +diff --git a/Source/WebKit/UIProcess/DrawingAreaProxy.messages.in b/Source/WebKit/UIProcess/DrawingAreaProxy.messages.in +index b0722e7da81e56530deb570b82ed7cfece970362..05ec3e3ea97ba49135a27d7f9b91f14c507d9318 100644 +--- a/Source/WebKit/UIProcess/DrawingAreaProxy.messages.in ++++ b/Source/WebKit/UIProcess/DrawingAreaProxy.messages.in +@@ -36,4 +36,7 @@ messages -> DrawingAreaProxy NotRefCounted { + DidUpdateBackingStoreState(uint64_t backingStoreStateID, WebKit::UpdateInfo updateInfo, WebKit::LayerTreeContext context) + ExitAcceleratedCompositingMode(uint64_t backingStoreStateID, WebKit::UpdateInfo updateInfo) + #endif ++#if PLATFORM(WIN) ++ DidChangeAcceleratedCompositingMode(bool enabled) ++#endif + } +diff --git a/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..3f7bfd524cff408bfaea96177e39a4e22949e7e7 +--- /dev/null ++++ b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp +@@ -0,0 +1,168 @@ ++/* ++ * Copyright (C) 2020 Microsoft Corporation. ++ * ++ * 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 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 "InspectorScreencastAgent.h" ++ ++#include "GenericCallback.h" ++#include "PageClient.h" ++#include "ScreencastEncoder.h" ++#include "WebPageInspectorController.h" ++#include "WebPageProxy.h" ++#include "WebsiteDataStore.h" ++#include ++#include ++#include ++#include ++#include ++ ++#if USE(CAIRO) ++#include "DrawingAreaProxyCoordinatedGraphics.h" ++#include "DrawingAreaProxy.h" ++#endif ++ ++namespace WebKit { ++ ++using namespace Inspector; ++ ++InspectorScreencastAgent::InspectorScreencastAgent(BackendDispatcher& backendDispatcher, Inspector::FrontendRouter& frontendRouter, WebPageProxy& page) ++ : InspectorAgentBase("Screencast"_s) ++ , m_backendDispatcher(ScreencastBackendDispatcher::create(backendDispatcher, this)) ++ , m_page(page) ++{ ++} ++ ++InspectorScreencastAgent::~InspectorScreencastAgent() ++{ ++} ++ ++void InspectorScreencastAgent::didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) ++{ ++} ++ ++void InspectorScreencastAgent::willDestroyFrontendAndBackend(DisconnectReason) ++{ ++ if (!m_encoder) ++ return; ++ ++ // The agent may be destroyed when the callback is invoked. ++ m_encoder->finish([sessionID = m_page.websiteDataStore().sessionID(), screencastID = WTFMove(m_currentScreencastID)] { ++ if (WebPageInspectorController::observer()) ++ WebPageInspectorController::observer()->didFinishScreencast(sessionID, screencastID); ++ }); ++ ++ m_encoder = nullptr; ++} ++ ++#if USE(CAIRO) ++void InspectorScreencastAgent::didPaint(cairo_surface_t* surface) ++{ ++ if (m_encoder) ++ m_encoder->encodeFrame(surface, m_page.drawingArea()->size()); ++} ++#endif ++ ++Inspector::Protocol::ErrorStringOr InspectorScreencastAgent::start(const String& file, int width, int height, Optional&& scale) ++{ ++ if (m_encoder) ++ return makeUnexpected("Already recording"_s); ++ ++ if (width < 10 || width > 10000 || height < 10 || height > 10000) ++ return makeUnexpected("Invalid size"_s); ++ ++ if (scale && (*scale <= 0 || *scale > 1)) ++ return makeUnexpected("Unsupported scale"_s); ++ ++ String errorString; ++ m_encoder = ScreencastEncoder::create(errorString, file, WebCore::IntSize(width, height), WTFMove(scale)); ++ if (!m_encoder) ++ return makeUnexpected(errorString); ++ ++ m_currentScreencastID = createCanonicalUUIDString(); ++ ++#if PLATFORM(MAC) ++ m_encoder->setOffsetTop(m_page.pageClient().browserToolbarHeight()); ++#endif ++#if !PLATFORM(WPE) ++ scheduleFrameEncoding(); ++#endif ++ // Force at least one frame on WPE. ++ m_page.forceRepaint([] { }); ++ ++ return { { m_currentScreencastID } }; ++} ++ ++void InspectorScreencastAgent::stop(Ref&& callback) ++{ ++ if (!m_encoder) { ++ callback->sendFailure("Not recording"_s); ++ return; ++ } ++ ++ // The agent may be destroyed when the callback is invoked. ++ m_encoder->finish([sessionID = m_page.websiteDataStore().sessionID(), screencastID = WTFMove(m_currentScreencastID), callback = WTFMove(callback)] { ++ if (WebPageInspectorController::observer()) ++ WebPageInspectorController::observer()->didFinishScreencast(sessionID, screencastID); ++ callback->sendSuccess(); ++ }); ++ m_encoder = nullptr; ++} ++ ++#if !PLATFORM(WPE) ++void InspectorScreencastAgent::scheduleFrameEncoding() ++{ ++ if (!m_encoder) ++ return; ++ ++ RunLoop::main().dispatchAfter(Seconds(1.0 / ScreencastEncoder::fps), [agent = makeWeakPtr(this)]() mutable { ++ if (!agent) ++ return; ++ ++ agent->encodeFrame(); ++ agent->scheduleFrameEncoding(); ++ }); ++} ++#endif ++ ++#if PLATFORM(MAC) ++void InspectorScreencastAgent::encodeFrame() ++{ ++ if (m_encoder) ++ m_encoder->encodeFrame(m_page.pageClient().takeSnapshotForAutomation()); ++} ++#endif ++ ++#if USE(CAIRO) && !PLATFORM(WPE) ++void InspectorScreencastAgent::encodeFrame() ++{ ++ if (!m_encoder) ++ return; ++ ++ if (auto* drawingArea = m_page.drawingArea()) ++ static_cast(drawingArea)->captureFrame(); ++} ++#endif ++ ++} // namespace WebKit +diff --git a/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.h b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.h +new file mode 100644 +index 0000000000000000000000000000000000000000..0d4a837cbb0bbba71e32ed083a4c4cfe9b5e4a27 +--- /dev/null ++++ b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.h +@@ -0,0 +1,77 @@ ++/* ++ * Copyright (C) 2020 Microsoft Corporation. ++ * ++ * 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 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. ++ */ ++ ++#pragma once ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++namespace Inspector { ++class BackendDispatcher; ++class FrontendChannel; ++class FrontendRouter; ++class ScreencastFrontendDispatcher; ++} ++ ++namespace WebKit { ++ ++class ScreencastEncoder; ++class WebPageProxy; ++ ++class InspectorScreencastAgent : public Inspector::InspectorAgentBase, public Inspector::ScreencastBackendDispatcherHandler, public CanMakeWeakPtr { ++ WTF_MAKE_NONCOPYABLE(InspectorScreencastAgent); ++ WTF_MAKE_FAST_ALLOCATED; ++public: ++ InspectorScreencastAgent(Inspector::BackendDispatcher& backendDispatcher, Inspector::FrontendRouter& frontendRouter, WebPageProxy& page); ++ ~InspectorScreencastAgent() override; ++ ++ void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) override; ++ void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override; ++ ++#if USE(CAIRO) ++ void didPaint(cairo_surface_t*); ++#endif ++ ++ Inspector::Protocol::ErrorStringOr start(const String& file, int width, int height, Optional&& scale) override; ++ void stop(Ref&&) override; ++ ++ ++private: ++#if !PLATFORM(WPE) ++ void scheduleFrameEncoding(); ++ void encodeFrame(); ++#endif ++ ++ Ref m_backendDispatcher; ++ WebPageProxy& m_page; ++ RefPtr m_encoder; ++ String m_currentScreencastID; ++}; ++ ++} // namespace WebKit +diff --git a/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.cpp b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..eca2c4cd9c8d312ad519e312c99f0b0a2435c9eb +--- /dev/null ++++ b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.cpp +@@ -0,0 +1,393 @@ ++/* ++ * Copyright (c) 2010, The WebM Project authors. All rights reserved. ++ * Copyright (c) 2013 The Chromium Authors. All rights reserved. ++ * Copyright (C) 2020 Microsoft Corporation. ++ * ++ * 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 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 "ScreencastEncoder.h" ++ ++#include "WebMFileWriter.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if USE(CAIRO) ++#include ++#endif ++ ++using namespace WebCore; ++ ++namespace WebKit { ++ ++namespace { ++ ++// Number of timebase unints per one frame. ++constexpr int timeScale = 1000; ++ ++// Defines the dimension of a macro block. This is used to compute the active ++// map for the encoder. ++const int kMacroBlockSize = 16; ++ ++void createImage(unsigned int width, unsigned int height, ++ std::unique_ptr& out_image, ++ std::unique_ptr& out_image_buffer) { ++ std::unique_ptr image(new vpx_image_t()); ++ memset(image.get(), 0, sizeof(vpx_image_t)); ++ ++ // libvpx seems to require both to be assigned. ++ image->d_w = width; ++ image->w = width; ++ image->d_h = height; ++ image->h = height; ++ ++ // I420 ++ image->fmt = VPX_IMG_FMT_YV12; ++ image->x_chroma_shift = 1; ++ image->y_chroma_shift = 1; ++ ++ // libyuv's fast-path requires 16-byte aligned pointers and strides, so pad ++ // the Y, U and V planes' strides to multiples of 16 bytes. ++ const int y_stride = ((image->w - 1) & ~15) + 16; ++ const int uv_unaligned_stride = y_stride >> image->x_chroma_shift; ++ const int uv_stride = ((uv_unaligned_stride - 1) & ~15) + 16; ++ ++ // libvpx accesses the source image in macro blocks, and will over-read ++ // if the image is not padded out to the next macroblock: crbug.com/119633. ++ // Pad the Y, U and V planes' height out to compensate. ++ // Assuming macroblocks are 16x16, aligning the planes' strides above also ++ // macroblock aligned them. ++ static_assert(kMacroBlockSize == 16, "macroblock_size_not_16"); ++ const int y_rows = ((image->h - 1) & ~(kMacroBlockSize-1)) + kMacroBlockSize; ++ const int uv_rows = y_rows >> image->y_chroma_shift; ++ ++ // Allocate a YUV buffer large enough for the aligned data & padding. ++ const int buffer_size = y_stride * y_rows + 2*uv_stride * uv_rows; ++ std::unique_ptr image_buffer(new uint8_t[buffer_size]); ++ ++ // Reset image value to 128 so we just need to fill in the y plane. ++ memset(image_buffer.get(), 128, buffer_size); ++ ++ // Fill in the information for |image_|. ++ unsigned char* uchar_buffer = ++ reinterpret_cast(image_buffer.get()); ++ image->planes[0] = uchar_buffer; ++ image->planes[1] = image->planes[0] + y_stride * y_rows; ++ image->planes[2] = image->planes[1] + uv_stride * uv_rows; ++ image->stride[0] = y_stride; ++ image->stride[1] = uv_stride; ++ image->stride[2] = uv_stride; ++ ++ out_image = std::move(image); ++ out_image_buffer = std::move(image_buffer); ++} ++ ++} // namespace ++ ++class ScreencastEncoder::VPXFrame { ++ WTF_MAKE_NONCOPYABLE(VPXFrame); ++ WTF_MAKE_FAST_ALLOCATED; ++public: ++#if USE(CAIRO) ++ explicit VPXFrame(RefPtr&& surface) ++ : m_surface(WTFMove(surface)) ++ { } ++#elif PLATFORM(MAC) ++ VPXFrame(RetainPtr windowImage, Optional scale, int offsetTop) ++ : m_windowImage(WTFMove(windowImage)) ++ , m_scale(scale) ++ , m_offsetTop(offsetTop) ++ { } ++#endif ++ ++ void setDuration(Seconds duration) { m_duration = duration; } ++ Seconds duration() const { return m_duration; } ++ ++ void convertToVpxImage(vpx_image_t* image) ++ { ++#if USE(CAIRO) ++ // Convert the updated region to YUV ready for encoding. ++ const uint8_t* argb_data = cairo_image_surface_get_data(m_surface.get()); ++ int argb_stride = cairo_image_surface_get_stride(m_surface.get()); ++#elif PLATFORM(MAC) ++ int argb_stride = image->w * 4; ++ UniqueArray buffer = makeUniqueArray(argb_stride * image->h); ++ uint8_t* argb_data = buffer.get(); ++ ScreencastEncoder::imageToARGB(m_windowImage.get(), argb_data, image->w, image->h, m_scale, m_offsetTop); ++#endif ++ const int y_stride = image->stride[0]; ++ ASSERT(image->stride[1] == image->stride[2]); ++ const int uv_stride = image->stride[1]; ++ uint8_t* y_data = image->planes[0]; ++ uint8_t* u_data = image->planes[1]; ++ uint8_t* v_data = image->planes[2]; ++ ++ // TODO: redraw only damaged regions? ++ libyuv::ARGBToI420(argb_data, argb_stride, ++ y_data, y_stride, ++ u_data, uv_stride, ++ v_data, uv_stride, ++ image->w, image->h); ++ } ++ ++private: ++#if USE(CAIRO) ++ RefPtr m_surface; ++#elif PLATFORM(MAC) ++ RetainPtr m_windowImage; ++ Optional m_scale; ++ int m_offsetTop { 0 }; ++#endif ++ Seconds m_duration; ++}; ++ ++ ++class ScreencastEncoder::VPXCodec { ++public: ++ VPXCodec(vpx_codec_ctx_t codec, vpx_codec_enc_cfg_t cfg, FILE* file) ++ : m_encoderQueue(WorkQueue::create("Screencast encoder")) ++ , m_codec(codec) ++ , m_cfg(cfg) ++ , m_file(file) ++ , m_writer(new WebMFileWriter(file, &m_cfg)) ++ { ++ createImage(cfg.g_w, cfg.g_h, m_image, m_imageBuffer); ++ } ++ ++ void encodeFrameAsync(std::unique_ptr&& frame) ++ { ++ m_encoderQueue->dispatch([this, frame = WTFMove(frame)] { ++ frame->convertToVpxImage(m_image.get()); ++ double frameCount = frame->duration().seconds() * fps; ++ // For long duration repeat frame at 1 fps to ensure last frame duration is short enough. ++ // TODO: figure out why simply passing duration doesn't work well. ++ for (;frameCount > 1.5; frameCount -= 1) { ++ encodeFrame(m_image.get(), timeScale); ++ } ++ encodeFrame(m_image.get(), std::max(1, frameCount * timeScale)); ++ }); ++ } ++ ++ void finishAsync(Function&& callback) ++ { ++ m_encoderQueue->dispatch([this, callback = WTFMove(callback)] { ++ finish(); ++ callback(); ++ }); ++ } ++ ++private: ++ bool encodeFrame(vpx_image_t *img, int duration) ++ { ++ vpx_codec_iter_t iter = nullptr; ++ const vpx_codec_cx_pkt_t *pkt = nullptr; ++ int flags = 0; ++ const vpx_codec_err_t res = vpx_codec_encode(&m_codec, img, m_pts, duration, flags, VPX_DL_REALTIME); ++ if (res != VPX_CODEC_OK) { ++ fprintf(stderr, "Failed to encode frame: %s\n", vpx_codec_error(&m_codec)); ++ return false; ++ } ++ ++ bool gotPkts = false; ++ while ((pkt = vpx_codec_get_cx_data(&m_codec, &iter)) != nullptr) { ++ gotPkts = true; ++ ++ if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { ++ if (!m_writer->writeFrame(pkt)) { ++ fprintf(stderr, "Failed to write compressed frame\n"); ++ return false; ++ } ++ ++m_frameCount; ++ // fprintf(stderr, " #%03d %spts=%" PRId64 " sz=%zd\n", m_frameCount, (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0 ? "[K] " : "", pkt->data.frame.pts, pkt->data.frame.sz); ++ m_pts += pkt->data.frame.duration; ++ } ++ } ++ ++ return gotPkts; ++ } ++ ++ void finish() ++ { ++ // Flush encoder. ++ while (encodeFrame(nullptr, 1)) ++ ++m_frameCount; ++ ++ m_writer->finish(); ++ fclose(m_file); ++ // fprintf(stderr, "ScreencastEncoder::finish %d frames\n", m_frameCount); ++ } ++ ++ Ref m_encoderQueue; ++ vpx_codec_ctx_t m_codec; ++ vpx_codec_enc_cfg_t m_cfg; ++ FILE* m_file { nullptr }; ++ std::unique_ptr m_writer; ++ int m_frameCount { 0 }; ++ int64_t m_pts { 0 }; ++ std::unique_ptr m_imageBuffer; ++ std::unique_ptr m_image; ++}; ++ ++ScreencastEncoder::ScreencastEncoder(std::unique_ptr&& vpxCodec, IntSize size, Optional scale) ++ : m_vpxCodec(WTFMove(vpxCodec)) ++ , m_size(size) ++ , m_scale(scale) ++{ ++ ASSERT(!size.isZero()); ++} ++ ++ScreencastEncoder::~ScreencastEncoder() ++{ ++} ++ ++RefPtr ScreencastEncoder::create(String& errorString, const String& filePath, IntSize size, Optional scale) ++{ ++ vpx_codec_iface_t* codec_interface = vpx_codec_vp8_cx(); ++ if (!codec_interface) { ++ errorString = "Codec not found."; ++ return nullptr; ++ } ++ ++ if (size.width() <= 0 || size.height() <= 0 || (size.width() % 2) != 0 || (size.height() % 2) != 0) { ++ errorString = makeString("Invalid frame size: "_s, size.width(), "x"_s, size.height()); ++ return nullptr; ++ } ++ ++ vpx_codec_enc_cfg_t cfg; ++ memset(&cfg, 0, sizeof(cfg)); ++ vpx_codec_err_t error = vpx_codec_enc_config_default(codec_interface, &cfg, 0); ++ if (error) { ++ errorString = makeString("Failed to get default codec config: "_s, vpx_codec_err_to_string(error)); ++ return nullptr; ++ } ++ ++ cfg.g_w = size.width(); ++ cfg.g_h = size.height(); ++ cfg.g_timebase.num = 1; ++ cfg.g_timebase.den = fps * timeScale; ++ cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT; ++ ++ vpx_codec_ctx_t codec; ++ if (vpx_codec_enc_init(&codec, codec_interface, &cfg, 0)) { ++ errorString = makeString("Failed to initialize encoder: "_s, vpx_codec_error(&codec)); ++ return nullptr; ++ } ++ ++ FILE* file = fopen(filePath.utf8().data(), "wb"); ++ if (!file) { ++ errorString = makeString("Failed to open file '", filePath, "' for writing: ", strerror(errno)); ++ return nullptr; ++ } ++ ++ std::unique_ptr vpxCodec(new VPXCodec(codec, cfg, file)); ++ // fprintf(stderr, "ScreencastEncoder initialized with: %s\n", vpx_codec_iface_name(codec_interface)); ++ return adoptRef(new ScreencastEncoder(WTFMove(vpxCodec), size, scale)); ++} ++ ++void ScreencastEncoder::flushLastFrame() ++{ ++ MonotonicTime now = MonotonicTime::now(); ++ if (m_lastFrameTimestamp) { ++ // If previous frame encoding failed for some rason leave the timestampt intact. ++ if (!m_lastFrame) ++ return; ++ ++ Seconds seconds = now - m_lastFrameTimestamp; ++ m_lastFrame->setDuration(seconds); ++ m_vpxCodec->encodeFrameAsync(WTFMove(m_lastFrame)); ++ } ++ m_lastFrameTimestamp = now; ++} ++ ++#if USE(CAIRO) ++void ScreencastEncoder::encodeFrame(cairo_surface_t* drawingAreaSurface, IntSize size) ++{ ++ // fprintf(stderr, "ScreencastEncoder::encodeFrame\n"); ++ flushLastFrame(); ++ // Note that in WPE drawing area size is updated asynchronously and may differ from acutal ++ // size of the surface. ++ if (size.isZero()) { ++ // fprintf(stderr, "Cairo surface size is 0\n"); ++ return; ++ } ++ ++ // TODO: adjust device scale factor? ++ RefPtr surface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, m_size.width(), m_size.height())); ++ { ++ RefPtr cr = adoptRef(cairo_create(surface.get())); ++ ++ // TODO: compare to libyuv scale functions? ++ cairo_matrix_t transform; ++ if (m_scale) { ++ cairo_matrix_init_scale(&transform, *m_scale, *m_scale); ++ cairo_transform(cr.get(), &transform); ++ } else if (size.width() > m_size.width() || size.height() > m_size.height()) { ++ // If no scale is specified shrink to fit the frame. ++ double scale = std::min(static_cast(m_size.width()) / size.width(), ++ static_cast(m_size.height()) / size.height()); ++ cairo_matrix_init_scale(&transform, scale, scale); ++ cairo_transform(cr.get(), &transform); ++ } ++ ++ // Record top left part of the drawing area that fits into the frame. ++ cairo_set_source_surface(cr.get(), drawingAreaSurface, 0, 0); ++ cairo_paint(cr.get()); ++ } ++ cairo_surface_flush(surface.get()); ++ ++ m_lastFrame = makeUnique(WTFMove(surface)); ++} ++#elif PLATFORM(MAC) ++void ScreencastEncoder::encodeFrame(RetainPtr&& windowImage) ++{ ++ // fprintf(stderr, "ScreencastEncoder::encodeFrame\n"); ++ flushLastFrame(); ++ ++ m_lastFrame = makeUnique(WTFMove(windowImage), m_scale, m_offsetTop); ++} ++#endif ++ ++void ScreencastEncoder::finish(Function&& callback) ++{ ++ if (!m_vpxCodec) { ++ callback(); ++ return; ++ } ++ ++ flushLastFrame(); ++ m_vpxCodec->finishAsync([protectRef = makeRef(*this), callback = WTFMove(callback)] () mutable { ++ RunLoop::main().dispatch([callback = WTFMove(callback)] { ++ callback(); ++ }); ++ }); ++} ++ ++ ++} // namespace WebKit +diff --git a/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h +new file mode 100644 +index 0000000000000000000000000000000000000000..c9ff0442e072d54c089540d291b7963688b6474b +--- /dev/null ++++ b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h +@@ -0,0 +1,81 @@ ++/* ++ * Copyright (C) 2020 Microsoft Corporation. ++ * ++ * 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 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. ++ */ ++ ++#pragma once ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if USE(CAIRO) ++#include ++#endif ++ ++namespace WebKit { ++ ++class WebPageProxy; ++ ++class ScreencastEncoder : public ThreadSafeRefCounted { ++ WTF_MAKE_NONCOPYABLE(ScreencastEncoder); ++ WTF_MAKE_FAST_ALLOCATED; ++public: ++ static constexpr int fps = 25; ++ ++ static RefPtr create(String& errorString, const String& filePath, WebCore::IntSize, Optional scale); ++ ++ class VPXCodec; ++ ScreencastEncoder(std::unique_ptr&&, WebCore::IntSize, Optional scale); ++ ~ScreencastEncoder(); ++ ++#if USE(CAIRO) ++ void encodeFrame(cairo_surface_t*, WebCore::IntSize); ++#elif PLATFORM(MAC) ++ void encodeFrame(RetainPtr&&); ++ void setOffsetTop(int offset) { m_offsetTop = offset;} ++#endif ++ ++ void finish(Function&& callback); ++ ++private: ++ void flushLastFrame(); ++#if PLATFORM(MAC) ++ static void imageToARGB(CGImageRef, uint8_t* rgba_data, int width, int height, Optional scale, int offsetTop); ++#endif ++ ++ std::unique_ptr m_vpxCodec; ++ const WebCore::IntSize m_size; ++ Optional m_scale; ++ MonotonicTime m_lastFrameTimestamp; ++ class VPXFrame; ++ std::unique_ptr m_lastFrame; ++#if PLATFORM(MAC) ++ int m_offsetTop { 0 }; ++#endif ++}; ++ ++} // namespace WebKit +diff --git a/Source/WebKit/UIProcess/Inspector/Agents/WebMFileWriter.cpp b/Source/WebKit/UIProcess/Inspector/Agents/WebMFileWriter.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..9b269b356e206f0252245a1497adb0d05128c9b4 +--- /dev/null ++++ b/Source/WebKit/UIProcess/Inspector/Agents/WebMFileWriter.cpp +@@ -0,0 +1,69 @@ ++/* ++ * Copyright (c) 2014 The WebM project authors. All Rights Reserved. ++ * Copyright (C) 2020 Microsoft Corporation. ++ * ++ * 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 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 "WebMFileWriter.h" ++ ++#include ++#include "mkvmuxer/mkvmuxerutil.h" ++ ++namespace WebKit { ++ ++WebMFileWriter::WebMFileWriter(FILE* file, vpx_codec_enc_cfg_t* cfg) ++ : m_cfg(cfg) ++ , m_writer(new mkvmuxer::MkvWriter(file)) ++ , m_segment(new mkvmuxer::Segment()) { ++ m_segment->Init(m_writer.get()); ++ m_segment->set_mode(mkvmuxer::Segment::kFile); ++ m_segment->OutputCues(true); ++ ++ mkvmuxer::SegmentInfo* info = m_segment->GetSegmentInfo(); ++ std::string version = "Playwright " + std::string(vpx_codec_version_str()); ++ info->set_writing_app(version.c_str()); ++ ++ // Add vp8 track. ++ m_videoTrackId = m_segment->AddVideoTrack( ++ static_cast(m_cfg->g_w), static_cast(m_cfg->g_h), 0); ++ if (!m_videoTrackId) { ++ fprintf(stderr, "Failed to add video track\n"); ++ } ++} ++ ++WebMFileWriter::~WebMFileWriter() {} ++ ++bool WebMFileWriter::writeFrame(const vpx_codec_cx_pkt_t* pkt) { ++ int64_t pts_ns = pkt->data.frame.pts * 1000000000ll * m_cfg->g_timebase.num / ++ m_cfg->g_timebase.den; ++ return m_segment->AddFrame(static_cast(pkt->data.frame.buf), ++ pkt->data.frame.sz, m_videoTrackId, pts_ns, ++ pkt->data.frame.flags & VPX_FRAME_IS_KEY); ++} ++ ++void WebMFileWriter::finish() { ++ m_segment->Finalize(); ++} ++ ++} // namespace WebKit +diff --git a/Source/WebKit/UIProcess/Inspector/Agents/WebMFileWriter.h b/Source/WebKit/UIProcess/Inspector/Agents/WebMFileWriter.h +new file mode 100644 +index 0000000000000000000000000000000000000000..e2ce910f3fd7f587add552275b7e7176cf8b2723 +--- /dev/null ++++ b/Source/WebKit/UIProcess/Inspector/Agents/WebMFileWriter.h +@@ -0,0 +1,53 @@ ++/* ++ * Copyright (C) 2020 Microsoft Corporation. ++ * ++ * 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 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. ++ */ ++ ++#pragma once ++ ++#include ++#include ++#include ++#include "vpx/vpx_encoder.h" ++ ++#include "mkvmuxer/mkvmuxer.h" ++#include "mkvmuxer/mkvwriter.h" ++ ++namespace WebKit { ++ ++class WebMFileWriter { ++public: ++ WebMFileWriter(FILE*, vpx_codec_enc_cfg_t* cfg); ++ ~WebMFileWriter(); ++ ++ bool writeFrame(const vpx_codec_cx_pkt_t* pkt); ++ void finish(); ++ ++private: ++ vpx_codec_enc_cfg_t* m_cfg = nullptr; ++ std::unique_ptr m_writer; ++ std::unique_ptr m_segment; ++ uint64_t m_videoTrackId = 0; ++}; ++ ++} // namespace WebKit +diff --git a/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp b/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp +index 6928ca2fbfb6939062e3cd14bb7ba6f2fdc87f5f..621b99e233ed5cf504fedbd3ca3209c03bcd611f 100644 +--- a/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp ++++ b/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp +@@ -27,11 +27,10 @@ + #include "InspectorTargetProxy.h" + + #include "ProvisionalPageProxy.h" +-#include "WebFrameProxy.h" ++#include "WebPageInspectorController.h" + #include "WebPageInspectorTarget.h" + #include "WebPageMessages.h" + #include "WebPageProxy.h" +-#include "WebProcessProxy.h" + + namespace WebKit { + +@@ -39,18 +38,17 @@ using namespace Inspector; + + std::unique_ptr InspectorTargetProxy::create(WebPageProxy& page, const String& targetId, Inspector::InspectorTargetType type) + { +- return makeUnique(page, targetId, type); ++ return makeUnique(page, nullptr, targetId, type); + } + +-std::unique_ptr InspectorTargetProxy::create(ProvisionalPageProxy& provisionalPage, const String& targetId, Inspector::InspectorTargetType type) ++std::unique_ptr InspectorTargetProxy::create(ProvisionalPageProxy& provisionalPage, const String& targetId) + { +- auto target = InspectorTargetProxy::create(provisionalPage.page(), targetId, type); +- target->m_provisionalPage = makeWeakPtr(provisionalPage); +- return target; ++ return makeUnique(provisionalPage.page(), &provisionalPage, targetId, Inspector::InspectorTargetType::Page); + } + +-InspectorTargetProxy::InspectorTargetProxy(WebPageProxy& page, const String& targetId, Inspector::InspectorTargetType type) ++InspectorTargetProxy::InspectorTargetProxy(WebPageProxy& page, ProvisionalPageProxy* provisionalPage, const String& targetId, Inspector::InspectorTargetType type) + : m_page(page) ++ , m_provisionalPage(makeWeakPtr(provisionalPage)) + , m_identifier(targetId) + , m_type(type) + { +@@ -97,6 +95,31 @@ void InspectorTargetProxy::didCommitProvisionalTarget() + m_provisionalPage = nullptr; + } + ++void InspectorTargetProxy::willResume() ++{ ++ if (m_page.hasRunningProcess()) ++ m_page.send(Messages::WebPage::ResumeInspectorIfPausedInNewWindow()); ++} ++ ++void InspectorTargetProxy::activate(String& error) ++{ ++ if (m_type != Inspector::InspectorTargetType::Page) ++ return InspectorTarget::activate(error); ++ ++ platformActivate(error); ++} ++ ++void InspectorTargetProxy::close(String& error, bool runBeforeUnload) ++{ ++ if (m_type != Inspector::InspectorTargetType::Page) ++ return InspectorTarget::close(error, runBeforeUnload); ++ ++ if (runBeforeUnload) ++ m_page.tryClose(); ++ else ++ m_page.closePage(); ++} ++ + bool InspectorTargetProxy::isProvisional() const + { + return !!m_provisionalPage; +diff --git a/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.h b/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.h +index a2239cec8e18850f35f7f88a9c4ebadc62bf4023..79f3ff84327dc075ec96983e04db4b10343b7fae 100644 +--- a/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.h ++++ b/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.h +@@ -37,13 +37,13 @@ class WebPageProxy; + // NOTE: This UIProcess side InspectorTarget doesn't care about the frontend channel, since + // any target -> frontend messages will be routed to the WebPageProxy with a targetId. + +-class InspectorTargetProxy final : public Inspector::InspectorTarget { ++class InspectorTargetProxy : public Inspector::InspectorTarget { + WTF_MAKE_FAST_ALLOCATED; + WTF_MAKE_NONCOPYABLE(InspectorTargetProxy); + public: + static std::unique_ptr create(WebPageProxy&, const String& targetId, Inspector::InspectorTargetType); +- static std::unique_ptr create(ProvisionalPageProxy&, const String& targetId, Inspector::InspectorTargetType); +- InspectorTargetProxy(WebPageProxy&, const String& targetId, Inspector::InspectorTargetType); ++ static std::unique_ptr create(ProvisionalPageProxy&, const String& targetId); ++ InspectorTargetProxy(WebPageProxy&, ProvisionalPageProxy*, const String& targetId, Inspector::InspectorTargetType); + ~InspectorTargetProxy() = default; + + Inspector::InspectorTargetType type() const final { return m_type; } +@@ -55,12 +55,17 @@ public: + void connect(Inspector::FrontendChannel::ConnectionType) override; + void disconnect() override; + void sendMessageToTargetBackend(const String&) override; ++ void activate(String& error) override; ++ void close(String& error, bool runBeforeUnload) override; + + private: ++ void willResume() override; ++ void platformActivate(String& error) const; ++ + WebPageProxy& m_page; ++ WeakPtr m_provisionalPage; + String m_identifier; + Inspector::InspectorTargetType m_type; +- WeakPtr m_provisionalPage; + }; + + } // namespace WebKit +diff --git a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp +index ed4e6f30b8c35966075573dccee801daceec865e..2357769f3f78a7fda3d3fff1005e77c5d082948d 100644 +--- a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp ++++ b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp +@@ -26,13 +26,21 @@ + #include "config.h" + #include "WebPageInspectorController.h" + ++#include "APINavigation.h" + #include "APIUIClient.h" + #include "InspectorBrowserAgent.h" ++#include "InspectorDialogAgent.h" ++#include "InspectorScreencastAgent.h" + #include "ProvisionalPageProxy.h" + #include "WebFrameProxy.h" + #include "WebPageInspectorAgentBase.h" ++#include "WebPageInspectorEmulationAgent.h" ++#include "WebPageInspectorInputAgent.h" + #include "WebPageInspectorTarget.h" + #include "WebPageProxy.h" ++#include "WebPreferences.h" ++#include ++#include + #include + #include + #include +@@ -49,27 +57,108 @@ static String getTargetID(const ProvisionalPageProxy& provisionalPage) + return WebPageInspectorTarget::toTargetID(provisionalPage.webPageID()); + } + ++WebPageInspectorControllerObserver* WebPageInspectorController::s_observer = nullptr; ++ ++void WebPageInspectorController::setObserver(WebPageInspectorControllerObserver* observer) ++{ ++ s_observer = observer; ++} ++ ++WebPageInspectorControllerObserver* WebPageInspectorController::observer() { ++ return s_observer; ++} ++ + WebPageInspectorController::WebPageInspectorController(WebPageProxy& inspectedPage) + : m_frontendRouter(FrontendRouter::create()) + , m_backendDispatcher(BackendDispatcher::create(m_frontendRouter.copyRef())) + , m_inspectedPage(inspectedPage) + { +- auto targetAgent = makeUnique(m_frontendRouter.get(), m_backendDispatcher.get()); +- m_targetAgent = targetAgent.get(); +- m_agents.append(WTFMove(targetAgent)); + } + + void WebPageInspectorController::init() + { ++ auto targetAgent = makeUnique(m_frontendRouter.get(), m_backendDispatcher.get()); ++ m_targetAgent = targetAgent.get(); ++ m_agents.append(WTFMove(targetAgent)); ++ auto emulationAgent = makeUnique(m_backendDispatcher.get(), m_inspectedPage); ++ m_emulationAgent = emulationAgent.get(); ++ m_agents.append(WTFMove(emulationAgent)); ++ auto inputAgent = makeUnique(m_backendDispatcher.get(), m_inspectedPage); ++ m_inputAgent = inputAgent.get(); ++ m_agents.append(WTFMove(inputAgent)); ++ m_agents.append(makeUnique(m_backendDispatcher.get(), m_frontendRouter.get(), m_inspectedPage)); ++ auto screencastAgent = makeUnique(m_backendDispatcher.get(), m_frontendRouter.get(), m_inspectedPage); ++ m_screecastAgent = screencastAgent.get(); ++ m_agents.append(WTFMove(screencastAgent)); ++ if (s_observer) ++ s_observer->didCreateInspectorController(m_inspectedPage); ++ ++ // window.open will create page with already running process. ++ if (!m_inspectedPage.hasRunningProcess()) ++ return; + String pageTargetId = WebPageInspectorTarget::toTargetID(m_inspectedPage.webPageID()); + createInspectorTarget(pageTargetId, Inspector::InspectorTargetType::Page); + } + ++void WebPageInspectorController::didFinishAttachingToWebProcess() ++{ ++ String pageTargetID = WebPageInspectorTarget::toTargetID(m_inspectedPage.webPageID()); ++ // Create target only after attaching to a Web Process first time. Before that ++ // we cannot event establish frontend connection. ++ if (m_targets.contains(pageTargetID)) ++ return; ++ createInspectorTarget(pageTargetID, Inspector::InspectorTargetType::Page); ++} ++ + void WebPageInspectorController::pageClosed() + { ++ String pageTargetId = WebPageInspectorTarget::toTargetID(m_inspectedPage.webPageID()); ++ destroyInspectorTarget(pageTargetId); ++ + disconnectAllFrontends(); + + m_agents.discardValues(); ++ ++ if (s_observer) ++ s_observer->willDestroyInspectorController(m_inspectedPage); ++} ++ ++bool WebPageInspectorController::pageCrashed(ProcessTerminationReason reason) ++{ ++ if (reason != ProcessTerminationReason::Crash) ++ return false; ++ String targetId = WebPageInspectorTarget::toTargetID(m_inspectedPage.webPageID()); ++ auto it = m_targets.find(targetId); ++ if (it == m_targets.end()) ++ return false; ++ m_targetAgent->targetCrashed(*it->value); ++ m_targets.remove(it); ++ ++ return m_targetAgent->isConnected(); ++} ++ ++void WebPageInspectorController::willCreateNewPage(const WebCore::WindowFeatures& features, const URL& url) ++{ ++ if (s_observer) ++ s_observer->willCreateNewPage(m_inspectedPage, features, url); ++} ++ ++void WebPageInspectorController::didShowPage() ++{ ++ if (m_frontendRouter->hasFrontends()) ++ m_emulationAgent->didShowPage(); ++} ++ ++void WebPageInspectorController::didProcessAllPendingKeyboardEvents() ++{ ++ if (m_frontendRouter->hasFrontends()) ++ m_inputAgent->didProcessAllPendingKeyboardEvents(); ++} ++ ++void WebPageInspectorController::didProcessAllPendingMouseEvents() ++{ ++ if (m_frontendRouter->hasFrontends()) ++ m_inputAgent->didProcessAllPendingMouseEvents(); + } + + bool WebPageInspectorController::hasLocalFrontend() const +@@ -83,6 +172,17 @@ void WebPageInspectorController::connectFrontend(Inspector::FrontendChannel& fro + + bool connectingFirstFrontend = !m_frontendRouter->hasFrontends(); + ++ // HACK: forcefully disconnect remote connections to show local inspector starting with initial ++ // agents' state. ++ if (frontendChannel.connectionType() == Inspector::FrontendChannel::ConnectionType::Local && ++ !connectingFirstFrontend && !m_frontendRouter->hasLocalFrontend()) { ++ disconnectAllFrontends(); ++ connectingFirstFrontend = true; ++ } ++ ++ if (connectingFirstFrontend) ++ adjustPageSettings(); ++ + m_frontendRouter->connectFrontend(frontendChannel); + + if (connectingFirstFrontend) +@@ -101,8 +201,10 @@ void WebPageInspectorController::disconnectFrontend(FrontendChannel& frontendCha + m_frontendRouter->disconnectFrontend(frontendChannel); + + bool disconnectingLastFrontend = !m_frontendRouter->hasFrontends(); +- if (disconnectingLastFrontend) ++ if (disconnectingLastFrontend) { + m_agents.willDestroyFrontendAndBackend(DisconnectReason::InspectorDestroyed); ++ m_pendingNavigations.clear(); ++ } + + m_inspectedPage.didChangeInspectorFrontendCount(m_frontendRouter->frontendCount()); + +@@ -125,6 +227,8 @@ void WebPageInspectorController::disconnectAllFrontends() + // Disconnect any remaining remote frontends. + m_frontendRouter->disconnectAllFrontends(); + ++ m_pendingNavigations.clear(); ++ + m_inspectedPage.didChangeInspectorFrontendCount(m_frontendRouter->frontendCount()); + + #if ENABLE(REMOTE_INSPECTOR) +@@ -151,6 +255,66 @@ void WebPageInspectorController::setIndicating(bool indicating) + } + #endif + ++#if USE(CAIRO) ++void WebPageInspectorController::didPaint(cairo_surface_t* surface) ++{ ++ if (!m_frontendRouter->hasFrontends()) ++ return; ++ ++ m_screecastAgent->didPaint(surface); ++} ++#endif ++ ++ ++void WebPageInspectorController::navigate(WebCore::ResourceRequest&& request, WebFrameProxy* frame, NavigationHandler&& completionHandler) ++{ ++ auto navigation = m_inspectedPage.loadRequestForInspector(WTFMove(request), frame); ++ if (!navigation) { ++ completionHandler("Failed to navigate"_s, 0); ++ return; ++ } ++ ++ m_pendingNavigations.set(navigation->navigationID(), WTFMove(completionHandler)); ++} ++ ++void WebPageInspectorController::didReceivePolicyDecision(WebCore::PolicyAction action, uint64_t navigationID) ++{ ++ if (!m_frontendRouter->hasFrontends()) ++ return; ++ ++ if (!navigationID) ++ return; ++ ++ auto completionHandler = m_pendingNavigations.take(navigationID); ++ if (!completionHandler) ++ return; ++ ++ if (action == WebCore::PolicyAction::Ignore) ++ completionHandler("Navigation cancelled"_s, 0); ++ else ++ completionHandler(String(), navigationID); ++} ++ ++void WebPageInspectorController::didDestroyNavigation(uint64_t navigationID) ++{ ++ if (!m_frontendRouter->hasFrontends()) ++ return; ++ ++ auto completionHandler = m_pendingNavigations.take(navigationID); ++ if (!completionHandler) ++ return; ++ ++ // Inspector initiated navigation is destroyed before policy check only when it ++ // becomes a fragment navigation (which always reuses current navigation). ++ completionHandler(String(), 0); ++} ++ ++void WebPageInspectorController::didFailProvisionalLoadForFrame(uint64_t navigationID, const WebCore::ResourceError& error) ++{ ++ if (s_observer) ++ s_observer->didFailProvisionalLoad(m_inspectedPage, navigationID, error.localizedDescription()); ++} ++ + void WebPageInspectorController::createInspectorTarget(const String& targetId, Inspector::InspectorTargetType type) + { + addTarget(InspectorTargetProxy::create(m_inspectedPage, targetId, type)); +@@ -170,6 +334,32 @@ void WebPageInspectorController::sendMessageToInspectorFrontend(const String& ta + m_targetAgent->sendMessageFromTargetToFrontend(targetId, message); + } + ++void WebPageInspectorController::setPauseOnStart(bool shouldPause) ++{ ++ ASSERT(m_frontendRouter->hasFrontends()); ++ m_targetAgent->setPauseOnStart(shouldPause); ++} ++ ++bool WebPageInspectorController::shouldPauseLoading() const ++{ ++ if (!m_frontendRouter->hasFrontends()) ++ return false; ++ ++ if (!m_inspectedPage.isPageOpenedByDOMShowingInitialEmptyDocument()) ++ return false; ++ ++ auto* target = m_targets.get(WebPageInspectorTarget::toTargetID(m_inspectedPage.webPageID())); ++ ASSERT(target); ++ return target->isPaused(); ++} ++ ++void WebPageInspectorController::setContinueLoadingCallback(WTF::Function&& callback) ++{ ++ auto* target = m_targets.get(WebPageInspectorTarget::toTargetID(m_inspectedPage.webPageID())); ++ ASSERT(target); ++ target->setResumeCallback(WTFMove(callback)); ++} ++ + bool WebPageInspectorController::shouldPauseLoading(const ProvisionalPageProxy& provisionalPage) const + { + if (!m_frontendRouter->hasFrontends()) +@@ -189,7 +379,7 @@ void WebPageInspectorController::setContinueLoadingCallback(const ProvisionalPag + + void WebPageInspectorController::didCreateProvisionalPage(ProvisionalPageProxy& provisionalPage) + { +- addTarget(InspectorTargetProxy::create(provisionalPage, getTargetID(provisionalPage), Inspector::InspectorTargetType::Page)); ++ addTarget(InspectorTargetProxy::create(provisionalPage, getTargetID(provisionalPage))); + } + + void WebPageInspectorController::willDestroyProvisionalPage(const ProvisionalPageProxy& provisionalPage) +@@ -267,4 +457,20 @@ void WebPageInspectorController::browserExtensionsDisabled(HashSet&& ext + m_enabledBrowserAgent->extensionsDisabled(WTFMove(extensionIDs)); + } + ++void WebPageInspectorController::adjustPageSettings() ++{ ++ // Set this to true as otherwise updating any preferences will override its ++ // value in the Web Process to false (and InspectorController sets it locally ++ // to true when frontend is connected). ++ m_inspectedPage.preferences().setDeveloperExtrasEnabled(true); ++ ++ // Navigation to cached pages doesn't fire some of the events (e.g. execution context created) ++ // that inspector depends on. So we disable the cache when front-end connects. ++ m_inspectedPage.preferences().setUsesBackForwardCache(false); ++ ++ // Enable popup debugging. ++ // TODO: allow to set preferences over the inspector protocol or find a better place for this. ++ m_inspectedPage.preferences().setJavaScriptCanOpenWindowsAutomatically(true); ++} ++ + } // namespace WebKit +diff --git a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h +index 8c1339345d451874502b271f6aa2eca3fa0d3faf..331b61c70c7370ace480724bdb53c99a54897374 100644 +--- a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h ++++ b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h +@@ -26,17 +26,35 @@ + #pragma once + + #include "InspectorTargetProxy.h" ++#include "ProcessTerminationReason.h" + #include + #include + #include + #include + #include + #include ++#include ++ ++#if USE(CAIRO) ++#include ++#endif + + namespace Inspector { + class BackendDispatcher; + class FrontendChannel; + class FrontendRouter; ++class InspectorTarget; ++} ++ ++namespace WebCore { ++class ResourceError; ++class ResourceRequest; ++enum class PolicyAction : uint8_t; ++struct WindowFeatures; ++} ++ ++namespace PAL { ++class SessionID; + } + + namespace WebKit { +@@ -44,6 +62,23 @@ namespace WebKit { + class InspectorBrowserAgent; + struct WebPageAgentContext; + ++class InspectorScreencastAgent; ++class WebFrameProxy; ++class WebPageInspectorEmulationAgent; ++class WebPageInspectorInputAgent; ++ ++class WebPageInspectorControllerObserver { ++public: ++ virtual void didCreateInspectorController(WebPageProxy&) = 0; ++ virtual void willDestroyInspectorController(WebPageProxy&) = 0; ++ virtual void didFailProvisionalLoad(WebPageProxy&, uint64_t navigationID, const String& error) = 0; ++ virtual void willCreateNewPage(WebPageProxy&, const WebCore::WindowFeatures&, const URL&) = 0; ++ virtual void didFinishScreencast(const PAL::SessionID& sessionID, const String& screencastID) = 0; ++ ++protected: ++ virtual ~WebPageInspectorControllerObserver() = default; ++}; ++ + class WebPageInspectorController { + WTF_MAKE_NONCOPYABLE(WebPageInspectorController); + WTF_MAKE_FAST_ALLOCATED; +@@ -51,7 +86,20 @@ public: + WebPageInspectorController(WebPageProxy&); + + void init(); ++ void didFinishAttachingToWebProcess(); ++ ++ static void setObserver(WebPageInspectorControllerObserver*); ++ static WebPageInspectorControllerObserver* observer(); ++ + void pageClosed(); ++ bool pageCrashed(ProcessTerminationReason); ++ ++ void willCreateNewPage(const WebCore::WindowFeatures&, const URL&); ++ ++ void didShowPage(); ++ ++ void didProcessAllPendingKeyboardEvents(); ++ void didProcessAllPendingMouseEvents(); + + bool hasLocalFrontend() const; + +@@ -64,11 +112,25 @@ public: + #if ENABLE(REMOTE_INSPECTOR) + void setIndicating(bool); + #endif ++#if USE(CAIRO) ++ void didPaint(cairo_surface_t*); ++#endif ++ using NavigationHandler = Function; ++ void navigate(WebCore::ResourceRequest&&, WebFrameProxy*, NavigationHandler&&); ++ void didReceivePolicyDecision(WebCore::PolicyAction action, uint64_t navigationID); ++ void didDestroyNavigation(uint64_t navigationID); ++ ++ void didFailProvisionalLoadForFrame(uint64_t navigationID, const WebCore::ResourceError& error); + + void createInspectorTarget(const String& targetId, Inspector::InspectorTargetType); + void destroyInspectorTarget(const String& targetId); + void sendMessageToInspectorFrontend(const String& targetId, const String& message); + ++ void setPauseOnStart(bool); ++ ++ bool shouldPauseLoading() const; ++ void setContinueLoadingCallback(WTF::Function&&); ++ + bool shouldPauseLoading(const ProvisionalPageProxy&) const; + void setContinueLoadingCallback(const ProvisionalPageProxy&, WTF::Function&&); + +@@ -87,6 +149,7 @@ private: + void createLazyAgents(); + + void addTarget(std::unique_ptr&&); ++ void adjustPageSettings(); + + Ref m_frontendRouter; + Ref m_backendDispatcher; +@@ -95,11 +158,17 @@ private: + WebPageProxy& m_inspectedPage; + + Inspector::InspectorTargetAgent* m_targetAgent { nullptr }; ++ WebPageInspectorEmulationAgent* m_emulationAgent { nullptr }; ++ WebPageInspectorInputAgent* m_inputAgent { nullptr }; ++ InspectorScreencastAgent* m_screecastAgent { nullptr }; + HashMap> m_targets; + + InspectorBrowserAgent* m_enabledBrowserAgent; + + bool m_didCreateLazyAgents { false }; ++ HashMap m_pendingNavigations; ++ ++ static WebPageInspectorControllerObserver* s_observer; + }; + + } // namespace WebKit +diff --git a/Source/WebKit/UIProcess/Inspector/mac/ScreencastEncoderMac.mm b/Source/WebKit/UIProcess/Inspector/mac/ScreencastEncoderMac.mm +new file mode 100644 +index 0000000000000000000000000000000000000000..0700f3624b34ab536f4101a12ba5fbd9a81e9a58 +--- /dev/null ++++ b/Source/WebKit/UIProcess/Inspector/mac/ScreencastEncoderMac.mm +@@ -0,0 +1,58 @@ ++/* ++ * Copyright (C) 2020 Microsoft Corporation. ++ * ++ * 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 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 "ScreencastEncoder.h" ++ ++#include ++#include ++#include ++ ++namespace WebKit { ++ ++void ScreencastEncoder::imageToARGB(CGImageRef image, uint8_t* argb_data, int width, int height, Optional scale, int offsetTop) ++{ ++ size_t bitsPerComponent = 8; ++ size_t bytesPerPixel = 4; ++ size_t bytesPerRow = bytesPerPixel * width; ++ RetainPtr colorSpace = adoptCF(CGColorSpaceCreateDeviceRGB()); ++ RetainPtr context = adoptCF(CGBitmapContextCreate(argb_data, width, height, bitsPerComponent, bytesPerRow, colorSpace.get(), kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little)); ++ double imageWidth = CGImageGetWidth(image); ++ double imageHeight = CGImageGetHeight(image); ++ // TODO: exclude controls from original screenshot ++ double pageHeight = imageHeight - offsetTop; ++ double ratio = 1; ++ if (scale) { ++ ratio = *scale; ++ } else if (imageWidth > width || pageHeight > height) { ++ ratio = std::min(width / imageWidth, height / pageHeight); ++ } ++ imageWidth *= ratio; ++ imageHeight *= ratio; ++ pageHeight *= ratio; ++ CGContextDrawImage(context.get(), CGRectMake(0, height - pageHeight, imageWidth, imageHeight), image); ++} ++ ++} // namespace WebKit +diff --git a/Source/WebKit/UIProcess/InspectorDialogAgent.cpp b/Source/WebKit/UIProcess/InspectorDialogAgent.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..663f92f0df76042cf6385b056f8a917d688259f9 +--- /dev/null ++++ b/Source/WebKit/UIProcess/InspectorDialogAgent.cpp +@@ -0,0 +1,88 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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 "InspectorDialogAgent.h" ++ ++#include "APINavigation.h" ++#include "APIUIClient.h" ++#include "WebPageProxy.h" ++#include ++ ++ ++namespace WebKit { ++ ++using namespace Inspector; ++ ++InspectorDialogAgent::InspectorDialogAgent(Inspector::BackendDispatcher& backendDispatcher, Inspector::FrontendRouter& frontendRouter, WebPageProxy& page) ++ : InspectorAgentBase("Dialog"_s) ++ , m_frontendDispatcher(makeUnique(frontendRouter)) ++ , m_backendDispatcher(DialogBackendDispatcher::create(backendDispatcher, this)) ++ , m_page(page) ++{ ++} ++ ++InspectorDialogAgent::~InspectorDialogAgent() ++{ ++ disable(); ++} ++ ++void InspectorDialogAgent::didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) ++{ ++} ++ ++void InspectorDialogAgent::willDestroyFrontendAndBackend(Inspector::DisconnectReason) ++{ ++} ++ ++Inspector::Protocol::ErrorStringOr InspectorDialogAgent::enable() ++{ ++ if (m_page.inspectorDialogAgent()) ++ return makeUnexpected("Dialog domain is already enabled."_s); ++ ++ m_page.setInspectorDialogAgent(this); ++ return { }; ++} ++ ++Inspector::Protocol::ErrorStringOr InspectorDialogAgent::disable() ++{ ++ if (m_page.inspectorDialogAgent() != this) ++ return { }; ++ ++ m_page.setInspectorDialogAgent(nullptr); ++ return { }; ++} ++ ++Inspector::Protocol::ErrorStringOr InspectorDialogAgent::handleJavaScriptDialog(bool accept, const String& value) ++{ ++ m_page.uiClient().handleJavaScriptDialog(m_page, accept, value); ++ return { }; ++} ++ ++void InspectorDialogAgent::javascriptDialogOpening(const String& type, const String& message, const String& defaultValue) { ++ m_frontendDispatcher->javascriptDialogOpening(type, message, defaultValue); ++} ++ ++} // namespace WebKit +diff --git a/Source/WebKit/UIProcess/InspectorDialogAgent.h b/Source/WebKit/UIProcess/InspectorDialogAgent.h +new file mode 100644 +index 0000000000000000000000000000000000000000..d0e11ed81a6257c011df23d5870da7403f8e9fe4 +--- /dev/null ++++ b/Source/WebKit/UIProcess/InspectorDialogAgent.h +@@ -0,0 +1,70 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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. ++ */ ++ ++#pragma once ++ ++#include "WebEvent.h" ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++namespace Inspector { ++class FrontendChannel; ++class FrontendRouter; ++} ++ ++namespace WebKit { ++ ++class NativeWebKeyboardEvent; ++class WebPageProxy; ++ ++class InspectorDialogAgent : public Inspector::InspectorAgentBase, public Inspector::DialogBackendDispatcherHandler { ++ WTF_MAKE_NONCOPYABLE(InspectorDialogAgent); ++ WTF_MAKE_FAST_ALLOCATED; ++public: ++ InspectorDialogAgent(Inspector::BackendDispatcher& backendDispatcher, Inspector::FrontendRouter& frontendRouter, WebPageProxy& page); ++ ~InspectorDialogAgent() override; ++ ++ void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) override; ++ void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override; ++ ++ Inspector::Protocol::ErrorStringOr enable() override; ++ Inspector::Protocol::ErrorStringOr disable() override; ++ Inspector::Protocol::ErrorStringOr handleJavaScriptDialog(bool accept, const String& promptText) override; ++ ++ void javascriptDialogOpening(const String& type, const String& message, const String& defaultValue = String()); ++ ++private: ++ void platformHandleJavaScriptDialog(bool accept, const String* promptText); ++ std::unique_ptr m_frontendDispatcher; ++ Ref m_backendDispatcher; ++ WebPageProxy& m_page; ++}; ++ ++} // namespace WebKit +diff --git a/Source/WebKit/UIProcess/InspectorPlaywrightAgent.cpp b/Source/WebKit/UIProcess/InspectorPlaywrightAgent.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..4463301d7cbe4831ee35f91664fe0ec2e8288fe6 +--- /dev/null ++++ b/Source/WebKit/UIProcess/InspectorPlaywrightAgent.cpp +@@ -0,0 +1,894 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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 "InspectorPlaywrightAgent.h" ++ ++#if ENABLE(REMOTE_INSPECTOR) ++ ++#include "APIPageConfiguration.h" ++#include "FrameInfoData.h" ++#include "InspectorPlaywrightAgentClient.h" ++#include "InspectorTargetProxy.h" ++#include "NetworkProcessMessages.h" ++#include "NetworkProcessProxy.h" ++#include "PageClient.h" ++#include "WebAutomationSession.h" ++#include "WebGeolocationManagerProxy.h" ++#include "WebGeolocationPosition.h" ++#include "WebInspectorUtilities.h" ++#include "WebPageInspectorController.h" ++#include "WebPageInspectorTarget.h" ++#include "WebPageProxy.h" ++#include "WebProcessPool.h" ++#include "WebProcessProxy.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++using namespace Inspector; ++ ++namespace WebKit { ++ ++class InspectorPlaywrightAgent::PageProxyChannel : public FrontendChannel { ++ WTF_MAKE_FAST_ALLOCATED; ++public: ++ PageProxyChannel(FrontendChannel& frontendChannel, String browserContextID, String pageProxyID, WebPageProxy& page) ++ : m_browserContextID(browserContextID) ++ , m_pageProxyID(pageProxyID) ++ , m_frontendChannel(frontendChannel) ++ , m_page(page) ++ { ++ } ++ ++ ~PageProxyChannel() override = default; ++ ++ void dispatchMessageFromFrontend(const String& message) ++ { ++ m_page.inspectorController().dispatchMessageFromFrontend(message); ++ } ++ ++ WebPageProxy& page() { return m_page; } ++ ++ void disconnect() ++ { ++ m_page.inspectorController().disconnectFrontend(*this); ++ } ++ ++private: ++ ConnectionType connectionType() const override { return m_frontendChannel.connectionType(); } ++ void sendMessageToFrontend(const String& message) override ++ { ++ m_frontendChannel.sendMessageToFrontend(addTabIdToMessage(message)); ++ } ++ ++ String addTabIdToMessage(const String& message) { ++ RefPtr parsedMessage = JSON::Value::parseJSON(message); ++ if (!parsedMessage) ++ return message; ++ ++ RefPtr messageObject = parsedMessage->asObject(); ++ if (!messageObject) ++ return message; ++ ++ messageObject->setString("browserContextId"_s, m_browserContextID); ++ messageObject->setString("pageProxyId"_s, m_pageProxyID); ++ return messageObject->toJSONString(); ++ } ++ ++ String m_browserContextID; ++ String m_pageProxyID; ++ FrontendChannel& m_frontendChannel; ++ WebPageProxy& m_page; ++}; ++ ++namespace { ++ ++String toBrowserContextIDProtocolString(const PAL::SessionID& sessionID) ++{ ++ StringBuilder builder; ++ builder.append(hex(sessionID.toUInt64(), 16)); ++ return builder.toString(); ++} ++ ++String toPageProxyIDProtocolString(const WebPageProxy& page) ++{ ++ return makeString(page.identifier().toUInt64()); ++} ++ ++ ++static Ref> getEnabledWindowFeatures(const WebCore::WindowFeatures& features) { ++ auto result = JSON::ArrayOf::create(); ++ if (features.x) ++ result->addItem("left=" + String::number(*features.x)); ++ if (features.y) ++ result->addItem("top=" + String::number(*features.y)); ++ if (features.width) ++ result->addItem("width=" + String::number(*features.width)); ++ if (features.height) ++ result->addItem("height=" + String::number(*features.height)); ++ if (features.menuBarVisible) ++ result->addItem("menubar"); ++ if (features.toolBarVisible) ++ result->addItem("toolbar"); ++ if (features.statusBarVisible) ++ result->addItem("status"); ++ if (features.locationBarVisible) ++ result->addItem("location"); ++ if (features.scrollbarsVisible) ++ result->addItem("scrollbars"); ++ if (features.resizable) ++ result->addItem("resizable"); ++ if (features.fullscreen) ++ result->addItem("fullscreen"); ++ if (features.dialog) ++ result->addItem("dialog"); ++ if (features.noopener) ++ result->addItem("noopener"); ++ if (features.noreferrer) ++ result->addItem("noreferrer"); ++ for (const auto& additionalFeature : features.additionalFeatures) ++ result->addItem(additionalFeature); ++ return result; ++} ++ ++Inspector::Protocol::Playwright::CookieSameSitePolicy cookieSameSitePolicy(WebCore::Cookie::SameSitePolicy policy) ++{ ++ switch (policy) { ++ case WebCore::Cookie::SameSitePolicy::None: ++ return Inspector::Protocol::Playwright::CookieSameSitePolicy::None; ++ case WebCore::Cookie::SameSitePolicy::Lax: ++ return Inspector::Protocol::Playwright::CookieSameSitePolicy::Lax; ++ case WebCore::Cookie::SameSitePolicy::Strict: ++ return Inspector::Protocol::Playwright::CookieSameSitePolicy::Strict; ++ } ++ ASSERT_NOT_REACHED(); ++ return Inspector::Protocol::Playwright::CookieSameSitePolicy::None; ++} ++ ++Ref buildObjectForCookie(const WebCore::Cookie& cookie) ++{ ++ return Inspector::Protocol::Playwright::Cookie::create() ++ .setName(cookie.name) ++ .setValue(cookie.value) ++ .setDomain(cookie.domain) ++ .setPath(cookie.path) ++ .setExpires(cookie.expires.valueOr(-1)) ++ .setHttpOnly(cookie.httpOnly) ++ .setSecure(cookie.secure) ++ .setSession(cookie.session) ++ .setSameSite(cookieSameSitePolicy(cookie.sameSite)) ++ .release(); ++} ++ ++} // namespace ++ ++BrowserContext::BrowserContext() = default; ++ ++BrowserContext::~BrowserContext() = default; ++ ++class InspectorPlaywrightAgent::BrowserContextDeletion { ++ WTF_MAKE_NONCOPYABLE(BrowserContextDeletion); ++ WTF_MAKE_FAST_ALLOCATED; ++public: ++ BrowserContextDeletion(std::unique_ptr&& context, size_t numberOfPages, Ref&& callback) ++ : m_browserContext(WTFMove(context)) ++ , m_numberOfPages(numberOfPages) ++ , m_callback(WTFMove(callback)) { } ++ ++ void didDestroyPage(const WebPageProxy& page) ++ { ++ ASSERT(m_browserContext->dataStore->sessionID() == page.sessionID()); ++ // Check if new pages have been created during the context destruction and ++ // close all of them if necessary. ++ if (m_numberOfPages == 1) { ++ auto pages = m_browserContext->pages; ++ size_t numberOfPages = pages.size(); ++ if (numberOfPages > 1) { ++ m_numberOfPages = numberOfPages; ++ for (auto* existingPage : pages) { ++ if (existingPage != &page) ++ existingPage->closePage(); ++ } ++ } ++ } ++ --m_numberOfPages; ++ if (m_numberOfPages) ++ return; ++ m_callback->sendSuccess(); ++ } ++ ++ bool isFinished() const { return !m_numberOfPages; } ++ ++ BrowserContext* context() const { return m_browserContext.get(); } ++ ++private: ++ std::unique_ptr m_browserContext; ++ size_t m_numberOfPages; ++ Ref m_callback; ++}; ++ ++ ++InspectorPlaywrightAgent::InspectorPlaywrightAgent(std::unique_ptr client) ++ : m_frontendChannel(nullptr) ++ , m_frontendRouter(FrontendRouter::create()) ++ , m_backendDispatcher(BackendDispatcher::create(m_frontendRouter.copyRef())) ++ , m_client(std::move(client)) ++ , m_frontendDispatcher(makeUnique(m_frontendRouter)) ++ , m_playwrightDispatcher(PlaywrightBackendDispatcher::create(m_backendDispatcher.get(), this)) ++{ ++} ++ ++InspectorPlaywrightAgent::~InspectorPlaywrightAgent() ++{ ++ if (m_frontendChannel) ++ disconnectFrontend(); ++} ++ ++void InspectorPlaywrightAgent::connectFrontend(FrontendChannel& frontendChannel) ++{ ++ ASSERT(!m_frontendChannel); ++ m_frontendChannel = &frontendChannel; ++ WebPageInspectorController::setObserver(this); ++ ++ m_frontendRouter->connectFrontend(frontendChannel); ++} ++ ++void InspectorPlaywrightAgent::disconnectFrontend() ++{ ++ if (!m_frontendChannel) ++ return; ++ ++ disable(); ++ ++ m_frontendRouter->disconnectFrontend(*m_frontendChannel); ++ ASSERT(!m_frontendRouter->hasFrontends()); ++ ++ WebPageInspectorController::setObserver(nullptr); ++ m_frontendChannel = nullptr; ++ ++ closeImpl([](String error){}); ++} ++ ++void InspectorPlaywrightAgent::dispatchMessageFromFrontend(const String& message) ++{ ++ m_backendDispatcher->dispatch(message, [&](const RefPtr& messageObject) { ++ RefPtr idValue; ++ if (!messageObject->getValue("id"_s, idValue)) ++ return BackendDispatcher::InterceptionResult::Continue; ++ RefPtr pageProxyIDValue; ++ if (!messageObject->getValue("pageProxyId"_s, pageProxyIDValue)) ++ return BackendDispatcher::InterceptionResult::Continue; ++ ++ String pageProxyID; ++ if (!pageProxyIDValue->asString(pageProxyID)) { ++ m_backendDispatcher->reportProtocolError(BackendDispatcher::InvalidRequest, "The type of 'pageProxyId' must be string"_s); ++ m_backendDispatcher->sendPendingErrors(); ++ return BackendDispatcher::InterceptionResult::Intercepted; ++ } ++ ++ if (auto pageProxyChannel = m_pageProxyChannels.get(pageProxyID)) { ++ pageProxyChannel->dispatchMessageFromFrontend(message); ++ return BackendDispatcher::InterceptionResult::Intercepted; ++ } ++ ++ Optional requestId = idValue->asInteger(); ++ if (!requestId) { ++ m_backendDispatcher->reportProtocolError(BackendDispatcher::InvalidRequest, "The type of 'id' must be number"_s); ++ m_backendDispatcher->sendPendingErrors(); ++ return BackendDispatcher::InterceptionResult::Intercepted; ++ } ++ ++ m_backendDispatcher->reportProtocolError(*requestId, BackendDispatcher::InvalidParams, "Cannot find page proxy with provided 'pageProxyId'"_s); ++ m_backendDispatcher->sendPendingErrors(); ++ return BackendDispatcher::InterceptionResult::Intercepted; ++ }); ++} ++ ++void InspectorPlaywrightAgent::didCreateInspectorController(WebPageProxy& page) ++{ ++ if (!m_isEnabled) ++ return; ++ ++ if (isInspectorProcessPool(page.process().processPool())) ++ return; ++ ++ ASSERT(m_frontendChannel); ++ ++ String browserContextID = toBrowserContextIDProtocolString(page.sessionID()); ++ String pageProxyID = toPageProxyIDProtocolString(page); ++ auto* opener = page.configuration().relatedPage(); ++ String openerId; ++ if (opener) ++ openerId = toPageProxyIDProtocolString(*opener); ++ ++ BrowserContext* browserContext = getExistingBrowserContext(browserContextID); ++ browserContext->pages.add(&page); ++ m_frontendDispatcher->pageProxyCreated(browserContextID, pageProxyID, openerId); ++ ++ // Auto-connect to all new pages. ++ auto pageProxyChannel = makeUnique(*m_frontendChannel, browserContextID, pageProxyID, page); ++ page.inspectorController().connectFrontend(*pageProxyChannel); ++ // Always pause new targets if controlled remotely. ++ page.inspectorController().setPauseOnStart(true); ++ m_pageProxyChannels.set(pageProxyID, WTFMove(pageProxyChannel)); ++} ++ ++void InspectorPlaywrightAgent::willDestroyInspectorController(WebPageProxy& page) ++{ ++ if (!m_isEnabled) ++ return; ++ ++ if (isInspectorProcessPool(page.process().processPool())) ++ return; ++ ++ String browserContextID = toBrowserContextIDProtocolString(page.sessionID()); ++ BrowserContext* browserContext = getExistingBrowserContext(browserContextID); ++ browserContext->pages.remove(&page); ++ m_frontendDispatcher->pageProxyDestroyed(toPageProxyIDProtocolString(page)); ++ ++ auto it = m_browserContextDeletions.find(browserContextID); ++ if (it != m_browserContextDeletions.end()) { ++ it->value->didDestroyPage(page); ++ if (it->value->isFinished()) ++ m_browserContextDeletions.remove(it); ++ } ++ ++ String pageProxyID = toPageProxyIDProtocolString(page); ++ auto channelIt = m_pageProxyChannels.find(pageProxyID); ++ ASSERT(channelIt != m_pageProxyChannels.end()); ++ channelIt->value->disconnect(); ++ m_pageProxyChannels.remove(channelIt); ++} ++ ++void InspectorPlaywrightAgent::didFailProvisionalLoad(WebPageProxy& page, uint64_t navigationID, const String& error) ++{ ++ if (!m_isEnabled) ++ return; ++ ++ m_frontendDispatcher->provisionalLoadFailed( ++ toPageProxyIDProtocolString(page), ++ String::number(navigationID), error); ++} ++ ++void InspectorPlaywrightAgent::willCreateNewPage(WebPageProxy& page, const WebCore::WindowFeatures& features, const URL& url) ++{ ++ if (!m_isEnabled) ++ return; ++ ++ m_frontendDispatcher->windowOpen( ++ toPageProxyIDProtocolString(page), ++ url.string(), ++ getEnabledWindowFeatures(features)); ++} ++ ++void InspectorPlaywrightAgent::didFinishScreencast(const PAL::SessionID& sessionID, const String& screencastID) ++{ ++ if (!m_isEnabled) ++ return; ++ ++ m_frontendDispatcher->screencastFinished(screencastID); ++} ++ ++static WebsiteDataStore* findDefaultWebsiteDataStore() { ++ WebsiteDataStore* result = nullptr; ++ WebsiteDataStore::forEachWebsiteDataStore([&result] (WebsiteDataStore& dataStore) { ++ if (dataStore.isPersistent()) { ++ RELEASE_ASSERT(result == nullptr); ++ result = &dataStore; ++ } ++ }); ++ return result; ++} ++ ++Inspector::Protocol::ErrorStringOr InspectorPlaywrightAgent::enable() ++{ ++ if (m_isEnabled) ++ return { }; ++ ++ m_isEnabled = true; ++ ++ auto* defaultDataStore = findDefaultWebsiteDataStore(); ++ if (!m_defaultContext && defaultDataStore) { ++ auto context = std::make_unique(); ++ m_defaultContext = context.get(); ++ context->processPool = WebProcessPool::allProcessPools().first(); ++ context->dataStore = defaultDataStore; ++ // Add default context to the map so that we can easily find it for ++ // created/deleted pages. ++ PAL::SessionID sessionID = context->dataStore->sessionID(); ++ m_browserContexts.set(toBrowserContextIDProtocolString(sessionID), WTFMove(context)); ++ } ++ ++ WebsiteDataStore::forEachWebsiteDataStore([this] (WebsiteDataStore& dataStore) { ++ dataStore.setDownloadInstrumentation(this); ++ }); ++ for (auto& pool : WebProcessPool::allProcessPools()) { ++ for (auto& process : pool->processes()) { ++ for (auto* page : process->pages()) ++ didCreateInspectorController(*page); ++ } ++ } ++ return { }; ++} ++ ++Inspector::Protocol::ErrorStringOr InspectorPlaywrightAgent::disable() ++{ ++ if (!m_isEnabled) ++ return { }; ++ ++ m_isEnabled = false; ++ ++ for (auto it = m_pageProxyChannels.begin(); it != m_pageProxyChannels.end(); ++it) ++ it->value->disconnect(); ++ m_pageProxyChannels.clear(); ++ ++ WebsiteDataStore::forEachWebsiteDataStore([] (WebsiteDataStore& dataStore) { ++ dataStore.setDownloadInstrumentation(nullptr); ++ dataStore.setDownloadForAutomation(Optional(), String()); ++ }); ++ for (auto& it : m_browserContexts) { ++ it.value->dataStore->setDownloadInstrumentation(nullptr); ++ it.value->pages.clear(); ++ } ++ m_browserContextDeletions.clear(); ++ return { }; ++} ++ ++void InspectorPlaywrightAgent::close(Ref&& callback) ++{ ++ closeImpl([callback = WTFMove(callback)] (String error) { ++ if (!callback->isActive()) ++ return; ++ if (error.isNull()) ++ callback->sendSuccess(); ++ else ++ callback->sendFailure(error); ++ }); ++} ++ ++void InspectorPlaywrightAgent::closeImpl(Function&& callback) ++{ ++ Vector pages; ++ // If Web Process crashed it will be disconnected from its pool until ++ // the page reloads. So we cannot discover such processes and the pages ++ // by traversing all process pools and their processes. Instead we look at ++ // all existing Web Processes wether in a pool or not. ++ for (auto* process : WebProcessProxy::allProcessesForInspector()) { ++ for (auto* page : process->pages()) ++ pages.append(page); ++ } ++ for (auto* page : pages) ++ page->closePage(); ++ ++ if (!WebProcessPool::allProcessPools().size()) { ++ m_client->closeBrowser(); ++ callback(String()); ++ return; ++ } ++ ++ if (!m_defaultContext) { ++ m_client->closeBrowser(); ++ callback(String()); ++ return; ++ } ++ ++ m_defaultContext->dataStore->syncLocalStorage([this, callback = WTFMove(callback)] () { ++ if (m_client == nullptr) { ++ callback("no platform delegate to close browser"); ++ } else { ++ m_client->closeBrowser(); ++ callback(String()); ++ } ++ }); ++ ++} ++ ++Inspector::Protocol::ErrorStringOr InspectorPlaywrightAgent::createContext(const String& proxyServer, const String& proxyBypassList) ++{ ++ String errorString; ++ std::unique_ptr browserContext = m_client->createBrowserContext(errorString, proxyServer, proxyBypassList); ++ if (!browserContext) ++ return makeUnexpected(errorString); ++ ++ // Ensure network process. ++ browserContext->dataStore->networkProcess(); ++ browserContext->dataStore->setDownloadInstrumentation(this); ++ ++ PAL::SessionID sessionID = browserContext->dataStore->sessionID(); ++ String browserContextID = toBrowserContextIDProtocolString(sessionID); ++ m_browserContexts.set(browserContextID, WTFMove(browserContext)); ++ return browserContextID; ++} ++ ++void InspectorPlaywrightAgent::deleteContext(const String& browserContextID, Ref&& callback) ++{ ++ String errorString; ++ BrowserContext* browserContext = lookupBrowserContext(errorString, browserContextID); ++ if (!lookupBrowserContext(errorString, browserContextID)) { ++ callback->sendFailure(errorString); ++ return; ++ } ++ ++ if (browserContext == m_defaultContext) { ++ callback->sendFailure("Cannot delete default context"_s); ++ return; ++ } ++ ++ auto pages = browserContext->pages; ++ PAL::SessionID sessionID = browserContext->dataStore->sessionID(); ++ auto contextHolder = m_browserContexts.take(browserContextID); ++ if (pages.isEmpty()) { ++ callback->sendSuccess(); ++ } else { ++ m_browserContextDeletions.set(browserContextID, makeUnique(WTFMove(contextHolder), pages.size(), WTFMove(callback))); ++ for (auto* page : pages) ++ page->closePage(); ++ } ++ m_client->deleteBrowserContext(errorString, sessionID); ++} ++ ++Inspector::Protocol::ErrorStringOr InspectorPlaywrightAgent::createPage(const String& browserContextID) ++{ ++ String errorString; ++ BrowserContext* browserContext = lookupBrowserContext(errorString, browserContextID); ++ if (!browserContext) ++ return makeUnexpected(errorString); ++ ++ RefPtr page = m_client->createPage(errorString, *browserContext); ++ if (!page) ++ return makeUnexpected(errorString); ++ ++ return toPageProxyIDProtocolString(*page); ++} ++ ++WebFrameProxy* InspectorPlaywrightAgent::frameForID(const String& frameID, String& error) ++{ ++ size_t dotPos = frameID.find("."); ++ if (dotPos == notFound) { ++ error = "Invalid frame id"_s; ++ return nullptr; ++ } ++ ++ if (!frameID.isAllASCII()) { ++ error = "Invalid frame id"_s; ++ return nullptr; ++ } ++ ++ String processIDString = frameID.left(dotPos); ++ uint64_t pid = strtoull(processIDString.ascii().data(), 0, 10); ++ auto processID = makeObjectIdentifier(pid); ++ WebProcessProxy* process = WebProcessProxy::processForIdentifier(processID); ++ if (!process) { ++ error = "Cannot find web process for the frame id"_s; ++ return nullptr; ++ } ++ ++ String frameIDString = frameID.substring(dotPos + 1); ++ uint64_t frameIDNumber = strtoull(frameIDString.ascii().data(), 0, 10); ++ auto frameIdentifier = makeObjectIdentifier(frameIDNumber); ++ WebFrameProxy* frame = process->webFrame(frameIdentifier); ++ if (!frame) { ++ error = "Cannot find web frame for the frame id"_s; ++ return nullptr; ++ } ++ ++ return frame; ++} ++ ++void InspectorPlaywrightAgent::navigate(const String& url, const String& pageProxyID, const String& frameID, const String& referrer, Ref&& callback) ++{ ++ auto* pageProxyChannel = m_pageProxyChannels.get(pageProxyID); ++ if (!pageProxyChannel) { ++ callback->sendFailure("Cannot find page proxy with provided 'pageProxyId'"_s); ++ return; ++ } ++ ++ WebCore::ResourceRequest resourceRequest { url }; ++ ++ if (!!referrer) ++ resourceRequest.setHTTPReferrer(referrer); ++ ++ if (!resourceRequest.url().isValid()) { ++ callback->sendFailure("Cannot navigate to invalid URL"_s); ++ return; ++ } ++ ++ WebFrameProxy* frame = nullptr; ++ if (!!frameID) { ++ String error; ++ frame = frameForID(frameID, error); ++ if (!frame) { ++ callback->sendFailure(error); ++ return; ++ } ++ ++ if (frame->page() != &pageProxyChannel->page()) { ++ callback->sendFailure("Frame with specified is not from the specified page"_s); ++ return; ++ } ++ } ++ ++ pageProxyChannel->page().inspectorController().navigate(WTFMove(resourceRequest), frame, [callback = WTFMove(callback)](const String& error, uint64_t navigationID) { ++ if (!error.isEmpty()) { ++ callback->sendFailure(error); ++ return; ++ } ++ ++ String navigationIDString; ++ if (navigationID) ++ navigationIDString = String::number(navigationID); ++ callback->sendSuccess(navigationIDString); ++ }); ++} ++ ++Inspector::Protocol::ErrorStringOr InspectorPlaywrightAgent::setIgnoreCertificateErrors(const String& browserContextID, bool ignore) ++{ ++ String errorString; ++ BrowserContext* browserContext = lookupBrowserContext(errorString, browserContextID); ++ if (!errorString.isEmpty()) ++ return makeUnexpected(errorString); ++ ++ PAL::SessionID sessionID = browserContext->dataStore->sessionID(); ++ NetworkProcessProxy& networkProcess = browserContext->dataStore->networkProcess(); ++ networkProcess.send(Messages::NetworkProcess::SetIgnoreCertificateErrors(sessionID, ignore), 0); ++ return { }; ++} ++ ++void InspectorPlaywrightAgent::getAllCookies(const String& browserContextID, Ref&& callback) { ++ String errorString; ++ BrowserContext* browserContext = lookupBrowserContext(errorString, browserContextID); ++ if (!errorString.isEmpty()) { ++ callback->sendFailure(errorString); ++ return; ++ } ++ ++ PAL::SessionID sessionID = browserContext->dataStore->sessionID(); ++ NetworkProcessProxy& networkProcess = browserContext->dataStore->networkProcess(); ++ networkProcess.sendWithAsyncReply(Messages::NetworkProcess::GetAllCookies(sessionID), ++ [callback = WTFMove(callback)](Vector allCookies) { ++ if (!callback->isActive()) ++ return; ++ auto cookies = JSON::ArrayOf::create(); ++ for (const auto& cookie : allCookies) ++ cookies->addItem(buildObjectForCookie(cookie)); ++ callback->sendSuccess(WTFMove(cookies)); ++ }, 0); ++} ++ ++void InspectorPlaywrightAgent::setCookies(const String& browserContextID, Ref&& in_cookies, Ref&& callback) { ++ String errorString; ++ BrowserContext* browserContext = lookupBrowserContext(errorString, browserContextID); ++ if (!errorString.isEmpty()) { ++ callback->sendFailure(errorString); ++ return; ++ } ++ ++ NetworkProcessProxy& networkProcess = browserContext->dataStore->networkProcess(); ++ PAL::SessionID sessionID = browserContext->dataStore->sessionID(); ++ ++ Vector cookies; ++ for (unsigned i = 0; i < in_cookies->length(); ++i) { ++ RefPtr item = in_cookies->get(i); ++ RefPtr obj = item->asObject(); ++ if (!obj) { ++ callback->sendFailure("Invalid cookie payload format"_s); ++ return; ++ } ++ ++ WebCore::Cookie cookie; ++ cookie.name = obj->getString("name"); ++ cookie.value = obj->getString("value"); ++ cookie.domain = obj->getString("domain"); ++ cookie.path = obj->getString("path"); ++ if (!cookie.name || !cookie.value || !cookie.domain || !cookie.path) { ++ callback->sendFailure("Invalid file payload format"_s); ++ return; ++ } ++ ++ Optional expires = obj->getDouble("expires"); ++ if (expires && *expires != -1) ++ cookie.expires = *expires; ++ if (Optional value = obj->getBoolean("httpOnly")) ++ cookie.httpOnly = *value; ++ if (Optional value = obj->getBoolean("secure")) ++ cookie.secure = *value; ++ if (Optional value = obj->getBoolean("session")) ++ cookie.session = *value; ++ String sameSite; ++ if (obj->getString("sameSite", sameSite)) { ++ if (sameSite == "None") ++ cookie.sameSite = WebCore::Cookie::SameSitePolicy::None; ++ if (sameSite == "Lax") ++ cookie.sameSite = WebCore::Cookie::SameSitePolicy::Lax; ++ if (sameSite == "Strict") ++ cookie.sameSite = WebCore::Cookie::SameSitePolicy::Strict; ++ } ++ cookies.append(WTFMove(cookie)); ++ } ++ ++ networkProcess.sendWithAsyncReply(Messages::NetworkProcess::SetCookies(sessionID, WTFMove(cookies)), ++ [callback = WTFMove(callback)](bool success) { ++ if (!callback->isActive()) ++ return; ++ ++ if (success) ++ callback->sendSuccess(); ++ else ++ callback->sendFailure("Internal error: no network storage"_s); ++ callback->sendSuccess(); ++ }, 0); ++} ++ ++void InspectorPlaywrightAgent::deleteAllCookies(const String& browserContextID, Ref&& callback) { ++ String errorString; ++ BrowserContext* browserContext = lookupBrowserContext(errorString, browserContextID); ++ if (!errorString.isEmpty()) { ++ callback->sendFailure(errorString); ++ return; ++ } ++ ++ NetworkProcessProxy& networkProcess = browserContext->dataStore->networkProcess(); ++ PAL::SessionID sessionID = browserContext->dataStore->sessionID(); ++ networkProcess.sendWithAsyncReply(Messages::NetworkProcess::DeleteAllCookies(sessionID), ++ [callback = WTFMove(callback)](bool success) { ++ if (!callback->isActive()) ++ return; ++ if (success) ++ callback->sendSuccess(); ++ else ++ callback->sendFailure("Internal error: no network storage"_s); ++ }, 0); ++} ++ ++Inspector::Protocol::ErrorStringOr InspectorPlaywrightAgent::setLanguages(Ref&& languages, const String& browserContextID) ++{ ++ String errorString; ++ BrowserContext* browserContext = lookupBrowserContext(errorString, browserContextID); ++ if (!errorString.isEmpty()) ++ return makeUnexpected(errorString); ++ ++ Vector items; ++ for (const auto& value : languages.get()) { ++ String language; ++ if (!value->asString(language)) ++ return makeUnexpected("Language must be a string"_s); ++ ++ items.append(language); ++ } ++ ++ browserContext->dataStore->setLanguagesForAutomation(WTFMove(items)); ++ return { }; ++} ++ ++Inspector::Protocol::ErrorStringOr InspectorPlaywrightAgent::setDownloadBehavior(const String& behavior, const String& downloadPath, const String& browserContextID) ++{ ++ String errorString; ++ BrowserContext* browserContext = lookupBrowserContext(errorString, browserContextID); ++ if (!errorString.isEmpty()) ++ return makeUnexpected(errorString); ++ ++ Optional allow; ++ if (behavior == "allow"_s) ++ allow = true; ++ if (behavior == "deny"_s) ++ allow = false; ++ browserContext->dataStore->setDownloadForAutomation(allow, downloadPath); ++ return { }; ++} ++ ++Inspector::Protocol::ErrorStringOr InspectorPlaywrightAgent::setGeolocationOverride(const String& browserContextID, RefPtr&& geolocation) ++{ ++ String errorString; ++ BrowserContext* browserContext = lookupBrowserContext(errorString, browserContextID); ++ if (!errorString.isEmpty()) ++ return makeUnexpected(errorString); ++ ++ auto* geoManager = browserContext->processPool->supplement(); ++ if (!geoManager) ++ return makeUnexpected("Internal error: geolocation manager is not available."_s); ++ ++ if (geolocation) { ++ Optional timestamp = geolocation->getDouble("timestamp"); ++ Optional latitude = geolocation->getDouble("latitude"); ++ Optional longitude = geolocation->getDouble("longitude"); ++ Optional accuracy = geolocation->getDouble("accuracy"); ++ if (!timestamp || !latitude || !longitude || !accuracy) ++ return makeUnexpected("Invalid geolocation format"_s); ++ ++ auto position = WebGeolocationPosition::create(WebCore::GeolocationPositionData(*timestamp, *latitude, *longitude, *accuracy)); ++ geoManager->providerDidChangePosition(&position.get()); ++ } else { ++ geoManager->providerDidFailToDeterminePosition("Position unavailable"_s); ++ } ++ return { }; ++} ++ ++void InspectorPlaywrightAgent::downloadCreated(const String& uuid, const WebCore::ResourceRequest& request, const FrameInfoData& frameInfoData, WebPageProxy* page) ++{ ++ if (!m_isEnabled) ++ return; ++ String frameID = WebCore::InspectorPageAgent::makeFrameID(page->process().coreProcessIdentifier(), frameInfoData.frameID ? *frameInfoData.frameID : page->mainFrame()->frameID()); ++ m_frontendDispatcher->downloadCreated( ++ toPageProxyIDProtocolString(*page), ++ frameID, ++ uuid, request.url().string()); ++} ++ ++void InspectorPlaywrightAgent::downloadFilenameSuggested(const String& uuid, const String& suggestedFilename) ++{ ++ if (!m_isEnabled) ++ return; ++ m_frontendDispatcher->downloadFilenameSuggested(uuid, suggestedFilename); ++} ++ ++void InspectorPlaywrightAgent::downloadFinished(const String& uuid, const String& error) ++{ ++ if (!m_isEnabled) ++ return; ++ m_frontendDispatcher->downloadFinished(uuid, error); ++} ++ ++BrowserContext* InspectorPlaywrightAgent::getExistingBrowserContext(const String& browserContextID) ++{ ++ BrowserContext* browserContext = m_browserContexts.get(browserContextID); ++ if (browserContext) ++ return browserContext; ++ ++ auto it = m_browserContextDeletions.find(browserContextID); ++ RELEASE_ASSERT(it != m_browserContextDeletions.end()); ++ return it->value->context(); ++} ++ ++BrowserContext* InspectorPlaywrightAgent::lookupBrowserContext(ErrorString& errorString, const String& browserContextID) ++{ ++ if (!browserContextID) { ++ if (!m_defaultContext) ++ errorString = "Browser started with no default context"_s; ++ return m_defaultContext; ++ } ++ ++ BrowserContext* browserContext = m_browserContexts.get(browserContextID); ++ if (!browserContext) ++ errorString = "Could not find browser context for given id"_s; ++ return browserContext; ++} ++ ++} // namespace WebKit ++ ++#endif // ENABLE(REMOTE_INSPECTOR) +diff --git a/Source/WebKit/UIProcess/InspectorPlaywrightAgent.h b/Source/WebKit/UIProcess/InspectorPlaywrightAgent.h +new file mode 100644 +index 0000000000000000000000000000000000000000..f5eecb22827ecd3b002cb1dd9e9938a1db0cb36e +--- /dev/null ++++ b/Source/WebKit/UIProcess/InspectorPlaywrightAgent.h +@@ -0,0 +1,123 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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. ++ */ ++ ++#pragma once ++ ++#if ENABLE(REMOTE_INSPECTOR) ++ ++#include "InspectorPlaywrightAgentClient.h" ++#include ++#include "WebPageInspectorController.h" ++#include "WebProcessPool.h" ++#include ++#include ++#include ++ ++namespace Inspector { ++class BackendDispatcher; ++class FrontendChannel; ++class FrontendRouter; ++class PlaywrightFrontendDispatcher; ++} ++ ++namespace PAL { ++class SessionID; ++} ++ ++namespace WebKit { ++ ++class WebFrameProxy; ++ ++class InspectorPlaywrightAgent final ++ : public WebPageInspectorControllerObserver ++ , public Inspector::PlaywrightBackendDispatcherHandler ++ , public DownloadInstrumentation { ++ WTF_MAKE_NONCOPYABLE(InspectorPlaywrightAgent); ++ WTF_MAKE_FAST_ALLOCATED; ++public: ++ explicit InspectorPlaywrightAgent(std::unique_ptr client); ++ ~InspectorPlaywrightAgent() override; ++ ++ // Transport ++ void connectFrontend(Inspector::FrontendChannel&); ++ void disconnectFrontend(); ++ void dispatchMessageFromFrontend(const String& message); ++ ++private: ++ class BrowserContextDeletion; ++ class PageProxyChannel; ++ class TargetHandler; ++ ++ // WebPageInspectorControllerObserver ++ void didCreateInspectorController(WebPageProxy&) override; ++ void willDestroyInspectorController(WebPageProxy&) override; ++ void didFailProvisionalLoad(WebPageProxy&, uint64_t navigationID, const String& error) override; ++ void willCreateNewPage(WebPageProxy&, const WebCore::WindowFeatures&, const URL&) override; ++ void didFinishScreencast(const PAL::SessionID& sessionID, const String& screencastID) override; ++ ++ // PlaywrightDispatcherHandler ++ Inspector::Protocol::ErrorStringOr enable() override; ++ Inspector::Protocol::ErrorStringOr disable() override; ++ void close(Ref&&) override; ++ Inspector::Protocol::ErrorStringOr createContext(const String& proxyServer, const String& proxyBypassList) override; ++ void deleteContext(const String& browserContextID, Ref&& callback) override; ++ Inspector::Protocol::ErrorStringOr createPage(const String& browserContextID) override; ++ void navigate(const String& url, const String& pageProxyID, const String& frameId, const String& referrer, Ref&&) override; ++ Inspector::Protocol::ErrorStringOr setIgnoreCertificateErrors(const String& browserContextID, bool ignore) override; ++ ++ void getAllCookies(const String& browserContextID, Ref&&) override; ++ void setCookies(const String& browserContextID, Ref&& in_cookies, Ref&&) override; ++ void deleteAllCookies(const String& browserContextID, Ref&&) override; ++ ++ Inspector::Protocol::ErrorStringOr setGeolocationOverride(const String& browserContextID, RefPtr&& geolocation) override; ++ Inspector::Protocol::ErrorStringOr setLanguages(Ref&& languages, const String& browserContextID) override; ++ Inspector::Protocol::ErrorStringOr setDownloadBehavior(const String& behavior, const String& downloadPath, const String& browserContextID) override; ++ ++ // DownloadInstrumentation ++ void downloadCreated(const String& uuid, const WebCore::ResourceRequest&, const FrameInfoData& frameInfoData, WebPageProxy* page) override; ++ void downloadFilenameSuggested(const String& uuid, const String& suggestedFilename) override; ++ void downloadFinished(const String& uuid, const String& error) override; ++ ++ BrowserContext* getExistingBrowserContext(const String& browserContextID); ++ BrowserContext* lookupBrowserContext(Inspector::ErrorString&, const String& browserContextID); ++ WebFrameProxy* frameForID(const String& frameID, String& error); ++ void closeImpl(Function&&); ++ ++ Inspector::FrontendChannel* m_frontendChannel { nullptr }; ++ Ref m_frontendRouter; ++ Ref m_backendDispatcher; ++ std::unique_ptr m_client; ++ std::unique_ptr m_frontendDispatcher; ++ Ref m_playwrightDispatcher; ++ HashMap> m_pageProxyChannels; ++ BrowserContext* m_defaultContext; ++ HashMap> m_browserContexts; ++ HashMap> m_browserContextDeletions; ++ bool m_isEnabled { false }; ++}; ++ ++} // namespace WebKit ++ ++#endif // ENABLE(REMOTE_INSPECTOR) +diff --git a/Source/WebKit/UIProcess/InspectorPlaywrightAgentClient.h b/Source/WebKit/UIProcess/InspectorPlaywrightAgentClient.h +new file mode 100644 +index 0000000000000000000000000000000000000000..11c8eadafca764aa549cb27c24967e15e6975774 +--- /dev/null ++++ b/Source/WebKit/UIProcess/InspectorPlaywrightAgentClient.h +@@ -0,0 +1,66 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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. ++ */ ++ ++#pragma once ++ ++#if ENABLE(REMOTE_INSPECTOR) ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++namespace WebKit { ++ ++class WebsiteDataStore; ++class WebPageProxy; ++class WebProcessPool; ++ ++class BrowserContext { ++ WTF_MAKE_NONCOPYABLE(BrowserContext); ++ WTF_MAKE_FAST_ALLOCATED; ++public: ++ BrowserContext(); ++ ~BrowserContext(); ++ ++ RefPtr dataStore; ++ RefPtr processPool; ++ HashSet pages; ++}; ++ ++class InspectorPlaywrightAgentClient { ++public: ++ virtual ~InspectorPlaywrightAgentClient() = default; ++ virtual RefPtr createPage(WTF::String& error, const BrowserContext& context) = 0; ++ virtual void closeBrowser() = 0; ++ virtual std::unique_ptr createBrowserContext(WTF::String& error, const WTF::String& proxyServer, const WTF::String& proxyBypassList) = 0; ++ virtual void deleteBrowserContext(WTF::String& error, PAL::SessionID) = 0; ++}; ++ ++} // namespace WebKit ++ ++#endif // ENABLE(REMOTE_INSPECTOR) +diff --git a/Source/WebKit/UIProcess/Launcher/win/ProcessLauncherWin.cpp b/Source/WebKit/UIProcess/Launcher/win/ProcessLauncherWin.cpp +index 7a14cfba15c103a2d4fe263fa49d25af3c396ec2..3ee0e154349661632799057c71f1d1f1551c2d69 100644 +--- a/Source/WebKit/UIProcess/Launcher/win/ProcessLauncherWin.cpp ++++ b/Source/WebKit/UIProcess/Launcher/win/ProcessLauncherWin.cpp +@@ -96,8 +96,11 @@ void ProcessLauncher::launchProcess() + + STARTUPINFO startupInfo { }; + startupInfo.cb = sizeof(startupInfo); +- startupInfo.dwFlags = STARTF_USESHOWWINDOW; ++ startupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; + startupInfo.wShowWindow = SW_HIDE; ++ startupInfo.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE); ++ startupInfo.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE); ++ startupInfo.hStdError = ::GetStdHandle(STD_ERROR_HANDLE); + PROCESS_INFORMATION processInformation { }; + BOOL result = ::CreateProcess(0, commandLine.data(), 0, 0, true, 0, 0, 0, &startupInfo, &processInformation); + +diff --git a/Source/WebKit/UIProcess/PageClient.h b/Source/WebKit/UIProcess/PageClient.h +index bafa92d1805ed200198072aa5cf391bc928073fe..bc93d16f3fce2647b831f93f6caf361d5d1db286 100644 +--- a/Source/WebKit/UIProcess/PageClient.h ++++ b/Source/WebKit/UIProcess/PageClient.h +@@ -312,6 +312,11 @@ public: + virtual void selectionDidChange() = 0; + #endif + ++// Paywright begin ++#if PLATFORM(COCOA) ++ virtual RetainPtr takeSnapshotForAutomation() = 0; ++#endif ++// Paywright end + #if PLATFORM(COCOA) || PLATFORM(GTK) + virtual RefPtr takeViewSnapshot(Optional&&) = 0; + #endif +@@ -328,6 +333,7 @@ public: + virtual WebCore::IntRect rootViewToAccessibilityScreen(const WebCore::IntRect&) = 0; + #if PLATFORM(MAC) + virtual WebCore::IntRect rootViewToWindow(const WebCore::IntRect&) = 0; ++ virtual int browserToolbarHeight() const { return 0; } + #endif + #if PLATFORM(IOS_FAMILY) + virtual void didNotHandleTapAsClick(const WebCore::IntPoint&) = 0; +diff --git a/Source/WebKit/UIProcess/RemoteInspectorPipe.cpp b/Source/WebKit/UIProcess/RemoteInspectorPipe.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..1d1eb4591ab865688bec7505334a208e00918701 +--- /dev/null ++++ b/Source/WebKit/UIProcess/RemoteInspectorPipe.cpp +@@ -0,0 +1,226 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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 "RemoteInspectorPipe.h" ++ ++#if ENABLE(REMOTE_INSPECTOR) ++ ++#include "InspectorPlaywrightAgent.h" ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if OS(UNIX) ++#include ++#include ++#endif ++ ++#if PLATFORM(WIN) ++#include ++#endif ++ ++namespace WebKit { ++ ++namespace { ++ ++const int readFD = 3; ++const int writeFD = 4; ++ ++const size_t kWritePacketSize = 1 << 16; ++ ++#if PLATFORM(WIN) ++HANDLE readHandle; ++HANDLE writeHandle; ++#endif ++ ++size_t ReadBytes(void* buffer, size_t size, bool exact_size) ++{ ++ size_t bytesRead = 0; ++ while (bytesRead < size) { ++#if PLATFORM(WIN) ++ DWORD sizeRead = 0; ++ bool hadError = !ReadFile(readHandle, static_cast(buffer) + bytesRead, ++ size - bytesRead, &sizeRead, nullptr); ++#else ++ int sizeRead = read(readFD, static_cast(buffer) + bytesRead, ++ size - bytesRead); ++ if (sizeRead < 0 && errno == EINTR) ++ continue; ++ bool hadError = sizeRead <= 0; ++#endif ++ if (hadError) { ++ return 0; ++ } ++ bytesRead += sizeRead; ++ if (!exact_size) ++ break; ++ } ++ return bytesRead; ++} ++ ++void WriteBytes(const char* bytes, size_t size) ++{ ++ size_t totalWritten = 0; ++ while (totalWritten < size) { ++ size_t length = size - totalWritten; ++ if (length > kWritePacketSize) ++ length = kWritePacketSize; ++#if PLATFORM(WIN) ++ DWORD bytesWritten = 0; ++ bool hadError = !WriteFile(writeHandle, bytes + totalWritten, static_cast(length), &bytesWritten, nullptr); ++#else ++ int bytesWritten = write(writeFD, bytes + totalWritten, length); ++ if (bytesWritten < 0 && errno == EINTR) ++ continue; ++ bool hadError = bytesWritten <= 0; ++#endif ++ if (hadError) ++ return; ++ totalWritten += bytesWritten; ++ } ++} ++ ++} // namespace ++ ++class RemoteInspectorPipe::RemoteFrontendChannel : public Inspector::FrontendChannel { ++ WTF_MAKE_FAST_ALLOCATED; ++ ++public: ++ RemoteFrontendChannel() ++ : m_senderQueue(WorkQueue::create("Inspector pipe writer")) ++ { ++ } ++ ++ ~RemoteFrontendChannel() override = default; ++ ++ ConnectionType connectionType() const override ++ { ++ return ConnectionType::Remote; ++ } ++ ++ void sendMessageToFrontend(const String& message) override ++ { ++ m_senderQueue->dispatch([message = message.isolatedCopy()]() { ++ WriteBytes(message.ascii().data(), message.length()); ++ WriteBytes("\0", 1); ++ }); ++ } ++ ++private: ++ Ref m_senderQueue; ++}; ++ ++RemoteInspectorPipe::RemoteInspectorPipe(InspectorPlaywrightAgent& playwrightAgent) ++ : m_playwrightAgent(playwrightAgent) ++{ ++ // Initialize main loop before creating WorkQueue ++ WTF::initializeMainThread(); ++ m_remoteFrontendChannel = makeUnique(); ++ start(); ++} ++ ++RemoteInspectorPipe::~RemoteInspectorPipe() ++{ ++ stop(); ++} ++ ++bool RemoteInspectorPipe::start() ++{ ++ if (m_receiverThread) ++ return true; ++ ++#if PLATFORM(WIN) ++ readHandle = reinterpret_cast(_get_osfhandle(readFD)); ++ writeHandle = reinterpret_cast(_get_osfhandle(writeFD)); ++#endif ++ ++ m_playwrightAgent.connectFrontend(*m_remoteFrontendChannel); ++ m_terminated = false; ++ m_receiverThread = Thread::create("Inspector pipe reader", [this] { ++ workerRun(); ++ }); ++ return true; ++} ++ ++void RemoteInspectorPipe::stop() ++{ ++ if (!m_receiverThread) ++ return; ++ ++ m_playwrightAgent.disconnectFrontend(); ++ ++ m_terminated = true; ++ m_receiverThread->waitForCompletion(); ++ m_receiverThread = nullptr; ++} ++ ++void RemoteInspectorPipe::workerRun() ++{ ++ const size_t bufSize = 256 * 1024; ++ auto buffer = makeUniqueArray(bufSize); ++ Vector line; ++ while (!m_terminated) { ++ size_t size = ReadBytes(buffer.get(), bufSize, false); ++ if (!size) { ++ RunLoop::main().dispatch([this] { ++ if (!m_terminated) ++ m_playwrightAgent.disconnectFrontend(); ++ }); ++ break; ++ } ++ size_t start = 0; ++ size_t end = line.size(); ++ line.append(buffer.get(), size); ++ while (true) { ++ for (; end < line.size(); ++end) { ++ if (line[end] == '\0') ++ break; ++ } ++ if (end == line.size()) ++ break; ++ ++ if (end > start) { ++ String message = String::fromUTF8(line.data() + start, end - start); ++ RunLoop::main().dispatch([this, message] { ++ if (!m_terminated) ++ m_playwrightAgent.dispatchMessageFromFrontend(message); ++ }); ++ } ++ ++end; ++ start = end; ++ } ++ if (start != 0 && start < line.size()) ++ memmove(line.data(), line.data() + start, line.size() - start); ++ line.shrink(line.size() - start); ++ } ++} ++ ++} // namespace WebKit ++ ++#endif // ENABLE(REMOTE_INSPECTOR) +diff --git a/Source/WebKit/UIProcess/RemoteInspectorPipe.h b/Source/WebKit/UIProcess/RemoteInspectorPipe.h +new file mode 100644 +index 0000000000000000000000000000000000000000..6d04f9290135069359ce6bf8726546482fd1dc95 +--- /dev/null ++++ b/Source/WebKit/UIProcess/RemoteInspectorPipe.h +@@ -0,0 +1,65 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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. ++ */ ++ ++#pragma once ++ ++#if ENABLE(REMOTE_INSPECTOR) ++ ++#include ++#include ++#include ++ ++namespace Inspector { ++class FrontendChannel; ++} ++ ++namespace WebKit { ++ ++class InspectorPlaywrightAgent; ++ ++class RemoteInspectorPipe { ++ WTF_MAKE_NONCOPYABLE(RemoteInspectorPipe); ++ WTF_MAKE_FAST_ALLOCATED; ++public: ++ explicit RemoteInspectorPipe(InspectorPlaywrightAgent&); ++ ~RemoteInspectorPipe(); ++ ++private: ++ class RemoteFrontendChannel; ++ ++ bool start(); ++ void stop(); ++ ++ void workerRun(); ++ ++ RefPtr m_receiverThread; ++ std::atomic m_terminated { false }; ++ std::unique_ptr m_remoteFrontendChannel; ++ InspectorPlaywrightAgent& m_playwrightAgent; ++}; ++ ++} // namespace WebKit ++ ++#endif // ENABLE(REMOTE_INSPECTOR) +diff --git a/Source/WebKit/UIProcess/SpeechRecognitionRemoteRealtimeMediaSource.cpp b/Source/WebKit/UIProcess/SpeechRecognitionRemoteRealtimeMediaSource.cpp +index 4384d49a17c9ef03c30b89f724b5b5397214d97c..5f44111b25053bc26ff7140ed67018dfa8cb21af 100644 +--- a/Source/WebKit/UIProcess/SpeechRecognitionRemoteRealtimeMediaSource.cpp ++++ b/Source/WebKit/UIProcess/SpeechRecognitionRemoteRealtimeMediaSource.cpp +@@ -37,6 +37,8 @@ + #include + #endif + ++using namespace WebCore; ++ + namespace WebKit { + + Ref SpeechRecognitionRemoteRealtimeMediaSource::create(SpeechRecognitionRemoteRealtimeMediaSourceManager& manager, const WebCore::CaptureDevice& captureDevice) +diff --git a/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.h b/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.h +index 94e4a4d7e4f8e16f20ecb94a7eb048fe629358be..cb508bc16d3acbb7a80c22ef353f9b1375566e5a 100644 +--- a/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.h ++++ b/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.h +@@ -28,6 +28,7 @@ + #if ENABLE(WEB_AUTHN) + + #include "LocalConnection.h" ++#include + #include + + namespace WebKit { +diff --git a/Source/WebKit/UIProcess/WebContextMenuProxy.h b/Source/WebKit/UIProcess/WebContextMenuProxy.h +index 2d2c5765c01f2680749a8f193d61fb666a08ab86..4a26ae64fee4c7e57e0336361ad92f9b024b5349 100644 +--- a/Source/WebKit/UIProcess/WebContextMenuProxy.h ++++ b/Source/WebKit/UIProcess/WebContextMenuProxy.h +@@ -43,6 +43,7 @@ public: + virtual ~WebContextMenuProxy(); + + virtual void show(); ++ virtual void hide() {} + + WebPageProxy* page() const { return m_page.get(); } + +diff --git a/Source/WebKit/UIProcess/WebGeolocationManagerProxy.cpp b/Source/WebKit/UIProcess/WebGeolocationManagerProxy.cpp +index 04f3227cd55c992a42cd96a3f25d697aed7965a2..f0d36935f47bab03ea2ec50b705092068ecd3efa 100644 +--- a/Source/WebKit/UIProcess/WebGeolocationManagerProxy.cpp ++++ b/Source/WebKit/UIProcess/WebGeolocationManagerProxy.cpp +@@ -128,7 +128,8 @@ void WebGeolocationManagerProxy::startUpdating(IPC::Connection& connection, WebP + if (!wasUpdating) { + m_provider->setEnableHighAccuracy(*this, isHighAccuracyEnabled()); + m_provider->startUpdating(*this); +- } else if (m_lastPosition) ++ } ++ if (m_lastPosition) + connection.send(Messages::WebGeolocationManager::DidChangePosition(m_lastPosition.value()), 0); + } + +diff --git a/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.cpp b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..e6e700e846ea091a190b6b1f5c5636fed4389909 +--- /dev/null ++++ b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.cpp +@@ -0,0 +1,146 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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 "WebPageInspectorEmulationAgent.h" ++ ++#include "APIPageConfiguration.h" ++#include "WebPageProxy.h" ++#include "WebPreferences.h" ++#include "PageClient.h" ++#include ++#include ++ ++ ++namespace WebKit { ++ ++using namespace Inspector; ++ ++WebPageInspectorEmulationAgent::WebPageInspectorEmulationAgent(BackendDispatcher& backendDispatcher, WebPageProxy& page) ++ : InspectorAgentBase("Emulation"_s) ++ , m_backendDispatcher(EmulationBackendDispatcher::create(backendDispatcher, this)) ++ , m_page(page) ++{ ++} ++ ++WebPageInspectorEmulationAgent::~WebPageInspectorEmulationAgent() ++{ ++} ++ ++void WebPageInspectorEmulationAgent::didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*) ++{ ++} ++ ++void WebPageInspectorEmulationAgent::willDestroyFrontendAndBackend(DisconnectReason) ++{ ++ m_commandsToRunWhenShown.clear(); ++} ++ ++void WebPageInspectorEmulationAgent::setDeviceMetricsOverride(int width, int height, double deviceScaleFactor, bool fixedlayout, Ref&& callback) ++{ ++#if PLATFORM(GTK) ++ // On gtk, fixed layout doesn't work with compositing enabled ++ // FIXME: This turns off compositing forever, even if fixedLayout is disabled. ++ if (fixedlayout) { ++ auto copy = m_page.preferences().copy(); ++ copy->setAcceleratedCompositingEnabled(false); ++ m_page.setPreferences(copy); ++ } ++#endif ++ ++ m_page.setCustomDeviceScaleFactor(deviceScaleFactor); ++ m_page.setUseFixedLayout(fixedlayout); ++ if (!m_page.pageClient().isViewVisible() && m_page.configuration().relatedPage()) { ++ m_commandsToRunWhenShown.append([this, width, height, callback = WTFMove(callback)]() mutable { ++ setSize(width, height, WTFMove(callback)); ++ }); ++ } else { ++ setSize(width, height, WTFMove(callback)); ++ } ++} ++ ++void WebPageInspectorEmulationAgent::setSize(int width, int height, Ref&& callback) ++{ ++ platformSetSize(width, height, [callback = WTFMove(callback)](const String& error) { ++ if (error.isEmpty()) ++ callback->sendSuccess(); ++ else ++ callback->sendFailure(error); ++ }); ++} ++ ++Inspector::Protocol::ErrorStringOr WebPageInspectorEmulationAgent::setJavaScriptEnabled(bool enabled) ++{ ++ auto copy = m_page.preferences().copy(); ++ copy->setJavaScriptEnabled(enabled); ++ m_page.setPreferences(copy); ++ return { }; ++} ++ ++Inspector::Protocol::ErrorStringOr WebPageInspectorEmulationAgent::setAuthCredentials(const String& username, const String& password) ++{ ++ if (!!username && !!password) ++ m_page.setAuthCredentialsForAutomation(WebCore::Credential(username, password, CredentialPersistencePermanent)); ++ else ++ m_page.setAuthCredentialsForAutomation(Optional()); ++ return { }; ++} ++ ++Inspector::Protocol::ErrorStringOr WebPageInspectorEmulationAgent::setActiveAndFocused(Optional&& active) ++{ ++ m_page.setActiveForAutomation(WTFMove(active)); ++ return { }; ++} ++ ++Inspector::Protocol::ErrorStringOr WebPageInspectorEmulationAgent::grantPermissions(const String& origin, Ref&& values) ++{ ++ HashSet set; ++ for (const auto& value : values.get()) { ++ String name; ++ if (!value->asString(name)) ++ return makeUnexpected("Permission must be a string"_s); ++ ++ set.add(name); ++ } ++ m_permissions.set(origin, WTFMove(set)); ++ m_page.setPermissionsForAutomation(m_permissions); ++ return { }; ++} ++ ++Inspector::Protocol::ErrorStringOr WebPageInspectorEmulationAgent::resetPermissions() ++{ ++ m_permissions.clear(); ++ m_page.setPermissionsForAutomation(m_permissions); ++ return { }; ++} ++ ++void WebPageInspectorEmulationAgent::didShowPage() ++{ ++ for (auto& command : m_commandsToRunWhenShown) ++ command(); ++ m_commandsToRunWhenShown.clear(); ++} ++ ++} // namespace WebKit +diff --git a/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.h b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.h +new file mode 100644 +index 0000000000000000000000000000000000000000..1353851472668b3e77c19db54f224c0ca151e9d3 +--- /dev/null ++++ b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.h +@@ -0,0 +1,75 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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. ++ */ ++ ++#pragma once ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++namespace Inspector { ++class BackendDispatcher; ++class FrontendChannel; ++class FrontendRouter; ++} ++ ++namespace WebKit { ++ ++class WebPageProxy; ++ ++class WebPageInspectorEmulationAgent : public Inspector::InspectorAgentBase, public Inspector::EmulationBackendDispatcherHandler { ++ WTF_MAKE_NONCOPYABLE(WebPageInspectorEmulationAgent); ++ WTF_MAKE_FAST_ALLOCATED; ++public: ++ WebPageInspectorEmulationAgent(Inspector::BackendDispatcher& backendDispatcher, WebPageProxy& page); ++ ~WebPageInspectorEmulationAgent() override; ++ ++ void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) override; ++ void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override; ++ ++ void setDeviceMetricsOverride(int width, int height, double deviceScaleFactor, bool fixedlayout, Ref&&) override; ++ Inspector::Protocol::ErrorStringOr setJavaScriptEnabled(bool enabled) override; ++ Inspector::Protocol::ErrorStringOr setAuthCredentials(const String&, const String&) override; ++ Inspector::Protocol::ErrorStringOr setActiveAndFocused(Optional&&) override; ++ Inspector::Protocol::ErrorStringOr grantPermissions(const String& origin, Ref&& permissions) override; ++ Inspector::Protocol::ErrorStringOr resetPermissions() override; ++ ++ void didShowPage(); ++ ++private: ++ void setSize(int width, int height, Ref&& callback); ++ void platformSetSize(int width, int height, Function&&); ++ ++ Ref m_backendDispatcher; ++ WebPageProxy& m_page; ++ Vector> m_commandsToRunWhenShown; ++ HashMap> m_permissions; ++}; ++ ++} // namespace WebKit +diff --git a/Source/WebKit/UIProcess/WebPageInspectorInputAgent.cpp b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..dc52f43a47153513e4ff063ff4edb4d4887104f0 +--- /dev/null ++++ b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.cpp +@@ -0,0 +1,288 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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 "WebPageInspectorInputAgent.h" ++ ++#include "NativeWebKeyboardEvent.h" ++#include "NativeWebMouseEvent.h" ++#include "WebPageProxy.h" ++#include ++#include ++ ++#include "WebPageMessages.h" ++ ++namespace WebKit { ++ ++using namespace Inspector; ++ ++namespace { ++ ++template ++class CallbackList { ++ WTF_MAKE_FAST_ALLOCATED; ++public: ++ ~CallbackList() ++ { ++ for (const auto& callback : m_callbacks) ++ callback->sendFailure("Page closed"); ++ } ++ ++ void append(Ref&& callback) ++ { ++ m_callbacks.append(WTFMove(callback)); ++ } ++ ++ void sendSuccess() ++ { ++ for (const auto& callback : m_callbacks) ++ callback->sendSuccess(); ++ m_callbacks.clear(); ++ } ++ ++private: ++ Vector> m_callbacks; ++}; ++ ++} // namespace ++ ++class WebPageInspectorInputAgent::KeyboardCallbacks : public CallbackList { ++}; ++ ++class WebPageInspectorInputAgent::MouseCallbacks : public CallbackList { ++}; ++ ++WebPageInspectorInputAgent::WebPageInspectorInputAgent(Inspector::BackendDispatcher& backendDispatcher, WebPageProxy& page) ++ : InspectorAgentBase("Input"_s) ++ , m_backendDispatcher(InputBackendDispatcher::create(backendDispatcher, this)) ++ , m_page(page) ++{ ++} ++ ++WebPageInspectorInputAgent::~WebPageInspectorInputAgent() = default; ++ ++void WebPageInspectorInputAgent::didProcessAllPendingKeyboardEvents() ++{ ++ m_keyboardCallbacks->sendSuccess(); ++} ++ ++void WebPageInspectorInputAgent::didProcessAllPendingMouseEvents() ++{ ++ m_page.setInterceptDrags(false); ++ m_mouseCallbacks->sendSuccess(); ++} ++ ++void WebPageInspectorInputAgent::didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) ++{ ++ m_keyboardCallbacks = makeUnique(); ++ m_mouseCallbacks = makeUnique(); ++} ++ ++void WebPageInspectorInputAgent::willDestroyFrontendAndBackend(Inspector::DisconnectReason) ++{ ++ m_keyboardCallbacks = nullptr; ++ m_mouseCallbacks = nullptr; ++} ++ ++static String keyIdentifierForKey(const String& key) ++{ ++ if (key.length() == 1) ++ return makeString("U+", hex(toASCIIUpper(key.characterAt(0)), 4)); ++ if (key == "Delete") ++ return "U+007F"; ++ if (key == "Backspace") ++ return "U+0008"; ++ if (key == "ArrowUp") ++ return "Up"; ++ if (key == "ArrowDown") ++ return "Down"; ++ if (key == "ArrowLeft") ++ return "Left"; ++ if (key == "ArrowRight") ++ return "Right"; ++ if (key == "Tab") ++ return "U+0009"; ++ if (key == "Pause") ++ return "Pause"; ++ if (key == "ScrollLock") ++ return "Scroll"; ++ return key; ++} ++ ++void WebPageInspectorInputAgent::dispatchKeyEvent(const String& type, Optional&& modifiers, const String& text, const String& unmodifiedText, const String& code, const String& key, Optional&& windowsVirtualKeyCode, Optional&& nativeVirtualKeyCode, Optional&& autoRepeat, Optional&& isKeypad, Optional&& isSystemKey, RefPtr&& commands, Ref&& callback) ++{ ++ WebKit::WebEvent::Type eventType; ++ if (type == "keyDown") { ++ eventType = WebKit::WebEvent::KeyDown; ++ } else if (type == "keyUp") { ++ eventType = WebKit::WebEvent::KeyUp; ++ } else { ++ callback->sendFailure("Unsupported event type."); ++ return; ++ } ++ OptionSet eventModifiers; ++ if (modifiers) ++ eventModifiers = eventModifiers.fromRaw(*modifiers); ++ int eventWindowsVirtualKeyCode = 0; ++ if (windowsVirtualKeyCode) ++ eventWindowsVirtualKeyCode = *windowsVirtualKeyCode; ++ int eventNativeVirtualKeyCode = 0; ++ if (nativeVirtualKeyCode) ++ eventNativeVirtualKeyCode = *nativeVirtualKeyCode; ++ Vector eventCommands; ++ if (commands) { ++ for (const auto& value : *commands) { ++ String command; ++ if (!value->asString(command)) { ++ callback->sendFailure("Command must be string"); ++ return; ++ } ++ eventCommands.append(command); ++ } ++ } ++ ++ String keyIdentifier = keyIdentifierForKey(key); ++ ++ bool eventIsAutoRepeat = false; ++ if (autoRepeat) ++ eventIsAutoRepeat = *autoRepeat; ++ bool eventIsKeypad = false; ++ if (isKeypad) ++ eventIsKeypad = *isKeypad; ++ bool eventIsSystemKey = false; ++ if (isSystemKey) ++ eventIsSystemKey = *isSystemKey; ++ WallTime timestamp = WallTime::now(); ++ ++ // cancel any active drag on Escape ++ if (eventType == WebKit::WebEvent::KeyDown && key == "Escape" && m_page.cancelDragIfNeeded()) { ++ callback->sendSuccess(); ++ return; ++ } ++ ++ m_keyboardCallbacks->append(WTFMove(callback)); ++ platformDispatchKeyEvent( ++ eventType, ++ text, ++ unmodifiedText, ++ key, ++ code, ++ keyIdentifier, ++ eventWindowsVirtualKeyCode, ++ eventNativeVirtualKeyCode, ++ eventIsAutoRepeat, ++ eventIsKeypad, ++ eventIsSystemKey, ++ eventModifiers, ++ eventCommands, ++ timestamp); ++} ++ ++void WebPageInspectorInputAgent::dispatchMouseEvent(const String& type, int x, int y, Optional&& modifiers, const String& button, Optional&& buttons, Optional&& clickCount, Optional&& deltaX, Optional&& deltaY, Ref&& callback) ++{ ++ WebEvent::Type eventType = WebEvent::NoType; ++ if (type == "down") ++ eventType = WebEvent::MouseDown; ++ else if (type == "up") ++ eventType = WebEvent::MouseUp; ++ else if (type == "move") ++ eventType = WebEvent::MouseMove; ++ else { ++ callback->sendFailure("Unsupported event type"); ++ return; ++ } ++ ++ OptionSet eventModifiers; ++ if (modifiers) ++ eventModifiers = eventModifiers.fromRaw(*modifiers); ++ ++ WebMouseEvent::Button eventButton = WebMouseEvent::NoButton; ++ if (!!button) { ++ if (button == "left") ++ eventButton = WebMouseEvent::LeftButton; ++ else if (button == "middle") ++ eventButton = WebMouseEvent::MiddleButton; ++ else if (button == "right") ++ eventButton = WebMouseEvent::RightButton; ++ else if (button == "none") ++ eventButton = WebMouseEvent::NoButton; ++ else { ++ callback->sendFailure("Unsupported eventButton"); ++ return; ++ } ++ } ++ ++ unsigned short eventButtons = 0; ++ if (buttons) ++ eventButtons = *buttons; ++ ++ int eventClickCount = 0; ++ if (clickCount) ++ eventClickCount = *clickCount; ++ int eventDeltaX = 0; ++ if (deltaX) ++ eventDeltaX = *deltaX; ++ int eventDeltaY = 0; ++ if (deltaY) ++ eventDeltaY = *deltaY; ++ m_mouseCallbacks->append(WTFMove(callback)); ++ ++ // Convert css coordinates to view coordinates (dip). ++ double totalScale = m_page.pageScaleFactor() * m_page.viewScaleFactor(); ++ x = clampToInteger(roundf(x * totalScale)); ++ y = clampToInteger(roundf(y * totalScale)); ++ eventDeltaX = clampToInteger(roundf(eventDeltaX * totalScale)); ++ eventDeltaY = clampToInteger(roundf(eventDeltaY * totalScale)); ++ ++ // We intercept any drags generated by this mouse event ++ // to prevent them from creating actual drags in the host ++ // operating system. This is turned off in the callback. ++ m_page.setInterceptDrags(true); ++#if PLATFORM(MAC) ++ platformDispatchMouseEvent(type, x, y, WTFMove(modifiers), button, WTFMove(clickCount)); ++#elif PLATFORM(GTK) || PLATFORM(WPE) || PLATFORM(WIN) ++ WallTime timestamp = WallTime::now(); ++ NativeWebMouseEvent event( ++ eventType, ++ eventButton, ++ eventButtons, ++ {x, y}, ++ WebCore::IntPoint(), ++ eventDeltaX, ++ eventDeltaY, ++ 0, ++ eventClickCount, ++ eventModifiers, ++ timestamp); ++ m_page.handleMouseEvent(event); ++#endif ++} ++ ++void WebPageInspectorInputAgent::dispatchTapEvent(int x, int y, Optional&& modifiers, Ref&& callback) { ++ m_page.sendWithAsyncReply(Messages::WebPage::FakeTouchTap(WebCore::IntPoint(x, y), modifiers ? *modifiers : 0), [callback]() { ++ callback->sendSuccess(); ++ }); ++} ++} // namespace WebKit +diff --git a/Source/WebKit/UIProcess/WebPageInspectorInputAgent.h b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.h +new file mode 100644 +index 0000000000000000000000000000000000000000..01b8f65e87b4898b1418f47f4d95c4011c0c180f +--- /dev/null ++++ b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.h +@@ -0,0 +1,85 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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. ++ */ ++ ++#pragma once ++ ++#include "WebEvent.h" ++#include "WebKeyboardEvent.h" ++#include "WebMouseEvent.h" ++#include ++#include ++#include ++#include ++ ++namespace Inspector { ++class BackendDispatcher; ++class FrontendChannel; ++class FrontendRouter; ++} ++ ++namespace WebKit { ++ ++class NativeWebKeyboardEvent; ++class WebPageProxy; ++ ++class WebPageInspectorInputAgent : public Inspector::InspectorAgentBase, public Inspector::InputBackendDispatcherHandler { ++ WTF_MAKE_NONCOPYABLE(WebPageInspectorInputAgent); ++ WTF_MAKE_FAST_ALLOCATED; ++public: ++ WebPageInspectorInputAgent(Inspector::BackendDispatcher& backendDispatcher, WebPageProxy& page); ++ ~WebPageInspectorInputAgent() override; ++ ++ void didProcessAllPendingKeyboardEvents(); ++ void didProcessAllPendingMouseEvents(); ++ ++ void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) override; ++ void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override; ++ ++ // Protocol handler ++ void dispatchKeyEvent(const String& type, Optional&& modifiers, const String& text, const String& unmodifiedText, const String& code, const String& key, Optional&& windowsVirtualKeyCode, Optional&& nativeVirtualKeyCode, Optional&& autoRepeat, Optional&& isKeypad, Optional&& isSystemKey, RefPtr&&, Ref&& callback) override; ++ void dispatchMouseEvent(const String& type, int x, int y, Optional&& modifiers, const String& button, Optional&& buttons, Optional&& clickCount, Optional&& deltaX, Optional&& deltaY, Ref&& callback) override; ++ void dispatchTapEvent(int x, int y, Optional&& modifiers, Ref&& callback) override; ++ ++private: ++ void platformDispatchKeyEvent(WebKeyboardEvent::Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, Vector& commands, WallTime timestamp); ++#if PLATFORM(WPE) ++ void platformDispatchMouseEvent(WebMouseEvent::Type type, int x, int y, WebMouseEvent::Button button, OptionSet modifiers); ++#endif ++#if PLATFORM(MAC) ++ void platformDispatchMouseEvent(const String& type, int x, int y, Optional&& modifier, const String& button, Optional&& clickCount); ++#endif ++ ++ Ref m_backendDispatcher; ++ WebPageProxy& m_page; ++ // Keep track of currently active modifiers across multiple keystrokes. ++ // Most platforms do not track current modifiers from synthesized events. ++ unsigned m_currentModifiers { 0 }; ++ class KeyboardCallbacks; ++ std::unique_ptr m_keyboardCallbacks; ++ class MouseCallbacks; ++ std::unique_ptr m_mouseCallbacks; ++}; ++ ++} // namespace WebKit +diff --git a/Source/WebKit/UIProcess/WebPageProxy.cpp b/Source/WebKit/UIProcess/WebPageProxy.cpp +index f2c53e8ecc35fa0767b823a6ef10311a5f4ef7c6..4b7e41e29ad9a7b0673172c37da08fc6d7f5d1b6 100644 +--- a/Source/WebKit/UIProcess/WebPageProxy.cpp ++++ b/Source/WebKit/UIProcess/WebPageProxy.cpp +@@ -237,7 +237,7 @@ + #include "ViewSnapshotStore.h" + #endif + +-#if PLATFORM(GTK) ++#if PLATFORM(GTK) || PLATFORM(WPE) + #include + #endif + +@@ -617,6 +617,10 @@ WebPageProxy::~WebPageProxy() + + for (auto& callback : m_nextActivityStateChangeCallbacks) + callback(); ++ ++#if PLATFORM(COCOA) ++ releaseInspectorDragPasteboard(); ++#endif + } + + // FIXME: Should return a const PageClient& and add a separate non-const +@@ -993,6 +997,7 @@ void WebPageProxy::finishAttachingToWebProcess(ProcessLaunchReason reason) + m_pageLoadState.didSwapWebProcesses(); + if (reason != ProcessLaunchReason::InitialProcess) + m_drawingArea->waitForBackingStoreUpdateOnNextPaint(); ++ m_inspectorController->didFinishAttachingToWebProcess(); + } + + void WebPageProxy::didAttachToRunningProcess() +@@ -1305,6 +1310,21 @@ WebProcessProxy& WebPageProxy::ensureRunningProcess() + return m_process; + } + ++RefPtr WebPageProxy::loadRequestForInspector(WebCore::ResourceRequest&& request, WebFrameProxy* frame) ++{ ++ if (!frame || frame == mainFrame()) ++ return loadRequest(WTFMove(request), WebCore::ShouldOpenExternalURLsPolicy::ShouldNotAllow); ++ ++ auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(request), m_backForwardList->currentItem()); ++ LoadParameters loadParameters; ++ loadParameters.navigationID = navigation->navigationID(); ++ loadParameters.request = WTFMove(request); ++ loadParameters.shouldOpenExternalURLsPolicy = WebCore::ShouldOpenExternalURLsPolicy::ShouldNotAllow; ++ loadParameters.shouldTreatAsContinuingLoad = false; ++ m_process->send(Messages::WebPage::LoadRequestInFrameForInspector(loadParameters, frame->frameID()), m_webPageID); ++ return navigation; ++} ++ + RefPtr WebPageProxy::loadRequest(ResourceRequest&& request, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, API::Object* userData) + { + if (m_isClosed) +@@ -1822,6 +1842,31 @@ void WebPageProxy::setControlledByAutomation(bool controlled) + websiteDataStore().networkProcess().send(Messages::NetworkProcess::SetSessionIsControlledByAutomation(m_websiteDataStore->sessionID(), m_controlledByAutomation), 0); + } + ++void WebPageProxy::setAuthCredentialsForAutomation(Optional&& credentials) ++{ ++ m_credentialsForAutomation = WTFMove(credentials); ++} ++ ++void WebPageProxy::setPermissionsForAutomation(const HashMap>& permissions) ++{ ++ m_permissionsForAutomation = permissions; ++} ++ ++void WebPageProxy::setActiveForAutomation(Optional active) { ++ m_activeForAutomation = active; ++ OptionSet state; ++ state.add(ActivityState::IsFocused); ++ state.add(ActivityState::WindowIsActive); ++ state.add(ActivityState::IsVisible); ++ state.add(ActivityState::IsVisibleOrOccluded); ++ activityStateDidChange(state); ++} ++ ++void WebPageProxy::logToStderr(const String& str) ++{ ++ fprintf(stderr, "RENDERER: %s\n", str.utf8().data()); ++} ++ + void WebPageProxy::createInspectorTarget(const String& targetId, Inspector::InspectorTargetType type) + { + MESSAGE_CHECK(m_process, !targetId.isEmpty()); +@@ -1969,6 +2014,25 @@ void WebPageProxy::updateActivityState(OptionSet flagsToUpd + { + bool wasVisible = isViewVisible(); + m_activityState.remove(flagsToUpdate); ++ ++ ++ if (m_activeForAutomation) { ++ if (*m_activeForAutomation) { ++ if (flagsToUpdate & ActivityState::IsFocused) ++ m_activityState.add(ActivityState::IsFocused); ++ if (flagsToUpdate & ActivityState::WindowIsActive) ++ m_activityState.add(ActivityState::WindowIsActive); ++ if (flagsToUpdate & ActivityState::IsVisible) ++ m_activityState.add(ActivityState::IsVisible); ++ if (flagsToUpdate & ActivityState::IsVisibleOrOccluded) ++ m_activityState.add(ActivityState::IsVisibleOrOccluded); ++ } ++ flagsToUpdate.remove(ActivityState::IsFocused); ++ flagsToUpdate.remove(ActivityState::WindowIsActive); ++ flagsToUpdate.remove(ActivityState::IsVisible); ++ flagsToUpdate.remove(ActivityState::IsVisibleOrOccluded); ++ } ++ + if (flagsToUpdate & ActivityState::IsFocused && pageClient().isViewFocused()) + m_activityState.add(ActivityState::IsFocused); + if (flagsToUpdate & ActivityState::WindowIsActive && pageClient().isViewWindowActive()) +@@ -2524,6 +2588,8 @@ void WebPageProxy::performDragControllerAction(DragControllerAction action, Drag + { + if (!hasRunningProcess()) + return; ++ if (action == DragControllerAction::Entered || action == DragControllerAction::Updated) ++ m_dragEventsQueued++; + #if PLATFORM(GTK) + UNUSED_PARAM(dragStorageName); + UNUSED_PARAM(sandboxExtensionHandle); +@@ -2534,6 +2600,8 @@ void WebPageProxy::performDragControllerAction(DragControllerAction action, Drag + m_process->assumeReadAccessToBaseURL(*this, url); + + ASSERT(dragData.platformData()); ++#endif ++#if PLATFORM(GTK) || PLATFORM(WPE) + send(Messages::WebPage::PerformDragControllerAction(action, dragData.clientPosition(), dragData.globalPosition(), dragData.draggingSourceOperationMask(), *dragData.platformData(), dragData.flags())); + #else + send(Messages::WebPage::PerformDragControllerAction(action, dragData, sandboxExtensionHandle, sandboxExtensionsForUpload)); +@@ -2549,18 +2617,41 @@ void WebPageProxy::didPerformDragControllerAction(OptionaldidProcessAllPendingMouseEvents(); ++ + } + +-#if PLATFORM(GTK) ++#if PLATFORM(GTK) || PLATFORM(WPE) + void WebPageProxy::startDrag(SelectionData&& selectionData, OptionSet dragOperationMask, const ShareableBitmap::Handle& dragImageHandle) + { +- RefPtr dragImage = !dragImageHandle.isNull() ? ShareableBitmap::create(dragImageHandle) : nullptr; +- pageClient().startDrag(WTFMove(selectionData), dragOperationMask, WTFMove(dragImage)); ++ if (m_interceptDrags) { ++ m_dragSelectionData = WTFMove(selectionData); ++ m_dragSourceOperationMask = dragOperationMask; ++ } else { ++#if PLATFORM(GTK) ++ RefPtr dragImage = !dragImageHandle.isNull() ? ShareableBitmap::create(dragImageHandle) : nullptr; ++ pageClient().startDrag(WTFMove(selectionData), dragOperationMask, WTFMove(dragImage)); ++#endif ++ } ++ ++ didStartDrag(); ++} ++#endif + ++#if PLATFORM(WIN) && ENABLE(DRAG_SUPPORT) ++void WebPageProxy::startDrag(WebCore::DragDataMap& dragDataMap) ++{ ++ if (m_interceptDrags) { ++ m_dragSelectionData = dragDataMap; ++ m_dragSourceOperationMask = WebCore::anyDragOperation(); ++ } + didStartDrag(); + } + #endif + ++ + void WebPageProxy::dragEnded(const IntPoint& clientPosition, const IntPoint& globalPosition, OptionSet dragOperationMask) + { + if (!hasRunningProcess()) +@@ -2569,6 +2660,24 @@ void WebPageProxy::dragEnded(const IntPoint& clientPosition, const IntPoint& glo + setDragCaretRect({ }); + } + ++bool WebPageProxy::cancelDragIfNeeded() { ++ if (!m_dragSelectionData) ++ return false; ++ m_dragSelectionData = WTF::nullopt; ++#if PLATFORM(COCOA) ++ releaseInspectorDragPasteboard(); ++#endif ++ ++ dragEnded(m_lastMousePositionForDrag, IntPoint(), m_dragSourceOperationMask); ++ return true; ++} ++ ++#if !PLATFORM(COCOA) ++void WebPageProxy::setInterceptDrags(bool shouldIntercept) { ++ m_interceptDrags = shouldIntercept; ++} ++#endif ++ + void WebPageProxy::didPerformDragOperation(bool handled) + { + pageClient().didPerformDragOperation(handled); +@@ -2581,8 +2690,18 @@ void WebPageProxy::didStartDrag() + + discardQueuedMouseEvents(); + send(Messages::WebPage::DidStartDrag()); ++ ++ if (m_interceptDrags) { ++#if PLATFORM(WIN) || PLATFORM(COCOA) ++ DragData dragData(*m_dragSelectionData, m_lastMousePositionForDrag, WebCore::IntPoint(), m_dragSourceOperationMask); ++#else ++ DragData dragData(&*m_dragSelectionData, m_lastMousePositionForDrag, WebCore::IntPoint(), m_dragSourceOperationMask); ++#endif ++ dragEntered(dragData); ++ dragUpdated(dragData); ++ } + } +- ++ + void WebPageProxy::dragCancelled() + { + if (hasRunningProcess()) +@@ -2687,16 +2806,38 @@ void WebPageProxy::processNextQueuedMouseEvent() + m_process->startResponsivenessTimer(); + } + +- Optional sandboxExtensions; ++ m_lastMousePositionForDrag = event.position(); ++ if (!m_dragSelectionData) { ++ Optional sandboxExtensions; + + #if PLATFORM(MAC) +- bool eventMayStartDrag = !m_currentDragOperation && eventType == WebEvent::MouseMove && event.button() != WebMouseEvent::Button::NoButton; +- if (eventMayStartDrag) +- sandboxExtensions = SandboxExtension::createHandlesForMachLookup({ "com.apple.iconservices"_s, "com.apple.iconservices.store"_s }, WTF::nullopt); ++ bool eventMayStartDrag = !m_currentDragOperation && eventType == WebEvent::MouseMove && event.button() != WebMouseEvent::Button::NoButton; ++ if (eventMayStartDrag) ++ sandboxExtensions = SandboxExtension::createHandlesForMachLookup({ "com.apple.iconservices"_s, "com.apple.iconservices.store"_s }, WTF::nullopt); + #endif +- +- LOG(MouseHandling, "UIProcess: sent mouse event %s (queue size %zu)", webMouseEventTypeString(eventType), m_mouseEventQueue.size()); +- send(Messages::WebPage::MouseEvent(event, sandboxExtensions)); ++ ++ LOG(MouseHandling, "UIProcess: sent mouse event %s (queue size %zu)", webMouseEventTypeString(eventType), m_mouseEventQueue.size()); ++ send(Messages::WebPage::MouseEvent(event, sandboxExtensions)); ++ } else { ++#if PLATFORM(WIN) || PLATFORM(COCOA) ++ DragData dragData(*m_dragSelectionData, event.position(), event.globalPosition(), m_dragSourceOperationMask); ++#else ++ DragData dragData(&*m_dragSelectionData, event.position(), event.globalPosition(), m_dragSourceOperationMask); ++#endif ++ if (eventType == WebEvent::MouseMove) { ++ dragUpdated(dragData); ++ } else if (eventType == WebEvent::MouseUp) { ++ if (m_currentDragOperation && m_dragSourceOperationMask.containsAny(m_currentDragOperation.value())) { ++ SandboxExtension::Handle sandboxExtensionHandle; ++ SandboxExtension::HandleArray sandboxExtensionsForUpload; ++ ++ performDragOperation(dragData, "", WTFMove(sandboxExtensionHandle), WTFMove(sandboxExtensionsForUpload)); ++ } ++ m_dragSelectionData = WTF::nullopt; ++ dragEnded(event.position(), event.globalPosition(), m_dragSourceOperationMask); ++ } ++ didReceiveEvent(eventType, true); ++ } + } + + void WebPageProxy::doAfterProcessingAllPendingMouseEvents(WTF::Function&& action) +@@ -2877,7 +3018,7 @@ static TrackingType mergeTrackingTypes(TrackingType a, TrackingType b) + + void WebPageProxy::updateTouchEventTracking(const WebTouchEvent& touchStartEvent) + { +-#if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA) ++#if ENABLE(ASYNC_SCROLLING) && PLATFORM(IOS_FAMILY) + const EventNames& names = eventNames(); + for (auto& touchPoint : touchStartEvent.touchPoints()) { + IntPoint location = touchPoint.location(); +@@ -2910,7 +3051,7 @@ void WebPageProxy::updateTouchEventTracking(const WebTouchEvent& touchStartEvent + m_touchAndPointerEventTracking.touchStartTracking = TrackingType::Synchronous; + m_touchAndPointerEventTracking.touchMoveTracking = TrackingType::Synchronous; + m_touchAndPointerEventTracking.touchEndTracking = TrackingType::Synchronous; +-#endif // ENABLE(ASYNC_SCROLLING) ++#endif // ENABLE(ASYNC_SCROLLING) && PLATFORM(IOS_FAMILY) + } + + TrackingType WebPageProxy::touchEventTrackingType(const WebTouchEvent& touchStartEvent) const +@@ -3345,6 +3486,7 @@ void WebPageProxy::receivedNavigationPolicyDecision(PolicyAction policyAction, A + + void WebPageProxy::receivedPolicyDecision(PolicyAction action, API::Navigation* navigation, RefPtr&& websitePolicies, Variant, Ref>&& navigationActionOrResponse, Ref&& sender, Optional sandboxExtensionHandle, WillContinueLoadInNewProcess willContinueLoadInNewProcess) + { ++ m_inspectorController->didReceivePolicyDecision(action, navigation ? navigation->navigationID() : 0); + if (!hasRunningProcess()) { + sender->send(PolicyDecision { sender->identifier(), isNavigatingToAppBoundDomain(), PolicyAction::Ignore, 0, WTF::nullopt, WTF::nullopt }); + return; +@@ -4054,6 +4196,11 @@ void WebPageProxy::pageScaleFactorDidChange(double scaleFactor) + m_pageScaleFactor = scaleFactor; + } + ++void WebPageProxy::viewScaleFactorDidChange(double scaleFactor) ++{ ++ m_viewScaleFactor = scaleFactor; ++} ++ + void WebPageProxy::pluginScaleFactorDidChange(double pluginScaleFactor) + { + m_pluginScaleFactor = pluginScaleFactor; +@@ -4385,6 +4532,7 @@ void WebPageProxy::didDestroyNavigation(uint64_t navigationID) + + // FIXME: Message check the navigationID. + m_navigationState->didDestroyNavigation(navigationID); ++ m_inspectorController->didDestroyNavigation(navigationID); + } + + void WebPageProxy::didStartProvisionalLoadForFrame(FrameIdentifier frameID, FrameInfoData&& frameInfo, ResourceRequest&& request, uint64_t navigationID, URL&& url, URL&& unreachableURL, const UserData& userData) +@@ -4607,6 +4755,8 @@ void WebPageProxy::didFailProvisionalLoadForFrameShared(Ref&& p + + m_failingProvisionalLoadURL = { }; + ++ m_inspectorController->didFailProvisionalLoadForFrame(navigationID, error); ++ + // If the provisional page's load fails then we destroy the provisional page. + if (m_provisionalPage && m_provisionalPage->mainFrame() == frame && willContinueLoading == WillContinueLoading::No) + m_provisionalPage = nullptr; +@@ -5044,7 +5194,14 @@ void WebPageProxy::decidePolicyForNavigationActionAsync(FrameIdentifier frameID, + NavigationActionData&& navigationActionData, FrameInfoData&& originatingFrameInfo, Optional originatingPageID, const WebCore::ResourceRequest& originalRequest, WebCore::ResourceRequest&& request, + IPC::FormDataReference&& requestBody, WebCore::ResourceResponse&& redirectResponse, const UserData& userData, uint64_t listenerID) + { +- decidePolicyForNavigationActionAsyncShared(m_process.copyRef(), m_webPageID, frameID, WTFMove(frameInfo), identifier, navigationID, WTFMove(navigationActionData), WTFMove(originatingFrameInfo), originatingPageID, originalRequest, WTFMove(request), WTFMove(requestBody), WTFMove(redirectResponse), userData, listenerID); ++ if (m_inspectorController->shouldPauseLoading()) { ++ m_inspectorController->setContinueLoadingCallback([this, protectedThis = makeRef(*this), frameID, frameInfo = WTFMove(frameInfo), identifier, navigationID, navigationActionData = WTFMove(navigationActionData), ++ originatingFrameInfo = WTFMove(originatingFrameInfo), originatingPageID, originalRequest, request = WTFMove(request), requestBody = WTFMove(requestBody), redirectResponse = WTFMove(redirectResponse), userData, listenerID] () mutable { ++ decidePolicyForNavigationActionAsyncShared(m_process.copyRef(), m_webPageID, frameID, WTFMove(frameInfo), identifier, navigationID, WTFMove(navigationActionData), WTFMove(originatingFrameInfo), originatingPageID, originalRequest, WTFMove(request), WTFMove(requestBody), WTFMove(redirectResponse), userData, listenerID); ++ }); ++ } else { ++ decidePolicyForNavigationActionAsyncShared(m_process.copyRef(), m_webPageID, frameID, WTFMove(frameInfo), identifier, navigationID, WTFMove(navigationActionData), WTFMove(originatingFrameInfo), originatingPageID, originalRequest, WTFMove(request), WTFMove(requestBody), WTFMove(redirectResponse), userData, listenerID); ++ } + } + + void WebPageProxy::decidePolicyForNavigationActionAsyncShared(Ref&& process, PageIdentifier webPageID, FrameIdentifier frameID, FrameInfoData&& frameInfo, +@@ -5558,6 +5715,7 @@ void WebPageProxy::createNewPage(FrameInfoData&& originatingFrameInfoData, WebPa + auto* originatingPage = m_process->webPage(originatingPageID); + auto originatingFrameInfo = API::FrameInfo::create(WTFMove(originatingFrameInfoData), originatingPage); + auto mainFrameURL = m_mainFrame ? m_mainFrame->url() : URL(); ++ m_inspectorController->willCreateNewPage(windowFeatures, request.url()); + auto completionHandler = [this, protectedThis = makeRef(*this), mainFrameURL, request, reply = WTFMove(reply), privateClickMeasurement = navigationActionData.privateClickMeasurement] (RefPtr newPage) mutable { + if (!newPage) { + reply(WTF::nullopt, WTF::nullopt); +@@ -5598,6 +5756,7 @@ void WebPageProxy::createNewPage(FrameInfoData&& originatingFrameInfoData, WebPa + void WebPageProxy::showPage() + { + m_uiClient->showPage(this); ++ m_inspectorController->didShowPage(); + } + + void WebPageProxy::exitFullscreenImmediately() +@@ -5633,6 +5792,10 @@ void WebPageProxy::closePage() + if (isClosed()) + return; + ++#if ENABLE(CONTEXT_MENUS) ++ if (m_activeContextMenu) ++ m_activeContextMenu->hide(); ++#endif + RELEASE_LOG_IF_ALLOWED(Process, "closePage:"); + pageClient().clearAllEditCommands(); + m_uiClient->close(this); +@@ -5658,6 +5821,8 @@ void WebPageProxy::runJavaScriptAlert(FrameIdentifier frameID, FrameInfoData&& f + // on top of the view in this case. + makeViewBlankIfUnpaintedSinceLastLoadCommit(); + ++ if (m_inspectorDialogAgent) ++ m_inspectorDialogAgent->javascriptDialogOpening("alert"_s, message); + m_uiClient->runJavaScriptAlert(*this, message, frame, WTFMove(frameInfo), WTFMove(reply)); + } + +@@ -5675,6 +5840,8 @@ void WebPageProxy::runJavaScriptConfirm(FrameIdentifier frameID, FrameInfoData&& + if (auto* automationSession = process().processPool().automationSession()) + automationSession->willShowJavaScriptDialog(*this); + } ++ if (m_inspectorDialogAgent) ++ m_inspectorDialogAgent->javascriptDialogOpening("confirm"_s, message); + + // If we have not painted yet since the last load commit, then we are likely still displaying the previous page. + // Displaying a JS prompt for the new page with the old page behind would be confusing so we add a blank overlay +@@ -5698,6 +5865,8 @@ void WebPageProxy::runJavaScriptPrompt(FrameIdentifier frameID, FrameInfoData&& + if (auto* automationSession = process().processPool().automationSession()) + automationSession->willShowJavaScriptDialog(*this); + } ++ if (m_inspectorDialogAgent) ++ m_inspectorDialogAgent->javascriptDialogOpening("prompt"_s, message, defaultValue); + + // If we have not painted yet since the last load commit, then we are likely still displaying the previous page. + // Displaying a JS prompt for the new page with the old page behind would be confusing so we add a blank overlay +@@ -5858,6 +6027,8 @@ void WebPageProxy::runBeforeUnloadConfirmPanel(FrameIdentifier frameID, FrameInf + return; + } + } ++ if (m_inspectorDialogAgent) ++ m_inspectorDialogAgent->javascriptDialogOpening("beforeunload"_s, message); + + // Since runBeforeUnloadConfirmPanel() can spin a nested run loop we need to turn off the responsiveness timer and the tryClose timer. + m_process->stopResponsivenessTimer(); +@@ -7060,6 +7231,8 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled) + if (auto* automationSession = process().processPool().automationSession()) + automationSession->mouseEventsFlushedForPage(*this); + didFinishProcessingAllPendingMouseEvents(); ++ if (m_dragEventsQueued == 0) ++ m_inspectorController->didProcessAllPendingMouseEvents(); + } + break; + } +@@ -7086,7 +7259,6 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled) + case WebEvent::RawKeyDown: + case WebEvent::Char: { + LOG(KeyHandling, "WebPageProxy::didReceiveEvent: %s (queue empty %d)", webKeyboardEventTypeString(type), m_keyEventQueue.isEmpty()); +- + MESSAGE_CHECK(m_process, !m_keyEventQueue.isEmpty()); + auto event = m_keyEventQueue.takeFirst(); + MESSAGE_CHECK(m_process, type == event.type()); +@@ -7105,7 +7277,6 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled) + // The call to doneWithKeyEvent may close this WebPage. + // Protect against this being destroyed. + Ref protect(*this); +- + pageClient().doneWithKeyEvent(event, handled); + if (!handled) + m_uiClient->didNotHandleKeyEvent(this, event); +@@ -7114,6 +7285,7 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled) + if (!canProcessMoreKeyEvents) { + if (auto* automationSession = process().processPool().automationSession()) + automationSession->keyboardEventsFlushedForPage(*this); ++ m_inspectorController->didProcessAllPendingKeyboardEvents(); + } + break; + } +@@ -7386,7 +7558,10 @@ void WebPageProxy::dispatchProcessDidTerminate(ProcessTerminationReason reason) + { + RELEASE_LOG_ERROR_IF_ALLOWED(Loading, "dispatchProcessDidTerminate: reason=%d", reason); + +- bool handledByClient = false; ++ bool handledByClient = m_inspectorController->pageCrashed(reason); ++ if (handledByClient) ++ return; ++ + if (m_loaderClient) + handledByClient = reason != ProcessTerminationReason::RequestedByClient && m_loaderClient->processDidCrash(*this); + else +@@ -7783,6 +7958,7 @@ static bool disableStaticFontRegistry() + + WebPageCreationParameters WebPageProxy::creationParameters(WebProcessProxy& process, DrawingAreaProxy& drawingArea, RefPtr&& websitePolicies) + { ++ + WebPageCreationParameters parameters; + + parameters.processDisplayName = configuration().processDisplayName(); +@@ -7967,6 +8143,8 @@ WebPageCreationParameters WebPageProxy::creationParameters(WebProcessProxy& proc + parameters.shouldRelaxThirdPartyCookieBlocking = m_configuration->shouldRelaxThirdPartyCookieBlocking(); + parameters.canUseCredentialStorage = m_canUseCredentialStorage; + ++ parameters.shouldPauseInInspectorWhenShown = m_inspectorController->shouldPauseLoading(); ++ + #if PLATFORM(GTK) + parameters.themeName = pageClient().themeName(); + #endif +@@ -8043,6 +8221,14 @@ void WebPageProxy::gamepadActivity(const Vector& gamepadDatas, Even + + void WebPageProxy::didReceiveAuthenticationChallengeProxy(Ref&& authenticationChallenge, NegotiatedLegacyTLS negotiatedLegacyTLS) + { ++ if (m_credentialsForAutomation.hasValue()) { ++ if (m_credentialsForAutomation->isEmpty() || authenticationChallenge->core().previousFailureCount()) { ++ authenticationChallenge->listener().completeChallenge(AuthenticationChallengeDisposition::PerformDefaultHandling); ++ return; ++ } ++ authenticationChallenge->listener().completeChallenge(AuthenticationChallengeDisposition::UseCredential, *m_credentialsForAutomation); ++ return; ++ } + if (negotiatedLegacyTLS == NegotiatedLegacyTLS::Yes) { + m_navigationClient->shouldAllowLegacyTLS(*this, authenticationChallenge.get(), [this, protectedThis = makeRef(*this), authenticationChallenge] (bool shouldAllowLegacyTLS) { + if (shouldAllowLegacyTLS) +@@ -8128,7 +8314,8 @@ void WebPageProxy::requestGeolocationPermissionForFrame(GeolocationIdentifier ge + MESSAGE_CHECK(m_process, frame); + + // FIXME: Geolocation should probably be using toString() as its string representation instead of databaseIdentifier(). +- auto origin = API::SecurityOrigin::create(frameInfo.securityOrigin.securityOrigin()); ++ auto securityOrigin = frameInfo.securityOrigin.securityOrigin(); ++ auto origin = API::SecurityOrigin::create(securityOrigin); + auto request = m_geolocationPermissionRequestManager.createRequest(geolocationID); + Function completionHandler = [request = WTFMove(request)](bool allowed) { + if (allowed) +@@ -8137,6 +8324,14 @@ void WebPageProxy::requestGeolocationPermissionForFrame(GeolocationIdentifier ge + request->deny(); + }; + ++ auto permissions = m_permissionsForAutomation.find(securityOrigin->toString()); ++ if (permissions == m_permissionsForAutomation.end()) ++ permissions = m_permissionsForAutomation.find("*"); ++ if (permissions != m_permissionsForAutomation.end()) { ++ completionHandler(permissions->value.contains("geolocation")); ++ return; ++ } ++ + // FIXME: Once iOS migrates to the new WKUIDelegate SPI, clean this up + // and make it one UIClient call that calls the completionHandler with false + // if there is no delegate instead of returning the completionHandler +diff --git a/Source/WebKit/UIProcess/WebPageProxy.h b/Source/WebKit/UIProcess/WebPageProxy.h +index 02cb990922b857cfa3d1f6798b78feb08c7d4f23..2b6c75c2c41069d946d62eaaeb43c0d3b55fb5ad 100644 +--- a/Source/WebKit/UIProcess/WebPageProxy.h ++++ b/Source/WebKit/UIProcess/WebPageProxy.h +@@ -38,6 +38,7 @@ + #include "GeolocationIdentifier.h" + #include "GeolocationPermissionRequestManagerProxy.h" + #include "HiddenPageThrottlingAutoIncreasesCounter.h" ++#include "InspectorDialogAgent.h" + #include "LayerTreeContext.h" + #include "MediaKeySystemPermissionRequestManagerProxy.h" + #include "MediaPlaybackState.h" +@@ -141,9 +142,11 @@ + OBJC_CLASS NSTextAlternatives; + OBJC_CLASS NSView; + OBJC_CLASS _WKRemoteObjectRegistry; ++OBJC_CLASS NSPasteboard; + + #if ENABLE(DRAG_SUPPORT) + #include ++#include + #endif + + #if ENABLE(TOUCH_EVENTS) +@@ -164,6 +167,14 @@ OBJC_CLASS _WKRemoteObjectRegistry; + #include "ArgumentCodersGtk.h" + #endif + ++#if PLATFORM(WPE) ++#include "ArgumentCodersWPE.h" ++#endif ++ ++#if PLATFORM(GTK) || PLATFORM(WPE) ++#include ++#endif ++ + #if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS_FAMILY) + #include + #include +@@ -226,6 +237,7 @@ class AuthenticationChallenge; + class CertificateInfo; + class Cursor; + class DragData; ++typedef HashMap> DragDataMap; + class FloatRect; + class FontAttributeChanges; + class FontChanges; +@@ -233,7 +245,6 @@ class GraphicsLayer; + class IntSize; + class ProtectionSpace; + class RunLoopObserver; +-class SelectionData; + class SharedBuffer; + class SpeechRecognitionRequest; + class TextIndicator; +@@ -500,6 +511,8 @@ public: + void setControlledByAutomation(bool); + + WebPageInspectorController& inspectorController() { return *m_inspectorController; } ++ InspectorDialogAgent* inspectorDialogAgent() { return m_inspectorDialogAgent; } ++ void setInspectorDialogAgent(InspectorDialogAgent * dialogAgent) { m_inspectorDialogAgent = dialogAgent; } + + #if PLATFORM(IOS_FAMILY) + void showInspectorIndication(); +@@ -571,6 +584,11 @@ public: + + void setPageLoadStateObserver(std::unique_ptr&&); + ++ void setAuthCredentialsForAutomation(Optional&&); ++ void setPermissionsForAutomation(const HashMap>&); ++ void setActiveForAutomation(Optional active); ++ void logToStderr(const String& str); ++ + void initializeWebPage(); + void setDrawingArea(std::unique_ptr&&); + +@@ -596,6 +614,7 @@ public: + void closePage(); + + void addPlatformLoadParameters(WebProcessProxy&, LoadParameters&); ++ RefPtr loadRequestForInspector(WebCore::ResourceRequest&&, WebFrameProxy*); + RefPtr loadRequest(WebCore::ResourceRequest&&, WebCore::ShouldOpenExternalURLsPolicy = WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemesButNotAppLinks, API::Object* userData = nullptr); + RefPtr loadFile(const String& fileURL, const String& resourceDirectoryURL, API::Object* userData = nullptr); + RefPtr loadData(const IPC::DataReference&, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData = nullptr, WebCore::ShouldOpenExternalURLsPolicy = WebCore::ShouldOpenExternalURLsPolicy::ShouldNotAllow); +@@ -1108,6 +1127,7 @@ public: + #endif + + void pageScaleFactorDidChange(double); ++ void viewScaleFactorDidChange(double); + void pluginScaleFactorDidChange(double); + void pluginZoomFactorDidChange(double); + +@@ -1182,14 +1202,20 @@ public: + void didStartDrag(); + void dragCancelled(); + void setDragCaretRect(const WebCore::IntRect&); ++ void setInterceptDrags(bool shouldIntercept); ++ bool cancelDragIfNeeded(); + #if PLATFORM(COCOA) + void startDrag(const WebCore::DragItem&, const ShareableBitmap::Handle& dragImageHandle); + void setPromisedDataForImage(const String& pasteboardName, const SharedMemory::IPCHandle& imageHandle, const String& filename, const String& extension, + const String& title, const String& url, const String& visibleURL, const SharedMemory::IPCHandle& archiveHandle, const String& originIdentifier); ++ void releaseInspectorDragPasteboard(); + #endif +-#if PLATFORM(GTK) ++#if PLATFORM(GTK) || PLATFORM(WPE) + void startDrag(WebCore::SelectionData&&, OptionSet, const ShareableBitmap::Handle& dragImage); + #endif ++#if PLATFORM(WIN) ++ void startDrag(WebCore::DragDataMap& dragDataMap); ++#endif + #endif + + void processDidBecomeUnresponsive(); +@@ -1428,6 +1454,8 @@ public: + + #if PLATFORM(COCOA) || PLATFORM(GTK) + RefPtr takeViewSnapshot(Optional&&); ++#elif PLATFORM(WPE) ++ RefPtr takeViewSnapshot(Optional&&) { return nullptr; } + #endif + + #if ENABLE(WEB_CRYPTO) +@@ -2462,6 +2490,7 @@ private: + String m_overrideContentSecurityPolicy; + + RefPtr m_inspector; ++ InspectorDialogAgent* m_inspectorDialogAgent { nullptr }; + + #if ENABLE(FULLSCREEN_API) + std::unique_ptr m_fullScreenManager; +@@ -2700,6 +2729,20 @@ private: + unsigned m_currentDragNumberOfFilesToBeAccepted { 0 }; + WebCore::IntRect m_currentDragCaretRect; + WebCore::IntRect m_currentDragCaretEditableElementRect; ++ bool m_interceptDrags { false }; ++ OptionSet m_dragSourceOperationMask; ++ WebCore::IntPoint m_lastMousePositionForDrag; ++ int m_dragEventsQueued = 0; ++#if PLATFORM(COCOA) ++ Optional m_dragSelectionData; ++ String m_overrideDragPasteboardName; ++#endif ++#if PLATFORM(GTK) || PLATFORM(WPE) ++ Optional m_dragSelectionData; ++#endif ++#if PLATFORM(WIN) ++ Optional m_dragSelectionData; ++#endif + #endif + + PageLoadState m_pageLoadState; +@@ -2905,6 +2948,9 @@ private: + RefPtr messageBody; + }; + Vector m_pendingInjectedBundleMessages; ++ Optional m_credentialsForAutomation; ++ HashMap> m_permissionsForAutomation; ++ Optional m_activeForAutomation; + + #if PLATFORM(IOS_FAMILY) && ENABLE(DEVICE_ORIENTATION) + std::unique_ptr m_webDeviceOrientationUpdateProviderProxy; +diff --git a/Source/WebKit/UIProcess/WebPageProxy.messages.in b/Source/WebKit/UIProcess/WebPageProxy.messages.in +index 873176d95916ff048c0b52255bde98fa9031fd57..71b5b330bd1b28e9ab24e41d7be5c0cf10bb3074 100644 +--- a/Source/WebKit/UIProcess/WebPageProxy.messages.in ++++ b/Source/WebKit/UIProcess/WebPageProxy.messages.in +@@ -29,6 +29,7 @@ messages -> WebPageProxy { + RunJavaScriptConfirm(WebCore::FrameIdentifier frameID, struct WebKit::FrameInfoData frameInfo, String message) -> (bool result) Synchronous + RunJavaScriptPrompt(WebCore::FrameIdentifier frameID, struct WebKit::FrameInfoData frameInfo, String message, String defaultValue) -> (String result) Synchronous + MouseDidMoveOverElement(struct WebKit::WebHitTestResultData hitTestResultData, uint32_t modifiers, WebKit::UserData userData) ++ LogToStderr(String text) + + #if ENABLE(NETSCAPE_PLUGIN_API) + UnavailablePluginButtonClicked(uint32_t pluginUnavailabilityReason, String mimeType, String pluginURLString, String pluginspageAttributeURLString, String frameURLString, String pageURLString) +@@ -178,6 +179,7 @@ messages -> WebPageProxy { + #endif + + PageScaleFactorDidChange(double scaleFactor) ++ ViewScaleFactorDidChange(double scaleFactor) + PluginScaleFactorDidChange(double zoomFactor) + PluginZoomFactorDidChange(double zoomFactor) + +@@ -303,10 +305,12 @@ messages -> WebPageProxy { + StartDrag(struct WebCore::DragItem dragItem, WebKit::ShareableBitmap::Handle dragImage) + SetPromisedDataForImage(String pasteboardName, WebKit::SharedMemory::IPCHandle imageHandle, String filename, String extension, String title, String url, String visibleURL, WebKit::SharedMemory::IPCHandle archiveHandle, String originIdentifier) + #endif +-#if PLATFORM(GTK) && ENABLE(DRAG_SUPPORT) ++#if (PLATFORM(GTK) || PLATFORM(WPE)) && ENABLE(DRAG_SUPPORT) + StartDrag(WebCore::SelectionData selectionData, OptionSet dragOperationMask, WebKit::ShareableBitmap::Handle dragImage) + #endif +- ++#if PLATFORM(WIN) && ENABLE(DRAG_SUPPORT) ++ StartDrag(HashMap> dragDataMap) ++#endif + #if ENABLE(DRAG_SUPPORT) + DidPerformDragOperation(bool handled) + #endif +diff --git a/Source/WebKit/UIProcess/WebProcessPool.cpp b/Source/WebKit/UIProcess/WebProcessPool.cpp +index 27a2ff96bb7cedff80a6208b39b9d058a6cc3ba7..6a2bdeb8ff495a7634c4dad6c3785c6f2db06f6a 100644 +--- a/Source/WebKit/UIProcess/WebProcessPool.cpp ++++ b/Source/WebKit/UIProcess/WebProcessPool.cpp +@@ -553,6 +553,14 @@ void WebProcessPool::establishWorkerContextConnectionToNetworkProcess(NetworkPro + + // Arbitrarily choose the first process pool to host the service worker process. + auto* processPool = processPools()[0]; ++ // Playwright begin ++ for (auto& process : websiteDataStore->processes()) { ++ if (process.processPoolIfExists()) { ++ processPool = process.processPoolIfExists(); ++ break; ++ } ++ } ++ // Playwright end + ASSERT(processPool); + + WebProcessProxy* serviceWorkerProcessProxy { nullptr }; +@@ -792,7 +800,10 @@ void WebProcessPool::initializeNewWebProcess(WebProcessProxy& process, WebsiteDa + #endif + + parameters.cacheModel = LegacyGlobalSettings::singleton().cacheModel(); +- parameters.overrideLanguages = configuration().overrideLanguages(); ++ if (websiteDataStore && websiteDataStore->languagesForAutomation().size()) ++ parameters.overrideLanguages = websiteDataStore->languagesForAutomation(); ++ else ++ parameters.overrideLanguages = configuration().overrideLanguages(); + + parameters.urlSchemesRegisteredAsEmptyDocument = copyToVector(m_schemesToRegisterAsEmptyDocument); + parameters.urlSchemesRegisteredAsSecure = copyToVector(LegacyGlobalSettings::singleton().schemesToRegisterAsSecure()); +diff --git a/Source/WebKit/UIProcess/WebProcessProxy.cpp b/Source/WebKit/UIProcess/WebProcessProxy.cpp +index 89282ad83efa06ac6c672472b27226ac0171aae0..7dd01b249d722370543c3c71e74a65e8c27b7cea 100644 +--- a/Source/WebKit/UIProcess/WebProcessProxy.cpp ++++ b/Source/WebKit/UIProcess/WebProcessProxy.cpp +@@ -122,6 +122,11 @@ HashMap& WebProcessProxy::allProcesses() + return map; + } + ++Vector WebProcessProxy::allProcessesForInspector() ++{ ++ return copyToVector(allProcesses().values()); ++} ++ + WebProcessProxy* WebProcessProxy::processForIdentifier(ProcessIdentifier identifier) + { + return allProcesses().get(identifier); +diff --git a/Source/WebKit/UIProcess/WebProcessProxy.h b/Source/WebKit/UIProcess/WebProcessProxy.h +index 5dac831c2ed26710c5708e8d4407a94cba466607..df88cdb910981c596c166e57540b24cad9cd47ac 100644 +--- a/Source/WebKit/UIProcess/WebProcessProxy.h ++++ b/Source/WebKit/UIProcess/WebProcessProxy.h +@@ -139,6 +139,7 @@ public: + ~WebProcessProxy(); + + static void forWebPagesWithOrigin(PAL::SessionID, const WebCore::SecurityOriginData&, const Function&); ++ static Vector allProcessesForInspector(); + + WebConnection* webConnection() const { return m_webConnection.get(); } + +diff --git a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp +index 8269e7f8dfffbbbfbae5e997ddaf4bac69ef1431..ff9f2bf60742e85b2767f063f483df1816817bb4 100644 +--- a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp ++++ b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp +@@ -2313,6 +2313,17 @@ void WebsiteDataStore::renameOriginInWebsiteData(URL&& oldName, URL&& newName, O + networkProcess().renameOriginInWebsiteData(m_sessionID, oldName, newName, dataTypes, WTFMove(completionHandler)); + } + ++void WebsiteDataStore::setLanguagesForAutomation(Vector&& languages) ++{ ++ m_languagesForAutomation = WTFMove(languages); ++} ++ ++void WebsiteDataStore::setDownloadForAutomation(Optional allow, const String& downloadPath) ++{ ++ m_allowDownloadForAutomation = allow; ++ m_downloadPathForAutomation = downloadPath; ++} ++ + #if ENABLE(APP_BOUND_DOMAINS) + void WebsiteDataStore::hasAppBoundSession(CompletionHandler&& completionHandler) const + { +diff --git a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h +index 5a7f577c4ae4088e52d472af5e890368dc5784fe..e9dae95384616f0ca31228e714717a99642752a0 100644 +--- a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h ++++ b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h +@@ -92,6 +92,7 @@ enum class CacheModel : uint8_t; + enum class WebsiteDataFetchOption : uint8_t; + enum class WebsiteDataType : uint32_t; + ++struct FrameInfoData; + struct NetworkProcessConnectionInfo; + struct WebsiteDataRecord; + struct WebsiteDataStoreParameters; +@@ -106,6 +107,16 @@ enum class StorageAccessPromptStatus; + struct PluginModuleInfo; + #endif + ++class WebsiteDataStore; ++ ++class DownloadInstrumentation { ++public: ++ virtual void downloadCreated(const String& uuid, const WebCore::ResourceRequest&, const FrameInfoData& frameInfoData, WebPageProxy* page) = 0; ++ virtual void downloadFilenameSuggested(const String& uuid, const String& suggestedFilename) = 0; ++ virtual void downloadFinished(const String& uuid, const String& error) = 0; ++ virtual ~DownloadInstrumentation() = default; ++}; ++ + class WebsiteDataStore : public API::ObjectImpl, public Identified, public CanMakeWeakPtr { + public: + static Ref defaultDataStore(); +@@ -278,11 +289,13 @@ public: + const WebCore::CurlProxySettings& networkProxySettings() const { return m_proxySettings; } + #endif + +-#if USE(SOUP) ++#if USE(SOUP) || PLATFORM(COCOA) || PLATFORM(WIN) + void setPersistentCredentialStorageEnabled(bool); + bool persistentCredentialStorageEnabled() const { return m_persistentCredentialStorageEnabled && isPersistent(); } + void setIgnoreTLSErrors(bool); + bool ignoreTLSErrors() const { return m_ignoreTLSErrors; } ++#endif ++#if USE(SOUP) + void setNetworkProxySettings(WebCore::SoupNetworkProxySettings&&); + const WebCore::SoupNetworkProxySettings& networkProxySettings() const { return m_networkProxySettings; } + #endif +@@ -335,6 +348,14 @@ public: + static WTF::String defaultJavaScriptConfigurationDirectory(); + static bool http3Enabled(); + ++ void setLanguagesForAutomation(Vector&&); ++ Vector& languagesForAutomation() { return m_languagesForAutomation; }; ++ void setDownloadForAutomation(Optional allow, const String& downloadPath); ++ Optional allowDownloadForAutomation() { return m_allowDownloadForAutomation; }; ++ String downloadPathForAutomation() { return m_downloadPathForAutomation; }; ++ void setDownloadInstrumentation(DownloadInstrumentation* instrumentation) { m_downloadInstrumentation = instrumentation; }; ++ DownloadInstrumentation* downloadInstrumentation() { return m_downloadInstrumentation; }; ++ + void resetQuota(CompletionHandler&&); + + #if ENABLE(APP_BOUND_DOMAINS) +@@ -419,9 +440,11 @@ private: + WebCore::CurlProxySettings m_proxySettings; + #endif + +-#if USE(SOUP) ++#if USE(SOUP) || PLATFORM(COCOA) || PLATFORM(WIN) + bool m_persistentCredentialStorageEnabled { true }; + bool m_ignoreTLSErrors { true }; ++#endif ++#if USE(SOUP) + WebCore::SoupNetworkProxySettings m_networkProxySettings; + #endif + +@@ -446,6 +469,11 @@ private: + RefPtr m_cookieStore; + RefPtr m_networkProcess; + ++ Vector m_languagesForAutomation; ++ Optional m_allowDownloadForAutomation; ++ String m_downloadPathForAutomation; ++ DownloadInstrumentation* m_downloadInstrumentation { nullptr }; ++ + #if HAVE(APP_SSO) + UniqueRef m_soAuthorizationCoordinator; + #endif +diff --git a/Source/WebKit/UIProcess/cairo/BackingStoreCairo.cpp b/Source/WebKit/UIProcess/cairo/BackingStoreCairo.cpp +index dc0a70b8824afdc7ec3dd1f69f4d9b51942924f6..a4e90dc22fb278864c49c0636964e82f3d0d7193 100644 +--- a/Source/WebKit/UIProcess/cairo/BackingStoreCairo.cpp ++++ b/Source/WebKit/UIProcess/cairo/BackingStoreCairo.cpp +@@ -27,9 +27,11 @@ + #include "config.h" + #include "BackingStore.h" + ++#include "DrawingAreaProxyCoordinatedGraphics.h" + #include "ShareableBitmap.h" + #include "UpdateInfo.h" + #include "WebPageProxy.h" ++#include "WebPageInspectorController.h" + #include + #include + #include +@@ -62,6 +64,13 @@ std::unique_ptr BackingStore::createBackend() + return makeUnique(m_size, m_deviceScaleFactor); + } + ++cairo_surface_t* BackingStore::surface() const { ++ if (!m_backend) ++ return nullptr; ++ ++ return m_backend->surface(); ++} ++ + void BackingStore::paint(cairo_t* context, const IntRect& rect) + { + ASSERT(m_backend); +diff --git a/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp b/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp +index 411056d43ea764c42bce0403e6c69ddb8b24b04e..86d4e842699a230ce595088b62a29eabea5b6b90 100644 +--- a/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp ++++ b/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp +@@ -60,6 +60,8 @@ void GeoclueGeolocationProvider::start(UpdateNotifyFunction&& updateNotifyFuncti + m_isRunning = true; + m_cancellable = adoptGRef(g_cancellable_new()); + if (!m_manager) { ++ g_cancellable_cancel(m_cancellable_start.get()); ++ m_cancellable_start = adoptGRef(g_cancellable_new()); + g_dbus_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, nullptr, + "org.freedesktop.GeoClue2", "/org/freedesktop/GeoClue2/Manager", "org.freedesktop.GeoClue2.Manager", m_cancellable.get(), + [](GObject*, GAsyncResult* result, gpointer userData) { +@@ -91,6 +93,12 @@ void GeoclueGeolocationProvider::stop() + g_cancellable_cancel(m_cancellable.get()); + m_cancellable = nullptr; + stopClient(); ++ g_cancellable_cancel(m_cancellable_start.get()); ++ m_cancellable_start = nullptr; ++ g_cancellable_cancel(m_cancellable_setup.get()); ++ m_cancellable_setup = nullptr; ++ g_cancellable_cancel(m_cancellable_create.get()); ++ m_cancellable_create = nullptr; + destroyManagerLater(); + } + +@@ -153,6 +161,8 @@ void GeoclueGeolocationProvider::createClient(const char* clientPath) + return; + } + ++ g_cancellable_cancel(m_cancellable_create.get()); ++ m_cancellable_create = adoptGRef(g_cancellable_new()); + g_dbus_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, nullptr, + "org.freedesktop.GeoClue2", clientPath, "org.freedesktop.GeoClue2.Client", m_cancellable.get(), + [](GObject*, GAsyncResult* result, gpointer userData) { +diff --git a/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.h b/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.h +index 31d29091985f34a65134a2b0e7cb3ace1dae441d..571ceac8a4b291fa6e91eb8b17065c0aba908ac3 100644 +--- a/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.h ++++ b/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.h +@@ -71,6 +71,9 @@ private: + GRefPtr m_manager; + GRefPtr m_client; + GRefPtr m_cancellable; ++ GRefPtr m_cancellable_start; ++ GRefPtr m_cancellable_setup; ++ GRefPtr m_cancellable_create; + UpdateNotifyFunction m_updateNotifyFunction; + RunLoop::Timer m_destroyManagerLaterTimer; + }; +diff --git a/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.cpp b/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..31a4e32d4cf8442049f0bea04c817a40b801c1f7 +--- /dev/null ++++ b/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.cpp +@@ -0,0 +1,147 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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 "InspectorPlaywrightAgentClientGLib.h" ++ ++#if ENABLE(REMOTE_INSPECTOR) ++ ++#include "InspectorPlaywrightAgent.h" ++#include "WebKitBrowserInspectorPrivate.h" ++#include "WebKitWebContextPrivate.h" ++#include "WebKitWebsiteDataManagerPrivate.h" ++#include "WebKitWebViewPrivate.h" ++#include "WebPageProxy.h" ++#include ++#include ++#include ++#include ++ ++namespace WebKit { ++ ++static WebCore::SoupNetworkProxySettings parseRawProxySettings(const String& proxyServer, const char* const* ignoreHosts) ++{ ++ WebCore::SoupNetworkProxySettings settings; ++ if (proxyServer.isEmpty()) ++ return settings; ++ ++ settings.mode = WebCore::SoupNetworkProxySettings::Mode::Custom; ++ settings.defaultProxyURL = proxyServer.utf8(); ++ settings.ignoreHosts.reset(g_strdupv(const_cast(ignoreHosts))); ++ return settings; ++} ++ ++static WebCore::SoupNetworkProxySettings parseProxySettings(const String& proxyServer, const String& proxyBypassList) ++{ ++ Vector ignoreHosts; ++ if (!proxyBypassList.isEmpty()) { ++ Vector tokens = proxyBypassList.split(','); ++ Vector protectTokens; ++ for (String token : tokens) { ++ CString cstr = token.utf8(); ++ ignoreHosts.append(cstr.data()); ++ protectTokens.append(WTFMove(cstr)); ++ } ++ } ++ ignoreHosts.append(nullptr); ++ return parseRawProxySettings(proxyServer, ignoreHosts.data()); ++} ++ ++InspectorPlaywrightAgentClientGlib::InspectorPlaywrightAgentClientGlib(const WTF::String& proxyURI, const char* const* ignoreHosts) ++ : m_proxySettings(parseRawProxySettings(proxyURI, ignoreHosts)) ++{ ++} ++ ++RefPtr InspectorPlaywrightAgentClientGlib::createPage(WTF::String& error, const BrowserContext& browserContext) ++{ ++ auto sessionID = browserContext.dataStore->sessionID(); ++ WebKitWebContext* context = m_idToContext.get(sessionID); ++ if (!context && !browserContext.dataStore->isPersistent()) { ++ ASSERT_NOT_REACHED(); ++ error = "Context with provided id not found"; ++ return nullptr; ++ } ++ ++ RefPtr page = webkitBrowserInspectorCreateNewPageInContext(context); ++ if (page == nullptr) { ++ error = "Failed to create new page in the context"; ++ return nullptr; ++ } ++ ++ if (context == nullptr && sessionID != page->sessionID()) { ++ ASSERT_NOT_REACHED(); ++ error = " Failed to create new page in default context"; ++ return nullptr; ++ } ++ ++ return page; ++} ++ ++void InspectorPlaywrightAgentClientGlib::closeBrowser() ++{ ++ m_idToContext.clear(); ++ webkitBrowserInspectorQuitApplication(); ++ if (webkitWebContextExistingCount() > 1) ++ fprintf(stderr, "LEAK: %d contexts are still alive when closing browser\n", webkitWebContextExistingCount()); ++} ++ ++static PAL::SessionID sessionIDFromContext(WebKitWebContext* context) ++{ ++ WebKitWebsiteDataManager* data_manager = webkit_web_context_get_website_data_manager(context); ++ WebsiteDataStore& websiteDataStore = webkitWebsiteDataManagerGetDataStore(data_manager); ++ return websiteDataStore.sessionID(); ++} ++ ++std::unique_ptr InspectorPlaywrightAgentClientGlib::createBrowserContext(WTF::String& error, const WTF::String& proxyServer, const WTF::String& proxyBypassList) ++{ ++ GRefPtr data_manager = adoptGRef(webkit_website_data_manager_new_ephemeral()); ++ GRefPtr context = adoptGRef(WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT, "website-data-manager", data_manager.get(), "process-swap-on-cross-site-navigation-enabled", true, nullptr))); ++ if (!context) { ++ error = "Failed to create GLib ephemeral context"; ++ return nullptr; ++ } ++ auto browserContext = std::make_unique(); ++ browserContext->processPool = &webkitWebContextGetProcessPool(context.get()); ++ browserContext->dataStore = &webkitWebsiteDataManagerGetDataStore(data_manager.get()); ++ PAL::SessionID sessionID = sessionIDFromContext(context.get()); ++ m_idToContext.set(sessionID, WTFMove(context)); ++ ++ if (!proxyServer.isEmpty()) { ++ WebCore::SoupNetworkProxySettings contextProxySettings = parseProxySettings(proxyServer, proxyBypassList); ++ browserContext->dataStore->setNetworkProxySettings(WTFMove(contextProxySettings)); ++ } else { ++ browserContext->dataStore->setNetworkProxySettings(WebCore::SoupNetworkProxySettings(m_proxySettings)); ++ } ++ return browserContext; ++} ++ ++void InspectorPlaywrightAgentClientGlib::deleteBrowserContext(WTF::String& error, PAL::SessionID sessionID) ++{ ++ m_idToContext.remove(sessionID); ++} ++ ++} // namespace WebKit ++ ++#endif // ENABLE(REMOTE_INSPECTOR) +diff --git a/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.h b/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.h +new file mode 100644 +index 0000000000000000000000000000000000000000..8006336003a4512b4c63bc8272d4b3507bb63159 +--- /dev/null ++++ b/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.h +@@ -0,0 +1,60 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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. ++ */ ++ ++#pragma once ++ ++#if ENABLE(REMOTE_INSPECTOR) ++ ++#include "InspectorPlaywrightAgentClient.h" ++#include ++#include "WebKitWebContext.h" ++#include ++#include ++#include ++#include ++ ++namespace WebKit { ++ ++class InspectorPlaywrightAgentClientGlib : public InspectorPlaywrightAgentClient { ++ WTF_MAKE_FAST_ALLOCATED; ++public: ++ InspectorPlaywrightAgentClientGlib(const WTF::String& proxyURI, const char* const* ignoreHosts); ++ ~InspectorPlaywrightAgentClientGlib() override = default; ++ ++ RefPtr createPage(WTF::String& error, const BrowserContext&) override; ++ void closeBrowser() override; ++ std::unique_ptr createBrowserContext(WTF::String& error, const WTF::String& proxyServer, const WTF::String& proxyBypassList) override; ++ void deleteBrowserContext(WTF::String& error, PAL::SessionID) override; ++ ++private: ++ WebKitWebContext* findContext(WTF::String& error, PAL::SessionID); ++ ++ HashMap> m_idToContext; ++ WebCore::SoupNetworkProxySettings m_proxySettings; ++}; ++ ++} // namespace API ++ ++#endif // ENABLE(REMOTE_INSPECTOR) +diff --git a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStore.h b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStore.h +index 39aeff71fe05354cf63d3b3701d363642d63aca4..32e96cdd0bdbd8c5dcde43fdf60052ac13a226f7 100644 +--- a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStore.h ++++ b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStore.h +@@ -28,6 +28,7 @@ + #include + + typedef struct _cairo cairo_t; ++typedef struct _cairo_surface cairo_surface_t; + + #if USE(GTK4) + typedef struct _GdkSnapshot GdkSnapshot; +@@ -56,6 +57,8 @@ public: + #else + virtual bool paint(cairo_t*, const WebCore::IntRect&) = 0; + #endif ++ virtual cairo_surface_t* surface() { return nullptr; } ++ + virtual void realize() { }; + virtual void unrealize() { }; + virtual bool makeContextCurrent() { return false; } +diff --git a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreX11.h b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreX11.h +index 054e80bd900cf16d69801e8102ca989ff0563e1d..8245d7ed58008dbb6152e55e619e4331d30ae674 100644 +--- a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreX11.h ++++ b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreX11.h +@@ -52,6 +52,7 @@ private: + #else + bool paint(cairo_t*, const WebCore::IntRect&) override; + #endif ++ cairo_surface_t* surface() override { return m_surface.get(); } + + RefPtr m_surface; + WebCore::XUniqueDamage m_damage; +diff --git a/Source/WebKit/UIProcess/gtk/InspectorTargetProxyGtk.cpp b/Source/WebKit/UIProcess/gtk/InspectorTargetProxyGtk.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..8a86cc348bc210b71bb463dcb3057f575ad7c1d3 +--- /dev/null ++++ b/Source/WebKit/UIProcess/gtk/InspectorTargetProxyGtk.cpp +@@ -0,0 +1,44 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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 "InspectorTargetProxy.h" ++ ++#include "WebPageProxy.h" ++#include ++#include ++ ++namespace WebKit { ++ ++void InspectorTargetProxy::platformActivate(String& error) const ++{ ++ GtkWidget* parent = gtk_widget_get_toplevel(m_page.viewWidget()); ++ if (WebCore::widgetIsOnscreenToplevelWindow(parent)) ++ gtk_window_present(GTK_WINDOW(parent)); ++ else ++ error = "The view is not on screen"; ++} ++ ++} // namespace WebKit +diff --git a/Source/WebKit/UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp b/Source/WebKit/UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..e5e25acebabb76a05a77db02a99f1267bd99a3af +--- /dev/null ++++ b/Source/WebKit/UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp +@@ -0,0 +1,69 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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 "DrawingAreaProxyCoordinatedGraphics.h" ++#include "WebPageInspectorEmulationAgent.h" ++#include "WebPageProxy.h" ++#include ++#include ++ ++namespace WebKit { ++void WebPageInspectorEmulationAgent::platformSetSize(int width, int height, Function&& callback) ++{ ++ GtkWidget* viewWidget = m_page.viewWidget(); ++ GtkWidget* window = gtk_widget_get_toplevel(viewWidget); ++ if (!window) { ++ callback("Cannot find parent window"_s); ++ return; ++ } ++ if (!GTK_IS_WINDOW(window)) { ++ callback("Toplevel is not a window"_s); ++ return; ++ } ++ GtkAllocation viewAllocation; ++ gtk_widget_get_allocation(viewWidget, &viewAllocation); ++ if (viewAllocation.width == width && viewAllocation.height == height) { ++ callback(String()); ++ return; ++ } ++ ++ GtkAllocation windowAllocation; ++ gtk_widget_get_allocation(window, &windowAllocation); ++ ++ width += windowAllocation.width - viewAllocation.width; ++ height += windowAllocation.height - viewAllocation.height; ++ ++ if (auto* drawingArea = static_cast(m_page.drawingArea())) { ++ drawingArea->waitForSizeUpdate([callback = WTFMove(callback)]() { ++ callback(String()); ++ }); ++ } else { ++ callback("No backing store for window"_s); ++ } ++ gtk_window_resize(GTK_WINDOW(window), width, height); ++} ++ ++} // namespace WebKit +diff --git a/Source/WebKit/UIProcess/gtk/WebPageInspectorInputAgentGtk.cpp b/Source/WebKit/UIProcess/gtk/WebPageInspectorInputAgentGtk.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..d0f9827544994e450e24e3f7a427c35eeff94d67 +--- /dev/null ++++ b/Source/WebKit/UIProcess/gtk/WebPageInspectorInputAgentGtk.cpp +@@ -0,0 +1,105 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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 "WebPageInspectorInputAgent.h" ++ ++#include "KeyBindingTranslator.h" ++#include "NativeWebKeyboardEvent.h" ++#include "WebPageProxy.h" ++#include ++ ++namespace WebKit { ++ ++static Vector commandsForKeyEvent(GdkEventType type, unsigned keyVal, unsigned state) ++{ ++ ASSERT(type == GDK_KEY_PRESS || type == GDK_KEY_RELEASE); ++ ++ GUniquePtr event(gdk_event_new(type)); ++ event->key.keyval = keyVal; ++ event->key.time = GDK_CURRENT_TIME; ++ event->key.state = state; ++ // When synthesizing an event, an invalid hardware_keycode value can cause it to be badly processed by GTK+. ++ GUniqueOutPtr keys; ++ int keysCount; ++ if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), keyVal, &keys.outPtr(), &keysCount) && keysCount) ++ event->key.hardware_keycode = keys.get()[0].keycode; ++ return KeyBindingTranslator().commandsForKeyEvent(&event->key); ++} ++ ++static unsigned modifiersToEventState(OptionSet modifiers) ++{ ++ unsigned state = 0; ++ if (modifiers.contains(WebEvent::Modifier::ControlKey)) ++ state |= GDK_CONTROL_MASK; ++ if (modifiers.contains(WebEvent::Modifier::ShiftKey)) ++ state |= GDK_SHIFT_MASK; ++ if (modifiers.contains(WebEvent::Modifier::AltKey)) ++ state |= GDK_META_MASK; ++ if (modifiers.contains(WebEvent::Modifier::CapsLockKey)) ++ state |= GDK_LOCK_MASK; ++ return state; ++} ++ ++void WebPageInspectorInputAgent::platformDispatchKeyEvent(WebKeyboardEvent::Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, Vector& macCommands, WallTime timestamp) ++{ ++ Vector commands; ++ const guint keyVal = WebCore::PlatformKeyboardEvent::gdkKeyCodeForWindowsKeyCode(windowsVirtualKeyCode); ++ if (keyVal) { ++ GdkEventType event = GDK_NOTHING; ++ switch (type) ++ { ++ case WebKeyboardEvent::KeyDown: ++ event = GDK_KEY_PRESS; ++ break; ++ case WebKeyboardEvent::KeyUp: ++ event = GDK_KEY_RELEASE; ++ break; ++ default: ++ fprintf(stderr, "Unsupported event type = %d\n", type); ++ break; ++ } ++ unsigned state = modifiersToEventState(modifiers); ++ commands = commandsForKeyEvent(event, keyVal, state); ++ } ++ NativeWebKeyboardEvent event( ++ type, ++ text, ++ unmodifiedText, ++ key, ++ code, ++ keyIdentifier, ++ windowsVirtualKeyCode, ++ nativeVirtualKeyCode, ++ isAutoRepeat, ++ isKeypad, ++ isSystemKey, ++ modifiers, ++ timestamp, ++ WTFMove(commands)); ++ m_page.handleKeyboardEvent(event); ++} ++ ++} // namespace WebKit +diff --git a/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm b/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm +index b9d8835cdef6ad8778744c664b02d683a27bc17e..47c855e9fabbb715ea0bb4c734680b7a7c7b7c5a 100644 +--- a/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm ++++ b/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm +@@ -435,6 +435,8 @@ IntRect PageClientImpl::rootViewToAccessibilityScreen(const IntRect& rect) + + void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool eventWasHandled) + { ++ if (!event.nativeEvent()) ++ return; + [m_contentView _didHandleKeyEvent:event.nativeEvent() eventWasHandled:eventWasHandled]; + } + +diff --git a/Source/WebKit/UIProcess/mac/InspectorPlaywrightAgentClientMac.h b/Source/WebKit/UIProcess/mac/InspectorPlaywrightAgentClientMac.h +new file mode 100644 +index 0000000000000000000000000000000000000000..a16815a6759da61a6a61e3d79058228af887fd7c +--- /dev/null ++++ b/Source/WebKit/UIProcess/mac/InspectorPlaywrightAgentClientMac.h +@@ -0,0 +1,51 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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. ++ */ ++ ++#pragma once ++ ++#include "InspectorPlaywrightAgentClient.h" ++#include ++ ++OBJC_PROTOCOL(_WKBrowserInspectorDelegate); ++ ++namespace WebKit { ++ ++class InspectorPlaywrightAgentClientMac : public InspectorPlaywrightAgentClient { ++ WTF_MAKE_FAST_ALLOCATED; ++public: ++ InspectorPlaywrightAgentClientMac(_WKBrowserInspectorDelegate* delegate); ++ ~InspectorPlaywrightAgentClientMac() override = default; ++ ++ RefPtr createPage(WTF::String& error, const BrowserContext&) override; ++ void closeBrowser() override; ++ std::unique_ptr createBrowserContext(WTF::String& error, const WTF::String& proxyServer, const WTF::String& proxyBypassList) override; ++ void deleteBrowserContext(WTF::String& error, PAL::SessionID) override; ++ ++private: ++ _WKBrowserInspectorDelegate* delegate_; ++}; ++ ++ ++} // namespace API +diff --git a/Source/WebKit/UIProcess/mac/InspectorPlaywrightAgentClientMac.mm b/Source/WebKit/UIProcess/mac/InspectorPlaywrightAgentClientMac.mm +new file mode 100644 +index 0000000000000000000000000000000000000000..8e588f7b8c8c29fb53dd37ea41d46f3d753077fd +--- /dev/null ++++ b/Source/WebKit/UIProcess/mac/InspectorPlaywrightAgentClientMac.mm +@@ -0,0 +1,77 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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. ++ */ ++ ++#import "config.h" ++#import "InspectorPlaywrightAgentClientMac.h" ++ ++#import ++#import ++#import "WebPageProxy.h" ++#import "WebProcessPool.h" ++#import "WebsiteDataStore.h" ++#import "_WKBrowserInspector.h" ++#import "WKProcessPoolInternal.h" ++#import "WKWebsiteDataStoreInternal.h" ++#import "WKWebView.h" ++#import "WKWebViewInternal.h" ++ ++namespace WebKit { ++ ++InspectorPlaywrightAgentClientMac::InspectorPlaywrightAgentClientMac(_WKBrowserInspectorDelegate* delegate) ++ : delegate_(delegate) ++{ ++} ++ ++RefPtr InspectorPlaywrightAgentClientMac::createPage(WTF::String& error, const BrowserContext& browserContext) ++{ ++ auto sessionID = browserContext.dataStore->sessionID(); ++ WKWebView *webView = [delegate_ createNewPage:sessionID.toUInt64()]; ++ if (!webView) { ++ error = "Internal error: can't create page in given context"_s; ++ return nil; ++ } ++ return [webView _page].get(); ++} ++ ++void InspectorPlaywrightAgentClientMac::closeBrowser() ++{ ++ [delegate_ quit]; ++} ++ ++std::unique_ptr InspectorPlaywrightAgentClientMac::createBrowserContext(WTF::String& error, const WTF::String& proxyServer, const WTF::String& proxyBypassList) ++{ ++ _WKBrowserContext* wkBrowserContext = [[delegate_ createBrowserContext:proxyServer WithBypassList:proxyBypassList] autorelease]; ++ auto browserContext = std::make_unique(); ++ browserContext->processPool = &static_cast([[wkBrowserContext processPool] _apiObject]); ++ browserContext->dataStore = &static_cast([[wkBrowserContext dataStore] _apiObject]); ++ return browserContext; ++} ++ ++void InspectorPlaywrightAgentClientMac::deleteBrowserContext(WTF::String& error, PAL::SessionID sessionID) ++{ ++ [delegate_ deleteBrowserContext:sessionID.toUInt64()]; ++} ++ ++} // namespace WebKit +diff --git a/Source/WebKit/UIProcess/mac/InspectorTargetProxyMac.mm b/Source/WebKit/UIProcess/mac/InspectorTargetProxyMac.mm +new file mode 100644 +index 0000000000000000000000000000000000000000..721826c8c98fc85b68a4f45deaee69c1219a7254 +--- /dev/null ++++ b/Source/WebKit/UIProcess/mac/InspectorTargetProxyMac.mm +@@ -0,0 +1,42 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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. ++ */ ++ ++#import "config.h" ++#import "InspectorTargetProxy.h" ++#import "WebPageProxy.h" ++ ++#if PLATFORM(MAC) ++ ++namespace WebKit { ++ ++void InspectorTargetProxy::platformActivate(String& error) const ++{ ++ NSWindow* window = m_page.platformWindow(); ++ [window makeKeyAndOrderFront:nil]; ++} ++ ++} // namespace WebKit ++ ++#endif +diff --git a/Source/WebKit/UIProcess/mac/PageClientImplMac.h b/Source/WebKit/UIProcess/mac/PageClientImplMac.h +index d50d9310e8c00e9f2aa8f7234b5129de407f0f52..397b609060e787f1d42adc4b4bf7bf12c68d59bd 100644 +--- a/Source/WebKit/UIProcess/mac/PageClientImplMac.h ++++ b/Source/WebKit/UIProcess/mac/PageClientImplMac.h +@@ -53,6 +53,8 @@ class PageClientImpl final : public PageClientImplCocoa + #endif + { + public: ++ static void setHeadless(bool headless); ++ + PageClientImpl(NSView *, WKWebView *); + virtual ~PageClientImpl(); + +@@ -119,6 +121,7 @@ private: + WebCore::IntRect rootViewToScreen(const WebCore::IntRect&) override; + #if PLATFORM(MAC) + WebCore::IntRect rootViewToWindow(const WebCore::IntRect&) override; ++ int browserToolbarHeight() const override; + #endif + WebCore::IntPoint accessibilityScreenToRootView(const WebCore::IntPoint&) override; + WebCore::IntRect rootViewToAccessibilityScreen(const WebCore::IntRect&) override; +@@ -162,6 +165,9 @@ private: + void updateAcceleratedCompositingMode(const LayerTreeContext&) override; + void didFirstLayerFlush(const LayerTreeContext&) override; + ++// Paywright begin ++ RetainPtr takeSnapshotForAutomation() override; ++// Paywright end + RefPtr takeViewSnapshot(Optional&&) override; + void wheelEventWasNotHandledByWebCore(const NativeWebWheelEvent&) override; + #if ENABLE(MAC_GESTURE_EVENTS) +@@ -216,6 +222,10 @@ private: + void beganExitFullScreen(const WebCore::IntRect& initialFrame, const WebCore::IntRect& finalFrame) override; + #endif + ++#if ENABLE(TOUCH_EVENTS) ++ void doneWithTouchEvent(const NativeWebTouchEvent&, bool wasEventHandled) override; ++#endif ++ + void navigationGestureDidBegin() override; + void navigationGestureWillEnd(bool willNavigate, WebBackForwardListItem&) override; + void navigationGestureDidEnd(bool willNavigate, WebBackForwardListItem&) override; +diff --git a/Source/WebKit/UIProcess/mac/PageClientImplMac.mm b/Source/WebKit/UIProcess/mac/PageClientImplMac.mm +index 5849a2d99964b8c3bcd034fcf83a60f2b9163ddd..1e269584b0f84bab7a3e9017521d3f283a74676e 100644 +--- a/Source/WebKit/UIProcess/mac/PageClientImplMac.mm ++++ b/Source/WebKit/UIProcess/mac/PageClientImplMac.mm +@@ -81,6 +81,7 @@ + #import + #import + #import ++#import + #import + #import + #import +@@ -107,6 +108,13 @@ namespace WebKit { + + using namespace WebCore; + ++static bool _headless = false; ++ ++// static ++void PageClientImpl::setHeadless(bool headless) { ++ _headless = headless; ++} ++ + PageClientImpl::PageClientImpl(NSView *view, WKWebView *webView) + : PageClientImplCocoa(webView) + , m_view(view) +@@ -160,6 +168,9 @@ NSWindow *PageClientImpl::activeWindow() const + + bool PageClientImpl::isViewWindowActive() + { ++ if (_headless) ++ return true; ++ + ASSERT(hasProcessPrivilege(ProcessPrivilege::CanCommunicateWithWindowServer)); + NSWindow *activeViewWindow = activeWindow(); + return activeViewWindow.isKeyWindow || (activeViewWindow && [NSApp keyWindow] == activeViewWindow); +@@ -167,6 +178,9 @@ bool PageClientImpl::isViewWindowActive() + + bool PageClientImpl::isViewFocused() + { ++ if (_headless) ++ return true; ++ + // FIXME: This is called from the WebPageProxy constructor before we have a WebViewImpl. + // Once WebViewImpl and PageClient merge, this won't be a problem. + if (!m_impl) +@@ -190,6 +204,9 @@ void PageClientImpl::makeFirstResponder() + + bool PageClientImpl::isViewVisible() + { ++ if (_headless) ++ return true; ++ + NSView *activeView = this->activeView(); + NSWindow *activeViewWindow = activeWindow(); + +@@ -273,7 +290,8 @@ void PageClientImpl::didRelaunchProcess() + + void PageClientImpl::preferencesDidChange() + { +- m_impl->preferencesDidChange(); ++ if (m_impl) ++ m_impl->preferencesDidChange(); + } + + void PageClientImpl::toolTipChanged(const String& oldToolTip, const String& newToolTip) +@@ -466,6 +484,15 @@ IntRect PageClientImpl::rootViewToWindow(const WebCore::IntRect& rect) + return enclosingIntRect(tempRect); + } + ++int PageClientImpl::browserToolbarHeight() const ++{ ++ // There are no controls in headless mode. ++ if (_headless) ++ return 0; ++ ++ return 55; ++} ++ + IntPoint PageClientImpl::accessibilityScreenToRootView(const IntPoint& point) + { + return screenToRootView(point); +@@ -478,6 +505,8 @@ IntRect PageClientImpl::rootViewToAccessibilityScreen(const IntRect& rect) + + void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool eventWasHandled) + { ++ if (!event.nativeEvent()) ++ return; + m_impl->doneWithKeyEvent(event.nativeEvent(), eventWasHandled); + } + +@@ -492,6 +521,8 @@ void PageClientImpl::requestImageExtraction(const URL& imageURL, const Shareable + + RefPtr PageClientImpl::createPopupMenuProxy(WebPageProxy& page) + { ++ if (_headless) ++ return nullptr; + return WebPopupMenuProxyMac::create(m_view, page); + } + +@@ -611,6 +642,12 @@ CALayer *PageClientImpl::acceleratedCompositingRootLayer() const + return m_impl->acceleratedCompositingRootLayer(); + } + ++// Paywright begin ++RetainPtr PageClientImpl::takeSnapshotForAutomation() { ++ return m_impl->takeSnapshotForAutomation(); ++} ++// Paywright begin ++ + RefPtr PageClientImpl::takeViewSnapshot(Optional&&) + { + return m_impl->takeViewSnapshot(); +@@ -789,6 +826,13 @@ void PageClientImpl::beganExitFullScreen(const IntRect& initialFrame, const IntR + + #endif // ENABLE(FULLSCREEN_API) + ++#if ENABLE(TOUCH_EVENTS) ++void PageClientImpl::doneWithTouchEvent(const NativeWebTouchEvent& event, bool wasEventHandled) ++{ ++ notImplemented(); ++} ++#endif // ENABLE(TOUCH_EVENTS) ++ + void PageClientImpl::navigationGestureDidBegin() + { + m_impl->dismissContentRelativeChildWindowsWithAnimation(true); +@@ -955,6 +999,9 @@ void PageClientImpl::didRestoreScrollPosition() + + bool PageClientImpl::windowIsFrontWindowUnderMouse(const NativeWebMouseEvent& event) + { ++ // Simulated event. ++ if (!event.nativeEvent()) ++ return false; + return m_impl->windowIsFrontWindowUnderMouse(event.nativeEvent()); + } + +diff --git a/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.h b/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.h +index 0bb07e679f30e7b3682b3736b5372cbbb2d31ec8..cc0740c7d88d11d419cf2ca51cbc00b193531100 100644 +--- a/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.h ++++ b/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.h +@@ -62,6 +62,7 @@ private: + void show() override; + void showContextMenuWithItems(Vector>&&) override; + void useContextMenuItems(Vector>&&) override; ++ void hide() override; + + void getContextMenuItem(const WebContextMenuItemData&, CompletionHandler&&); + void getContextMenuFromItems(const Vector&, CompletionHandler&&); +diff --git a/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm b/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm +index 8f2a7d46c539818a58add4ba808dc61ab493653d..7b346b4312eea31bfa599fa3d4ea47b89fdef37f 100644 +--- a/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm ++++ b/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm +@@ -328,6 +328,12 @@ void WebContextMenuProxyMac::getShareMenuItem(CompletionHandler&& callback) ++{ ++ NSWindow* window = m_page.platformWindow(); ++ NSRect windowRect = [window frame]; ++ NSRect viewRect = window.contentLayoutRect; ++ windowRect.size.width += width - viewRect.size.width; ++ windowRect.size.height += height - viewRect.size.height; ++ [window setFrame:windowRect display:YES animate:NO]; ++ callback(String()); ++} ++ ++} // namespace WebKit +diff --git a/Source/WebKit/UIProcess/mac/WebPageInspectorInputAgentMac.mm b/Source/WebKit/UIProcess/mac/WebPageInspectorInputAgentMac.mm +new file mode 100644 +index 0000000000000000000000000000000000000000..726053d74b9283d734d8699daca0e5e7f8893eca +--- /dev/null ++++ b/Source/WebKit/UIProcess/mac/WebPageInspectorInputAgentMac.mm +@@ -0,0 +1,124 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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. ++ */ ++ ++#import "config.h" ++#import "NativeWebMouseEvent.h" ++#import "WebPageInspectorInputAgent.h" ++#import "WebPageProxy.h" ++#import ++#import ++#import "NativeWebKeyboardEvent.h" ++ ++namespace WebKit { ++ ++using namespace WebCore; ++ ++void WebPageInspectorInputAgent::platformDispatchMouseEvent(const String& type, int x, int y, Optional&& optionalModifiers, const String& button, Optional&& optionalClickCount) { ++ IntPoint locationInWindow(x, y); ++ ++ NSEventModifierFlags modifiers = 0; ++ if (optionalModifiers) { ++ int inputModifiers = *optionalModifiers; ++ if (inputModifiers & 1) ++ modifiers |= NSEventModifierFlagShift; ++ if (inputModifiers & 2) ++ modifiers |= NSEventModifierFlagControl; ++ if (inputModifiers & 4) ++ modifiers |= NSEventModifierFlagOption; ++ if (inputModifiers & 8) ++ modifiers |= NSEventModifierFlagCommand; ++ } ++ int clickCount = optionalClickCount ? *optionalClickCount : 0; ++ ++ NSTimeInterval timestamp = [NSDate timeIntervalSinceReferenceDate]; ++ NSWindow *window = m_page.platformWindow(); ++ NSInteger windowNumber = window.windowNumber; ++ ++ NSEventType downEventType = (NSEventType)0; ++ NSEventType dragEventType = (NSEventType)0; ++ NSEventType upEventType = (NSEventType)0; ++ ++ if (!button || button == "none") { ++ downEventType = NSEventTypeMouseMoved; ++ dragEventType = NSEventTypeMouseMoved; ++ upEventType = NSEventTypeMouseMoved; ++ } else if (button == "left") { ++ downEventType = NSEventTypeLeftMouseDown; ++ dragEventType = NSEventTypeLeftMouseDragged; ++ upEventType = NSEventTypeLeftMouseUp; ++ } else if (button == "middle") { ++ downEventType = NSEventTypeOtherMouseDown; ++ dragEventType = NSEventTypeLeftMouseDragged; ++ upEventType = NSEventTypeOtherMouseUp; ++ } else if (button == "right") { ++ downEventType = NSEventTypeRightMouseDown; ++ upEventType = NSEventTypeRightMouseUp; ++ } ++ ++ NSInteger eventNumber = 0; ++ ++ NSEvent* event = nil; ++ if (type == "move") { ++ event = [NSEvent mouseEventWithType:dragEventType location:locationInWindow modifierFlags:modifiers timestamp:timestamp windowNumber:windowNumber context:nil eventNumber:eventNumber clickCount:clickCount pressure:0.0f]; ++ } else if (type == "down") { ++ event = [NSEvent mouseEventWithType:downEventType location:locationInWindow modifierFlags:modifiers timestamp:timestamp windowNumber:windowNumber context:nil eventNumber:eventNumber clickCount:clickCount pressure:WebCore::ForceAtClick]; ++ } else if (type == "up") { ++ event = [NSEvent mouseEventWithType:upEventType location:locationInWindow modifierFlags:modifiers timestamp:timestamp windowNumber:windowNumber context:nil eventNumber:eventNumber clickCount:clickCount pressure:0.0f]; ++ } ++ ++ if (event) { ++ NativeWebMouseEvent nativeEvent(event, nil, [window contentView]); ++ m_page.handleMouseEvent(nativeEvent); ++ } ++} ++ ++void WebPageInspectorInputAgent::platformDispatchKeyEvent(WebKeyboardEvent::Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, Vector& commands, WallTime timestamp) ++{ ++ Vector macCommands; ++ for (const String& command : commands) { ++ m_page.registerKeypressCommandName(command); ++ macCommands.append(WebCore::KeypressCommand(command.utf8().data())); ++ } ++ if (text.length() > 0 && macCommands.size() == 0) ++ macCommands.append(WebCore::KeypressCommand("insertText:", text)); ++ NativeWebKeyboardEvent event( ++ type, ++ text, ++ unmodifiedText, ++ key, ++ code, ++ keyIdentifier, ++ windowsVirtualKeyCode, ++ nativeVirtualKeyCode, ++ isAutoRepeat, ++ isKeypad, ++ isSystemKey, ++ modifiers, ++ timestamp, ++ WTFMove(macCommands)); ++ m_page.handleKeyboardEvent(event); ++} ++ ++} // namespace WebKit +diff --git a/Source/WebKit/UIProcess/win/InspectorPlaywrightAgentClientWin.cpp b/Source/WebKit/UIProcess/win/InspectorPlaywrightAgentClientWin.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..dd7fe0604188bb025f361f1c44685e38bbf935ca +--- /dev/null ++++ b/Source/WebKit/UIProcess/win/InspectorPlaywrightAgentClientWin.cpp +@@ -0,0 +1,90 @@ ++/* ++ * Copyright (C) 2020 Microsoft Corporation. ++ * ++ * 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 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 "InspectorPlaywrightAgentClientWin.h" ++ ++#if ENABLE(REMOTE_INSPECTOR) ++ ++#include "APIPageConfiguration.h" ++#include "APIProcessPoolConfiguration.h" ++#include "InspectorPlaywrightAgent.h" ++#include "WebPageProxy.h" ++#include "WebsiteDataStore.h" ++#include "WebPreferences.h" ++#include "WebProcessPool.h" ++#include "WebView.h" ++#include "WKAPICast.h" ++#include ++#include ++#include ++#include ++#include ++ ++namespace WebKit { ++ ++InspectorPlaywrightAgentClientWin::InspectorPlaywrightAgentClientWin(ConfigureDataStoreCallback configureDataStore, CreatePageCallback createPage, QuitCallback quit) ++ : m_configureDataStore(configureDataStore) ++ , m_createPage(createPage) ++ , m_quit(quit) ++{ ++} ++ ++RefPtr InspectorPlaywrightAgentClientWin::createPage(WTF::String& error, const BrowserContext& context) ++{ ++ auto conf = API::PageConfiguration::create(); ++ conf->setProcessPool(context.processPool.get()); ++ conf->setWebsiteDataStore(context.dataStore.get()); ++ return toImpl(m_createPage(toAPI(&conf.get()))); ++} ++ ++void InspectorPlaywrightAgentClientWin::closeBrowser() ++{ ++ m_quit(); ++} ++ ++std::unique_ptr InspectorPlaywrightAgentClientWin::createBrowserContext(WTF::String& error, const WTF::String& proxyServer, const WTF::String& proxyBypassList) ++{ ++ auto config = API::ProcessPoolConfiguration::create(); ++ auto browserContext = std::make_unique(); ++ browserContext->processPool = WebKit::WebProcessPool::create(config); ++ browserContext->dataStore = WebKit::WebsiteDataStore::createNonPersistent(); ++ m_configureDataStore(toAPI(browserContext->dataStore.get())); ++ if (!proxyServer.isEmpty()) { ++ URL proxyURL = URL(URL(), proxyServer); ++ WebCore::CurlProxySettings settings(WTFMove(proxyURL), String(proxyBypassList)); ++ browserContext->dataStore->setNetworkProxySettings(WTFMove(settings)); ++ } ++ PAL::SessionID sessionID = browserContext->dataStore->sessionID(); ++ return browserContext; ++} ++ ++void InspectorPlaywrightAgentClientWin::deleteBrowserContext(WTF::String& error, PAL::SessionID sessionID) ++{ ++} ++ ++} // namespace WebKit ++ ++#endif // ENABLE(REMOTE_INSPECTOR) +diff --git a/Source/WebKit/UIProcess/win/InspectorPlaywrightAgentClientWin.h b/Source/WebKit/UIProcess/win/InspectorPlaywrightAgentClientWin.h +new file mode 100644 +index 0000000000000000000000000000000000000000..df18883b2b7d22d73540cb084d3dd5291231097d +--- /dev/null ++++ b/Source/WebKit/UIProcess/win/InspectorPlaywrightAgentClientWin.h +@@ -0,0 +1,60 @@ ++/* ++ * Copyright (C) 2020 Microsoft Corporation. ++ * ++ * 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 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. ++ */ ++ ++#pragma once ++ ++#if ENABLE(REMOTE_INSPECTOR) ++ ++#include "InspectorPlaywrightAgentClient.h" ++#include ++#include ++#include ++ ++typedef void (*ConfigureDataStoreCallback)(WKWebsiteDataStoreRef dataStore); ++typedef WKPageRef (*CreatePageCallback)(WKPageConfigurationRef configuration); ++typedef void (*QuitCallback)(); ++ ++namespace WebKit { ++ ++class InspectorPlaywrightAgentClientWin : public InspectorPlaywrightAgentClient { ++ WTF_MAKE_FAST_ALLOCATED; ++public: ++ InspectorPlaywrightAgentClientWin(ConfigureDataStoreCallback, CreatePageCallback, QuitCallback); ++ ~InspectorPlaywrightAgentClientWin() override = default; ++ ++ RefPtr createPage(WTF::String& error, const BrowserContext&) override; ++ void closeBrowser() override; ++ std::unique_ptr createBrowserContext(WTF::String& error, const WTF::String& proxyServer, const WTF::String& proxyBypassList) override; ++ void deleteBrowserContext(WTF::String& error, PAL::SessionID) override; ++ ++private: ++ ConfigureDataStoreCallback m_configureDataStore; ++ CreatePageCallback m_createPage; ++ QuitCallback m_quit; ++}; ++ ++} // namespace API ++ ++#endif // ENABLE(REMOTE_INSPECTOR) +diff --git a/Source/WebKit/UIProcess/win/InspectorTargetProxyWin.cpp b/Source/WebKit/UIProcess/win/InspectorTargetProxyWin.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..135a60361fa8fbf907382625e7c8dd4ea64ceb94 +--- /dev/null ++++ b/Source/WebKit/UIProcess/win/InspectorTargetProxyWin.cpp +@@ -0,0 +1,36 @@ ++/* ++ * Copyright (C) 2020 Microsoft Corporation. ++ * ++ * 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 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 "InspectorTargetProxy.h" ++#include "WebPageProxy.h" ++ ++namespace WebKit { ++ ++void InspectorTargetProxy::platformActivate(String& error) const ++{ ++} ++ ++} // namespace WebKit +diff --git a/Source/WebKit/UIProcess/win/WebContextMenuProxyWin.cpp b/Source/WebKit/UIProcess/win/WebContextMenuProxyWin.cpp +index 3dcd0ec35c92e37239208a8f5d4f461fbeaac3ce..84ba07c57f2abac1bd0ca5d0af2e7366ad036892 100644 +--- a/Source/WebKit/UIProcess/win/WebContextMenuProxyWin.cpp ++++ b/Source/WebKit/UIProcess/win/WebContextMenuProxyWin.cpp +@@ -112,5 +112,11 @@ WebContextMenuProxyWin::~WebContextMenuProxyWin() + ::DestroyMenu(m_menu); + } + ++void WebContextMenuProxyWin::hide() ++{ ++ if (m_menu) ++ ::EndMenu(); ++} ++ + } // namespace WebKit + #endif // ENABLE(CONTEXT_MENUS) +diff --git a/Source/WebKit/UIProcess/win/WebContextMenuProxyWin.h b/Source/WebKit/UIProcess/win/WebContextMenuProxyWin.h +index 0c80d970c3f9a987faf620081c909f6c7021970d..1467e5481f7417913c0d12a1cb492d02b2a7d1b7 100644 +--- a/Source/WebKit/UIProcess/win/WebContextMenuProxyWin.h ++++ b/Source/WebKit/UIProcess/win/WebContextMenuProxyWin.h +@@ -47,6 +47,7 @@ public: + private: + WebContextMenuProxyWin(WebPageProxy&, ContextMenuContextData&&, const UserData&); + void showContextMenuWithItems(Vector>&&) override; ++ void hide() override; + + HMENU m_menu; + }; +diff --git a/Source/WebKit/UIProcess/win/WebPageInspectorEmulationAgentWin.cpp b/Source/WebKit/UIProcess/win/WebPageInspectorEmulationAgentWin.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..62b841fe1d0de2296e1c61e328cff564f5aa1c0f +--- /dev/null ++++ b/Source/WebKit/UIProcess/win/WebPageInspectorEmulationAgentWin.cpp +@@ -0,0 +1,58 @@ ++/* ++ * Copyright (C) 2020 Microsoft Corporation. ++ * ++ * 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 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 "WebPageInspectorEmulationAgent.h" ++#include "WebPageProxy.h" ++ ++namespace WebKit { ++ ++void WebPageInspectorEmulationAgent::platformSetSize(int width, int height, Function&& callback) ++{ ++ HWND viewHwnd = m_page.viewWidget(); ++ HWND windowHwnd = GetAncestor(viewHwnd, GA_ROOT); ++ RECT viewRect; ++ RECT windowRect; ++ ++ if (!windowHwnd || !GetWindowRect(windowHwnd, &windowRect)) { ++ callback("Could not retrieve window size"); ++ return; ++ } ++ if (!GetWindowRect(viewHwnd, &viewRect)) { ++ callback("Could retrieve view size"); ++ return; ++ } ++ ++ width += windowRect.right - windowRect.left - viewRect.right + viewRect.left; ++ height += windowRect.bottom - windowRect.top - viewRect.bottom + viewRect.top; ++ ++ if (!SetWindowPos(windowHwnd, 0, 0, 0, width, height, SWP_NOCOPYBITS | SWP_NOSENDCHANGING | SWP_NOMOVE)) { ++ callback("Could not resize window"); ++ return; ++ } ++ callback(String()); ++} ++ ++} // namespace WebKit +diff --git a/Source/WebKit/UIProcess/win/WebPageInspectorInputAgentWin.cpp b/Source/WebKit/UIProcess/win/WebPageInspectorInputAgentWin.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..5cf8a010e9809e6a95741cdb7c2cbeb445ab638b +--- /dev/null ++++ b/Source/WebKit/UIProcess/win/WebPageInspectorInputAgentWin.cpp +@@ -0,0 +1,55 @@ ++/* ++ * Copyright (C) 2020 Microsoft Corporation. ++ * ++ * 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 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 "WebPageInspectorInputAgent.h" ++ ++#include "NativeWebKeyboardEvent.h" ++#include "WebPageProxy.h" ++#include ++ ++namespace WebKit { ++ ++void WebPageInspectorInputAgent::platformDispatchKeyEvent(WebKeyboardEvent::Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, Vector& macCommands, WallTime timestamp) ++{ ++ NativeWebKeyboardEvent event( ++ type, ++ text, ++ unmodifiedText, ++ key, ++ code, ++ keyIdentifier, ++ windowsVirtualKeyCode, ++ nativeVirtualKeyCode, ++ isAutoRepeat, ++ isKeypad, ++ isSystemKey, ++ modifiers, ++ timestamp); ++ m_page.handleKeyboardEvent(event); ++} ++ ++} // namespace WebKit +diff --git a/Source/WebKit/UIProcess/wpe/InspectorTargetProxyWPE.cpp b/Source/WebKit/UIProcess/wpe/InspectorTargetProxyWPE.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..7453194ca6f032ba86a4c67f5bf12688ab6ec1be +--- /dev/null ++++ b/Source/WebKit/UIProcess/wpe/InspectorTargetProxyWPE.cpp +@@ -0,0 +1,40 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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 "InspectorTargetProxy.h" ++ ++#include "WebPageProxy.h" ++#include ++ ++namespace WebKit { ++ ++void InspectorTargetProxy::platformActivate(String& error) const ++{ ++ struct wpe_view_backend* backend = m_page.viewBackend(); ++ wpe_view_backend_add_activity_state(backend, wpe_view_activity_state_visible | wpe_view_activity_state_focused | wpe_view_activity_state_in_window); ++} ++ ++} // namespace WebKit +diff --git a/Source/WebKit/UIProcess/wpe/WebPageInspectorEmulationAgentWPE.cpp b/Source/WebKit/UIProcess/wpe/WebPageInspectorEmulationAgentWPE.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..5dc76aa302cb574307059e66a1b73730efe920da +--- /dev/null ++++ b/Source/WebKit/UIProcess/wpe/WebPageInspectorEmulationAgentWPE.cpp +@@ -0,0 +1,41 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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 "WebPageInspectorEmulationAgent.h" ++ ++#include "WebPageProxy.h" ++#include ++ ++namespace WebKit { ++ ++void WebPageInspectorEmulationAgent::platformSetSize(int width, int height, Function&& callback) ++{ ++ struct wpe_view_backend* backend = m_page.viewBackend(); ++ wpe_view_backend_dispatch_set_size(backend, width, height); ++ callback(String()); ++} ++ ++} // namespace WebKit +diff --git a/Source/WebKit/UIProcess/wpe/WebPageInspectorInputAgentWPE.cpp b/Source/WebKit/UIProcess/wpe/WebPageInspectorInputAgentWPE.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..c3d7cacea987ba2b094d5022c670705ef6ced129 +--- /dev/null ++++ b/Source/WebKit/UIProcess/wpe/WebPageInspectorInputAgentWPE.cpp +@@ -0,0 +1,55 @@ ++/* ++ * Copyright (C) 2019 Microsoft Corporation. ++ * ++ * 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 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 "WebPageInspectorInputAgent.h" ++ ++#include "NativeWebKeyboardEvent.h" ++#include "WebPageProxy.h" ++#include ++#include ++ ++namespace WebKit { ++ ++void WebPageInspectorInputAgent::platformDispatchKeyEvent(WebKeyboardEvent::Type type, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool isAutoRepeat, bool isKeypad, bool isSystemKey, OptionSet modifiers, Vector& macCommands, WallTime timestamp) ++{ ++ NativeWebKeyboardEvent event( ++ type, ++ text, ++ unmodifiedText, ++ key, ++ code, ++ keyIdentifier, ++ windowsVirtualKeyCode, ++ nativeVirtualKeyCode, ++ isAutoRepeat, ++ isKeypad, ++ isSystemKey, ++ modifiers, ++ timestamp); ++ m_page.handleKeyboardEvent(event); ++} ++ ++} // namespace WebKit +diff --git a/Source/WebKit/WebKit.xcodeproj/project.pbxproj b/Source/WebKit/WebKit.xcodeproj/project.pbxproj +index 2512541c5ef9605706dd0741fb04235a1e300146..74d4a8d7bb0af66f0a203b951e0603e41a733be4 100644 +--- a/Source/WebKit/WebKit.xcodeproj/project.pbxproj ++++ b/Source/WebKit/WebKit.xcodeproj/project.pbxproj +@@ -1933,6 +1933,18 @@ + DF0C5F28252ECB8E00D921DB /* WKDownload.h in Headers */ = {isa = PBXBuildFile; fileRef = DF0C5F24252ECB8D00D921DB /* WKDownload.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DF0C5F2A252ECB8E00D921DB /* WKDownloadDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = DF0C5F26252ECB8E00D921DB /* WKDownloadDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DF0C5F2B252ED44000D921DB /* WKDownloadInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = DF0C5F25252ECB8E00D921DB /* WKDownloadInternal.h */; }; ++ D71A94322370E025002C4D9E /* InspectorPlaywrightAgentClientMac.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94302370E025002C4D9E /* InspectorPlaywrightAgentClientMac.h */; }; ++ D71A94342370E07A002C4D9E /* InspectorPlaywrightAgentClient.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94332370E07A002C4D9E /* InspectorPlaywrightAgentClient.h */; }; ++ D71A943A2370F061002C4D9E /* RemoteInspectorPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94392370F060002C4D9E /* RemoteInspectorPipe.h */; }; ++ D71A94422371F67E002C4D9E /* WebPageInspectorEmulationAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A943F2371F67E002C4D9E /* WebPageInspectorEmulationAgent.h */; }; ++ D71A94432371F67E002C4D9E /* WebPageInspectorInputAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94402371F67E002C4D9E /* WebPageInspectorInputAgent.h */; }; ++ D71A944A2372290B002C4D9E /* _WKBrowserInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A94492372290B002C4D9E /* _WKBrowserInspector.h */; settings = {ATTRIBUTES = (Private, ); }; }; ++ D71A944C237239FB002C4D9E /* BrowserInspectorPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = D71A944B237239FB002C4D9E /* BrowserInspectorPipe.h */; }; ++ D76D6888238DBD81008D314B /* InspectorDialogAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = D76D6887238DBD80008D314B /* InspectorDialogAgent.h */; }; ++ D79902B1236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = D79902AE236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm */; }; ++ D79902B2236E9404005D6F7E /* InspectorTargetProxyMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = D79902AF236E9404005D6F7E /* InspectorTargetProxyMac.mm */; }; ++ D79902B3236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = D79902B0236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm */; }; ++ D7EB04E72372A73B00F744CE /* InspectorPlaywrightAgentClientMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = D7EB04E62372A73B00F744CE /* InspectorPlaywrightAgentClientMac.mm */; }; + DF462E0F23F22F5500EFF35F /* WKHTTPCookieStorePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DF462E0E23F22F5300EFF35F /* WKHTTPCookieStorePrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; + DF462E1223F338BE00EFF35F /* WKContentWorldPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DF462E1123F338AD00EFF35F /* WKContentWorldPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; + DF84CEE4249AA24D009096F6 /* WKPDFHUDView.mm in Sources */ = {isa = PBXBuildFile; fileRef = DF84CEE2249AA21F009096F6 /* WKPDFHUDView.mm */; }; +@@ -1990,6 +2002,9 @@ + E5BEF6822130C48000F31111 /* WebDataListSuggestionsDropdownIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = E5BEF6802130C47F00F31111 /* WebDataListSuggestionsDropdownIOS.h */; }; + E5CB07DC20E1678F0022C183 /* WKFormColorControl.h in Headers */ = {isa = PBXBuildFile; fileRef = E5CB07DA20E1678F0022C183 /* WKFormColorControl.h */; }; + ED82A7F2128C6FAF004477B3 /* WKBundlePageOverlay.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A22F0FF1289FCD90085E74F /* WKBundlePageOverlay.h */; settings = {ATTRIBUTES = (Private, ); }; }; ++ F303B849249A8D640031DE5C /* ScreencastEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = F303B848249A8D3A0031DE5C /* ScreencastEncoder.h */; }; ++ F33C7AC7249AD79C0018BE41 /* libwebrtc.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F33C7AC6249AD79C0018BE41 /* libwebrtc.dylib */; }; ++ F3867F0A24607D4E008F0F31 /* InspectorScreencastAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = F3867F0424607D2B008F0F31 /* InspectorScreencastAgent.h */; }; + F4094CBD2553053D003D73E3 /* DisplayListReaderHandle.h in Headers */ = {isa = PBXBuildFile; fileRef = F4094CBB255304AF003D73E3 /* DisplayListReaderHandle.h */; }; + F4094CBE25530540003D73E3 /* DisplayListWriterHandle.h in Headers */ = {isa = PBXBuildFile; fileRef = F4094CB92553047E003D73E3 /* DisplayListWriterHandle.h */; }; + F409BA181E6E64BC009DA28E /* WKDragDestinationAction.h in Headers */ = {isa = PBXBuildFile; fileRef = F409BA171E6E64B3009DA28E /* WKDragDestinationAction.h */; settings = {ATTRIBUTES = (Private, ); }; }; +@@ -5750,6 +5765,19 @@ + DF0C5F24252ECB8D00D921DB /* WKDownload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKDownload.h; sourceTree = ""; }; + DF0C5F25252ECB8E00D921DB /* WKDownloadInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKDownloadInternal.h; sourceTree = ""; }; + DF0C5F26252ECB8E00D921DB /* WKDownloadDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKDownloadDelegate.h; sourceTree = ""; }; ++ D71A942C2370DF81002C4D9E /* WKBrowserInspector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKBrowserInspector.h; sourceTree = ""; }; ++ D71A94302370E025002C4D9E /* InspectorPlaywrightAgentClientMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorPlaywrightAgentClientMac.h; sourceTree = ""; }; ++ D71A94332370E07A002C4D9E /* InspectorPlaywrightAgentClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorPlaywrightAgentClient.h; sourceTree = ""; }; ++ D71A94392370F060002C4D9E /* RemoteInspectorPipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoteInspectorPipe.h; sourceTree = ""; }; ++ D71A943F2371F67E002C4D9E /* WebPageInspectorEmulationAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPageInspectorEmulationAgent.h; sourceTree = ""; }; ++ D71A94402371F67E002C4D9E /* WebPageInspectorInputAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPageInspectorInputAgent.h; sourceTree = ""; }; ++ D71A94492372290B002C4D9E /* _WKBrowserInspector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKBrowserInspector.h; sourceTree = ""; }; ++ D71A944B237239FB002C4D9E /* BrowserInspectorPipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BrowserInspectorPipe.h; sourceTree = ""; }; ++ D76D6887238DBD80008D314B /* InspectorDialogAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorDialogAgent.h; sourceTree = ""; }; ++ D79902AE236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebPageInspectorEmulationAgentMac.mm; sourceTree = ""; }; ++ D79902AF236E9404005D6F7E /* InspectorTargetProxyMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InspectorTargetProxyMac.mm; sourceTree = ""; }; ++ D79902B0236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebPageInspectorInputAgentMac.mm; sourceTree = ""; }; ++ D7EB04E62372A73B00F744CE /* InspectorPlaywrightAgentClientMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InspectorPlaywrightAgentClientMac.mm; sourceTree = ""; }; + DF462E0E23F22F5300EFF35F /* WKHTTPCookieStorePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKHTTPCookieStorePrivate.h; sourceTree = ""; }; + DF462E1123F338AD00EFF35F /* WKContentWorldPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKContentWorldPrivate.h; sourceTree = ""; }; + DF58C6311371AC5800F9A37C /* NativeWebWheelEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeWebWheelEvent.h; sourceTree = ""; }; +@@ -5864,6 +5892,14 @@ + ECA680D31E6904B500731D20 /* ExtraPrivateSymbolsForTAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExtraPrivateSymbolsForTAPI.h; sourceTree = ""; }; + ECBFC1DB1E6A4D66000300C7 /* ExtraPublicSymbolsForTAPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExtraPublicSymbolsForTAPI.h; sourceTree = ""; }; + F036978715F4BF0500C3A80E /* WebColorPicker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebColorPicker.cpp; sourceTree = ""; }; ++ F303B847249A8D3A0031DE5C /* ScreencastEncoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScreencastEncoder.cpp; sourceTree = ""; }; ++ F303B848249A8D3A0031DE5C /* ScreencastEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScreencastEncoder.h; sourceTree = ""; }; ++ F31E2DA424C76E4B004B2775 /* WebMFileWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebMFileWriter.cpp; sourceTree = ""; }; ++ F31E2DA524C76E4C004B2775 /* WebMFileWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebMFileWriter.h; sourceTree = ""; }; ++ F33C7AC6249AD79C0018BE41 /* libwebrtc.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; path = libwebrtc.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; ++ F3867F0324607D2B008F0F31 /* InspectorScreencastAgent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorScreencastAgent.cpp; sourceTree = ""; }; ++ F3867F0424607D2B008F0F31 /* InspectorScreencastAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorScreencastAgent.h; sourceTree = ""; }; ++ F3970344249BD4CE003E1A22 /* ScreencastEncoderMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ScreencastEncoderMac.mm; sourceTree = ""; }; + F4094CB92553047E003D73E3 /* DisplayListWriterHandle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DisplayListWriterHandle.h; sourceTree = ""; }; + F4094CBA2553047E003D73E3 /* DisplayListWriterHandle.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DisplayListWriterHandle.cpp; sourceTree = ""; }; + F4094CBB255304AF003D73E3 /* DisplayListReaderHandle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DisplayListReaderHandle.h; sourceTree = ""; }; +@@ -5969,6 +6005,7 @@ + 3766F9EF189A1244003CF19B /* QuartzCore.framework in Frameworks */, + 37694525184FC6B600CDE21F /* Security.framework in Frameworks */, + 37BEC4DD1948FC6A008B4286 /* WebCore.framework in Frameworks */, ++ F33C7AC7249AD79C0018BE41 /* libwebrtc.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +@@ -7789,6 +7826,7 @@ + 37C4C08318149C2A003688B9 /* Cocoa */ = { + isa = PBXGroup; + children = ( ++ D71A94492372290B002C4D9E /* _WKBrowserInspector.h */, + 1A43E826188F38E2009E4D30 /* Deprecated */, + 37A5E01218BBF937000A081E /* _WKActivatedElementInfo.h */, + 37A5E01118BBF937000A081E /* _WKActivatedElementInfo.mm */, +@@ -8830,6 +8868,7 @@ + isa = PBXGroup; + children = ( + 57A9FF15252C6AEF006A2040 /* libWTF.a */, ++ F33C7AC6249AD79C0018BE41 /* libwebrtc.dylib */, + 5750F32A2032D4E500389347 /* LocalAuthentication.framework */, + 570DAAB0230273D200E8FC04 /* NearField.framework */, + ); +@@ -9262,6 +9301,12 @@ + children = ( + 9197940423DBC4BB00257892 /* InspectorBrowserAgent.cpp */, + 9197940323DBC4BB00257892 /* InspectorBrowserAgent.h */, ++ F3867F0324607D2B008F0F31 /* InspectorScreencastAgent.cpp */, ++ F3867F0424607D2B008F0F31 /* InspectorScreencastAgent.h */, ++ F303B847249A8D3A0031DE5C /* ScreencastEncoder.cpp */, ++ F303B848249A8D3A0031DE5C /* ScreencastEncoder.h */, ++ F31E2DA424C76E4B004B2775 /* WebMFileWriter.cpp */, ++ F31E2DA524C76E4C004B2775 /* WebMFileWriter.h */, + ); + path = Agents; + sourceTree = ""; +@@ -9270,6 +9315,7 @@ + isa = PBXGroup; + children = ( + A5D3504D1D78F0D2005124A9 /* RemoteWebInspectorProxyMac.mm */, ++ F3970344249BD4CE003E1A22 /* ScreencastEncoderMac.mm */, + 1CA8B935127C774E00576C2B /* WebInspectorProxyMac.mm */, + 994BADF11F7D77EA00B571E7 /* WKInspectorViewController.h */, + 994BADF21F7D77EB00B571E7 /* WKInspectorViewController.mm */, +@@ -9754,6 +9800,12 @@ + BC032DC310F438260058C15A /* UIProcess */ = { + isa = PBXGroup; + children = ( ++ D76D6887238DBD80008D314B /* InspectorDialogAgent.h */, ++ D71A944B237239FB002C4D9E /* BrowserInspectorPipe.h */, ++ D71A943F2371F67E002C4D9E /* WebPageInspectorEmulationAgent.h */, ++ D71A94402371F67E002C4D9E /* WebPageInspectorInputAgent.h */, ++ D71A94392370F060002C4D9E /* RemoteInspectorPipe.h */, ++ D71A94332370E07A002C4D9E /* InspectorPlaywrightAgentClient.h */, + BC032DC410F4387C0058C15A /* API */, + 512F588D12A8836F00629530 /* Authentication */, + 9955A6E81C79809000EB6A93 /* Automation */, +@@ -10054,6 +10106,7 @@ + BC0C376610F807660076D7CB /* C */ = { + isa = PBXGroup; + children = ( ++ D71A942C2370DF81002C4D9E /* WKBrowserInspector.h */, + 5123CF18133D25E60056F800 /* cg */, + 6EE849C41368D9040038D481 /* mac */, + BCB63477116BF10600603215 /* WebKit2_C.h */, +@@ -10654,6 +10707,11 @@ + BCCF085C113F3B7500C650C5 /* mac */ = { + isa = PBXGroup; + children = ( ++ D7EB04E62372A73B00F744CE /* InspectorPlaywrightAgentClientMac.mm */, ++ D71A94302370E025002C4D9E /* InspectorPlaywrightAgentClientMac.h */, ++ D79902AE236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm */, ++ D79902B0236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm */, ++ D79902AF236E9404005D6F7E /* InspectorTargetProxyMac.mm */, + B878B613133428DC006888E9 /* CorrectionPanel.h */, + B878B614133428DC006888E9 /* CorrectionPanel.mm */, + C1817362205844A900DFDA65 /* DisplayLink.cpp */, +@@ -11465,6 +11523,7 @@ + 99788ACB1F421DDA00C08000 /* _WKAutomationSessionConfiguration.h in Headers */, + 990D28AC1C6420CF00986977 /* _WKAutomationSessionDelegate.h in Headers */, + 990D28B11C65208D00986977 /* _WKAutomationSessionInternal.h in Headers */, ++ D71A944A2372290B002C4D9E /* _WKBrowserInspector.h in Headers */, + 5C4609E7224317B4009943C2 /* _WKContentRuleListAction.h in Headers */, + 5C4609E8224317BB009943C2 /* _WKContentRuleListActionInternal.h in Headers */, + 1A5704F81BE01FF400874AF1 /* _WKContextMenuElementInfo.h in Headers */, +@@ -11764,6 +11823,7 @@ + 1A14F8E21D74C834006CBEC6 /* FrameInfoData.h in Headers */, + 1AE00D611831792100087DD7 /* FrameLoadState.h in Headers */, + 5C121E842410208D00486F9B /* FrameTreeNodeData.h in Headers */, ++ F303B849249A8D640031DE5C /* ScreencastEncoder.h in Headers */, + 2D4AF0892044C3C4006C8817 /* FrontBoardServicesSPI.h in Headers */, + CD78E1151DB7D7ED0014A2DE /* FullscreenClient.h in Headers */, + CD19D2EA2046406F0017074A /* FullscreenTouchSecheuristic.h in Headers */, +@@ -11779,6 +11839,7 @@ + 4614F13225DED875007006E7 /* GPUProcessConnectionParameters.h in Headers */, + F40BBB41257FF46E0067463A /* GPUProcessWakeupMessageArguments.h in Headers */, + 2DA049B8180CCD0A00AAFA9E /* GraphicsLayerCARemote.h in Headers */, ++ D71A94342370E07A002C4D9E /* InspectorPlaywrightAgentClient.h in Headers */, + C0CE72AD1247E78D00BC0EC4 /* HandleMessage.h in Headers */, + 1AC75A1B1B3368270056745B /* HangDetectionDisabler.h in Headers */, + 57AC8F50217FEED90055438C /* HidConnection.h in Headers */, +@@ -11925,8 +11986,10 @@ + 413075AC1DE85F370039EC69 /* NetworkRTCMonitor.h in Headers */, + 41DC45961E3D6E2200B11F51 /* NetworkRTCProvider.h in Headers */, + 5C20CBA01BB1ECD800895BB1 /* NetworkSession.h in Headers */, ++ D71A94422371F67E002C4D9E /* WebPageInspectorEmulationAgent.h in Headers */, + 532159551DBAE7290054AA3C /* NetworkSessionCocoa.h in Headers */, + 417915B92257046F00D6F97E /* NetworkSocketChannel.h in Headers */, ++ D71A943A2370F061002C4D9E /* RemoteInspectorPipe.h in Headers */, + 570DAAC22303730300E8FC04 /* NfcConnection.h in Headers */, + 570DAAAE23026F5C00E8FC04 /* NfcService.h in Headers */, + 31A2EC5614899C0900810D71 /* NotificationPermissionRequest.h in Headers */, +@@ -12009,6 +12072,7 @@ + BC1A7C581136E19C00FB7167 /* ProcessLauncher.h in Headers */, + 463FD4821EB94EC000A2982C /* ProcessTerminationReason.h in Headers */, + 86E67A251910B9D100004AB7 /* ProcessThrottler.h in Headers */, ++ D71A944C237239FB002C4D9E /* BrowserInspectorPipe.h in Headers */, + 83048AE61ACA45DC0082C832 /* ProcessThrottlerClient.h in Headers */, + A1E688701F6E2BAB007006A6 /* QuarantineSPI.h in Headers */, + 1A0C227E2451130A00ED614D /* QuickLookThumbnailingSoftLink.h in Headers */, +@@ -12335,6 +12399,7 @@ + A543E30D215C8A9000279CD9 /* WebPageInspectorTargetController.h in Headers */, + A543E307215AD13700279CD9 /* WebPageInspectorTargetFrontendChannel.h in Headers */, + C0CE72A11247E71D00BC0EC4 /* WebPageMessages.h in Headers */, ++ F3867F0A24607D4E008F0F31 /* InspectorScreencastAgent.h in Headers */, + 2D5C9D0619C81D8F00B3C5C1 /* WebPageOverlay.h in Headers */, + 46C392292316EC4D008EED9B /* WebPageProxyIdentifier.h in Headers */, + BCBD3915125BB1A800D2C29F /* WebPageProxyMessages.h in Headers */, +@@ -12465,6 +12530,7 @@ + BCD25F1711D6BDE100169B0E /* WKBundleFrame.h in Headers */, + BCF049E611FE20F600F86A58 /* WKBundleFramePrivate.h in Headers */, + BC49862F124D18C100D834E1 /* WKBundleHitTestResult.h in Headers */, ++ D71A94432371F67E002C4D9E /* WebPageInspectorInputAgent.h in Headers */, + BC204EF211C83EC8008F3375 /* WKBundleInitialize.h in Headers */, + 65B86F1E12F11DE300B7DD8A /* WKBundleInspector.h in Headers */, + 1A8B66B41BC45B010082DF77 /* WKBundleMac.h in Headers */, +@@ -12519,6 +12585,7 @@ + 5C795D71229F3757003FF1C4 /* WKContextMenuElementInfoPrivate.h in Headers */, + 51A555F6128C6C47009ABCEC /* WKContextMenuItem.h in Headers */, + 51A55601128C6D92009ABCEC /* WKContextMenuItemTypes.h in Headers */, ++ D76D6888238DBD81008D314B /* InspectorDialogAgent.h in Headers */, + A1EA02381DABFF7E0096021F /* WKContextMenuListener.h in Headers */, + BCC938E11180DE440085E5FE /* WKContextPrivate.h in Headers */, + 9FB5F395169E6A80002C25BF /* WKContextPrivateMac.h in Headers */, +@@ -12673,6 +12740,7 @@ + 1AB8A1F818400BB800E9AE69 /* WKPageContextMenuClient.h in Headers */, + 8372DB251A674C8F00C697C5 /* WKPageDiagnosticLoggingClient.h in Headers */, + 1AB8A1F418400B8F00E9AE69 /* WKPageFindClient.h in Headers */, ++ D71A94322370E025002C4D9E /* InspectorPlaywrightAgentClientMac.h in Headers */, + 1AB8A1F618400B9D00E9AE69 /* WKPageFindMatchesClient.h in Headers */, + 1AB8A1F018400B0000E9AE69 /* WKPageFormClient.h in Headers */, + BC7B633712A45ABA00D174A4 /* WKPageGroup.h in Headers */, +@@ -13846,6 +13914,7 @@ + C1A152D724E5A29A00978C8B /* HandleXPCEndpointMessages.mm in Sources */, + 2749F6442146561B008380BF /* InjectedBundleNodeHandle.cpp in Sources */, + 2749F6452146561E008380BF /* InjectedBundleRangeHandle.cpp in Sources */, ++ D79902B2236E9404005D6F7E /* InspectorTargetProxyMac.mm in Sources */, + A31F60A525CC7DB900AF14F4 /* IPCSemaphore.cpp in Sources */, + 9BF5EC642541145600984E77 /* JSIPCBinding.cpp in Sources */, + 2D913441212CF9F000128AFD /* JSNPMethod.cpp in Sources */, +@@ -13864,6 +13933,7 @@ + 2D92A781212B6A7100F493FD /* MessageReceiverMap.cpp in Sources */, + 2D92A782212B6A7100F493FD /* MessageSender.cpp in Sources */, + 2D92A77A212B6A6100F493FD /* Module.cpp in Sources */, ++ D79902B1236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm in Sources */, + 57B826452304F14000B72EB0 /* NearFieldSoftLink.mm in Sources */, + 2D913443212CF9F000128AFD /* NetscapeBrowserFuncs.cpp in Sources */, + 2D913444212CF9F000128AFD /* NetscapePlugin.cpp in Sources */, +@@ -13888,6 +13958,7 @@ + 1A2D8439127F65D5001EB962 /* NPObjectMessageReceiverMessageReceiver.cpp in Sources */, + 2D92A792212B6AD400F493FD /* NPObjectProxy.cpp in Sources */, + 2D92A793212B6AD400F493FD /* NPRemoteObjectMap.cpp in Sources */, ++ D7EB04E72372A73B00F744CE /* InspectorPlaywrightAgentClientMac.mm in Sources */, + 2D913447212CF9F000128AFD /* NPRuntimeObjectMap.cpp in Sources */, + 2D913448212CF9F000128AFD /* NPRuntimeUtilities.cpp in Sources */, + 2D92A794212B6AD400F493FD /* NPVariantData.cpp in Sources */, +@@ -14191,6 +14262,7 @@ + 2D92A78C212B6AB100F493FD /* WebMouseEvent.cpp in Sources */, + 31BA924D148831260062EDB5 /* WebNotificationManagerMessageReceiver.cpp in Sources */, + 2DF6FE52212E110900469030 /* WebPage.cpp in Sources */, ++ D79902B3236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm in Sources */, + C0CE72A01247E71D00BC0EC4 /* WebPageMessageReceiver.cpp in Sources */, + BCBD3914125BB1A800D2C29F /* WebPageProxyMessageReceiver.cpp in Sources */, + 7CE9CE101FA0767A000177DE /* WebPageUpdatePreferences.cpp in Sources */, +diff --git a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp +index 22ce092598f10da6c8c1e04637f620191c09ee62..ee8c7ddc5a38d3f6bcb373f42d7be524ec994bbf 100644 +--- a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp ++++ b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp +@@ -234,6 +234,11 @@ void WebLoaderStrategy::scheduleLoad(ResourceLoader& resourceLoader, CachedResou + } + #endif + ++ if (m_emulateOfflineState) { ++ scheduleInternallyFailedLoad(resourceLoader); ++ return; ++ } ++ + if (!tryLoadingUsingURLSchemeHandler(resourceLoader, trackingParameters)) { + WEBLOADERSTRATEGY_RELEASE_LOG_IF_ALLOWED("scheduleLoad: URL will be scheduled with the NetworkProcess"); + +@@ -294,7 +299,8 @@ static void addParametersShared(const Frame* frame, NetworkResourceLoadParameter + } + } + +-void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceLoader, const ResourceRequest& request, const WebResourceLoader::TrackingParameters& trackingParameters, bool shouldClearReferrerOnHTTPSToHTTPRedirect, Seconds maximumBufferingTime) ++// static ++bool WebLoaderStrategy::fillParametersForNetworkProcessLoad(ResourceLoader& resourceLoader, const ResourceRequest& request, const WebResourceLoader::TrackingParameters& trackingParameters, bool shouldClearReferrerOnHTTPSToHTTPRedirect, Seconds maximumBufferingTime, NetworkResourceLoadParameters& loadParameters) + { + ResourceLoadIdentifier identifier = resourceLoader.identifier(); + ASSERT(identifier); +@@ -307,7 +313,6 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL + + auto* frame = resourceLoader.frame(); + +- NetworkResourceLoadParameters loadParameters; + loadParameters.identifier = identifier; + loadParameters.webPageProxyID = trackingParameters.webPageProxyID; + loadParameters.webPageID = trackingParameters.pageID; +@@ -383,14 +388,11 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL + + if (loadParameters.options.mode != FetchOptions::Mode::Navigate) { + ASSERT(loadParameters.sourceOrigin); +- if (!loadParameters.sourceOrigin) { +- WEBLOADERSTRATEGY_RELEASE_LOG_ERROR_IF_ALLOWED("scheduleLoad: no sourceOrigin (priority=%d)", static_cast(resourceLoader.request().priority())); +- scheduleInternallyFailedLoad(resourceLoader); +- return; +- } ++ if (!loadParameters.sourceOrigin) ++ return false; + } + +- loadParameters.shouldRestrictHTTPResponseAccess = shouldPerformSecurityChecks(); ++ loadParameters.shouldRestrictHTTPResponseAccess = RuntimeEnabledFeatures::sharedFeatures().restrictedHTTPResponseAccess(); + + loadParameters.isMainFrameNavigation = resourceLoader.frame() && resourceLoader.frame()->isMainFrame() && resourceLoader.options().mode == FetchOptions::Mode::Navigate; + +@@ -406,6 +408,17 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL + } + + ASSERT((loadParameters.webPageID && loadParameters.webFrameID) || loadParameters.clientCredentialPolicy == ClientCredentialPolicy::CannotAskClientForCredentials); ++ return true; ++} ++ ++void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceLoader, const ResourceRequest& request, const WebResourceLoader::TrackingParameters& trackingParameters, bool shouldClearReferrerOnHTTPSToHTTPRedirect, Seconds maximumBufferingTime) ++{ ++ NetworkResourceLoadParameters loadParameters; ++ if (!fillParametersForNetworkProcessLoad(resourceLoader, request, trackingParameters, shouldClearReferrerOnHTTPSToHTTPRedirect, maximumBufferingTime, loadParameters)) { ++ WEBLOADERSTRATEGY_RELEASE_LOG_ERROR_IF_ALLOWED("scheduleLoad: no sourceOrigin (priority=%d)", static_cast(resourceLoader.request().priority())); ++ scheduleInternallyFailedLoad(resourceLoader); ++ return; ++ } + + WEBLOADERSTRATEGY_RELEASE_LOG_IF_ALLOWED("scheduleLoad: Resource is being scheduled with the NetworkProcess (priority=%d)", static_cast(resourceLoader.request().priority())); + if (!WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::ScheduleResourceLoad(loadParameters), 0)) { +@@ -417,7 +430,7 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL + } + + auto loader = WebResourceLoader::create(resourceLoader, trackingParameters); +- m_webResourceLoaders.set(identifier, WTFMove(loader)); ++ m_webResourceLoaders.set(resourceLoader.identifier(), WTFMove(loader)); + } + + void WebLoaderStrategy::scheduleInternallyFailedLoad(WebCore::ResourceLoader& resourceLoader) +@@ -815,7 +828,7 @@ void WebLoaderStrategy::didFinishPreconnection(uint64_t preconnectionIdentifier, + + bool WebLoaderStrategy::isOnLine() const + { +- return m_isOnLine; ++ return m_emulateOfflineState ? false : m_isOnLine; + } + + void WebLoaderStrategy::addOnlineStateChangeListener(Function&& listener) +@@ -835,6 +848,11 @@ void WebLoaderStrategy::isResourceLoadFinished(CachedResource& resource, Complet + + void WebLoaderStrategy::setOnLineState(bool isOnLine) + { ++ if (m_emulateOfflineState) { ++ m_isOnLine = isOnLine; ++ return; ++ } ++ + if (m_isOnLine == isOnLine) + return; + +@@ -843,6 +861,12 @@ void WebLoaderStrategy::setOnLineState(bool isOnLine) + listener(isOnLine); + } + ++void WebLoaderStrategy::setEmulateOfflineState(bool offline) { ++ m_emulateOfflineState = offline; ++ for (auto& listener : m_onlineStateChangeListeners) ++ listener(offline ? false : m_isOnLine); ++} ++ + void WebLoaderStrategy::setCaptureExtraNetworkLoadMetricsEnabled(bool enabled) + { + WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::SetCaptureExtraNetworkLoadMetricsEnabled(enabled), 0); +diff --git a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h +index b23d5b8a9f72696f33a1e0b7778ffbf8ec21049c..1a778a275d7b1a3338328abb91ef70f39e5aeed7 100644 +--- a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h ++++ b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h +@@ -40,6 +40,7 @@ struct FetchOptions; + namespace WebKit { + + class NetworkProcessConnection; ++class NetworkResourceLoadParameters; + class WebFrame; + class WebPage; + class WebURLSchemeTaskProxy; +@@ -88,8 +89,10 @@ public: + bool isOnLine() const final; + void addOnlineStateChangeListener(Function&&) final; + void setOnLineState(bool); ++ void setEmulateOfflineState(bool) final; + + static uint64_t generateLoadIdentifier(); ++ static bool fillParametersForNetworkProcessLoad(WebCore::ResourceLoader&, const WebCore::ResourceRequest&, const WebResourceLoader::TrackingParameters&, bool shouldClearReferrerOnHTTPSToHTTPRedirect, Seconds maximumBufferingTime, NetworkResourceLoadParameters&); + + private: + void scheduleLoad(WebCore::ResourceLoader&, WebCore::CachedResource*, bool shouldClearReferrerOnHTTPSToHTTPRedirect); +@@ -134,6 +137,7 @@ private: + HashMap m_preconnectCompletionHandlers; + Vector> m_onlineStateChangeListeners; + bool m_isOnLine { true }; ++ bool m_emulateOfflineState { false }; + }; + + } // namespace WebKit +diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp +index a5770daa4dd4cbb35e8c3cbf5cff7d16c6648366..b5f00b44bcc0e5a22530930e2dfb01862b18310f 100644 +--- a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp ++++ b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp +@@ -397,6 +397,8 @@ void WebChromeClient::setResizable(bool resizable) + + void WebChromeClient::addMessageToConsole(MessageSource source, MessageLevel level, const String& message, unsigned lineNumber, unsigned columnNumber, const String& sourceID) + { ++ if (level == MessageLevel::Error) ++ m_page.send(Messages::WebPageProxy::LogToStderr(message)); + // Notify the bundle client. + m_page.injectedBundleUIClient().willAddMessageToConsole(&m_page, source, level, message, lineNumber, columnNumber, sourceID); + } +@@ -827,6 +829,13 @@ std::unique_ptr WebChromeClient::createDateTimeChooser(DateTime + + #endif + ++#if ENABLE(ORIENTATION_EVENTS) && !PLATFORM(IOS_FAMILY) ++int WebChromeClient::deviceOrientation() const { ++ // Only overrides are supported for non-iOS platforms. ++ return 0; ++} ++#endif ++ + void WebChromeClient::runOpenPanel(Frame& frame, FileChooser& fileChooser) + { + if (m_page.activeOpenPanelResultListener()) +diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebDragClient.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebDragClient.cpp +index 2eb0886f13ed035a53b8eaa60605de4dfe53fbe3..c46393209cb4f80704bbc9268fad4371347d5b30 100644 +--- a/Source/WebKit/WebProcess/WebCoreSupport/WebDragClient.cpp ++++ b/Source/WebKit/WebProcess/WebCoreSupport/WebDragClient.cpp +@@ -29,6 +29,13 @@ + #if ENABLE(DRAG_SUPPORT) + + #include "WebPage.h" ++#include ++#include ++#include "ShareableBitmap.h" ++ ++#if PLATFORM(WPE) ++#include "ArgumentCodersWPE.h" ++#endif + + namespace WebKit { + using namespace WebCore; +@@ -50,7 +57,7 @@ OptionSet WebDragClient::dragSourceActionMaskForPoint(const In + return m_page->allowedDragSourceActions(); + } + +-#if !PLATFORM(COCOA) && !PLATFORM(GTK) ++#if !PLATFORM(COCOA) && !PLATFORM(GTK) && !PLATFORM(WPE) && !PLATFORM(WIN) + void WebDragClient::startDrag(DragItem, DataTransfer&, Frame&) + { + } +diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp +index 36512025eceacdd355affc59dee14fdd3b707fe0..9fc9f66e2d693ce0577087d514f07cd62ffffae2 100644 +--- a/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp ++++ b/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp +@@ -1561,13 +1561,6 @@ void WebFrameLoaderClient::transitionToCommittedForNewPage() + if (webPage->scrollPinningBehavior() != DoNotPin) + view->setScrollPinningBehavior(webPage->scrollPinningBehavior()); + +-#if USE(COORDINATED_GRAPHICS) +- if (shouldUseFixedLayout) { +- view->setDelegatesScrolling(shouldUseFixedLayout); +- view->setPaintsEntireContents(shouldUseFixedLayout); +- return; +- } +-#endif + } + + void WebFrameLoaderClient::didRestoreFromBackForwardCache() +diff --git a/Source/WebKit/WebProcess/WebCoreSupport/mac/WebDragClientMac.mm b/Source/WebKit/WebProcess/WebCoreSupport/mac/WebDragClientMac.mm +index 6023ce78f840bdcd39b6637a84ba4f84308b1d9b..c93e1bd0c7bdbea6b288c943befc5ff16f41704e 100644 +--- a/Source/WebKit/WebProcess/WebCoreSupport/mac/WebDragClientMac.mm ++++ b/Source/WebKit/WebProcess/WebCoreSupport/mac/WebDragClientMac.mm +@@ -129,7 +129,8 @@ static WebCore::CachedImage* cachedImage(Element& element) + void WebDragClient::declareAndWriteDragImage(const String& pasteboardName, Element& element, const URL& url, const String& label, Frame*) + { + ALLOW_DEPRECATED_DECLARATIONS_BEGIN +- ASSERT(pasteboardName == String(NSDragPboard)); ++ if (pasteboardName != String(NSDragPboard)) ++ return; + ALLOW_DEPRECATED_DECLARATIONS_END + + WebCore::CachedImage* image = cachedImage(element); +diff --git a/Source/WebKit/WebProcess/WebCoreSupport/win/WebDragClientWin.cpp b/Source/WebKit/WebProcess/WebCoreSupport/win/WebDragClientWin.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..2606914d22e85affd9b2f71c361c9db3a14da4f3 +--- /dev/null ++++ b/Source/WebKit/WebProcess/WebCoreSupport/win/WebDragClientWin.cpp +@@ -0,0 +1,58 @@ ++/* ++ * 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. ++ * ++ * 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 "WebDragClient.h" ++ ++#if ENABLE(DRAG_SUPPORT) ++ ++//#include "ArgumentCodersWPE.h" ++#include "ShareableBitmap.h" ++#include "WebPage.h" ++#include "WebPageProxyMessages.h" ++#include ++#include ++#include ++#include ++#include ++ ++//#include ++ ++namespace WebKit { ++using namespace WebCore; ++ ++void WebDragClient::didConcludeEditDrag() ++{ ++} ++ ++void WebDragClient::startDrag(DragItem, DataTransfer& dataTransfer, Frame& frame) ++{ ++ m_page->willStartDrag(); ++ m_page->send(Messages::WebPageProxy::StartDrag(dataTransfer.pasteboard().createDragDataMap())); ++} ++ ++}; // namespace WebKit. ++ ++#endif // ENABLE(DRAG_SUPPORT) +diff --git a/Source/WebKit/WebProcess/WebCoreSupport/wpe/WebDragClientWPE.cpp b/Source/WebKit/WebProcess/WebCoreSupport/wpe/WebDragClientWPE.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..9b413bb8150a1633d29b6e2606127c9c1d02442b +--- /dev/null ++++ b/Source/WebKit/WebProcess/WebCoreSupport/wpe/WebDragClientWPE.cpp +@@ -0,0 +1,57 @@ ++/* ++ * 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. ++ * ++ * 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 "WebDragClient.h" ++ ++#if ENABLE(DRAG_SUPPORT) ++ ++#include "ArgumentCodersWPE.h" ++#include "ShareableBitmap.h" ++#include "WebPage.h" ++#include "WebPageProxyMessages.h" ++#include ++#include ++#include ++#include ++ ++namespace WebKit { ++using namespace WebCore; ++ ++void WebDragClient::didConcludeEditDrag() ++{ ++} ++ ++void WebDragClient::startDrag(DragItem, DataTransfer& dataTransfer, Frame&) ++{ ++ m_page->willStartDrag(); ++ ++ ShareableBitmap::Handle handle; ++ m_page->send(Messages::WebPageProxy::StartDrag(dataTransfer.pasteboard().selectionData(), dataTransfer.sourceOperationMask(), handle)); ++} ++ ++}; // namespace WebKit. ++ ++#endif // ENABLE(DRAG_SUPPORT) +diff --git a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp +index 974427b3de2805d13d631efe1e47c20923952938..6c91d586eaa69aa57a010a46d491716bf669aa2e 100644 +--- a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp ++++ b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp +@@ -36,7 +36,9 @@ + #include "WebPageCreationParameters.h" + #include "WebPreferencesKeys.h" + #include ++#include + #include ++#include + #include + #include + #include +@@ -122,6 +124,16 @@ void DrawingAreaCoordinatedGraphics::scroll(const IntRect& scrollRect, const Int + ASSERT(m_scrollRect.isEmpty()); + ASSERT(m_scrollOffset.isEmpty()); + ASSERT(m_dirtyRegion.isEmpty()); ++// Playwright begin ++#if !PLATFORM(WIN) ++ if (m_webPage.mainFrameView() && m_webPage.mainFrameView()->useFixedLayout()) { ++ IntRect visibleRect = IntRect(m_layerTreeHost->viewportController().visibleContentsRect()); ++ visibleRect.move(-scrollDelta.width(), -scrollDelta.height()); ++ m_layerTreeHost->scrollNonCompositedContents(visibleRect); ++ return; ++ } ++#endif ++// Playwright end + m_layerTreeHost->scrollNonCompositedContents(scrollRect); + return; + } +@@ -252,6 +264,7 @@ void DrawingAreaCoordinatedGraphics::updatePreferences(const WebPreferencesStore + settings.setAcceleratedCompositingEnabled(false); + } + #endif ++ + settings.setForceCompositingMode(store.getBoolValueForKey(WebPreferencesKey::forceCompositingModeKey())); + // Fixed position elements need to be composited and create stacking contexts + // in order to be scrolled by the ScrollingCoordinator. +@@ -626,6 +639,11 @@ void DrawingAreaCoordinatedGraphics::enterAcceleratedCompositingMode(GraphicsLay + m_scrollOffset = IntSize(); + m_displayTimer.stop(); + m_isWaitingForDidUpdate = false; ++// Playwright begin ++#if PLATFORM(WIN) ++ didChangeAcceleratedCompositingMode(true); ++#endif ++// Playwright end + } + + void DrawingAreaCoordinatedGraphics::exitAcceleratedCompositingMode() +@@ -675,6 +693,11 @@ void DrawingAreaCoordinatedGraphics::exitAcceleratedCompositingMode() + // UI process, we still need to let it know about the new contents, so send an Update message. + send(Messages::DrawingAreaProxy::Update(m_backingStoreStateID, updateInfo)); + } ++// Playwright begin ++#if PLATFORM(WIN) ++ didChangeAcceleratedCompositingMode(false); ++#endif ++// Playwright end + } + + void DrawingAreaCoordinatedGraphics::scheduleDisplay() +diff --git a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp +index 407f4f3fb1fc69a6be366a4a5fb37b3dd4bb2252..ee32e49c7bee97bf4269df1d8e7599edf4a7f1ff 100644 +--- a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp ++++ b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp +@@ -166,8 +166,16 @@ void LayerTreeHost::setViewOverlayRootLayer(GraphicsLayer* viewOverlayRootLayer) + void LayerTreeHost::scrollNonCompositedContents(const IntRect& rect) + { + auto* frameView = m_webPage.mainFrameView(); ++ ++// Playwright begin ++#if PLATFORM(WIN) + if (!frameView || !frameView->delegatesScrolling()) ++ return ++#else ++ if (!frameView) + return; ++#endif ++// Playwright end + + m_viewportController.didScroll(rect.location()); + if (m_isDiscardable) +@@ -286,6 +294,10 @@ void LayerTreeHost::didChangeViewport() + + if (!view->useFixedLayout()) + view->notifyScrollPositionChanged(m_lastScrollPosition); ++// Playwright begin ++ else ++ m_viewportController.didScroll(m_lastScrollPosition); ++// Playwright end + } + + if (m_lastPageScaleFactor != pageScale) { +diff --git a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.h b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.h +index 6727d16c8c0b86c15ff31af038aa9d7588527545..b9b3c242375c7a8849d973298d680acffbbdd024 100644 +--- a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.h ++++ b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.h +@@ -97,7 +97,11 @@ public: + RefPtr createDisplayRefreshMonitor(WebCore::PlatformDisplayID); + + WebCore::PlatformDisplayID displayID() const { return m_displayID; } +- ++// Playwright begin ++#if USE(COORDINATED_GRAPHICS) ++ const SimpleViewportController& viewportController() const { return m_viewportController; } ++#endif ++// Playwright end + private: + #if USE(COORDINATED_GRAPHICS) + void layerFlushTimerFired(); +diff --git a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHostTextureMapper.cpp b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHostTextureMapper.cpp +index 8444a454c603c671a6813a445550b40761e7fd84..c5cc0d6092c500f0f0bf63700ada1e86bb93346b 100644 +--- a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHostTextureMapper.cpp ++++ b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHostTextureMapper.cpp +@@ -29,6 +29,7 @@ + + #if USE(GRAPHICS_LAYER_TEXTURE_MAPPER) + ++#include "DrawingArea.h" + #include "WebPage.h" + #include + #include +diff --git a/Source/WebKit/WebProcess/WebPage/DrawingArea.cpp b/Source/WebKit/WebProcess/WebPage/DrawingArea.cpp +index af312d719a2241a2390aa861680ee9fd4d48eaa7..d5a54187d0e6e25d77a08a258a033e3aa81de8c0 100644 +--- a/Source/WebKit/WebProcess/WebPage/DrawingArea.cpp ++++ b/Source/WebKit/WebProcess/WebPage/DrawingArea.cpp +@@ -27,6 +27,7 @@ + #include "DrawingArea.h" + + #include "DrawingAreaMessages.h" ++#include "DrawingAreaProxyMessages.h" + #include "WebPage.h" + #include "WebPageCreationParameters.h" + #include "WebProcess.h" +@@ -89,6 +90,13 @@ RefPtr DrawingArea::createDisplayRefreshMonitor( + } + #endif + ++#if PLATFORM(WIN) ++void DrawingArea::didChangeAcceleratedCompositingMode(bool enabled) ++{ ++ send(Messages::DrawingAreaProxy::DidChangeAcceleratedCompositingMode(enabled)); ++} ++#endif ++ + void DrawingArea::removeMessageReceiverIfNeeded() + { + if (m_hasRemovedMessageReceiver) +diff --git a/Source/WebKit/WebProcess/WebPage/DrawingArea.h b/Source/WebKit/WebProcess/WebPage/DrawingArea.h +index 64d5329b86608bc02d467cd43ecdef72b54a271e..a83412d42e6d0622cc58dc5413bfc22072514bb9 100644 +--- a/Source/WebKit/WebProcess/WebPage/DrawingArea.h ++++ b/Source/WebKit/WebProcess/WebPage/DrawingArea.h +@@ -145,6 +145,9 @@ public: + virtual void didChangeViewportAttributes(WebCore::ViewportAttributes&&) = 0; + virtual void deviceOrPageScaleFactorChanged() = 0; + #endif ++#if PLATFORM(WIN) ++ void didChangeAcceleratedCompositingMode(bool enabled); ++#endif + + virtual void adoptLayersFromDrawingArea(DrawingArea&) { } + virtual void adoptDisplayRefreshMonitorsFromDrawingArea(DrawingArea&) { } +diff --git a/Source/WebKit/WebProcess/WebPage/WebCookieJar.cpp b/Source/WebKit/WebProcess/WebPage/WebCookieJar.cpp +index a75588b5d2a541bf47cae34b0aabe18651d719bd..0826607f42e566652050273192561487bd151bb1 100644 +--- a/Source/WebKit/WebProcess/WebPage/WebCookieJar.cpp ++++ b/Source/WebKit/WebProcess/WebPage/WebCookieJar.cpp +@@ -28,15 +28,19 @@ + + #include "NetworkConnectionToWebProcessMessages.h" + #include "NetworkProcessConnection.h" ++#include "NetworkResourceLoadParameters.h" + #include "WebFrame.h" ++#include "WebLoaderStrategy.h" + #include "WebPage.h" + #include "WebProcess.h" ++#include "WebResourceLoader.h" + #include + #include + #include + #include + #include + #include ++#include + #include + #include + +@@ -255,4 +259,22 @@ void WebCookieJar::deleteCookie(const WebCore::Document& document, const URL& ur + WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::DeleteCookie(url, cookieName), 0); + } + ++void WebCookieJar::setCookieFromResponse(ResourceLoader& loader, const String& setCookieValue) ++{ ++ auto* webFrame = WebFrame::fromCoreFrame(*loader.frame()); ++ ++ WebResourceLoader::TrackingParameters trackingParameters; ++ trackingParameters.webPageProxyID = webFrame->page()->webPageProxyIdentifier(); ++ trackingParameters.pageID = webFrame->page()->identifier(); ++ trackingParameters.frameID = webFrame->frameID(); ++ trackingParameters.resourceID = loader.identifier(); ++ ++ NetworkResourceLoadParameters loadParameters; ++ if (!WebLoaderStrategy::fillParametersForNetworkProcessLoad(loader, loader.request(), trackingParameters, true, 0_s, loadParameters)) ++ return; ++ ++ URL mainDocumentURL = loader.frame()->document()->topDocument().url(); ++ WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::SetCookieFromResponse(loadParameters, mainDocumentURL, setCookieValue), 0); ++} ++ + } // namespace WebKit +diff --git a/Source/WebKit/WebProcess/WebPage/WebCookieJar.h b/Source/WebKit/WebProcess/WebPage/WebCookieJar.h +index 70f87ac8b194b220c285cdb20ed8ceffd7eca28c..b935a85eeb1822a7cdb523efb1805300ec3da7d4 100644 +--- a/Source/WebKit/WebProcess/WebPage/WebCookieJar.h ++++ b/Source/WebKit/WebProcess/WebPage/WebCookieJar.h +@@ -52,6 +52,8 @@ public: + void cookiesDeleted(const String& host, const Vector&); + void allCookiesDeleted(); + ++ void setCookieFromResponse(WebCore::ResourceLoader&, const String& setCookieValue); ++ + private: + WebCookieJar(); + +diff --git a/Source/WebKit/WebProcess/WebPage/WebDocumentLoader.cpp b/Source/WebKit/WebProcess/WebPage/WebDocumentLoader.cpp +index b2d54a627b94583bda3518c4e7c3364481b605a4..d407e32b6a7b8b27925c49391e86d42c9b3dfa8b 100644 +--- a/Source/WebKit/WebProcess/WebPage/WebDocumentLoader.cpp ++++ b/Source/WebKit/WebProcess/WebPage/WebDocumentLoader.cpp +@@ -47,6 +47,14 @@ void WebDocumentLoader::detachFromFrame() + DocumentLoader::detachFromFrame(); + } + ++void WebDocumentLoader::replacedByFragmentNavigation(Frame& frame) ++{ ++ ASSERT(!this->frame()); ++ // Notify WebPageProxy that the navigation has been converted into same page navigation. ++ if (m_navigationID) ++ WebFrame::fromCoreFrame(frame)->documentLoaderDetached(m_navigationID); ++} ++ + void WebDocumentLoader::setNavigationID(uint64_t navigationID) + { + ASSERT(navigationID); +diff --git a/Source/WebKit/WebProcess/WebPage/WebDocumentLoader.h b/Source/WebKit/WebProcess/WebPage/WebDocumentLoader.h +index f127d64d005ab7b93875591b94a5899205e91579..df0de26e4dc449a0fbf93e7037444df4e5365822 100644 +--- a/Source/WebKit/WebProcess/WebPage/WebDocumentLoader.h ++++ b/Source/WebKit/WebProcess/WebPage/WebDocumentLoader.h +@@ -43,7 +43,10 @@ public: + private: + WebDocumentLoader(const WebCore::ResourceRequest&, const WebCore::SubstituteData&); + ++ uint64_t loaderIDForInspector() override { return navigationID(); } ++ + void detachFromFrame() override; ++ void replacedByFragmentNavigation(WebCore::Frame&) override; + + uint64_t m_navigationID; + }; +diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.cpp b/Source/WebKit/WebProcess/WebPage/WebPage.cpp +index a958d48f4c9c9f67f668cd7e71fdc232c5a6807f..55fd4b734332e5a58c174b570fe3a10e474c82b6 100644 +--- a/Source/WebKit/WebProcess/WebPage/WebPage.cpp ++++ b/Source/WebKit/WebProcess/WebPage/WebPage.cpp +@@ -868,6 +868,9 @@ WebPage::WebPage(PageIdentifier pageID, WebPageCreationParameters&& parameters) + + m_page->setCanUseCredentialStorage(parameters.canUseCredentialStorage); + ++ if (parameters.shouldPauseInInspectorWhenShown) ++ m_page->inspectorController().pauseWhenShown(); ++ + updateThrottleState(); + } + +@@ -1636,6 +1639,22 @@ void WebPage::platformDidReceiveLoadParameters(const LoadParameters& loadParamet + } + #endif + ++void WebPage::loadRequestInFrameForInspector(LoadParameters&& loadParameters, WebCore::FrameIdentifier frameID) ++{ ++ WebFrame* frame = WebProcess::singleton().webFrame(frameID); ++ if (!frame) { ++ send(Messages::WebPageProxy::DidDestroyNavigation(loadParameters.navigationID)); ++ return; ++ } ++ ++ // FIXME: use m_pendingNavigationID instead? ++ m_pendingFrameNavigationID = loadParameters.navigationID; ++ ++ FrameLoadRequest frameLoadRequest { *frame->coreFrame(), loadParameters.request }; ++ frame->coreFrame()->loader().load(WTFMove(frameLoadRequest)); ++ ASSERT(!m_pendingFrameNavigationID); ++} ++ + void WebPage::loadRequest(LoadParameters&& loadParameters) + { + setLastNavigationWasAppBound(loadParameters.request.isAppBound()); +@@ -1896,17 +1915,13 @@ void WebPage::setSize(const WebCore::IntSize& viewSize) + view->resize(viewSize); + m_drawingArea->setNeedsDisplay(); + +-#if USE(COORDINATED_GRAPHICS) + if (view->useFixedLayout()) + sendViewportAttributesChanged(m_page->viewportArguments()); +-#endif + } + +-#if USE(COORDINATED_GRAPHICS) + void WebPage::sendViewportAttributesChanged(const ViewportArguments& viewportArguments) + { +- FrameView* view = m_page->mainFrame().view(); +- ASSERT(view && view->useFixedLayout()); ++ ASSERT(m_page->mainFrame().view() && m_page->mainFrame().view()->useFixedLayout()); + + // Viewport properties have no impact on zero sized fixed viewports. + if (m_viewSize.isEmpty()) +@@ -1923,20 +1938,18 @@ void WebPage::sendViewportAttributesChanged(const ViewportArguments& viewportArg + + ViewportAttributes attr = computeViewportAttributes(viewportArguments, minimumLayoutFallbackWidth, deviceWidth, deviceHeight, 1, m_viewSize); + +- // If no layout was done yet set contentFixedOrigin to (0,0). +- IntPoint contentFixedOrigin = view->didFirstLayout() ? view->fixedVisibleContentRect().location() : IntPoint(); +- +- // Put the width and height to the viewport width and height. In css units however. +- // Use FloatSize to avoid truncated values during scale. +- FloatSize contentFixedSize = m_viewSize; +- +- contentFixedSize.scale(1 / attr.initialScale); +- view->setFixedVisibleContentRect(IntRect(contentFixedOrigin, roundedIntSize(contentFixedSize))); ++#if ENABLE(CSS_DEVICE_ADAPTATION) ++ FrameView* view = m_page->mainFrame().view(); ++ // CSS viewport descriptors might be applied to already affected viewport size ++ // if the page enables/disables stylesheets, so need to keep initial viewport size. ++ view->setInitialViewportSize(roundedIntSize(m_viewSize)); ++#endif + + attr.initialScale = m_page->viewportArguments().zoom; // Resets auto (-1) if no value was set by user. + + // This also takes care of the relayout. + setFixedLayoutSize(roundedIntSize(attr.layoutSize)); ++ scaleView(deviceWidth / attr.layoutSize.width()); + + #if USE(COORDINATED_GRAPHICS) + m_drawingArea->didChangeViewportAttributes(WTFMove(attr)); +@@ -1944,7 +1957,6 @@ void WebPage::sendViewportAttributesChanged(const ViewportArguments& viewportArg + send(Messages::WebPageProxy::DidChangeViewportProperties(attr)); + #endif + } +-#endif + + void WebPage::scrollMainFrameIfNotAtMaxScrollPosition(const IntSize& scrollOffset) + { +@@ -2243,6 +2255,7 @@ void WebPage::scaleView(double scale) + } + + m_page->setViewScaleFactor(scale); ++ send(Messages::WebPageProxy::ViewScaleFactorDidChange(scale)); + scalePage(pageScale, scrollPositionAtNewScale); + } + +@@ -2347,17 +2360,13 @@ void WebPage::viewportPropertiesDidChange(const ViewportArguments& viewportArgum + viewportConfigurationChanged(); + #endif + +-#if USE(COORDINATED_GRAPHICS) + FrameView* view = m_page->mainFrame().view(); + if (view && view->useFixedLayout()) + sendViewportAttributesChanged(viewportArguments); ++#if USE(COORDINATED_GRAPHICS) + else + m_drawingArea->didChangeViewportAttributes(ViewportAttributes()); + #endif +- +-#if !PLATFORM(IOS_FAMILY) && !USE(COORDINATED_GRAPHICS) +- UNUSED_PARAM(viewportArguments); +-#endif + } + + void WebPage::listenForLayoutMilestones(OptionSet milestones) +@@ -3214,6 +3223,104 @@ void WebPage::touchEvent(const WebTouchEvent& touchEvent) + + send(Messages::WebPageProxy::DidReceiveEvent(static_cast(touchEvent.type()), handled)); + } ++ ++void WebPage::fakeTouchTap(const WebCore::IntPoint& position, uint8_t modifiers, CompletionHandler&& completionHandler) ++{ ++ SetForScope userIsInteractingChange { m_userIsInteracting, true }; ++ ++ bool handled = false; ++ ++ uint32_t id = 0; ++ float radiusX = 1.0; ++ float radiusY = 1.0; ++ float rotationAngle = 0.0; ++ float force = 1.0; ++ const WebCore::IntSize radius(radiusX,radiusY); ++ const WebCore::IntPoint screenPosition = position; ++ OptionSet eventModifiers; ++ eventModifiers = eventModifiers.fromRaw(modifiers); ++ ++ { ++ Vector touchPoints; ++ WebPlatformTouchPoint::TouchPointState state = WebPlatformTouchPoint::TouchPointState::TouchPressed; ++ touchPoints.append(WebPlatformTouchPoint(id, state, screenPosition, position, radius, rotationAngle, force)); ++ ++ WebTouchEvent touchEvent(WebEvent::TouchStart, WTFMove(touchPoints), eventModifiers, WallTime::now()); ++ ++ CurrentEvent currentEvent(touchEvent); ++ handled = handleTouchEvent(touchEvent, m_page.get()); ++ } ++ { ++ Vector touchPoints; ++ WebPlatformTouchPoint::TouchPointState state = WebPlatformTouchPoint::TouchPointState::TouchReleased; ++ touchPoints.append(WebPlatformTouchPoint(id, state, screenPosition, position, radius, rotationAngle, force)); ++ ++ WebTouchEvent touchEvent(WebEvent::TouchEnd, WTFMove(touchPoints), eventModifiers, WallTime::now()); ++ ++ CurrentEvent currentEvent(touchEvent); ++ handled = handleTouchEvent(touchEvent, m_page.get()) || handled; ++ } ++ if (!handled) { ++ FloatPoint adjustedPoint; ++ Node* nodeRespondingToClick = m_page->mainFrame().nodeRespondingToClickEvents(position, adjustedPoint); ++ Frame* frameRespondingToClick = nodeRespondingToClick ? nodeRespondingToClick->document().frame() : nullptr; ++ IntPoint adjustedIntPoint = roundedIntPoint(adjustedPoint); ++ if (!frameRespondingToClick) { ++ completionHandler(); ++ return; ++ } ++ bool shiftKey = eventModifiers.contains(WebEvent::Modifier::ShiftKey); ++ bool ctrlKey = eventModifiers.contains(WebEvent::Modifier::ControlKey); ++ bool altKey = eventModifiers.contains(WebEvent::Modifier::AltKey); ++ bool metaKey = eventModifiers.contains(WebEvent::Modifier::MetaKey); ++ double force = 0.0; ++ SyntheticClickType syntheticClickType = SyntheticClickType::OneFingerTap; ++ ++ m_page->mainFrame().eventHandler().mouseMoved(PlatformMouseEvent( ++ adjustedIntPoint, ++ adjustedIntPoint, ++ MouseButton::NoButton, ++ PlatformEvent::Type::MouseMoved, ++ 0, ++ shiftKey, ++ ctrlKey, ++ altKey, ++ metaKey, ++ WallTime::now(), ++ force, ++ syntheticClickType ++ )); ++ m_page->mainFrame().eventHandler().handleMousePressEvent(PlatformMouseEvent( ++ adjustedIntPoint, ++ adjustedIntPoint, ++ MouseButton::LeftButton, ++ PlatformEvent::Type::MousePressed, ++ 1, ++ shiftKey, ++ ctrlKey, ++ altKey, ++ metaKey, ++ WallTime::now(), ++ force, ++ syntheticClickType ++ )); ++ m_page->mainFrame().eventHandler().handleMouseReleaseEvent(PlatformMouseEvent( ++ adjustedIntPoint, ++ adjustedIntPoint, ++ MouseButton::LeftButton, ++ PlatformEvent::Type::MouseReleased, ++ 1, ++ shiftKey, ++ ctrlKey, ++ altKey, ++ metaKey, ++ WallTime::now(), ++ force, ++ syntheticClickType ++ )); ++ } ++ completionHandler(); ++} + #endif + + void WebPage::cancelPointer(WebCore::PointerID pointerId, const WebCore::IntPoint& documentPoint) +@@ -3290,6 +3397,11 @@ void WebPage::sendMessageToTargetBackend(const String& targetId, const String& m + m_inspectorTargetController->sendMessageToTargetBackend(targetId, message); + } + ++void WebPage::resumeInspectorIfPausedInNewWindow() ++{ ++ m_page->inspectorController().resumeIfPausedInNewWindow(); ++} ++ + void WebPage::insertNewlineInQuotedContent() + { + Frame& frame = m_page->focusController().focusedOrMainFrame(); +@@ -3527,6 +3639,7 @@ void WebPage::didCompletePageTransition() + void WebPage::show() + { + send(Messages::WebPageProxy::ShowPage()); ++ m_page->inspectorController().didShowNewWindow(); + } + + void WebPage::setIsTakingSnapshotsForApplicationSuspension(bool isTakingSnapshotsForApplicationSuspension) +@@ -4195,7 +4308,7 @@ NotificationPermissionRequestManager* WebPage::notificationPermissionRequestMana + + #if ENABLE(DRAG_SUPPORT) + +-#if PLATFORM(GTK) ++#if PLATFORM(GTK) || PLATFORM(WPE) + void WebPage::performDragControllerAction(DragControllerAction action, const IntPoint& clientPosition, const IntPoint& globalPosition, OptionSet draggingSourceOperationMask, SelectionData&& selectionData, OptionSet flags) + { + if (!m_page) { +@@ -6491,6 +6604,9 @@ Ref WebPage::createDocumentLoader(Frame& frame, const ResourceRe + WebsitePoliciesData::applyToDocumentLoader(WTFMove(*m_pendingWebsitePolicies), documentLoader); + m_pendingWebsitePolicies = WTF::nullopt; + } ++ } else if (m_pendingFrameNavigationID) { ++ documentLoader->setNavigationID(m_pendingFrameNavigationID); ++ m_pendingFrameNavigationID = 0; + } + + return documentLoader; +diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.h b/Source/WebKit/WebProcess/WebPage/WebPage.h +index 1c7f46b65bb3f72c69d72320fa67786762f49940..fe55c1c6c4da5612a0dec72fa41062271c6adda8 100644 +--- a/Source/WebKit/WebProcess/WebPage/WebPage.h ++++ b/Source/WebKit/WebProcess/WebPage/WebPage.h +@@ -110,6 +110,10 @@ typedef struct _AtkObject AtkObject; + #include "WebPrintOperationGtk.h" + #endif + ++#if PLATFORM(WPE) ++#include "ArgumentCodersWPE.h" ++#endif ++ + #if PLATFORM(GTK) || PLATFORM(WPE) + #include "InputMethodState.h" + #endif +@@ -942,11 +946,11 @@ public: + void clearSelection(); + void restoreSelectionInFocusedEditableElement(); + +-#if ENABLE(DRAG_SUPPORT) && PLATFORM(GTK) ++#if ENABLE(DRAG_SUPPORT) && (PLATFORM(GTK) || PLATFORM(WPE)) + void performDragControllerAction(DragControllerAction, const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition, OptionSet draggingSourceOperationMask, WebCore::SelectionData&&, OptionSet); + #endif + +-#if ENABLE(DRAG_SUPPORT) && !PLATFORM(GTK) ++#if ENABLE(DRAG_SUPPORT) && !PLATFORM(GTK) && !PLATFORM(WPE) + void performDragControllerAction(DragControllerAction, const WebCore::DragData&, SandboxExtension::Handle&&, SandboxExtension::HandleArray&&); + #endif + +@@ -960,6 +964,9 @@ public: + void didStartDrag(); + void dragCancelled(); + OptionSet allowedDragSourceActions() const { return m_allowedDragSourceActions; } ++#if PLATFORM(MAC) ++ void setDragPasteboardName(const String& pasteboardName) { m_page->setDragPasteboardName(pasteboardName); } ++#endif + #endif + + void beginPrinting(WebCore::FrameIdentifier, const PrintInfo&); +@@ -1190,6 +1197,7 @@ public: + void connectInspector(const String& targetId, Inspector::FrontendChannel::ConnectionType); + void disconnectInspector(const String& targetId); + void sendMessageToTargetBackend(const String& targetId, const String& message); ++ void resumeInspectorIfPausedInNewWindow(); + + void insertNewlineInQuotedContent(); + +@@ -1505,6 +1513,7 @@ private: + // Actions + void tryClose(CompletionHandler&&); + void platformDidReceiveLoadParameters(const LoadParameters&); ++ void loadRequestInFrameForInspector(LoadParameters&&, WebCore::FrameIdentifier); + void loadRequest(LoadParameters&&); + NO_RETURN void loadRequestWaitingForProcessLaunch(LoadParameters&&, URL&&, WebPageProxyIdentifier, bool); + void loadData(LoadParameters&&); +@@ -1542,6 +1551,7 @@ private: + void updatePotentialTapSecurityOrigin(const WebTouchEvent&, bool wasHandled); + #elif ENABLE(TOUCH_EVENTS) + void touchEvent(const WebTouchEvent&); ++ void fakeTouchTap(const WebCore::IntPoint& position, uint8_t modifiers, CompletionHandler&& completionHandler); + #endif + + void cancelPointer(WebCore::PointerID, const WebCore::IntPoint&); +@@ -1659,9 +1669,7 @@ private: + void countStringMatches(const String&, OptionSet, uint32_t maxMatchCount); + void replaceMatches(const Vector& matchIndices, const String& replacementText, bool selectionOnly, CompletionHandler&&); + +-#if USE(COORDINATED_GRAPHICS) + void sendViewportAttributesChanged(const WebCore::ViewportArguments&); +-#endif + + void didChangeSelectedIndexForActivePopupMenu(int32_t newIndex); + void setTextForActivePopupMenu(int32_t index); +@@ -2157,6 +2165,7 @@ private: + UserActivity m_userActivity; + + uint64_t m_pendingNavigationID { 0 }; ++ uint64_t m_pendingFrameNavigationID { 0 }; + Optional m_pendingWebsitePolicies; + + bool m_mainFrameProgressCompleted { false }; +diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.messages.in b/Source/WebKit/WebProcess/WebPage/WebPage.messages.in +index 3be88aa0ca4abf12abfe33696e412f355c918d78..18ebf86aea6dea680531a008a10946ba6b0119c0 100644 +--- a/Source/WebKit/WebProcess/WebPage/WebPage.messages.in ++++ b/Source/WebKit/WebProcess/WebPage/WebPage.messages.in +@@ -132,6 +132,7 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType + ConnectInspector(String targetId, Inspector::FrontendChannel::ConnectionType connectionType) + DisconnectInspector(String targetId) + SendMessageToTargetBackend(String targetId, String message) ++ ResumeInspectorIfPausedInNewWindow(); + + #if ENABLE(REMOTE_INSPECTOR) + SetIndicating(bool indicating); +@@ -143,6 +144,7 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType + #endif + #if !ENABLE(IOS_TOUCH_EVENTS) && ENABLE(TOUCH_EVENTS) + TouchEvent(WebKit::WebTouchEvent event) ++ FakeTouchTap(WebCore::IntPoint position, uint8_t modifiers) -> () Async + #endif + + CancelPointer(WebCore::PointerID pointerId, WebCore::IntPoint documentPoint) +@@ -177,6 +179,7 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType + LoadURLInFrame(URL url, String referrer, WebCore::FrameIdentifier frameID) + LoadDataInFrame(IPC::DataReference data, String MIMEType, String encodingName, URL baseURL, WebCore::FrameIdentifier frameID) + LoadRequest(struct WebKit::LoadParameters loadParameters) ++ LoadRequestInFrameForInspector(struct WebKit::LoadParameters loadParameters, WebCore::FrameIdentifier frameID) + LoadRequestWaitingForProcessLaunch(struct WebKit::LoadParameters loadParameters, URL resourceDirectoryURL, WebKit::WebPageProxyIdentifier pageID, bool checkAssumedReadAccessToResourceURL) + LoadData(struct WebKit::LoadParameters loadParameters) + LoadSimulatedRequestAndResponse(struct WebKit::LoadParameters loadParameters, WebCore::ResourceResponse simulatedResponse) +@@ -313,10 +316,10 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType + AddMIMETypeWithCustomContentProvider(String mimeType) + + # Drag and drop. +-#if PLATFORM(GTK) && ENABLE(DRAG_SUPPORT) ++#if (PLATFORM(GTK) || PLATFORM(WPE)) && ENABLE(DRAG_SUPPORT) + PerformDragControllerAction(enum:uint8_t WebKit::DragControllerAction action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, OptionSet draggingSourceOperationMask, WebCore::SelectionData selection, OptionSet flags) + #endif +-#if !PLATFORM(GTK) && ENABLE(DRAG_SUPPORT) ++#if !PLATFORM(GTK) && !PLATFORM(WPE) && ENABLE(DRAG_SUPPORT) + PerformDragControllerAction(enum:uint8_t WebKit::DragControllerAction action, WebCore::DragData dragData, WebKit::SandboxExtension::Handle sandboxExtensionHandle, WebKit::SandboxExtension::HandleArray sandboxExtensionsForUpload) + #endif + #if ENABLE(DRAG_SUPPORT) +@@ -325,6 +328,10 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType + DragCancelled() + #endif + ++#if PLATFORM(MAC) && ENABLE(DRAG_SUPPORT) ++ SetDragPasteboardName(String pasteboardName) ++#endif ++ + #if PLATFORM(IOS_FAMILY) && ENABLE(DRAG_SUPPORT) + RequestDragStart(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, OptionSet allowedActionsMask) + RequestAdditionalItemsForDragSession(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, OptionSet allowedActionsMask) +diff --git a/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm b/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm +index 0a4440dfa5f470a4d76e8ec2a5c9679d289393c6..6acd1c03dc8f77b62b737976c9e28459dd32eb17 100644 +--- a/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm ++++ b/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm +@@ -837,21 +837,37 @@ String WebPage::platformUserAgent(const URL&) const + + bool WebPage::hoverSupportedByPrimaryPointingDevice() const + { ++#if ENABLE(TOUCH_EVENTS) ++ return !screenIsTouchPrimaryInputDevice(); ++#else + return true; ++#endif + } + + bool WebPage::hoverSupportedByAnyAvailablePointingDevice() const + { ++#if ENABLE(TOUCH_EVENTS) ++ return !screenHasTouchDevice(); ++#else + return true; ++#endif + } + + Optional WebPage::pointerCharacteristicsOfPrimaryPointingDevice() const + { ++#if ENABLE(TOUCH_EVENTS) ++ if (screenIsTouchPrimaryInputDevice()) ++ return PointerCharacteristics::Coarse; ++#endif + return PointerCharacteristics::Fine; + } + + OptionSet WebPage::pointerCharacteristicsOfAllAvailablePointingDevices() const + { ++#if ENABLE(TOUCH_EVENTS) ++ if (screenHasTouchDevice()) ++ return PointerCharacteristics::Coarse; ++#endif + return PointerCharacteristics::Fine; + } + +diff --git a/Source/WebKit/WebProcess/WebPage/win/WebPageWin.cpp b/Source/WebKit/WebProcess/WebPage/win/WebPageWin.cpp +index fbfc1fd3ece09dc3dfd9300dc1d67f045942053b..08a671959b8483760771a790ad6793eb124a9495 100644 +--- a/Source/WebKit/WebProcess/WebPage/win/WebPageWin.cpp ++++ b/Source/WebKit/WebProcess/WebPage/win/WebPageWin.cpp +@@ -43,6 +43,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -118,21 +119,37 @@ String WebPage::platformUserAgent(const URL&) const + + bool WebPage::hoverSupportedByPrimaryPointingDevice() const + { ++#if ENABLE(TOUCH_EVENTS) ++ return !screenIsTouchPrimaryInputDevice(); ++#else + return true; ++#endif + } + + bool WebPage::hoverSupportedByAnyAvailablePointingDevice() const + { ++#if ENABLE(TOUCH_EVENTS) ++ return !screenHasTouchDevice(); ++#else + return true; ++#endif + } + + Optional WebPage::pointerCharacteristicsOfPrimaryPointingDevice() const + { ++#if ENABLE(TOUCH_EVENTS) ++ if (screenIsTouchPrimaryInputDevice()) ++ return PointerCharacteristics::Coarse; ++#endif + return PointerCharacteristics::Fine; + } + + OptionSet WebPage::pointerCharacteristicsOfAllAvailablePointingDevices() const + { ++#if ENABLE(TOUCH_EVENTS) ++ if (screenHasTouchDevice()) ++ return PointerCharacteristics::Coarse; ++#endif + return PointerCharacteristics::Fine; + } + +diff --git a/Source/WebKit/WebProcess/WebProcess.cpp b/Source/WebKit/WebProcess/WebProcess.cpp +index 5ac61209bd386af18b249e1212e5477fd44631c4..02b76d58c85ac45f95293ed2498421f2a80494dd 100644 +--- a/Source/WebKit/WebProcess/WebProcess.cpp ++++ b/Source/WebKit/WebProcess/WebProcess.cpp +@@ -86,6 +86,7 @@ + #include "WebsiteData.h" + #include "WebsiteDataStoreParameters.h" + #include "WebsiteDataType.h" ++#include + #include + #include + #include +@@ -319,6 +320,8 @@ void WebProcess::initializeProcess(const AuxiliaryProcessInitializationParameter + + platformInitializeProcess(parameters); + updateCPULimit(); ++ ++ Inspector::IdentifiersFactory::initializeWithProcessID(parameters.processIdentifier->toUInt64()); + } + + void WebProcess::initializeConnection(IPC::Connection* connection) +diff --git a/Source/WebKit/WebProcess/win/WebProcessMainWin.cpp b/Source/WebKit/WebProcess/win/WebProcessMainWin.cpp +index 8987c3964a9308f2454759de7f8972215a3ae416..bcac0afeb94ed8123d1f9fb0b932c8497d157b49 100644 +--- a/Source/WebKit/WebProcess/win/WebProcessMainWin.cpp ++++ b/Source/WebKit/WebProcess/win/WebProcessMainWin.cpp +@@ -42,7 +42,9 @@ public: + bool platformInitialize() override + { + if (SetProcessDpiAwarenessContextPtr()) +- SetProcessDpiAwarenessContextPtr()(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); ++ // Playwright begin ++ SetProcessDpiAwarenessContextPtr()(DPI_AWARENESS_CONTEXT_UNAWARE); ++ // Playwright end + else + SetProcessDPIAware(); + return true; +diff --git a/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm b/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm +index db96b4048060387a9436348fd2d390c44881e381..441945e813a24cbd03b72dd4c55e7e9dcd5ab3c6 100644 +--- a/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm ++++ b/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm +@@ -4230,7 +4230,7 @@ static BOOL currentScrollIsBlit(NSView *clipView) + _private->handlingMouseDownEvent = NO; + } + +-#if ENABLE(TOUCH_EVENTS) ++#if ENABLE(IOS_TOUCH_EVENTS) + + - (void)touch:(WebEvent *)event + { +diff --git a/Source/WebKitLegacy/mac/WebView/WebView.mm b/Source/WebKitLegacy/mac/WebView/WebView.mm +index d3968be3ff4b66f3e2698ebde74323e585d3eb8d..ae496cb1282bff19749cf2697126ed3f8cba27a7 100644 +--- a/Source/WebKitLegacy/mac/WebView/WebView.mm ++++ b/Source/WebKitLegacy/mac/WebView/WebView.mm +@@ -4023,7 +4023,7 @@ IGNORE_WARNINGS_END + } + #endif // PLATFORM(IOS_FAMILY) + +-#if ENABLE(TOUCH_EVENTS) ++#if ENABLE(IOS_TOUCH_EVENTS) + + - (NSArray *)_touchEventRegions + { +@@ -4065,7 +4065,7 @@ IGNORE_WARNINGS_END + }).autorelease(); + } + +-#endif // ENABLE(TOUCH_EVENTS) ++#endif // ENABLE(IOS_TOUCH_EVENTS) + + // For backwards compatibility with the WebBackForwardList API, we honor both + // a per-WebView and a per-preferences setting for whether to use the back/forward cache. +diff --git a/Source/cmake/FindLibVPX.cmake b/Source/cmake/FindLibVPX.cmake +new file mode 100644 +index 0000000000000000000000000000000000000000..dd6a53e2d57318489b7e49dd7373706d5d9dc387 +--- /dev/null ++++ b/Source/cmake/FindLibVPX.cmake +@@ -0,0 +1,25 @@ ++# Find LibVPX ++ ++find_package(PkgConfig QUIET) ++pkg_check_modules(PC_LIBVPX REQUIRED vpx) ++ ++find_path(LIBVPX_INCLUDE_DIRS ++ NAMES vpx/vp8.h ++ HINTS ${PC_LIBVPX_INCLUDEDIR} ++ ${PC_LIBVPX_INCLUDE_DIRS} ++) ++ ++find_library(LIBVPX_LIBRARIES ++ NAMES vpx ++ HINTS ${PC_LIBVPX_LIBDIR} ++ ${PC_LIBVPX_LIBRARY_DIRS} ++) ++ ++include(FindPackageHandleStandardArgs) ++FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibVPX REQUIRED_VARS LIBVPX_INCLUDE_DIRS LIBVPX_LIBRARIES ++ VERSION_VAR PC_LIBVPX_VERSION) ++ ++mark_as_advanced( ++ LIBVPX_INCLUDE_DIRS ++ LIBVPX_LIBRARIES ++) +diff --git a/Source/cmake/OptionsGTK.cmake b/Source/cmake/OptionsGTK.cmake +index c1c2382b6cda74d0b909780277b6124360492b9e..e94161d03a9e3ad61b15725ba6bf73daf47b2e65 100644 +--- a/Source/cmake/OptionsGTK.cmake ++++ b/Source/cmake/OptionsGTK.cmake +@@ -6,6 +6,8 @@ WEBKIT_OPTION_DEFINE(USE_GTK4 "Whether to enable usage of GTK4 instead of GTK3." + + SET_PROJECT_VERSION(2 33 0) + ++set(ENABLE_WEBKIT_LEGACY OFF) ++ + if (USE_GTK4) + set(WEBKITGTK_API_VERSION 5.0) + set(GTK_MINIMUM_VERSION 3.98.5) +@@ -54,6 +56,10 @@ find_package(EGL) + find_package(OpenGL) + find_package(OpenGLES2) + ++# Playwright begin ++find_package(LibVPX REQUIRED) ++# Playwright end ++ + include(GStreamerDefinitions) + + SET_AND_EXPOSE_TO_BUILD(USE_ATK TRUE) +@@ -150,7 +156,7 @@ endif () + # without approval from a GTK reviewer. There must be strong reason to support + # changing the value of the option. + WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DRAG_SUPPORT PUBLIC ON) +-WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_GAMEPAD PUBLIC ON) ++WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_GAMEPAD PUBLIC OFF) + WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SPELLCHECK PUBLIC ON) + WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_TOUCH_EVENTS PUBLIC ON) + WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_CRYPTO PUBLIC ON) +@@ -192,6 +198,12 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SHAREABLE_RESOURCE PRIVATE ON) + WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_API_STATISTICS PRIVATE ON) + WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_RTC PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES}) + ++# Playwright ++WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_APPLICATION_MANIFEST PRIVATE ON) ++WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_TRAILING_WORD PRIVATE ON) ++WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CURSOR_VISIBILITY PRIVATE ON) ++WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DOWNLOAD_ATTRIBUTE PRIVATE ON) ++ + include(GStreamerDependencies) + + # Finalize the value for all options. Do not attempt to use an option before +diff --git a/Source/cmake/OptionsWPE.cmake b/Source/cmake/OptionsWPE.cmake +index 3fec7c0f1a1edbfbf5d1992dcf605b45b0ef6def..03fbc776f7ce45bee266fa520aa541bb8b3b6bb4 100644 +--- a/Source/cmake/OptionsWPE.cmake ++++ b/Source/cmake/OptionsWPE.cmake +@@ -3,6 +3,7 @@ include(VersioningUtils) + + SET_PROJECT_VERSION(2 31 1) + set(WPE_API_VERSION 1.0) ++set(ENABLE_WEBKIT_LEGACY OFF) + + CALCULATE_LIBRARY_VERSIONS_FROM_LIBTOOL_TRIPLE(WEBKIT 16 0 13) + +@@ -79,13 +80,21 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEBGL2 PRIVATE OFF) + WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_RTC PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES}) + WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEBXR PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES}) + ++# Playwright ++WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_APPLICATION_MANIFEST PRIVATE ON) ++WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_TRAILING_WORD PRIVATE ON) ++WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CURSOR_VISIBILITY PRIVATE ON) ++WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DARK_MODE_CSS PRIVATE ON) ++WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DOWNLOAD_ATTRIBUTE PRIVATE ON) ++WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DRAG_SUPPORT PUBLIC ON) ++ + # Public options specific to the WPE port. Do not add any options here unless + # there is a strong reason we should support changing the value of the option, + # and the option is not relevant to any other WebKit ports. + WEBKIT_OPTION_DEFINE(ENABLE_GTKDOC "Whether or not to use generate gtkdoc." PUBLIC OFF) + WEBKIT_OPTION_DEFINE(USE_OPENJPEG "Whether to enable support for JPEG2000 images." PUBLIC ON) + WEBKIT_OPTION_DEFINE(USE_WOFF2 "Whether to enable support for WOFF2 Web Fonts." PUBLIC ON) +-WEBKIT_OPTION_DEFINE(ENABLE_WPE_QT_API "Whether to enable support for the Qt5/QML plugin" PUBLIC ${ENABLE_DEVELOPER_MODE}) ++WEBKIT_OPTION_DEFINE(ENABLE_WPE_QT_API "Whether to enable support for the Qt5/QML plugin" PUBLIC OFF) + WEBKIT_OPTION_DEFINE(USE_SYSTEMD "Whether to enable journald logging" PUBLIC ON) + WEBKIT_OPTION_DEFINE(USE_SOUP2 "Whether to enable usage of Soup 2 instead of Soup 3." PUBLIC ON) + +diff --git a/Source/cmake/OptionsWin.cmake b/Source/cmake/OptionsWin.cmake +index c4ab493bb1bb2fbc0ebf135d1f8711d911800c7f..d46bd960ec04597e4ea75ef0ac61262f88f75942 100644 +--- a/Source/cmake/OptionsWin.cmake ++++ b/Source/cmake/OptionsWin.cmake +@@ -7,8 +7,9 @@ add_definitions(-D_WINDOWS -DWINVER=0x601 -D_WIN32_WINNT=0x601) + add_definitions(-DNOMINMAX) + add_definitions(-DUNICODE -D_UNICODE) + ++set(ENABLE_WEBKIT_LEGACY OFF) ++ + if ((NOT DEFINED ENABLE_WEBKIT_LEGACY) OR ENABLE_WEBKIT_LEGACY) +- set(ENABLE_WEBKIT_LEGACY ON) + set(ENABLE_WEBKIT OFF) + endif () + +@@ -89,6 +90,13 @@ if (${WTF_PLATFORM_WIN_CAIRO}) + # No support planned + WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_FTPDIR PRIVATE OFF) + ++ # Playwright ++ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_CONIC_GRADIENTS PRIVATE ON) ++ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_TRAILING_WORD PRIVATE ON) ++ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DARK_MODE_CSS PRIVATE ON) ++ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DOWNLOAD_ATTRIBUTE PRIVATE ON) ++ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_TOUCH_EVENTS PRIVATE ON) ++ + # FIXME: Implement plugin process on Modern WebKit. https://bugs.webkit.org/show_bug.cgi?id=185313 + WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_NETSCAPE_PLUGIN_API PRIVATE OFF) + else () +diff --git a/Source/cmake/OptionsWinCairo.cmake b/Source/cmake/OptionsWinCairo.cmake +index 6b4900a90e64c19e551faf47cda2ef8cfef38480..7a2807d25641fd583c9a7c1a96723afbca29ec1d 100644 +--- a/Source/cmake/OptionsWinCairo.cmake ++++ b/Source/cmake/OptionsWinCairo.cmake +@@ -32,15 +32,36 @@ if (OpenJPEG_FOUND) + endif () + + find_package(WOFF2 1.0.2 COMPONENTS dec) +-if (WOFF2_FOUND) +- SET_AND_EXPOSE_TO_BUILD(USE_WOFF2 ON) +-endif () ++SET_AND_EXPOSE_TO_BUILD(USE_WOFF2 ON) + + find_package(WebP COMPONENTS demux) + if (WebP_FOUND) + SET_AND_EXPOSE_TO_BUILD(USE_WEBP ON) + endif () + ++# Playwright begin ++if (NOT LIBVPX_PACKAGE_PATH) ++ set(LIBVPX_PACKAGE_PATH "C:\\vcpkg\\packages\\libvpx_x64-windows") ++endif() ++file(TO_CMAKE_PATH "${LIBVPX_PACKAGE_PATH}" LIBVPX_PACKAGE_PATH) ++message(STATUS "Using LIBVPX_PACKAGE_PATH = ${LIBVPX_PACKAGE_PATH}") ++ ++find_library(LIBVPX_CUSTOM_LIBRARY vpxmd.lib ++ HINTS ${LIBVPX_PACKAGE_PATH}/lib ++ REQIRED ++ NO_DEFAULT_PATH ++) ++message(STATUS "Found LIBVPX_CUSTOM_LIBRARY = ${LIBVPX_CUSTOM_LIBRARY}") ++ ++find_path(LIBVPX_CUSTOM_INCLUDE_DIR ++ NAMES vpx/vp8.h ++ HINTS ${LIBVPX_PACKAGE_PATH}/include ++ REQUIRED ++ NO_DEFAULT_PATH ++) ++message(STATUS "Found LIBVPX_CUSTOM_INCLUDE_DIR = ${LIBVPX_CUSTOM_INCLUDE_DIR}") ++# Playwright end ++ + # TODO: Add a check for HAVE_RSA_PSS for support of CryptoAlgorithmRSA_PSS + # https://bugs.webkit.org/show_bug.cgi?id=206635 + +diff --git a/Tools/MiniBrowser/gtk/BrowserTab.c b/Tools/MiniBrowser/gtk/BrowserTab.c +index 3b2f5decdb26d42c39bd48e6f5af069c6e919c30..0a07ed1aa77ab4ece367d48350f90b4b2984f7de 100644 +--- a/Tools/MiniBrowser/gtk/BrowserTab.c ++++ b/Tools/MiniBrowser/gtk/BrowserTab.c +@@ -161,6 +161,11 @@ static void loadChanged(WebKitWebView *webView, WebKitLoadEvent loadEvent, Brows + #endif + } + ++static gboolean loadFailed() ++{ ++ return TRUE; ++} ++ + static GtkWidget *createInfoBarQuestionMessage(const char *title, const char *text) + { + GtkWidget *dialog = gtk_info_bar_new_with_buttons("No", GTK_RESPONSE_NO, "Yes", GTK_RESPONSE_YES, NULL); +@@ -650,6 +655,7 @@ static void browserTabConstructed(GObject *gObject) + g_signal_connect(tab->webView, "notify::is-loading", G_CALLBACK(isLoadingChanged), tab); + g_signal_connect(tab->webView, "decide-policy", G_CALLBACK(decidePolicy), tab); + g_signal_connect(tab->webView, "load-changed", G_CALLBACK(loadChanged), tab); ++ g_signal_connect(tab->webView, "load-failed", G_CALLBACK(loadFailed), tab); + g_signal_connect(tab->webView, "load-failed-with-tls-errors", G_CALLBACK(loadFailedWithTLSerrors), tab); + g_signal_connect(tab->webView, "permission-request", G_CALLBACK(decidePermissionRequest), tab); + g_signal_connect(tab->webView, "run-color-chooser", G_CALLBACK(runColorChooserCallback), tab); +@@ -699,6 +705,9 @@ static char *getInternalURI(const char *uri) + if (g_str_has_prefix(uri, "about:") && !g_str_equal(uri, "about:blank")) + return g_strconcat(BROWSER_ABOUT_SCHEME, uri + strlen ("about"), NULL); + ++ if (!g_str_has_prefix(uri, "http://") && !g_str_has_prefix(uri, "https://") && !g_str_has_prefix(uri, "file://")) ++ return g_strconcat("http://", uri, NULL); ++ + return g_strdup(uri); + } + +diff --git a/Tools/MiniBrowser/gtk/BrowserWindow.c b/Tools/MiniBrowser/gtk/BrowserWindow.c +index d1eb89ad99fe7a96f3c21bd75641c80210e7e5d5..f04149ba5f52f671b30ffbf0283f391aa1fc778f 100644 +--- a/Tools/MiniBrowser/gtk/BrowserWindow.c ++++ b/Tools/MiniBrowser/gtk/BrowserWindow.c +@@ -1355,6 +1355,12 @@ static gboolean browserWindowDeleteEvent(GtkWidget *widget, GdkEventAny* event) + } + #endif + ++static void zeroPreferredSize(GtkWidget* widget, gint* minimumSize, gint* naturalSize) ++{ ++ *minimumSize = 10; ++ *naturalSize = 10; ++} ++ + static void browser_window_class_init(BrowserWindowClass *klass) + { + GObjectClass *gobjectClass = G_OBJECT_CLASS(klass); +@@ -1368,6 +1374,14 @@ static void browser_window_class_init(BrowserWindowClass *klass) + GtkWidgetClass *widgetClass = GTK_WIDGET_CLASS(klass); + widgetClass->delete_event = browserWindowDeleteEvent; + #endif ++ ++// Playwrigth begin ++ // Override preferred (which is minimum :-) size to 0 so that we can ++ // emulate arbitrary resolution. ++ GtkWidgetClass* browserWidgetClass = GTK_WIDGET_CLASS(klass); ++ browserWidgetClass->get_preferred_width = zeroPreferredSize; ++ browserWidgetClass->get_preferred_height = zeroPreferredSize; ++// Playwrigth end + } + + /* Public API. */ +diff --git a/Tools/MiniBrowser/gtk/BrowserWindow.h b/Tools/MiniBrowser/gtk/BrowserWindow.h +index 62629b4c1c25ae82bd797b39bbf9de0331f8eed2..5de7900a29b0e629f1ac404bbb0dc5b4e605294d 100644 +--- a/Tools/MiniBrowser/gtk/BrowserWindow.h ++++ b/Tools/MiniBrowser/gtk/BrowserWindow.h +@@ -37,7 +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/" ++#define BROWSER_DEFAULT_URL "about:blank" + #define BROWSER_ABOUT_SCHEME "minibrowser-about" + + typedef struct _BrowserWindow BrowserWindow; +diff --git a/Tools/MiniBrowser/gtk/main.c b/Tools/MiniBrowser/gtk/main.c +index b4ad6cad7ee375d92cb12a4f168418e67fe1afb6..0ef28c90628dc8e9d5ac521db489180de913f881 100644 +--- a/Tools/MiniBrowser/gtk/main.c ++++ b/Tools/MiniBrowser/gtk/main.c +@@ -54,7 +54,12 @@ static gboolean darkMode; + static gboolean enableITP; + static gboolean exitAfterLoad; + static gboolean webProcessCrashed; ++static gboolean inspectorPipe; ++static gboolean headless; ++static gboolean noStartupWindow; ++static const char *userDataDir; + static gboolean printVersion; ++static GtkApplication *browserApplication = NULL; + + typedef enum { + MINI_BROWSER_ERROR_INVALID_ABOUT_PATH +@@ -147,6 +152,10 @@ static const GOptionEntry commandLineOptions[] = + { "enable-itp", 0, 0, G_OPTION_ARG_NONE, &enableITP, "Enable Intelligent Tracking Prevention (ITP)", NULL }, + { "exit-after-load", 0, 0, G_OPTION_ARG_NONE, &exitAfterLoad, "Quit the browser after the load finishes", NULL }, + { "version", 'v', 0, G_OPTION_ARG_NONE, &printVersion, "Print the WebKitGTK version", NULL }, ++ { "inspector-pipe", 0, 0, G_OPTION_ARG_NONE, &inspectorPipe, "Open pipe connection to the remote inspector", NULL }, ++ { "user-data-dir", 0, 0, G_OPTION_ARG_STRING, &userDataDir, "Default profile persistence folder location", NULL }, ++ { "headless", 0, 0, G_OPTION_ARG_NONE, &headless, "Noop headless operation", NULL }, ++ { "no-startup-window", 0, 0, G_OPTION_ARG_NONE, &noStartupWindow, "Do not open default page", NULL }, + { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &uriArguments, 0, "[URL…]" }, + { 0, 0, 0, 0, 0, 0, 0 } + }; +@@ -615,6 +624,48 @@ static void filterSavedCallback(WebKitUserContentFilterStore *store, GAsyncResul + g_main_loop_quit(data->mainLoop); + } + ++static WebKitWebContext *persistentWebContext = NULL; ++ ++static WebKitWebView *createNewPage(WebKitBrowserInspector *browser_inspector, WebKitWebContext *context) ++{ ++ if (context == NULL) ++ context = persistentWebContext; ++ ++ WebKitWebView *newWebView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, ++ "web-context", context, ++ "is-ephemeral", webkit_web_context_is_ephemeral(context), ++ "is-controlled-by-automation", TRUE, ++ NULL)); ++ GtkWidget *newWindow = browser_window_new(NULL, context); ++ gtk_window_set_application(GTK_WINDOW(newWindow), browserApplication); ++ browser_window_append_view(BROWSER_WINDOW(newWindow), newWebView); ++ gtk_widget_grab_focus(GTK_WIDGET(newWebView)); ++ gtk_widget_show(GTK_WIDGET(newWindow)); ++ webkit_web_view_load_uri(newWebView, "about:blank"); ++ return newWebView; ++} ++ ++static void quitBroserApplication(WebKitBrowserInspector* browser_inspector) ++{ ++ g_application_release(G_APPLICATION(browserApplication)); ++} ++ ++static void keepApplicationAliveUntilQuit(GApplication *application) ++{ ++ // Reference the application, it will be released in quitBroserApplication. ++ g_application_hold(application); ++ WebKitBrowserInspector* browserInspector = webkit_browser_inspector_get_default(); ++ g_signal_connect(browserInspector, "quit-application", G_CALLBACK(quitBroserApplication), NULL); ++} ++ ++static void configureBrowserInspectorPipe() ++{ ++ WebKitBrowserInspector* browserInspector = webkit_browser_inspector_get_default(); ++ g_signal_connect(browserInspector, "create-new-page", G_CALLBACK(createNewPage), NULL); ++ ++ webkit_browser_inspector_initialize_pipe(proxy, ignoreHosts); ++} ++ + static void startup(GApplication *application) + { + const char *actionAccels[] = { +@@ -645,10 +696,22 @@ static void startup(GApplication *application) + + static void activate(GApplication *application, WebKitSettings *webkitSettings) + { ++ if (inspectorPipe) ++ configureBrowserInspectorPipe(); ++ ++ if (noStartupWindow) { ++ keepApplicationAliveUntilQuit(application); ++ g_clear_object(&webkitSettings); ++ return; ++ } ++ + WebKitWebsiteDataManager *manager; +- if (privateMode || automationMode) ++ if (userDataDir) { ++ manager = webkit_website_data_manager_new("base-data-directory", userDataDir, "base-cache-directory", userDataDir, NULL); ++ cookiesFile = g_build_filename(userDataDir, "cookies.txt", NULL); ++ } else if (inspectorPipe || privateMode || automationMode) { + manager = webkit_website_data_manager_new_ephemeral(); +- else { ++ } else { + char *dataDirectory = g_build_filename(g_get_user_data_dir(), "webkitgtk-" WEBKITGTK_API_VERSION_STRING, "MiniBrowser", NULL); + char *cacheDirectory = g_build_filename(g_get_user_cache_dir(), "webkitgtk-" WEBKITGTK_API_VERSION_STRING, "MiniBrowser", NULL); + manager = webkit_website_data_manager_new("base-data-directory", dataDirectory, "base-cache-directory", cacheDirectory, NULL); +@@ -672,6 +735,7 @@ static void activate(GApplication *application, WebKitSettings *webkitSettings) + "use-system-appearance-for-scrollbars", FALSE, + #endif + NULL); ++ persistentWebContext = webContext; + g_object_unref(manager); + + if (cookiesPolicy) { +@@ -750,9 +814,7 @@ static void activate(GApplication *application, WebKitSettings *webkitSettings) + if (exitAfterLoad) + exitAfterWebViewLoadFinishes(webView, application); + } +- gchar *url = argumentToURL(uriArguments[i]); +- webkit_web_view_load_uri(webView, url); +- g_free(url); ++ webkit_web_view_load_uri(webView, uriArguments[i]); + } + } else { + WebKitWebView *webView = createBrowserTab(mainWindow, webkitSettings, userContentManager, defaultWebsitePolicies); +@@ -828,9 +890,11 @@ int main(int argc, char *argv[]) + } + + GtkApplication *application = gtk_application_new(NULL, G_APPLICATION_FLAGS_NONE); ++ browserApplication = application; + g_signal_connect(application, "startup", G_CALLBACK(startup), NULL); + g_signal_connect(application, "activate", G_CALLBACK(activate), webkitSettings); + g_application_run(G_APPLICATION(application), 0, NULL); ++ browserApplication = NULL; + g_object_unref(application); + + return exitAfterLoad && webProcessCrashed ? 1 : 0; +diff --git a/Tools/MiniBrowser/wpe/main.cpp b/Tools/MiniBrowser/wpe/main.cpp +index 2ab04ce061cffbfcbbc4e64c6683996b672abbce..2d105be12aa764a538132c8a7cf19b4ea8ec5099 100644 +--- a/Tools/MiniBrowser/wpe/main.cpp ++++ b/Tools/MiniBrowser/wpe/main.cpp +@@ -40,6 +40,9 @@ static gboolean headlessMode; + static gboolean privateMode; + static gboolean automationMode; + static gboolean ignoreTLSErrors; ++static gboolean inspectorPipe; ++static gboolean noStartupWindow; ++static const char* userDataDir; + static const char* contentFilter; + static const char* cookiesFile; + static const char* cookiesPolicy; +@@ -63,6 +66,9 @@ static const GOptionEntry commandLineOptions[] = + { "bg-color", 0, 0, G_OPTION_ARG_STRING, &bgColor, "Window background color. Default: white", "COLOR" }, + { "enable-itp", 0, 0, G_OPTION_ARG_NONE, &enableITP, "Enable Intelligent Tracking Prevention (ITP)", nullptr }, + { "version", 'v', 0, G_OPTION_ARG_NONE, &printVersion, "Print the WPE version", nullptr }, ++ { "inspector-pipe", 'v', 0, G_OPTION_ARG_NONE, &inspectorPipe, "Expose remote debugging protocol over pipe", nullptr }, ++ { "user-data-dir", 0, 0, G_OPTION_ARG_STRING, &userDataDir, "Default profile persistence folder location", "FILE" }, ++ { "no-startup-window", 0, 0, G_OPTION_ARG_NONE, &noStartupWindow, "Do not open default page", nullptr }, + { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &uriArguments, nullptr, "[URL]" }, + { nullptr, 0, 0, G_OPTION_ARG_NONE, nullptr, nullptr, nullptr } + }; +@@ -147,13 +153,34 @@ static void filterSavedCallback(WebKitUserContentFilterStore *store, GAsyncResul + g_main_loop_quit(data->mainLoop); + } + ++static gboolean webViewLoadFailed() ++{ ++ return TRUE; ++} ++ + static void webViewClose(WebKitWebView* webView, gpointer) + { + // Hash table key delete func takes care of unref'ing the view + g_hash_table_remove(openViews, webView); + } + +-static WebKitWebView* createWebView(WebKitWebView* webView, WebKitNavigationAction*, gpointer) ++static gboolean scriptDialog(WebKitWebView*, WebKitScriptDialog* dialog, gpointer) ++{ ++ if (inspectorPipe) ++ webkit_script_dialog_ref(dialog); ++ return TRUE; ++} ++ ++static gboolean scriptDialogHandled(WebKitWebView*, WebKitScriptDialog* dialog, gpointer) ++{ ++ if (inspectorPipe) ++ webkit_script_dialog_unref(dialog); ++ return TRUE; ++} ++ ++static WebKitWebView* createWebView(WebKitWebView* webView, WebKitNavigationAction*, gpointer); ++ ++static WebKitWebView* createWebViewImpl(WebKitWebView* webView, WebKitWebContext *webContext) + { + auto backend = createViewBackend(1280, 720); + struct wpe_view_backend* wpeBackend = backend->backend(); +@@ -165,17 +192,66 @@ static WebKitWebView* createWebView(WebKitWebView* webView, WebKitNavigationActi + delete static_cast(data); + }, backend.release()); + +- auto* newWebView = webkit_web_view_new_with_related_view(viewBackend, webView); +- webkit_web_view_set_settings(newWebView, webkit_web_view_get_settings(webView)); ++// Playwright begin ++ if (headlessMode) { ++ webkit_web_view_backend_set_screenshot_callback(viewBackend, ++ [](gpointer data) { ++ return static_cast(data)->snapshot(); ++ }); ++ } ++// Playwright end ++ WebKitWebView* newWebView; ++ if (webView) { ++ newWebView = webkit_web_view_new_with_related_view(viewBackend, webView); ++ } else { ++ newWebView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, ++ "backend", viewBackend, ++ "web-context", webContext, ++ nullptr)); ++ } + + g_signal_connect(newWebView, "create", G_CALLBACK(createWebView), nullptr); + g_signal_connect(newWebView, "close", G_CALLBACK(webViewClose), nullptr); + + g_hash_table_add(openViews, newWebView); + ++ g_signal_connect(newWebView, "load-failed", G_CALLBACK(webViewLoadFailed), nullptr); ++ g_signal_connect(newWebView, "script-dialog", G_CALLBACK(scriptDialog), nullptr); ++ g_signal_connect(newWebView, "script-dialog-handled", G_CALLBACK(scriptDialogHandled), nullptr); ++ g_signal_connect(newWebView, "create", G_CALLBACK(createWebView), nullptr); + return newWebView; + } + ++static WebKitWebView* createWebView(WebKitWebView* webView, WebKitNavigationAction*, gpointer) ++{ ++ return createWebViewImpl(webView, nullptr); ++} ++ ++static WebKitWebContext *persistentWebContext = NULL; ++ ++static WebKitWebView* createNewPage(WebKitBrowserInspector*, WebKitWebContext *webContext) ++{ ++ if (!webContext) ++ webContext = persistentWebContext; ++ WebKitWebView* webView = createWebViewImpl(nullptr, webContext); ++ webkit_web_view_load_uri(webView, "about:blank"); ++ return webView; ++} ++ ++static void quitBroserApplication(WebKitBrowserInspector* browser_inspector, gpointer data) ++{ ++ GMainLoop* mainLoop = static_cast(data); ++ g_main_loop_quit(mainLoop); ++} ++ ++static void configureBrowserInspector(GMainLoop* mainLoop) ++{ ++ WebKitBrowserInspector* browserInspector = webkit_browser_inspector_get_default(); ++ g_signal_connect(browserInspector, "create-new-page", G_CALLBACK(createNewPage), NULL); ++ g_signal_connect(browserInspector, "quit-application", G_CALLBACK(quitBroserApplication), mainLoop); ++ webkit_browser_inspector_initialize_pipe(proxy, ignoreHosts); ++} ++ + int main(int argc, char *argv[]) + { + #if ENABLE_DEVELOPER_MODE +@@ -207,6 +283,16 @@ int main(int argc, char *argv[]) + } + + auto* loop = g_main_loop_new(nullptr, FALSE); ++ if (inspectorPipe) ++ configureBrowserInspector(loop); ++ ++ openViews = g_hash_table_new_full(nullptr, nullptr, g_object_unref, nullptr); ++ ++ if (noStartupWindow) { ++ g_main_loop_run(loop); ++ g_main_loop_unref(loop); ++ return 0; ++ } + + auto backend = createViewBackend(1280, 720); + struct wpe_view_backend* wpeBackend = backend->backend(); +@@ -216,7 +302,15 @@ int main(int argc, char *argv[]) + return 1; + } + +- auto* manager = (privateMode || automationMode) ? webkit_website_data_manager_new_ephemeral() : webkit_website_data_manager_new(nullptr); ++ WebKitWebsiteDataManager *manager; ++ if (userDataDir) { ++ manager = webkit_website_data_manager_new("base-data-directory", userDataDir, "base-cache-directory", userDataDir, NULL); ++ cookiesFile = g_build_filename(userDataDir, "cookies.txt", NULL); ++ } else if (inspectorPipe || privateMode || automationMode) { ++ manager = webkit_website_data_manager_new_ephemeral(); ++ } else { ++ manager = webkit_website_data_manager_new(NULL); ++ } + webkit_website_data_manager_set_itp_enabled(manager, enableITP); + + if (proxy) { +@@ -228,7 +322,8 @@ int main(int argc, char *argv[]) + if (ignoreTLSErrors) + webkit_website_data_manager_set_tls_errors_policy(manager, WEBKIT_TLS_ERRORS_POLICY_IGNORE); + +- auto* webContext = webkit_web_context_new_with_website_data_manager(manager); ++ WebKitWebContext *webContext = WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT, "website-data-manager", manager, "process-swap-on-cross-site-navigation-enabled", TRUE, NULL)); ++ persistentWebContext = webContext; + g_object_unref(manager); + + if (cookiesPolicy) { +@@ -287,7 +382,14 @@ int main(int argc, char *argv[]) + auto* viewBackend = webkit_web_view_backend_new(wpeBackend, [](gpointer data) { + delete static_cast(data); + }, backend.release()); +- ++// Playwright begin ++ if (headlessMode) { ++ webkit_web_view_backend_set_screenshot_callback(viewBackend, ++ [](gpointer data) { ++ return static_cast(data)->snapshot(); ++ }); ++ } ++// Playwright end + auto* webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, + "backend", viewBackend, + "web-context", webContext, +@@ -304,8 +406,6 @@ int main(int argc, char *argv[]) + backendPtr->setAccessibleChild(ATK_OBJECT(accessible)); + #endif + +- openViews = g_hash_table_new_full(nullptr, nullptr, g_object_unref, nullptr); +- + webkit_web_context_set_automation_allowed(webContext, automationMode); + g_signal_connect(webContext, "automation-started", G_CALLBACK(automationStartedCallback), webView); + g_signal_connect(webView, "permission-request", G_CALLBACK(decidePermissionRequest), nullptr); +@@ -318,16 +418,9 @@ int main(int argc, char *argv[]) + webkit_web_view_set_background_color(webView, &color); + + if (uriArguments) { +- const char* uri = uriArguments[0]; +- if (g_str_equal(uri, "about:gpu")) +- uri = "webkit://gpu"; +- +- GFile* file = g_file_new_for_commandline_arg(uri); +- char* url = g_file_get_uri(file); +- g_object_unref(file); +- webkit_web_view_load_uri(webView, url); +- g_free(url); +- } else if (automationMode) ++ // Playwright: avoid weird url transformation like http://trac.webkit.org/r240840 ++ webkit_web_view_load_uri(webView, uriArguments[0]); ++ } else if (automationMode || inspectorPipe) + webkit_web_view_load_uri(webView, "about:blank"); + else + webkit_web_view_load_uri(webView, "https://wpewebkit.org"); +@@ -337,8 +430,7 @@ int main(int argc, char *argv[]) + g_hash_table_destroy(openViews); + + +- if (privateMode || automationMode) +- g_object_unref(webContext); ++ g_object_unref(webContext); + g_main_loop_unref(loop); + + return 0; +diff --git a/Tools/PlatformWin.cmake b/Tools/PlatformWin.cmake +index ef4407cfc114e602d98ed81724da504f453e258f..448dd483715162baba484f756fbcc1d72de4ba0c 100644 +--- a/Tools/PlatformWin.cmake ++++ b/Tools/PlatformWin.cmake +@@ -12,4 +12,5 @@ endif () + + if (ENABLE_WEBKIT) + add_subdirectory(WebKitTestRunner) ++ add_subdirectory(Playwright/win) + endif () +diff --git a/Tools/Scripts/build-webkit b/Tools/Scripts/build-webkit +index ddc2a96ac68cd51d5f4efeca78a118db91709aa2..57a78f54e72d264daa27faa53ac2a30cab98dd82 100755 +--- a/Tools/Scripts/build-webkit ++++ b/Tools/Scripts/build-webkit +@@ -247,7 +247,7 @@ if (isAppleCocoaWebKit()) { + push @projects, ("Source/WebKit"); + + if (!isEmbeddedWebKit()) { +- push @projects, ("Tools/MiniBrowser"); ++ push @projects, ("Tools/Playwright"); + + # WebInspectorUI must come after JavaScriptCore and WebCore but before WebKit and WebKit2 + my $webKitIndex = first { $projects[$_] eq "Source/WebKitLegacy" } 0..$#projects; +diff --git a/Tools/WebKitTestRunner/PlatformGTK.cmake b/Tools/WebKitTestRunner/PlatformGTK.cmake +index 6f8366b63e43eca6b95b67bb47fee9e7a1970cf9..cc8299dfa4380b833e79a870779a222059579d3b 100644 +--- a/Tools/WebKitTestRunner/PlatformGTK.cmake ++++ b/Tools/WebKitTestRunner/PlatformGTK.cmake +@@ -26,6 +26,7 @@ list(APPEND WebKitTestRunner_LIBRARIES + ${GLIB_LIBRARIES} + Cairo::Cairo + GTK::GTK ++ stdc++fs + ) + + list(APPEND WebKitTestRunnerInjectedBundle_LIBRARIES +diff --git a/Tools/WebKitTestRunner/PlatformWPE.cmake b/Tools/WebKitTestRunner/PlatformWPE.cmake +index 775b41868718ea6734efc9082f8161eee2e0015e..68a720c0cb01d534653a259536c481683873680d 100644 +--- a/Tools/WebKitTestRunner/PlatformWPE.cmake ++++ b/Tools/WebKitTestRunner/PlatformWPE.cmake +@@ -31,6 +31,7 @@ list(APPEND WebKitTestRunner_LIBRARIES + ${WPEBACKEND_FDO_LIBRARIES} + Cairo::Cairo + WPEToolingBackends ++ stdc++fs + ) + + list(APPEND WebKitTestRunnerInjectedBundle_LIBRARIES +diff --git a/Tools/WebKitTestRunner/TestController.cpp b/Tools/WebKitTestRunner/TestController.cpp +index 6d73abc3b6da331cf712b70b384d0d18cc392dd6..d8d65723430e9a00379bbff09891cb314b2c7087 100644 +--- a/Tools/WebKitTestRunner/TestController.cpp ++++ b/Tools/WebKitTestRunner/TestController.cpp +@@ -790,6 +790,7 @@ void TestController::createWebViewWithOptions(const TestOptions& options) + 0, // requestStorageAccessConfirm + shouldAllowDeviceOrientationAndMotionAccess, + runWebAuthenticationPanel, ++ 0, // handleJavaScriptDialog + decidePolicyForSpeechRecognitionPermissionRequest, + decidePolicyForMediaKeySystemPermissionRequest + }; +diff --git a/Tools/WebKitTestRunner/mac/EventSenderProxy.mm b/Tools/WebKitTestRunner/mac/EventSenderProxy.mm +index bacc141154331b79d1a3ced681c7f948988b9066..2510aeebae530265918f7bd08e114faa6b7b81c2 100644 +--- a/Tools/WebKitTestRunner/mac/EventSenderProxy.mm ++++ b/Tools/WebKitTestRunner/mac/EventSenderProxy.mm +@@ -873,4 +873,51 @@ void EventSenderProxy::mouseScrollByWithWheelAndMomentumPhases(int x, int y, int + } + } + ++#if ENABLE(TOUCH_EVENTS) ++void EventSenderProxy::addTouchPoint(int, int) ++{ ++} ++ ++void EventSenderProxy::updateTouchPoint(int, int, int) ++{ ++} ++ ++void EventSenderProxy::touchStart() ++{ ++} ++ ++void EventSenderProxy::touchMove() ++{ ++} ++ ++void EventSenderProxy::touchEnd() ++{ ++} ++ ++void EventSenderProxy::touchCancel() ++{ ++} ++ ++void EventSenderProxy::clearTouchPoints() ++{ ++} ++ ++void EventSenderProxy::releaseTouchPoint(int) ++{ ++} ++ ++void EventSenderProxy::cancelTouchPoint(int) ++{ ++} ++ ++void EventSenderProxy::setTouchPointRadius(int, int) ++{ ++} ++ ++void EventSenderProxy::setTouchModifier(WKEventModifiers, bool) ++{ ++} ++#endif // ENABLE(TOUCH_EVENTS) ++ ++ + } // namespace WTR +diff --git a/Tools/gtk/install-dependencies b/Tools/gtk/install-dependencies +index bbfa91f92945a1a383505b20e6acc22fda605972..3906b66f9cc03e2b061b8a375f4df537e6e0a6de 100755 +--- a/Tools/gtk/install-dependencies ++++ b/Tools/gtk/install-dependencies +@@ -142,6 +142,7 @@ function installDependenciesWithApt { + libupower-glib-dev \ + libwebp-dev \ + libwoff-dev \ ++ libxcb-glx0-dev \ + libxcomposite-dev \ + libxt-dev \ + libxtst-dev \ +@@ -149,6 +150,7 @@ function installDependenciesWithApt { + libwayland-dev \ + ninja-build \ + patch \ ++ patchelf \ + ruby \ + xfonts-utils" + +diff --git a/Tools/win/DLLLauncher/DLLLauncherMain.cpp b/Tools/win/DLLLauncher/DLLLauncherMain.cpp +index 39238ac08dbcab92fb1d053928938a96f154c9b1..64bc9f1458254322dca9005b5e2d2b19bb901386 100644 +--- a/Tools/win/DLLLauncher/DLLLauncherMain.cpp ++++ b/Tools/win/DLLLauncher/DLLLauncherMain.cpp +@@ -96,11 +96,9 @@ static bool prependPath(const wstring& directoryToPrepend) + static int fatalError(const wstring& programName, const wstring& message) + { + wstring caption = programName + L" can't open."; +-#if USE_CONSOLE_ENTRY_POINT ++// Playwright begin + fwprintf(stderr, L"%s\n%s\n", caption.c_str(), message.c_str()); +-#else +- ::MessageBoxW(0, message.c_str(), caption.c_str(), MB_ICONERROR); +-#endif ++// Playwright end + return 1; + } + +diff --git a/Tools/wpe/backends/HeadlessViewBackend.cpp b/Tools/wpe/backends/HeadlessViewBackend.cpp +index c09b6f39f894943f11b7a453428fab7d6f6e68fb..bc21acb648562ee0380811599b08f7d26c3e706a 100644 +--- a/Tools/wpe/backends/HeadlessViewBackend.cpp ++++ b/Tools/wpe/backends/HeadlessViewBackend.cpp +@@ -145,27 +145,24 @@ void HeadlessViewBackend::updateSnapshot(struct wpe_fdo_shm_exported_buffer* exp + return; + } + +- uint32_t bufferStride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, m_width); +- uint8_t* buffer = new uint8_t[bufferStride * m_height]; +- memset(buffer, 0, bufferStride * m_height); ++ uint32_t width = std::max(0, wl_shm_buffer_get_width(shmBuffer)); ++ uint32_t height = std::max(0, wl_shm_buffer_get_height(shmBuffer)); ++ if (!width || !height) { ++ fprintf(stderr, "HeadlessViewBackend::updateSnapshot shmBuffer is empty: %ux%u\n", width, height); ++ return; ++ } + ++ uint32_t bufferStride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); ++ uint32_t stride = std::max(0, wl_shm_buffer_get_stride(shmBuffer)); ++ if (bufferStride != stride) { ++ fprintf(stderr, "bufferStride != stride: %u != %u\n", bufferStride, stride); ++ return; ++ } ++ uint8_t* buffer = new uint8_t[bufferStride * height]; + { +- uint32_t width = std::min(m_width, std::max(0, wl_shm_buffer_get_width(shmBuffer))); +- uint32_t height = std::min(m_height, std::max(0, wl_shm_buffer_get_height(shmBuffer))); +- uint32_t stride = std::max(0, wl_shm_buffer_get_stride(shmBuffer)); +- + wl_shm_buffer_begin_access(shmBuffer); + auto* data = static_cast(wl_shm_buffer_get_data(shmBuffer)); +- +- for (uint32_t y = 0; y < height; ++y) { +- for (uint32_t x = 0; x < width; ++x) { +- buffer[bufferStride * y + 4 * x + 0] = data[stride * y + 4 * x + 0]; +- buffer[bufferStride * y + 4 * x + 1] = data[stride * y + 4 * x + 1]; +- buffer[bufferStride * y + 4 * x + 2] = data[stride * y + 4 * x + 2]; +- buffer[bufferStride * y + 4 * x + 3] = data[stride * y + 4 * x + 3]; +- } +- } +- ++ memcpy(buffer, data, bufferStride * height); + wl_shm_buffer_end_access(shmBuffer); + } + +@@ -173,7 +170,7 @@ void HeadlessViewBackend::updateSnapshot(struct wpe_fdo_shm_exported_buffer* exp + cairo_surface_destroy(m_snapshot); + + m_snapshot = cairo_image_surface_create_for_data(buffer, CAIRO_FORMAT_ARGB32, +- m_width, m_height, cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, m_width)); ++ width, height, cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width)); + + static cairo_user_data_key_t bufferKey; + cairo_surface_set_user_data(m_snapshot, &bufferKey, buffer, +diff --git a/Tools/wpe/install-dependencies b/Tools/wpe/install-dependencies +index b31b71d862862acec966a6684bf1e2df3c1cc506..10b05a61a9d3e598665065f6b1bac5c98f5d013b 100755 +--- a/Tools/wpe/install-dependencies ++++ b/Tools/wpe/install-dependencies +@@ -86,10 +86,12 @@ function installDependenciesWithApt { + libtool \ + libwebp-dev \ + libwoff-dev \ ++ libxcb-glx0-dev \ + libxml2-dev \ + libxslt1-dev \ + ninja-build \ + patch \ ++ patchelf \ + pkg-config \ + ruby \ + zlib1g-dev" diff --git a/browser_patches/deprecated-webkit-mac-10.14/pw_run.sh b/browser_patches/deprecated-webkit-mac-10.14/pw_run.sh new file mode 100755 index 0000000000000..64c85959347c8 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/pw_run.sh @@ -0,0 +1,77 @@ +#!/bin/bash + +function runOSX() { + # if script is run as-is + if [[ -d $SCRIPT_PATH/checkout/WebKitBuild/Release/Playwright.app ]]; then + DYLIB_PATH="$SCRIPT_PATH/checkout/WebKitBuild/Release" + elif [[ -d $SCRIPT_PATH/Playwright.app ]]; then + DYLIB_PATH="$SCRIPT_PATH" + elif [[ -d $SCRIPT_PATH/WebKitBuild/Release/Playwright.app ]]; then + DYLIB_PATH="$SCRIPT_PATH/WebKitBuild/Release" + else + echo "Cannot find a Playwright.app in neither location" 1>&2 + exit 1 + fi + PLAYWRIGHT="$DYLIB_PATH/Playwright.app/Contents/MacOS/Playwright" + DYLD_FRAMEWORK_PATH="$DYLIB_PATH" DYLD_LIBRARY_PATH="$DYLIB_PATH" "$PLAYWRIGHT" "$@" +} + +function runLinux() { + # if script is run as-is + GIO_DIR=""; + LD_PATH=""; + BUNDLE_DIR=""; + DEPENDENCIES_FOLDER="DependenciesGTK"; + MINIBROWSER_FOLDER="minibrowser-gtk"; + BUILD_FOLDER="WebKitBuild/GTK"; + if [[ "$*" == *--headless* ]]; then + DEPENDENCIES_FOLDER="DependenciesWPE"; + MINIBROWSER_FOLDER="minibrowser-wpe"; + BUILD_FOLDER="WebKitBuild/WPE"; + fi + # Setting extra environment variables like LD_LIBRARY_PATH or WEBKIT_INJECTED_BUNDLE_PATH + # is only needed when calling MiniBrowser from the build folder. The MiniBrowser from + # the zip bundle wrapper already sets itself the needed env variables. + if [[ -d $SCRIPT_PATH/$MINIBROWSER_FOLDER ]]; then + MINIBROWSER="$SCRIPT_PATH/$MINIBROWSER_FOLDER/MiniBrowser" + elif [[ -d $SCRIPT_PATH/checkout/$BUILD_FOLDER ]]; then + LD_PATH="$SCRIPT_PATH/checkout/$BUILD_FOLDER/$DEPENDENCIES_FOLDER/Root/lib:$SCRIPT_PATH/checkout/$BUILD_FOLDER/Release/bin" + GIO_DIR="$SCRIPT_PATH/checkout/$BUILD_FOLDER/$DEPENDENCIES_FOLDER/Root/lib/gio/modules" + BUNDLE_DIR="$SCRIPT_PATH/checkout/$BUILD_FOLDER/Release/lib" + MINIBROWSER="$SCRIPT_PATH/checkout/$BUILD_FOLDER/Release/bin/MiniBrowser" + elif [[ -f $SCRIPT_PATH/MiniBrowser ]]; then + MINIBROWSER="$SCRIPT_PATH/MiniBrowser" + elif [[ -d $SCRIPT_PATH/$BUILD_FOLDER ]]; then + LD_PATH="$SCRIPT_PATH/$BUILD_FOLDER/$DEPENDENCIES_FOLDER/Root/lib:$SCRIPT_PATH/$BUILD_FOLDER/Release/bin" + GIO_DIR="$SCRIPT_PATH/$BUILD_FOLDER/$DEPENDENCIES_FOLDER/Root/lib/gio/modules" + BUNDLE_DIR="$SCRIPT_PATH/$BUILD_FOLDER/Release/lib" + MINIBROWSER="$SCRIPT_PATH/$BUILD_FOLDER/Release/bin/MiniBrowser" + else + echo "Cannot find a MiniBrowser.app in neither location" 1>&2 + exit 1 + fi + + if [[ -n "$GIO_DIR" ]]; then + export GIO_EXTRA_MODULES="$GIO_DIR" + fi + + if [[ -n "$LD_PATH" ]]; then + export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$LD_PATH" + fi + + if [[ -n "$BUNDLE_DIR" ]]; then + export WEBKIT_INJECTED_BUNDLE_PATH="$BUNDLE_DIR" + fi + + WEBKIT_FORCE_COMPLEX_TEXT="1" "$MINIBROWSER" "$@" +} + +SCRIPT_PATH="$(cd "$(dirname "$0")" ; pwd -P)" +if [[ "$(uname)" == "Darwin" ]]; then + runOSX "$@" +elif [[ "$(uname)" == "Linux" ]]; then + runLinux "$@" +else + echo "ERROR: cannot run on this platform!" 1>&2 + exit 1; +fi diff --git a/browser_patches/deprecated-webkit-mac-10.14/pw_run_debug.sh b/browser_patches/deprecated-webkit-mac-10.14/pw_run_debug.sh new file mode 100755 index 0000000000000..0e41b28a8ec52 --- /dev/null +++ b/browser_patches/deprecated-webkit-mac-10.14/pw_run_debug.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +function runOSX() { + # if script is run as-is + if [ -d $SCRIPT_PATH/checkout/WebKitBuild/Debug/MiniBrowser.app ]; then + DYLIB_PATH="$SCRIPT_PATH/checkout/WebKitBuild/Debug" + elif [ -d $SCRIPT_PATH/MiniBrowser.app ]; then + DYLIB_PATH="$SCRIPT_PATH" + elif [ -d $SCRIPT_PATH/WebKitBuild/Debug/MiniBrowser.app ]; then + DYLIB_PATH="$SCRIPT_PATH/WebKitBuild/Debug" + else + echo "Cannot find a MiniBrowser.app in neither location" 1>&2 + exit 1 + fi + MINIBROWSER="$DYLIB_PATH/MiniBrowser.app/Contents/MacOS/MiniBrowser" + DYLD_FRAMEWORK_PATH=$DYLIB_PATH DYLD_LIBRARY_PATH=$DYLIB_PATH $MINIBROWSER "$@" +} + +function runLinux() { + # if script is run as-is + if [ -d $SCRIPT_PATH/checkout/WebKitBuild/GTK ]; then + LD_PATH="$SCRIPT_PATH/checkout/WebKitBuild/GTK/DependenciesGTK/Root/lib:$SCRIPT_PATH/checkout/WebKitBuild/GTK/Debug/bin" + MINIBROWSER="$SCRIPT_PATH/checkout/WebKitBuild/GTK/Debug/bin/MiniBrowser" + elif [ -f $SCRIPT_PATH/MiniBrowser ]; then + LD_PATH="$SCRIPT_PATH" + MINIBROWSER="$SCRIPT_PATH/MiniBrowser" + elif [ -d $SCRIPT_PATH/WebKitBuild/GTK ]; then + LD_PATH="$SCRIPT_PATH/WebKitBuild/GTK/DependenciesGTK/Root/lib:$SCRIPT_PATH/WebKitBuild/GTK/Debug/bin" + MINIBROWSER="$SCRIPT_PATH/WebKitBuild/GTK/Debug/bin/MiniBrowser" + else + echo "Cannot find a MiniBrowser.app in neither location" 1>&2 + exit 1 + fi + LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$LD_PATH $MINIBROWSER "$@" +} + +SCRIPT_PATH="$(cd "$(dirname "$0")" ; pwd -P)" +if [ "$(uname)" == "Darwin" ]; then + runOSX "$@" +elif [ "$(uname)" == "Linux" ]; then + runLinux "$@" +else + echo "ERROR: cannot run on this platform!" 1>&2 + exit 1; +fi diff --git a/browser_patches/prepare_checkout.sh b/browser_patches/prepare_checkout.sh index 137a4cbd1f931..d70087919391d 100755 --- a/browser_patches/prepare_checkout.sh +++ b/browser_patches/prepare_checkout.sh @@ -93,6 +93,18 @@ elif [[ ("$1" == "firefox") || ("$1" == "firefox/") || ("$1" == "ff") ]]; then CHECKOUT_PATH="${FF_CHECKOUT_PATH}" FRIENDLY_CHECKOUT_PATH="" fi +elif [[ ("$1" == "deprecated-webkit-mac-10.14") ]]; then + FRIENDLY_CHECKOUT_PATH="//browser_patches/deprecated-webkit-mac-10.14/checkout"; + CHECKOUT_PATH="$PWD/deprecated-webkit-mac-10.14/checkout" + PATCHES_PATH="$PWD/deprecated-webkit-mac-10.14/patches" + WEBKIT_EXTRA_FOLDER_PATH="$PWD/deprecated-webkit-mac-10.14/embedder/Playwright" + BUILD_NUMBER=$(head -1 "$PWD/deprecated-webkit-mac-10.14/BUILD_NUMBER") + source "./deprecated-webkit-mac-10.14/UPSTREAM_CONFIG.sh" + if [[ ! -z "${WK_CHECKOUT_PATH}" ]]; then + echo "WARNING: using checkout path from WK_CHECKOUT_PATH env: ${WK_CHECKOUT_PATH}" + CHECKOUT_PATH="${WK_CHECKOUT_PATH}" + FRIENDLY_CHECKOUT_PATH="" + fi elif [[ ("$1" == "webkit") || ("$1" == "webkit/") || ("$1" == "wk") ]]; then FRIENDLY_CHECKOUT_PATH="//browser_patches/webkit/checkout"; CHECKOUT_PATH="$PWD/webkit/checkout"